Commits

seccanj committed c257140

Release 1.4.3. Enhancement #8427 (Track-Hacks): Add XML-RPC complete interface for remote management of test objects.

  • Participants
  • Parent commits 1cc63f2

Comments (0)

Files changed (93)

File BUILD.txt

File contents unchanged.

File INSTALLATION.txt

File contents unchanged.

File LICENSE.txt

File contents unchanged.
 
 (Refer to the tickets on trac-hacks or SourceForge for complete descriptions.)
 
+Release 1.4.3 (2011-01-20):
+  o Enhancement #8427 (Track-Hacks): Add XML-RPC complete interface for remote management of test objects
+
 Release 1.4.2 (2011-01-09):
   o Fixed Ticket #8378 (Track-Hacks): Set date and time format correctly in Test Stats page
   Also added support for custom test case outcomes in the Test Stats page

File build.cmd

File contents unchanged.

File build_wininst.cmd

File contents unchanged.

File clean.cmd

File contents unchanged.

File package.cmd

File contents unchanged.

File sqlexecutor/trunk/setup.py

File contents unchanged.

File sqlexecutor/trunk/sqlexecutor/LICENSE.txt

File contents unchanged.

File sqlexecutor/trunk/sqlexecutor/README.txt

File contents unchanged.

File sqlexecutor/trunk/sqlexecutor/__init__.py

File contents unchanged.

File sqlexecutor/trunk/sqlexecutor/htdocs/place.holder

File contents unchanged.

File sqlexecutor/trunk/sqlexecutor/sql.py

File contents unchanged.

File sqlexecutor/trunk/sqlexecutor/templates/empty.html

File contents unchanged.

File sqlexecutor/trunk/sqlexecutor/templates/result.html

File contents unchanged.

File testman4trac/trunk/messages-js.cfg

File contents unchanged.

File testman4trac/trunk/setup.cfg

File contents unchanged.

