conduit r1214 - in trunk: . conduit conduit/dataproviders conduit/gtkui conduit/hildonui scripts test/python-tests



Author: jstowers
Date: Mon Jan 14 10:10:07 2008
New Revision: 1214
URL: http://svn.gnome.org/viewvc/conduit?rev=1214&view=rev

Log:
2008-01-14  John Stowers  <john stowers gmail com>

	* conduit/ModuleWrapper.py: Refactor to use keyword args in the constructor

	* conduit/DBus.py:
	* conduit/Module.py:
	* conduit/SyncSet.py:
	* conduit/dataproviders/DataProvider.py:
	* conduit/gtkui/Tree.py:
	* conduit/hildonui/UI.py:
	* test/python-tests/TestSyncTomboyiPod.py:
	* test/python-tests/common.py: Update to new ModuleWrapper API
	
	* conduit/gtkui/UI.py: Display files that failed to load in the prefs window
	
	* scripts/build-svn-packages.sh: Fix repo url



Modified:
   trunk/ChangeLog
   trunk/conduit/DBus.py
   trunk/conduit/Module.py
   trunk/conduit/ModuleWrapper.py
   trunk/conduit/SyncSet.py
   trunk/conduit/dataproviders/DataProvider.py
   trunk/conduit/gtkui/Tree.py
   trunk/conduit/gtkui/UI.py
   trunk/conduit/hildonui/UI.py
   trunk/scripts/build-svn-packages.sh
   trunk/test/python-tests/TestSyncTomboyiPod.py
   trunk/test/python-tests/common.py

Modified: trunk/conduit/DBus.py
==============================================================================
--- trunk/conduit/DBus.py	(original)
+++ trunk/conduit/DBus.py	Mon Jan 14 10:10:07 2008
@@ -457,12 +457,12 @@
         @param key: Key of the DP to create
         @returns: The new DP
         """
-        dp = self.moduleManager.get_new_module_instance(key)
-        if dp == None:
+        dpw = self.moduleManager.get_module_wrapper_with_instance(key)
+        if dpw == None:
             raise ConduitException("Could not find dataprovider with key: %s" % key)
 
         i = Utils.uuid_string()
-        new = DataProviderDBusItem(dp, i)
+        new = DataProviderDBusItem(dpw, i)
         EXPORTED_OBJECTS[new.get_path()] = new
         return new
 

Modified: trunk/conduit/Module.py
==============================================================================
--- trunk/conduit/Module.py	(original)
+++ trunk/conduit/Module.py	Mon Jan 14 10:10:07 2008
@@ -52,6 +52,8 @@
         #Stored seperate to the classes because dynamic dataproviders may
         #use the same class but with different initargs (diff keys)
         self.moduleWrappers = {}
+        #Files that could not be loaded properly
+        self.invalidFiles = []
         #Keep a ref to dataprovider factories so they are not collected
         self.dataproviderFactories = []
         #scan all dirs for files in the right format (*Module/*Module.py)
@@ -174,65 +176,60 @@
         Primarily for internal use. Note that the python module returned may actually
         contain several more loadable modules.
         """
-        try:
-            mods = pydoc.importfile (filename)
-        except Exception:
-            log.warn("Error loading the file: %s.\n%s" % (filename, traceback.format_exc()))
-            return
-
+        mods = pydoc.importfile (filename)
         try:
             if (mods.MODULES): pass
         except AttributeError:
             log.warn("The file %s is not a valid module. Skipping." % (filename))
             log.warn("A module must have the variable MODULES defined as a dictionary.")
-            return
-
+            raise
         for modules, infos in mods.MODULES.items():
             for i in ModuleWrapper.COMPULSORY_ATTRIBUTES:
                 if i not in infos:
                     log.warn("Class %s in file %s does define a %s attribute. Skipping." % (modules, filename, i))
-                    return
-
+                    raise Exception
         return mods
         
     def _load_modules_in_file(self, filename):
         """
         Loads all modules in the given file
         """
