Просмотр исходного кода

Miniconda script review comments

README, better docs + logging
pull/1361/head
Chris Barnes 6 лет назад
Родитель
Сommit
81e797be12
2 измененных файлов: 61 добавлений и 10 удалений
  1. +22
    -0
      plugins/python-build/scripts/README.md
  2. +39
    -10
      plugins/python-build/scripts/add_miniconda.py

+ 22
- 0
plugins/python-build/scripts/README.md Просмотреть файл

@ -0,0 +1,22 @@
# Scripts for updating python-build
Install dependencies with `pip install -r requirements.txt`.
## add_miniconda.py
```_add_miniconda
usage: add_miniconda.py [-h] [-d] [-v]
Script to add non-"latest" miniconda releases. Written for python 3.7. Checks
the miniconda download archives for new versions, then writes a build script
for any which do not exist locally, saving it to plugins/python-
build/share/python-build. Ignores releases below 4.3.30. Also ignores sub-
patch releases if that major.minor.patch already exists, but otherwise, takes
the latest sub-patch release for given OS/arch. Assumes all miniconda3
releases < 4.7 default to python 3.6, and anything else 3.7.
optional arguments:
-h, --help show this help message and exit
-d, --dry-run Do not write scripts, just report them to stdout
-v, --verbose Increase verbosity of logging
```

+ 39
- 10
plugins/python-build/scripts/add_miniconda.py Просмотреть файл

