call or invoke a function in same .py script?

Posted on
Tue Feb 02, 2021 11:10 pm
whmoorejr offline
User avatar
Posts: 762
Joined: Jan 15, 2013
Location: Houston, TX

call or invoke a function in same .py script?

I have a chunk of code that is pretty big and I'll need to re-use it several times.... Can I define it as a function and call it or invoke it elsewhere in the same script?
Small sample just as an idea of what I'm looking at.

Code: Select all
def updateFoo(self):
     indigo.server.log("I'm a function from somewhere else"+foo)


I've tried a few different ways to call or invoke it elsewhere with no success.

Code: Select all
def otherFunction(self):
     foo = "bar"
     >>>def updateFooa():

                     or
     updateFoo():

But I've noticed that code snippets I find on stack overflow don't always pan out.

Bill
My Plugin: My People

Posted on
Wed Feb 03, 2021 6:22 am
DaveL17 offline
User avatar
Posts: 6742
Joined: Aug 20, 2013
Location: Chicago, IL, USA

Re: call or invoke a function in same .py script?

Without converting the whole thing to a class, I think this is the easiest way. There may be landmines with this approach, but I've not run across any.

Code: Select all
#! /usr/bin/env python
# -*- coding: utf-8 -*-

def foo():
   def bar():
      print("bar")
   
   foo.bar = bar  # <--
   print("foo")
   bar()

def stuff():
   print("stuff")
   foo()
   foo.bar()
   
foo()
foo.bar()
stuff()
yields:

Code: Select all
foo
bar
bar
stuff
foo
bar
bar

EDIT: this will only work after the first call of foo() because the line foo.bar = bar has to be called at least once for it to be assigned.

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

[My Plugins] - [My Forums]

Posted on
Wed Feb 03, 2021 8:44 am
FlyingDiver offline
User avatar
Posts: 7189
Joined: Jun 07, 2014
Location: Southwest Florida, USA

Re: call or invoke a function in same .py script?

What is "foo" in your example?

If the entire block of code needs to be executed in multiple places, you should be able to just make it a function and call it. But it appears you have something that needs to change between calls. Can you not pass that data as a parameter to your new function?

For instance, would this work?

Code: Select all
def updateFoo(self, foo):
     indigo.server.log("I'm a function from somewhere else"+foo)

def otherFunction(self):
    updateFoo("bar")


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

Posted on
Wed Feb 03, 2021 9:43 am
whmoorejr offline
User avatar
Posts: 762
Joined: Jan 15, 2013
Location: Houston, TX

Re: call or invoke a function in same .py script?

    1) The primary focus of the plugin is a control page tool to provide a different way of organizing and viewing indigo devices. (updates don't have to be continual or happen with every device or variable, just when actively viewing a control page).
    2)The plugin could be used to trigger events (so the user may want more frequent updating)
1+2 = I would like to have multiple ways to update (when the user does something that will change states + ability to change the background update frequency)

Foo is a chunk of code that updates a laundry list of device metadata. The metadata is a map to the source device/variable or text (about 140 lines or so). It will be called when a device is created, updated, and when a few different actions are called.... So I'll need to use that 140+/- lines about 11 times. I could just copy-paste the lines in for every place I need it, but that would add an extra 1400 lines to the overall script.

The plugin doesn't have to update in the background to function if the plugin is used primarily as a control page tool. If the plugin is used to trigger other things from, then more frequent updates would be important. So, the update function is presently in the runConcurrentThread. The "self.sleep" interval can be manipulated from the plugin config dialog.

Right now, the update function updates 16 states. Once I figure out where everything should go, that will be expanded to the full 60 device states. I won't know the server impact until I fully build out 60 device states for 10 or so plugin devices. Right now, sleep=5, 3 devices @ 16 states = 0.2% of my cpu. (when looking at the plugin PID).

So, at a minimum, it's important to update the states whenever they are charged by the user (4 different actions) or whenever the control page actions are run (5 different actions) Plus 1 (update all now action)... 10 actions + 1 runConcurrent = 11 places where I would use an updateAll function

