Access eg.result of plugin inside of a script

Do you have questions about writing plugins or scripts in Python? Meet the coders here.
Post Reply
User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Access eg.result of plugin inside of a script

Post by Luca Brasi » Tue Sep 19, 2017 8:35 am

Hey,

this info has to be sitting somewhere here in the forums but I couldn't find it.
If I call a plugin form inside a script I'd like to work with its result later in the script. But if I use eg.result after calling the plugin eg.result will still be the same as before starting the script and the plugin inside of it. I have seen this with "find window" and "read text from file".

Code: Select all

eg.plugins.Window.FindWindow(None, None, None, None, None, None, None, None, None)
eg.plugins.Window.GrabText(False)
print eg.result
will give me

Code: Select all

10:33:12      {u'value': u'DIRECTSOUND:{15ACAB82-6989-44D2-845D-C2520D80055D}'}
which is the result of the last action before running the script.
Is there any way to solve this?
Thanks guys
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
yokel22
Experienced User
Posts: 237
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Access eg.result of plugin inside of a script

Post by yokel22 » Tue Sep 19, 2017 2:05 pm

Not all actions will return a valid eg.result. I believe this is the case on both of those. That's why it's still giving you an old eg. result. The way you have it setup is correct though.

User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Re: Access eg.result of plugin inside of a script

Post by Luca Brasi » Tue Sep 19, 2017 2:29 pm

But it does work in the tree:
screen_mmstation_20170919_16h27m02s.jpg
So the result from
eg.plugins.Window.GrabText(False)
seems to be fine right?
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
yokel22
Experienced User
Posts: 237
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Access eg.result of plugin inside of a script

Post by yokel22 » Tue Sep 19, 2017 2:39 pm

Yes that looks correct, i was wrong there, the grab text action does return a valid eg.result. When doing it from script do it like this instead & it should work.

Code: Select all

eg.plugins.Window.FindWindow(None, None, None, None, None, None, None, None, None)
text = eg.plugins.Window.GrabText(False)
print text[0]
Last edited by yokel22 on Tue Sep 19, 2017 2:56 pm, edited 3 times in total.

User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Re: Access eg.result of plugin inside of a script

Post by Luca Brasi » Tue Sep 19, 2017 2:50 pm

I tried something and it workes...

Code: Select all

eg.plugins.Window.FindWindow(u'lightroom.exe', u'2017 - Adobe Photoshop Lightroom - Bibliothek', u'AgWinMainFrame', None, None, None, False, 0.0, 2)
result = eg.plugins.Window.GrabText(False)
print result
screen_mmstation_20170919_16h49m22s.jpg
I have the feeling that I asked that one before a long time ago so maybe I just remembered :D
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
yokel22
Experienced User
Posts: 237
Joined: Thu Feb 05, 2015 5:56 pm
Location: U.S. - Kansas city

Re: Access eg.result of plugin inside of a script

Post by yokel22 » Tue Sep 19, 2017 2:52 pm

Yep, I was just going to post that. I'd forgotten you need to do it like that from script

User avatar
kgschlosser
Site Admin
Posts: 4034
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Access eg.result of plugin inside of a script

Post by kgschlosser » Tue Sep 19, 2017 7:29 pm

ok this is how eg.result works.


since all plugins are not loaded in the traditional sense. they are loaded as a script file using exec. which runs the script in it's own namespace. so when an action gets run anything that is returned from the action actually gets set into a local variable that is apart of eg.plugins.PLUGIN_NAME.plugin.info which is a PluginInstanceInfo based class. (not exactly how this is but it's a general idea) so when you do a eg.plugins.Window.GetText() it is not actually calling the action directly there is a bit of code between the 2. so it will intercept any returned values from the action and set them to eg.result. the reason why you are seeing changes in eg.result that may not be what you expect is because if you call an action from code it is going to change the original eg.result that may have been set by another action that was called before the script started.


so as an example. if you use the action Find Window and then you have a python script that uses eg.plugins.Window.GetText() even thos you may not have set the returned value of the GetText to a variable if you then print out eg.result you will notice that it is not the window handle from the Find Window anymore. simple test would be set up the example above and do a print eg.result before and after GetText(). so good form is with anything using payloads or even eg.result would be to set those things to a local variable to your python script as soon as the script starts. if you know eg.result or payload is a mutable object like a dict or a list then you need to make special concessions for these.