-        mod = self._import_file(filename)
-        if mod is None:
-            return
-
-        for modules, infos in mod.MODULES.items():
-            try:
-                klass = getattr(mod, modules)
-
-                if infos["type"] == "dataprovider" or infos["type"] == "converter":
-                    mod_wrapper = ModuleWrapper (   
-                                        getattr(klass, "_name_", ""),
-                                        getattr(klass, "_description_", ""),
-                                        getattr(klass, "_icon_", ""),
-                                        getattr(klass, "_module_type_", infos["type"]),
-                                        getattr(klass, "_category_", CATEGORY_TEST),
-                                        getattr(klass, "_in_type_", ""),
-                                        getattr(klass, "_out_type_", ""),
-                                        klass.__name__,     #classname
-                                        (),                 #Init args
-                                        )
-                    #Save the module (signal is emitted _append_module
-                    self._append_module(mod_wrapper, klass)
-                elif infos["type"] == "dataprovider-factory":
-                    # build a dict of kwargs to pass to factories
-                    kwargs = {
-                        "moduleManager": self,
-                    }
-                    #instantiate and store the factory
-                    instance = klass(**kwargs)
-                    self.dataproviderFactories.append(instance)
-                else:
-                    log.warn("Class %s is an unknown type: %s" % (klass.__name__, infos["type"]))
-            except AttributeError:
-                log.warn("Could not find module %s in %s\n%s" % (modules,filename,traceback.format_exc()))
+        try:
+            mod = self._import_file(filename)
+            for modules, infos in mod.MODULES.items():
+                try:
+                    klass = getattr(mod, modules)
+                    if infos["type"] == "dataprovider" or infos["type"] == "converter":
+                        mod_wrapper = ModuleWrapper(   
+                                            name=getattr(klass, "_name_", ""),
+                                            description=getattr(klass, "_description_", ""),
+                                            icon_name=getattr(klass, "_icon_", ""),
+                                            module_type=getattr(klass, "_module_type_", infos["type"]),
+                                            category=getattr(klass, "_category_", CATEGORY_TEST),
+                                            in_type=getattr(klass, "_in_type_", ""),
+                                            out_type=getattr(klass, "_out_type_", ""),
+                                            filename=filename,
+                                            classname=klass.__name__,
+                                            initargs=(),
+                                            enabled=True
+                                            )
+                        #Save the module (signal is emitted _append_module
+                        self._append_module(mod_wrapper, klass)
+                    elif infos["type"] == "dataprovider-factory":
+                        # build a dict of kwargs to pass to factories
+                        kwargs = {
+                            "moduleManager": self,
+                        }
+                        #instantiate and store the factory
+                        instance = klass(**kwargs)
+                        self.dataproviderFactories.append(instance)
+                    else:
+                        log.warn("Class %s is an unknown type: %s" % (klass.__name__, infos["type"]))
+                except AttributeError:
+                    log.warn("Could not find module %s in %s\n%s" % (modules,filename,traceback.format_exc()))
+        except Exception, e:
+            log.warn("Error loading the file: %s.\n%s" % (filename, traceback.format_exc()))
+            self.invalidFiles.append(os.path.basename(filename))
 
     def _instantiate_class(self, classname, initargs):
         if type(initargs) != tuple:
@@ -265,28 +262,18 @@
         """
         return self.moduleWrappers.values()
         
-    def get_modules_by_type(self, type_filter):
+    def get_modules_by_type(self, *type_filter):
         """
         Returns all loaded modules of type specified by type_filter 
         or all if the filter is set to None.
-        
-        @rtype: L{conduit.ModuleManager.ModuleWrapper}[]
-        @returns: A list of L{conduit.ModuleManager.ModuleWrapper}
         """
-        if type_filter is None:
+        if len(type_filter) == 0:
             return self.moduleWrappers.values()
-        else:
-            #sorry about the one-liner
-            return [i for i in self.moduleWrappers.values() if i.module_type == type_filter]
+        return [i for i in self.moduleWrappers.values() if i.module_type in type_filter]
             
-    def get_new_module_instance(self, wrapperKey):
+    def get_module_wrapper_with_instance(self, wrapperKey):
         """
