Hello community,

here is the log from the commit of package python-Yapsy for openSUSE:Factory 
checked in at 2019-07-26 12:42:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Yapsy (Old)
 and      /work/SRC/openSUSE:Factory/.python-Yapsy.new.4126 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Yapsy"

Fri Jul 26 12:42:08 2019 rev:3 rq:718566 version:1.12.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Yapsy/python-Yapsy.changes        
2018-12-13 19:45:57.856893920 +0100
+++ /work/SRC/openSUSE:Factory/.python-Yapsy.new.4126/python-Yapsy.changes      
2019-07-26 12:42:12.237859736 +0200
@@ -1,0 +2,9 @@
+Thu Jul 25 13:31:48 UTC 2019 - [email protected]
+
+- version update to 1.12.0
+  * no upstream change log
+- deleted patches
+  - fix-error-plugin-test.patch (unneeded)
+  - fix-file-location-test.patch (unneeded)
+
+-------------------------------------------------------------------

Old:
----
  Yapsy-1.11.223.tar.gz
  fix-error-plugin-test.patch
  fix-file-location-test.patch

New:
----
  Yapsy-1.12.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-Yapsy.spec ++++++
--- /var/tmp/diff_new_pack.vqJ4RH/_old  2019-07-26 12:42:14.029858984 +0200
+++ /var/tmp/diff_new_pack.vqJ4RH/_new  2019-07-26 12:42:14.029858984 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-Yapsy
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,19 +17,14 @@
 
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
-%bcond_without test
 Name:           python-Yapsy
-Version:        1.11.223
+Version:        1.12.0
 Release:        0
 Summary:        Yet another plugin system
 License:        BSD-2-Clause
 Group:          Development/Languages/Python
 Url:            http://yapsy.sourceforge.net
-Source:         
https://files.pythonhosted.org/packages/source/Y/Yapsy/Yapsy-1.11.223.tar.gz
-# PATCH-FIX-OPENSUSE fix-file-location-test.patch [email protected] -- 
Fix file locations for tests
-Patch0:         fix-file-location-test.patch
-# PATCH-FIX-OPENSUSE fix-error-plugin-test.patch [email protected] -- 
Fix exception class for tests
-Patch1:         fix-error-plugin-test.patch
+Source:         
https://files.pythonhosted.org/packages/source/Y/Yapsy/Yapsy-%{version}.tar.gz
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
@@ -59,8 +54,6 @@
 
 %prep
 %setup -q -n Yapsy-%{version}
-%patch0
-%patch1
 
 %build
 %{python_build}
@@ -74,10 +67,8 @@
 %{python_install}
 %{python_expand %fdupes %{buildroot}%{$python_sitelib}}
 
-%if %{with test}
 %check
 %{python_exec setup.py test}
