From kwrite-devel Tue Nov 12 17:33:49 2013 From: "Philipp A." Date: Tue, 12 Nov 2013 17:33:49 +0000 To: kwrite-devel Subject: Python plugins refactored, step 2 Message-Id: X-MARC-Message: https://marc.info/?l=kwrite-devel&m=138427764028030 MIME-Version: 1 Content-Type: multipart/mixed; boundary="--===============7145806668542988938==" --===============7145806668542988938== Content-Type: multipart/alternative; boundary=e89a8fb1fa6267566104eafe403b --e89a8fb1fa6267566104eafe403b Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable hi, i already mentioned it in a review request, but i think this is better. how about making python plugins python modules? currently, they are =E2=80=9Ceither a single-file module or a directory ful= l of modules, with one special module that gets imported/executed=E2=80=9D, whic= h is not only more unwieldy to explain, but also a more complex implementation and puts many modules into the namespace. e.g. i=E2=80=99m not sure if it=E2=80=99s possible to create a =E2=80=9Cuti= l.py=E2=80=9D module inside one of your plugins, because another one might have the same. they have to be prefixed, which is rather silly in a namespace-focused language. so i=E2=80=99ll explain how it works now: ``` $ pwd ...plugins $ ls foo.desktop foo.py bar/bar.desktop bar/bar.py bar/baz.py $ head -n 1 bar/bar.py from baz import symbol ``` the desktop files point to foo.py and bar/bar.py P=C3=A2t=C3=A9 loads both and checks if they are activated. for each activa= ted one that is in a subdirectory, it prepends that one to the python path. if both are activated, the python path now contains =E2=80=9C...plugins/bar= /=E2=80=9D and =E2=80=9C...plugins/=E2=80=9D (in that order) now the base name (remove directory part and =E2=80=9C.py=E2=80=9D extensio= n) of both gets imported: 1. `py.import("foo")`: python checks in =E2=80=9C...plugins/bar/=E2=80=9D, = doesn=E2=80=99t find it, checks in =E2=80=9C...plugins/=E2=80=9D, finds & imports it 2. `py.import("bar")`: checks in =E2=80=9C...plugins/bar/=E2=80=9D, finds &= imports it 3. during importing, =E2=80=9Cbar/bar.py=E2=80=9D checks for the =E2=80=9Cb= az=E2=80=9D module in =E2=80=9C...plugins/bar/=E2=80=9D, finds & imports it now if any plugin directory that gets prepended after =E2=80=9Cbar/=E2=80= =9D would contain baz.py, or if any plugin depended on some system module called =E2=80=9Cbaz= =E2=80=9D, we=E2=80=99d be fucked. --- my proposed changes: * don=E2=80=99t change the path after adding the plugin directories (in our example, just add =E2=80=9C...plugins/=E2=80=9D, and be done with it) * just put the module name in the .desktop files (in our example: =E2=80=9C= foo=E2=80=9D and =E2=80=9Cbar=E2=80=9D) * change the name of the to-be-loaded submodule inside a plugin directory (bar/bar.py) to __init__.py * change all relative imports inside plugins to python-3-style `from .relative_module import symbol` now we have ``` $ pwd ...plugins $ ls foo.desktop foo.py bar/bar.desktop bar/__init__.py bar/baz.py $ head -n 1 bar/__init__.py from .baz import symbol # note the dot ``` how does it work now? just the plugin directory =E2=80=9C...plugins/=E2=80=9D gets prepended to t= he python path the names given in the desktop files of each activated plugin =E2=80=93 =E2= =80=9Cfoo=E2=80=9D and =E2=80=9Cbar=E2=80=9D =E2=80=93 get imported: 1. `py.import("foo")`: python checks in =E2=80=9C...plugins/=E2=80=9D, find= s & imports it 2. `py.import("bar")`: python checks in =E2=80=9C...plugins/=E2=80=9D, find= s & imports it (as directory-based module) 3. during importing, =E2=80=9Cbar/__init__.py=E2=80=9D checks for the =E2= =80=9C.baz=E2=80=9D module next to itself (explicit relative import), finds & imports it baz is invisible for other plugins --- what do you say? --e89a8fb1fa6267566104eafe403b Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
hi, i already mentioned it in a review request, = but i think this is better.

