Skip to content

Commit 7aca51a

Browse files
add typing
1 parent a6ff9cb commit 7aca51a

File tree

6 files changed

+55
-16
lines changed

6 files changed

+55
-16
lines changed

planemo/linters/biocontainer_registered.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
"""Ensure best-practice biocontainer registered for this tool."""
22

3-
from typing import TYPE_CHECKING
3+
from typing import (
4+
Optional,
5+
TYPE_CHECKING,
6+
)
47

58
from galaxy.tool_util.deps.container_resolvers.mulled import targets_to_mulled_name
69
from galaxy.tool_util.deps.mulled.mulled_build_tool import requirements_to_mulled_targets
710
from galaxy.tool_util.lint import Linter
811

12+
from .util import xml_node_from_toolsource
13+
914
if TYPE_CHECKING:
15+
from galaxy.tool_util.deps.conda_util import CondaTarget
1016
from galaxy.tool_util.lint import LintContext
1117
from galaxy.tool_util.parser.interface import ToolSource
1218

@@ -24,7 +30,8 @@ def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
2430
targets = requirements_to_mulled_targets(requirements)
2531
name = mulled_container_name("biocontainers", targets)
2632
if name:
27-
lint_ctx.info(MESSAGE_INFO_FOUND_BIOCONTAINER % name, linter=cls.name(), node=requirements)
33+
requirements_node = xml_node_from_toolsource(tool_source, "requirements")
34+
lint_ctx.info(MESSAGE_INFO_FOUND_BIOCONTAINER % name, linter=cls.name(), node=requirements_node)
2835

2936

3037
class BiocontainerMissing(Linter):
@@ -34,10 +41,11 @@ def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
3441
targets = requirements_to_mulled_targets(requirements)
3542
name = mulled_container_name("biocontainers", targets)
3643
if not name:
44+
requirements_node = xml_node_from_toolsource(tool_source, "requirements")
3745
lint_ctx.warn(MESSAGE_WARN_NO_CONTAINER, linter=cls.name(), node=requirements)
3846

3947

40-
def mulled_container_name(namespace, targets):
48+
def mulled_container_name(namespace: str, targets: List[CondaTarget]) -> Optional[str]:
4149
name = targets_to_mulled_name(targets=targets, hash_func="v2", namespace=namespace)
4250
if name:
4351
return f"quay.io/{namespace}/{name}"

planemo/linters/conda_requirements.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
"""Ensure requirements are matched in best practice conda channels."""
22

3-
from typing import TYPE_CHECKING
3+
from typing import (
4+
Generator,
5+
TYPE_CHECKING,
6+
)
47

58
from galaxy.tool_util.deps.conda_util import requirement_to_conda_targets
69
from galaxy.tool_util.lint import Linter
710

