Kodi Community Forum

Full Version: Discussion - Concerns about plugin development and the wiki entry
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Okay, so I've started my first plugin (made a view other addons already) a few weeks ago and was
working my way through the wiki on how to implement the navigation between pages

I quickly ended up with bulky if ... elif ... blocks to determine what page to show and what function to call and decided
that that's not the way to go.
Hence I started a small side-project... ... to make all this easier.

So my concerns now...
The way the wiki (which is the entry point for new add-on developers like me) suggests how to implement page navigation seems not quite right to me.
Especially how e.g. the plugin urls are built plugin://plugin.video.myaddon/?mode=folder&foldername=Folder+One.
That's not how a URL should look like, that's how one should look like plugin://plugin.video.myaddon/folder-one?param=value

If a developer follows the wiki he will end up with bulky if ... elif ... blocks making the source hard to maintain and read.
I'm not quite sure if modules (like the one I made) already exist.
IF they do, they really should be mention in the wiki.

I know the wiki is only supposed to get you started and the rest is up to you, but still, there should be at least some mentioning on how to properly proceed
once you understood how the basics work and e.g. mention modules that really can help you with your implementation.
I can not (and will not) believe that I'm the first one to create such a module for Kodi. I couldn't fine one though so I had to reinvent the wheel and make a new one ^^
(I found some stuff that pretty much sounded like it would do something similar but there was no readme, no documentation so I just wrote one myself)

Please keep in mind that all this are just my thoughts and that I might be well and truly wrong.
I'm really looking forward to all of your thoughts on this Smile
Just some thoughts:

1. Wiki indeed should get you started, and your opinion on "properly", well, is just your opinion. However, the Wiki is open for updating by any registered user, so you can freely express your opinion there. Smile

2. There is kodi-plugin-routing module (if we are takling about plugin callback routing only) that implements a decorator-based routing mechanism similar to Flask/Bottle web-frameworks. xbmcswift2 Kodi plugin framework uses similar mechanism for its callback routing. I also wrote my own simpleplugin framework for my home projects, but it uses a simpler dictionary-mapping mechanism.

3. I've looked in your code and immediately bumped into this:
Code:
def url(pattern, type_cast={}):
A default argument of a mutable type is serious programming error in Python and a potential source of bugs (short story: a mutable default argument is instantiated only once on module import and lives in module's global scope. I'd recommend to read some theory on mutable an immutable types and use an editor/IDE with code inspection for Python, e.g. free PyCharm Community Edition, that can help you avoid such things.
Roman_V_M makes a good point with item #3 in the post above, I learned that the very hard way (probably should read the documentation occasionally).

There are a number of addons which implement plugin://plugin.video.myaddon/folder-one?param=value , I believe the YT addon does for one.

I'm curious as to whether or not there is a significant performance hit adopting the callback routing method? I've stuck with ELIFs because I felt there would be quite a hit on the callbacks, particularly for a plugin where they would be re-built on each entry.
(2015-10-30, 17:45)Roman_V_M Wrote: [ -> ]1. Wiki indeed should get you started, and your opinion on "properly", well, is just your opinion. However, the Wiki is open for updating by any registered user, so you can freely express your opinion there. Smile
Well, I don't quite feel like someone who should mess with the wiki, that's why I've decided to start a discussion here and see what other people say about those thoughts first Smile

(2015-10-30, 17:45)Roman_V_M Wrote: [ -> ]2. There is kodi-plugin-routing module (if we are takling about plugin callback routing only) that implements a decorator-based routing mechanism similar to Flask/Bottle web-frameworks. xbmcswift2 Kodi plugin framework uses similar mechanism for its callback routing. I also wrote my own simpleplugin framework for my home projects, but it uses a simpler dictionary-mapping mechanism.
As expected, there are existing modules Big Grin
To bad they are not mentioned in the wiki IMHO

(2015-10-30, 17:45)Roman_V_M Wrote: [ -> ]3. I've looked in your code and immediately bumped into this:
Code:
def url(pattern, type_cast={}):
A default argument of a mutable type is serious programming error in Python and a potential source of bugs (short story: a mutable default argument is instantiated only once on module import and lives in module's global namespace. I'd recommend to read some theory on mutable an immutable types and use an editor/IDE with code inspection for Python, e.g. free PyCharm Community Edition, that can help you avoid such things.
Yeah, I'm still sort of new to python so thanks for pointing that out Smile

(2015-10-30, 19:21)learningit Wrote: [ -> ]I'm curious as to whether or not there is a significant performance hit adopting the callback routing method? I've stuck with ELIFs because I felt there would be quite a hit on the callbacks, particularly for a plugin where they would be re-built on each entry.
Well, it will hit the performance most certainly for reasons you described BUT I'm pretty sure you won't feel that on any plattform other than raspberry pis maybe.
I mean look at the tech we got these days and it's not like one add-on registers 1000 urls.
(2015-10-30, 19:53)Tadly Wrote: [ -> ]As expected, there are existing modules Big Grin
To bad they are not mentioned in the wiki IMHO

ahum ;-)

Category:Add-on_libraries/modules (wiki)
(2015-10-30, 21:40)ronie Wrote: [ -> ]
(2015-10-30, 19:53)Tadly Wrote: [ -> ]As expected, there are existing modules Big Grin
To bad they are not mentioned in the wiki IMHO

ahum ;-)

