Search code examples
sublimetext2sublimetext3sublimetextsublime-text-plugin

Add variable to the instance of the class


I'm trying to add variable to the instance of the class.

In console, I get this error:

TypeError: __init__() missing 1 required positional argument: 'view'

And here is the code itself:

import sublime_plugin

class TestMe(sublime_plugin.EventListener):

    def __init__(self, view):
        self.view = view
        self.need_update = False

    def setme():
        need_update = True

    def on_activated(self, view):
        setme()
        if need_update == True:
            print("it works")

I spend all day trying to figure out different ways to resolve it. What I'm doing wrong?


Solution

  • It looks like the core of your issue is that you're subclassing EventListener and not ViewEventListener.

    The reason you're seeing this error is that the __init__ method of the EventListener class takes no arguments (with the exception of self, which is always present in class methods). When Sublime creates the instance, it doesn't pass in a view, and since your __init__ requires one, you get an error that you're missing a positional parameter.

    This is because the events in EventListener all pass in the view that they apply to (if any), so the class doesn't associate with one specific view and thus one is not needed when the listener is created.

    In contrast, ViewEventListener offers only a subset of the events that EventListener does, but its instances apply to a specific view, so its constructor is provided with the view that it applies to. In this case the events themselves don't have a view argument because the listener already knows what view it is associated with.

    A modified version of your code that takes all of this into account would look like this:

    import sublime_plugin
    
    class TestMe(sublime_plugin.ViewEventListener):
        def __init__(self, view):
            super().__init__(view)
            self.need_update = False
    
        def setme(self):
            self.need_update = True
    
        def on_activated(self):
            self.setme()
            if self.need_update == True:
                print("it works")
    

    Here the super class is ViewEventListener, for which Sublime will pass a view when it is created. This also invokes the super class version of the __init__ method instead of setting self.view to the view passed in, which allows it to do whatever other setup the default class needs to do (in this case none, but better safe than sorry).

    Additionally the methods are adjusted a little bit, since in this case every view will have a unique instance of this class created for it:

    • setme takes a self argument so that it knows what instance it is being called for
    • on_activated does not take a view argument because it has access to self.view if it needs it
    • Calls to setme need to be prefixed with self. so that python knows what we're trying to do (this also implicitly passes in the self argument)
    • All accesses for need_update are prefixed with self. so that each method accesses the version of the variable that is unique to its own instance.