Split linters in separate classes#17081
Conversation
| try: | ||
| re.compile(match) | ||
| except Exception as e: | ||
| lint_ctx.error(f"Match '{match}' is no valid regular expression: {str(e)}", node=child) |
There was a problem hiding this comment.
Don't we need to have a code per message, unless one linter only emits one possible message ?
There was a problem hiding this comment.
We can try to do this. With the current state I would need to split StdIOAbsence only, or? I hoped to come away with something like at most one message per linter (which would be fine for profile versions as in StdIOAbsence.
There was a problem hiding this comment.
Also, it's important to note that we currently filter for linter function/class names (here) and not linter message codes. I would say that do not need the codes. But we can either name the filter classes using a code.
There was a problem hiding this comment.
One message per linter sounds fine, but also like a lot of work.
There was a problem hiding this comment.
One message per linter sounds fine, but also like a lot of work.
The good thing is that we have good unit test coverage - which now pays off.
There was a problem hiding this comment.
If you augment the lint_ctx.function to instead pass codes we can use those codes to determine what is classified as an error / what can be ignored. This seems like less work (we'd have to run all relatively coarse linters, but I think that's ok ?)
There was a problem hiding this comment.
Excellent idea, but I think we are fixed to the signature of the linter function, i.e 1st parameter ToolSource and 2nd parameter LintContext. The reason is that there are some linters that live in the planemo sources. One option would be to move them here (not sure if this would add extra requirements) - which might be good anyway.
But there might be another way, due to this hack we can filter the messages before adding them to the final message list (and also if without this hack we could filter the list of messages after each linter application).
I'm a bit worried how we can ensure that our codes are not duplicated.
One message per linter sounds fine, but also like a lot of work.
Main question for me is what is the "best" solution ..
we'd have to run all relatively coarse linters, but I think that's ok ?
I also think this would be OK. Runtime should not be a concern.
There was a problem hiding this comment.
The reason is that there are some linters that live in the planemo sources
I think when I first implemented the XSD validation the external dependency on xmllint (https://github.com/galaxyproject/planemo/blob/master/planemo/xml/validation.py#L14C20-L14C27) was the issue. lxml seemed less mature at the time than xmllint. I guess we use lxml a lot more aggressively now and we have been generally pleased with the XSD validation it is doing and we now have a Galaxy dependency on lxml. I think I would be fine dropping the xmllint path through planemo if it would simplify things and let the XSD validation move into Galaxy.
There was a problem hiding this comment.
Thanks for the comment @jmchilton. Will try to move it here, but probably in a separate PR.
I'm still experimenting if separate classes are the way to go. It seems difficult to avoid code duplication, but it will become clearer how we end up in the different linter messages.
1780d95 to
3305cef
Compare
bb17d76 to
aa85c64
Compare
|
Ping @mvdbeek and @jmchilton I'm quite happy with the current state. I have moved the For me, the TODOs would be
Regarding lxml I was also wondering if we should remove https://github.com/galaxyproject/galaxy/blob/e7a168000e627dc8579ad749174bd5eabbe15873/lib/galaxy/util/__init__.py#L68C9-L68C9 |
aa85c64 to
26c2a89
Compare
* fix all XML schema errors discovered here galaxyproject/galaxy#17081 * more linter fixes * fix value * add missing macros file for deprecated tool creates a slightly annoying Traceback in the CI setup job * ampvis: fix URLs * ampvis2: more URL fixes * ampvis2 heatmap fix duplicated output label * Apply suggestions from code review Co-authored-by: Marius van den Beek <m.vandenbeek@gmail.com> --------- Co-authored-by: Marius van den Beek <m.vandenbeek@gmail.com>
0fc0ec4 to
555fe5f
Compare
42dd707 to
ccced2f
Compare
now in galaxy core galaxyproject/galaxy#17081
| return lint_tool_source_with(lint_context, tool_source, extra_modules=extra_modules) | ||
|
|
||
|
|
||
| def list_linters(extra_modules: Optional[List[str]] = None) -> List[str]: |
There was a problem hiding this comment.
I think that's actually a rare case where you can use a Metaclass:
In [1]: linters = {}
...:
...: class LinterMeta(type):
...: def __new__(cls, clsname, bases, attrs):
...: newclass = super(LinterMeta, cls).__new__(cls, clsname, bases, attrs)
...: linters[clsname] = newclass
...: return newclass
...:
...:
...: class MyLinter(metaclass=LinterMeta):
...: pass
...:
...: linters
Out[1]: {'MyLinter': __main__.MyLinter}
There was a problem hiding this comment.
Thanks for pointing me to metaclasses. Never took the time to learn about them.
Still I hope that 3a98a3a is sufficient?
using `__subclasses__`
2021ffb to
3a98a3a
Compare
|
Any chance you could resolve the conflicts ? |
This reverts commit 46ff3f2.
Co-authored-by: Nicola Soranzo <nicola.soranzo@gmail.com>
…hias/galaxy into topic/linter-overhaul
|
Thanks a lot @bernt-matthias, this is really important work! |
|
This PR was merged without a "kind/" label, please correct. |
now in galaxy core galaxyproject/galaxy#17081
now in galaxy core galaxyproject/galaxy#17081
So far mainly a call for discussion. Would be nice to have this discussed first before I continue with the other linters
(discuss we could transform only stdio, a few more, or all linters within this PR).
Currently, a linter is a function prefixed by
lint_(most of them are contained intool_util.linterswhich are used by default). These linters are at the moment quite monolithic, e.g. there is a single linter for theinputtag and we haveonly a limited number of states (check, info, warn, error).
This led to a lot of problems and frustration (see) since
So far this change does the following
Linterclass which makes it easier to decide what a linter is in the loop over the modules.lintfixmethod that may be used to fix some problems (discuss: maybe not in this PR?).codeproperty (inspired by pep8/flake8 codes) which we could add to theLintMessagesthat are generated by thelintmethods. But then I realised that skipping of linters simply works by the linter name (i.e. class name) .. maybe this is sufficient (discuss: advantage of codes is that we definitely have short codes for the planemo CLI, alphanumeric codes might become longer but this is closer to what we have at the moment). Alternatively we could just call the classes with codes, e.g.S001.The following already works:
planemo lint tools/filters/cutWrapper.xml --skip StdIOAbsenceHow to test the changes?
(Select all options that apply)
License