* src/RelLib.py: added get_backlink_handles method to PrimaryObject
* test/GrampsDbBase_Test.py: factored out common db test methods * test/GrampsDbTestBase.py: new base class for unittests that need to create database records * test/RelLib_Test.py: unittest for the * get_backlink_handles method svn: r5583
This commit is contained in:
		@@ -1,3 +1,10 @@
 | 
			
		||||
2005-12-19 Richard Taylor <rjt-gramps@thegrindstone.me.uk>
 | 
			
		||||
	* src/RelLib.py: added get_backlink_handles method to PrimaryObject
 | 
			
		||||
        * test/GrampsDbBase_Test.py: factored out common db test methods
 | 
			
		||||
	* test/GrampsDbTestBase.py: new base class for unittests that need to 
 | 
			
		||||
	create database records
 | 
			
		||||
	* test/RelLib_Test.py: unittest for the get_backlink_handles method
 | 
			
		||||
	
 | 
			
		||||
2005-12-17  Alex Roitman  <shura@gramps-project.org>
 | 
			
		||||
	* src/GrampsBSDDB.py (gramps_upgrade_9): Switch to using keys in
 | 
			
		||||
	upgrade. When using DB cusrsor, modifying the record sometimes
 | 
			
		||||
 
 | 
			
		||||
@@ -347,6 +347,24 @@ class PrimaryObject(BaseObject):
 | 
			
		||||
    def _replace_handle_reference(self,classname,old_handle,new_handle):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def get_backlink_handles(self,db,include_classes=None):
 | 
			
		||||
        """Get a list of all primary objects that make some reference to this
 | 
			
		||||
        primary object, either directly or via a child object.
 | 
			
		||||
 | 
			
		||||
        Returns an iterator over tuples each of the form (class_name,handle).
 | 
			
		||||
 | 
			
		||||
        To get a list use:
 | 
			
		||||
 | 
			
		||||
        references = [ ref for ref in obj.get_backlink_handles() ]
 | 
			
		||||
 | 
			
		||||
        @param db: a object with the find_backlink_handles method
 | 
			
		||||
        @type db: usually a instance of a class derived from GrampsDbBase.
 | 
			
		||||
        @param include_classes: the primary classes to include in the result.
 | 
			
		||||
        @type: tuple of primary class names as strings, or None for all classes.
 | 
			
		||||
        """
 | 
			
		||||
        
 | 
			
		||||
        return db.find_backlink_handles(self.get_handle(),include_classes)
 | 
			
		||||
        
 | 
			
		||||
    def set_marker(self,marker):
 | 
			
		||||
        self.marker = marker
 | 
			
		||||
    
 | 
			
		||||
 
 | 
			
		||||
@@ -19,128 +19,12 @@ import RelLib
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger('Gramps.GrampsDbBase_Test')
 | 
			
		||||
 | 
			
		||||