-        Returns a new instance ModuleWrapper specified by name
-        
-        @param classname: Classname of the module to get
-        @type classname: C{string}
-        @returns: An newly instanciated ModuleWrapper
-        @rtype: a L{conduit.Module.ModuleWrapper}
+        Returns a new ModuleWrapper with a dp instace described by wrapperKey
         """
         mod_wrapper = None
     
@@ -297,18 +284,19 @@
             classname = m.classname
             initargs = m.initargs
             mod_wrapper = ModuleWrapper(  
-                                        m.name, 
-                                        m.description,
-                                        m.icon_name, 
-                                        m.module_type, 
-                                        m.category, 
-                                        m.in_type,
-                                        m.out_type,
-                                        classname,
-                                        initargs,
-                                        self._instantiate_class(classname, initargs),
-                                        True)
-                
+                                name=m.name, 
+                                description=m.description,
+                                icon_name=m.icon_name, 
+                                module_type=m.module_type, 
+                                category=m.category, 
+                                in_type=m.in_type,
+                                out_type=m.out_type,
+                                filename=m.filename,
+                                classname=classname,
+                                initargs=initargs,
+                                module=self._instantiate_class(classname, initargs),
+                                enabled=True
+                                )
         else:
             log.warn("Could not find module wrapper: %s" % (wrapperKey))
             mod_wrapper = PendingDataproviderWrapper(wrapperKey)

Modified: trunk/conduit/ModuleWrapper.py
==============================================================================
--- trunk/conduit/ModuleWrapper.py	(original)
+++ trunk/conduit/ModuleWrapper.py	Mon Jan 14 10:10:07 2008
@@ -8,31 +8,6 @@
     of a stored L{conduit.DataProvider.DataProvider} behind additional
     descriptive fields like name and description. Useful for classification 
     and searching for moldules of certain types, etc.
-    
-    @ivar name: The name of the contained module
-    @type name: C{string}
-    @ivar description: The description of the contained module
-    @type description: C{string}
-    @ivar module_type: The type of the contained module (e.g. sink, source)
-    @type module_type: C{string}
-    @ivar category: The category of the contained module
-    @type category: C{string}
-    @ivar in_type: The name of the datatype that the module accepts (put())
-    @type in_type: C{string}
-    @ivar out_type: The name of the datatype that the module produces (get())
-    @type out_type: C{string}        
-    @ivar classname: The classname used to instanciate another
-    modulewrapper of type C{module} contained in C{filename}
-    @type classname: C{string}
-    @ivar initargs: The arguments the module was initialised with
-    @type initargs: C{tuple}
-    @ivar module: The name of the contained module
-    @type module: L{conduit.DataProvider.DataProvider} or derived class     
-    @ivar enabled: Whether the call to the modules initialize() method was
-    successful or not. 
-    @type enabled: C{bool}    
-    @ivar icon: An icon representing this wrapper or the module it holds
-    @type icon: C{pixbuf}
     """
     
     NUM_UID_DIGITS = 5
@@ -40,55 +15,49 @@
                             "type"
                             ]
     	
