Mercurial > repos > shellac > guppy_basecaller
diff env/lib/python3.7/site-packages/planemo/conda_verify/recipe.py @ 5:9b1c78e6ba9c draft default tip
"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author | shellac |
---|---|
date | Mon, 01 Jun 2020 08:59:25 -0400 |
parents | 79f47841a781 |
children |
line wrap: on
line diff
--- a/env/lib/python3.7/site-packages/planemo/conda_verify/recipe.py Thu May 14 16:47:39 2020 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,337 +0,0 @@ -from __future__ import ( - absolute_import, - division, - print_function, -) - -import os -import re -from os.path import ( - basename, - getsize, - isfile, - join, -) - -import yaml - -from planemo.conda_verify.const import ( - FIELDS, - LICENSE_FAMILIES, -) -from planemo.conda_verify.utils import ( - all_ascii, - get_bad_seq, - memoized, -) - -PEDANTIC = True -sel_pat = re.compile(r'(.+?)\s*\[(.+)\]$') -name_pat = re.compile(r'[a-z0-9_][a-z0-9_\-\.]*$') -version_pat = re.compile(r'[\w\.]+$') -url_pat = re.compile(r'(ftp|http(s)?)://') - - -class RecipeError(Exception): - pass - - -def ns_cfg(cfg): - plat = cfg['plat'] - py = cfg['PY'] - np = cfg['NPY'] - for x in py, np: - assert isinstance(x, int), x - return dict( - nomkl=False, - debug=False, - linux=plat.startswith('linux-'), - linux32=bool(plat == 'linux-32'), - linux64=bool(plat == 'linux-64'), - armv7l=False, - arm=False, - ppc64le=False, - osx=plat.startswith('osx-'), - unix=plat.startswith(('linux-', 'osx-')), - win=plat.startswith('win-'), - win32=bool(plat == 'win-32'), - win64=bool(plat == 'win-64'), - x86=plat.endswith(('-32', '-64')), - x86_64=plat.endswith('-64'), - py=py, - py3k=bool(30 <= py < 40), - py2k=bool(20 <= py < 30), - py26=bool(py == 26), - py27=bool(py == 27), - py33=bool(py == 33), - py34=bool(py == 34), - py35=bool(py == 35), - np=np, - ) - - -def select_lines(data, namespace): - lines = [] - for line in data.splitlines(): - line = line.rstrip() - m = sel_pat.match(line) - if m: - if PEDANTIC: - x = m.group(1).strip() - # error on comment, unless the whole line is a comment - if '#' in x and not x.startswith('#'): - raise RecipeError("found commented selector: %s" % line) - cond = m.group(2) - if eval(cond, namespace, {}): - lines.append(m.group(1)) - continue - lines.append(line) - return '\n'.join(lines) + '\n' - - -@memoized -def yamlize(data): - res = yaml.safe_load(data) - # ensure the result is a dict - if res is None: - res = {} - return res - - -def parse(data, cfg): - if cfg is not None: - data = select_lines(data, ns_cfg(cfg)) - # ensure we create new object, because yamlize is memoized - return dict(yamlize(data)) - - -def get_field(meta, field, default=None): - section, key = field.split('/') - submeta = meta.get(section) - if submeta is None: - submeta = {} - res = submeta.get(key) - if res is None: - res = default - return res - - -def check_name(name): - if name: - name = str(name) - else: - raise RecipeError("package name missing") - if not name_pat.match(name) or name.endswith(('.', '-', '_')): - raise RecipeError("invalid package name '%s'" % name) - seq = get_bad_seq(name) - if seq: - raise RecipeError("'%s' is not allowed in " - "package name: '%s'" % (seq, name)) - - -def check_version(ver): - if ver: - ver = str(ver) - else: - raise RecipeError("package version missing") - if not version_pat.match(ver): - raise RecipeError("invalid version '%s'" % ver) - if ver.startswith(('_', '.')) or ver.endswith(('_', '.')): - raise RecipeError("version cannot start or end with '_' or '.': %s" % - ver) - seq = get_bad_seq(ver) - if seq: - raise RecipeError("'%s' not allowed in version '%s'" % (seq, ver)) - - -def check_build_number(bn): - if not (isinstance(bn, int) and bn >= 0): - raise RecipeError("build/number '%s' (not a positive interger)" % bn) - - -def check_requirements(meta): - for req in get_field(meta, 'requirements/run', []): - name = req.split()[0] - if not name_pat.match(name): - raise RecipeError("invalid run requirement name '%s'" % name) - - -def check_license_family(meta): - if not PEDANTIC: - return - lf = get_field(meta, 'about/license_family', - get_field(meta, 'about/license')) - if lf not in LICENSE_FAMILIES: - print("""\ -Error: license_family is invalid: %s -Note that about/license_family falls back to about/license. -Allowed license families are:""" % lf) - for x in LICENSE_FAMILIES: - print(" - %s" % x) - raise RecipeError("wrong license family") - - -def check_url(url): - if not url_pat.match(url): - raise RecipeError("not a valid URL: %s" % url) - - -def check_about(meta): - summary = get_field(meta, 'about/summary') - if summary and len(summary) > 80: - msg = "summary exceeds 80 characters" - if PEDANTIC: - raise RecipeError(msg) - else: - print("Warning: %s" % msg) - - for field in ('about/home', 'about/dev_url', 'about/doc_url', - 'about/license_url'): - url = get_field(meta, field) - if url: - check_url(url) - - check_license_family(meta) - - -hash_pat = {'md5': re.compile(r'[a-f0-9]{32}$'), - 'sha1': re.compile(r'[a-f0-9]{40}$'), - 'sha256': re.compile(r'[a-f0-9]{64}$')} - - -def check_source(meta): - src = meta.get('source') - if not src: - return - fn = src.get('fn') - if fn: - for ht in 'md5', 'sha1', 'sha256': - hexgigest = src.get(ht) - if hexgigest and not hash_pat[ht].match(hexgigest): - raise RecipeError("invalid hash: %s" % hexgigest) - url = src.get('url') - if url: - check_url(url) - - git_url = src.get('git_url') - if git_url and (src.get('git_tag') and src.get('git_branch')): - raise RecipeError("cannot specify both git_branch and git_tag") - - -def validate_meta(meta): - for section in meta: - if PEDANTIC and section not in FIELDS: - raise RecipeError("Unknown section: %s" % section) - submeta = meta.get(section) - if submeta is None: - submeta = {} - for key in submeta: - if PEDANTIC and key not in FIELDS[section]: - raise RecipeError("in section %r: unknown key %r" % - (section, key)) - - check_name(get_field(meta, 'package/name')) - check_version(get_field(meta, 'package/version')) - check_build_number(get_field(meta, 'build/number', 0)) - check_requirements(meta) - check_about(meta) - check_source(meta) - - -def validate_files(recipe_dir, meta): - for field in 'test/files', 'source/patches': - flst = get_field(meta, field) - if not flst: - continue - for fn in flst: - if PEDANTIC and fn.startswith('..'): - raise RecipeError("path outsite recipe: %s" % fn) - path = join(recipe_dir, fn) - if isfile(path): - continue - raise RecipeError("no such file '%s'" % path) - - -def iter_cfgs(): - for py in 27, 34, 35: - for plat in 'linux-64', 'linux-32', 'osx-64', 'win-32', 'win-64': - yield dict(plat=plat, PY=py, NPY=111) - - -def dir_size(dir_path): - return sum(sum(getsize(join(root, fn)) for fn in files) - for root, unused_dirs, files in os.walk(dir_path)) - - -def check_dir_content(recipe_dir): - disallowed_extensions = ( - '.tar', '.tar.gz', '.tar.bz2', '.tar.xz', - '.so', '.dylib', '.la', '.a', '.dll', '.pyd', - ) - for root, unused_dirs, files in os.walk(recipe_dir): - for fn in files: - fn_lower = fn.lower() - if fn_lower.endswith(disallowed_extensions): - if PEDANTIC: - raise RecipeError("found: %s" % fn) - else: - print("Warning: found: %s" % fn) - path = join(root, fn) - # only allow small archives for testing - if (PEDANTIC and fn_lower.endswith(('.bz2', '.gz')) and getsize(path) > 512): - raise RecipeError("found: %s (too large)" % fn) - - if basename(recipe_dir) == 'icu': - return - - # check total size od recipe directory (recursively) - kb_size = dir_size(recipe_dir) / 1024 - kb_limit = 512 - if PEDANTIC and kb_size > kb_limit: - raise RecipeError("recipe too large: %d KB (limit %d KB)" % - (kb_size, kb_limit)) - - if PEDANTIC: - try: - with open(join(recipe_dir, 'build.sh'), 'rb') as fi: - data = fi.read() - if data and not data.decode('utf-8').startswith(('#!/bin/bash\n', - '#!/bin/sh\n')): - raise RecipeError("not a bash script: build.sh") - except IOError: - pass - - -def render_jinja2(recipe_dir): - import jinja2 - - loaders = [jinja2.FileSystemLoader(recipe_dir)] - env = jinja2.Environment(loader=jinja2.ChoiceLoader(loaders)) - template = env.get_or_select_template('meta.yaml') - return template.render(environment=env) - - -def validate_recipe(recipe_dir, pedantic=True): - global PEDANTIC - PEDANTIC = bool(pedantic) - - meta_path = join(recipe_dir, 'meta.yaml') - with open(meta_path, 'rb') as fi: - data = fi.read() - if PEDANTIC and not all_ascii(data): - raise RecipeError("non-ASCII in: %s" % meta_path) - if b'{{' in data: - if PEDANTIC: - raise RecipeError("found {{ in %s (Jinja templating not allowed)" % - meta_path) - else: - data = render_jinja2(recipe_dir) - else: - data = data.decode('utf-8') - - check_dir_content(recipe_dir) - - for cfg in iter_cfgs(): - meta = parse(data, cfg) - validate_meta(meta) - validate_files(recipe_dir, meta)