Category:Add-on_libraries/modules (wiki)

Well... alright
1. let's just say I'm way to stupid to use the kodi wiki properly Big Grin
2. If you know exactly what you'r looking for, you'll find it (like the routing module) but Xbmcswift and Xbmcswift2... like seriously? No description, no summary, the name doesnt tell me what it does and xbmcswift2 doesn't even have a link to a repo or something where it tells me what it does ^^
You aren't wrong, a lot of the tutorials on the wiki aren't exactly encouraging good programming practices, abusing query strings being one of them. But you know, writing documentation is boring... Trust me though, there has been far worse on the wiki in the past than the one linked. It's actually one of the better ones You are welcome to improve it ofc, or create new pages for specific topics like url handling.
in any case they're not meant to teach you how to code, they are meant to be easily readable. much crap can be said about if-spaghetti, however the good thing is everyone can read it. fancy callbacks and decorators and such hides the real thing you try to exemplify. tutorials should never be used verbatim, they are meant for devs to read, understand then go implement as they want. they are not intended for copy-paste monkeys and script-kiddies.
(2015-10-31, 12:42)takoi Wrote: [ -> ]You aren't wrong, a lot of the tutorials on the wiki aren't exactly encouraging good programming practices, abusing query strings being one of them. But you know, writing documentation is boring... Trust me though, there has been far worse on the wiki in the past than the one linked. It's actually one of the better ones You are welcome to improve it ofc, or create new pages for specific topics like url handling.
Thanks for having my back there Big Grin
Yeah I know, writing documentation is boring. In terms of improving them / writing new pages.. I wasn't sure on that and as I said in the initial post, I wasn't sure about whether there are reasons for doing things that way or not.
That's why I opened that thread Smile
Also, since I consider myself still sort of new to python / kodi add-on development I'm not sure if it's a good idea for me to write documentation for it.
But I could just write one and throw it in here so people could approve to it first...

(2015-11-01, 10:32)ironic_monkey Wrote: [ -> ]in any case they're not meant to teach you how to code, they are meant to be easily readable. much crap can be said about if-spaghetti, however the good thing is everyone can read it. fancy callbacks and decorators and such hides the real thing you try to exemplify. tutorials should never be used verbatim, they are meant for devs to read, understand then go implement as they want. they are not intended for copy-paste monkeys and script-kiddies.
I'm with you on that, really. On the other hand, using bad-practice code in a wiki which shows you how to implement add-ons isn't the way to go either.
Only the ones who don't know YET how to write add-ons will read through the wiki and telling them to abuse e.g. query-strings is bad. Like me the might end up
confused about it because they don't know if there are reasons for this decision or not.
I'm not saying everyone should use "fancy" callbacks and decorators. I just think this makes everything way more readable.
e.g. I had a browse through the youtube add-ons source because I thought I should/could use it as reference (being probably one of the most popular add-ons) and oh dear...
Not going to say any more about it other than I abandoned that idea and just went with my "style" ^^
(2015-11-02, 11:01)Tadly Wrote: [ -> ]e.g. I had a browse through the youtube add-ons source because I thought I should/could use it as reference (being probably one of the most popular add-ons) and oh dear...

