Mercurial > repos > bcclaywell > argo_navis
comparison venv/lib/python2.7/site-packages/planemo/shed_lint.py @ 0:d67268158946 draft
planemo upload commit a3f181f5f126803c654b3a66dd4e83a48f7e203b
| author | bcclaywell |
|---|---|
| date | Mon, 12 Oct 2015 17:43:33 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:d67268158946 |
|---|---|
| 1 import os | |
| 2 import yaml | |
| 3 from galaxy.tools.lint import LintContext | |
| 4 from galaxy.tools.linters.help import rst_invalid | |
| 5 from planemo.lint import lint_xsd | |
| 6 from planemo.shed import ( | |
| 7 REPO_TYPE_UNRESTRICTED, | |
| 8 REPO_TYPE_TOOL_DEP, | |
| 9 REPO_TYPE_SUITE, | |
| 10 CURRENT_CATEGORIES, | |
| 11 validate_repo_owner, | |
| 12 validate_repo_name, | |
| 13 ) | |
| 14 from planemo.tool_lint import ( | |
| 15 build_lint_args, | |
| 16 yield_tool_xmls, | |
| 17 handle_tool_load_error, | |
| 18 ) | |
| 19 from planemo.shed2tap import base | |
| 20 from planemo.xml import XSDS_PATH | |
| 21 | |
| 22 | |
| 23 from planemo.io import info | |
| 24 from planemo.io import error | |
| 25 | |
| 26 from galaxy.tools.lint import lint_xml_with | |
| 27 | |
| 28 TOOL_DEPENDENCIES_XSD = os.path.join(XSDS_PATH, "tool_dependencies.xsd") | |
| 29 REPO_DEPENDENCIES_XSD = os.path.join(XSDS_PATH, "repository_dependencies.xsd") | |
| 30 | |
| 31 | |
| 32 VALID_REPOSITORY_TYPES = [ | |
| 33 REPO_TYPE_UNRESTRICTED, | |
| 34 REPO_TYPE_TOOL_DEP, | |
| 35 REPO_TYPE_SUITE, | |
| 36 ] | |
| 37 | |
| 38 SHED_METADATA = [ | |
| 39 "description", | |
| 40 "long_description", | |
| 41 "remote_repository_url", | |
| 42 "homepage_url", | |
| 43 "categories", | |
| 44 ] | |
| 45 | |
| 46 | |
| 47 def lint_repository(ctx, realized_repository, **kwds): | |
| 48 # TODO: this really needs to start working with realized path. | |
| 49 failed = False | |
| 50 path = realized_repository.real_path | |
| 51 info("Linting repository %s" % path) | |
| 52 lint_args = build_lint_args(ctx, **kwds) | |
| 53 lint_ctx = LintContext(lint_args["level"]) | |
| 54 lint_ctx.lint( | |
| 55 "lint_expansion", | |
| 56 lint_expansion, | |
| 57 realized_repository, | |
| 58 ) | |
| 59 lint_ctx.lint( | |
| 60 "lint_expected_files", | |
| 61 lint_expected_files, | |
| 62 realized_repository, | |
| 63 ) | |
| 64 lint_ctx.lint( | |
| 65 "lint_tool_dependencies_xsd", | |
| 66 lint_tool_dependencies_xsd, | |
| 67 path, | |
| 68 ) | |
| 69 lint_ctx.lint( | |
| 70 "lint_tool_dependencies_actions", | |
| 71 lint_tool_dependencies_actions, | |
| 72 path, | |
| 73 ) | |
| 74 lint_ctx.lint( | |
| 75 "lint_repository_dependencies", | |
| 76 lint_repository_dependencies, | |
| 77 path, | |
| 78 ) | |
| 79 lint_ctx.lint( | |
| 80 "lint_shed_yaml", | |
| 81 lint_shed_yaml, | |
| 82 realized_repository, | |
| 83 ) | |
| 84 lint_ctx.lint( | |
| 85 "lint_readme", | |
| 86 lint_readme, | |
| 87 path, | |
| 88 ) | |
| 89 if kwds["tools"]: | |
| 90 for (tool_path, tool_xml) in yield_tool_xmls(ctx, path, | |
| 91 recursive=True): | |
| 92 info("+Linting tool %s" % tool_path) | |
| 93 if handle_tool_load_error(tool_path, tool_xml): | |
| 94 failed = True | |
| 95 continue | |
| 96 lint_xml_with( | |
| 97 lint_ctx, | |
| 98 tool_xml, | |
| 99 extra_modules=lint_args["extra_modules"] | |
| 100 ) | |
| 101 if kwds["ensure_metadata"]: | |
| 102 lint_ctx.lint( | |
| 103 "lint_shed_metadata", | |
| 104 lint_shed_metadata, | |
| 105 realized_repository, | |
| 106 ) | |
| 107 if not failed: | |
| 108 failed = lint_ctx.failed(lint_args["fail_level"]) | |
| 109 if failed: | |
| 110 error("Failed linting") | |
| 111 return 1 if failed else 0 | |
| 112 | |
| 113 | |
| 114 def lint_expansion(realized_repository, lint_ctx): | |
| 115 missing = realized_repository.missing | |
| 116 if missing: | |
| 117 msg = "Failed to expand inclusions %s" % missing | |
| 118 lint_ctx.warn(msg) | |
| 119 else: | |
| 120 lint_ctx.info("Included files all found.") | |
| 121 | |
| 122 | |
| 123 def lint_shed_metadata(realized_repository, lint_ctx): | |
| 124 found_all = True | |
| 125 for key in SHED_METADATA: | |
| 126 if key not in realized_repository.config: | |
| 127 found_all = False | |
| 128 lint_ctx.warn( | |
| 129 "Missing shed metadata field [%s] for repository" % key | |
| 130 ) | |
| 131 if found_all: | |
| 132 lint_ctx.info( | |
| 133 "Found all shed metadata fields required for automated repository " | |
| 134 "creation and/or updates." | |
| 135 ) | |
| 136 | |
| 137 | |
| 138 def lint_readme(path, lint_ctx): | |
| 139 readme_rst = os.path.join(path, "README.rst") | |
| 140 readme = os.path.join(path, "README") | |
| 141 readme_txt = os.path.join(path, "README.txt") | |
| 142 | |
| 143 readme_found = False | |
| 144 for readme in [readme_rst, readme, readme_txt]: | |
| 145 if os.path.exists(readme): | |
| 146 readme_found = readme | |
| 147 | |
| 148 readme_md = os.path.join(path, "README.md") | |
| 149 if not readme_found and os.path.exists(readme_md): | |
| 150 lint_ctx.warn("Tool Shed doesn't render markdown, " | |
| 151 "README.md is invalid readme.") | |
| 152 return | |
| 153 | |
| 154 if not readme_found: | |
| 155 # TODO: filter on TYPE and make this a warning if | |
| 156 # unrestricted repository - need to update iuc standards | |
| 157 # first though. | |
| 158 lint_ctx.info("No README found skipping.") | |
| 159 return | |
| 160 | |
| 161 if readme_found.endswith(".rst"): | |
| 162 readme_text = open(readme_found, "r").read() | |
| 163 invalid_rst = rst_invalid(readme_text) | |
| 164 if invalid_rst: | |
| 165 template = "Invalid restructured text found in README [%s]." | |
| 166 msg = template % invalid_rst | |
| 167 lint_ctx.warn(msg) | |
| 168 return | |
| 169 lint_ctx.info("README found containing valid reStructuredText.") | |
| 170 else: | |
| 171 lint_ctx.info("README found containing plain text.") | |
| 172 | |
| 173 | |
| 174 def lint_tool_dependencies_xsd(path, lint_ctx): | |
| 175 tool_dependencies = os.path.join(path, "tool_dependencies.xml") | |
| 176 if not os.path.exists(tool_dependencies): | |
| 177 lint_ctx.info("No tool_dependencies.xml, skipping.") | |
| 178 return | |
| 179 lint_xsd(lint_ctx, TOOL_DEPENDENCIES_XSD, tool_dependencies) | |
| 180 | |
| 181 | |
| 182 def lint_tool_dependencies_actions(path, lint_ctx): | |
| 183 tool_dependencies = os.path.join(path, "tool_dependencies.xml") | |
| 184 if not os.path.exists(tool_dependencies): | |
| 185 lint_ctx.info("No tool_dependencies.xml, skipping.") | |
| 186 return | |
| 187 try: | |
| 188 base.Dependencies(tool_dependencies) | |
| 189 lint_ctx.info("Parsed tool dependencies.") | |
| 190 except Exception as e: | |
| 191 import sys | |
| 192 import traceback | |
| 193 exc_type, exc_value, exc_traceback = sys.exc_info() | |
| 194 traceback.print_tb(exc_traceback, limit=1, file=sys.stdout) | |
| 195 traceback.print_exc() | |
| 196 template = "Problem parsing tool_dependenies.xml [%s]" | |
| 197 msg = template % str(e) | |
| 198 lint_ctx.warn(msg) | |
| 199 return | |
| 200 | |
| 201 | |
| 202 def lint_expected_files(realized_repository, lint_ctx): | |
| 203 if realized_repository.is_package: | |
| 204 if not os.path.exists(realized_repository.tool_dependencies_path): | |
| 205 lint_ctx.warn("Package repository does not contain a " | |
| 206 "tool_dependencies.xml file.") | |
| 207 | |
| 208 if realized_repository.is_suite: | |
| 209 if not os.path.exists(realized_repository.repo_dependencies_path): | |
| 210 lint_ctx.warn("Suite repository does not contain a " | |
| 211 "repository_dependencies.xml file.") | |
| 212 | |
| 213 | |
| 214 def lint_repository_dependencies(path, lint_ctx): | |
| 215 repo_dependencies = os.path.join(path, "repository_dependencies.xml") | |
| 216 if not os.path.exists(repo_dependencies): | |
| 217 lint_ctx.info("No repository_dependencies.xml, skipping.") | |
| 218 return | |
| 219 lint_xsd(lint_ctx, REPO_DEPENDENCIES_XSD, repo_dependencies) | |
| 220 | |
| 221 | |
| 222 def lint_shed_yaml(realized_repository, lint_ctx): | |
| 223 path = realized_repository.real_path | |
| 224 shed_yaml = os.path.join(path, ".shed.yml") | |
| 225 if not os.path.exists(shed_yaml): | |
| 226 lint_ctx.info("No .shed.yml file found, skipping.") | |
| 227 return | |
| 228 try: | |
| 229 yaml.load(open(shed_yaml, "r")) | |
| 230 except Exception as e: | |
| 231 lint_ctx.warn("Failed to parse .shed.yml file [%s]" % str(e)) | |
| 232 return | |
| 233 lint_ctx.info(".shed.yml found and appears to be valid YAML.") | |
| 234 _lint_shed_contents(lint_ctx, realized_repository) | |
| 235 | |
| 236 | |
| 237 def _lint_shed_contents(lint_ctx, realized_repository): | |
| 238 config = realized_repository.config | |
| 239 | |
| 240 def _lint_if_present(key, func, *args): | |
| 241 value = config.get(key, None) | |
| 242 if value is not None: | |
| 243 msg = func(value, *args) | |
| 244 if msg: | |
| 245 lint_ctx.warn(msg) | |
| 246 | |
| 247 _lint_if_present("owner", validate_repo_owner) | |
| 248 _lint_if_present("name", validate_repo_name) | |
| 249 _lint_if_present("type", _validate_repo_type, config["name"]) | |
| 250 _lint_if_present("categories", _validate_categories, realized_repository) | |
| 251 | |
| 252 | |
| 253 def _validate_repo_type(repo_type, name): | |
| 254 if repo_type not in VALID_REPOSITORY_TYPES: | |
| 255 return "Invalid repository type specified [%s]" % repo_type | |
| 256 | |
| 257 is_dep = repo_type == "tool_dependency_definition" | |
| 258 is_suite = repo_type == "repository_suite_definition" | |
| 259 if is_dep and not name.startswith("package_"): | |
| 260 return ("Tool dependency definition repositories should have names " | |
| 261 "starting with package_") | |
| 262 if is_suite and not name.startswith("suite_"): | |
| 263 return ("Repository suite definition repositories should have names " | |
| 264 "starting with suite_") | |
| 265 if name.startswith("package_") or name.startswith("suite_"): | |
| 266 if repo_type == "unrestricted": | |
| 267 return ("Repository name indicated specialized repository type " | |
| 268 "but repository is listed as unrestricted.") | |
| 269 | |
| 270 | |
| 271 def _validate_categories(categories, realized_repository): | |
| 272 msg = None | |
| 273 if len(categories) == 0: | |
| 274 msg = "Repository should specify one or more categories." | |
| 275 else: | |
| 276 for category in categories: | |
| 277 unknown_categories = [] | |
| 278 if category not in CURRENT_CATEGORIES: | |
| 279 unknown_categories.append(category) | |
| 280 if unknown_categories: | |
| 281 msg = "Categories [%s] unknown." % unknown_categories | |
| 282 if realized_repository.is_package: | |
| 283 if "Tool Dependency Packages" not in categories: | |
| 284 msg = ("Packages should be placed and should only be placed " | |
| 285 "in the category 'Tool Dependency Packages'.") | |
| 286 | |
| 287 return msg |