Code: Select all
      def updateAllFromMetadata():   
         for dev in indigo.devices.iter(filter="com.whmoorejr.my-rooms"):
            ###### Identifier States   
               subRoomName = self.substitute(dev.pluginProps.get("meta_roomName","unknown"))
               subRoomState = self.substitute(dev.pluginProps.get("meta_roomState","Other"))
               subFloorLevel = self.substitute(dev.pluginProps.get("meta_floorLevel","unknown"))
               subBuilding = self.substitute(dev.pluginProps.get("meta_building","unknown"))
            ###### Occupancy States   
               subIsOccupied = self.substitute(dev.pluginProps.get("meta_isOccupied","unknown"))
               subLastOccupied = self.substitute(dev.pluginProps.get("meta_lastOccupied","unknown"))
               subLastVacant = self.substitute(dev.pluginProps.get("meta_lastVacant","unknown"))
               subOccupiedBy1 = self.substitute(dev.pluginProps.get("meta_occupiedBy1","unknown"))
               subOccupiedBy2 = self.substitute(dev.pluginProps.get("meta_occupiedBy2","unknown"))
            ###### Lighting Device States
               subMainLight = self.substitute(dev.pluginProps.get("meta_mainLight","unknown"))
               subAccentLight = self.substitute(dev.pluginProps.get("meta_accentLight","unknown"))
               subLuminescence = self.substitute(dev.pluginProps.get("meta_luminescence","unknown"))
               subWindowShades = self.substitute(dev.pluginProps.get("meta_windowShades","unknown"))
            ###### Climate Device States
               subTemperature = self.substitute(dev.pluginProps.get("meta_temperature","unknown"))
               subHumidity = self.substitute(dev.pluginProps.get("meta_humidity","unknown"))
               subCeilingFan = self.substitute(dev.pluginProps.get("meta_ceilingFan","unknown"))
            ###### Outlet Device States    <- need to populate this
            ###### Audio/Vidoe Device States  <- need to populate this
            ###### Security Device States  <- need to populate this   
            ###### Auxiliary Device States   <- need to populate this                  
               
               
               #indigo.server.log("Sleep Test") # <-- for testing
               updatedStates = [
                  {'key' : u'roomName', 'value' : subRoomName},
                  {'key' : u'roomState', 'value' : subRoomState},
                  {'key' : u'floorLevel', 'value' : subFloorLevel},
                  {'key' : u'building', 'value' : subBuilding},
                  {'key' : u'isOccupied', 'value' : subIsOccupied},
                  {'key' : u'lastOccupied', 'value' : subLastOccupied},
                  {'key' : u'lastVacant', 'value' : subLastVacant},
                  {'key' : u'occupiedBy1', 'value' : subOccupiedBy1},
                  {'key' : u'occupiedBy2', 'value' : subOccupiedBy2},
                  {'key' : u'mainLight', 'value' : subMainLight},
                  {'key' : u'accentLight', 'value' : subAccentLight},
                  {'key' : u'luminescence', 'value' : subLuminescence},
                  {'key' : u'windowShades', 'value' : subWindowShades},
                  {'key' : u'temperature', 'value' : subTemperature},
                  {'key' : u'humidity', 'value' : subHumidity},
                  {'key' : u'ceilingFan', 'value' : subCeilingFan}
                  ]
               dev.updateStatesOnServer(updatedStates)
               if subRoomState == "On":
                  dev.updateStateImageOnServer(indigo.kStateImageSel.SensorOn)
               elif subRoomState == "Off":
                  dev.updateStateImageOnServer(indigo.kStateImageSel.SensorOff)
               else:
                  dev.updateStateImageOnServer(indigo.kStateImageSel.SensorTripped)

I considered the subscribeToChanges route, but since the plugin can utilize any state from any device or any variable... the plugin would have to look at every device change and every variable change across all of indigo and if the user is only using the plugin as a control page tool, that would be a lot of unnecessary server load if their plugin devices are associated with a ton of other devices/variables. Example, a light switch with a motion detector in a kids room will be updating/changing almost consistently... Do I need a control page I'm not looking at updating consistently? Or is it okay if the state only updates when I run the action to view the page or press a button on the page to "update now" or wait 5, 10, 30, 60 seconds etc, for the runConcurrent to do it's thing?

A lot of guessing on my part as I'm learning as I go.... I just learned how to write a runConcurrentThread yesterday. (Thank you Karl for helping baby-step me through that process)

Bill
My Plugin: My People

Posted on
Wed Feb 03, 2021 11:04 am
RogueProeliator offline
User avatar
Posts: 2501
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: call or invoke a function in same .py script?