-    def __init__ (self, name, description, icon, module_type, category, in_type, out_type, classname, initargs, module=None, enabled=True):
+    def __init__ (self, **kwargs):
         """
         Constructor for ModuleWrapper. A convenient wrapper around a dynamically
         loaded module.
         
-        @param name: The name of the contained module
-        @type name: C{string}
-        @param description: The description of the contained module
-        @type description: C{string}
-        @param module_type: The type of the contained module (e.g. sink, source)
-        @type module_type: C{string}
-        @param category: The category of the contained module
-        @type category: C{string}
-        @param in_type: The name of the datatype that the module accepts (put())
-        @type in_type: C{string}
-        @param out_type: The name of the datatype that the module produces (get())
-        @type out_type: C{string}        
-        @param classname: The classname used to instanciate another
-        modulewrapper of type C{module} contained in C{filename}
-        @type classname: C{string}
-        @param filename: The arguments the module was initialised with
-        @type filename: C{tuple}
-        @param module: The name of the contained module
-        @type module: L{conduit.DataProvider.DataProvider} or derived class     
-        @param enabled: Whether the call to the modules initialize() method was
-        successful or not. 
-        @type enabled: C{bool}
-        """
-        self.name = name
-        self.description = description 
-        self.icon_name = icon       
-        self.module_type = module_type
-        self.category = category
-        self.in_type = in_type
-        self.out_type = out_type
-        self.classname = classname
+        @keyword name: The name of the contained module
+        @keyword description: The description of the contained module
+        @keyword icon_name: The name of an icon representing the contained module
+        @keyword module_type: The type of the contained module (e.g. sink, source)
+        @keyword category: The category of the contained module
+        @keyword in_type: The name of the datatype that the module accepts (put())
+        @keyword out_type: The name of the datatype that the module produces (get())
+        @keyword filename: The filename from which the module was loaded
+        @keyword classname: The classname used to instanciate another module instance
+        @keyword initargs: The arguments passed to the new module if created
+        @keyword module: An instance of the described module
+        @keyword loaded: Whether the module was loaded corectly 
+        """
+        self.name =                 kwargs.get("name","")
+        self.description =          kwargs.get("description","")
+        self.icon_name =            kwargs.get("icon_name","image-missing")
+        self.module_type =          kwargs.get('module_type',"twoway")
+        self.category =             kwargs.get('category',"")
+        self.in_type =              kwargs.get('in_type',"")
+        self.out_type =             kwargs.get('out_type',"")
+        self.filename =             kwargs.get('filename',"")
+        self.classname =            kwargs.get('classname',"")
+        self.initargs =             kwargs.get('initargs',())
+        self.module =               kwargs.get('module',None)
+        self.enabled =              kwargs.get('enabled',True)
+
         #Initargs must be a tuple or a list for get_key() to work
-        if type(initargs) == tuple:
-            self.initargs = initargs
-        else:
-            log.warn("INIT ARGS MUST BE A TUPLE (was a %s)" % type(initargs))
-            self.initargs = ()
-        self.module = module
-        self.enabled = enabled
+        if type(self.initargs) != tuple:
+            log.warn("init args must be a tuple (was:%s type:%s)" % (self.initargs,type(self.initargs)))
+            raise Exception
         
         self.icon_path = ""
         self.icon = {}
         self.descriptiveIcon = None
 
+    def __str__(self):
+        return "Wrapper: %s %s (UID: %s)" % (self.get_name(), self.module_type, self.get_UID())
+
     def get_key(self):
         """
         Returns a string in the form of classname:initarg0:initarg1:...
@@ -244,9 +213,6 @@
     
         return self.descriptiveIcon
         
-    def __str__(self):
-        return "Wrapper: %s %s (UID: %s)" % (self.name, self.module_type, self.get_UID())
-
     def set_configuration_xml(self, xmltext):
         self.module.set_configuration_xml(xmltext)
 
@@ -260,20 +226,17 @@
     def __init__(self, key):
         ModuleWrapper.__init__(
                     self,
-                    "", 
-                    "",
-                    "gtk-missing",          #use a missing image
-                    "twoway",               #twoway so can placehold as source or sink
-                    "", 
-                    "",
-                    "",
-                    key.split(':')[0],
-                    (),
-                    None,                   #module is None. 
-                    False)                  #enabled = False so a sync is not performed
+                    module_type="twoway",
+                    classname=key.split(':')[0],
+                    module=None,
+                    enabled=False
+                    )
         self.key = key
         self.xmltext = ""
 
+    def __str__(self):
+        return "PendingWrapper Key: %s" % self.get_key()
+
     def get_key(self):
         return self.key
 
@@ -283,7 +246,4 @@
     def get_configuration_xml(self):
         return self.xmltext
 
-    def __str__(self):
-        return "PendingWrapper Key: %s" % self.get_key()
-
 