to copy a list you would do

Code: Select all

result = eg.result[:]
the code below is pseudo code and I have not tested it

for a dict it is a little more complex the code below will handle nested dicts and make a copy of them. there is the copy.deepcopy module you can use as well but it does not like instances so if you set a class into a dict and then try to copy it using deepcopy it pitches a fit about it.

Code: Select all

def copy_dict(old_dict, new_dict):
    for key, value in old_dict.items():
        if isinstance(value, dict):
            new_dict[key] = dict()
            copy_dict(value, new_dict[key])
        elif isinstance(value, list):
            new_dict[key] = value[:]
        else:
            new_dict[key] = value

result = dict()
copy_dict(eg.result, result)
    
If you like the work I have been doing then feel free to Image

User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Re: Access eg.result of plugin inside of a script

Post by Luca Brasi » Wed Sep 20, 2017 8:04 am

kgschlosser wrote: since all plugins are not loaded in the traditional sense. they are loaded as a script file using exec. which runs the script in it's own namespace. so when an action gets run anything that is returned from the action actually gets set into a local variable that is apart of eg.plugins.PLUGIN_NAME.plugin.info which is a PluginInstanceInfo based class. (not exactly how this is but it's a general idea) so when you do a eg.plugins.Window.GetText() it is not actually calling the action directly there is a bit of code between the 2. so it will intercept any returned values from the action and set them to eg.result.
Ok, understood.
kgschlosser wrote: the reason why you are seeing changes in eg.result that may not be what you expect is because if you call an action from code it is going to change the original eg.result that may have been set by another action that was called before the script started.
so as an example. if you use the action Find Window and then you have a python script that uses eg.plugins.Window.GetText() even thos you may not have set the returned value of the GetText to a variable if you then print out eg.result you will notice that it is not the window handle from the Find Window anymore. simple test would be set up the example above and do a print eg.result before and after GetText().
Ok, here I am not entirely sure if I understand you correctly because in my example above the problem was that eg.result was not changed when doing an action inside the script. I tried to test your example:
screen_mmnote_2017-09-20 10 07 23.png
screen_mmnote_2017-09-20 10 07 23.png (53.77 KiB) Viewed 1476 times

So the following is to keep the data which was generated before the script and stored in eg.result and have it accessible for later use?
kgschlosser wrote: so good form is with anything using payloads or even eg.result would be to set those things to a local variable to your python script as soon as the script starts. if you know eg.result or payload is a mutable object like a dict or a list then you need to make special concessions for these.

to copy a list you would do

Code: Select all

result = eg.result[:]
I looked up how [:] works. This will come in handy.


kgschlosser wrote: the code below is pseudo code and I have not tested it

for a dict it is a little more complex the code below will handle nested dicts and make a copy of them. there is the copy.deepcopy module you can use as well but it does not like instances so if you set a class into a dict and then try to copy it using deepcopy it pitches a fit about it.

Code: Select all

def copy_dict(old_dict, new_dict):
    for key, value in old_dict.items():
        if isinstance(value, dict):
            new_dict[key] = dict()
            copy_dict(value, new_dict[key])
        elif isinstance(value, list):
            new_dict[key] = value[:]
        else:
            new_dict[key] = value

result = dict()
copy_dict(eg.result, result)
    
This one too. I remember going crazy one time when I tried to get a dict (audio devices with their usbids) into script and work with it there. I will have to do that again.
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
kgschlosser
Site Admin
Posts: 4034
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Access eg.result of plugin inside of a script

Post by kgschlosser » Wed Sep 20, 2017 3:51 pm

Luca Brasi wrote:Ok, here I am not entirely sure if I understand you correctly because in my example above the problem was that eg.result was not changed when doing an action inside the script.
ok here goes another attempt at explaining this. since i made a mess of the last one! :shock:

from the code I read if you call the action directly eg.plugins.SOME_PLUGIN.SOME_ACTION() it will only return the value. eg.result will only get set if an action gets run from it's GUI form.

**** more information on eg.result and python scripts ****

here is a code block from the python script plugin. self.mod is the storage for any local variables. local variables are variables only accessible by the script.