I considered the subscribeToChanges route, but since the plugin can utilize any state from any device or any variable... the plugin would have to look at every device change and every variable change across all of indigo and if the user is only using the plugin as a control page tool, that would be a lot of unnecessary server load if their plugin devices are associated with a ton of other devices/variables. Example, a light switch with a motion detector in a kids room will be updating/changing almost consistently... Do I need a control page I'm not looking at updating consistently? Or is it okay if the state only updates when I run the action to view the page or press a button on the page to "update now" or wait 5, 10, 30, 60 seconds etc, for the runConcurrent to do it's thing?

If I understand your plugin correctly and what you are trying to accomplish, I would personally take a different approach because I suspect your update routine is not going to be wonderfully performant if it is is having to fetch a bunch of devices all over the place where in many will presumably have a high chance of not having been changed.

If I were developing the plugin, I would do something such as:

  • Maintain a list of your plugin devices (adding it upon the device being started, removing when stopped) so that you don't have to retrieve the value anew each time. You should know when your values change and it has to be reloaded/refreshed (when the user saves the data, which depending upon your plugin will restart the device)
  • When each device/room is loaded, build a list of the devices and variables that it is dependent upon
  • Subscribe to the device and variable changes -- when you receive one from the server, check your dictionary to see which (if any) of your devices and states would be affected and only update those specific devices and states. A check into a dictionary is EXTREMELY fast so it should not have a huge impact on the system to "see" all changes if you are merely looking to see what may or may not have changed for the non-affected devices. THEN, and here is an important part, I would send the processing of the update to a separate thread (can use the concurrent thread you just setup). That way the processing of the event call is not held up and the server is (presumably) not affected much. You might even be able to get fancy and ensure that the update is only in the queue once.

Now, I may be off on fully understanding the plugin and, if so, my apologies... and, of course, you can still have an "update all" that really does that and could be an action, called upon the plugin fully starting up, etc.

Of course, if you decide to try some changes such as this we can certainly help you through it.

Posted on
Wed Feb 03, 2021 11:52 am
jay (support) offline
Site Admin
User avatar
Posts: 18199
Joined: Mar 19, 2008
Location: Austin, Texas

Re: call or invoke a function in same .py script?

RogueProeliator wrote:
I considered the subscribeToChanges route, but since the plugin can utilize any state from any device or any variable... the plugin would have to look at every device change and every variable change across all of indigo and if the user is only using the plugin as a control page tool, that would be a lot of unnecessary server load if their plugin devices are associated with a ton of other devices/variables. Example, a light switch with a motion detector in a kids room will be updating/changing almost consistently... Do I need a control page I'm not looking at updating consistently? Or is it okay if the state only updates when I run the action to view the page or press a button on the page to "update now" or wait 5, 10, 30, 60 seconds etc, for the runConcurrent to do it's thing?

If I understand your plugin correctly and what you are trying to accomplish, I would personally take a different approach because I suspect your update routine is not going to be wonderfully performant if it is is having to fetch a bunch of devices all over the place where in many will presumably have a high chance of not having been changed.


This was my suggestion in another thread (great minds and all that :)).

What I don't necessarily understand, because I don't see the code, is how the updated information from the device/variable is retrieved. If he has a list of devices and variables that are used in all of his devices, then it might not be too much of an issue, though I would caution that as a general solution, calling a script to update the data right before loading a control page is probably not a great solution because back/forward navigation could cause that script to get reloaded multiple times in a short period. That could cause significant server round trips to get the necessary data.

As Adam says, subscriptions to device and variable changes in and of itself isn't a huge amount of overhead for the server since it doesn't wait for the reply from the methods that it calls in plugins. So if you have a list of IDs that you care about, it's easy to look up the id from the list/dict, and the deviceUpdated method even supplies you an instance of the new vs the old device, so you can compare whether the state(s) you care about have changed.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Wed Feb 03, 2021 12:43 pm
whmoorejr offline
User avatar
Posts: 762
Joined: Jan 15, 2013
Location: Houston, TX

Re: call or invoke a function in same .py script?

Summary of current method: It basically uses a room:statekey as the destination and lets the user select a source device:statekey.
The source device:statekey is saved in the room:statekey as a substitute. The source %%d:12345:statekey%% is saved as a device property "meta_statekey".
Example:
Actual Light in Living Room = %%12345:OnOffState%% ; current value = "Off"
My Room Device, "LivingRoom" key "mainLight" = "Off" (substitute device:state)
My Room Device, "LivingRoom" meta_mainLight = "%%12345:OnOffState%%

- Light Turns On-

Update: substitute(meta_mainLight) = "On". Write value to LivingRoom:mainLight