how about making python plugins python m= odules?

currently, they are =E2=80=9Ceither a single-file module or = a directory full of modules, with one special module that gets imported/exe= cuted=E2=80=9D, which is not only more unwieldy to explain, but also a more= complex implementation and puts many modules into the namespace.

e.g. i=E2=80=99m not sure if it=E2=80=99s possible to create a =E2=80= =9Cutil.py=E2=80=9D module inside one of your plugins, because another one = might have the same. they have to be prefixed, which is rather silly in a n= amespace-focused language.

so i=E2=80=99ll explain how it works now:

```
$ pwd
...plu= gins
$ ls
foo.desktop
foo.py
bar/bar.desktop
bar/bar.py
b= ar/baz.py
$ head -n 1 bar/bar.py
from baz import symbol
```

the desktop files point to foo.py and bar/bar.py

P= =C3=A2t=C3=A9 loads both and checks if they are activated. for each activat= ed one that is in a subdirectory, it prepends that one to the python path.<= br>
if both are activated, the python path now contains =E2=80=9C...plug= ins/bar/=E2=80=9D and =E2=80=9C...plugins/=E2=80=9D (in that order)

now the base name (remove directory part and =E2=80=9C.py=E2=80=9D exte= nsion) of both gets imported:

1. `py.import("foo")`: pytho= n checks in =E2=80=9C...plugins/bar/=E2=80=9D, doesn=E2=80=99t find it, che= cks in =E2=80=9C...plugins/=E2=80=9D, finds & imports it
2. `py.import("bar")`: checks in =E2=80=9C...plugins/bar/=E2=80= =9D, finds & imports it
3. during importing, =E2=80=9Cbar= /bar.py=E2=80=9D checks for the =E2=80=9Cbaz=E2=80=9D module in =E2=80=9C..= .plugins/bar/=E2=80=9D, finds & imports it

now if any plu= gin directory that gets prepended after =E2=80=9Cbar/=E2=80=9D would contai= n baz.py, or if any plugin depended on some system module called =E2=80=9Cb= az=E2=80=9D, we=E2=80=99d be fucked.

---

my proposed changes:

* don=E2=80=99t change the path = after adding the plugin directories (in our example, just add =E2=80=9C...p= lugins/=E2=80=9D, and be done with it)
* just put the module name in the= .desktop files (in our example: =E2=80=9Cfoo=E2=80=9D and =E2=80=9Cbar=E2= =80=9D)
* change the name of the to-be-loaded submodule inside a plugin directory (= bar/bar.py) to __init__.py
* change all relative imports inside plugins = to python-3-style `from .relative_module import symbol`

now we have

```
$ pwd
...plugins
$ ls
fo= o.desktop
foo.py
bar/bar.desktop
bar/__init__.py
bar/baz.py
= $ head -n 1 bar/__init__.py
from .baz import symbol=C2=A0 # note the dot=
```

how does it work now?

just the plugin director= y =E2=80=9C...plugins/=E2=80=9D gets prepended to the python path

the names given in the desktop files of each activated plugin =E2= =80=93 =E2=80=9Cfoo=E2=80=9D and =E2=80=9Cbar=E2=80=9D =E2=80=93 get import= ed:

1. `py.import("foo")`: python checks in =E2=80=9C...plugins/= =E2=80=9D, finds & imports it
2. `py.import("bar")`: pytho= n checks in =E2=80=9C...plugins/=E2=80=9D, finds & imports it (as direc= tory-based module)
3. during importing, =E2=80=9Cbar/__init__.py=E2=80= =9D checks for the =E2=80=9C.baz=E2=80=9D module next to itself (explicit r= elative import), finds & imports it

baz is invisible for other plugins

---

<= div>what do you say?
--e89a8fb1fa6267566104eafe403b-- --===============7145806668542988938== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ KWrite-Devel mailing list KWrite-Devel@kde.org https://mail.kde.org/mailman/listinfo/kwrite-devel --===============7145806668542988938==--