Way to Determine Method Signatures

Posted on
Wed Mar 01, 2017 9:59 am
DaveL17 offline
User avatar
Posts: 6758
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Way to Determine Method Signatures

This is probably a stupid question, but is there a way to ask the Indigo server to report the signature for a method?

What I do now is consult the Wiki and Adam's excellent Plugin Developer Documenter, but it would be nice if there were a way to get the server to tell me the signature of the method directly.

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Wed Mar 01, 2017 10:39 am
FlyingDiver online
User avatar
Posts: 7222
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Way to Determine Method Signatures

You mean you provide the function name and the server reports the argument(s) it takes?

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Wed Mar 01, 2017 11:32 am
jay (support) offline
Site Admin
User avatar
Posts: 18224
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Way to Determine Method Signatures

From inside a plugin:

Code: Select all
import inspect
inspect.getargspec(self.deviceStartComm)
>ArgSpec(args=['self', 'dev'], varargs=None, keywords=None, defaults=None)


It also works in a scripting shell because it is also a plugin (a special one). So in the scripting shell you can see all the methods defined in the Plugin base class. If you do a Reload in Interactive Shell on any plugin, you can inspect any methods defined in that plugin (as well as those in the Plugin base class).

Combine that with:

Code: Select all
dir(self)


to show all methods (beware, it also shows properties which dir won't work on) you can pretty much find and inspect anything about an object.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Wed Mar 01, 2017 11:37 am
FlyingDiver online
User avatar
Posts: 7222
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Way to Determine Method Signatures

Code: Select all
Starting shell for plugin MyQ.indigoPlugin.
To access the plugin instance use the global named self.

Python 2.7.10 (default, Jul 30 2016, 19:40:32)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
Connected to Indigo Server v7.0.3, api v2.0 (localhost:1176)
Started Plugin MyQ v7.2.0
>>> import inspect
>>> inspect.getsargsspec(self.deviceStartComm)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'module' object has no attribute 'getsargsspec'
>>>

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Wed Mar 01, 2017 12:00 pm
jay (support) offline
Site Admin
User avatar
Posts: 18224
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Way to Determine Method Signatures

Typo - fixed it in the code snip above.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Wed Mar 01, 2017 12:01 pm
DaveL17 offline
User avatar
Posts: 6758
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Way to Determine Method Signatures

Perfect. I tried inspect before, but must've done something wrong.

Code: Select all
Python 2.7.10 (default, Jul 30 2016, 19:40:32)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
Connected to Indigo Server v7.0.3, api v2.0 (localhost:1176)
>>> import inspect
>>> inspect.getargspec(self.deviceStartComm)
ArgSpec(args=['self', 'dev'], varargs=None, keywords=None, defaults=None)

>>> inspect.getargspec(self.validatePrefsConfigUi)
ArgSpec(args=['self', 'valuesDict'], varargs=None, keywords=None, defaults=None)

>>> inspect.getargspec(self.validateDeviceConfigUi)
ArgSpec(args=['self', 'valuesDict', 'typeId', 'devId'], varargs=None, keywords=None, defaults=None)
>>>



This will help immensely in confirming I have signatures arranged properly. Thanks Jay.
Last edited by DaveL17 on Wed Mar 01, 2017 1:03 pm, edited 2 times in total.

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Wed Mar 01, 2017 12:22 pm
jay (support) offline
Site Admin
User avatar
Posts: 18224
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Way to Determine Method Signatures

DaveL17 wrote:
Thanks Matt.


Who? :shock:

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Wed Mar 01, 2017 12:24 pm
FlyingDiver online
User avatar
Posts: 7222
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: Way to Determine Method Signatures

:lol:

joe (aka FlyingDiver)
my plugins: http://forums.indigodomo.com/viewforum.php?f=177

Posted on
Wed Mar 01, 2017 1:04 pm
DaveL17 offline
User avatar
Posts: 6758
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Way to Determine Method Signatures

jay (support) wrote:
DaveL17 wrote:
Thanks Matt.


Who? :shock:


Typo - fixed it in the post above. :D

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Wed Mar 01, 2017 2:14 pm
DaveL17 offline
User avatar
Posts: 6758
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Way to Determine Method Signatures

Bitchin. I wrote a small plugin and it works great. The key parts:

plugin.py
Code: Select all
    def listOfMethods(self, valuesDict, typeId, targetId):
        list_of_methods = dir(self)
        return [(method, method) for method in list_of_methods]

    def inspectMethod(self, valuesDict, typeId):
        import inspect
        method = getattr(self, valuesDict['listOfMethods'])
        signature = inspect.getargspec(method)
        indigo.server.log(u"self.{0}: {1}".format(valuesDict['listOfMethods'], signature))


Menuitems.xml
Code: Select all
    <MenuItem id="methodSignature">
        <Name>Method Signature</Name>
        <ConfigUI>
            <Field id="listOfMethods" type="menu">
                <Label>Method:</Label>
                <List class="self" filter="" method="listOfMethods" dynamicReload="true"/>
                <CallbackMethod>inspectMethod</CallbackMethod>
            </Field>
        </ConfigUI>
    </MenuItem>


Result:
Code: Select all
Mar 1, 2017, 2:07:34 PM
   plugin                       self.actionGroupCreated: ArgSpec(args=['self', 'group'], varargs=None, keywords=None, defaults=None)
   plugin                       self.deviceCreated: ArgSpec(args=['self', 'dev'], varargs=None, keywords=None, defaults=None)

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Wed Mar 01, 2017 4:41 pm
jay (support) offline
Site Admin
User avatar
Posts: 18224
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Way to Determine Method Signatures

Cool. Somewhere in there before callinginspect.getargspec() you might want to see if it's a method using callable(self.XXXX) which will return True if it's a method and False if it's a variable/property. dir() shows all names defined by the object which includes both methods and properties. This might work:

Code: Select all
def listOfMethods():
   list_of_methods = dir(self)
   return [(method, method) for method in list_of_methods if callable(getattr(self, method))]

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Wed Mar 01, 2017 4:42 pm
jay (support) offline
Site Admin
User avatar
Posts: 18224
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Way to Determine Method Signatures

Man, I LOVE Python... :P

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Wed Mar 01, 2017 5:04 pm
DaveL17 offline
User avatar
Posts: 6758
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Way to Determine Method Signatures

jay (support) wrote:
Cool. Somewhere in there before callinginspect.getargspec() you might want to see if it's a method using callable(self.XXXX) which will return True if it's a method and False if it's a variable/property. dir() shows all names defined by the object which includes both methods and properties. This might work:

Code: Select all
def listOfMethods():
   list_of_methods = dir(self)
   return [(method, method) for method in list_of_methods if callable(getattr(self, method))]

Great minds think alike. I couldn't get callable() to work after a couple quick tests (it would pass __delattr__ for example), but I had already done something similar if, somewhat more inelegant:

Code: Select all
    def listOfMethods(self, valuesDict, typeId, targetId):
        list_of_attributes = []
        for method in dir(self):
            try:
                inspect.getargspec(getattr(self, method))
                list_of_attributes.append((method, method))
            except TypeError:
                continue
        return list_of_attributes

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Posted on
Wed Mar 01, 2017 5:18 pm
jay (support) offline
Site Admin
User avatar
Posts: 18224
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Way to Determine Method Signatures

That works too. :)

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Thu Mar 02, 2017 5:05 pm
DaveL17 offline
User avatar
Posts: 6758
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: Way to Determine Method Signatures

