pystand 1.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pystand
3
- Version: 1.2
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
@@ -117,7 +117,8 @@ 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] [-V]
120
+ [--purge-days PURGE_DAYS]
121
+ [--github-access-token GITHUB_ACCESS_TOKEN] [-V]
121
122
  {install,update,remove,list,show,path} ...
122
123
 
123
124
  Command line tool to download, install, and update pre-built Python versions
@@ -139,8 +140,11 @@ options:
139
140
  before rechecking for latest. Default is 60 minutes
140
141
  --purge-days PURGE_DAYS
141
142
  cache release file lists for this number of days after
142
- last version referencing it is removed. Default is 30
143
+ last version referencing it is removed. Default is 90
143
144
  days
145
+ --github-access-token GITHUB_ACCESS_TOKEN
146
+ Optional Github access token. Can specify to reduce
147
+ rate limiting.
144
148
  -V show pystand version
145
149
 
146
150
  Commands:
@@ -333,8 +337,8 @@ anything after on a line) are ignored. Type `pystand` to see all
333
337
  supported options.
334
338
 
335
339
  The global options: `--distribution`, `--base-dir`, `--cache-minutes`,
336
- `--purge-days` are the only sensible candidates to consider setting as
337
- defaults.
340
+ `--purge-days`, `--github-access-token` are the only sensible candidates
341
+ to consider setting as defaults.
338
342
 
339
343
  ## Command Line Tab Completion
340
344
 
@@ -101,7 +101,8 @@ 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] [-V]
104
+ [--purge-days PURGE_DAYS]
105
+ [--github-access-token GITHUB_ACCESS_TOKEN] [-V]
105
106
  {install,update,remove,list,show,path} ...
106
107
 
107
108
  Command line tool to download, install, and update pre-built Python versions
@@ -123,8 +124,11 @@ options:
123
124
  before rechecking for latest. Default is 60 minutes
124
125
  --purge-days PURGE_DAYS
125
126
  cache release file lists for this number of days after
126
- last version referencing it is removed. Default is 30
127
+ last version referencing it is removed. Default is 90
127
128
  days
129
+ --github-access-token GITHUB_ACCESS_TOKEN
130
+ Optional Github access token. Can specify to reduce
131
+ rate limiting.
128
132
  -V show pystand version
129
133
 
130
134
  Commands:
@@ -317,8 +321,8 @@ anything after on a line) are ignored. Type `pystand` to see all
317
321
  supported options.
318
322
 
319
323
  The global options: `--distribution`, `--base-dir`, `--cache-minutes`,
320
- `--purge-days` are the only sensible candidates to consider setting as
321
- defaults.
324
+ `--purge-days`, `--github-access-token` are the only sensible candidates
325
+ to consider setting as defaults.
322
326
 
323
327
  ## Command Line Tab Completion
324
328
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pystand
3
- Version: 1.2
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
@@ -117,7 +117,8 @@ 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] [-V]
120
+ [--purge-days PURGE_DAYS]
121
+ [--github-access-token GITHUB_ACCESS_TOKEN] [-V]
121
122
  {install,update,remove,list,show,path} ...
122
123
 
123
124
  Command line tool to download, install, and update pre-built Python versions
@@ -139,8 +140,11 @@ options:
139
140
  before rechecking for latest. Default is 60 minutes
140
141
  --purge-days PURGE_DAYS
141
142
  cache release file lists for this number of days after
142
- last version referencing it is removed. Default is 30
143
+ last version referencing it is removed. Default is 90
143
144
  days
145
+ --github-access-token GITHUB_ACCESS_TOKEN
146
+ Optional Github access token. Can specify to reduce
147
+ rate limiting.
144
148
  -V show pystand version
145
149
 
146
150
  Commands:
@@ -333,8 +337,8 @@ anything after on a line) are ignored. Type `pystand` to see all
333
337
  supported options.
334
338
 
335
339
  The global options: `--distribution`, `--base-dir`, `--cache-minutes`,
336
- `--purge-days` are the only sensible candidates to consider setting as
337
- defaults.
340
+ `--purge-days`, `--github-access-token` are the only sensible candidates
341
+ to consider setting as defaults.
338
342
 
339
343
  ## Command Line Tab Completion
340
344
 
@@ -31,6 +31,13 @@ GITHUB_REPO = f'{REPO_OWNER}/{REPO}'
31
31
  LATEST_RELEASE_URL = f'https://raw.githubusercontent.com/{GITHUB_REPO}'\
32
32
  '/latest-release/latest-release.json'
33
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
+
34
41
  PROG = Path(__file__).stem