Modified: trunk/conduit/SyncSet.py
==============================================================================
--- trunk/conduit/SyncSet.py	(original)
+++ trunk/conduit/SyncSet.py	Mon Jan 14 10:10:07 2008
@@ -54,7 +54,7 @@
         location and configures it with the given settings
         """
         log.debug("Restoring %s to (source=%s)" % (wrapperKey,trySourceFirst))
-        wrapper = self.moduleManager.get_new_module_instance(wrapperKey)
+        wrapper = self.moduleManager.get_module_wrapper_with_instance(wrapperKey)
         wrapper.set_name(dpName)
         if wrapper is not None:
             for i in dpxml.childNodes:
@@ -69,7 +69,7 @@
         key = dpw.get_key()
         for c in self.get_all_conduits():
             for dp in c.get_dataproviders_by_key(key):
-                new = self.moduleManager.get_new_module_instance(key)
+                new = self.moduleManager.get_module_wrapper_with_instance(key)
                 #retain configuration information
                 new.set_configuration_xml(dp.get_configuration_xml())
                 new.set_name(dp.get_name())

Modified: trunk/conduit/dataproviders/DataProvider.py
==============================================================================
--- trunk/conduit/dataproviders/DataProvider.py	(original)
+++ trunk/conduit/dataproviders/DataProvider.py	Mon Jan 14 10:10:07 2008
@@ -502,16 +502,19 @@
     def emit_added(self, klass, initargs=(), category=None):
         if category == None:
             category = getattr(klass, "_category_", conduit.dataproviders.CATEGORY_TEST)
-        dpw = ModuleWrapper.ModuleWrapper (   
-                    getattr(klass, "_name_", ""),
-                    getattr(klass, "_description_", ""),
-                    getattr(klass, "_icon_", ""),
-                    getattr(klass, "_module_type_", ""),
-                    category,
-                    getattr(klass, "_in_type_", ""),
-                    getattr(klass, "_out_type_", ""),
-                    klass.__name__,     #classname
-                    initargs,
+        dpw = ModuleWrapper.ModuleWrapper(   
+                    name=getattr(klass, "_name_", ""),
+                    description=getattr(klass, "_description_", ""),
+                    icon_name=getattr(klass, "_icon_", ""),
+                    module_type=getattr(klass, "_module_type_", ""),
+                    category=category,
+                    in_type=getattr(klass, "_in_type_", ""),
+                    out_type=getattr(klass, "_out_type_", ""),
+                    filename=__file__,
+                    classname=klass.__name__,
+                    initargs=initargs,
+                    module=None,
+                    enabled=True
                     )
         log.debug("DataProviderFactory %s: Emitting dataprovider-available for %s" % (self, dpw.get_key()))
         self.emit("dataprovider-available", dpw, klass)

Modified: trunk/conduit/gtkui/Tree.py
==============================================================================
--- trunk/conduit/gtkui/Tree.py	(original)
+++ trunk/conduit/gtkui/Tree.py	Mon Jan 14 10:10:07 2008
@@ -27,18 +27,11 @@
     def __init__(self, category):
         ModuleWrapper.__init__(
                             self,
-                            category.name,  #name: shows in name column
-                            None,           #description: shows in description column
-                            category.icon,  #icon name
-                            "category",     #module_type: used to cancel drag and drop
-                            category,       #category: untranslated version on Name 
-                            None,           #in_type: N/A
-                            None,           #out_type: N/A
-                            None,           #classname: N/A
-                            (),             #initargs: N/A
-                            category,       #object instance: N/A
-                            True)           #enabled: True but N/A
-
+                            name=category.name,
+                            icon_name=category.icon,
+                            module_type="category",
+                            category=category
+                            )
        
 class DataProviderTreeModel(gtk.GenericTreeModel):
     """

Modified: trunk/conduit/gtkui/UI.py
==============================================================================
--- trunk/conduit/gtkui/UI.py	(original)
+++ trunk/conduit/gtkui/UI.py	Mon Jan 14 10:10:07 2008
@@ -239,12 +239,12 @@
             string = "%s %s %s %s" % (CONVERT_FROM_MESSAGE, froms, CONVERT_INTO_MESSAGE, tos)
             converterListStore.append( (string,) )
         dataProviderListStore = gtk.ListStore( str, bool )
-        for i in self.moduleManager.get_modules_by_type("sink"):
-            dataProviderListStore.append(("Name: %s\nDescription: %s\n(type:%s in:%s out:%s)" % (i.name, i.description, i.module_type, i.get_input_type(), i.get_output_type()), i.enabled))
-        for i in self.moduleManager.get_modules_by_type("source"):
-            dataProviderListStore.append(("Name: %s\nDescription: %s\n(type:%s in:%s out:%s)" % (i.name, i.description, i.module_type, i.get_input_type(), i.get_output_type()), i.enabled))
-        for i in self.moduleManager.get_modules_by_type("twoway"):
-            dataProviderListStore.append(("Name: %s\nDescription: %s\n(type:%s in:%s out:%s)" % (i.name, i.description, i.module_type, i.get_input_type(), i.get_output_type()), i.enabled))
+        #get all dataproviders
+        for i in self.moduleManager.get_modules_by_type("sink","source","twoway"):
+            dataProviderListStore.append(("Name: %s\nDescription: %s)" % (i.name, i.description), True))
+        #include files that could not be loaded
+        for f in self.moduleManager.invalidFiles:
+            dataProviderListStore.append(("Error loading file: %s" % f, False))
 
         #construct the dialog
         tree = gtk.glade.XML(self.gladeFile, "PreferencesDialog")