File testman4trac/trunk/setup.py

 
 setup(
     name='TestManager',
-    version='1.4.2',
+    version='1.4.3',
     packages=['testmanager'],
     package_data={
         'testmanager' : [

File testman4trac/trunk/testmanager/INSTALLATION.txt

File contents unchanged.

File testman4trac/trunk/testmanager/LICENSE.txt

File contents unchanged.

File testman4trac/trunk/testmanager/README.txt

 
 (Refer to the tickets on trac-hacks or SourceForge for complete descriptions.)
 
+Release 1.4.3 (2011-01-20):
+  o Enhancement #8427 (Track-Hacks): Add XML-RPC complete interface for remote management of test objects
+
 Release 1.4.2 (2011-01-09):
   o Fixed Ticket #8378 (Track-Hacks): Set date and time format correctly in Test Stats page
   Also added support for custom test case outcomes in the Test Stats page

File testman4trac/trunk/testmanager/__init__.py

 import util
 import stats
 import workflow
+import rpcsupport

File testman4trac/trunk/testmanager/api.py

File contents unchanged.

File testman4trac/trunk/testmanager/htdocs/css/images/nav-bg.gif

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/css/images/nav-bg.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/css/images/nav_dropdown_grad.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/css/images/nav_dropdown_sep.gif

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/css/images/nav_separator.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/css/images/submenu-bottom.gif

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/css/images/submenu-bottom.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/css/images/submenu-selected-bottom.gif

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/css/images/submenu-selected-top.gif

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/css/menu.css

File contents unchanged.

File testman4trac/trunk/testmanager/htdocs/css/testmanager.css

File contents unchanged.

File testman4trac/trunk/testmanager/htdocs/images/empty.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/images/gray.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/images/green.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/images/minus.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/images/pencil.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/images/plus.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/images/red.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/images/trash.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/images/tree.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/images/tree_table.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/images/yellow.png

Old
Old image
New
New image

File testman4trac/trunk/testmanager/htdocs/js/compatibility.js

File contents unchanged.

File testman4trac/trunk/testmanager/htdocs/js/cookies.js

File contents unchanged.

File testman4trac/trunk/testmanager/htdocs/js/it.js

File contents unchanged.

File testman4trac/trunk/testmanager/htdocs/js/labels.js

File contents unchanged.

File testman4trac/trunk/testmanager/htdocs/js/labels_en.js

File contents unchanged.

File testman4trac/trunk/testmanager/htdocs/js/labels_it.js

File contents unchanged.

File testman4trac/trunk/testmanager/htdocs/js/menu.js

File contents unchanged.

File testman4trac/trunk/testmanager/htdocs/js/testmanager.js

File contents unchanged.

File testman4trac/trunk/testmanager/labels.py

File contents unchanged.

File testman4trac/trunk/testmanager/labels_en.py

File contents unchanged.

File testman4trac/trunk/testmanager/labels_it.py

File contents unchanged.

File testman4trac/trunk/testmanager/locale/it/LC_MESSAGES/testmanager-js.mo

Binary file modified.

File testman4trac/trunk/testmanager/locale/it/LC_MESSAGES/testmanager-js.po

File contents unchanged.

File testman4trac/trunk/testmanager/locale/it/LC_MESSAGES/testmanager.mo

Binary file modified.

File testman4trac/trunk/testmanager/locale/it/LC_MESSAGES/testmanager.po

File contents unchanged.

File testman4trac/trunk/testmanager/locale/messages-js.pot

File contents unchanged.

File testman4trac/trunk/testmanager/locale/messages.pot

File contents unchanged.

File testman4trac/trunk/testmanager/macros.py

File contents unchanged.

File testman4trac/trunk/testmanager/model.py

 
             return TestCatalog(self.env, cat_id, cat_page)
         
-    def list_subcatalogs(self):
+    def list_subcatalogs(self, db=None):
         """
         Returns a list of the sub catalogs of this catalog.
         """
-        # TODO: Implement method
-        return ()
+        tc_search = TestCatalog(self.env)
+        tc_search['page_name'] = self.values['page_name'] + '_TT%'
         
-    def list_testcases(self):
+        cat_re = re.compile('^TT[0-9]*$')
+        
+        for tc in tc_search.list_matching_objects(exact_match=False, db=db):
+            # Only return direct sub-catalogs and exclude test cases
+            if cat_re.match(tc['page_name'].partition(self.values['page_name']+'_')[2]) :
+                yield tc
+        
+    def list_testcases(self, plan_id=None, db=None):
         """
         Returns a list of the test cases in this catalog.
+        If plan_id is provided, returns a list of TestCaseInPlan objects,
+        otherwise, of TestCase objects.
         """
-        # TODO: Implement method
-        return ()
+
+        if plan_id is not None:
+            from testmanager.api import TestManagerSystem
+            default_status = TestManagerSystem(self.env).get_default_tc_status()
+        
+        tc_search = TestCase(self.env)
+        tc_search['page_name'] = self.values['page_name'] + '_TC%'
+        
+        for tc in tc_search.list_matching_objects(False, db):
+            if plan_id is None:
+                yield tc
+            else:
+                tcip = TestCaseInPlan(self.env, tc['id'], plan_id)
+                if not tcip.exists:
+                    tcip['status'] = default_status
+
+                yield tcip
 
     def list_testplans(self, db=None):
         """
         tp_search = TestPlan(self.env)
         tp_search['catid'] = self.values['id']
         
-        for tp in tp_search.list_matching_objects(db):
+        for tp in tp_search.list_matching_objects(db=db):
             yield tp
 
     def create_instance(self, key):
         # Remove test case from all the plans
         tcip_search = TestCaseInPlan(self.env)
         tcip_search['id'] = self.values['id']
-        for tcip in tcip_search.list_matching_objects(db):
+        for tcip in tcip_search.list_matching_objects(db=db):
             tcip.delete(db)
 
         # Update self properties and save
         self.env.log.debug("Deleting all test cases in the plan...")
         tcip_search = TestCaseInPlan(self.env)
         tcip_search['planid'] = self.values['id']
-        for tcip in tcip_search.list_matching_objects(db):
+        for tcip in tcip_search.list_matching_objects(db=db):
             self.env.log.debug("Deleting test case in plan, with id %s" % tcip['id'])
             tcip.delete(db)
 

File testman4trac/trunk/testmanager/rpcsupport.py

+# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2010 Roberto Longobardi
+#
+
+import os
+from datetime import datetime
+
+from trac.core import *
+from trac.util import get_reporter_id
+
+from tracrpc.api import IXMLRPCHandler, AbstractRPCHandler, expose_rpc, Binary
+from tracrpc.util import StringIO, to_utimestamp, from_utimestamp
+
+from tracgenericclass.model import GenericClassModelProvider
+from tracgenericclass.util import formatExceptionInfo
+
+from testmanager.api import TestManagerSystem
+from testmanager.model import TestCatalog, TestCase, TestCaseInPlan, TestPlan
+
+
+__all__ = ['TestManagerRPC']
+
+class TestManagerRPC(Component):
+    implements(IXMLRPCHandler)
+
+    def __init__(self):
+        self.testmanagersys = TestManagerSystem(self.env)
+
+    def xmlrpc_namespace(self):
+        return 'testmanager'
+
+    def xmlrpc_methods(self):
+        yield ('TEST_MODIFY', ((str, str, str, str),), self.createTestCatalog)
+        yield ('TEST_MODIFY', ((str, str, str, str),), self.createTestCase)
+        yield ('TEST_PLAN_ADMIN', ((str, str, str),), self.createTestPlan)
+        yield (None, ((bool, str, str),), self.deleteTestObject)
+        yield (None, ((bool, str, str),(bool, str, str, dict)), self.modifyTestObject)
+        yield (None, ((bool, str, str, str),), self.setTestCaseStatus)
+        yield ('TEST_VIEW', ((list, str),(list, str, str)), self.listTestCases)
+        yield ('TEST_VIEW', ((list, str),), self.getTestCatalog)
+        yield ('TEST_VIEW', ((list, str),(list, str, str)), self.getTestCase)
+        yield ('TEST_VIEW', ((list, str, str),), self.getTestPlan)
+        yield ('TEST_VIEW', ((list, str),), self.listSubCatalogs)
+        yield ('TEST_VIEW', ((list, str),), self.listTestPlans)
+
+    def createTestCatalog(self, req, parent_catalog_id, title, description):
+        """ Creates a new test catalog, in the parent catalog specified, 
+        with the specified title and description.
+		To create a root catalog, specify '' as the parent catalog.
+        Returns the generated object ID, or '-1' if an error occurs. """
+        
+        result = '-1'
+        try:
+            id = self.testmanagersys.get_next_id('catalog')
+
+            pagename = None
+            if parent_catalog_id is not None and parent_catalog_id != '':
+                # Check parent catalog really exists, and get its page_name
+                tcat = TestCatalog(self.env, parent_catalog_id)
+                if not tcat.exists:
+                    self.env.log.error("Input parent test catalog with ID %s not found." % parent_catalog_id)
+                    return result
+                    
+                pagename = tcat['page_name'] + '_TT' + id
+            else:
+                pagename = 'TC_TT' + id
+
+            author = get_reporter_id(req, 'author')
+            
+            new_tc = TestCatalog(self.env, id, pagename, title, description)
+            new_tc.author = author
+            new_tc.remote_addr = req.remote_addr
+            # This also creates the Wiki page
+            new_tc.insert()
+            result = id
+            
+        except:
+            self.env.log.error("Error adding test catalog with title '%s' in catalog with ID %s!" % (title, parent_catalog_id))
+            self.env.log.error(formatExceptionInfo())
+        
+        return id
+
+    def createTestCase(self, req, catalog_id, title, description):
+        """ Creates a new test case, in the catalog specified, with the 
+        specified title and description.
+        Returns the generated object ID, or '-1' if an error occurs. """
+        
+        result = '-1'
+        try:
+            if catalog_id is None or catalog_id == '':
+                self.env.log.error("Cannot create a test plan on the root catalog container.")
+                return result
+            
+            # Check catalog really exists, and get its page_name
+            tcat = TestCatalog(self.env, catalog_id)
+            if not tcat.exists:
+                self.env.log.error("Input test catalog with ID %s not found." % catalog_id)
+                return result
+            
+            author = get_reporter_id(req, 'author')
+            
+            id = self.testmanagersys.get_next_id('testcase')
+            pagename = tcat['page_name'] + '_TC' + id
+
+            new_tc = TestCase(self.env, id, pagename, title, description)
+            new_tc.author = author
+            new_tc.remote_addr = req.remote_addr
+            # This also creates the Wiki page
+            new_tc.insert()
+            result = id
+            
+        except:
+            self.env.log.error("Error adding test case with title '%s' in catalog with ID %s!" % (title, catalog_id))
+            self.env.log.error(formatExceptionInfo())
+        
+        return id
+
+    def createTestPlan(self, req, catalog_id, name):
+        """ Creates a new test plan, on the catalog specified, with the 
+        specified name.
+        Returns the generated object ID, or '-1' if an error occurs. """
+        
+        result = '-1'
+        try:
+            # Check catalog really exists, and get its page_name
+            tcat = TestCatalog(self.env, catalog_id)
+            if not tcat.exists:
+                self.env.log.error("Input test catalog with ID %s not found." % catalog_id)
+                return result
+            
+            author = get_reporter_id(req, 'author')
+            
+            id = self.testmanagersys.get_next_id('testplan')
+            pagename = tcat['page_name']
+
+            new_tp = TestPlan(self.env, id, catalog_id, pagename, name, author)
+            new_tp.insert()
+            result = id
+            
+        except:
+            self.env.log.error("Error adding test plan with name '%s' for catalog with ID %s!" % (name, catalog_id))
+            self.env.log.error(formatExceptionInfo())
+        
+        return result
+
+    def deleteTestObject(self, req, objtype, id):
+        """ Deletes the test object of the specified type identified
+        by the given id. 
+        Returns True if successful, False otherwise. """
+        
+        try:
+            # Check the object exists
+            obj = None
+            if objtype == 'testcatalog':
+                req.perm.require('TEST_MODIFY')
+                obj = TestCatalog(self.env, id)
+            elif objtype == 'testcase':
+                req.perm.require('TEST_MODIFY')
+                obj = TestCase(self.env, id)
+            elif objtype == 'testplan':
+                req.perm.require('TEST_PLAN_ADMIN')
+                obj = TestPlan(self.env, id)
+
+            if not obj.exists:
+                self.env.log.error("Input test object of type %s with ID %s not found." % (objtype, id))
+                return False
+
+            obj.delete()
+            
+        except:
+            self.env.log.error("Error deleting test object of type %s with ID %s." % (objtype, id))
+            self.env.log.error(formatExceptionInfo())
+            return False
+        
+        return True
+
+    def modifyTestObject(self, req, objtype, id, attributes={}):
+        """ Modifies the test object of the specified type identified
+        by the given id.
+        Returns True if successful, False otherwise. """
+
+        try:
+            # Check the object exists
+            obj = None
+            if objtype == 'testcatalog':
+                req.perm.require('TEST_MODIFY')
+                obj = TestCatalog(self.env, id)
+            elif objtype == 'testcase':
+                req.perm.require('TEST_MODIFY')
+                obj = TestCase(self.env, id)
+            elif objtype == 'testplan':
+                req.perm.require('TEST_PLAN_ADMIN')
+                obj = TestPlan(self.env, id)
+
+            if not obj.exists:
+                self.env.log.error("Input test object of type %s with ID %s not found." % (objtype, id))
+                return False
+
+            author = get_reporter_id(req, 'author')
+
+            for k, v in attributes.iteritems():
+                if k == 'title':
+                    obj.title = v
+                elif k == 'description':
+                    obj.description = v
+                else:
+                    obj[k] = v
+                
+            obj.author = author
+            obj.remote_addr = req.remote_addr
+            obj.save_changes(author, "Changed through RPC.")
+
+        except:
+            self.env.log.error("Error modifying test object of type %s with ID %s." % (objtype, id))
+            self.env.log.error(formatExceptionInfo())
+            return False
+        
+        return True
+
+    def setTestCaseStatus(self, req, testcase_id, plan_id, status):
+        """ Sets the test case status.
+        Returns True if successful, False otherwise. """
+        
+        try:
+            author = get_reporter_id(req, 'author')
+
+            tcip = TestCaseInPlan(self.env, testcase_id, plan_id)
+            if tcip.exists:
+                tcip.set_status(status, author)
+                tcip.save_changes(author, "Status changed")
+            else:
+                tc = TestCase(self.env, testcase_id)
+                tcip['page_name'] = tc['page_name']
+                tcip.set_status(status, author)
+                tcip.insert()
+
+        except:
+            self.env.log.error("Error setting the test case status with ID %s on plan %s to %s!" % (testcase_id, plan_id, status))
+            self.env.log.error(formatExceptionInfo())
+            return False
+
+        return True
+            
+    def getTestCatalog(self, req, catalog_id):
+        """ Returns the catalog properties.
+        The result is in the form, all strings:
+        (wiki_page_name, title, description) """
+        
+        try:
+            # Check catalog really exists
+            tcat = TestCatalog(self.env, catalog_id)
+            if not tcat.exists:
+                self.env.log.error("Input test catalog with ID %s not found." % catalog_id)
+            else:
+                return (tcat['page_name'], tcat.title, tcat.description)
+
+        except:
+            self.env.log.error("Error getting the test catalog with ID %s!" % catalog_id)
+            self.env.log.error(formatExceptionInfo())
+            
+    def getTestCase(self, req, testcase_id, plan_id=''):
+        """ Returns the test case properties.
+        If plan_id is provided, also the status of the test case in the
+        plan will be returned.
+        Each result is in the form, all strings:
+            If plan_id is NOT provided:
+                (wiki_page_name, title, description)
+            If plan_id is provided:
+                (wiki_page_name, title, description, status) """
+        
+        try:
+            # Check test case really exists
+            tc = TestCase(self.env, testcase_id)
+            if not tc.exists:
+                self.env.log.error("Input test case with ID %s not found." % testcase_id)
+            else:
+                if plan_id is None or plan_id == '':
+                    return (tc['page_name'], tc.title, tc.description)
+                else:
+                    tcip = TestCaseInPlan(self.env, testcase_id, plan_id)
+                    return (tc['page_name'], tc.title, tc.description, tcip['status'])
+
+        except:
+            self.env.log.error("Error getting the test case with ID %s!" % testcase_id)
+            self.env.log.error(formatExceptionInfo())
+            
+    def getTestPlan(self, req, plan_id, catalog_id):
+        """ Returns the test plan properties.
+        The result is in the form, all strings:
+        (wiki_page_name, name) """
+        
+        try:
+            # Check test plan really exists
+            tp = TestPlan(self.env, plan_id, catalog_id)
+            if not tp.exists:
+                self.env.log.error("Input test plan with ID %s on catalog %s not found." % (plan_id, catalog_id))
+            else:
+                return (tp['page_name'], tp['name'])
+
+        except:
+            self.env.log.error("Error getting the test plan with ID %s on catalog %s." % (plan_id, catalog_id))
+            self.env.log.error(formatExceptionInfo())
+            
+    def listSubCatalogs(self, req, catalog_id):
+        """ Returns a iterator over the direct sub-catalogs of the specified 
+        catalog.
+        Each result is in the form, all strings:
+        (test_catalog_id, wiki_page_name, title, description) """
+        
+        try:
+            # Check catalog really exists
+            tcat = TestCatalog(self.env, catalog_id)
+            if not tcat.exists:
+                self.env.log.error("Input test catalog with ID %s not found." % catalog_id)
+            else:
+                for tc in tcat.list_subcatalogs():
+                    yield (tc['id'], tc['page_name'], tc.title, tc.description)
+            
+        except:
+            self.env.log.error("Error listing the test catalogs!")
+            self.env.log.error(formatExceptionInfo())
+
+    def listTestPlans(self, req, catalog_id):
+        """ Returns a iterator over the test plans associated 
+        to the specified catalog.
+        Each result is in the form, all strings:
+        (testplan_id, name) """
+        
+        try:
+            # Check catalog really exists
+            tcat = TestCatalog(self.env, catalog_id)
+            if not tcat.exists:
+                self.env.log.error("Input test catalog with ID %s not found." % catalog_id)
+            else:
+                for tp in tcat.list_testplans():
+                    yield (tp['id'], tp['name'])
+            
+        except:
+            self.env.log.error("Error listing the test plans!")
+            self.env.log.error(formatExceptionInfo())
+
+    def listTestCases(self, req, catalog_id, plan_id=''):
+        """ Returns a iterator over the test cases directly in the 
+        specified catalog (no sub-catalogs).
+        If plan_id is provided, also the status of the test case in the
+        plan will be returned.
+        Each result is in the form, all strings:
+            If plan_id is NOT provided:
+                (testcase_id, wiki_page_name, title, description)
+            If plan_id is provided:
+                (testcase_id, wiki_page_name, status) """
+        
+        try:
+            # Check catalog really exists
+            tcat = TestCatalog(self.env, catalog_id)
+            if not tcat.exists:
+                self.env.log.error("Input test catalog with ID %s not found." % catalog_id)
+            else:
+                if plan_id is None or plan_id == '':
+                    for tc in tcat.list_testcases():
+                        # Returned object is a TestCase
+                        yield (tc['id'], tc['page_name'], tc.title, tc.description)
+                else:
+                    for tcip in tcat.list_testcases(plan_id):
+                        # Returned object is a TestCaseInPlan
+                        yield (tcip['id'], tcip['page_name'], tcip['status'])
+            
+        except:
+            self.env.log.error("Error listing the test cases in the catalog with ID %s!" % catalog_id)
+            self.env.log.error(formatExceptionInfo())
+

File testman4trac/trunk/testmanager/stats.py

File contents unchanged.

File testman4trac/trunk/testmanager/templates/content.html

File contents unchanged.

File testman4trac/trunk/testmanager/templates/empty.html

File contents unchanged.

File testman4trac/trunk/testmanager/templates/jsondata.html

File contents unchanged.

File testman4trac/trunk/testmanager/templates/testmanagerstats.html

File contents unchanged.

File testman4trac/trunk/testmanager/util.py

File contents unchanged.

File testman4trac/trunk/testmanager/web_ui.py

File contents unchanged.

File testman4trac/trunk/testmanager/wiki.py

File contents unchanged.

File testman4trac/trunk/testmanager/workflow.py

File contents unchanged.

File tracgenericclass/trunk/setup.py

 
 setup(
     name='TracGenericClass',
-    version='1.0.3',
+    version='1.0.4',
     packages=['tracgenericclass'],
     package_data={'tracgenericclass' : ['*.txt', 'templates/*.html', 'htdocs/*.*', 'htdocs/js/*.js', 'htdocs/css/*.css', 'htdocs/images/*.*']},
     author = 'Roberto Longobardi',

File tracgenericclass/trunk/tracgenericclass/LICENSE.txt

File contents unchanged.

File tracgenericclass/trunk/tracgenericclass/README.txt

 
 (Refer to the tickets on trac-hacks for complete descriptions.)
 
+Release 1.0.4 (2011-01-17):
+  o Added support for LIKE match in list_matching_objects.
+
 Release 1.0.0 (2010-10-01):
   o First release publicly available apart from the core Test Manager plugin
   

File tracgenericclass/trunk/tracgenericclass/__init__.py

File contents unchanged.

File tracgenericclass/trunk/tracgenericclass/api.py

File contents unchanged.

File tracgenericclass/trunk/tracgenericclass/htdocs/place.holder

File contents unchanged.

File tracgenericclass/trunk/tracgenericclass/model.py

         """
         pass
             
-    def list_matching_objects(self, db=None):
+    def list_matching_objects(self, exact_match=True, db=None):
         """
         List the objects that match the current values of this object's
         fields.
         match on, then call this method.
         A collection of objects found in the database matching the 
         fields you had provided values for will be returned.
+        An exact match, i.e. an SQL '=' operator, will be used, unless you
+        specify exact_match=False, in which case the SQL 'LIKE' operator
+        will be used.
         
         The `db` argument is deprecated in favor of `with_transaction()`.
         """
         non_empty_std_values = self.get_values(non_empty_std_names)
         non_empty_custom_values = self.get_values(non_empty_custom_names)
 
+        operator = '='
+        if not exact_match:
+            operator = ' LIKE '
+        
         sql_where = '1=1'
         for k in non_empty_std_names:
-            sql_where += " AND " + k + "=%%s" 
+            sql_where += " AND " + k + operator + '%%s'
         
-        cursor.execute(("SELECT %s FROM %s WHERE " + sql_where)
+        cursor.execute(('SELECT %s FROM %s WHERE ' + sql_where)
                        % (','.join(self.get_key_prop_names()), self.realm), 
                        non_empty_std_values)
 
         wikipage.text = self.text
         wikipage.save(self.author, '', self.remote_addr)
     
+        print("YEEEES!!!")
+    
         self.wikipage = wikipage
 
         return True

File tracgenericclass/trunk/tracgenericclass/templates/empty.html

File contents unchanged.

File tracgenericclass/trunk/tracgenericclass/util.py

File contents unchanged.

File tracgenericworkflow/trunk/setup.py

File contents unchanged.

File tracgenericworkflow/trunk/tracgenericworkflow/LICENSE.txt

File contents unchanged.

File tracgenericworkflow/trunk/tracgenericworkflow/README.txt

File contents unchanged.

File tracgenericworkflow/trunk/tracgenericworkflow/__init__.py

File contents unchanged.

File tracgenericworkflow/trunk/tracgenericworkflow/api.py

File contents unchanged.

File tracgenericworkflow/trunk/tracgenericworkflow/htdocs/place.holder

File contents unchanged.

File tracgenericworkflow/trunk/tracgenericworkflow/model.py

File contents unchanged.

File tracgenericworkflow/trunk/tracgenericworkflow/operations.py

File contents unchanged.

File tracgenericworkflow/trunk/tracgenericworkflow/templates/empty.html

File contents unchanged.