Tricks for using pylint with Sikuli?

Asked by Brian Redmond

I'm a vim user and have the syntastic plugin for it to run pylint. Sikuli causes problems for pylint which some I've been able to workaround and others I'm wondering if anyone has any thoughts on.
The first problem is with importing other Sikuli scripts. Since Sikuli uses subfolders to keep scripts and images together, pylint doesn't understand this structure and can't follow the import statements. To work around this, I create hardlinks to the scripts from the parent folder and open the scripts in vim using those. This allows pylint to find the other scripts since they now all reside in the same folder.
The next problem is pylint recognizing Sikuli functions themselves. At the top of my scripts I explicitly 'from sikuli.Sikuli import *', but again, pylint can't follow this. If I create a folder 'sikuli' with an init file and a file called 'Sikuli.py', this becomes a file pylint can find, but Sikuli will ignore since it's not in its import path. In the Sikuli.py, I add stubbed out definitions for the various Sikuli features which allows pylint to know Sikuli's syntax. It would be nice to have an easy way to generate this, but the API isn't huge so it's not bad.
I'm curious if anyone has ideas on better/easier ways to do this?

Question information

Language:
English Edit question
Status:
Solved
For:
SikuliX Edit question
Assignee:
No assignee Edit question
Solved by:
Brian Redmond
Solved:
Last query:
Last reply:
Revision history for this message
RaiMan (raimund-hocke) said :
#1

--- it would be nice to have an easy way to generate this, but the API isn't huge so it's not bad.
The API has about 15 relevant classes and depending on how you count more than a hundred public methods.
The SikuliX API is implemented on the Java level, so generally only Java aware interpreters/frameworks are able access the API.
In case of Python scripting, the interpreter is Jython.
What always leads to some misunderstanding is the fact, that the methods of class Region are made available, so you can use them undotted. Internally these calls like click(), find(), wait(), ... are mapped to a "constant" object SCREEN, which is initialised to be Screen(0). So this is simply a convenience for those who start with scripting and use the whole screen for searching.
With more experience you will very soon start to work with restricted search regions, that forces you to use the API in the intended way: reg.click(), reg.wait(), ... (if you do not use the ugly trick with setROI()).

-- API "not seen" by Pylint
The problem that all source code based analysers have (including full featured IDE's like NetBeans, Eclipse, PyCharm, ...), that this convenience API only exists at runtime.
so a line like
wait(image)
will always be marked as "name wait not known".
For this there is no solution, besides implementing an additional mapping layer.

On the other hand: Pylint will never work with any Jython script structure, that heavily relies on Java libraries, because it cannot access the Java level without additional adaptions/plugins/...

conclusion: the things you are pointing to are a design bug looking from the Pylint perspective. But the original developers decided for some beginners conveniences, that now have to be kept, to be backward compatible.

So you have to setup your own wrapper/mapper using the Python reflection methods with a Jython script.
I am not an expert with Pylint, but does it not have any option to provide information about special cases?

Revision history for this message
Brian Redmond (bredmond) said :
#2

Thanks Raimund. Pylint has various rules you can set to ignore warnings and errors, but setting it to ignore everything in the Sikuli API would cut down its usefulness to me too much. It's helpful that you've been able to confirm, though, that there isn't an existing or automatic way to access the API in a way that's helpful to Pylint. Creating a file by hand to mirror the API in Python hasn't been hard, I just wanted to make sure I wasn't doing work that had already been done :) It also works with the autocompletion plugin I'm using.
As for the access to other modules I've created, I've found that the problem with the solution I described before using hard links is that hard links are a problem for git. Another solution that's actually easier is to run this from my working folder:
for x in $PWD/*.sikuli;do export PYTHONPATH="$PYTHONPATH:$x";done
That adds all the sikuli folders to my python path for pylint to find and works great.