@@ -296,7 +296,7 @@
                                         gtk.CellRendererText(), 
                                         text=0)
                                         )                                                   
-        dataproviderTreeView.append_column(gtk.TreeViewColumn(_("Enabled"), 
+        dataproviderTreeView.append_column(gtk.TreeViewColumn(_("Loaded"), 
                                         gtk.CellRendererToggle(), 
                                         active=1)
                                         )                                        
@@ -420,7 +420,7 @@
         #signal and NOT here
         if dataproviderKey != "":
             #Add a new instance if the dataprovider to the canvas.
-            new = self.moduleManager.get_new_module_instance(dataproviderKey)
+            new = self.moduleManager.get_module_wrapper_with_instance(dataproviderKey)
             self.canvas.add_dataprovider_to_canvas(dataproviderKey, new, x, y)
         
         context.finish(True, True, etime)

Modified: trunk/conduit/hildonui/UI.py
==============================================================================
--- trunk/conduit/hildonui/UI.py	(original)
+++ trunk/conduit/hildonui/UI.py	Mon Jan 14 10:10:07 2008
@@ -112,7 +112,7 @@
         #signal and NOT here
         if dataproviderKey != "":
             #Add a new instance if the dataprovider to the canvas.
-            new = self.moduleManager.get_new_module_instance(dataproviderKey)
+            new = self.moduleManager.get_module_wrapper_with_instance(dataproviderKey)
             self.canvas.add_dataprovider_to_canvas(dataproviderKey, new, x, y)
         
         context.finish(True, True, etime)

Modified: trunk/scripts/build-svn-packages.sh
==============================================================================
--- trunk/scripts/build-svn-packages.sh	(original)
+++ trunk/scripts/build-svn-packages.sh	Mon Jan 14 10:10:07 2008
@@ -31,7 +31,7 @@
 
 # First checkout trunk so that the SVN version can be determined.
 # This could be done a nicer way like using pysvn perhaps?
-svn co --non-interactive https://svn.gnome.org/conduit/trunk conduit
+svn co --non-interactive http://svn.gnome.org/svn/conduit/trunk conduit
 cd conduit
 
 SVNREV=`svnversion .`

Modified: trunk/test/python-tests/TestSyncTomboyiPod.py
==============================================================================
--- trunk/test/python-tests/TestSyncTomboyiPod.py	(original)
+++ trunk/test/python-tests/TestSyncTomboyiPod.py	Mon Jan 14 10:10:07 2008
@@ -10,7 +10,6 @@
 
 from conduit.datatypes import COMPARISON_EQUAL
 from conduit.modules import iPodModule
-from conduit.ModuleWrapper import ModuleWrapper
 
 #setup the test
 test = SimpleSyncTest()

Modified: trunk/test/python-tests/common.py
==============================================================================
--- trunk/test/python-tests/common.py	(original)
+++ trunk/test/python-tests/common.py	Mon Jan 14 10:10:07 2008
@@ -260,7 +260,7 @@
         wrapper = None
         for dp in self.model.get_all_modules():
             if dp.classname == name:
-                wrapper = self.model.get_new_module_instance(dp.get_key())
+                wrapper = self.model.get_module_wrapper_with_instance(dp.get_key())
 
         ok("Find DataProviderWrapper '%s'" % name, wrapper != None, die)
         return wrapper
@@ -274,20 +274,11 @@
         return factory
 
     def wrap_dataprovider(self, dp):
-        wrapper = ModuleWrapper.ModuleWrapper (   
-                    getattr(dp, "_name_", ""),
-                    getattr(dp, "_description_", ""),
-                    getattr(dp, "_icon_", ""),
-                    getattr(dp, "_module_type_", ""),
-                    None,
-                    getattr(dp, "_in_type_", ""),
-                    getattr(dp, "_out_type_", ""),
-                    dp.__class__.__name__,     #classname
-                    tuple([]),
-                    dp,
-                    True
-                    )
-
+        wrapper = ModuleWrapper.ModuleWrapper(   
+                        classname=dp.__class__.__name__,
+                        module=dp,
+                        enabled=True
+                        )
         return wrapper
 
     def networked_dataprovider(self, dp):



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]