I am sure bromix can defend himself, but pull your head in. Sneering at other contributer's code is not going to earn you respect.

Callbacks and decorators are often little more than coding wankery. They certainly are NOT more readable or understandable than plain English IF|ELSEs. Nor should they be anywhere near a wiki unless your object is to scare off would-be developers.
(2015-10-30, 19:21)learningit Wrote: [ -> ]I'm curious as to whether or not there is a significant performance hit adopting the callback routing method? I've stuck with ELIFs because I felt there would be quite a hit on the callbacks, particularly for a plugin where they would be re-built on each entry.


I guess, from the point of view of performance, dictionary mapping will be the fastest way. Dicts are widely used in Python internals and seriously optimized. By dictionary mapping i mean something like this:

Code:
import sys
from urlparse import parse_qsl


def foo(params):
    # Do some stuff


def bar(params):
    # Do some other stuff


def router(paramstring):
    params = dict(parse_qsl(paramstring))
    {'foo': foo, 'bar': bar}[params['action']](params)


if __name__ == '__main__':
    router(sys.argv[2][1:])

Here the call
Code:
plugin://plugin.video.foo?action=foo&param1=value1
will be routed to "foo" function, and the call
Code:
plugin://plugin.video.foo?action=bar&param2=value2
will be routed to "bar" function, and each function will receive the parsed params as a dict to work with.

(2015-10-30, 21:50)Tadly Wrote: [ -> ]
(2015-10-30, 21:40)ronie Wrote: [ -> ]
(2015-10-30, 19:53)Tadly Wrote: [ -> ]As expected, there are existing modules Big Grin
To bad they are not mentioned in the wiki IMHO

ahum ;-)

Category:Add-on_libraries/modules (wiki)

Well... alright
1. let's just say I'm way to stupid to use the kodi wiki properly Big Grin
2. If you know exactly what you'r looking for, you'll find it (like the routing module) but Xbmcswift and Xbmcswift2... like seriously? No description, no summary, the name doesnt tell me what it does and xbmcswift2 doesn't even have a link to a repo or something where it tells me what it does ^^

