pystand 1.6__tar.gz → 1.7__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.6/pystand.egg-info → pystand-1.7}/PKG-INFO +8 -6
- {pystand-1.6 → pystand-1.7}/README.md +7 -5
- {pystand-1.6 → pystand-1.7/pystand.egg-info}/PKG-INFO +8 -6
- {pystand-1.6 → pystand-1.7}/pystand.py +77 -41
- {pystand-1.6 → pystand-1.7}/.flake8 +0 -0
- {pystand-1.6 → pystand-1.7}/.gitignore +0 -0
- {pystand-1.6 → pystand-1.7}/Makefile +0 -0
- {pystand-1.6 → pystand-1.7}/pyproject.toml +0 -0
- {pystand-1.6 → pystand-1.7}/pystand.egg-info/SOURCES.txt +0 -0
- {pystand-1.6 → pystand-1.7}/pystand.egg-info/dependency_links.txt +0 -0
- {pystand-1.6 → pystand-1.7}/pystand.egg-info/entry_points.txt +0 -0
- {pystand-1.6 → pystand-1.7}/pystand.egg-info/requires.txt +0 -0
- {pystand-1.6 → pystand-1.7}/pystand.egg-info/top_level.txt +0 -0
- {pystand-1.6 → pystand-1.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pystand
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.7
|
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
|
@@ -121,8 +121,8 @@ Type `pystand` or `pystand -h` to view the usage summary:
|
|
121
121
|
```
|
122
122
|
usage: pystand [-h] [-D DISTRIBUTION] [-B BASE_DIR] [-C CACHE_MINUTES]
|
123
123
|
[--purge-days PURGE_DAYS]
|
124
|
-
[--github-access-token GITHUB_ACCESS_TOKEN] [--
|
125
|
-
[-V]
|
124
|
+
[--github-access-token GITHUB_ACCESS_TOKEN] [--no-strip]
|
125
|
+
[--no-extra-strip] [-V]
|
126
126
|
{install,update,remove,list,show,path} ...
|
127
127
|
|
128
128
|
Command line tool to download, install, and update pre-built Python versions
|
@@ -150,7 +150,8 @@ options:
|
|
150
150
|
--github-access-token GITHUB_ACCESS_TOKEN
|
151
151
|
optional Github access token. Can specify to reduce
|
152
152
|
rate limiting.
|
153
|
-
--
|
153
|
+
--no-strip do not use or create stripped binaries
|
154
|
+
--no-extra-strip do not restrip already stripped source binaries
|
154
155
|
-V show pystand version
|
155
156
|
|
156
157
|
Commands:
|
@@ -344,8 +345,9 @@ anything after on a line) are ignored. Type `pystand` to see all
|
|
344
345
|
supported options.
|
345
346
|
|
346
347
|
The global options: `--distribution`, `--base-dir`, `--cache-minutes`,
|
347
|
-
`--purge-days`, `--github-access-token`, `--
|
348
|
-
sensible candidates to consider setting
|
348
|
+
`--purge-days`, `--github-access-token`, `--no-strip`,
|
349
|
+
`--no-extra-strip` are the only sensible candidates to consider setting
|
350
|
+
as defaults.
|
349
351
|
|
350
352
|
## Command Line Tab Completion
|
351
353
|
|
@@ -105,8 +105,8 @@ Type `pystand` or `pystand -h` to view the usage summary:
|
|
105
105
|
```
|
106
106
|
usage: pystand [-h] [-D DISTRIBUTION] [-B BASE_DIR] [-C CACHE_MINUTES]
|
107
107
|
[--purge-days PURGE_DAYS]
|
108
|
-
[--github-access-token GITHUB_ACCESS_TOKEN] [--
|
109
|
-
[-V]
|
108
|
+
[--github-access-token GITHUB_ACCESS_TOKEN] [--no-strip]
|
109
|
+
[--no-extra-strip] [-V]
|
110
110
|
{install,update,remove,list,show,path} ...
|
111
111
|
|
112
112
|
Command line tool to download, install, and update pre-built Python versions
|
@@ -134,7 +134,8 @@ options:
|
|
134
134
|
--github-access-token GITHUB_ACCESS_TOKEN
|
135
135
|
optional Github access token. Can specify to reduce
|
136
136
|
rate limiting.
|
137
|
-
--
|
137
|
+
--no-strip do not use or create stripped binaries
|
138
|
+
--no-extra-strip do not restrip already stripped source binaries
|
138
139
|
-V show pystand version
|
139
140
|
|
140
141
|
Commands:
|
@@ -328,8 +329,9 @@ anything after on a line) are ignored. Type `pystand` to see all
|
|
328
329
|
supported options.
|
329
330
|
|
330
331
|
The global options: `--distribution`, `--base-dir`, `--cache-minutes`,
|
331
|
-
`--purge-days`, `--github-access-token`, `--
|
332
|
-
sensible candidates to consider setting
|
332
|
+
`--purge-days`, `--github-access-token`, `--no-strip`,
|
333
|
+
`--no-extra-strip` are the only sensible candidates to consider setting
|
334
|
+
as defaults.
|
333
335
|
|
334
336
|
## Command Line Tab Completion
|
335
337
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pystand
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.7
|
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
|
@@ -121,8 +121,8 @@ Type `pystand` or `pystand -h` to view the usage summary:
|
|
121
121
|
```
|
122
122
|
usage: pystand [-h] [-D DISTRIBUTION] [-B BASE_DIR] [-C CACHE_MINUTES]
|
123
123
|
[--purge-days PURGE_DAYS]
|
124
|
-
[--github-access-token GITHUB_ACCESS_TOKEN] [--
|
125
|
-
[-V]
|
124
|
+
[--github-access-token GITHUB_ACCESS_TOKEN] [--no-strip]
|
125
|
+
[--no-extra-strip] [-V]
|
126
126
|
{install,update,remove,list,show,path} ...
|
127
127
|
|
128
128
|
Command line tool to download, install, and update pre-built Python versions
|
@@ -150,7 +150,8 @@ options:
|
|
150
150
|
--github-access-token GITHUB_ACCESS_TOKEN
|
151
151
|
optional Github access token. Can specify to reduce
|
152
152
|
rate limiting.
|
153
|
-
--
|
153
|
+
--no-strip do not use or create stripped binaries
|
154
|
+
--no-extra-strip do not restrip already stripped source binaries
|
154
155
|
-V show pystand version
|
155
156
|
|
156
157
|
Commands:
|
@@ -344,8 +345,9 @@ anything after on a line) are ignored. Type `pystand` to see all
|
|
344
345
|
supported options.
|
345
346
|
|
346
347
|
The global options: `--distribution`, `--base-dir`, `--cache-minutes`,
|
347
|
-
`--purge-days`, `--github-access-token`, `--
|
348
|
-
sensible candidates to consider setting
|
348
|
+
`--purge-days`, `--github-access-token`, `--no-strip`,
|
349
|
+
`--no-extra-strip` are the only sensible candidates to consider setting
|
350
|
+
as defaults.
|
349
351
|
|
350
352
|
## Command Line Tab Completion
|
351
353
|
|
@@ -40,6 +40,8 @@ FIRST_RELEASE = '20210724'
|
|
40
40
|
# Sample release tag for documentation/usage examples
|
41
41
|
SAMPL_RELEASE = '20240415'
|
42
42
|
|
43
|
+
STRIP_EXT = '_stripped'
|
44
|
+
|
43
45
|
# The following regexp pattern is used to match the end of a release file name
|
44
46
|
ENDPAT = r'-install_only[-\dT]*.tar.gz$'
|
45
47
|
|
@@ -234,14 +236,22 @@ def get_release_tag(args: Namespace) -> str:
|
|
234
236
|
args._latest_release.write_text(tag + '\n')
|
235
237
|
return tag
|
236
238
|
|
237
|
-
def
|
238
|
-
'
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
#
|
243
|
-
#
|
244
|
-
|
239
|
+
def merge(files: dict, name: str, url: str, stripped: bool) -> None:
|
240
|
+
'Merge a file into the files dict'
|
241
|
+
# We store: A string url when there is no stripped version; or a
|
242
|
+
# tuple of string urls, the first unstripped and the second
|
243
|
+
# stripped. It's a bit messy but we are keeping compatibility with
|
244
|
+
# earlier releases (and their cached release files) which did not
|
245
|
+
# have stripped versions.
|
246
|
+
impl, ver, distrib = name.split('-', maxsplit=2)
|
247
|
+
if impl not in files:
|
248
|
+
files[impl] = defaultdict(dict)
|
249
|
+
|
250
|
+
if exist := files[impl].get(ver, {}).get(distrib, {}):
|
251
|
+
files[impl][ver][distrib] = (exist, url) \
|
252
|
+
if stripped else (url, exist[1])
|
253
|
+
else:
|
254
|
+
files[impl][ver][distrib] = ('', url) if stripped else url
|
245
255
|
|
246
256
|
def get_release_files(args, tag, implementation: Optional[str] = None) -> dict:
|
247
257
|
'Return the release files for the given tag'
|
@@ -260,17 +270,19 @@ def get_release_files(args, tag, implementation: Optional[str] = None) -> dict:
|
|
260
270
|
except Exception:
|
261
271
|
return {}
|
262
272
|
|
263
|
-
# Iterate over the release assets and store
|
264
|
-
# return
|
265
|
-
for
|
266
|
-
|
267
|
-
|
273
|
+
# Iterate over the release assets and store pertinent files in a
|
274
|
+
# dict to return.
|
275
|
+
for asset in release.get_assets():
|
276
|
+
name = asset.name
|
277
|
+
if is_stripped := (STRIP_EXT in name):
|
278
|
+
name = name.replace(STRIP_EXT, '')
|
268
279
|
|
269
|
-
|
270
|
-
|
271
|
-
files
|
280
|
+
if m := re.search(ENDPAT, name):
|
281
|
+
name = re.sub(r'\+\d{8}', '', name[:m.start()])
|
282
|
+
merge(files, name, asset.browser_download_url, is_stripped)
|
272
283
|
|
273
|
-
|
284
|
+
if not files:
|
285
|
+
sys.exit(f'Failed to fetch any files for release {tag}')
|
274
286
|
|
275
287
|
if error := set_json(jfile, files):
|
276
288
|
sys.exit(f'Failed to write release {tag} file {jfile}: {error}')
|
@@ -309,13 +321,13 @@ def update_version_symlinks(args: Namespace) -> None:
|
|
309
321
|
for name, tgt in oldlinks.items():
|
310
322
|
new_tgt = newlinks.get(name)
|
311
323
|
if not new_tgt or new_tgt != tgt:
|
312
|
-
|
324
|
+
(base / name).unlink()
|
313
325
|
|
314
326
|
# Create all needed new links
|
315
327
|
for name, tgt in newlinks.items():
|
316
328
|
old_tgt = oldlinks.get(name)
|
317
329
|
if not old_tgt or old_tgt != tgt:
|
318
|
-
|
330
|
+
(base / name).symlink_to(tgt, target_is_directory=True)
|
319
331
|
|
320
332
|
def purge_unused_releases(args: Namespace) -> None:
|
321
333
|
'Purge old releases that are no longer needed and have expired'
|
@@ -368,34 +380,43 @@ def remove(args: Namespace, version: str) -> None:
|
|
368
380
|
|
369
381
|
shutil.rmtree(vdir)
|
370
382
|
|
371
|
-
def strip_binaries(vdir: Path, distribution: str) ->
|
383
|
+
def strip_binaries(vdir: Path, distribution: str) -> bool:
|
372
384
|
'Strip binaries from files in a version directory'
|
373
385
|
# Only run the strip command on Linux hosts and for Linux distributions
|
374
|
-
|
375
|
-
|
386
|
+
was_stripped = False
|
387
|
+
if platform.system() == 'Linux' and '-linux-' in distribution:
|
388
|
+
for path in ('bin', 'lib'):
|
389
|
+
base = vdir / path
|
390
|
+
if not base.is_dir():
|
391
|
+
continue
|
376
392
|
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
393
|
+
for file in base.iterdir():
|
394
|
+
if not file.is_symlink() and file.is_file():
|
395
|
+
cmd = f'strip -p --strip-unneeded {file}'.split()
|
396
|
+
try:
|
397
|
+
subprocess.run(cmd, stderr=subprocess.DEVNULL)
|
398
|
+
except Exception:
|
399
|
+
pass
|
400
|
+
else:
|
401
|
+
was_stripped = True
|
381
402
|
|
382
|
-
|
383
|
-
if not file.is_symlink() and file.is_file():
|
384
|
-
cmd = f'strip -p --strip-unneeded {file}'.split()
|
385
|
-
try:
|
386
|
-
subprocess.run(cmd, stderr=subprocess.DEVNULL)
|
387
|
-
except Exception:
|
388
|
-
pass
|
403
|
+
return was_stripped
|
389
404
|
|
390
405
|
def install(args: Namespace, vdir: Path, release: str, distribution: str,
|
391
406
|
files: dict) -> Optional[str]:
|
392
407
|
'Install a version'
|
393
408
|
version = vdir.name
|
394
409
|
|
395
|
-
if not (
|
410
|
+
if not (fileurl := files[version].get(distribution)):
|
396
411
|
return f'Arch "{distribution}" not found for release '\
|
397
412
|
f'{release} version {version}.'
|
398
413
|
|
414
|
+
if isinstance(fileurl, tuple):
|
415
|
+
stripped = not args.no_strip
|
416
|
+
fileurl = fileurl[stripped]
|
417
|
+
else:
|
418
|
+
stripped = False
|
419
|
+
|
399
420
|
tmpdir = args._versions / f'.{version}-tmp'
|
400
421
|
rm_path(tmpdir)
|
401
422
|
tmpdir.mkdir()
|
@@ -403,19 +424,32 @@ def install(args: Namespace, vdir: Path, release: str, distribution: str,
|
|
403
424
|
error = None
|
404
425
|
|
405
426
|
try:
|
406
|
-
urllib.request.urlretrieve(
|
427
|
+
urllib.request.urlretrieve(fileurl, tmpdir / 'tmp.tar.gz')
|
428
|
+
except Exception as e:
|
429
|
+
error = f'Failed to fetch "{fileurl}": {e}'
|
430
|
+
|
431
|
+
try:
|
407
432
|
shutil.unpack_archive(tmpdir / 'tmp.tar.gz', tmpdir)
|
408
433
|
except Exception as e:
|
409
|
-
error = f'Failed to
|
434
|
+
error = f'Failed to unpack "{fileurl}": {e}'
|
410
435
|
|
411
436
|
if not error:
|
412
437
|
data = {'release': release, 'distribution': distribution}
|
438
|
+
|
439
|
+
if args.no_strip:
|
440
|
+
data['stripped'] = 'forced off'
|
441
|
+
elif stripped and args.no_extra_strip:
|
442
|
+
data['stripped'] = 'at_source_only'
|
443
|
+
else:
|
444
|
+
if strip_binaries(tmpdir_py, distribution):
|
445
|
+
data['stripped'] = 'at_source_and_manually' \
|
446
|
+
if stripped else 'manually'
|
447
|
+
else:
|
448
|
+
data['stripped'] = 'at_source' if stripped else 'n/a'
|
449
|
+
|
413
450
|
if (error := set_json(tmpdir_py / args._data, data)):
|
414
451
|
error = f'Failed to write {version} data file: {error}'
|
415
452
|
|
416
|
-
if not args.do_not_strip:
|
417
|
-
strip_binaries(tmpdir_py, distribution)
|
418
|
-
|
419
453
|
if not error:
|
420
454
|
remove(args, version)
|
421
455
|
tmpdir_py.replace(vdir)
|
@@ -456,8 +490,10 @@ def main() -> Optional[str]:
|
|
456
490
|
opt.add_argument('--github-access-token',
|
457
491
|
help='optional Github access token. Can specify to reduce '
|
458
492
|
'rate limiting.')
|
459
|
-
opt.add_argument('--
|
460
|
-
help='
|
493
|
+
opt.add_argument('--no-strip', action='store_true',
|
494
|
+
help='do not use or create stripped binaries')
|
495
|
+
opt.add_argument('--no-extra-strip', action='store_true',
|
496
|
+
help='do not restrip already stripped source binaries')
|
461
497
|
opt.add_argument('-V', action='store_true',
|
462
498
|
help=f'show {PROG} version')
|
463
499
|
cmd = opt.add_subparsers(title='Commands', dest='cmdname')
|
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
|