11+
from .util import xml_node_from_toolsource
812
from planemo.conda import (
913
BEST_PRACTICE_CHANNELS,
1014
best_practice_search,
@@ -20,43 +24,48 @@
2024
class CondaRequirementValid(Linter):
2125
@classmethod
2226
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
23-
for conda_target, requirement in _requirements_conda_targets(tool_source):
27+
for conda_target in _requirements_conda_targets(tool_source):
2428
(best_hit, exact) = best_practice_search(conda_target)
2529
conda_target_str = conda_target.package
2630
if conda_target.version:
2731
conda_target_str += "@%s" % (conda_target.version)
2832
if best_hit and exact:
2933
message = f"Requirement [{conda_target_str}] matches target in best practice Conda channel [{best_hit.get('channel')}]."
30-
lint_ctx.info(message, linter=cls.name(), node=requirement)
34+
requirements_node = xml_node_from_toolsource(tool_source, "requirements")
35+
lint_ctx.info(message, linter=cls.name(), node=requirements_nodes)
3136

3237

3338
class CondaRequirementInexact(Linter):
3439
@classmethod
3540
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
36-
for conda_target, requirement in _requirements_conda_targets(tool_source):
41+
for conda_target in _requirements_conda_targets(tool_source):
3742
(best_hit, exact) = best_practice_search(conda_target)
3843
conda_target_str = conda_target.package
3944
if conda_target.version:
4045
conda_target_str += "@%s" % (conda_target.version)
4146
if best_hit and not exact:
4247
message = f"Requirement [{conda_target_str}] doesn't exactly match available version [{best_hit['version']}] in best practice Conda channel [{best_hit.get('channel')}]."
43-
lint_ctx.warn(message, linter=cls.name(), node=requirement)
48+
requirements_node = xml_node_from_toolsource(tool_source, "requirements")
49+
lint_ctx.warn(message, linter=cls.name(), node=requirements_node)
4450

4551

4652
class CondaRequirementMissing(Linter):
4753
@classmethod
4854
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
49-
for conda_target, requirement in _requirements_conda_targets(tool_source):
55+
for conda_target in _requirements_conda_targets(tool_source):
5056
(best_hit, exact) = best_practice_search(conda_target)
5157
conda_target_str = conda_target.package
5258
if conda_target.version:
5359
conda_target_str += "@%s" % (conda_target.version)
5460
if best_hit and not exact:
5561
message = f"Requirement [{conda_target_str}] doesn't match any recipe in a best practice conda channel ['{BEST_PRACTICE_CHANNELS}']."
56-
lint_ctx.warn(message, linter=cls.name(), node=requirement)
62+
requirements_node = xml_node_from_toolsource(tool_source, "requirements")
63+
lint_ctx.warn(message, linter=cls.name(), node=requirements_node)
5764

5865

59-
def _requirements_conda_targets(tool_source):
66+
def _requirements_conda_targets(tool_source: "ToolSource") -> Generator[CondaTarget]:
6067
requirements, *_ = tool_source.parse_requirements_and_containers()
6168
for requirement in requirements:
62-
yield requirement_to_conda_targets(requirement), requirement
69+
conda_target = requirement_to_conda_targets(requirement)
70+
if conda_target:
71+
yield conda_target

planemo/linters/doi.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,15 @@
99
if TYPE_CHECKING:
1010
from galaxy.tool_util.lint import LintContext
1111
from galaxy.tool_util.parser.interface import ToolSource
12+
from galaxy.util import ElementTree
1213

1314

1415
class DoiEmptyNone(Linter):
1516
@classmethod
1617
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
1718
tool_xml = getattr(tool_source, "xml_tree", None)
19+
if not tool_xml:
20+
return
1821
for citation, *_ in _doi_citations(tool_xml):
1922
if citation.text is None:
2023
lint_ctx.error("Empty DOI citation", linter=cls.name(), node=citation)
@@ -24,6 +27,8 @@ class DoiEmpty(Linter):
2427
@classmethod
2528
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
2629
tool_xml = getattr(tool_source, "xml_tree", None)
30+
if not tool_xml:
31+
return
2732
for citation, publication_id, doiless_publication_id in _doi_citations(tool_xml):
2833
if citation.text is None:
2934
continue
@@ -35,6 +40,8 @@ class DoiValid(Linter):
3540
@classmethod
3641
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
3742
tool_xml = getattr(tool_source, "xml_tree", None)
43+
if not tool_xml:
44+
return
3845
for citation, publication_id, doiless_publication_id in _doi_citations(tool_xml):
3946
if citation.text is None or not doiless_publication_id:
4047
continue
@@ -48,6 +55,8 @@ class DoiValidWithDoi(Linter):
4855
@classmethod
4956
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
5057
tool_xml = getattr(tool_source, "xml_tree", None)
58+
if not tool_xml:
59+
return
5160
for citation, publication_id, doiless_publication_id in _doi_citations(tool_xml):
5261
if citation.text is None or not doiless_publication_id:
5362
continue
@@ -65,6 +74,8 @@ class DoiInvalid(Linter):
6574
@classmethod
6675
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
6776
tool_xml = getattr(tool_source, "xml_tree", None)
77+
if not tool_xml:
78+
return
6879
for citation, publication_id, doiless_publication_id in _doi_citations(tool_xml):
6980
if citation.text is None or not doiless_publication_id:
7081
continue
@@ -78,6 +89,8 @@ class DoiUnexpectedResponse(Linter):
7889
@classmethod
7990
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
8091
tool_xml = getattr(tool_source, "xml_tree", None)
92+
if not tool_xml:
93+
return
8194
for citation, publication_id, doiless_publication_id in _doi_citations(tool_xml):
8295
if citation.text is None or not doiless_publication_id:
8396
continue
@@ -89,7 +102,7 @@ def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
89102
)
90103