This is the part that gets the source state from the user (code below). There is a separate one for a source variable and a separate one to get a text entry (with device/variable substitutions... and where I started which sorta explains the route I took). For a real good chuckle, the full code/plugin is here: https://github.com/whmoorejr/My-Rooms. It works, but it's obviously a work in progress.

Things I don't know how to do or just don't know:
    1) get the inputted source device:state and save in a dictionary so just those are the ones checked for update.
    2) Same as #1, but with variables
    3) Text... if the user enters a VaribleID or Device:statekey, would that work with a subscribeToChanges or if I have the other two options, would I then change text to just text.... no substitutions.
    4) "or", see below "def filterDevStatesFS" and my use of if if if if if. Not sure if that's the best way to do that.
    5) Can your device filter be != instead of =? See "def filterAllDevices", I excluded one device, how would I exclude all "com.whmoorejr.my-rooms"?
    6) I don't want to do #5, I'm just curious. I like the ability to have one room device reflect the value of another.
    7) what's the "u" do in a string? Sometimes I use it, sometimes I don't... depends on where I grabbed that snippet of code from, but either way it seems to work... <-- also, just curious.
Sidenote:
    1) Karl has been really helpful and we did a screen-share conference call too which helped me move things along
    2) Putting this on a separate development instal of indigo with the "Sample House" with almost no background log noise has made things go a lot faster. (thank's Jay!)
Code: Select all
def setAnyStateFS(self, pluginAction, dev):
      requestedDev = str(pluginAction.props.get(u"setADeviceFieldFS"))
      requestedState = str(pluginAction.props.get(u"setAnyStateFieldFS")) 
      sourceDevID = str(pluginAction.props.get(u"setSourceDeviceField"))
      sourceState = str(pluginAction.props.get(u"setSourceStateField"))
      newValue = (u"%%d:"+sourceDevID+":"+sourceState+"%%")
      subNewValue = self.substitute(newValue)
      sourceDevice = indigo.devices[int(sourceDevID)]
      sourceDeviceName = sourceDevice.name
      thisRoomDev = indigo.devices[int(requestedDev)]
      thisDevName = thisRoomDev.name
      thisRoomDev.updateStateOnServer(key=requestedState, value=subNewValue)
      self.debugLog(u"The Device -"+thisDevName+":"+requestedState+"- value set to: -" + subNewValue + "- From Source: -" +sourceDeviceName+ ":"+sourceState+"-")
      
      newProps = thisRoomDev.pluginProps
      metaDataItem = "meta_"+requestedState
      newProps[metaDataItem] = newValue
      thisRoomDev.replacePluginPropsOnServer(newProps)
      self.debugLog("metadata added to " + thisDevName + ". key= " + metaDataItem + " with value: " + newValue)
      
   def filterDevicesFS(self, filter, valuesDict, typeId, targetId):
      xList =[]
      for dev in indigo.devices.iter(filter="com.whmoorejr.my-rooms"):
         if dev.name != "Now Showing Room":
            xList.append(( unicode(dev.id),dev.name))
      return xList
      
   def buttonConfirmDeviceFS(self, valuesDict, typeID, devId):
      return valuesDict

   def filterDevStatesFS(self, filter, valuesDict, typeId, targetId):
      xList =[]
      if len(valuesDict) < 2:                         return [("0","")]
      if "setADeviceFieldFS" not in valuesDict:       return [("0","")]
      if valuesDict["setADeviceFieldFS"] in ["0",""]: return [("0","")]
      dev = indigo.devices[int(valuesDict["setADeviceFieldFS"])]
      for state in dev.states:
         if state !="roomState":
            if state!="roomState.On":
               if state!="roomState.Off":
                  if state!="roomState.Other":
                     xList.append((state,state+"   ; currentV: "+unicode(dev.states[state]) ))
      #xList.append(("0","==== off, do not use ===="))
      return xList   
   
   def filterAllDevices(self, filter, valuesDict, typeId, targetId):
      xList =[]
      for dev in indigo.devices:
         if dev.name !="Now Showing Room":
            xList.append(( unicode(dev.id),dev.name))
      return xList
   
   def buttonConfirmSourceFS(self, valuesDict, typeID, devID):
      return valuesDict
   
   def filterSourceDevStates(self, filter, valuesDict, typeId, targetId):
      xList =[]
      if len(valuesDict) < 2:                         return [("0","")]
      if "setSourceDeviceField" not in valuesDict:       return [("0","")]
      if valuesDict["setSourceDeviceField"] in ["0",""]: return [("0","")]
      dev = indigo.devices[int(valuesDict["setSourceDeviceField"])]
      for state in dev.states:
         xList.append((state,state+"   ; currentV: "+unicode(dev.states[state]) ))
      return xList
         
   def buttonConfirmNewValueFS(self, valuesDict, typeId, devId):
      self.debugLog("I Pushed the Confirm Button")
      requestedDev = valuesDict["setADeviceFieldFS"]
      requestedState = valuesDict["setAnyStateFieldFS"]
      sourceDevID = valuesDict["setSourceDeviceField"]
      sourceState = valuesDict["setSourceStateField"]
      newValue = (u"%%d:"+sourceDevID+":"+sourceState+"%%")
      subNewValue = self.substitute(newValue)
      sourceDevice = indigo.devices[int(sourceDevID)]
      sourceDeviceName = sourceDevice.name
      thisRoomDev = indigo.devices[int(requestedDev)]
      thisDevName = thisRoomDev.name
      thisRoomDev.updateStateOnServer(key=requestedState, value=subNewValue)
      self.debugLog(u"The Device -"+thisDevName+":"+requestedState+"- value set to: -" + subNewValue + "- From Source: -" +sourceDeviceName+ ":"+sourceState+"-")
      
      newProps = thisRoomDev.pluginProps
      metaDataItem = "meta_"+requestedState
      newProps[metaDataItem] = newValue
      thisRoomDev.replacePluginPropsOnServer(newProps)
      self.debugLog("metadata added to " + thisDevName + ". key= " + metaDataItem + " with value: " + newValue)
      return valuesDict
Note on above: def setAnyStateFS is a near copy of def buttonConfirmNewValueFS, that's on purpose. If the user is updating a room, then can update through all the states they want from the GUI without having to save - execute action, open, change state, save, execute, etc. Primarily because I couldn't figure out how to make an action or do a device config that would open with all state keys pre-populated so the user would just have to update versus getting a blank form every time.

Bill
My Plugin: My People

Posted on
Wed Feb 03, 2021 1:38 pm
jay (support) offline
Site Admin
User avatar
Posts: 18199
Joined: Mar 19, 2008
Location: Austin, Texas

Re: call or invoke a function in same .py script?

Gotcha, I sorta overlooked that :oops: .

FYI, for every call to substitute it's going to do a round-trip to the server to get any device and/or variable it finds in the string. Not super efficient, but if the number of devices/variables is small probably not too bad.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Wed Feb 03, 2021 1:47 pm
RogueProeliator offline
User avatar
Posts: 2501
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: call or invoke a function in same .py script?

If he has a list of devices and variables that are used in all of his devices, then it might not be too much of an issue,

Based upon my super quick glance, and he can confirm, but I think he is not pulling up the devices himself but instead utilizing the Plugin's base substitute call. Which means that the same device may be retrieved from the server multiple times (potentially) if they exist in multiple substitution strings. Unless there is some caching of the retrieval, it looked to me like the base substitute retrieved a new copy of the device each time. Actually, I think it was retrieving a new copy of the device for each token even if the same device appeared twice in the string, though that could have changed since I looked.

@whmoorejr -- I can look at your longer post later... didn't forget about you but have to get back to work from lunch or my demo won't have much to demo. LOL Some may answer in the meantime, but I will definitely look back again, hopefully this evening.

Adam

Posted on
Sat Feb 06, 2021 3:31 pm
RogueProeliator offline
User avatar
Posts: 2501
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: call or invoke a function in same .py script?

1) get the inputted source device:state and save in a dictionary so just those are the ones checked for update.
2) Same as #1, but with variables
3) Text... if the user enters a VaribleID or Device:statekey, would that work with a subscribeToChanges or if I have the other two options, would I then change text to just text.... no substitutions.

