Skip to content

a package for creating classes whose instances have tracked methods

License

Notifications You must be signed in to change notification settings

draperjames/spectate

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status

Spectate

Create classes whose instances have tracked methods

Installation

  • stable : pip install spectate
  • master : pip install git+https://github.com/rmorshea/spectate.git#egg=spectate
  • developer : git clone https://github.com/rmorshea/spectate; cd spectate/; pip install -e .

Basic Usage

spectate is useful for remotely tracking how an instance is modified. This means that protocols for managing updates, don't need to be the outward responsibility of a user, and can instead be done automagically in the background.

For example, if it were desirable to keep track of element changes in a list, spectate could be used to observe list.__setitiem__ in order to be notified when a user sets the value of an element in the list. To do this, we would first create an elist type using expose_as, construct an instance of that type, and then store callback pairs to that instance's spectator. To access a spectator, register one with watch (e.g. spectator = watch(the_elist)), retrieve a preexisting one with the watcher function. Callback pairs are stored by calling the watcher(the_list).callback method. You can then specify, with keywords, whether the callback should be triggered before, and/or or after a given method is called - hereafter refered to as "beforebacks" and "afterbacks" respectively.

Beforebacks

  • Have a signature of (instance, call)
    • instance is the owner of the method
    • call is a Bunch with the keys
      • 'name' - the name of the method which was called
      • 'args' - the arguments which that method will call
      • 'kwargs' - the keywords which that method will call
  • Can return a value which gets passed on to its respective afterback.

Afterbacks

  • Have a signature of (instance, answer)
    • instance is the owner of the method
    • answer is a Bunch with the keys
      • 'name' - the name of the method which was called
      • 'value' - the value returned by the method
      • 'before' - the value returned by the respective beforeback

Example

    from spectate import expose_as

    elist = expose_as('elist', list, '__setitem__')

    def pass_on_old_value(inst, call):
        """The beforeback"""
        index = call.args[0]
        old = inst[index]
        return index, old

    def print_element_change(inst, answer):
        """The afterback"""
        # answer.before = pass_on_old_value(call)
        index, old = answer.before
        new = inst[index]
        if new != old:
            print("{%s: %s} -> {%s: %s}" %
                (index, old, index, new))

pass_on_old_value simply pulls the old value stored at the given index, and then passes that value and the index on to its afterback. The afterback then checks to see if the value which is now stored at that index, is equal to the value which was stored there. If it is, nothing happens, however if it isn't, the change gets printed.

Instances of EventfulList will behave exactly like a list in every way. The only difference being that when a user decides to change the value of a preexisting element, the spectator is notified, and will print once the action is complete:

    # if a WatchableType is passed to watch, any following
    # arguments are passed to it constructor. Thus a new
    # instance is returned along with its spectator
    l = elist([1, 2, 3]]
    spectator = watch(l)

    spectator.callback('__setitem__',
        before=pass_on_old_value,
        after=print_element_change)

    l[0] = 0

Prints {0: 1} -> {0: 0}

...more examples

Under The Hood

Methods are tracked by using expose or (expose_as) to create a new class with MethodSpectator descriptors in the place of specified methods. Then, a user will create a Spectator using watch which is stored on the instance under the attribute _instance_spectator. When a MethodSpectator is accessed through an instance, the descriptor will return a wrapper that will redirect to Spectator.wrapper, which triggers the beforebacks and afterbacks registered to the instance.

About

a package for creating classes whose instances have tracked methods

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Python 100.0%