@ -1,12 +1,15 @@
#!/usr/bin/env python3.7
#!/usr/bin/env python3
"""Script to add non-"latest" miniconda releases. """Script to add non-"latest" miniconda releases.
Written for python 3.7.
- Ignores releases below 4.3.30.
- Ignores sub-patch releases if that major.minor.patch already exists
- But otherwise, takes the latest sub-patch release for given OS/arch
- Assumes all miniconda3 releases < 4.7 default to python 3.6, and anything else 3.7
Checks the miniconda download archives for new versions,
then writes a build script for any which do not exist locally,
saving it to plugins/python-build/share/python-build.
Use -d for dry run.
Ignores releases below 4.3.30.
Also ignores sub-patch releases if that major.minor.patch already exists,
but otherwise, takes the latest sub-patch release for given OS/arch.
Assumes all miniconda3 releases < 4.7 default to python 3.6, and anything else 3.7.
""" """
import textwrap import textwrap
from argparse import ArgumentParser from argparse import ArgumentParser
@ -15,9 +18,12 @@ from enum import Enum
from functools import total_ordering from functools import total_ordering
from pathlib import Path from pathlib import Path
from typing import NamedTuple, List, Optional, DefaultDict, Dict from typing import NamedTuple, List, Optional, DefaultDict, Dict
import logging
import requests_html import requests_html
logger = logging.getLogger(__name__)
CONDA_REPO = "https://repo.anaconda.com" CONDA_REPO = "https://repo.anaconda.com"
MINICONDA_REPO = CONDA_REPO + "/miniconda" MINICONDA_REPO = CONDA_REPO + "/miniconda"
# ANACONDA_REPO = CONDA_REPO + "/archive" # ANACONDA_REPO = CONDA_REPO + "/archive"
@ -47,7 +53,7 @@ out_dir: Path = here.parent.parent / "share" / "python-build"
class StrEnum(str, Enum): class StrEnum(str, Enum):
"""Enum subclass which members are also instances of str
"""Enum subclass whose members are also instances of str
and directly comparable to strings. str type is forced at declaration. and directly comparable to strings. str type is forced at declaration.
Adapted from https://github.com/kissgyorgy/enum34-custom/blob/dbc89596761c970398701d26c6a5bbcfcf70f548/enum_custom.py#L100 Adapted from https://github.com/kissgyorgy/enum34-custom/blob/dbc89596761c970398701d26c6a5bbcfcf70f548/enum_custom.py#L100
@ -189,6 +195,7 @@ def make_script(specs: List[MinicondaSpec]):
def get_existing_minicondas(): def get_existing_minicondas():
logger.info("Getting known miniconda versions")
for p in out_dir.iterdir(): for p in out_dir.iterdir():
name = p.name name = p.name
if not p.is_file() or not name.startswith("miniconda"): if not p.is_file() or not name.startswith("miniconda"):
@ -196,12 +203,14 @@ def get_existing_minicondas():
try: try:
v = MinicondaVersion.from_str(name) v = MinicondaVersion.from_str(name)
if v.version_str != "latest": if v.version_str != "latest":
logger.debug("Found existing miniconda version %s", v)
yield v yield v
except ValueError: except ValueError:
pass pass
def get_available_minicondas(): def get_available_minicondas():
logger.info("Fetching remote miniconda versions")
session = requests_html.HTMLSession() session = requests_html.HTMLSession()
response = session.get(MINICONDA_REPO) response = session.get(MINICONDA_REPO)
page: requests_html.HTML = response.html page: requests_html.HTML = response.html
@ -219,6 +228,7 @@ def get_available_minicondas():
try: try:
s = MinicondaSpec.from_filestem(stem, md5) s = MinicondaSpec.from_filestem(stem, md5)
if s.version.version_str != "latest": if s.version.version_str != "latest":
logger.debug("Found remote miniconda version %s", s)
yield s yield s
except ValueError: except ValueError:
pass pass
@ -234,10 +244,26 @@ def key_fn(spec: MinicondaSpec):
if __name__ == "__main__": if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("-d", "--dry_run", action="store_true")
parser = ArgumentParser(description=__doc__)
parser.add_argument(
"-d", "--dry-run", action="store_true",
help="Do not write scripts, just report them to stdout",
)
parser.add_argument(
"-v", "--verbose", action="count",
help="Increase verbosity of logging",
)
parsed = parser.parse_args() parsed = parser.parse_args()
log_level = {
0: logging.WARNING,
1: logging.INFO,
2: logging.DEBUG,
}.get(parsed.verbose, logging.DEBUG)
logging.basicConfig(level=log_level)
if parsed.verbose < 3:
logging.getLogger("requests").setLevel(logging.WARNING)
existing_versions = set(get_existing_minicondas()) existing_versions = set(get_existing_minicondas())
available_specs = set(get_available_minicondas()) available_specs = set(get_available_minicondas())
@ -246,18 +272,21 @@ if __name__ == "__main__":
MinicondaVersion, Dict[MinicondaSpec, MinicondaSpec] MinicondaVersion, Dict[MinicondaSpec, MinicondaSpec]
] = defaultdict(dict) ] = defaultdict(dict)
logger.info("Checking for new versions")
for s in sorted(available_specs, key=key_fn): for s in sorted(available_specs, key=key_fn):
key = s.version.with_version_triple() key = s.version.with_version_triple()
if key in existing_versions or key.version_str.info() <= (4, 3, 30): if key in existing_versions or key.version_str.info() <= (4, 3, 30):
logger.debug("Ignoring version %s (too old or already exists)", s)
continue continue
to_add[key][s.with_version_triple()] = s to_add[key][s.with_version_triple()] = s
logger.info("Writing %s scripts", len(to_add))
for ver, d in to_add.items(): for ver, d in to_add.items():
specs = list(d.values()) specs = list(d.values())
fpath = out_dir / ver.to_filename() fpath = out_dir / ver.to_filename()
script_str = make_script(specs) script_str = make_script(specs)
logger.debug("Writing script for %s", ver)
if parsed.dry_run: if parsed.dry_run:
print(f"Would write spec to {fpath}:\n" + textwrap.indent(script_str, " ")) print(f"Would write spec to {fpath}:\n" + textwrap.indent(script_str, " "))
else: else:

Загрузка…
Отмена
Сохранить