pystand 1.1__tar.gz → 1.3__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.
- {pystand-1.1/pystand.egg-info → pystand-1.3}/PKG-INFO +17 -10
- {pystand-1.1 → pystand-1.3}/README.md +16 -9
- {pystand-1.1 → pystand-1.3/pystand.egg-info}/PKG-INFO +17 -10
- {pystand-1.1 → pystand-1.3}/pystand.py +69 -23
- {pystand-1.1 → pystand-1.3}/.flake8 +0 -0
- {pystand-1.1 → pystand-1.3}/.gitignore +0 -0
- {pystand-1.1 → pystand-1.3}/Makefile +0 -0
- {pystand-1.1 → pystand-1.3}/pyproject.toml +0 -0
- {pystand-1.1 → pystand-1.3}/pystand.egg-info/SOURCES.txt +0 -0
- {pystand-1.1 → pystand-1.3}/pystand.egg-info/dependency_links.txt +0 -0
- {pystand-1.1 → pystand-1.3}/pystand.egg-info/entry_points.txt +0 -0
- {pystand-1.1 → pystand-1.3}/pystand.egg-info/requires.txt +0 -0
- {pystand-1.1 → pystand-1.3}/pystand.egg-info/top_level.txt +0 -0
- {pystand-1.1 → pystand-1.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pystand
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.3
|
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: GPLv3
|
@@ -18,8 +18,8 @@ Requires-Dist: pygithub
|
|
18
18
|
[](https://pypi.org/project/pystand/)
|
19
19
|
[](https://aur.archlinux.org/packages/pystand/)
|
20
20
|
|
21
|
-
[`pystand`][pystand] is a command line tool to facilitate the
|
22
|
-
installation and update of pre-built Python versions from the
|
21
|
+
[`pystand`][pystand] is a command line tool to facilitate the download,
|
22
|
+
installation, and update of pre-built Python versions from the
|
23
23
|
[`python-build-standalone`][pbs] project. The following commands are
|
24
24
|
provided:
|
25
25
|
|
@@ -117,11 +117,13 @@ Type `pystand` or `pystand -h` to view the usage summary:
|
|
117
117
|
|
118
118
|
```
|
119
119
|
usage: pystand [-h] [-D DISTRIBUTION] [-B BASE_DIR] [-C CACHE_MINUTES]
|
120
|
-
[--purge-days PURGE_DAYS]
|
120
|
+
[--purge-days PURGE_DAYS]
|
121
|
+
[--github-access-token GITHUB_ACCESS_TOKEN] [-V]
|
121
122
|
{install,update,remove,list,show,path} ...
|
122
123
|
|
123
|
-
Command line tool to install pre-built Python versions
|
124
|
-
standalone project
|
124
|
+
Command line tool to download, install, and update pre-built Python versions
|
125
|
+
from the python-build-standalone project at
|
126
|
+
https://github.com/indygreg/python-build-standalone.
|
125
127
|
|
126
128
|
options:
|
127
129
|
-h, --help show this help message and exit
|
@@ -138,8 +140,11 @@ options:
|
|
138
140
|
before rechecking for latest. Default is 60 minutes
|
139
141
|
--purge-days PURGE_DAYS
|
140
142
|
cache release file lists for this number of days after
|
141
|
-
last version referencing it is removed. Default is
|
143
|
+
last version referencing it is removed. Default is 90
|
142
144
|
days
|
145
|
+
--github-access-token GITHUB_ACCESS_TOKEN
|
146
|
+
Optional Github access token. Can specify to reduce
|
147
|
+
rate limiting.
|
143
148
|
-V show pystand version
|
144
149
|
|
145
150
|
Commands:
|
@@ -181,7 +186,7 @@ options:
|
|
181
186
|
### Command `update`
|
182
187
|
|
183
188
|
```
|
184
|
-
usage: pystand update [-h] [-r RELEASE] [-a] [--skip] [version ...]
|
189
|
+
usage: pystand update [-h] [-r RELEASE] [-a] [--skip] [-k] [version ...]
|
185
190
|
|
186
191
|
Update one, more, or all versions to another release.
|
187
192
|
|
@@ -196,6 +201,8 @@ options:
|
|
196
201
|
-a, --all update ALL versions
|
197
202
|
--skip skip the specified versions when updating all (only
|
198
203
|
can be specified with --all)
|
204
|
+
-k, --keep keep old version after updating (but only if different
|
205
|
+
version number)
|
199
206
|
```
|
200
207
|
|
201
208
|
### Command `remove`
|
@@ -330,8 +337,8 @@ anything after on a line) are ignored. Type `pystand` to see all
|
|
330
337
|
supported options.
|
331
338
|
|
332
339
|
The global options: `--distribution`, `--base-dir`, `--cache-minutes`,
|
333
|
-
`--purge-days` are the only sensible candidates
|
334
|
-
defaults.
|
340
|
+
`--purge-days`, `--github-access-token` are the only sensible candidates
|
341
|
+
to consider setting as defaults.
|
335
342
|
|
336
343
|
## Command Line Tab Completion
|
337
344
|
|
@@ -2,8 +2,8 @@
|
|
2
2
|
[](https://pypi.org/project/pystand/)
|
3
3
|
[](https://aur.archlinux.org/packages/pystand/)
|
4
4
|
|
5
|
-
[`pystand`][pystand] is a command line tool to facilitate the
|
6
|
-
installation and update of pre-built Python versions from the
|
5
|
+
[`pystand`][pystand] is a command line tool to facilitate the download,
|
6
|
+
installation, and update of pre-built Python versions from the
|
7
7
|
[`python-build-standalone`][pbs] project. The following commands are
|
8
8
|
provided:
|
9
9
|
|
@@ -101,11 +101,13 @@ Type `pystand` or `pystand -h` to view the usage summary:
|
|
101
101
|
|
102
102
|
```
|
103
103
|
usage: pystand [-h] [-D DISTRIBUTION] [-B BASE_DIR] [-C CACHE_MINUTES]
|
104
|
-
[--purge-days PURGE_DAYS]
|
104
|
+
[--purge-days PURGE_DAYS]
|
105
|
+
[--github-access-token GITHUB_ACCESS_TOKEN] [-V]
|
105
106
|
{install,update,remove,list,show,path} ...
|
106
107
|
|
107
|
-
Command line tool to install pre-built Python versions
|
108
|
-
standalone project
|
108
|
+
Command line tool to download, install, and update pre-built Python versions
|
109
|
+
from the python-build-standalone project at
|
110
|
+
https://github.com/indygreg/python-build-standalone.
|
109
111
|
|
110
112
|
options:
|
111
113
|
-h, --help show this help message and exit
|
@@ -122,8 +124,11 @@ options:
|
|
122
124
|
before rechecking for latest. Default is 60 minutes
|
123
125
|
--purge-days PURGE_DAYS
|
124
126
|
cache release file lists for this number of days after
|
125
|
-
last version referencing it is removed. Default is
|
127
|
+
last version referencing it is removed. Default is 90
|
126
128
|
days
|
129
|
+
--github-access-token GITHUB_ACCESS_TOKEN
|
130
|
+
Optional Github access token. Can specify to reduce
|
131
|
+
rate limiting.
|
127
132
|
-V show pystand version
|
128
133
|
|
129
134
|
Commands:
|
@@ -165,7 +170,7 @@ options:
|
|
165
170
|
### Command `update`
|
166
171
|
|
167
172
|
```
|
168
|
-
usage: pystand update [-h] [-r RELEASE] [-a] [--skip] [version ...]
|
173
|
+
usage: pystand update [-h] [-r RELEASE] [-a] [--skip] [-k] [version ...]
|
169
174
|
|
170
175
|
Update one, more, or all versions to another release.
|
171
176
|
|
@@ -180,6 +185,8 @@ options:
|
|
180
185
|
-a, --all update ALL versions
|
181
186
|
--skip skip the specified versions when updating all (only
|
182
187
|
can be specified with --all)
|
188
|
+
-k, --keep keep old version after updating (but only if different
|
189
|
+
version number)
|
183
190
|
```
|
184
191
|
|
185
192
|
### Command `remove`
|
@@ -314,8 +321,8 @@ anything after on a line) are ignored. Type `pystand` to see all
|
|
314
321
|
supported options.
|
315
322
|
|
316
323
|
The global options: `--distribution`, `--base-dir`, `--cache-minutes`,
|
317
|
-
`--purge-days` are the only sensible candidates
|
318
|
-
defaults.
|
324
|
+
`--purge-days`, `--github-access-token` are the only sensible candidates
|
325
|
+
to consider setting as defaults.
|
319
326
|
|
320
327
|
## Command Line Tab Completion
|
321
328
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pystand
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.3
|
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: GPLv3
|
@@ -18,8 +18,8 @@ Requires-Dist: pygithub
|
|
18
18
|
[](https://pypi.org/project/pystand/)
|
19
19
|
[](https://aur.archlinux.org/packages/pystand/)
|
20
20
|
|
21
|
-
[`pystand`][pystand] is a command line tool to facilitate the
|
22
|
-
installation and update of pre-built Python versions from the
|
21
|
+
[`pystand`][pystand] is a command line tool to facilitate the download,
|
22
|
+
installation, and update of pre-built Python versions from the
|
23
23
|
[`python-build-standalone`][pbs] project. The following commands are
|
24
24
|
provided:
|
25
25
|
|
@@ -117,11 +117,13 @@ Type `pystand` or `pystand -h` to view the usage summary:
|
|
117
117
|
|
118
118
|
```
|
119
119
|
usage: pystand [-h] [-D DISTRIBUTION] [-B BASE_DIR] [-C CACHE_MINUTES]
|
120
|
-
[--purge-days PURGE_DAYS]
|
120
|
+
[--purge-days PURGE_DAYS]
|
121
|
+
[--github-access-token GITHUB_ACCESS_TOKEN] [-V]
|
121
122
|
{install,update,remove,list,show,path} ...
|
122
123
|
|
123
|
-
Command line tool to install pre-built Python versions
|
124
|
-
standalone project
|
124
|
+
Command line tool to download, install, and update pre-built Python versions
|
125
|
+
from the python-build-standalone project at
|
126
|
+
https://github.com/indygreg/python-build-standalone.
|
125
127
|
|
126
128
|
options:
|
127
129
|
-h, --help show this help message and exit
|
@@ -138,8 +140,11 @@ options:
|
|
138
140
|
before rechecking for latest. Default is 60 minutes
|
139
141
|
--purge-days PURGE_DAYS
|
140
142
|
cache release file lists for this number of days after
|
141
|
-
last version referencing it is removed. Default is
|
143
|
+
last version referencing it is removed. Default is 90
|
142
144
|
days
|
145
|
+
--github-access-token GITHUB_ACCESS_TOKEN
|
146
|
+
Optional Github access token. Can specify to reduce
|
147
|
+
rate limiting.
|
143
148
|
-V show pystand version
|
144
149
|
|
145
150
|
Commands:
|
@@ -181,7 +186,7 @@ options:
|
|
181
186
|
### Command `update`
|
182
187
|
|
183
188
|
```
|
184
|
-
usage: pystand update [-h] [-r RELEASE] [-a] [--skip] [version ...]
|
189
|
+
usage: pystand update [-h] [-r RELEASE] [-a] [--skip] [-k] [version ...]
|
185
190
|
|
186
191
|
Update one, more, or all versions to another release.
|
187
192
|
|
@@ -196,6 +201,8 @@ options:
|
|
196
201
|
-a, --all update ALL versions
|
197
202
|
--skip skip the specified versions when updating all (only
|
198
203
|
can be specified with --all)
|
204
|
+
-k, --keep keep old version after updating (but only if different
|
205
|
+
version number)
|
199
206
|
```
|
200
207
|
|
201
208
|
### Command `remove`
|
@@ -330,8 +337,8 @@ anything after on a line) are ignored. Type `pystand` to see all
|
|
330
337
|
supported options.
|
331
338
|
|
332
339
|
The global options: `--distribution`, `--base-dir`, `--cache-minutes`,
|
333
|
-
`--purge-days` are the only sensible candidates
|
334
|
-
defaults.
|
340
|
+
`--purge-days`, `--github-access-token` are the only sensible candidates
|
341
|
+
to consider setting as defaults.
|
335
342
|
|
336
343
|
## Command Line Tab Completion
|
337
344
|
|
@@ -1,8 +1,9 @@
|
|
1
1
|
#!/usr/bin/python3
|
2
2
|
# PYTHON_ARGCOMPLETE_OK
|
3
3
|
'''
|
4
|
-
Command line tool to install pre-built Python
|
5
|
-
python-build-standalone project
|
4
|
+
Command line tool to download, install, and update pre-built Python
|
5
|
+
versions from the python-build-standalone project at
|
6
|
+
https://github.com/indygreg/python-build-standalone.
|
6
7
|
'''
|
7
8
|
from __future__ import annotations
|
8
9
|
|
@@ -30,6 +31,13 @@ GITHUB_REPO = f'{REPO_OWNER}/{REPO}'
|
|
30
31
|
LATEST_RELEASE_URL = f'https://raw.githubusercontent.com/{GITHUB_REPO}'\
|
31
32
|
'/latest-release/latest-release.json'
|
32
33
|
|
34
|
+
# The following release is the first one that supports "install_only"
|
35
|
+
# builds so this tool does not support any releases before this.
|
36
|
+
FIRST_RELEASE = '20210724'
|
37
|
+
|
38
|
+
# The following regexp pattern is used to match the end of a release file name
|
39
|
+
ENDPAT = r'-install_only[-\dT]*.tar.gz$'
|
40
|
+
|
33
41
|
PROG = Path(__file__).stem
|
34
42
|
CNFFILE = platformdirs.user_config_path(f'{PROG}-flags.conf')
|
35
43
|
|
@@ -98,7 +106,14 @@ def get_gh(args: Namespace) -> Any:
|
|
98
106
|
return get_gh_handle
|
99
107
|
|
100
108
|
from github import Github
|
101
|
-
|
109
|
+
if args.github_access_token:
|
110
|
+
from github import Auth
|
111
|
+
auth = Auth.Token(args.github_access_token)
|
112
|
+
else:
|
113
|
+
auth = None
|
114
|
+
|
115
|
+
# Save this handle globally for future use
|
116
|
+
get_gh_handle = Github(auth=auth) # type: ignore
|
102
117
|
return get_gh_handle
|
103
118
|
|
104
119
|
def rm_path(path: Path) -> None:
|
@@ -168,8 +183,18 @@ def get_version_names(args: Namespace) -> list[str]:
|
|
168
183
|
return sorted(all_names - given, key=parse_version) \
|
169
184
|
if args.all else versions
|
170
185
|
|
171
|
-
def
|
172
|
-
'Return the latest
|
186
|
+
def get_release_tag(args: Namespace) -> str:
|
187
|
+
'Return the release tag, or latest if not specified'
|
188
|
+
if release := args.release:
|
189
|
+
if not release.isdigit() or len(release) != len(FIRST_RELEASE):
|
190
|
+
sys.exit('Release must be a YYYYMMDD string.')
|
191
|
+
if release < FIRST_RELEASE:
|
192
|
+
sys.exit(f'Releases before "{FIRST_RELEASE}" do not '
|
193
|
+
'include "*-install_only" builds so are '
|
194
|
+
'not supported.')
|
195
|
+
|
196
|
+
return release
|
197
|
+
|
173
198
|
if args._latest_release.exists():
|
174
199
|
stat = args._latest_release.stat()
|
175
200
|
if time.time() < (stat.st_mtime + int(args.cache_minutes * 60)):
|
@@ -192,11 +217,25 @@ def get_latest_release_tag(args: Namespace) -> str:
|
|
192
217
|
args._latest_release.write_text(tag + '\n')
|
193
218
|
return tag
|
194
219
|
|
220
|
+
def get_release_name(filename: str) -> Optional[str]:
|
221
|
+
'Search for and strip the release name from the file name'
|
222
|
+
if not (m := re.search(ENDPAT, filename)):
|
223
|
+
return None
|
224
|
+
|
225
|
+
# Strip of end of file name and also strip any +8 digit embedded
|
226
|
+
# release date
|
227
|
+
return re.sub(r'\+\d{8}', '', filename[:m.start()])
|
228
|
+
|
195
229
|
def get_release_files(args, tag, implementation: Optional[str] = None) -> dict:
|
196
230
|
'Return the release files for the given tag'
|
197
231
|
# Look for tag data in our release cache
|
198
232
|
jfile = args._releases / tag
|
199
233
|
if not (files := get_json(jfile)):
|
234
|
+
|
235
|
+
# May have read this release before but it has no assets
|
236
|
+
if jfile.exists():
|
237
|
+
return {}
|
238
|
+
|
200
239
|
# Not in cache so fetch it (and also store in cache)
|
201
240
|
gh = get_gh(args)
|
202
241
|
try:
|
@@ -206,17 +245,11 @@ def get_release_files(args, tag, implementation: Optional[str] = None) -> dict:
|
|
206
245
|
|
207
246
|
# Iterate over the release assets and store the files in a dict to
|
208
247
|
# return
|
209
|
-
end = '-install_only.tar.gz'
|
210
248
|
for file in release.get_assets():
|
211
|
-
name
|
212
|
-
if not name.endswith(end):
|
249
|
+
if not (name := get_release_name(file.name)):
|
213
250
|
continue
|
214
251
|
|
215
|
-
|
216
|
-
impl_ver, rest = name.split('+', maxsplit=1)
|
217
|
-
impl, ver = impl_ver.split('-', maxsplit=1)
|
218
|
-
rest = rest.split('-', maxsplit=1)[1]
|
219
|
-
|
252
|
+
impl, ver, rest = name.split('-', maxsplit=2)
|
220
253
|
if impl not in files:
|
221
254
|
files[impl] = defaultdict(dict)
|
222
255
|
|
@@ -378,10 +411,13 @@ def main() -> Optional[str]:
|
|
378
411
|
help='cache latest release tag fetch for this many '
|
379
412
|
'minutes, before rechecking for latest. '
|
380
413
|
'Default is %(default)d minutes')
|
381
|
-
opt.add_argument('--purge-days', default=
|
414
|
+
opt.add_argument('--purge-days', default=90, type=int,
|
382
415
|
help='cache release file lists for this number '
|
383
416
|
'of days after last version referencing it is removed. '
|
384
417
|
'Default is %(default)d days')
|
418
|
+
opt.add_argument('--github-access-token',
|
419
|
+
help='Optional Github access token. Can specify to reduce '
|
420
|
+
'rate limiting.')
|
385
421
|
opt.add_argument('-V', action='store_true',
|
386
422
|
help=f'show {PROG} version')
|
387
423
|
cmd = opt.add_subparsers(title='Commands', dest='cmdname')
|
@@ -469,10 +505,10 @@ class _install(COMMAND):
|
|
469
505
|
|
470
506
|
@staticmethod
|
471
507
|
def run(args: Namespace) -> Optional[str]:
|
472
|
-
release =
|
508
|
+
release = get_release_tag(args)
|
473
509
|
files = get_release_files(args, release, 'cpython')
|
474
510
|
if not files:
|
475
|
-
return f'Release "{release}" not found.'
|
511
|
+
return f'Release "{release}" not found, or has no compatible files.'
|
476
512
|
|
477
513
|
matcher = VersionMatcher(files)
|
478
514
|
for version in args.version:
|
@@ -504,13 +540,16 @@ class _update(COMMAND):
|
|
504
540
|
parser.add_argument('--skip', action='store_true',
|
505
541
|
help='skip the specified versions when '
|
506
542
|
'updating all (only can be specified with --all)')
|
543
|
+
parser.add_argument('-k', '--keep', action='store_true',
|
544
|
+
help='keep old version after updating (but only '
|
545
|
+
'if different version number)')
|
507
546
|
parser.add_argument('version', nargs='*',
|
508
547
|
help='version to update (or to skip for '
|
509
548
|
'--all --skip)')
|
510
549
|
|
511
550
|
@staticmethod
|
512
551
|
def run(args: Namespace) -> Optional[str]:
|
513
|
-
release_target =
|
552
|
+
release_target = get_release_tag(args)
|
514
553
|
files = get_release_files(args, release_target, 'cpython')
|
515
554
|
if not files:
|
516
555
|
return f'Release "{release_target}" not found.'
|
@@ -525,14 +564,21 @@ class _update(COMMAND):
|
|
525
564
|
continue
|
526
565
|
|
527
566
|
nextver = matcher.match(version, upconvert_minor=True)
|
528
|
-
new_vdir = args._versions / nextver
|
529
|
-
if nextver != version and new_vdir.exists():
|
530
|
-
continue
|
531
567
|
|
532
568
|
distribution = data.get('distribution')
|
533
569
|
if not distribution or distribution not in files.get(nextver, {}):
|
534
570
|
continue
|
535
571
|
|
572
|
+
if nextver == version and args.keep:
|
573
|
+
print(f'Error: {fmt(version, release)} would not be kept '
|
574
|
+
f'if update to {fmt(nextver, release_target)} '
|
575
|
+
f'distribution="{distribution}"', file=sys.stderr)
|
576
|
+
continue
|
577
|
+
|
578
|
+
new_vdir = args._versions / nextver
|
579
|
+
if nextver != version and new_vdir.exists():
|
580
|
+
continue
|
581
|
+
|
536
582
|
print(f'{fmt(version, release)} updating to '
|
537
583
|
f'{fmt(nextver, release_target)} '
|
538
584
|
f'distribution="{distribution}" ..')
|
@@ -541,7 +587,7 @@ class _update(COMMAND):
|
|
541
587
|
files):
|
542
588
|
return error
|
543
589
|
|
544
|
-
if nextver != version:
|
590
|
+
if nextver != version and not args.keep:
|
545
591
|
remove(args, version)
|
546
592
|
|
547
593
|
@COMMAND.add
|
@@ -586,7 +632,7 @@ class _list(COMMAND):
|
|
586
632
|
|
587
633
|
@staticmethod
|
588
634
|
def run(args: Namespace) -> Optional[str]:
|
589
|
-
release_target =
|
635
|
+
release_target = get_release_tag(args)
|
590
636
|
files = get_release_files(args, release_target, 'cpython')
|
591
637
|
if not files:
|
592
638
|
return f'Release "{release_target}" not found.'
|
@@ -640,7 +686,7 @@ class _show(COMMAND):
|
|
640
686
|
|
641
687
|
@staticmethod
|
642
688
|
def run(args: Namespace) -> None:
|
643
|
-
release =
|
689
|
+
release = get_release_tag(args)
|
644
690
|
files = get_release_files(args, release, 'cpython')
|
645
691
|
if not files:
|
646
692
|
sys.exit(f'Error: release "{release}" not found.')
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|