-%endif
 
 %files %{python_files}
 %{python_sitelib}/*

++++++ Yapsy-1.11.223.tar.gz -> Yapsy-1.12.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/PKG-INFO new/Yapsy-1.12.0/PKG-INFO
--- old/Yapsy-1.11.223/PKG-INFO 2015-06-25 20:35:47.000000000 +0200
+++ new/Yapsy-1.12.0/PKG-INFO   2018-09-02 18:41:16.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: Yapsy
-Version: 1.11.223
+Version: 1.12.0
 Summary: Yet another plugin system
 Home-page: http://yapsy.sourceforge.net
 Author: Thibauld Nion
@@ -38,6 +38,10 @@
           - Josip Delic (delijati)
           - frmdstryr
           - Pierre-Yves Langlois
+          - Guillaume Binet (gbin)
+          - Blake Oliver (Oliver2213)
+          - Xuecheng Zhang (csuzhangxc)
+          
         
         
         Contributions are welcome as pull requests, patches or tickets on the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/README.txt new/Yapsy-1.12.0/README.txt
--- old/Yapsy-1.11.223/README.txt       2015-04-19 14:39:05.000000000 +0200
+++ new/Yapsy-1.12.0/README.txt 2018-09-02 18:13:44.000000000 +0200
@@ -30,6 +30,10 @@
   - Josip Delic (delijati)
   - frmdstryr
   - Pierre-Yves Langlois
+  - Guillaume Binet (gbin)
+  - Blake Oliver (Oliver2213)
+  - Xuecheng Zhang (csuzhangxc)
+  
 
 
 Contributions are welcome as pull requests, patches or tickets on the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/Yapsy.egg-info/PKG-INFO 
new/Yapsy-1.12.0/Yapsy.egg-info/PKG-INFO
--- old/Yapsy-1.11.223/Yapsy.egg-info/PKG-INFO  2015-06-25 20:35:47.000000000 
+0200
+++ new/Yapsy-1.12.0/Yapsy.egg-info/PKG-INFO    2018-09-02 18:41:16.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: Yapsy
-Version: 1.11.223
+Version: 1.12.0
 Summary: Yet another plugin system
 Home-page: http://yapsy.sourceforge.net
 Author: Thibauld Nion
@@ -38,6 +38,10 @@
           - Josip Delic (delijati)
           - frmdstryr
           - Pierre-Yves Langlois
+          - Guillaume Binet (gbin)
+          - Blake Oliver (Oliver2213)
+          - Xuecheng Zhang (csuzhangxc)
+          
         
         
         Contributions are welcome as pull requests, patches or tickets on the
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/Yapsy.egg-info/SOURCES.txt 
new/Yapsy-1.12.0/Yapsy.egg-info/SOURCES.txt
--- old/Yapsy-1.11.223/Yapsy.egg-info/SOURCES.txt       2015-06-25 
20:35:47.000000000 +0200
+++ new/Yapsy-1.12.0/Yapsy.egg-info/SOURCES.txt 2018-09-02 18:41:16.000000000 
+0200
@@ -48,6 +48,7 @@
 test/test_settings.py
 test/plugins/ConfigPlugin.py
 test/plugins/ErroneousPlugin.py
+test/plugins/LegacyMultiprocessPlugin.py
 test/plugins/SimpleMultiprocessPlugin.py
 test/plugins/SimplePlugin.py
 test/plugins/VersionedPlugin10.py
@@ -58,6 +59,7 @@
 test/plugins/configplugin.yapsy-config-plugin
 test/plugins/configplugin.yapsy-filter-plugin
 test/plugins/erroneousplugin.yapsy-error-plugin
+test/plugins/legacymultiprocessplugin.multiprocess-plugin
 test/plugins/simplemultiprocessplugin.multiprocess-plugin
 test/plugins/simpleplugin.yapsy-filter-plugin
 test/plugins/simpleplugin.yapsy-plugin
@@ -78,6 +80,7 @@
 yapsy/ConfigurablePluginManager.py
 yapsy/FilteredPluginManager.py
 yapsy/IMultiprocessChildPlugin.py
+yapsy/IMultiprocessPlugin.py
 yapsy/IPlugin.py
 yapsy/IPluginLocator.py
 yapsy/MultiprocessPluginManager.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/setup.cfg new/Yapsy-1.12.0/setup.cfg
--- old/Yapsy-1.11.223/setup.cfg        2015-06-25 20:35:47.000000000 +0200
+++ new/Yapsy-1.12.0/setup.cfg  2018-09-02 18:41:16.000000000 +0200
@@ -1,5 +1,4 @@
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Yapsy-1.11.223/test/plugins/LegacyMultiprocessPlugin.py 
new/Yapsy-1.12.0/test/plugins/LegacyMultiprocessPlugin.py
--- old/Yapsy-1.11.223/test/plugins/LegacyMultiprocessPlugin.py 1970-01-01 
01:00:00.000000000 +0100
+++ new/Yapsy-1.12.0/test/plugins/LegacyMultiprocessPlugin.py   2018-09-02 
17:52:22.000000000 +0200
@@ -0,0 +1,19 @@
+# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t; python-indent: 4 -*-
+
+"""
+A simple multiprocessed plugin that echoes the content received to the parent
+"""
+
+from yapsy.IMultiprocessChildPlugin import IMultiprocessChildPlugin
+
+class LegacyMultiprocessPlugin(IMultiprocessChildPlugin):
+       """
+       Only trigger the expected test results.
+       """
+
+       def __init__(self, parent_pipe):
+               IMultiprocessChildPlugin.__init__(self, parent_pipe=parent_pipe)
+
+       def run(self):
+               content_from_parent = self.parent_pipe.recv()
+               
self.parent_pipe.send("{0}|echo_from_child".format(content_from_parent))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Yapsy-1.11.223/test/plugins/SimpleMultiprocessPlugin.py 
new/Yapsy-1.12.0/test/plugins/SimpleMultiprocessPlugin.py
--- old/Yapsy-1.11.223/test/plugins/SimpleMultiprocessPlugin.py 2015-03-28 
22:03:30.000000000 +0100
+++ new/Yapsy-1.12.0/test/plugins/SimpleMultiprocessPlugin.py   2018-09-02 
17:52:22.000000000 +0200
@@ -4,16 +4,17 @@
 A simple multiprocessed plugin that echoes the content received to the parent
 """
 
-from yapsy.IMultiprocessChildPlugin import IMultiprocessChildPlugin
+from yapsy.IMultiprocessPlugin import IMultiprocessPlugin
 
-class SimpleMultiprocessPlugin(IMultiprocessChildPlugin):
+class SimpleMultiprocessPlugin(IMultiprocessPlugin):
        """
        Only trigger the expected test results.
        """
 
        def __init__(self, parent_pipe):
-               IMultiprocessChildPlugin.__init__(self, parent_pipe=parent_pipe)
+               IMultiprocessPlugin.__init__(self, parent_pipe=parent_pipe)
 
        def run(self):
                content_from_parent = self.parent_pipe.recv()
                
self.parent_pipe.send("{0}|echo_from_child".format(content_from_parent))
+               
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Yapsy-1.11.223/test/plugins/legacymultiprocessplugin.multiprocess-plugin 
new/Yapsy-1.12.0/test/plugins/legacymultiprocessplugin.multiprocess-plugin
--- 
old/Yapsy-1.11.223/test/plugins/legacymultiprocessplugin.multiprocess-plugin    
    1970-01-01 01:00:00.000000000 +0100
+++ new/Yapsy-1.12.0/test/plugins/legacymultiprocessplugin.multiprocess-plugin  
2018-09-02 17:52:22.000000000 +0200
@@ -0,0 +1,9 @@
+[Core]
+Name = Legacy Multiprocess Plugin
+Module = LegacyMultiprocessPlugin
+
+[Documentation]
+Author = Pierre-Yves Langlois
+Version = 0.1
+Description = A minimal plugin to test multiprocessing
+Copyright = 2015
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/test/test_AutoInstallPlugin.py 
new/Yapsy-1.12.0/test/test_AutoInstallPlugin.py
--- old/Yapsy-1.11.223/test/test_AutoInstallPlugin.py   2015-03-28 
22:00:00.000000000 +0100
+++ new/Yapsy-1.12.0/test/test_AutoInstallPlugin.py     2018-09-02 
17:52:22.000000000 +0200
@@ -8,7 +8,6 @@
 
 from yapsy.AutoInstallPluginManager import AutoInstallPluginManager
 
-
 class AutoInstallTestsCase(unittest.TestCase):
        """
        Test the correct installation and loading of a simple plugin.
@@ -92,8 +91,9 @@
                Test getting and setting install dir.
                """
                
self.assertEqual(self.storing_dir,self.pluginManager.getInstallDir())
-               self.pluginManager.setInstallDir("mouf/bla")
-               self.assertEqual("mouf/bla",self.pluginManager.getInstallDir())
+               custom_install_dir = os.path.join("mouf", "bla")
+               self.pluginManager.setInstallDir(custom_install_dir)
+               self.assertEqual(custom_install_dir, 
self.pluginManager.getInstallDir())
                
                
        def testNoneLoaded(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/test/test_ErrorInPlugin.py 
new/Yapsy-1.12.0/test/test_ErrorInPlugin.py
--- old/Yapsy-1.11.223/test/test_ErrorInPlugin.py       2015-03-28 
22:00:14.000000000 +0100
+++ new/Yapsy-1.12.0/test/test_ErrorInPlugin.py 2017-01-29 18:44:25.000000000 
+0100
@@ -31,6 +31,9 @@
                callback_infos = []
                def preload_cbk(i_plugin_info):
                        callback_infos.append(i_plugin_info)
+               callback_after_infos = []
+               def postload_cbk(i_plugin_info):
+                       callback_after_infos.append(i_plugin_info)
                # - gather infos about the processed plugins (loaded or not)
                # and for the test, monkey patch the logger
                originalLogLevel = log.getEffectiveLevel()
@@ -41,7 +44,7 @@
                originalErrorMethod = log.error
                log.error = errorMock 
                try:
-                       loadedPlugins = spm.loadPlugins(callback=preload_cbk)
+                       loadedPlugins = spm.loadPlugins(callback=preload_cbk, 
callback_after=postload_cbk)
                finally:
                        log.setLevel(originalLogLevel)
                        log.error = originalErrorMethod
@@ -50,7 +53,8 @@
                self.assertEqual(len(callback_infos),1)
                self.assertTrue(isinstance(callback_infos[0].error,tuple))
                self.assertEqual(loadedPlugins[0],callback_infos[0])
-               self.assertEqual(callback_infos[0].error[0],ImportError)
+               
self.assertTrue(issubclass(callback_infos[0].error[0],ImportError))
+               self.assertEqual(len(callback_after_infos),0)
                # check that the getCategories works
                self.assertEqual(len(spm.getCategories()),1)
                sole_category = spm.getCategories()[0]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/test/test_PluginFileLocator.py 
new/Yapsy-1.12.0/test/test_PluginFileLocator.py
--- old/Yapsy-1.11.223/test/test_PluginFileLocator.py   2015-04-18 
22:48:35.000000000 +0200
+++ new/Yapsy-1.12.0/test/test_PluginFileLocator.py     2018-09-02 
17:52:22.000000000 +0200
@@ -8,6 +8,7 @@
 import tempfile
 import shutil
 
+import yapsy
 from yapsy import PLUGIN_NAME_FORBIDEN_STRING
 from yapsy.PluginManager import PluginManager
 from yapsy.PluginManager import IPlugin
@@ -60,7 +61,14 @@
                analyzer = PluginFileAnalyzerWithInfoFile("mouf")
                info_dict,cf_parser =  
analyzer.getInfosDictFromPlugin(self.plugin_directory,
                                                                                
                                           
os.path.basename(self.yapsy_plugin_path))
-               self.assertEqual(info_dict,{'website': 
'http://mathbench.sourceforge.net', 'description': 'A simple plugin usefull for 
basic testing', 'author': 'Thibauld Nion', 'version': '0.1', 'path': 
'%s/SimplePlugin' % self.plugin_directory, 'name': 'Simple Plugin', 
'copyright': '2014'})
+               self.assertEqual(info_dict,
+                                                {'website': 
'http://mathbench.sourceforge.net',
+                             'description': 'A simple plugin usefull for basic 
testing',
+                                                 'author': 'Thibauld Nion',
+                                                 'version': '0.1',
+                                                 'path': '%s' % 
os.path.join(self.plugin_directory,"SimplePlugin"),
+                                                 'name': 'Simple Plugin',
+                                                 'copyright': '2014'})
                self.assertTrue(isinstance(cf_parser,ConfigParser))
                
        def test_isValid_WithMultiExtensions(self):
@@ -192,8 +200,14 @@
        def test_default_plugins_place_is_parent_dir(self):
                """Test a non-trivial default behaviour introduced some time 
ago :S"""
                pl = PluginFileLocator()
-               self.assertTrue("package/yapsy" in pl.plugins_places[0])
+               expected_yapsy_module_path = os.path.dirname(yapsy.__file__)
+               first_plugin_place = pl.plugins_places[0]
+               self.assertEqual(expected_yapsy_module_path, first_plugin_place)
        
+       def test_given_string_as_plugin_places_raises_error(self):
+               pl = PluginFileLocator()
+               self.assertRaises(ValueError, pl.setPluginPlaces, "/mouf")
+
        def test_locatePlugins(self):
                pl = PluginFileLocator()
                pl.setPluginPlaces([self.plugin_directory])
@@ -207,7 +221,7 @@
                self.assertTrue(isinstance(candidates[0][2],PluginInfo))
                
        def test_locatePlugins_when_plugin_is_symlinked(self):
-               if "win" in sys.platform:
+               if sys.platform.startswith("win"):
                        return
                temp_dir = tempfile.mkdtemp()
                try:
@@ -244,7 +258,7 @@
                self.assertTrue(isinstance(candidates[0][2],PluginInfo))
        
        def test_locatePlugins_when_plugin_is_a_symlinked_directory(self):
-               if "win" in sys.platform:
+               if sys.platform.startswith("win"):
                        return
                temp_dir = tempfile.mkdtemp()
                try:
@@ -301,6 +315,8 @@
                        shutil.rmtree(temp_dir)
                        
        def 
test_locatePlugins_recursively_when_plugin_is_a_symlinked_directory(self):
+               if sys.platform.startswith("win"):
+                       return
                temp_dir = tempfile.mkdtemp()
                try:
                        temp_sub_dir = os.path.join(temp_dir,"plugins")
@@ -326,6 +342,8 @@
                        shutil.rmtree(temp_dir)
        
        def 
test_locatePlugins_recursively_when_plugin_parent_dir_is_a_symlinked_directory(self):
+               if sys.platform.startswith("win"):
+                       return
                # This actually reproduced the "Plugin detection doesn't follow 
symlinks" bug
                # at http://sourceforge.net/p/yapsy/bugs/19/
                temp_dir = tempfile.mkdtemp()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/test/test_SimpleMultiprocessPlugin.py 
new/Yapsy-1.12.0/test/test_SimpleMultiprocessPlugin.py
--- old/Yapsy-1.11.223/test/test_SimpleMultiprocessPlugin.py    2015-03-29 
00:26:07.000000000 +0100
+++ new/Yapsy-1.12.0/test/test_SimpleMultiprocessPlugin.py      2018-09-02 
17:52:22.000000000 +0200
@@ -29,17 +29,18 @@
                """
                Test if the plugin is loaded and if the communication pipe is 
properly setuped.
                """
-               numTestedPlugins = 0
-               for plugin in self.mpPluginManager.getAllPlugins():
-                       content_from_parent = "hello-from-parent"
+               for plugin_index, plugin in 
enumerate(self.mpPluginManager.getAllPlugins()):
+                       child_pipe = plugin.plugin_object.child_pipe
+                       content_from_parent = 
"hello-{0}-from-parent".format(plugin_index)
+                       child_pipe.send(content_from_parent)
                        content_from_child = False
-                       
plugin.plugin_object.child_pipe.send(content_from_parent)
-                       if plugin.plugin_object.child_pipe.poll(5):
-                               content_from_child = 
plugin.plugin_object.child_pipe.recv()
-                       self.assertEqual(content_from_child, 
"{0}|echo_from_child".format(content_from_parent))
-                       numTestedPlugins += 1
-               self.assertTrue(numTestedPlugins >= 1)
-
+                       if child_pipe.poll(5):
+                               content_from_child = child_pipe.recv()
+                       
self.assertEqual("{0}|echo_from_child".format(content_from_parent),
+                                                        content_from_child)
+               num_tested_plugin = plugin_index+1
+               self.assertEqual(2, num_tested_plugin)
+               
 suite = unittest.TestSuite([
                
unittest.TestLoader().loadTestsFromTestCase(SimpleMultiprocessTestCase),
                ])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/test/test_SimplePlugin.py 
new/Yapsy-1.12.0/test/test_SimplePlugin.py
--- old/Yapsy-1.11.223/test/test_SimplePlugin.py        2015-03-29 
00:26:34.000000000 +0100
+++ new/Yapsy-1.12.0/test/test_SimplePlugin.py  2018-09-02 17:52:22.000000000 
+0200
@@ -7,7 +7,9 @@
 from yapsy.PluginManager import PluginManager
 from yapsy.IPlugin import IPlugin
 from yapsy.PluginFileLocator import PluginFileLocator
+from yapsy.PluginFileLocator import IPluginFileAnalyzer
 from yapsy import NormalizePluginNameForModuleName
+from yapsy.compat import ConfigParser
 
 class YapsyUtils(unittest.TestCase):
 
@@ -179,12 +181,17 @@
                callback_infos = []
                def preload_cbk(plugin_info):
                        callback_infos.append(plugin_info)
+               callback_after_infos = []
+               def postload_cbk(plugin_info):
+                       callback_after_infos.append(plugin_info)
                # - gather infos about the processed plugins (loaded or not)
-               loadedPlugins = spm.loadPlugins(callback=preload_cbk)
+               loadedPlugins = spm.loadPlugins(callback=preload_cbk, 
callback_after=postload_cbk)
                self.assertEqual(len(loadedPlugins),1)
                self.assertEqual(len(callback_infos),1)
                self.assertEqual(loadedPlugins[0].error,None)
                self.assertEqual(loadedPlugins[0],callback_infos[0])
+               self.assertEqual(len(callback_after_infos),1)
+               self.assertEqual(loadedPlugins[0],callback_infos[0])
                # check that the getCategories works
                self.assertEqual(len(spm.getCategories()),1)
                sole_category = spm.getCategories()[0]
@@ -245,7 +252,34 @@
                spm.appendPluginToCategory(plugin_info, "Default")
                self.assertEqual(len(spm.getPluginsOfCategory("Default")),1)
                self.assertEqual(len(spm.getPluginsOfCategory("IP")),1)
-               
+
+       def testGetPluginOf(self):
+               """
+               Test the plugin query function.
+               """
+               spm = PluginManager(
+                       categories_filter = {
+                               "Default": IPlugin,
+                               "IP": IPlugin,
+                               },
+                       directories_list=[
+                               os.path.join(
+                                       
os.path.dirname(os.path.abspath(__file__)),"plugins")])
+               # load the plugins that may be found
+               spm.collectPlugins()
+               # check the getPluginsOfCategory
+               self.assertEqual(len(spm.getPluginsOf(categories="IP")), 1)
+               self.assertEqual(len(spm.getPluginsOf(categories="Default")), 1)
+               self.assertEqual(len(spm.getPluginsOf(name="Simple Plugin")), 1)
+               self.assertEqual(len(spm.getPluginsOf(is_activated=False)), 1)
+               self.assertEqual(len(spm.getPluginsOf(categories="IP", 
is_activated=True)), 0)
+               self.assertEqual(len(spm.getPluginsOf(categories="IP", 
is_activated=False)), 1)
+               self.assertEqual(len(spm.getPluginsOf(categories="IP", 
pouet=False)), 0)
+               self.assertEqual(len(spm.getPluginsOf(categories=["IP"])), 0)
+        # The order in the categories are added to plugin info is random in 
this setup, hence the strange formula below
+               self.assertEqual(len(spm.getPluginsOf(categories=["IP", 
"Default"]) | spm.getPluginsOf(categories=["Default", "IP"])), 1)
+               self.assertEqual(len(spm.getPluginsOf(category="Default") | 
spm.getPluginsOf(category="IP")), 1)
+
 class SimplePluginDetectionTestsCase(unittest.TestCase):
        """
        Test particular aspects of plugin detection
@@ -254,7 +288,7 @@
        def testRecursivePluginlocation(self):
                """
                Test detection of plugins which by default must be
-               recusrive. Here we give the test directory as a plugin place
+               recursive. Here we give the test directory as a plugin place
                whereas we expect the plugins to be in test/plugins.
                """
                spm = PluginManager(directories_list=[
@@ -309,6 +343,40 @@
                # check the getPluginsOfCategory
                self.assertEqual(len(spm.getPluginsOfCategory(sole_category)),1)
 
+       def testEnforcingPluginDirsDoesNotKeepDefaultDir(self):
+               """
+               Test that providing the directories list override the default 
search directory
+               instead of extending the default list.
+               """
+
+               class AcceptAllPluginFileAnalyzer(IPluginFileAnalyzer):
+
+                       def __init__(self):
+                               IPluginFileAnalyzer.__init__(self, "AcceptAll")
+                               
+                       def isValidPlugin(self, filename):
+                               return True
+
+                       def getInfosDictFromPlugin(self, dirpath, filename):
+                               return { "name": filename, "path": dirpath}, 
ConfigParser()
+                               
+               pluginLocator = PluginFileLocator()
+               pluginLocator.setAnalyzers([AcceptAllPluginFileAnalyzer()])
+
+               spm_default_dirs = PluginManager(plugin_locator= pluginLocator)
+               spm_default_dirs.locatePlugins()
+               candidates_in_default_dir = 
spm_default_dirs.getPluginCandidates()
+               candidates_files_in_default_dir = set([c[0] for c in 
candidates_in_default_dir])
+
+               pluginLocator = PluginFileLocator()
+               pluginLocator.setAnalyzers([AcceptAllPluginFileAnalyzer()])
+               spm = PluginManager(plugin_locator= pluginLocator,
+                                                       
directories_list=[os.path.dirname(os.path.abspath(__file__)),"does-not-exists"])
+               spm.locatePlugins()
+               candidates = spm.getPluginCandidates()
+               candidates_files = set([c[0] for c in candidates])
+
+               
self.assertFalse(set(candidates_files_in_default_dir).issubset(set(candidates_files)))
                
 suite = unittest.TestSuite([
                unittest.TestLoader().loadTestsFromTestCase(YapsyUtils),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/AutoInstallPluginManager.py 
new/Yapsy-1.12.0/yapsy/AutoInstallPluginManager.py
--- old/Yapsy-1.11.223/yapsy/AutoInstallPluginManager.py        2015-05-08 
22:35:28.000000000 +0200
+++ new/Yapsy-1.12.0/yapsy/AutoInstallPluginManager.py  2018-09-02 
17:52:22.000000000 +0200
@@ -179,8 +179,19 @@
                        if moduleName is None:
                                        continue
                        log.info("Checking existence of the expected module 
'%s' in the zip file" % moduleName)
-                       if moduleName in zipContent or 
os.path.join(moduleName,"__init__.py") in zipContent:
-                               isValid = True
+                       candidate_module_paths = [
+                               moduleName,
+                               # Try path consistent with the platform 
specific one
+                               os.path.join(moduleName,"__init__.py"),
+                               # Try typical paths (unix and windows)
+                               "%s/__init__.py" % moduleName,
+                               "%s\\__init__.py" % moduleName
+                               ]
+                       for candidate in candidate_module_paths:
+                               if candidate in zipContent:
+                                       isValid = True
+                                       break
+                       if isValid:
                                break
                if not isValid:
                        log.warning("Zip file structure seems wrong in '%s', "
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/ConfigurablePluginManager.py 
new/Yapsy-1.12.0/yapsy/ConfigurablePluginManager.py
--- old/Yapsy-1.11.223/yapsy/ConfigurablePluginManager.py       2015-05-08 
22:50:56.000000000 +0200
+++ new/Yapsy-1.12.0/yapsy/ConfigurablePluginManager.py 2017-01-29 
18:38:55.000000000 +0100
@@ -250,13 +250,13 @@
                                return plugin_object
                return None
 
-       def loadPlugins(self,callback=None):
+       def loadPlugins(self,callback=None, callback_after=None):
                """
                Walk through the plugins' places and look for plugins.  Then
                for each plugin candidate look for its category, load it and
                stores it in the appropriate slot of the ``category_mapping``.
                """
-               self._component.loadPlugins(callback)
+               self._component.loadPlugins(callback, callback_after)
                # now load the plugins according to the recorded configuration
                if self.config_parser.has_section(self.CONFIG_SECTION_NAME):
                        # browse all the categories
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/IMultiprocessChildPlugin.py 
new/Yapsy-1.12.0/yapsy/IMultiprocessChildPlugin.py
--- old/Yapsy-1.11.223/yapsy/IMultiprocessChildPlugin.py        2015-03-28 
21:57:17.000000000 +0100
+++ new/Yapsy-1.12.0/yapsy/IMultiprocessChildPlugin.py  2018-09-02 
17:52:22.000000000 +0200
@@ -5,41 +5,38 @@
 Role
 ====
 
-Defines the basic interfaces for multiprocessed plugins.
+Originally defined the basic interfaces for multiprocessed plugins.
 
-Extensibility
-=============
+Deprecation Note
+================
 
-In your own software, you'll probably want to build derived classes of
-the ``IMultiprocessChildPlugin`` class as it is a mere interface with no 
specific
-functionality.
+This class is deprecated and replaced by :doc:`IMultiprocessChildPlugin`.
 
-Your software's plugins should then inherit your very own plugin class
-(itself derived from ``IMultiprocessChildPlugin``).
+Child classes of `IMultiprocessChildPlugin` used to be an `IPlugin` as well as
+a `multiprocessing.Process`, possibly playing with the functionalities of both,
+which make maintenance harder than necessary.
 
-Override the run method to include your code. Use the self.parent_pipe to send
-and receive data with the parent process or create your own communication
-mecanism.
-
-Where and how to code these plugins is explained in the section about
-the :doc:`PluginManager`.
+And indeed following a bug fix to make multiprocess plugins work on Windows,
+instances of IMultiprocessChildPlugin inherit Process but are not exactly the
+running process (there is a new wrapper process).
 
 API
 ===
 """
 
 from multiprocessing import Process
-from yapsy.IPlugin import IPlugin
+from yapsy.IMultiprocessPlugin import IMultiprocessPlugin
 
 
-class IMultiprocessChildPlugin(IPlugin, Process):
+class IMultiprocessChildPlugin(IMultiprocessPlugin, Process):
        """
        Base class for multiprocessed plugin.
+
+       DEPRECATED(>1.11): Please use IMultiProcessPluginBase instead !
        """
 
        def __init__(self, parent_pipe):
-               self.parent_pipe = parent_pipe
-               IPlugin.__init__(self)
+               IMultiprocessPlugin.__init__(self, parent_pipe)
                Process.__init__(self)
 
        def run(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/IMultiprocessPlugin.py 
new/Yapsy-1.12.0/yapsy/IMultiprocessPlugin.py
--- old/Yapsy-1.11.223/yapsy/IMultiprocessPlugin.py     1970-01-01 
01:00:00.000000000 +0100
+++ new/Yapsy-1.12.0/yapsy/IMultiprocessPlugin.py       2018-09-02 
17:52:22.000000000 +0200
@@ -0,0 +1,47 @@
+# -*- coding: utf-8; tab-width: 4; indent-tabs-mode: t; python-indent: 4 -*-
+
+
+"""
+Role
+====
+
+Defines the basic interfaces for multiprocessed plugins.
+
+Extensibility
+=============
+
+In your own software, you'll probably want to build derived classes of
+the ``IMultiprocessPlugin`` class as it is a mere interface with no specific
+functionality.
+
+Your software's plugins should then inherit your very own plugin class
+(itself derived from ``IMultiprocessPlugin``).
+
+Override the `run` method to include your code. Use the `self.parent_pipe` to 
send
+and receive data with the parent process or create your own communication
+mecanism.
+
+Where and how to code these plugins is explained in the section about
+the :doc:`PluginManager`.
+
+API
+===
+"""
+
+from yapsy.IPlugin import IPlugin
+
+
+class IMultiprocessPlugin(IPlugin):
+       """
+       Base class for multiprocessed plugin.
+       """
+
+       def __init__(self, parent_pipe):
+               IPlugin.__init__(self)
+               self.parent_pipe = parent_pipe
+
+       def run(self):
+               """
+               Override this method in your implementation
+               """
+               return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/IPluginLocator.py 
new/Yapsy-1.12.0/yapsy/IPluginLocator.py
--- old/Yapsy-1.11.223/yapsy/IPluginLocator.py  2015-03-28 21:57:28.000000000 
+0100
+++ new/Yapsy-1.12.0/yapsy/IPluginLocator.py    2017-01-29 18:35:58.000000000 
+0100
@@ -60,7 +60,7 @@
                data *in a tuple*, if the required info could be
                localised, else return ``(None,None,None)``.
                """
-               log.warn("setPluginInfoClass was called but '%s' doesn't 
implement it." % self)
+               log.warning("setPluginInfoClass was called but '%s' doesn't 
implement it." % self)
                return None,None,None
        
 
@@ -72,7 +72,7 @@
                Set the class that holds PluginInfo. The class should inherit
                from ``PluginInfo``.
                """
-               log.warn("setPluginInfoClass was called but '%s' doesn't 
implement it." % self)
+               log.warning("setPluginInfoClass was called but '%s' doesn't 
implement it." % self)
 
        def getPluginInfoClass(self):
                """
@@ -81,7 +81,7 @@
                
                Get the class that holds PluginInfo.
                """
-               log.warn("getPluginInfoClass was called but '%s' doesn't 
implement it." % self)
+               log.warning("getPluginInfoClass was called but '%s' doesn't 
implement it." % self)
                return None
 
        def setPluginPlaces(self, directories_list):
@@ -91,7 +91,7 @@
                
                Set the list of directories where to look for plugin places.
                """
-               log.warn("setPluginPlaces was called but '%s' doesn't implement 
it." % self)
+               log.warning("setPluginPlaces was called but '%s' doesn't 
implement it." % self)
 
        def updatePluginPlaces(self, directories_list):
                """
@@ -100,5 +100,5 @@
                
                Updates the list of directories where to look for plugin places.
                """
-               log.warn("updatePluginPlaces was called but '%s' doesn't 
implement it." % self)
+               log.warning("updatePluginPlaces was called but '%s' doesn't 
implement it." % self)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/MultiprocessPluginManager.py 
new/Yapsy-1.12.0/yapsy/MultiprocessPluginManager.py
--- old/Yapsy-1.11.223/yapsy/MultiprocessPluginManager.py       2015-05-08 
22:37:29.000000000 +0200
+++ new/Yapsy-1.12.0/yapsy/MultiprocessPluginManager.py 2018-09-02 
17:52:22.000000000 +0200
@@ -14,6 +14,7 @@
 
 import multiprocessing as mproc
 
+from yapsy.IMultiprocessPlugin import IMultiprocessPlugin
 from yapsy.IMultiprocessChildPlugin import IMultiprocessChildPlugin
 from yapsy.MultiprocessPluginProxy import MultiprocessPluginProxy
 from yapsy.PluginManager import  PluginManager
@@ -22,7 +23,7 @@
 class MultiprocessPluginManager(PluginManager):
        """
        Subclass of the PluginManager that runs each plugin in a different 
process
-       """
+       """     
 
        def __init__(self,
                                 categories_filter=None,
@@ -30,26 +31,65 @@
                                 plugin_info_ext=None,
                                 plugin_locator=None):
                if categories_filter is None:
-                       categories_filter = {"Default": 
IMultiprocessChildPlugin}
+                       categories_filter = {"Default": IMultiprocessPlugin}
                PluginManager.__init__(self,
                                                                 
categories_filter=categories_filter,
                                                                 
directories_list=directories_list,
                                                                 
plugin_info_ext=plugin_info_ext,
                                                                 
plugin_locator=plugin_locator)
+               self.connections = []
 
-       def instanciateElement(self, element):
-               """
-               This method instanciate each plugin in a new process and link 
it to
+               
+       def instanciateElementWithImportInfo(self, element, element_name,
+                                                                               
 plugin_module_name, candidate_filepath):
+               """This method instanciates each plugin in a new process and 
links it to
                the parent with a pipe.
 
-               In the parent process context, the plugin's class is replaced 
by the ``MultiprocessPluginProxy``
-               class that hold the information about the child process and the 
pipe to communicate with it. See
-               :doc:`IMultiprocessChildPlugin`
+               In the parent process context, the plugin's class is replaced by
+               the ``MultiprocessPluginProxy`` class that hold the information
+               about the child process and the pipe to communicate with it.
+
+               :warning: The plugin code should only use the pipe to
+               communicate with the rest of the applica`tion and should not
+               assume any kind of shared memory, not any specific functionality
+               of the `multiprocessing.Process` parent class (its behaviour is
+               different between platforms !)
+               
+               See :doc:`IMultiprocessPlugin`
                """
+               if element is IMultiprocessChildPlugin:
+                       # The following will keep retro compatibility for 
IMultiprocessChildPlugin
+                       raise Exception("Preventing instanciation of a bar 
child plugin interface.")
                instanciated_element = MultiprocessPluginProxy()
                parent_pipe, child_pipe = mproc.Pipe()
-               instanciated_element.proc = element(child_pipe)
                instanciated_element.child_pipe = parent_pipe
+               instanciated_element.proc = 
MultiprocessPluginManager._PluginProcessWrapper(
+                       element_name, plugin_module_name, candidate_filepath,
+                       child_pipe)
                instanciated_element.proc.start()
                return instanciated_element
 
+
+       class _PluginProcessWrapper(mproc.Process):
+               """Helper class that strictly needed to be able to spawn the
+               plugin on Windows but kept also for Unix platform to get a more
+               uniform behaviour.
+
+               This will handle re-importing the plugin's module in the child
+               process (again this is necessary on windows because what has
+               been imported in the main thread/process will not be shared with
+               the spawned process.)
+               """
+               def __init__(self, element_name, plugin_module_name, 
candidate_filepath, child_pipe):
+                       self.element_name = element_name
+                       self.child_pipe = child_pipe
+                       self.plugin_module_name = plugin_module_name
+                       self.candidate_filepath = candidate_filepath
+                       mproc.Process.__init__(self)
+        
+               def run(self):
+                       module = 
PluginManager._importModule(self.plugin_module_name,
+                                                                               
                 self.candidate_filepath)
+                       element = getattr(module, self.element_name)
+                       e = element(self.child_pipe)
+                       e.run()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/PluginFileLocator.py 
new/Yapsy-1.12.0/yapsy/PluginFileLocator.py
--- old/Yapsy-1.11.223/yapsy/PluginFileLocator.py       2015-05-08 
22:55:16.000000000 +0200
+++ new/Yapsy-1.12.0/yapsy/PluginFileLocator.py 2018-09-02 17:52:22.000000000 
+0200
@@ -332,7 +332,7 @@
                self._analyzers = analyzers      # analyzers used to locate 
plugins
                if self._analyzers is None:
                        self._analyzers = 
[PluginFileAnalyzerWithInfoFile("info_ext")]
-               self._default_plugin_info_cls = PluginInfo
+               self._default_plugin_info_cls = plugin_info_cls
                self._plugin_info_cls_map = {}
                self._max_size = 1e3*1024 # in octets (by default 1 Mo)
                self.recursive = True
@@ -433,7 +433,7 @@
 #                                              print candidate_infofile
                                                plugin_info = 
self._getInfoForPluginFromAnalyzer(analyzer, dirpath, filename)
                                                if plugin_info is None:
-                                                       log.warning("Plugin 
candidate '%s'  rejected by strategy '%s'" % (candidate_infofile, 
analyzer.name))
+                                                       log.debug("Plugin 
candidate '%s'  rejected by strategy '%s'" % (candidate_infofile, 
analyzer.name))
                                                        break # we consider 
this was the good strategy to use for: it failed -> not a plugin -> don't try 
another strategy
                                                # now determine the path of the 
file to execute,
                                                # depending on wether the path 
indicated is a
@@ -514,6 +514,8 @@
                """
                Set the list of directories where to look for plugin places.
                """
+               if isinstance(directories_list, basestring):
+                       raise ValueError("'directories_list' given as a string, 
but expected to be a list or enumeration of strings")
                if directories_list is None:
                        directories_list = [os.path.dirname(__file__)]
                self.plugins_places = directories_list
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/PluginInfo.py 
new/Yapsy-1.12.0/yapsy/PluginInfo.py
--- old/Yapsy-1.11.223/yapsy/PluginInfo.py      2015-05-08 22:40:29.000000000 
+0200
+++ new/Yapsy-1.12.0/yapsy/PluginInfo.py        2017-01-29 20:58:27.000000000 
+0100
@@ -167,7 +167,7 @@
        def __setCategory(self,c):
                """
                DEPRECATED (>1.9): Mimic former behaviour by making so
-               that if a category is set as it it was the only category to
+               that if a category is set as if it were the only category to
                which the plugin belongs, then a __getCategory will return
                this newly set category.
                """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/PluginManager.py 
new/Yapsy-1.12.0/yapsy/PluginManager.py
--- old/Yapsy-1.11.223/yapsy/PluginManager.py   2015-05-08 22:43:22.000000000 
+0200
+++ new/Yapsy-1.12.0/yapsy/PluginManager.py     2018-09-02 17:52:22.000000000 
+0200
@@ -296,12 +296,15 @@
                """
                Sets the strategy used to locate the basic information.
 
+               .. note: If a dir_list is provided it overrides the directory 
list
+               that may have been previously set in the locator.
+
                See ``IPluginLocator`` for the policy that plugin_locator must 
enforce.
                """
                if isinstance(plugin_locator, IPluginLocator):
                        self._plugin_locator = plugin_locator
                        if dir_list is not None:
-                               
self._plugin_locator.updatePluginPlaces(dir_list)
+                               self._plugin_locator.setPluginPlaces(dir_list)
                        if picls is not None:
                                self.setPluginInfoClass(picls)
                else:
@@ -381,7 +384,7 @@
                Append a new plugin to the given category.
                """
                self.category_mapping[category_name].append(plugin)
-
+               
        def getPluginsOfCategory(self, category_name):
                """
                Return the list of all plugins belonging to a category.
@@ -397,6 +400,30 @@
                                allPlugins.update(pluginsOfOneCategory)
                return list(allPlugins)
 
+       def getPluginsOf(self, **kwargs):
+               """
+               Returns a set of plugins whose properties match the named 
arguments provided here along with their correspoding values.
+               """
+               selectedPLugins = set()
+               for plugin in self.getAllPlugins():
+                       for attrName in kwargs:
+                               if not hasattr(plugin, attrName):
+                                       break
+                               attrValue = kwargs[attrName]
+                               pluginValue = getattr(plugin, attrName)
+                               if pluginValue == attrValue:
+                                       continue
+                               if type(pluginValue) == type(attrValue):
+                                       break
+                               try:
+                                       if attrValue in pluginValue:
+                                               continue
+                               except:
+                                       break
+                       else:
+                               selectedPLugins.add(plugin)
+               return selectedPLugins
+       
        def getPluginCandidates(self):
                """
                Return the list of possible plugins.
@@ -442,16 +469,16 @@
                """
                self._candidates, npc = self.getPluginLocator().locatePlugins()
        
-       def loadPlugins(self, callback=None):
+       def loadPlugins(self, callback=None, callback_after=None):
                """
                Load the candidate plugins that have been identified through a
                previous call to locatePlugins.  For each plugin candidate
                look for its category, load it and store it in the appropriate
                slot of the ``category_mapping``.
 
-               If a callback function is specified, call it before every load
+               You can specify 2 callbacks: callback, and callback_after. If 
either of these are passed a function, (in the case of callback), it will get 
called before each plugin load attempt and (for callback_after), after each 
                attempt.  The ``plugin_info`` instance is passed as an argument 
to
-               the callback.
+               each callback. This is meant to facilitate code that needs to 
run for each plugin, such as adding the directory it resides in to sys.path (so 
imports of other files in the plugin's directory work correctly). You can use 
callback_after to remove anything you added to the path.
                """
 #              print "%s.loadPlugins" % self.__class__
                if not hasattr(self, '_candidates'):
@@ -480,28 +507,27 @@
                        if "__init__" in  os.path.basename(candidate_filepath):
                                candidate_filepath = 
os.path.dirname(candidate_filepath)
                        try:
-                               # use imp to correctly load the plugin as a 
module
-                               if os.path.isdir(candidate_filepath):
-                                       candidate_module = 
imp.load_module(plugin_module_name,None,candidate_filepath,("py","r",imp.PKG_DIRECTORY))
-                               else:
-                                       with open(candidate_filepath+".py","r") 
as plugin_file:
-                                               candidate_module = 
imp.load_module(plugin_module_name,plugin_file,candidate_filepath+".py",("py","r",imp.PY_SOURCE))
+                               candidate_module = 
PluginManager._importModule(plugin_module_name, candidate_filepath)
                        except Exception:
                                exc_info = sys.exc_info()
                                log.error("Unable to import plugin: %s" % 
candidate_filepath, exc_info=exc_info)
                                plugin_info.error = exc_info
                                processed_plugins.append(plugin_info)
                                continue
+
                        processed_plugins.append(plugin_info)
                        if "__init__" in  os.path.basename(candidate_filepath):
                                sys.path.remove(plugin_info.path)
                        # now try to find and initialise the first subclass of 
the correct plugin interface
-                       for element in (getattr(candidate_module,name) for name 
in dir(candidate_module)):
+                       last_failed_attempt_message = None
+                       for element, element_name in 
((getattr(candidate_module,name),name) for name in dir(candidate_module)):
                                plugin_info_reference = None
                                for category_name in self.categories_interfaces:
                                        try:
                                                is_correct_subclass = 
issubclass(element, self.categories_interfaces[category_name])
                                        except Exception:
+                                               exc_info = sys.exc_info()
+                                               log.debug("correct subclass 
tests failed for: %s in %s" % (element_name, candidate_filepath), 
exc_info=exc_info)
                                                continue
                                        if is_correct_subclass and element is 
not self.categories_interfaces[category_name]:
                                                        current_category = 
category_name
@@ -509,27 +535,68 @@
                                                                # we found a 
new plugin: initialise it and search for the next one
                                                                if not 
plugin_info_reference:
                                                                        try:
-                                                                               
plugin_info.plugin_object = self.instanciateElement(element)
+                                                                               
plugin_info.plugin_object = self.instanciateElementWithImportInfo(element, 
element_name, plugin_module_name, candidate_filepath)
                                                                                
plugin_info_reference = plugin_info
                                                                        except 
Exception:
                                                                                
exc_info = sys.exc_info()
-                                                                               
log.error("Unable to create plugin object: %s" % candidate_filepath, 
exc_info=exc_info)
+                                                                               
last_failed_attempt_message = "Unable to create plugin object: %s" % 
candidate_filepath
+                                                                               
log.debug(last_failed_attempt_message, exc_info=exc_info)
                                                                                
plugin_info.error = exc_info
                                                                                
break # If it didn't work once it wont again
+                                                                       else:
+                                                                               
last_failed_attempt_message = None
                                                                
plugin_info.categories.append(current_category)
                                                                
self.category_mapping[current_category].append(plugin_info_reference)
                                                                
self._category_file_mapping[current_category].append(candidate_infofile)
+                                                               #Everything is 
loaded and instantiated for this plugin now
+                                                               if 
callback_after is not None:
+                                                                       
callback_after(plugin_info)
+                       else:
+                               if last_failed_attempt_message:
+                                       log.error(last_failed_attempt_message, 
exc_info=plugin_info.error)
+                                       
                # Remove candidates list since we don't need them any more and
                # don't need to take up the space
                delattr(self, '_candidates')
                return processed_plugins
 
+       
+       @staticmethod
+       def _importModule(plugin_module_name, candidate_filepath):
+               """
+               Import a module, trying either to find it as a single file or 
as a directory.
+
+               :note: Isolated and provided to be reused, but not to be 
reimplemented !
+               """
+               # use imp to correctly load the plugin as a module
+               if os.path.isdir(candidate_filepath):
+                       candidate_module = 
imp.load_module(plugin_module_name,None,candidate_filepath,("py","r",imp.PKG_DIRECTORY))
+               else:
+                       with open(candidate_filepath+".py","r") as plugin_file:
+                               candidate_module = 
imp.load_module(plugin_module_name,plugin_file,candidate_filepath+".py",("py","r",imp.PY_SOURCE))
+               return candidate_module
+       
+       def instanciateElementWithImportInfo(self, element, element_name,
+                                                                               
 plugin_module_name, candidate_filepath):
+               """Override this method to customize how plugins are 
instanciated.
+               
+               :note: This methods recieves the 'element' that is a candidate
+               as the plugin's main file, but also enough information to reload
+               its containing module and this element.
+               """
+               return self.instanciateElement(element)
+       
        def instanciateElement(self, element):
                """
-               Override this method to customize how plugins are instanciated
+               DEPRECATED(>1.11): reimplement instead 
`instanciateElementWithImportInfo` !
+               
+               Override this method to customize how plugins are instanciated.
+
+               :warning: This method is called only if
+               `instanciateElementWithImportInfo` has not been reimplemented !
                """
                return element()
-
+       
        def collectPlugins(self):
                """
                Walk through the plugins' places and look for plugins.  Then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/VersionedPluginManager.py 
new/Yapsy-1.12.0/yapsy/VersionedPluginManager.py
--- old/Yapsy-1.11.223/yapsy/VersionedPluginManager.py  2015-05-08 
22:43:55.000000000 +0200
+++ new/Yapsy-1.12.0/yapsy/VersionedPluginManager.py    2017-01-29 
18:38:39.000000000 +0100
@@ -94,7 +94,7 @@
                """
                return self.getPluginsOfCategory(category_name)
        
-       def loadPlugins(self, callback=None):
+       def loadPlugins(self, callback=None, callback_after=None):
                """
                Load the candidate plugins that have been identified through a
                previous call to locatePlugins.
@@ -103,7 +103,7 @@
                needs to find the latest version of each plugin.
                """
                self._prepareAttic()
-               self._component.loadPlugins(callback)
+               self._component.loadPlugins(callback, callback_after)
                for categ in self.getCategories():
                        latest_plugins = {}
                        allPlugins = self.getPluginsOfCategory(categ)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Yapsy-1.11.223/yapsy/__init__.py 
new/Yapsy-1.12.0/yapsy/__init__.py
--- old/Yapsy-1.11.223/yapsy/__init__.py        2015-06-25 20:29:24.000000000 
+0200
+++ new/Yapsy-1.12.0/yapsy/__init__.py  2018-09-02 18:23:56.000000000 +0200
@@ -52,7 +52,7 @@
 
 """
 
-__version__="1.11.223"
+__version__="1.12.0"
 
 # tell epydoc that the documentation is in the reStructuredText format
 __docformat__ = "restructuredtext en"


Reply via email to