class ReferenceMapTest (unittest.TestCase):
 | 
			
		||||
 | 
			
		||||
    def setUp(self):        
 | 
			
		||||
        self._tmpdir = tempfile.mkdtemp()
 | 
			
		||||
        self._filename = os.path.join(self._tmpdir,'test.grdb')
 | 
			
		||||
        
 | 
			
		||||
        self._db = GrampsBSDDB.GrampsBSDDB()
 | 
			
		||||
        self._db.load(self._filename,
 | 
			
		||||
                      None, # callback
 | 
			
		||||
                      "w")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        shutil.rmtree(self._tmpdir)
 | 
			
		||||
 | 
			
		||||
    def _populate_database(self,
 | 
			
		||||
                           num_sources = 1,
 | 
			
		||||
                           num_persons = 0,
 | 
			
		||||
                           num_families = 0,
 | 
			
		||||
                           num_events = 0,
 | 
			
		||||
                           num_places = 0,
 | 
			
		||||
                           num_media_objects = 0,
 | 
			
		||||
                           num_links = 1):
 | 
			
		||||
 | 
			
		||||
        # start with sources
 | 
			
		||||
        sources = []
 | 
			
		||||
        for i in xrange(0,num_sources):
 | 
			
		||||
            sources.append(self._add_source())
 | 
			
		||||
 | 
			
		||||
        # now for each of the other tables. Give each entry a link
 | 
			
		||||
        # to num_link sources, sources are chosen on a round robin
 | 
			
		||||
        # basis
 | 
			
		||||
 | 
			
		||||
        for num, add_func in ((num_persons, self._add_person_with_sources),
 | 
			
		||||
                              (num_families, self._add_family_with_sources),
 | 
			
		||||
                              (num_events, self._add_event_with_sources),
 | 
			
		||||
                              (num_places, self._add_place_with_sources),
 | 
			
		||||
                              (num_media_objects, self._add_media_object_with_sources)):
 | 
			
		||||
                                   
 | 
			
		||||
            source_idx = 1
 | 
			
		||||
            for person_idx in xrange(0,num):
 | 
			
		||||
 | 
			
		||||
                # Get the list of sources to link
 | 
			
		||||
                lnk_sources = set()
 | 
			
		||||
                for i in xrange(0,num_links):
 | 
			
		||||
                    lnk_sources.add(sources[source_idx-1])
 | 
			
		||||
                    source_idx = (source_idx+1) % len(sources)
 | 
			
		||||
 | 
			
		||||
                try:
 | 
			
		||||
                    add_func(lnk_sources)
 | 
			
		||||
                except:
 | 
			
		||||
                    print "person_idx = ", person_idx
 | 
			
		||||
                    print "lnk_sources = ", repr(lnk_sources)
 | 
			
		||||
                    raise
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    def _add_source(self):
 | 
			
		||||
        # Add a Source
 | 
			
		||||
        
 | 
			
		||||
        tran = self._db.transaction_begin()
 | 
			
		||||
        source = RelLib.Source()
 | 
			
		||||
        self._db.add_source(source,tran)
 | 
			
		||||
        self._db.commit_source(source,tran)
 | 
			
		||||
        self._db.transaction_commit(tran, "Add Source")
 | 
			
		||||
 | 
			
		||||
        return source
 | 
			
		||||
 | 
			
		||||
                           
 | 
			
		||||
    def _add_object_with_source(self,sources,object_class,add_method,commit_method):
 | 
			
		||||
 | 
			
		||||
        object = object_class()
 | 
			
		||||
 | 
			
		||||
        for source in sources:
 | 
			
		||||
            src_ref = RelLib.SourceRef()
 | 
			
		||||
            src_ref.set_base_handle(source.get_handle())
 | 
			
		||||
            object.add_source_reference(src_ref)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        tran = self._db.transaction_begin()
 | 
			
		||||
        add_method(object,tran)
 | 
			
		||||
        commit_method(object,tran)
 | 
			
		||||
        self._db.transaction_commit(tran, "Add Object")
 | 
			
		||||
 | 
			
		||||
        return object
 | 
			
		||||
 | 
			
		||||
    def _add_person_with_sources(self,sources):
 | 
			
		||||
 | 
			
		||||
        return self._add_object_with_source(sources,
 | 
			
		||||
                                            RelLib.Person,
 | 
			
		||||
                                            self._db.add_person,
 | 
			
		||||
                                            self._db.commit_person)
 | 
			
		||||
 | 
			
		||||
    def _add_family_with_sources(self,sources):
 | 
			
		||||
 | 
			
		||||
        return self._add_object_with_source(sources,
 | 
			
		||||
                                            RelLib.Family,
 | 
			
		||||
                                            self._db.add_family,
 | 
			
		||||
                                            self._db.commit_family)
 | 
			
		||||
 | 
			
		||||
    def _add_event_with_sources(self,sources):
 | 
			
		||||
 | 
			
		||||
        return self._add_object_with_source(sources,
 | 
			
		||||
                                            RelLib.Event,
 | 
			
		||||
                                            self._db.add_event,
 | 
			
		||||
                                            self._db.commit_event)
 | 
			
		||||
 | 
			
		||||
    def _add_place_with_sources(self,sources):
 | 
			
		||||
 | 
			
		||||
        return self._add_object_with_source(sources,
 | 
			
		||||
                                            RelLib.Place,
 | 
			
		||||
                                            self._db.add_place,
 | 
			
		||||
                                            self._db.commit_place)
 | 
			
		||||
 | 
			
		||||
    def _add_media_object_with_sources(self,sources):
 | 
			
		||||
 | 
			
		||||
        return self._add_object_with_source(sources,
 | 
			
		||||
                                            RelLib.MediaObject,
 | 
			
		||||
                                            self._db.add_object,
 | 
			
		||||
                                            self._db.commit_media_object)
 | 
			
		||||
