Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/planemo/lint.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
author | shellac |
---|---|
date | Sat, 02 May 2020 07:14:21 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:26e78fe6e8c4 |
---|---|
1 """Utilities to help linting various targets.""" | |
2 from __future__ import absolute_import | |
3 | |
4 import os | |
5 | |
6 import requests | |
7 from galaxy.tool_util.lint import LintContext | |
8 from six.moves.urllib.request import urlopen | |
9 | |
10 import planemo.linters.biocontainer_registered | |
11 import planemo.linters.conda_requirements | |
12 import planemo.linters.doi | |
13 import planemo.linters.urls | |
14 import planemo.linters.xsd | |
15 from planemo.io import error | |
16 from planemo.shed import find_urls_for_xml | |
17 from planemo.xml import validation | |
18 | |
19 | |
20 def build_lint_args(ctx, **kwds): | |
21 """Handle common report, error, and skip linting arguments.""" | |
22 report_level = kwds.get("report_level", "all") | |
23 fail_level = kwds.get("fail_level", "warn") | |
24 skip = kwds.get("skip", None) | |
25 if skip is None: | |
26 skip = ctx.global_config.get("lint_skip", "") | |
27 if isinstance(skip, list): | |
28 skip = ",".join(skip) | |
29 | |
30 skip_types = [s.strip() for s in skip.split(",")] | |
31 lint_args = dict( | |
32 level=report_level, | |
33 fail_level=fail_level, | |
34 extra_modules=_lint_extra_modules(**kwds), | |
35 skip_types=skip_types, | |
36 ) | |
37 return lint_args | |
38 | |
39 | |
40 # TODO: Move this back to tool_lint. | |
41 def _lint_extra_modules(**kwds): | |
42 linters = [] | |
43 if kwds.get("xsd", True): | |
44 linters.append(planemo.linters.xsd) | |
45 | |
46 if kwds.get("doi", False): | |
47 linters.append(planemo.linters.doi) | |
48 | |
49 if kwds.get("urls", False): | |
50 linters.append(planemo.linters.urls) | |
51 | |
52 if kwds.get("conda_requirements", False): | |
53 linters.append(planemo.linters.conda_requirements) | |
54 | |
55 if kwds.get("biocontainer", False): | |
56 linters.append(planemo.linters.biocontainer_registered) | |
57 | |
58 return linters | |
59 | |
60 | |
61 def setup_lint(ctx, **kwds): | |
62 """Setup lint_args and lint_ctx to begin linting a target.""" | |
63 lint_args = build_lint_args(ctx, **kwds) | |
64 lint_ctx = LintContext(lint_args["level"]) | |
65 return lint_args, lint_ctx | |
66 | |
67 | |
68 def handle_lint_complete(lint_ctx, lint_args, failed=False): | |
69 """Complete linting of a target and decide exit code.""" | |
70 if not failed: | |
71 failed = lint_ctx.failed(lint_args["fail_level"]) | |
72 if failed: | |
73 error("Failed linting") | |
74 return 1 if failed else 0 | |
75 | |
76 | |
77 def lint_dois(tool_xml, lint_ctx): | |
78 """Find referenced DOIs and check they have valid with https://doi.org.""" | |
79 dois = find_dois_for_xml(tool_xml) | |
80 for publication in dois: | |
81 is_doi(publication, lint_ctx) | |
82 | |
83 | |
84 def find_dois_for_xml(tool_xml): | |
85 dois = [] | |
86 for element in tool_xml.getroot().findall("citations"): | |
87 for citation in list(element): | |
88 if citation.tag == 'citation' and citation.attrib.get('type', '') == 'doi': | |
89 dois.append(citation.text) | |
90 return dois | |
91 | |
92 | |
93 def is_doi(publication_id, lint_ctx): | |
94 """Check if dx.doi knows about the ``publication_id``.""" | |
95 base_url = "https://doi.org" | |
96 if publication_id is None: | |
97 lint_ctx.error('Empty DOI citation') | |
98 return | |
99 publication_id = publication_id.strip() | |
100 doiless_publication_id = publication_id.split("doi:", 1)[-1] | |
101 if not doiless_publication_id: | |
102 lint_ctx.error('Empty DOI citation') | |
103 return | |
104 url = "%s/%s" % (base_url, doiless_publication_id) | |
105 r = requests.get(url) | |
106 if r.status_code == 200: | |
107 if publication_id != doiless_publication_id: | |
108 lint_ctx.error("%s is valid, but Galaxy expects DOI without 'doi:' prefix" % publication_id) | |
109 else: | |
110 lint_ctx.info("%s is a valid DOI" % publication_id) | |
111 elif r.status_code == 404: | |
112 lint_ctx.error("%s is not a valid DOI" % publication_id) | |
113 else: | |
114 lint_ctx.warn("dx.doi returned unexpected status code %d" % r.status_code) | |
115 | |
116 | |
117 def lint_xsd(lint_ctx, schema_path, path): | |
118 """Lint XML at specified path with supplied schema.""" | |
119 name = lint_ctx.object_name or os.path.basename(path) | |
120 validator = validation.get_validator(require=True) | |
121 validation_result = validator.validate(schema_path, path) | |
122 if not validation_result.passed: | |
123 msg = "Invalid XML found in file: %s. Errors [%s]" | |
124 msg = msg % (name, validation_result.output) | |
125 lint_ctx.error(msg) | |
126 else: | |
127 lint_ctx.info("File validates against XML schema.") | |
128 | |
129 | |
130 def lint_urls(root, lint_ctx): | |
131 """Find referenced URLs and verify they are valid.""" | |
132 urls, docs = find_urls_for_xml(root) | |
133 | |
134 # This is from Google Chome on macOS, current at time of writing: | |
135 BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36" | |
136 | |
137 def validate_url(url, lint_ctx, user_agent=None): | |
138 is_valid = True | |
139 if url.startswith('http://') or url.startswith('https://'): | |
140 if user_agent: | |
141 headers = {"User-Agent": user_agent, 'Accept': '*/*'} | |
142 else: | |
143 headers = None | |
144 r = None | |
145 try: | |
146 r = requests.get(url, headers=headers, stream=True) | |
147 r.raise_for_status() | |
148 next(r.iter_content(1000)) | |
149 except Exception as e: | |
150 if r and r.status_code == 429: | |
151 # too many requests | |
152 pass | |
153 else: | |
154 is_valid = False | |
155 lint_ctx.error("Error '%s' accessing %s" % (e, url)) | |
156 else: | |
157 try: | |
158 with urlopen(url) as handle: | |
159 handle.read(100) | |
160 except Exception as e: | |
161 is_valid = False | |
162 lint_ctx.error("Error '%s' accessing %s" % (e, url)) | |
163 if is_valid: | |
164 lint_ctx.info("URL OK %s" % url) | |
165 | |
166 for url in urls: | |
167 validate_url(url, lint_ctx) | |
168 for url in docs: | |
169 validate_url(url, lint_ctx, BROWSER_USER_AGENT) | |
170 | |
171 | |
172 __all__ = ( | |
173 "build_lint_args", | |
174 "handle_lint_complete", | |
175 "lint_dois", | |
176 "lint_urls", | |
177 "lint_xsd", | |
178 ) |