Small change from above. By changing 'self' to 'indigo.PluginBase' in listOfMethods(), it avoids having the calling plugin's methods show up in the returned list. Reposting the whole thing so it's together in one place.

Menuitems.xml
Code: Select all
    <MenuItem id="methodSignature">
        <Name>Method Signature</Name>
        <ConfigUI>
            <Field id="instructions" type="label">
                <Label>Select the method that you would like to inspect.</Label>
            </Field>
            <Field id="listOfMethods" type="menu">
                <Label>Method:</Label>
                <List class="self" filter="" method="listOfMethods" dynamicReload="true"/>
                <CallbackMethod>inspectMethod</CallbackMethod>
            </Field>
        </ConfigUI>
    </MenuItem>


plugin.py
Code: Select all
    def inspectMethod(self, valuesDict, typeId):
        self.logger.debug(u"Call to inspectMethod")

        method = getattr(self, valuesDict['listOfMethods'])
        signature = inspect.getargspec(method)
        indigo.server.log(u"self.{0}: {1}".format(valuesDict['listOfMethods'], signature))

    def listOfMethods(self, valuesDict, typeId, targetId):
        self.logger.debug(u"Call to listOfMethods")

        list_of_attributes = []
        for method in dir(indigo.PluginBase):
            try:
                inspect.getargspec(getattr(indigo.PluginBase, method))
                list_of_attributes.append((method, method))
            except (AttributeError, TypeError):
                continue
        return list_of_attributes



[*] Also updates for Indigo 7 logging. For earlier versions, change 'self.logger.debug' to 'self.debugLog'.

I came here to drink milk and kick ass....and I've just finished my milk.

[My Plugins] - [My Forums]

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 10 guests