I totally agree with you on this. As far as understand, this list of addons is auto-generated from Kodi repo. But addons in the official repo do include at least brief descriptions and some metadata (it's the requirement for including in the official repo) in their addon.xml files. It would be good if those metadata were included in the wiki too.

(2015-10-31, 12:42)takoi Wrote: [ -> ]You aren't wrong, a lot of the tutorials on the wiki aren't exactly encouraging good programming practices, abusing query strings being one of them.

Honestly, I don't understand, how one can "abuse" query strings. Plugin calls are stateless and query strings are the most straightforward way to pass data between plugin calls. And to deal with query strings you don't need anything except Python standard library.
(2015-11-02, 12:39)Karnagious Wrote: [ -> ]I am sure bromix can defend himself, but pull your head in. Sneering at other contributer's code is not going to earn you respect.

Callbacks and decorators are often little more than coding wankery. They certainly are NOT more readable or understandable than plain English IF|ELSEs. Nor should they be anywhere near a wiki unless your object is to scare off would-be developers.
Yeah, that backfired. I really didn't meant to offend anyone. :/
To prevent me from digging a even deeper hole I'll just shut up...

(2015-11-02, 12:39)Karnagious Wrote: [ -> ]
(2015-10-31, 12:42)takoi Wrote: [ -> ]You aren't wrong, a lot of the tutorials on the wiki aren't exactly encouraging good programming practices, abusing query strings being one of them.

Honestly, I don't understand, how one can "abuse" query strings. Plugin calls are stateless and query strings are the most straightforward way to pass data between plugin calls. And to deal with query strings you don't need anything except Python standard library.
By "abuse" we (or well... I at least) where talking about how urls look.
Following url (from the wiki) suggests that when you select a entry you'll than see the contents of "Folder One"
plugin://plugin.video.myaddon/?mode=folder&foldername=Folder+One
Ever seen urls like that on the web?
And that's what I'm talking about all the time. I'm still unsure to whether there are reasons for it or not
These are my words actually.

(2015-11-02, 13:10)Tadly Wrote: [ -> ]
(2015-11-02, 12:39)Karnagious Wrote: [ -> ]
(2015-10-31, 12:42)takoi Wrote: [ -> ]You aren't wrong, a lot of the tutorials on the wiki aren't exactly encouraging good programming practices, abusing query strings being one of them.

Honestly, I don't understand, how one can "abuse" query strings. Plugin calls are stateless and query strings are the most straightforward way to pass data between plugin calls. And to deal with query strings you don't need anything except Python standard library.
By "abuse" we (or well... I at least) where talking about how urls look.

Again, opinion-based conclusion. Does it really matter how a plugin URL looks like? Most of plugin users never see them.

Quote:Following url (from the wiki) suggests that when you select a entry you'll than see the contents of "Folder One"
plugin://plugin.video.myaddon/?mode=folder&foldername=Folder+One
Ever seen urls like that on the web?
And that's what I'm talking about all the time. I'm still unsure to whether there are reasons for it or not

Well, Kodi plugins are not web so there is no reason to follow web-dev patterns. I do understand that plugin URLs based on path routing may look "prettier" or more familiar to those who are used to Python web-frameworks like Flask or Bottle, but in Kodi plugins implementing path routing require either additional components (like plugin-routing library) or additional efforts, while query string creating/parsing is pretty straightforward, especially for beginners. And, as was mentioned above, there may be some performance impact.

I have nothing against path routing. Moreover, in plugins with complex structure path-based URLs may be preferable from the point of view of code structure and readability. But if you have enough knowledge to write a complex plugin, you won't need Wiki to decide which plugin URL routing mechanism to choose. Once again, Wiki is just a starting point.
(2015-11-02, 12:59)Roman_V_M Wrote: [ -> ]
(2015-10-31, 12:42)takoi Wrote: [ -> ]You aren't wrong, a lot of the tutorials on the wiki aren't exactly encouraging good programming practices, abusing query strings being one of them.
Honestly, I don't understand, how one can "abuse" query strings. Plugin calls are stateless and query strings are the most straightforward way to pass data between plugin calls. And to deal with query strings you don't need anything except Python standard library.
It's conventional (and even standardized) to use paths for hierarchical data and query strings for non-hierarchical. You can technically achieve the same and your small foo bar action example is fine. The problem is that they tend to get complex, and increasingly harder to follow and debug the more parameters you get because it's structure is flat, while plugins are not.

Btw. the main point of plugin-routing and libraries like that is not to add pretty paths, but to make parameter passing explicit via pattern matching so you don't accentually forget a parameter or do errors like that.

(2015-11-02, 12:59)Roman_V_M Wrote: [ -> ]
(2015-10-30, 19:21)learningit Wrote: [ -> ]I'm curious as to whether or not there is a significant performance hit adopting the callback routing method? I've stuck with ELIFs because I felt there would be quite a hit on the callbacks, particularly for a plugin where they would be re-built on each entry.
I guess, from the point of view of performance, dictionary mapping will be the fastest way. Dicts are widely used in Python internals and seriously optimized. By dictionary mapping i mean something like this:
Before your fast lookup you add all the n function to a dictionary so what's the difference from elifs checking n functions or a loop checking n function?