Giter Club home page Giter Club logo

plugnplay's Introduction

Dalton Barreto (@daltonmatos)

  • Fiz Ciência da Computação na UFRJ (2002/2 - 2010/2)

  • Tenho interesse por Programação e Infra-estrutura

  • Trabalho profissionalmente com Desenvolvimento (desde 2007) e Infra-estrutura(desde 2012)

  • Mantenho meu blog/site em https://daltonmatos.com onde escrevo sobre projetos e pesquisas que faço

  • Minha linguagem de escolha é Python (3+) (https://docs.python.org/3/)

  • Em meu tempo livre desenvolvo alguns projetos

    • asyncowrker - Framework para escrever workers com I/O assíncrono em Python e baseado em Typehints
    • aiologger - Lib para gerar logs usando I/O assíncrono em Python
  • Me pergunte sobre Python!

  • Me interesso também por micro-controladores em especial pela família AVR.

    • Aqui tem uma pesquisa que fiz e que me ensinou muito sobre esses chips e onde aprendi bastante sobre assembly para AVR também.
  • Você pode me encontrar também no twitter em @daltonmatos

plugnplay's People

Contributors

daltonmatos avatar dundeemt avatar fabaff avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

plugnplay's Issues

My plugin can't import interface

Hi, again.

Something strange happened in new version (0.5.0), when pnp import my plugin, my plugin fail to imports interface.

hugosenari@hugosenari:~/devel/git/dtc$ python -m dtc
DEBUG:root:no mainloop found
DEBUG:root:importing gobject
DEBUG:root:add dir: dtc/core/interfaces to path
DEBUG:root:add dir: dtc/core/interfaces/gui to path
DEBUG:root:add dir: dtc/modules to path
DEBUG:root:Set up plugnplay
DEBUG:root:Error loading plugin: logger
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/plugnplay-0.5.0-py2.7.egg/plugnplay/__init__.py", line 116, in _import_module
    imported_module = _import_from_python_package(_mod_name, mod_name)
  File "/usr/local/lib/python2.7/dist-packages/plugnplay-0.5.0-py2.7.egg/plugnplay/__init__.py", line 100, in _import_from_python_package
    locals=locals(), fromlist=[module])
  File "dtc/modules/logger.py", line 15, in <module>
    from dtc.core.interfaces import loggable
ImportError: cannot import name loggable
DEBUG:root:execute modules

You can download my code to test here

Download and run: python -m dtc

This is sys.path one line before import that fail:


(sys.path)
['dtc', 'dtc/core', 'dtc/core', 'dtc/core/interfaces', 'dtc/core/interfaces', 'dtc/core', 'dtc', 'dtc/core/interfaces', 'dtc/core', '', '/usr/local/lib/python2.7/dist-packages/pyenchant-1.6.5-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/d_feet-0.1.14-py2.7.egg', '/usr/local/lib/python2.7/dist-packages/plugnplay-0.5.0-py2.7.egg', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-linux2', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/lib/python2.7/lib-dynload', '/usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages/PIL', '/usr/lib/python2.7/dist-packages/gst-0.10', '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/usr/lib/python2.7/dist-packages/ubuntu-sso-client', '/usr/lib/python2.7/dist-packages/ubuntuone-client', '/usr/lib/python2.7/dist-packages/ubuntuone-control-panel', '/usr/lib/python2.7/dist-packages/ubuntuone-couch', '/usr/lib/python2.7/dist-packages/ubuntuone-installer', '/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol', '/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode']

Previous version (0.4.0) don't have this problem but have old problem that I can't import plugins with same file name. Then I update to this version (0.5.0 your trunk) and for some reason I can't import plugin because my plugin 'cant import interface.

Suggestions?

New way to call Interface implementors

Until now, we had to manually get all implementors of a given interface, like this:

 for impl in SomeInterface.implementors():
     impl.some_method()

Now we can call the method directly from the Interface itself. Suppose we have an Interface like this one:

class CopyChecker(plugnplay.Interface):

    def check(self, orig, dest):
        pass

We were used to write this purely for documentation, just to inform our implementors which methods they must implement.

Now we call all implementors like this:

CopyChecker.check(orig, dest)

This will have the very same effect of the for loop above.

Do not abort on loading error

Currently plugnplay does not load the modules inside a try/except block, this can cause serious problems. Also because of this, plugnplay stops loading on the first error.