from GrampsDbTestBase import GrampsDbBaseTest
 | 
			
		||||
    
 | 
			
		||||
        
 | 
			
		||||
class ReferenceMapTest (GrampsDbBaseTest):
 | 
			
		||||
    """Test methods on the GrampsDbBase class that are related to the reference_map
 | 
			
		||||
    index implementation."""
 | 
			
		||||
 | 
			
		||||
    def test_simple_lookup(self):
 | 
			
		||||
        """insert a record and a reference and check that
 | 
			
		||||
@@ -295,7 +179,8 @@ class ReferenceMapTest (unittest.TestCase):
 | 
			
		||||
        assert with_reference_map < (without_reference_map / 10), "Reference_map should an order of magnitude faster."
 | 
			
		||||
        
 | 
			
		||||
def testSuite():
 | 
			
		||||
    return unittest.makeSuite(ReferenceMapTest,'test')
 | 
			
		||||
    suite = unittest.makeSuite(ReferenceMapTest,'test')
 | 
			
		||||
    return suite
 | 
			
		||||
 | 
			
		||||
def perfSuite():
 | 
			
		||||
    return unittest.makeSuite(ReferenceMapTest,'perf')
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										144
									
								
								gramps2/test/GrampsDbTestBase.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								gramps2/test/GrampsDbTestBase.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,144 @@
 | 
			
		||||
import unittest
 | 
			
		||||
import logging
 | 
			
		||||
import os
 | 
			
		||||
import tempfile
 | 
			
		||||
import shutil
 | 
			
		||||
import time
 | 
			
		||||
import traceback
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
sys.path.append('../src')
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    set()
 | 
			
		||||
except NameError:
 | 
			
		||||
    from sets import Set as set
 | 
			
		||||
    
 | 
			
		||||
import GrampsBSDDB
 | 
			
		||||
import RelLib
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger('Gramps.GrampsDbTestBase')
 | 
			
		||||
 | 
			
		||||
class GrampsDbBaseTest(unittest.TestCase):
 | 
			
		||||
    """Base class for unittest that need to be able to create
 | 
			
		||||
    test databases."""
 | 
			
		||||
    
 | 
			
		||||
    def setUp(self):        
 | 
			
		||||
        self._tmpdir = tempfile.mkdtemp()
 | 
			
		||||
        self._filename = os.path.join(self._tmpdir,'test.grdb')
 | 
			
		||||
        
 | 
			
		||||
        self._db = GrampsBSDDB.GrampsBSDDB()
 | 
			
		||||
        self._db.load(self._filename,
 | 
			
		||||
                      None, # callback
 | 
			
		||||
                      "w")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def tearDown(self):
 | 
			
		||||
        shutil.rmtree(self._tmpdir)
 | 
			
		||||
 | 
			
		||||
    def _populate_database(self,
 | 
			
		||||
                           num_sources = 1,
 | 
			
		||||
                           num_persons = 0,
 | 
			
		||||
                           num_families = 0,
 | 
			
		||||
                           num_events = 0,
 | 
			
		||||
                           num_places = 0,
 | 
			
		||||
                           num_media_objects = 0,
 | 
			
		||||
                           num_links = 1):
 | 
			
		||||
 | 
			
		||||
        # start with sources
 | 
			
		||||
        sources = []
 | 
			
		||||
        for i in xrange(0,num_sources):
 | 
			
		||||
            sources.append(self._add_source())
 | 
			
		||||
 | 
			
		||||
        # now for each of the other tables. Give each entry a link
 | 
			
		||||
        # to num_link sources, sources are chosen on a round robin
 | 
			
		||||
        # basis
 | 
			
		||||
 | 
			
		||||
        for num, add_func in ((num_persons, self._add_person_with_sources),
 | 
			
		||||
                              (num_families, self._add_family_with_sources),
 | 
			
		||||
                              (num_events, self._add_event_with_sources),
 | 
			
		||||
                              (num_places, self._add_place_with_sources),
 | 
			
		||||
                              (num_media_objects, self._add_media_object_with_sources)):
 | 
			
		||||
                                   
 | 
			
		||||
            source_idx = 1
 | 
			
		||||
            for person_idx in xrange(0,num):
 | 
			
		||||
 | 
			
		||||
                # Get the list of sources to link
 | 
			
		||||
                lnk_sources = set()
 | 
			
		||||
                for i in xrange(0,num_links):
 | 
			
		||||
                    lnk_sources.add(sources[source_idx-1])
 | 
			
		||||
                    source_idx = (source_idx+1) % len(sources)
 | 
			
		||||
 | 
			
		||||
                try:
 | 
			
		||||
                    add_func(lnk_sources)
 | 
			
		||||
                except:
 | 
			
		||||
                    print "person_idx = ", person_idx
 | 
			
		||||
                    print "lnk_sources = ", repr(lnk_sources)
 | 
			
		||||
                    raise
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    def _add_source(self):
 | 
			
		||||
        # Add a Source
 | 
			
		||||
        
 | 
			
		||||
        tran = self._db.transaction_begin()
 | 
			
		||||
        source = RelLib.Source()
 | 
			
		||||
        self._db.add_source(source,tran)
 | 
			
		||||
        self._db.commit_source(source,tran)
 | 
			
		||||
        self._db.transaction_commit(tran, "Add Source")
 | 
			
		||||
 | 
			
		||||
        return source
 | 
			
		||||
 | 
			
		||||
                           
 | 
			
		||||
    def _add_object_with_source(self,sources,object_class,add_method,commit_method):
 | 
			
		||||
 | 
			
		||||
        object = object_class()
 | 
			
		||||
 | 
			
		||||
        for source in sources:
 | 
			
		||||
            src_ref = RelLib.SourceRef()
 | 
			
		||||
            src_ref.set_base_handle(source.get_handle())
 | 
			
		||||
            object.add_source_reference(src_ref)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        tran = self._db.transaction_begin()
 | 
			
		||||
        add_method(object,tran)
 | 
			
		||||
        commit_method(object,tran)
 | 
			
		||||
        self._db.transaction_commit(tran, "Add Object")
 | 
			
		||||
 | 
			
		||||
        return object
 | 
			
		||||
 | 
			
		||||
    def _add_person_with_sources(self,sources):
 | 
			
		||||
 | 
			
		||||
        return self._add_object_with_source(sources,
 | 
			
		||||
                                            RelLib.Person,
 | 
			
		||||
                                            self._db.add_person,
 | 
			
		||||
                                            self._db.commit_person)
 | 
			
		||||
 | 
			
		||||
    def _add_family_with_sources(self,sources):
 | 
			
		||||
 | 
			
		||||
        return self._add_object_with_source(sources,
 | 
			
		||||
                                            RelLib.Family,
 | 
			
		||||
                                            self._db.add_family,
 | 
			
		||||
                                            self._db.commit_family)
 | 
			
		||||
 | 
			
		||||
    def _add_event_with_sources(self,sources):
 | 
			
		||||
 | 
			
		||||
        return self._add_object_with_source(sources,
 | 
			
		||||
                                            RelLib.Event,
 | 
			
		||||
                                            self._db.add_event,
 | 
			
		||||
                                            self._db.commit_event)
 | 
			
		||||
 | 
			
		||||
    def _add_place_with_sources(self,sources):
 | 
			
		||||
 | 
			
		||||
        return self._add_object_with_source(sources,
 | 
			
		||||
                                            RelLib.Place,
 | 
			
		||||
                                            self._db.add_place,
 | 
			
		||||
                                            self._db.commit_place)
 | 
			
		||||
 | 
			
		||||
    def _add_media_object_with_sources(self,sources):
 | 
			
		||||
 | 
			
		||||
        return self._add_object_with_source(sources,
 | 
			
		||||
                                            RelLib.MediaObject,
 | 
			
		||||
                                            self._db.add_object,
 | 
			
		||||
                                            self._db.commit_media_object)
 | 
			
		||||
    
 | 
			
		||||
							
								
								
									
										75
									
								
								gramps2/test/RelLib_Test.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								gramps2/test/RelLib_Test.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
import unittest
 | 
			
		||||
import logging
 | 
			
		||||
import os
 | 
			
		||||
import tempfile
 | 
			
		||||
import shutil
 | 
			
		||||
import time
 | 
			
		||||
import traceback
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
sys.path.append('../src')
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    set()
 | 
			
		||||
except NameError:
 | 
			
		||||
    from sets import Set as set
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import RelLib
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger('Gramps.RelLib_Test')
 | 
			
		||||
 | 
			
		||||
from GrampsDbTestBase import GrampsDbBaseTest
 | 
			
		||||
    
 | 
			
		||||
class PrimaryObjectTest (GrampsDbBaseTest):
 | 
			
		||||
    """Test methods on the PrimaryObject class"""
 | 
			
		||||
    
 | 
			
		||||
    def test_get_backlink_handles(self):
 | 
			
		||||
        """Check that backlink lookup works."""
 | 
			
		||||
 | 
			
		||||
        source = self._add_source()
 | 
			
		||||
        person = self._add_person_with_sources([source])
 | 
			
		||||
 | 
			
		||||
        references = [ ref for ref in source.get_backlink_handles(self._db) ]
 | 
			
		||||
 | 
			
		||||
        assert len(references) == 1
 | 
			
		||||
        assert references[0] == (RelLib.Person.__name__,person.get_handle())
 | 
			
		||||
 | 
			
		||||
    def test_get_backlink_handles_with_class_list(self):
 | 
			
		||||
        """Check backlink lookup with class list."""
 | 
			
		||||
        
 | 
			
		||||
        source = self._add_source()
 | 
			
		||||
        person = self._add_person_with_sources([source])
 | 
			
		||||
 | 
			
		||||
        self._add_family_with_sources([source])
 | 
			
		||||
        self._add_event_with_sources([source])
 | 
			
		||||
        self._add_place_with_sources([source])
 | 
			
		||||
        self._add_media_object_with_sources([source])
 | 
			
		||||
 | 
			
		||||
        references = [ ref for ref in source.get_backlink_handles(self._db) ]
 | 
			
		||||
 | 
			
		||||
        # make sure that we have the correct number of references (one for each object)
 | 
			
		||||
        references = [ ref for ref in source.get_backlink_handles(self._db) ]
 | 
			
		||||
 | 
			
		||||
        assert len(references) == 5, "len(references) == %s " % str(len(references))
 | 
			
		||||
 | 
			
		||||
        # should just return the person reference
 | 
			
		||||
        references = [ ref for ref in source.get_backlink_handles(self._db,(RelLib.Person.__name__,)) ]
 | 
			
		||||
        assert len(references) == 1, "len(references) == %s " % str(len(references))
 | 
			
		||||
        assert references[0][0] == RelLib.Person.__name__, "references = %s" % repr(references)
 | 
			
		||||
 | 
			
		||||
        # should just return the person  and event reference
 | 
			
		||||
        references = [ ref for ref in  source.get_backlink_handles(self._db,(RelLib.Person.__name__,
 | 
			
		||||
                                                                             RelLib.Event.__name__)) ]
 | 
			
		||||
        assert len(references) == 2, "len(references) == %s " % str(len(references))
 | 
			
		||||
        assert references[0][0] == RelLib.Person.__name__, "references = %s" % repr(references)
 | 
			
		||||
        assert references[1][0] == RelLib.Event.__name__, "references = %s" % repr(references)
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        
 | 
			
		||||
def testSuite():
 | 
			
		||||
    suite = unittest.makeSuite(PrimaryObjectTest,'test')
 | 
			
		||||
    return suite
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    unittest.TextTestRunner().run(testSuite())
 | 
			
		||||
		Reference in New Issue
	
	Block a user