What I personally would do is capture the devices/variables used in the substitution patterns when the device starts up... so in a pseudo-code algorithm it would look something like:

  1. In your plugin, define a dictionary to store the list of IDs that are required, or maybe one each for devices and variables...
    Code: Select all
    self.monitoredDevices = dict()
    self.monitoredVariables = dict()
  2. In the deviceStartComm routine, capture the IDs of the variables/devices... which I assume in your case would be looking for the substitution pattern:
    Code: Select all
    def deviceStartComm(self, dev):
       ... build a list of the IDs that are required and add them to the dictionary ... not sure if you are storing the ID or have to parse the string; if so, a simply regular expression would find all tokens ... just something simple like:
       self.monitoredVariables[id] = list of *whatever is needed to show what needs to update*
    Without a deep dive I don't know what you need, but guessing here you would store something like the room device ID and state name?
  3. In the subscription to changes routine, you will check to see if that ID is in your list...
    Code: Select all
    if dev.id in self.monitoredDevices:
       ... run the update for each entry in self.monitoredDevices[dev.id] since you know those require updating ...

7) what's the "u" do in a string? Sometimes I use it, sometimes I don't... depends on where I grabbed that snippet of code from, but either way it seems to work... <-- also, just curious.

This can get very complicated, but the short & simple answer is that the u in front of a string makes it into a Unicode string, capable of handing characters outside of the simple ASCII set. So it would allow, for example, non-US characters with accents/umlauts or Cyrillic characters. Anything supporting user-entered characters should be Unicide with the u as we have many users that utilize non-ASCII characters in their native language.