The idea is to receive an optional logger as an parameter and use log.debug() do log any errors.

Standardize Plugin Load/Execution order

Plugins are currently found by iterating over the plugin director(y/ies) as specified in set_plugin_dirs, and then glob'ing them to find the .py files. Because glob.glob uses os.listdir, the order that plugins is found is arbitrary, http://docs.python.org/library/os.html#os.listdir

I propose a enhancement that standardizes the order in which plugins are loaded in the load_plugins method.

  1. iterate over plugin directories and build a complete py_files list of all plugins in all directories and then sorting those module names in alpha order.
  2. then walk the py_files list loading the modules in sorted order.

This would build each implementor list structure in a known order for repeat-ability of plugin execution order. Useful for those cases when a plugin does a transformation.

Additional tests would need to be created for this feature.

Impact to existing code: No impact would be expected since the plugins are currently loaded and executed in an arbitrary order. If they are currently relying on execution order, it is a latent bug in their code that will be exposed by this modification.

Future: This would set the stage to create a method of allowing a plugin to influence its position in the execution order. I'll submit another issue for that if this enhancement proposal is accepted.

Implement external python files loading

Implement automatic loading:

from plugnplay import Manager

Manager.load_files('/path/of/some/python/files')

With this code plugnplay will be able to load all python files inside any directory

Choose the order which Interface implementors will be executed

Currently, plugnplay executes all implementors of a given interface in the order they were loaded. Issue #5 garantees that the same set of plugins will be loaded in the same order, every time.

This issue will add the ability to choose, per implementor, the order of its execution among all other implementors of the same interface.

The first ideia is to add an order atribute to the implementor class declaration, like this:

class MyImplementor(plugnplay.Plugin):
    implements = [MyInterface,]
    order = 10

This would tell plungplay that this implementor would be the 10th in the list of implementors of MyInterface. If two plugins declares the same order value, they would be ordered alphabetically.

if you want to give a high precence to a specific implementor you will be able to use order = plugnplay.FIRST, if you want to push an implementor to the end of the execution chain, you will be able to use order = plugnplay.LAST.

This will define a global order, that is, one given implementor would have the same order in every Interface it implements. This issue could evolve to implement a way of choosing an order per implemented Interface.

Something on these lines:

class MyImplementor(plugnplay.Plugin):
    implements = [(MyInterface, 10), (OtherInterface, 2),]

Or like this:

class MyImplementor(plugnplay.Plugin):
    implements = [(MyInterface, 10), (OtherInterface, 2),]
    MyInterface_order = 10
    OtherInterface_order = 2

But this could lead to a problem if some interface changes name and we forget to update the *_order line accordingly.

Anyway, just ideas. =)

Incompatibility with py3k filter() function

In py3k, different from py2, the filter() function returns an filter object, not a list or tuple, etc.

With this, plugnplay breaks here:

def normalize_path(path):

Traceback (most recent call last):
  File "/home/daltonmatos/projetos/plugnplay/tests/common.py", line 17, in test_normalize_path_complex
    self.assertEquals('pnp.some.module.path', normalize_path('/some/module/path'))
  File "/home/daltonmatos/projetos/plugnplay/plugnplay/__init__.py", line 92, in normalize_path
    return '.'.join([PNP_SYS_MODULES_PREFIX] + parts)
TypeError: can only concatenate list (not "filter") to list

Modules from dirs with same name

Hi again,

That are something wrong when I try to import plugin for dirs that have same name already imported.

Something like this:

  • dtc
  • dtc/modules
  • dtc/modules/init.py
  • dtc/modules/foo.py
  • dtc_linux
  • dtc_linux/modules
  • dtc_linux/modules/init.py
  • dtc_linux/modules/bar.py

Foo are imported and bar

You can test with my code:
[email protected]:hugosenari/dtc.git

python -m dtc_linux

__init__ of a direct plugnplay.Plugin descending is called upon loading

Here it is:

class IFace(plugnplay.Interface):
    pass


class MyP(plugnplay.Plugin):

    def __init__(self):
        print "__init__()"


class Plyg(MyP):
    implements = [IFace]

    pass


print IFace.implementors()

When plugnplay is loading, it creates an instance of class MyP, which is not necessary since it does not implement any interface.

Maybe a good approach could be to create instances only for classes that have the implements = [...] attribute.

modules from different dirs but with same file name

For some reason, plugnplay can't import modules with same file name

Example:

