Changeset 47
- Timestamp:
- 02/12/07 15:27:25 (6 years ago)
- Location:
- elixir/trunk
- Files:
-
- 1 added
- 12 modified
-
elixir/__init__.py (modified) (2 diffs)
-
elixir/entity.py (modified) (12 diffs)
-
elixir/fields.py (modified) (1 diff)
-
elixir/options.py (modified) (6 diffs)
-
elixir/relationships.py (modified) (15 diffs)
-
tests/test_autoload.py (added)
-
tests/test_hasfield.py (modified) (1 diff)
-
tests/test_movies.py (modified) (2 diffs)
-
tests/test_multi.py (modified) (3 diffs)
-
tests/test_oneway.py (modified) (4 diffs)
-
tests/test_options.py (modified) (1 diff)
-
tests/test_order_by.py (modified) (6 diffs)
-
tests/test_selfref.py (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
elixir/trunk/elixir/__init__.py
r45 r47 30 30 'belongs_to', 'has_one', 'has_many', 'has_and_belongs_to_many', 31 31 'using_options', 'using_table_options', 'using_mapper_options', 32 'create_all', 'drop_all', 'metadata', 'objectstore'] + \ 32 'options_defaults', 'metadata', 'objectstore', 33 'create_all', 'drop_all', 'setup_all', 'cleanup_all', 34 'delay_setup'] + \ 33 35 sqlalchemy.types.__all__ 34 36 35 __pudge_all__ = ['create_all', 'drop_all', 'metadata', 'objectstore'] 37 __pudge_all__ = ['create_all', 'drop_all', 'metadata', 'objectstore', 38 'delay_setup', 'setup_all'] 36 39 37 40 # connect … … 62 65 for md in metadatas: 63 66 md.drop_all() 67 68 delayed_entities = set() 69 delay_setup = False 70 71 def setup_all(): 72 '''Setup the table and mapper for all entities which have been delayed. 73 74 This should be used in conjunction with setting ``delay_setup`` to ``True`` 75 before defining your entities. 76 ''' 77 global delay_setup 78 delay_setup = False 79 for entity in delayed_entities: 80 entity.setup() 81 delayed_entities.clear() 82 create_all() 83 84 def cleanup_all(): 85 drop_all() 86 for md in metadatas: 87 md.clear() 88 metadatas.clear() 89 EntityDescriptor.uninitialized_rels.clear() 90 91 objectstore.clear() 92 sqlalchemy.clear_mappers() 93 -
elixir/trunk/elixir/entity.py
r46 r47 7 7 from elixir.statements import Statement 8 8 from elixir.fields import Field 9 from elixir.options import options_defaults 9 10 10 11 import sys … … 18 19 DEFAULT_AUTO_PRIMARYKEY_NAME = "id" 19 20 DEFAULT_AUTO_PRIMARYKEY_TYPE = Integer 20 21 class Entity(object):22 '''23 The base class for all entities24 25 All Elixir model objects should inherit from this class. Statements can26 appear within the body of the definition of an entity to define its27 fields, relationships, and other options.28 29 Here is an example:30 31 ::32 33 class Person(Entity):34 has_field('name', Unicode(128))35 has_field('birthdate', DateTime, default=datetime.now)36 37 Please note, that if you don't specify any primary keys, Elixir will38 automatically create one called ``id``.39 40 For further information, please refer to the provided examples or41 tutorial.42 '''43 44 class __metaclass__(type):45 def __init__(cls, name, bases, dict_):46 # only process subclasses of Entity, not Entity itself47 if bases[0] is object:48 return49 50 # create the entity descriptor51 desc = cls._descriptor = EntityDescriptor(cls)52 EntityDescriptor.current = desc53 54 # process statements55 Statement.process(cls)56 57 # setup misc options here (like tablename etc.)58 desc.setup_options()59 60 # create table & assign (empty) mapper61 desc.setup()62 63 # try to setup all uninitialized relationships64 EntityDescriptor.setup_relationships()65 21 66 22 … … 90 46 91 47 # set default value for options 48 self.order_by = None 49 self.tablename = None 92 50 self.metadata = getattr(self.module, 'metadata', elixir.metadata) 93 self.autoload = None 94 self.tablename = None 95 self.shortnames = False 96 self.auto_primarykey = True 97 self.order_by = None 98 self.mapper_options = dict() 99 self.table_options = dict() 51 52 for option in ('autoload', 'shortnames', 'auto_primarykey'): 53 setattr(self, option, options_defaults[option]) 54 55 for option_dict in ('mapper_options', 'table_options'): 56 setattr(self, option_dict, options_defaults[option_dict].copy()) 100 57 101 58 def setup_options(self): … … 122 79 ''' 123 80 81 if elixir.delay_setup: 82 elixir.delayed_entities.add(self) 83 return 84 85 self.setup_table() 124 86 self.setup_mapper() 125 87 … … 128 90 EntityDescriptor.uninitialized_rels.update( 129 91 self.relationships.values()) 92 93 # try to setup all uninitialized relationships 94 EntityDescriptor.setup_relationships() 130 95 131 96 def setup_mapper(self): … … 138 103 139 104 session = getattr(self.module, 'session', elixir.objectstore) 140 table = self.setup_table()141 105 142 106 kwargs = self.mapper_options … … 144 108 kwargs['order_by'] = self.translate_order_by(self.order_by) 145 109 146 assign_mapper(session.context, self.entity, table, **kwargs) 110 assign_mapper(session.context, self.entity, self.entity.table, 111 **kwargs) 147 112 elixir.metadatas.add(self.metadata) 148 113 … … 157 122 col = desc(col) 158 123 order.append(col) 159 160 124 return order 161 125 … … 183 147 kwargs['autoload'] = True 184 148 185 table = Table(self.tablename, self.metadata, *args, **kwargs) 186 self.entity.table = table 187 return table 149 self.entity.table = Table(self.tablename, self.metadata, 150 *args, **kwargs) 188 151 189 152 def create_auto_primary_key(self): … … 232 195 raise Exception( 233 196 "Several relations match as inverse of the '%s' " 234 "relation in class'%s'. You should specify "197 "relation in entity '%s'. You should specify " 235 198 "inverse relations manually by using the inverse " 236 199 "keyword." … … 246 209 return matching_rel 247 210 248 249 211 @classmethod 250 212 def setup_relationships(cls): … … 253 215 EntityDescriptor.uninitialized_rels.remove(relationship) 254 216 217 218 class Entity(object): 219 ''' 220 The base class for all entities 221 222 All Elixir model objects should inherit from this class. Statements can 223 appear within the body of the definition of an entity to define its 224 fields, relationships, and other options. 225 226 Here is an example: 227 228 :: 229 230 class Person(Entity): 231 has_field('name', Unicode(128)) 232 has_field('birthdate', DateTime, default=datetime.now) 233 234 Please note, that if you don't specify any primary keys, Elixir will 235 automatically create one called ``id``. 236 237 For further information, please refer to the provided examples or 238 tutorial. 239 ''' 240 241 class __metaclass__(type): 242 def __init__(cls, name, bases, dict_): 243 # only process subclasses of Entity, not Entity itself 244 if bases[0] is object: 245 return 246 247 # create the entity descriptor 248 desc = cls._descriptor = EntityDescriptor(cls) 249 EntityDescriptor.current = desc 250 251 # process statements 252 Statement.process(cls) 253 254 # setup misc options here (like tablename etc.) 255 desc.setup_options() 256 257 # create table & assign (empty) mapper 258 desc.setup() 259 -
elixir/trunk/elixir/fields.py
r45 r47 1 1 ''' 2 Field statements for Elixir entities 3 2 4 ====== 3 5 Fields -
elixir/trunk/elixir/options.py
r46 r47 1 1 ''' 2 Option statements for Elixir entities 3 2 4 ======= 3 5 Options … … 6 8 This module provides DSL statements for defining options on your Elixir 7 9 entities. There are three different kinds of options that can be set 8 up, and for this there are three different statements: 9 10 up, and for this there are three different statements: using_options_, 11 using_table_options_ and using_mapper_options_. Alternatively, options can be 12 set on all Elixir entities by modifying the `options_defaults` dictionary 13 before defining any entity. 10 14 11 15 `using_options` … … 25 29 The list of supported arguments are as follows: 26 30 27 +---------------------+---------------------------------------------------+ 28 | Option Name | Description | 29 +=====================+===================================================+ 30 | ``metadata`` | Specify a custom MetaData | 31 +---------------------+---------------------------------------------------+ 32 | ``autoload`` | Automatically load column definitions from the | 33 | | existing database table | 34 +---------------------+---------------------------------------------------+ 35 | ``tablename`` | Specify a custom tablename | 36 +---------------------+---------------------------------------------------+ 37 | ``shortnames`` | Usually tablenames include the full module-path | 38 | | to the entity, but lower-cased and separated by | 39 | | underscores ("_"), eg.: "project1_model_myentity" | 40 | | for an entity named "MyEntity" in the module | 41 | | "project1.model". If shortnames is True, the | 42 | | tablename will just be the entity's classname | 43 | | lower-cased, ie. "myentity". | 44 +---------------------+---------------------------------------------------+ 45 | ``auto_primarykey`` | If given as string, it will represent the | 46 | | auto-primary-key's column name. If this option | 47 | | is True, it will allow auto-creation of a primary | 48 | | key if there's no primary key defined for the | 49 | | corresponding entity. If this option is False, | 50 | | it will disallow auto-creation of a primary key. | 51 +---------------------+---------------------------------------------------+ 52 | ``order_by`` | How to order select results. Either a string or a | 53 | | list of strings, composed of the field name, | 54 | | optionally lead by a minus (descending order). | 55 +---------------------+---------------------------------------------------+ 31 +---------------------+-------------------------------------------------------+ 32 | Option Name | Description | 33 +=====================+=======================================================+ 34 | ``metadata`` | Specify a custom MetaData | 35 +---------------------+-------------------------------------------------------+ 36 | ``autoload`` | Automatically load column definitions from the | 37 | | existing database table. For now, it does **not** | 38 | | work for ``has_and_belongs_to_many`` relationships. | 39 | | Using autoloaded tables implies setting | 40 | | ``delay_setup`` to ``True`` before defining your | 41 | | entities. | 42 +---------------------+-------------------------------------------------------+ 43 | ``tablename`` | Specify a custom tablename | 44 +---------------------+-------------------------------------------------------+ 45 | ``shortnames`` | Usually tablenames include the full module-path | 46 | | to the entity, but lower-cased and separated by | 47 | | underscores ("_"), eg.: "project1_model_myentity" | 48 | | for an entity named "MyEntity" in the module | 49 | | "project1.model". If shortnames is True, the | 50 | | tablename will just be the entity's classname | 51 | | lower-cased, ie. "myentity". | 52 +---------------------+-------------------------------------------------------+ 53 | ``auto_primarykey`` | If given as string, it will represent the | 54 | | auto-primary-key's column name. If this option | 55 | | is True, it will allow auto-creation of a primary | 56 | | key if there's no primary key defined for the | 57 | | corresponding entity. If this option is False, | 58 | | it will disallow auto-creation of a primary key. | 59 +---------------------+-------------------------------------------------------+ 60 | ``order_by`` | How to order select results. Either a string or a | 61 | | list of strings, composed of the field name, | 62 | | optionally lead by a minus (descending order). | 63 +---------------------+-------------------------------------------------------+ 56 64 57 65 For examples, please refer to the examples and unit tests. … … 67 75 without any processing. 68 76 69 For further information, please refer to the SQLAlchemy documentation.70 77 For further information, please refer to the `SQLAlchemy table's documentation <http://www.sqlalchemy.org/docs/docstrings.myt 78 #docstrings_sqlalchemy.schema_Table>`_. 71 79 72 80 `using_mapper_options` … … 79 87 without any processing. 80 88 81 For further information, please refer to the SQLAlchemy documentation. 89 For further information, please refer to the `SQLAlchemy mapper 90 function's documentation <http://www.sqlalchemy.org/docs/adv_datamapping.myt 91 #advdatamapping_mapperoptions>`_. 82 92 ''' 83 93 84 94 from elixir.statements import Statement 85 95 86 __all__ = ['using_options', 'using_table_options', 'using_mapper_options'] 96 __all__ = ['using_options', 'using_table_options', 'using_mapper_options', 97 'options_defaults'] 87 98 88 __pudge_all__ = [] 99 __pudge_all__ = ['options_defaults'] 100 101 options_defaults = dict( 102 autoload=None, 103 shortnames=False, 104 auto_primarykey=True, 105 mapper_options=dict(), 106 table_options=dict(), 107 ) 89 108 90 109 class UsingOptions(object): … … 108 127 class UsingTableOptions(object): 109 128 def __init__(self, entity, *args, **kwargs): 110 entity._descriptor.table_options = kwargs129 entity._descriptor.table_options.update(kwargs) 111 130 112 131 113 132 class UsingMapperOptions(object): 114 133 def __init__(self, entity, *args, **kwargs): 115 entity._descriptor.mapper_options = kwargs134 entity._descriptor.mapper_options.update(kwargs) 116 135 117 136 -
elixir/trunk/elixir/relationships.py
r45 r47 1 1 ''' 2 Relationship statements for Elixir entities 3 2 4 ============= 3 5 Relationships … … 28 30 keyword arguments are supported, but you should keep in mind, the following 29 31 keyword arguments are taken care of by Elixir and should not be used: 30 ``uselist``, ``remote_side``, ``primaryjoin`` and ``secondaryjoin``. 32 ``uselist``, ``remote_side``, ``secondary``, ``primaryjoin`` and 33 ``secondaryjoin``. 31 34 32 35 .. _order_by: … … 58 61 foreign key referencing the `id` column of the `Person` entity. 59 62 63 In addition to the keyword arguments inherited from SQLAlchemy, ``belongs_to`` 64 relationships accept an optional ``colname`` keyword argument, used to specify 65 a custom name for the column which will be created. 66 60 67 `has_one` 61 68 --------- … … 92 99 Note that an ``has_many`` relationship **cannot exist** without a 93 100 corresponding ``belongs_to`` relationship in the other way. This is because the 94 ``has_one`` relationship needs the foreign _key created by the ``belongs_to``101 ``has_one`` relationship needs the foreign key created by the ``belongs_to`` 95 102 relationship. 96 103 … … 164 171 self.kwargs = kwargs 165 172 166 #CHECKME: is this useful?167 173 self.entity._descriptor.relationships[self.name] = self 168 169 def create_keys(self, autoload=False): 174 self.setup_done = False 175 176 def create_keys(self): 170 177 ''' 171 178 Subclasses (ie. concrete relationships) may override this method to … … 193 200 return False 194 201 202 if self.setup_done: 203 return True 204 205 # FIXME: this should only happen if the relation was not setup already 195 206 self.create_keys() 196 207 self.create_tables() 197 208 self.create_properties() 209 self.setup_done = True 198 210 199 211 return True … … 274 286 ''' 275 287 276 277 def create_keys(self, autoload=False): 288 def __init__(self, entity, name, *args, **kwargs): 289 self.colname = kwargs.pop('colname', None) 290 if self.colname and not isinstance(self.colname, list): 291 self.colname = [self.colname] 292 super(BelongsTo, self).__init__(entity, name, *args, **kwargs) 293 294 def create_keys(self): 278 295 ''' 279 296 Find all primary keys on the target and create foreign keys on the … … 284 301 target_desc = self.target._descriptor 285 302 303 #FIXME: this is buggy, because it seems 304 # like the field is used for two different purpose. 305 # FK is what? 306 307 # convert strings to Field instances 286 308 if self.foreign_key: 287 309 self.foreign_key = [source_desc.fields[k] … … 289 311 if isinstance(k, basestring)] 290 312 return 291 292 fk_refcols = list()293 fk_colnames = list()294 313 295 314 self.foreign_key = list() 296 315 self.primaryjoin_clauses = list() 297 316 298 for key in target_desc.primary_keys: 299 pk_col = key.column 300 301 colname = '%s_%s' % (self.name, pk_col.name) 302 # we use a Field here instead of using a Column directly 303 # because of add_field 304 field = Field(pk_col.type, colname=colname, index=True) 305 source_desc.add_field(field) 306 307 self.foreign_key.append(field) 308 309 # build the list of local columns which will be part of 310 # the foreign key 311 fk_colnames.append(colname) 312 313 # build the list of columns the foreign key will point to 314 fk_refcols.append(target_desc.tablename + '.' + pk_col.name) 315 316 # build up the primary join. This is needed when you have several 317 # belongs_to relations between two objects 318 self.primaryjoin_clauses.append(field.column == pk_col) 319 320 # TODO: better constraint-naming? 321 #CHECKME: do we really need use_alter systematically? 322 source_desc.add_constraint(ForeignKeyConstraint( 323 fk_colnames, fk_refcols, 324 name=self.name +'_fk', 325 use_alter=True)) 317 if source_desc.autoload: 318 if not self.colname: 319 raise Exception( 320 "Entity '%s' is autoloaded but relation '%s' has no " 321 "column name specified. You should specify it by " 322 "using the colname keyword." 323 % (self.entity.__name__, self.name) 324 ) 325 326 #TODO: test if this works when colname is a list 327 for colname in self.colname: 328 for col in self.entity.table.columns: 329 if col.name == colname: 330 # We need to take the first foreign key, but 331 # foreign_keys is an util.OrderedSet which doesn't 332 # support indexation. 333 fk_iter = iter(col.foreign_keys) 334 fk = fk_iter.next() 335 self.primaryjoin_clauses.append(col == fk.column) 336 337 if not self.primaryjoin_clauses: 338 raise Exception("Column '%s' not found in table '%s'" 339 % (self.colname, self.entity.table.name)) 340 else: 341 fk_refcols = list() 342 fk_colnames = list() 343 344 if self.colname and \ 345 len(self.colname) != len(target_desc.primary_keys): 346 raise Exception( 347 "The number of column names provided in the colname " 348 "keyword argument of the '%s' relationship of the " 349 "'%s' entity is not the same as the number of columns " 350 "of the primary key of '%s'." 351 % (self.name, self.entity.__name__, 352 self.target.__name__) 353 ) 354 355 for key_num, key in enumerate(target_desc.primary_keys): 356 pk_col = key.column 357 358 if self.colname: 359 colname = self.colname[key_num] 360 else: 361 colname = '%s_%s' % (self.name, pk_col.name) 362 363 # we use a Field here instead of using a Column directly 364 # because of add_field 365 field = Field(pk_col.type, colname=colname, index=True) 366 source_desc.add_field(field) 367 368 self.foreign_key.append(field) 369 370 # build the list of local columns which will be part of 371 # the foreign key 372 fk_colnames.append(colname) 373 374 # build the list of columns the foreign key will point to 375 fk_refcols.append(target_desc.tablename + '.' + pk_col.name) 376 377 # build up the primary join. This is needed when you have 378 # several belongs_to relations between two objects 379 self.primaryjoin_clauses.append(field.column == pk_col) 380 381 # TODO: better constraint-naming? 382 #CHECKME: do we really need use_alter systematically? 383 source_desc.add_constraint(ForeignKeyConstraint( 384 fk_colnames, fk_refcols, 385 name=self.name +'_fk', 386 use_alter=True)) 326 387 327 388 def create_properties(self): … … 342 403 uselist = False 343 404 344 def create_keys(self , autoload=False):405 def create_keys(self): 345 406 # make sure the inverse is set up because it creates the 346 407 # foreign key we'll need … … 350 411 kwargs = self.kwargs 351 412 413 #TODO: for now, we don't break any test if we remove those 3 lines. 414 # So, we should either complete the selfref test to prove that they 415 # are indeed useful, or remove them. It might be they are indeed 416 # useless because of the primaryjoin, and that the remote_side is 417 # already setup in the other way (belongs_to). 352 418 if self.entity is self.target: 419 #FIXME: this won't work for autoloaded relations 420 # so I need to change the type of foreign_key 353 421 kwargs['remote_side'] = [field.column 354 422 for field in self.inverse.foreign_key] … … 376 444 def __init__(self, entity, name, *args, **kwargs): 377 445 self.user_tablename = kwargs.pop('tablename', None) 378 self.secondary = None446 self.secondary_table = None 379 447 super(HasAndBelongsToMany, self).__init__(entity, name, 380 448 *args, **kwargs) … … 382 450 def create_tables(self): 383 451 if self.inverse: 384 if self.inverse.secondary :385 self.secondary = self.inverse.secondary452 if self.inverse.secondary_table: 453 self.secondary_table = self.inverse.secondary_table 386 454 self.primaryjoin_clauses = self.inverse.secondaryjoin_clauses 387 455 self.secondaryjoin_clauses = self.inverse.primaryjoin_clauses 388 456 389 if not self.secondary :457 if not self.secondary_table: 390 458 e1_desc = self.entity._descriptor 391 459 e2_desc = self.target._descriptor … … 461 529 462 530 args = columns + constraints 463 self.secondary = Table(tablename, e1_desc.metadata, *args)531 self.secondary_table = Table(tablename, e1_desc.metadata, *args) 464 532 465 533 def create_properties(self): … … 474 542 self.target._descriptor.translate_order_by(kwargs['order_by']) 475 543 476 self.property = relation(self.target, secondary=self.secondary ,544 self.property = relation(self.target, secondary=self.secondary_table, 477 545 uselist=True, **kwargs) 478 546 self.entity.mapper.add_property(self.name, self.property) -
elixir/trunk/tests/test_hasfield.py
r17 r47 24 24 25 25 def teardown(self): 26 drop_all()26 cleanup_all() 27 27 28 28 def test_hasfield(self): -
elixir/trunk/tests/test_movies.py
r17 r47 7 7 from sqlalchemy import create_engine 8 8 from elixir import * 9 10 9 11 10 class Director(Entity): … … 63 62 64 63 def teardown(self): 65 drop_all()64 cleanup_all() 66 65 67 66 def test_bidirectional(self): -
elixir/trunk/tests/test_multi.py
r17 r47 8 8 from elixir import * 9 9 10 #TODO: test multi-col-pk VS many2many selfref11 12 # multi belongs-to13 class Person(Entity):14 has_field('name', Unicode(32))15 16 has_many('pets', of_kind='Animal', inverse='owner')17 has_many('animals', of_kind='Animal', inverse='feeder')18 19 def __str__(self):20 s = '%s\n' % self.name.encode('utf-8')21 for pet in self.pets:22 s += ' * pet: %s\n' % pet.name23 return s24 25 class Animal(Entity):26 has_field('name', String(15))27 has_field('color', String(15))28 29 belongs_to('owner', of_kind='Person')30 belongs_to('feeder', of_kind='Person')31 32 10 #----------- 33 11 34 class Article(Entity): 35 has_field('title', String(100)) 12 class TestMultiBelongsTo(object): 13 def setup(self): 14 global Person, Animal 15 16 #--------------------------------------- 17 # classes for the multi belongs_to test 36 18 37 has_and_belongs_to_many('editor_tags', of_kind='Tag') 38 has_and_belongs_to_many('user_tags', of_kind='Tag') 39 40 class Tag(Entity): 41 has_field('name', String(20), primary_key=True) 19 class Person(Entity): 20 has_field('name', Unicode(32)) 21 22 has_many('pets', of_kind='Animal', inverse='owner') 23 has_many('animals', of_kind='Animal', inverse='feeder') 24 25 def __str__(self): 26 s = '%s\n' % self.name.encode('utf-8') 27 for pet in self.pets: 28 s += ' * pet: %s\n' % pet.name 29 return s 42 30 43 #----------- 31 class Animal(Entity): 32 has_field('name', String(15)) 33 has_field('color', String(15)) 34 35 belongs_to('owner', of_kind='Person') 36 belongs_to('feeder', of_kind='Person') 44 37 45 class TestMulti(object):46 def setup(self):47 38 engine = sqlalchemy.create_engine('sqlite:///') 48 # engine.echo = True49 39 metadata.connect(engine) 50 40 create_all() 51 41 52 42 def teardown(self): 53 drop_all()43 cleanup_all() 54 44 55 45 def test_belongs_to_multi_ref(self): … … 70 60 assert homer == lisa.pets[0].feeder 71 61 assert homer == slh.owner 62 63 class TestMultiHasAndBelongsToMany(object): 64 def setup(self): 65 global Article, Tag 66 67 class Article(Entity): 68 has_field('title', String(100)) 69 70 has_and_belongs_to_many('editor_tags', of_kind='Tag') 71 has_and_belongs_to_many('user_tags', of_kind='Tag') 72 73 class Tag(Entity): 74 has_field('name', String(20), primary_key=True) 75 76 engine = sqlalchemy.create_engine('sqlite:///') 77 metadata.connect(engine) 78 create_all() 79 80 def teardown(self): 81 cleanup_all() 72 82 73 83 def test_has_and_belongs_to_many_multi_ref(self): … … 96 106 test.test_belongs_to_multi_ref() 97 107 test.teardown() 108 109 test = TestMultiHasAndBelongsToMany() 98 110 test.setup() 99 111 test.test_has_and_belongs_to_many_multi_ref() -
elixir/trunk/tests/test_oneway.py
r17 r47 8 8 from elixir import * 9 9 10 #FIXME: this shouldn't be necessary. cleanup_all should handle it. The problem 11 # is that with this damn dynamic behavior, we can't easily re-setup the 12 # entities once they've been setup once 13 metadata.clear() 10 14 11 15 class Person(Entity): … … 13 17 name = Field(Unicode(30)) 14 18 ) 15 16 using_options(shortnames=True, order_by="name")17 18 19 19 20 class Animal(Entity): … … 24 25 25 26 belongs_to('owner', of_kind='Person') 26 27 using_options(shortnames=True, order_by="name")28 27 29 28 … … 35 34 36 35 def teardown(self): 37 drop_all()36 cleanup_all() 38 37 39 38 def test_oneway(self): -
elixir/trunk/tests/test_options.py
r22 r47 28 28 29 29 def teardown(self): 30 drop_all()30 cleanup_all() 31 31 32 32 -
elixir/trunk/tests/test_order_by.py
r22 r47 3 3 """ 4 4 5 import nose6 5 from sqlalchemy import create_engine 7 6 from elixir import * … … 32 31 def setup(self): 33 32 engine = create_engine('sqlite:///') 33 # engine.echo = True 34 34 metadata.connect(engine) 35 35 create_all() … … 57 57 58 58 def teardown(self): 59 # we don't use cleanup_all because setup and teardown are called for 60 # each test, and since the class is not redefined, it will not be 61 # reinitialized so we can't kill it 59 62 drop_all() 60 63 … … 62 65 records = Record.select() 63 66 64 print "-year, title"67 print "-year, +title" 65 68 for record in records: 66 69 print record … … 74 77 records = Artist.get_by(name="Dream Theater").records 75 78 76 print "+year, title"79 print "+year, -title" 77 80 for record in records: 78 81 print record … … 81 84 assert records[2].year <= records[5].year 82 85 assert records[3].year <= records[4].year 86 assert records[-1].title == 'Octavarium' 83 87 assert records[-1].year == 2005 84 88 -
elixir/trunk/tests/test_selfref.py
r17 r47 7 7 8 8 9 class Person(Entity):10 with_fields(11 name = Field(Unicode(30))12 )13 14 belongs_to('father', of_kind='Person', inverse='children')15 has_many('children', of_kind='Person', inverse='father')16 has_and_belongs_to_many('friends', of_kind='Person')17 18 # define a self-referential table with several relations19 class TreeNode(Entity):20 has_field('name', String(50), nullable=False)21 22 belongs_to('parent', of_kind='TreeNode')23 has_many('children', of_kind='TreeNode', inverse='parent')24 belongs_to('root', of_kind='TreeNode')25 26 def __str__(self):27 return self._getstring(0)28 29 def _getstring(self, level):30 s = (' ' * level) + "%s (%s,%s,%s, %d)" % (self.name, self.id, self.parent_id, self.root_id, id(self)) + '\n'31 s += ''.join([n._getstring(level+1) for n in self.children])32 return s33 34 9 class TestSelfRef(object): 35 10 def setup(self): 36 11 engine = create_engine('sqlite:///') 37 12 metadata.connect(engine) 38 # engine.echo = True39 create_all()40 13 41 14 def teardown(self): 42 drop_all()15 cleanup_all() 43 16 44 17 def test_belongs_to_selfref(self): 18 class Person(Entity): 19 with_fields( 20 name = Field(Unicode(30)) 21 ) 22 23 belongs_to('father', of_kind='Person', inverse='children') 24 has_many('children', of_kind='Person', inverse='father') 25 26 create_all() 27 45 28 grampa = Person(name="Abe") 46 29 homer = Person(name="Homer") … … 66 49 67 50 def test_has_and_belongs_to_many_selfref(self): 51 class Person(Entity): 52 with_fields( 53 name = Field(Unicode(30)) 54 ) 55 56 has_and_belongs_to_many('friends', of_kind='Person') 57 58 create_all() 59 68 60 barney = Person(name="Barney") 69 61 homer = Person(name="Homer", friends=[barney]) … … 79 71 assert barney in homer.friends 80 72 73 class TestMultiSelfRef(object): 74 def setup(self): 75 engine = create_engine('sqlite:///') 76 metadata.connect(engine) 77 78 def teardown(self): 79 cleanup_all() 80 81 81 def test_belongs_to_multiple_selfref(self): 82 # define a self-referential table with several relations 83 class TreeNode(Entity): 84 has_field('name', String(50), nullable=False) 85 86 belongs_to('parent', of_kind='TreeNode') 87 has_many('children', of_kind='TreeNode', inverse='parent') 88 belongs_to('root', of_kind='TreeNode') 89 90 def __str__(self): 91 return self._getstring(0) 92 93 def _getstring(self, level): 94 s = ' ' * level + \ 95 "%s (%s,%s,%s, %d)" % (self.name, self.id, self.parent_id, 96 self.root_id, id(self)) + \ 97 '\n' 98 s += ''.join([n._getstring(level+1) for n in self.children]) 99 return s 100 101 create_all() 102 82 103 node2 = TreeNode(name='node2') 83 104 node2.children.append(TreeNode(name='subnode1')) … … 102 123 test.test_has_and_belongs_to_many_selfref() 103 124 test.teardown() 125 126 test = TestMultiSelfRef() 104 127 test.setup() 105 128 test.test_belongs_to_multiple_selfref()