Obviously can answer any more or more detailed, but may need to break it down and look at each step that you have trouble with one function at a time to make more sense. For example, maybe start with just trying to capture which devices need to change. ALSO, note that rarely in programming is there a single way -- and sometimes not even a "best" way. So you can always start with something you have working and try to improve it with this method; if it works out, then great. If not, just roll back to the old method.

Adam

Posted on
Sat Feb 06, 2021 4:29 pm
jay (support) offline
Site Admin
User avatar
Posts: 18199
Joined: Mar 19, 2008
Location: Austin, Texas

Re: call or invoke a function in same .py script?

@whmoorejr wrote:
5) Can your device filter be != instead of =? See "def filterAllDevices", I excluded one device, how would I exclude all "com.whmoorejr.my-rooms"?


No. In the case of this method definition:

Code: Select all
def filterAllDevices(self, filter, valuesDict, typeId, targetId)


filter is a parameter to the method. When calling a method using named parameters:

Code: Select all
somePluginObject.filterAllDevices(filter="some filter here", valuesDict=domeValuesDict, typeId="some type id", targetId="some target id")


the equals in this context is an assignment operator, setting the value of the filter parameter to be "some filter here". != is a comparison operator, not an assignment operator, and can't be used in this context.

@whmoorejr wrote:
7) what's the "u" do in a string? Sometimes I use it, sometimes I don't... depends on where I grabbed that snippet of code from, but either way it seems to work... <-- also, just curious.


Adam's description is good, but TL;DR: use u"string" everywhere and you'll be safe®. I don't always follow my own advice, but I should... :oops:

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Sat Feb 06, 2021 5:56 pm
whmoorejr offline
User avatar
Posts: 762
Joined: Jan 15, 2013
Location: Houston, TX

Re: call or invoke a function in same .py script?

RogueProeliator wrote:
For example, maybe start with just trying to capture which devices need to change.
That will be my next step. The plugin functions now. But I want to clean it up before I grow it by adding in the rest of the custom states...

And I mean this as a compliment... If you look at the menus and stuff in this plugin compared to the My People plugin... that's all you and what I've learned poking around with the Plugin Developer Documenter.

jay (support) wrote:
but TL;DR: use u"string" everywhere and you'll be safe
Good idea. Until I sift through it all, it's the "My Rooms - 'Merica edition."

Bill
My Plugin: My People

Posted on
Sat Feb 06, 2021 9:31 pm
RogueProeliator offline
User avatar
Posts: 2501
Joined: Nov 13, 2012
Location: Baton Rouge, LA

Re: call or invoke a function in same .py script?

Adam's description is good, but TL;DR: use u"string" everywhere and you'll be safe®. I don't always follow my own advice, but I should...

Yeah, I should have said that... it basically won't hurt. I actually didn't use that in the first couple of versions of my plugins and, of course, had people with issues immediately. I've since gone to using it everywhere, even literals where I know what I am typing in... except if I forget. :-) Should make people start doing code reviews lol

And I mean this as a compliment... If you look at the menus and stuff in this plugin compared to the My People plugin... that's all you and what I've learned poking around with the Plugin Developer Documenter.

Glad it could help some, and that is exactly what it is there for, to easy grab bits and pieces out as needed. It doesn't go into device specific stuff, which is what the SDK is better suited to show, but for individual features within it, makes it easy to grab-and-go!

Adam

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 3 guests