91104

92-
def _doi_citations(tool_xml):
105+
def _doi_citations(tool_xml: "ElementTree"):
93106
for element in tool_xml.getroot().findall("citations"):
94107
for citation in list(element):
95108
if citation.tag == "citation" and citation.attrib.get("type", "") == "doi":

planemo/linters/urls.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
""" Tool linting module that lints Galaxy tools for their URLs
22
"""
3+
34
from typing import TYPE_CHECKING
45

56
import requests
@@ -11,11 +12,12 @@
1112
if TYPE_CHECKING:
1213
from galaxy.tool_util.lint import LintContext
1314
from galaxy.tool_util.parser.interface import ToolSource
15+
from galaxy.util import ElementTree
1416

1517
BROWSER_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"
1618

1719

18-
def find_urls_in_help(root):
20+
def find_urls_in_help(root: "ElementTree"):
1921
for help in root.findall("help"):
2022
for url in _find_urls_in_text(help.text):
2123
yield url[0], help
@@ -25,6 +27,8 @@ class URLInaccessibleHttp(Linter):
2527
@classmethod
2628
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
2729
tool_xml = getattr(tool_source, "xml_tree", None)
30+
if not tool_xml:
31+
return
2832
for url, help in find_urls_in_help(tool_xml):
2933
if url.startswith("http://") or url.startswith("https://"):
3034
headers = {"User-Agent": BROWSER_USER_AGENT, "Accept": "*/*"}
@@ -48,6 +52,8 @@ class URLInaccessible(Linter):
4852
@classmethod
4953
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
5054
tool_xml = getattr(tool_source, "xml_tree", None)
55+
if not tool_xml:
56+
return
5157
for url, help in find_urls_in_help(tool_xml):
5258
if not url.startswith("http://") and not url.startswith("https://"):
5359
try:
@@ -61,6 +67,8 @@ class URLValid(Linter):
6167
@classmethod
6268
def lint(cls, tool_source: "ToolSource", lint_ctx: "LintContext"):
6369
tool_xml = getattr(tool_source, "xml_tree", None)
70+
if not tool_xml:
71+
return
6472
for url, help in find_urls_in_help(tool_xml):
6573
is_valid = True
6674
if url.startswith("http://") or url.startswith("https://"):

planemo/options.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1425,7 +1425,7 @@ def lint_planemo_defined_tool_linters_options():
14251425
return _compose(
14261426
lint_urls(),
14271427
lint_doi(),
1428-
lint_conda_requirements,
1428+
lint_conda_requirements(),
14291429
lint_biocontainers_option(),
14301430
)
14311431

planemo/shed_lint.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
from planemo.io import info
1313
from planemo.lint import (
1414
handle_lint_complete,
15-
lint_urls,
1615
lint_xsd,
1716
setup_lint,
1817
)
@@ -189,6 +188,8 @@ def lint_readme(realized_repository, lint_ctx):
189188

190189

191190
def lint_tool_dependencies_urls(realized_repository, lint_ctx):
191+
192+
192193
path = realized_repository.real_path
193194
tool_dependencies = os.path.join(path, "tool_dependencies.xml")
194195
if not os.path.exists(tool_dependencies):

0 commit comments

Comments
 (0)