35
42
  CNFFILE = platformdirs.user_config_path(f'{PROG}-flags.conf')
36
43
 
@@ -99,7 +106,14 @@ def get_gh(args: Namespace) -> Any:
99
106
  return get_gh_handle
100
107
 
101
108
  from github import Github
102
- get_gh_handle = Github() # type: ignore
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
103
117
  return get_gh_handle
104
118
 
105
119
  def rm_path(path: Path) -> None:
@@ -169,8 +183,18 @@ def get_version_names(args: Namespace) -> list[str]:
169
183
  return sorted(all_names - given, key=parse_version) \
170
184
  if args.all else versions
171
185
 
172
- def get_latest_release_tag(args: Namespace) -> str:
173
- 'Return the latest release tag'
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
+
174
198
  if args._latest_release.exists():
175
199
  stat = args._latest_release.stat()
176
200
  if time.time() < (stat.st_mtime + int(args.cache_minutes * 60)):
@@ -193,6 +217,15 @@ def get_latest_release_tag(args: Namespace) -> str:
193
217
  args._latest_release.write_text(tag + '\n')
194
218
  return tag
195
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
+
196
229
  def get_release_files(args, tag, implementation: Optional[str] = None) -> dict:
197
230
  'Return the release files for the given tag'
198
231
  # Look for tag data in our release cache
@@ -212,17 +245,11 @@ def get_release_files(args, tag, implementation: Optional[str] = None) -> dict:
212
245
 
213
246
  # Iterate over the release assets and store the files in a dict to
214
247
  # return
215
- end = '-install_only.tar.gz'
216
248
  for file in release.get_assets():
217
- name = file.name
218
- if not name.endswith(end):
249
+ if not (name := get_release_name(file.name)):
219
250
  continue
220
251
 
221
- name = name[:-len(end)]
222
- impl_ver, rest = name.split('+', maxsplit=1)
223
- impl, ver = impl_ver.split('-', maxsplit=1)
224
- rest = rest.split('-', maxsplit=1)[1]
225
-
252
+ impl, ver, rest = name.split('-', maxsplit=2)
226
253
  if impl not in files:
227
254
  files[impl] = defaultdict(dict)
228
255
 
@@ -384,10 +411,13 @@ def main() -> Optional[str]:
384
411
  help='cache latest release tag fetch for this many '
385
412
  'minutes, before rechecking for latest. '
386
413
  'Default is %(default)d minutes')
387
- opt.add_argument('--purge-days', default=30, type=int,
414
+ opt.add_argument('--purge-days', default=90, type=int,
388
415
  help='cache release file lists for this number '
389
416
  'of days after last version referencing it is removed. '
390
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.')
391
421
  opt.add_argument('-V', action='store_true',
392
422
  help=f'show {PROG} version')
393
423
  cmd = opt.add_subparsers(title='Commands', dest='cmdname')
@@ -475,7 +505,7 @@ class _install(COMMAND):
475
505
 
476
506
  @staticmethod
477
507
  def run(args: Namespace) -> Optional[str]:
478
- release = args.release or get_latest_release_tag(args)
508
+ release = get_release_tag(args)
479
509
  files = get_release_files(args, release, 'cpython')
480
510
  if not files:
481
511
  return f'Release "{release}" not found, or has no compatible files.'
@@ -519,7 +549,7 @@ class _update(COMMAND):
519
549
 
520
550
  @staticmethod
521
551
  def run(args: Namespace) -> Optional[str]:
522
- release_target = args.release or get_latest_release_tag(args)
552
+ release_target = get_release_tag(args)
523
553
  files = get_release_files(args, release_target, 'cpython')
524
554
  if not files:
525
555
  return f'Release "{release_target}" not found.'
@@ -602,7 +632,7 @@ class _list(COMMAND):
602
632
 
603
633
  @staticmethod
604
634
  def run(args: Namespace) -> Optional[str]:
605
- release_target = args.release or get_latest_release_tag(args)
635
+ release_target = get_release_tag(args)
606
636
  files = get_release_files(args, release_target, 'cpython')
607
637
  if not files:
608
638
  return f'Release "{release_target}" not found.'
@@ -656,7 +686,7 @@ class _show(COMMAND):
656
686
 
657
687
  @staticmethod
658
688
  def run(args: Namespace) -> None:
659
- release = args.release or get_latest_release_tag(args)
689
+ release = get_release_tag(args)
660
690
  files = get_release_files(args, release, 'cpython')
661
691
  if not files:
662
692
  sys.exit(f'Error: release "{release}" not found.')
File without changes
File without changes
File without changes
File without changes
File without changes