Cast into custom type

2009-11-03 Thread Henning Bredel
Hi,

I created a plugin mechanism for my application orientating
at the mechanism described by Martin Alchy in

  http://martyalchin.com/2008/jan/10/simple-plugin-framework/

Now I'd like to call methods like `initialize(parent)' when
the user chooses to use a plugin. As described in the blog
mentioned above, I only have access to the general type called
`PluginMount' (holding all the actual plugin instances).

I tried to define "abstract" methods in PluginMount type 
raising a `NotImplementedError' but it seems, there is no
late binding (similar to Java), so the right method would be
called. Only the message 

  TypeError: unbound method initialize() must be called 
  with GeoCache instance as first argument (got PluginMount 
  instance instead)

`GeoCache' would be the plugin type. What is strange, is the
fact, that when asking what instances are hold by PluginMount

   []

is listed. So it seems, that no late binding is applied when
calling the `initialize(self, parent)' method.

I'm quite new using Python, so this might be a quite basic 
question caused by some misunderstandings in general. Feel
free to point me to appropriate site to solve my problem.

Thanks in advance.

  Henning
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Cast into custom type

2009-11-03 Thread Henning Bredel
Diez, Gabriel, Steven,

thanks for your answers. I'll mainly give response in this posting, so 
I hope not repeating myself.

On Tue, 03 Nov 2009 10:18:29 +, Steven D'Aprano wrote:

> On Tue, 03 Nov 2009 09:41:37 +0000, Henning Bredel wrote:
> 
>> Now I'd like to call methods like `initialize(parent)' when the user
>> chooses to use a plugin. As described in the blog mentioned above, I
>> only have access to the general type called `PluginMount' (holding all
>> the actual plugin instances).
>> 
>> I tried to define "abstract" methods in PluginMount type raising a
>> `NotImplementedError' but it seems, there is no late binding (similar
>> to Java), so the right method would be called.
> 
> You need to give some actual examples of what you are trying to do, and
> what you are expecting to happen. How is initialized() being called?

Example: Assume a framework which offers common functionality for a plugin
or a module a user can choose at the beginning. The framework does not
know the concrete type of the plugin so it is possible to extend it by
implementing a well known interface or abstract class.

The framework reads the plugin directory, loads each module and creates
buttons for each plugin with a callback method for initializing. To use
common functionality of the framework, initialization method takes it as
the parent parameter.

I think this listing makes the most sense to you:

  # initialize all plugins
  self._plugin_modules = _load_plugins() # imp loading here
  LOGGER.debug(ActionProvider.plugins) # print what was loaded
  for plugin in ActionProvider.plugins: # create button for each
  app_button = gtk.Button(plugin.title)
  LOGGER.debug('Title of plugin: %s' % plugin.title)
  app_button.connect("clicked", 
 plugin.initialize(plugin, self), 
 None)
  self.set_canvas(app_button)
  app_button.show()

>>   TypeError: unbound method initialize() must be called with GeoCache
>>   instance as first argument (got PluginMount instance instead)
> 
> Sounds like you are calling initialize on the class instead of on an
> instance. I'm *guessing* that you are doing something like this:

Oh, I didn't expext PluginMount to hold only classes :/.

When calling `LOGGER.debug('Title of plugin: %s' % plugin.title)' the
global (not class attribute) `title' attribute is printed out though.
Probably some misinterpretation, too ..?!

> (1) Change the for-loop to:
> 
> for cls in plugin_manager.plugins:
> cls().initialize(plugin_Manager)

Good guess .. but calling it in that way another error says

  app_button.connect("clicked", plugin().initialize(self), None)
  TypeError: __init__() takes exactly 2 arguments (1 given)

But also

  app_button.connect("clicked", plugin().initialize(plugin, self), None)
  TypeError: __init__() takes exactly 2 arguments (1 given)

That is strange, because neither initialize() nor __init__ of the
plugin is called .. only a logging statement shall print a msg.

I hope it got a bit clearer what I am intended to do.

Thanks for your help.

  Henning

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: Cast into custom type

2009-11-04 Thread Henning Bredel
Gabriel,

thanks for your reply. See my comments below.

On Tue, 03 Nov 2009 21:31:27 -0300, Gabriel Genellina wrote:

> En Tue, 03 Nov 2009 09:07:01 -0300, Henning Bredel
>  escribió:
>> On Tue, 03 Nov 2009 10:18:29 +, Steven D'Aprano wrote:
> 
> Then forget about the code you read in that blog post, doesn't apply to
> your use case.

Well, but it shows how to mount plugins into the application without
creating instances instantly. I only use one plugin/module at a time,
so I'd like to avoid holding instances which aren't used.

If the solution from the blogpost are meant completely different, 
I'd appreciate if you could point me on some concrete arguments why I
shouldn't realize plugin mechanism in that way.

BTW: I made it work now (was only a(nother) misinterpretation of how
a callable should look like.
 
> Try something like this:

[...]

> class PluginManager:
>  def __init__(self, plugin_directory):
>  self.plugin_directory = plugin_directory self.plugins = []
> 
>  def load_all(self):
>  for fn in glob(os.path.join(self.plugin_directory, '*.py')):
>  namespace = {}
>  execfile(fn, namespace)
>  for name, obj in namespace.items():
>  if (isinstance(obj, type) and
>  issubclass(obj, Plugin) and
>  obj is not Plugin):
>  # obj is a Plugin subclass
>  cls = obj
>  print cls.__name__, fn
>  print cls.__doc__
>  print
>  plugin = cls(self)  # call the constructor
>  self.plugins.append(plugin)

[...]

Yes, I get your point. But you instantiate all available plugins. I'd like
to avoid that. Will a callable like `plugin().initialize' avoid
that, or is an instance created immediately when passing this callable?

> Plugin is the base class; all plugins must inherit from it. PluginMgr
> scans the plugin directory, executes all modules it finds there (be
> careful...), and looks for Plugin subclasses. Then creates an instance
> of each Plugin subclass.

Well, as far I understand it, I'd say that the ActionProvider class from
the blogpost is the (nearly) the same as your Plugin base class. All new
plugins has to implement the abstract ActionProvider class. The module
loading/recognizing is done by my main application. So what would be the
main difference here?

Thanks for your advice

  Henning
-- 
http://mail.python.org/mailman/listinfo/python-list