/core/interface/runnable.Runnable (interface)
/modules/notify.Notify
/modules/maemo/notify.Notify (implements Runnable)

This don't work to me when want call runnable

only work when I changed
/modules/maemo/notify_maemo.NotifyMaemo (implements Runnable)

Hint: first I changed the class name, and don't work, then I changed file name.

[]'s

[Python 3.2] Unable to install 0.5.1 via pip or setup.py

In attempting to upgrade plugnplay 0.5.1 via pip (1.2.1) or setup.py (distribute 6.30) I get the following errors. Any suggestions on how to fix this? Or does the current version of plugnplay no longer support Python 3.x? Cheers

$ sudo pip-3.2 install plugnplay --upgrade

Downloading/unpacking plugnplay from http://pypi.python.org/packages/source/p/plugnplay/plugnplay-0.5.1.tar.gz#md5=d7aebad58acf6f0604bdd7d464c348e2
Downloading plugnplay-0.5.1.tar.gz
Running setup.py egg_info for package plugnplay
Traceback (most recent call last):
File "", line 16, in
File "/tmp/pip-build/plugnplay/setup.py", line 3, in
from plugnplay import __version__
File "plugnplay/init.py", line 79, in
Interface = InterfaceMeta('Interface', (object, ), {'implementors': implementors})
File "plugnplay/init.py", line 42, in __new__
for k, v in new_class.dict.iteritems():
AttributeError: 'dict_proxy' object has no attribute 'iteritems'
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "", line 16, in
File "/tmp/pip-build/plugnplay/setup.py", line 3, in
from plugnplay import __version__
File "plugnplay/init.py", line 79, in
Interface = InterfaceMeta('Interface', (object, ), {'implementors': implementors})
File "plugnplay/init.py", line 42, in new
for k, v in new_class.dict.iteritems():
AttributeError: 'dict_proxy' object has no attribute 'iteritems'

Command python setup.py egg_info failed with error code 1 in /tmp/pip-build/plugnplay
Storing complete log in /Users/adam/.pip/pip.log```

PnP does not run plugins that inherit a plugin without set implements again

Hi,

PnP does not run plugins that inherit a plugin without set 'implements' again

ie:

class Parent(Plugin)
    implement=[SomeInterface]

    def helloIm(self):
        print(self)

class Child(Parent)
    pass

The Child will be called only if I set implement

ie:

class Parent(Plugin)
    implement=[SomeInterface]

    def helloIm(self):
        print(self)

class Child(Parent)
    implement=[SomeInterface]

Broken egg: README.rst missing

When installing plugnplay 0.4.1 I get:

error: README.rst: No such file or directory

so it looks like the egg manifest is incomplete.

Add the ability to filter which implementors of an Interface will be returned

Currently plugnplay always returns all implementors of an Interface when you call MyInterface.implementors(). The idea of this issue is to be able to filter which implementors will be returned by this call.

The first idea would be to pass a callback to the implementors classmethod, something on the same line of Python's built-in filter function.

A simple example:

def callback(obj):
     return len(obj) > 5

MyInterface.implementors(callback)

Assuming that all implementors of MyInterface responds to the __len__ method, only implementors bigger than 5 would be returned by this call.

Another idea: implementors() could return a custom iterable object that has a filer() method. This way you could continue to have this code:

for impl in MyInterface.implementors():
    # code

but at the same time you could do this:

for impl in MyInterface.implementors().filter(callback):
    # code

to iterate on a filtered list of implementors.

plugnplay can't find implementors using different imports

Hi,

I'm trying something like this:

I have:
main.py
modules/module.py
modules/notifiable.py

In notifiable.py
class _CoreModule(Interface):

In plugin.py:

from module import _CoreModule

In main.py:

from modules.module import _CoreModule

In this case plugnplay, can't find module:

Manager.implementors vars:

self.iface_implementors = dict: {<class 'module._CoreModule'>: [<configurable._Notifiable object at 0x2416310>}
interface =       InterfaceMeta: <class 'modules.module._CoreModule'>

The key has same content (and came from same file) but, from different imports.

In my tests this is normal, because dict use hash to match keys, and namespace matters to hash function

import dbus
from dbus import Bus

hash(dbus.bus)
#3051581

hash(Bus)
#3070785

id(Bus)
#49132560

id(dbus.bus)
#48825296

cmp(Bus, dbus.Bus)
#0    ( maybe solve this problem )

[]'s

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.