masteroftime / Python-Plugin-Loader

55 stars 18 forks source link

Workaround for bound methods #7

Closed senritsu closed 12 years ago

senritsu commented 12 years ago

Hey,

I did a quick workaround to be able to use the decorators on bound methods, using an additional boolean argument for event decorators (after priority), and the additional keyword argument "deferred = True" for command decorators, to defer the event registrations for those functions until instances have been created. The registration has to be manually triggered via "hook.register(self)" from the instance, for example at the end of init.

It's probably not the most elegant way, but for now it works :)

zaph34r/senritsu

senritsu commented 12 years ago

I reverted the hackish changes to the @hook.event and @hook.command decorators, and introduced a (mostly) pure python metaclass based decoration method, using @EventHandler and @CommandHandler that work like the old decorators, but support functions, staticmethods, classmethods and instancemethods.

The registration is automatic as long as the class using them is the main plugin class inheriting from PythonPlugin, or the class inherits from Listener (a stub class that just implements the metaclass necessary for handler registration)

Additionally, the @EventHandler decorator supports argument-less usage and properly links functions with names like PlayerJoin or onPlayerJoin to the correct event with Normal priority.

masteroftime commented 12 years ago

hi senritsu,

It's really great what you've done there but somehow I can't get it to work. I've tried it with something like this:

class TestListener(Listener):
    @EventHandler
    def onBlockPlace(self, event):
        print "Placed a block"

Somehow the event is registered twice, once as a static method and once as an instance method. Whenever the event fires I get an error because the event handler is called with only one parameter, but it is called a second time as an instance method and prints the sentence.

If you could fix this problem I will pull it, it is really good.

senritsu commented 12 years ago

that is indeed curious, maybe a bug with the auto-event-recognition, i didn't test that a lot yet. Does it work if you explicitely specify the event type with @EventHandler("block.BlockPlaceEvent") ? I will also run a few more tests myself, once i get the server running again, it seems a few things broke when i migrated my OS to a SSD yesterday :/

senritsu commented 12 years ago

Ok so getting the server back took less time than expected :) Somehow my ram disk got corrupted in the process of getting my OS partition to another drive, but i had a backup at least.

I tested your function, and for me it only prints one "Placed a block", i integrated it in the existing TestClass class in my PyDevTools version (http://dl.dropbox.com/u/7063219/minecraft/plugins/PyDevTools.zip) with the modded plugin loader (http://dl.dropbox.com/u/7063219/minecraft/plugins/PyPluginLoader-0.3.2.jar), both straight from my server, does the loader differ in size from the one you used? They should be the same, if you tested it with either a pull from my fork, or the one i linked from the PyDevTools page.

senritsu commented 12 years ago

I made another small change to make things a bit more transparent. Now all my changes in this fork basically boil down to:

Everything else is in the python scripts themselves.

Also added lazy argument support to @EventHandler, it should now be possible to use @EventHandler with 0-2 arguments in any order, it sorts out what's what by itself. Might be of use if the event type should be inferred from the function name, but with a different priority than default "normal".