server/test/unittest_migractions.py
changeset 8935 a8a9ba6f4cdd
parent 8696 0bb18407c053
child 8942 0f60f1061a2e
equal deleted inserted replaced
8934:48a6e6b88b16 8935:a8a9ba6f4cdd
    29 from cubicweb.devtools.testlib import CubicWebTC
    29 from cubicweb.devtools.testlib import CubicWebTC
    30 from cubicweb.schema import CubicWebSchemaLoader
    30 from cubicweb.schema import CubicWebSchemaLoader
    31 from cubicweb.server.sqlutils import SQL_PREFIX
    31 from cubicweb.server.sqlutils import SQL_PREFIX
    32 from cubicweb.server.migractions import *
    32 from cubicweb.server.migractions import *
    33 
    33 
       
    34 import cubicweb.devtools
       
    35 
    34 migrschema = None
    36 migrschema = None
    35 def tearDownModule(*args):
    37 def tearDownModule(*args):
    36     global migrschema
    38     global migrschema
    37     del migrschema
    39     del migrschema
    38     if hasattr(MigrationCommandsTC, 'origschema'):
    40     if hasattr(MigrationCommandsTC, 'origschema'):
    39         del MigrationCommandsTC.origschema
    41         del MigrationCommandsTC.origschema
    40 
    42 
    41 class MigrationCommandsTC(CubicWebTC):
    43 class MigrationCommandsTC(CubicWebTC):
       
    44 
       
    45     configcls = cubicweb.devtools.TestServerConfiguration
    42 
    46 
    43     tags = CubicWebTC.tags | Tags(('server', 'migration', 'migractions'))
    47     tags = CubicWebTC.tags | Tags(('server', 'migration', 'migractions'))
    44 
    48 
    45     @classmethod
    49     @classmethod
    46     def _init_repo(cls):
    50     def _init_repo(cls):
    71         CubicWebTC.tearDown(self)
    75         CubicWebTC.tearDown(self)
    72         self.repo.vreg['etypes'].clear_caches()
    76         self.repo.vreg['etypes'].clear_caches()
    73 
    77 
    74     def test_add_attribute_int(self):
    78     def test_add_attribute_int(self):
    75         self.assertFalse('whatever' in self.schema)
    79         self.assertFalse('whatever' in self.schema)
    76         self.request().create_entity('Note')
    80         self.session.create_entity('Note')
    77         self.commit()
    81         self.session.commit(free_cnxset=False)
    78         orderdict = dict(self.mh.rqlexec('Any RTN, O WHERE X name "Note", RDEF from_entity X, '
    82         orderdict = dict(self.mh.rqlexec('Any RTN, O WHERE X name "Note", RDEF from_entity X, '
    79                                          'RDEF relation_type RT, RDEF ordernum O, RT name RTN'))
    83                                          'RDEF relation_type RT, RDEF ordernum O, RT name RTN'))
    80         self.mh.cmd_add_attribute('Note', 'whatever')
    84         self.mh.cmd_add_attribute('Note', 'whatever')
    81         self.assertTrue('whatever' in self.schema)
    85         self.assertTrue('whatever' in self.schema)
    82         self.assertEqual(self.schema['whatever'].subjects(), ('Note',))
    86         self.assertEqual(self.schema['whatever'].subjects(), ('Note',))
    83         self.assertEqual(self.schema['whatever'].objects(), ('Int',))
    87         self.assertEqual(self.schema['whatever'].objects(), ('Int',))
    84         self.assertEqual(self.schema['Note'].default('whatever'), 2)
    88         self.assertEqual(self.schema['Note'].default('whatever'), 2)
    85         # test default value set on existing entities
    89         # test default value set on existing entities
    86         note = self.execute('Note X').get_entity(0, 0)
    90         note = self.session.execute('Note X').get_entity(0, 0)
    87         self.assertEqual(note.whatever, 2)
    91         self.assertEqual(note.whatever, 2)
    88         # test default value set for next entities
    92         # test default value set for next entities
    89         self.assertEqual(self.request().create_entity('Note').whatever, 2)
    93         self.assertEqual(self.session.create_entity('Note').whatever, 2)
    90         # test attribute order
    94         # test attribute order
    91         orderdict2 = dict(self.mh.rqlexec('Any RTN, O WHERE X name "Note", RDEF from_entity X, '
    95         orderdict2 = dict(self.mh.rqlexec('Any RTN, O WHERE X name "Note", RDEF from_entity X, '
    92                                           'RDEF relation_type RT, RDEF ordernum O, RT name RTN'))
    96                                           'RDEF relation_type RT, RDEF ordernum O, RT name RTN'))
    93         whateverorder = migrschema['whatever'].rdef('Note', 'Int').order
    97         whateverorder = migrschema['whatever'].rdef('Note', 'Int').order
    94         for k, v in orderdict.iteritems():
    98         for k, v in orderdict.iteritems():
   105         #     two different entities)
   109         #     two different entities)
   106         self.mh.rollback()
   110         self.mh.rollback()
   107 
   111 
   108     def test_add_attribute_varchar(self):
   112     def test_add_attribute_varchar(self):
   109         self.assertFalse('whatever' in self.schema)
   113         self.assertFalse('whatever' in self.schema)
   110         self.request().create_entity('Note')
   114         self.session.create_entity('Note')
   111         self.commit()
   115         self.session.commit(free_cnxset=False)
   112         self.assertFalse('shortpara' in self.schema)
   116         self.assertFalse('shortpara' in self.schema)
   113         self.mh.cmd_add_attribute('Note', 'shortpara')
   117         self.mh.cmd_add_attribute('Note', 'shortpara')
   114         self.assertTrue('shortpara' in self.schema)
   118         self.assertTrue('shortpara' in self.schema)
   115         self.assertEqual(self.schema['shortpara'].subjects(), ('Note', ))
   119         self.assertEqual(self.schema['shortpara'].subjects(), ('Note', ))
   116         self.assertEqual(self.schema['shortpara'].objects(), ('String', ))
   120         self.assertEqual(self.schema['shortpara'].objects(), ('String', ))
   117         # test created column is actually a varchar(64)
   121         # test created column is actually a varchar(64)
   118         notesql = self.mh.sqlexec("SELECT sql FROM sqlite_master WHERE type='table' and name='%sNote'" % SQL_PREFIX)[0][0]
   122         notesql = self.mh.sqlexec("SELECT sql FROM sqlite_master WHERE type='table' and name='%sNote'" % SQL_PREFIX)[0][0]
   119         fields = dict(x.strip().split()[:2] for x in notesql.split('(', 1)[1].rsplit(')', 1)[0].split(','))
   123         fields = dict(x.strip().split()[:2] for x in notesql.split('(', 1)[1].rsplit(')', 1)[0].split(','))
   120         self.assertEqual(fields['%sshortpara' % SQL_PREFIX], 'varchar(64)')
   124         self.assertEqual(fields['%sshortpara' % SQL_PREFIX], 'varchar(64)')
   121         req = self.request()
       
   122         # test default value set on existing entities
   125         # test default value set on existing entities
   123         self.assertEqual(req.execute('Note X').get_entity(0, 0).shortpara, 'hop')
   126         self.assertEqual(self.session.execute('Note X').get_entity(0, 0).shortpara, 'hop')
   124         # test default value set for next entities
   127         # test default value set for next entities
   125         self.assertEqual(req.create_entity('Note').shortpara, 'hop')
   128         self.assertEqual(self.session.create_entity('Note').shortpara, 'hop')
   126         self.mh.rollback()
   129         self.mh.rollback()
   127 
   130 
   128     def test_add_datetime_with_default_value_attribute(self):
   131     def test_add_datetime_with_default_value_attribute(self):
   129         self.assertFalse('mydate' in self.schema)
   132         self.assertFalse('mydate' in self.schema)
   130         self.assertFalse('shortpara' in self.schema)
   133         self.assertFalse('shortpara' in self.schema)
   193         self.assertFalse('Folder2' in self.schema)
   196         self.assertFalse('Folder2' in self.schema)
   194         self.assertFalse('filed_under2' in self.schema)
   197         self.assertFalse('filed_under2' in self.schema)
   195         self.mh.cmd_add_entity_type('Folder2')
   198         self.mh.cmd_add_entity_type('Folder2')
   196         self.assertTrue('Folder2' in self.schema)
   199         self.assertTrue('Folder2' in self.schema)
   197         self.assertTrue('Old' in self.schema)
   200         self.assertTrue('Old' in self.schema)
   198         self.assertTrue(self.execute('CWEType X WHERE X name "Folder2"'))
   201         self.assertTrue(self.session.execute('CWEType X WHERE X name "Folder2"'))
   199         self.assertTrue('filed_under2' in self.schema)
   202         self.assertTrue('filed_under2' in self.schema)
   200         self.assertTrue(self.execute('CWRType X WHERE X name "filed_under2"'))
   203         self.assertTrue(self.session.execute('CWRType X WHERE X name "filed_under2"'))
   201         self.schema.rebuild_infered_relations()
   204         self.schema.rebuild_infered_relations()
   202         self.assertEqual(sorted(str(rs) for rs in self.schema['Folder2'].subject_relations()),
   205         self.assertEqual(sorted(str(rs) for rs in self.schema['Folder2'].subject_relations()),
   203                           ['created_by', 'creation_date', 'cw_source', 'cwuri',
   206                           ['created_by', 'creation_date', 'cw_source', 'cwuri',
   204                            'description', 'description_format',
   207                            'description', 'description_format',
   205                            'eid',
   208                            'eid',
   223                                       ensure_workflowable=False)
   226                                       ensure_workflowable=False)
   224         todo = wf.add_state(u'todo', initial=True)
   227         todo = wf.add_state(u'todo', initial=True)
   225         done = wf.add_state(u'done')
   228         done = wf.add_state(u'done')
   226         wf.add_transition(u'redoit', done, todo)
   229         wf.add_transition(u'redoit', done, todo)
   227         wf.add_transition(u'markasdone', todo, done)
   230         wf.add_transition(u'markasdone', todo, done)
   228         self.commit()
   231         self.session.commit(free_cnxset=False)
   229         eschema = self.schema.eschema('Folder2')
   232         eschema = self.schema.eschema('Folder2')
   230         self.mh.cmd_drop_entity_type('Folder2')
   233         self.mh.cmd_drop_entity_type('Folder2')
   231         self.assertFalse('Folder2' in self.schema)
   234         self.assertFalse('Folder2' in self.schema)
   232         self.assertFalse(self.execute('CWEType X WHERE X name "Folder2"'))
   235         self.assertFalse(self.session.execute('CWEType X WHERE X name "Folder2"'))
   233         # test automatic workflow deletion
   236         # test automatic workflow deletion
   234         self.assertFalse(self.execute('Workflow X WHERE NOT X workflow_of ET'))
   237         self.assertFalse(self.session.execute('Workflow X WHERE NOT X workflow_of ET'))
   235         self.assertFalse(self.execute('State X WHERE NOT X state_of WF'))
   238         self.assertFalse(self.session.execute('State X WHERE NOT X state_of WF'))
   236         self.assertFalse(self.execute('Transition X WHERE NOT X transition_of WF'))
   239         self.assertFalse(self.session.execute('Transition X WHERE NOT X transition_of WF'))
   237 
   240 
   238     def test_rename_entity_type(self):
   241     def test_rename_entity_type(self):
   239         entity = self.mh.create_entity('Old', name=u'old')
   242         entity = self.mh.create_entity('Old', name=u'old')
   240         self.repo.type_and_source_from_eid(entity.eid)
   243         self.repo.type_and_source_from_eid(entity.eid)
   241         self.mh.cmd_rename_entity_type('Old', 'New')
   244         self.mh.cmd_rename_entity_type('Old', 'New')
   266         self.mh.cmd_add_relation_definition('Personne', 'concerne2', 'Note')
   269         self.mh.cmd_add_relation_definition('Personne', 'concerne2', 'Note')
   267         self.assertEqual(sorted(self.schema['concerne2'].objects()), ['Affaire', 'Note'])
   270         self.assertEqual(sorted(self.schema['concerne2'].objects()), ['Affaire', 'Note'])
   268         self.mh.create_entity('Personne', nom=u'tot')
   271         self.mh.create_entity('Personne', nom=u'tot')
   269         self.mh.create_entity('Affaire')
   272         self.mh.create_entity('Affaire')
   270         self.mh.rqlexec('SET X concerne2 Y WHERE X is Personne, Y is Affaire')
   273         self.mh.rqlexec('SET X concerne2 Y WHERE X is Personne, Y is Affaire')
   271         self.commit()
   274         self.session.commit(free_cnxset=False)
   272         self.mh.cmd_drop_relation_definition('Personne', 'concerne2', 'Affaire')
   275         self.mh.cmd_drop_relation_definition('Personne', 'concerne2', 'Affaire')
   273         self.assertTrue('concerne2' in self.schema)
   276         self.assertTrue('concerne2' in self.schema)
   274         self.mh.cmd_drop_relation_definition('Personne', 'concerne2', 'Note')
   277         self.mh.cmd_drop_relation_definition('Personne', 'concerne2', 'Note')
   275         self.assertFalse('concerne2' in self.schema)
   278         self.assertFalse('concerne2' in self.schema)
   276 
   279 
   288         self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
   291         self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
   289                           ['Affaire', 'Personne'])
   292                           ['Affaire', 'Personne'])
   290         self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
   293         self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
   291                           ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision'])
   294                           ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision'])
   292         # trick: overwrite self.maxeid to avoid deletion of just reintroduced types
   295         # trick: overwrite self.maxeid to avoid deletion of just reintroduced types
   293         self.maxeid = self.execute('Any MAX(X)')[0][0]
   296         self.maxeid = self.session.execute('Any MAX(X)')[0][0]
   294 
   297 
   295     def test_drop_relation_definition_with_specialization(self):
   298     def test_drop_relation_definition_with_specialization(self):
   296         self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
   299         self.assertEqual(sorted(str(e) for e in self.schema['concerne'].subjects()),
   297                           ['Affaire', 'Personne'])
   300                           ['Affaire', 'Personne'])
   298         self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
   301         self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
   312                           ['Affaire', 'Note', 'Societe'])
   315                           ['Affaire', 'Note', 'Societe'])
   313         self.schema.rebuild_infered_relations() # need to be explicitly called once everything is in place
   316         self.schema.rebuild_infered_relations() # need to be explicitly called once everything is in place
   314         self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
   317         self.assertEqual(sorted(str(e) for e in self.schema['concerne'].objects()),
   315                           ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision'])
   318                           ['Affaire', 'Division', 'Note', 'Societe', 'SubDivision'])
   316         # trick: overwrite self.maxeid to avoid deletion of just reintroduced types
   319         # trick: overwrite self.maxeid to avoid deletion of just reintroduced types
   317         self.maxeid = self.execute('Any MAX(X)')[0][0]
   320         self.maxeid = self.session.execute('Any MAX(X)')[0][0]
   318 
   321 
   319     def test_rename_relation(self):
   322     def test_rename_relation(self):
   320         self.skipTest('implement me')
   323         self.skipTest('implement me')
   321 
   324 
   322     def test_change_relation_props_non_final(self):
   325     def test_change_relation_props_non_final(self):
   493                                           ('Bookmark', 'Note'),
   496                                           ('Bookmark', 'Note'),
   494                                           ('Note', 'Note'),
   497                                           ('Note', 'Note'),
   495                                           ('Note', 'Bookmark')]))
   498                                           ('Note', 'Bookmark')]))
   496                 self.assertEqual(sorted(schema['see_also'].subjects()), ['Bookmark', 'Folder', 'Note'])
   499                 self.assertEqual(sorted(schema['see_also'].subjects()), ['Bookmark', 'Folder', 'Note'])
   497                 self.assertEqual(sorted(schema['see_also'].objects()), ['Bookmark', 'Folder', 'Note'])
   500                 self.assertEqual(sorted(schema['see_also'].objects()), ['Bookmark', 'Folder', 'Note'])
   498                 self.assertEqual(self.execute('Any X WHERE X pkey "system.version.email"').rowcount, 0)
   501                 self.assertEqual(self.session.execute('Any X WHERE X pkey "system.version.email"').rowcount, 0)
   499                 self.assertEqual(self.execute('Any X WHERE X pkey "system.version.file"').rowcount, 0)
   502                 self.assertEqual(self.session.execute('Any X WHERE X pkey "system.version.file"').rowcount, 0)
   500             except :
   503             except :
   501                 import traceback
   504                 import traceback
   502                 traceback.print_exc()
   505                 traceback.print_exc()
   503                 raise
   506                 raise
   504         finally:
   507         finally:
   518                                       ('Note', 'Bookmark')]))
   521                                       ('Note', 'Bookmark')]))
   519             self.assertEqual(sorted(schema['see_also'].subjects()), ['Bookmark', 'EmailThread', 'Folder', 'Note'])
   522             self.assertEqual(sorted(schema['see_also'].subjects()), ['Bookmark', 'EmailThread', 'Folder', 'Note'])
   520             self.assertEqual(sorted(schema['see_also'].objects()), ['Bookmark', 'EmailThread', 'Folder', 'Note'])
   523             self.assertEqual(sorted(schema['see_also'].objects()), ['Bookmark', 'EmailThread', 'Folder', 'Note'])
   521             from cubes.email.__pkginfo__ import version as email_version
   524             from cubes.email.__pkginfo__ import version as email_version
   522             from cubes.file.__pkginfo__ import version as file_version
   525             from cubes.file.__pkginfo__ import version as file_version
   523             self.assertEqual(self.execute('Any V WHERE X value V, X pkey "system.version.email"')[0][0],
   526             self.assertEqual(self.session.execute('Any V WHERE X value V, X pkey "system.version.email"')[0][0],
   524                               email_version)
   527                               email_version)
   525             self.assertEqual(self.execute('Any V WHERE X value V, X pkey "system.version.file"')[0][0],
   528             self.assertEqual(self.session.execute('Any V WHERE X value V, X pkey "system.version.file"')[0][0],
   526                               file_version)
   529                               file_version)
   527             # trick: overwrite self.maxeid to avoid deletion of just reintroduced
   530             # trick: overwrite self.maxeid to avoid deletion of just reintroduced
   528             #        types (and their associated tables!)
   531             #        types (and their associated tables!)
   529             self.maxeid = self.execute('Any MAX(X)')[0][0]
   532             self.maxeid = self.session.execute('Any MAX(X)')[0][0]
   530             # why this commit is necessary is unclear to me (though without it
   533             # why this commit is necessary is unclear to me (though without it
   531             # next test may fail complaining of missing tables
   534             # next test may fail complaining of missing tables
   532             self.commit()
   535             self.session.commit(free_cnxset=False)
   533 
   536 
   534 
   537 
   535     @tag('longrun')
   538     @tag('longrun')
   536     def test_add_remove_cube_no_deps(self):
   539     def test_add_remove_cube_no_deps(self):
   537         cubes = set(self.config.cubes())
   540         cubes = set(self.config.cubes())
   552         finally:
   555         finally:
   553             self.mh.cmd_add_cube('email')
   556             self.mh.cmd_add_cube('email')
   554             self.assertTrue('email' in self.config.cubes())
   557             self.assertTrue('email' in self.config.cubes())
   555             # trick: overwrite self.maxeid to avoid deletion of just reintroduced
   558             # trick: overwrite self.maxeid to avoid deletion of just reintroduced
   556             #        types (and their associated tables!)
   559             #        types (and their associated tables!)
   557             self.maxeid = self.execute('Any MAX(X)')[0][0]
   560             self.maxeid = self.session.execute('Any MAX(X)')[0][0]
   558             # why this commit is necessary is unclear to me (though without it
   561             # why this commit is necessary is unclear to me (though without it
   559             # next test may fail complaining of missing tables
   562             # next test may fail complaining of missing tables
   560             self.commit()
   563             self.session.commit(free_cnxset=False)
   561 
   564 
   562     def test_remove_dep_cube(self):
   565     def test_remove_dep_cube(self):
   563         with self.assertRaises(ConfigurationError) as cm:
   566         with self.assertRaises(ConfigurationError) as cm:
   564             self.mh.cmd_remove_cube('file')
   567             self.mh.cmd_remove_cube('file')
   565         self.assertEqual(str(cm.exception), "can't remove cube file, used as a dependency")
   568         self.assertEqual(str(cm.exception), "can't remove cube file, used as a dependency")
   575         self.mh.repo.schema.rebuild_infered_relations()
   578         self.mh.repo.schema.rebuild_infered_relations()
   576         self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()),
   579         self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()),
   577                           ['Note', 'Text'])
   580                           ['Note', 'Text'])
   578         self.assertEqual(self.schema['Text'].specializes().type, 'Para')
   581         self.assertEqual(self.schema['Text'].specializes().type, 'Para')
   579         # test columns have been actually added
   582         # test columns have been actually added
   580         text = self.execute('INSERT Text X: X para "hip", X summary "hop", X newattr "momo"').get_entity(0, 0)
   583         text = self.session.execute('INSERT Text X: X para "hip", X summary "hop", X newattr "momo"').get_entity(0, 0)
   581         note = self.execute('INSERT Note X: X para "hip", X shortpara "hop", X newattr "momo", X unique_id "x"').get_entity(0, 0)
   584         note = self.session.execute('INSERT Note X: X para "hip", X shortpara "hop", X newattr "momo", X unique_id "x"').get_entity(0, 0)
   582         aff = self.execute('INSERT Affaire X').get_entity(0, 0)
   585         aff = self.session.execute('INSERT Affaire X').get_entity(0, 0)
   583         self.assertTrue(self.execute('SET X newnotinlined Y WHERE X eid %(x)s, Y eid %(y)s',
   586         self.assertTrue(self.session.execute('SET X newnotinlined Y WHERE X eid %(x)s, Y eid %(y)s',
   584                                      {'x': text.eid, 'y': aff.eid}))
   587                                      {'x': text.eid, 'y': aff.eid}))
   585         self.assertTrue(self.execute('SET X newnotinlined Y WHERE X eid %(x)s, Y eid %(y)s',
   588         self.assertTrue(self.session.execute('SET X newnotinlined Y WHERE X eid %(x)s, Y eid %(y)s',
   586                                      {'x': note.eid, 'y': aff.eid}))
   589                                      {'x': note.eid, 'y': aff.eid}))
   587         self.assertTrue(self.execute('SET X newinlined Y WHERE X eid %(x)s, Y eid %(y)s',
   590         self.assertTrue(self.session.execute('SET X newinlined Y WHERE X eid %(x)s, Y eid %(y)s',
   588                                      {'x': text.eid, 'y': aff.eid}))
   591                                      {'x': text.eid, 'y': aff.eid}))
   589         self.assertTrue(self.execute('SET X newinlined Y WHERE X eid %(x)s, Y eid %(y)s',
   592         self.assertTrue(self.session.execute('SET X newinlined Y WHERE X eid %(x)s, Y eid %(y)s',
   590                                      {'x': note.eid, 'y': aff.eid}))
   593                                      {'x': note.eid, 'y': aff.eid}))
   591         # XXX remove specializes by ourselves, else tearDown fails when removing
   594         # XXX remove specializes by ourselves, else tearDown fails when removing
   592         # Para because of Note inheritance. This could be fixed by putting the
   595         # Para because of Note inheritance. This could be fixed by putting the
   593         # MemSchemaCWETypeDel(session, name) operation in the
   596         # MemSchemaCWETypeDel(session, name) operation in the
   594         # after_delete_entity(CWEType) hook, since in that case the MemSchemaSpecializesDel
   597         # after_delete_entity(CWEType) hook, since in that case the MemSchemaSpecializesDel
   596         #
   599         #
   597         # also we need more tests about introducing/removing base classes or
   600         # also we need more tests about introducing/removing base classes or
   598         # specialization relationship...
   601         # specialization relationship...
   599         self.session.data['rebuild-infered'] = True
   602         self.session.data['rebuild-infered'] = True
   600         try:
   603         try:
   601             self.execute('DELETE X specializes Y WHERE Y name "Para"')
   604             self.session.execute('DELETE X specializes Y WHERE Y name "Para"')
   602             self.commit()
   605             self.session.commit(free_cnxset=False)
   603         finally:
   606         finally:
   604             self.session.data['rebuild-infered'] = False
   607             self.session.data['rebuild-infered'] = False
   605         self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()),
   608         self.assertEqual(sorted(et.type for et in self.schema['Para'].specialized_by()),
   606                           [])
   609                           [])
   607         self.assertEqual(self.schema['Note'].specializes(), None)
   610         self.assertEqual(self.schema['Note'].specializes(), None)