Code: Select all

            mod = self.mod
            oldResult = eg.result
            mod.result = oldResult
            try:
                exec(self.code, mod.__dict__)  # pylint: disable-msg=W0122
            except SystemExit:
                pass
            except:
                self.PrintTraceback()
            if eg.result is not oldResult:
                return eg.result
            else:
                return mod.result
so what is taking place here is eg.result gets set into the result variable of your script. so while the script is running you can access eg.result as just result inside of your script. if you want to return a value from your script (which will then get set as eg.result) simply set whatever data is to be returned from the script into the result variable.

Code: Select all

result = 'this  is what i want returned from the script'

****some more info that might be useful****

now here is a real brain spinner for ya. i believe you can do this because the variables are stored in a dict which is mutable and will carry the variable names and values between running instances. I have not tested this but from the code it looks like this can be done.

Code: Select all


try:
    print 'This script has been run %d times.' % run_count
    run_count += 1
except:
    print 'This is the first time this script has run.'
    run_count = 1
If you like the work I have been doing then feel free to Image

User avatar
Luca Brasi
Experienced User
Posts: 262
Joined: Sat Oct 11, 2008 12:39 pm

Re: Access eg.result of plugin inside of a script

Post by Luca Brasi » Thu Sep 21, 2017 7:13 am

kgschlosser wrote:ok here goes another attempt at explaining this. since i made a mess of the last one! :shock:

from the code I read if you call the action directly eg.plugins.SOME_PLUGIN.SOME_ACTION() it will only return the value. eg.result will only get set if an action gets run from it's GUI form.

**** more information on eg.result and python scripts ****

here is a code block from the python script plugin. self.mod is the storage for any local variables. local variables are variables only accessible by the script.

Code: Select all
mod = self.mod
oldResult = eg.result
mod.result = oldResult
try:
exec(self.code, mod.__dict__) # pylint: disable-msg=W0122
except SystemExit:
pass
except:
self.PrintTraceback()
if eg.result is not oldResult:
return eg.result
else:
return mod.result



so what is taking place here is eg.result gets set into the result variable of your script. so while the script is running you can access eg.result as just result inside of your script. if you want to return a value from your script (which will then get set as eg.result) simply set whatever data is to be returned from the script into the result variable.

Code: Select all
result = 'this is what i want returned from the script'[/code]
Thanks! I think I got it now. I actually was pretty useful in understanding to have a look at the code block from the python script plugin.
To test I set up my script like this:

Code: Select all

print 'Printing eg.result from within script before the actions:'
print eg.result
eg.plugins.Window.FindWindow(u'firefox.exe', None, None, None, None, None, False, 0.0, 0)
result = eg.plugins.Window.GrabText(False)
print result
print type(result)
print 'Printing eg.result from within script after the actions:'
print eg.result

print 'The dict thingy:'
try:
    print 'This script has been run %d times.' % run_count
    run_count += 1
except:
    print 'This is the first time this script has run.'
    run_count = 1
I cannot upload screenshots atm for any reason but the result is as expected.
And I included the dict code you posted. The result is as you expected and counter is increasing from time to time I run the script.
This makes me thinking that I will have to check some of my scripts which are run with a high frequency. Like the osd for volume changes. I can see some erratic behavior there from time to time. That variables are stored between the runs might explain this.
Win10 x64 Prof. / Eventghost latest / MCE Plugin / MCE RC6 Receiver / Logitech Harmony Hub / MediaPortal / kodi

User avatar
kgschlosser
Site Admin
Posts: 4034
Joined: Fri Jun 05, 2015 5:43 am
Location: Rocky Mountains, Colorado USA

Re: Access eg.result of plugin inside of a script

Post by kgschlosser » Thu Sep 21, 2017 11:00 am

the variables being stored is something i just discovered. It is a very cool thing that it does this. because it will eliminate the need for setting things to a global if it is going to be used by the same script the next time it runs. but it can be a bad thing a well if ya didn't know that it did. like you said odd behavior can arise from it. so it is good to know that it does this.


and eg.result should work as of my refined explanation of it.

so to simplify it.
eg.result gets set by an action being run from the tree and not an action being called from inside of a python script
result in a python script gets set to the same value as eg.result at the start of the script
if you set result in a script it will be passed to eg.result after the script has ended
If you like the work I have been doing then feel free to Image

Post Reply