![]() Registered Member ![]()
|
I was thinking about making it easier to install Python Plugins and so this Python Plugin to import Python Plugins from zip files happened. It's very much a WIP or proof of concept so far, because right now the Krita resources directory is hardcoded to ~/.local/share/krita and most of the error handling is still missing.
See the github repository for screenshots and code. Since I didn't want to assume a specific directory structure inside the zip, the plugin uses the following strategy to find the correct files: 1. Find files with the ending .desktop and read the Python module name from them 2. Find directories that correspond to the Python module names and that contain an __init__.py file 3. Find files with ending .action that have matching <Action name=...> tags (these files are optional) Then the found desktop- and action-files and the Python module directories are extracted into the corresponding pykrita and actions folders. This approach is very flexible and doesn't seem too error-prone to me, as long as the zip files aren't too wild. (One could easily make the algorithm more restrictive, though, if needed.) I've tested it with a couple of Python plugins out there. The user still needs to restart Krita and activate the imported plugins in the Settings, but it's the sorting the plugin files into the resources directory that's the most complicated part for non-technical users, so I think it's an improvement. Now before I go any further with this, what I'd need is to be able to access the location of the resources directory via the Python API. Also, it would be nice if this already came with Krita, because not having to know how to install plugins is the main point of this. So my question is: Is there interest that I keep working on this and make a pull request to the Krita repository eventually? Would someone be willing to put the location of the resources directory in the Python API? |
![]() KDE Developer ![]()
|
Yes, this is very interesting. You should be able to get the toplevel location for Krita's resources with QStandardPaths.standardLocations(QStandardPaths.AppDataLocation)
|
![]() Registered Member ![]()
|
Ah, ok, that's a Qt thing! That makes sense, thank you!
|
![]() Registered Member ![]()
|
I've added the correct resources directory, error handling, and i18n. I'll do some more testing but otherwise, I think I'm done. Since the importing logic is separate from the Qt and Krita stuff, I also could write unit tests for the importer. (Or more like integration tests, since the only thing that would make sense would be to provide a couple of sample directory structures for the importer import.)
But: I haven't found any unit tests for the Python plugins in the Krita source and I don't know what the smartest way to structure tests is with this kind of project where the Python code is embedded code. The only way I can think of that actually works is this (using PyTest): 1. Put a subdirectory tests inside the plugins/python/myplugin directory, since the plugins themselves aren't distributed as installable standalone Python modules, so we can only import them in the tests via relative imports. (I think?) (Does that mess up distributing Krita? Test files shouldn't be shipped. Probably not a problem since we are compiling an executable?) 2. Make the __init__.py of the plugin very minimal and catch the import error of the krita module:
I really don't like this. ![]() I don't know if anyone has thought about unit tests for the Python plugins? Otherwise, I'd probably just submit the code without tests. |
![]() KDE Developer ![]()
|
We tried to add python unittests, but they didn't work, and I'm not actually knowledgeable enough to figure out how to do this.
|
![]() Registered Member ![]()
|
|
![]() Registered Member ![]()
|
I couldn't stop thinking about the unit test situation.
It's actually super easy to make a mock Krita module that can be imported outside of Krita and will accept any attribute names plus provide a mock i18n function, see here. This way, importing krita and registering Plugins etc. become no-ops that don't throw off unit tests for the actual code logic that's independent of Krita stuff, see example unit tests using pytest here. The only caveat is that it only works if your plugin imports the krita module like this:
and not like this:
But since * imports are a bad idea anyway, I wouldn't call that much of a drawback. This generic krita mock doesn't help if you want do do actual mocking/patching/testing of Krita objects in your unittests, since the smart mock/patch functions rely on having proper code for speccing the mock objects, and missing those, you'd have to do a lot of the work yourself. The mock krita module has a basic setup.py file so that it can be easily installed into the current Python environment with pip install -e tools/mock_krita or with setup.py install. In addition to having it somewhere inside the Krite sources, one could even put in into its own github repository so that people could use it for unit testing their own Python plugins, since pip can install Python modules directly from github as well. Idk, right now, this sounds like a good idea to me, not sure if I'm missing something. Maybe depends on what sort of stuff one would want to test in other plugins and how independent of Krita stuff one could make that? Btw, running a Python code checker/linter via CI is also usually a good idea for various reasons. The current Python code base in Krita has a bunch of code violations if I run a checker on it. I'd be willing to help with this (fix the existing code issues etc) if there's interest. (Is this even the right place to discuss this kind of stuff?) |
![]() KDE Developer ![]()
|
This sounds interesting. It's one of the right places: if you've also got more code, phabricator might be easier. We used to use the mailing list for things like this, but that's sort of fallen by the wayside.
|
![]() KDE Developer ![]()
|
Oh, and yes, if you've got a patch fixing the existing python code, that's fine as well.
|
Registered users: Bing [Bot], claydoh, Evergrowing, Google [Bot], rblackwell