Implement Callbacks in Different Module than __init__.py

Function named 'morePhotos' couldn't be found in the curre
Hello,


How does Plex "resolve" its Callback functions?


I want to implement parts of my Instagram plugin logic in a different module "InstaStream.py". That source file is located in the same location as my __init__.py source file.

In **InstaStream.py** I have:


<br />
def readStream(title, url):<br />
    oc = ObjectContainer(title2 = title, view_group = 'Pictures')<br />
    ...<br />
    oc.add(DirectoryObject(key = Callback(morePhotos, url=nextUrl, title=title), title = 'Next...'))<br />
    return oc<br />




In that same file I have the Callback:


<br />
def morePhotos(title,  url):<br />
    return readStream(title = title, url = url)<br />




However when I run that code my callback is not called and I get in the plugin Log:

**"Function named 'morePhotos' couldn't be found in the current environment"**

When I place the callback morePhotos **into my __init__.py** file, **then it works** (and by changing the function call to "return InstaStream.readStream(...)").

Now this introduces a mutual dependency on these modules. I can live with that, but want to understand what's going on and whether I'm doing something wrong here (mind you, I'm still new to Plex Plugin development as well as Python).

Off course I could also place everything into __init__.py - but you know, old programmer's habbit of structuring my code ;)


So how does this "Callback" (aka "Function" in pre-V2 Plugin API) work? I read somewhere in this forum that Plex imposes some restrictions onto "external Python modules". Is this one of them? Or does Plex simply assume that the "Callback" has to be implemented in __init__.py? Or am I simply not understanding the concept of "function callbacks" in Python? (Currently I have "function pointers" in mind, which probably won't help much here ;))

Thanks, Oliver

I think you should be able to call those functions if you import the necessary file.


 import InstaStream 


I can't really comment on whether your approach is "right" or "wrong" from the Plex framework perspective but, I believe it *should* work.


Yes, I do have such an import statement in my __init__.py module (otherwise I wouldn't have been able to call the functions therein in the first place).

However the situation is even worse: I have to have some "dummy" (empty) functions with the expected function signature in the InstaStream.py source file, otherwise I get an error:

NameError: global name 'morePhotos' is not defined

So apparently the "Callback" function expects a "global name" in the same source file (InstaStream.py in this case), but when the "lookup" is actually done the implementation in __init.py__ is called.


So I have:


<br />
# InstaStream.py:<br />
def someFunction(...)<br />
    oc = ObjectContainer(...)<br />
    ...<br />
    oc.add(DirectoryObject(key = Callback(morePhotos, url=nextUrl, title=title), ...) <br />
<br />
<br />
def morePhotos(url, title):<br />
    # dummy implementation, never called<br />
    return None<br />




And:


<br />
# __init__.py<br />
import InstaStream<br />
<br />
...<br />
def morePhotos(url, title):<br />
    # This implementation is actually called<br />
    return InstaStream.readStream(url = url, title = title)<br />





Does that make sense?

Hmmm… That is strange. The simplest thing to do would probably be to just contain all the code in the init.py file. However, there is a flag you can add to the info.plist file which might help.


<br />
<key>PlexPluginCodePolicy</key><br />
<string>Elevated</string><br />



I know it's required to be able to use 3rd party libraries and it might help here as well.


Yes, that would work. However I would really like to "group" my code into different modules, if possible. And as I am still new to Plex API and Python as well, I am just trying to understand currently how this "Callback" mechanism works.

So I assume the Plex API "Callback" function takes a "function variable", creates some "string" out of it (a "function signature") and when the callback is actually to take place then the framework tries to "lookup that function name in the __init.py__ module/namespace" - probably by simply "assembling" a function call at runtime like "__init__" + callback, resulting in something like "__init__.morePhotos", and when that fails (Python exception of some sort) the said error "Function not found in context" is produced.

Maybe if I would also add an explicit:

import morePhotos from InstaStream

in my __init__.py, maybe that would make a difference?



Yes, thank you, that was the flag I stumbled across already somewhere in this forum :). I'll give that one a try as well and let you know.


Thanks, Oliver


For the record: http://forums.plexapp.com/index.php/topic/18324-updating-plugins-to-v2-framework/

Cheers, Oliver

I wish I could be more help. I think someone else might be better able to answer your questions. I think I’m out of my depth at this point.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.