Contact: fumanchu@aminus.org

Log in as guest/geniusql to create tickets

Changeset 4

Show
Ignore:
Timestamp:
02/12/07 05:59:01
Author:
fumanchu
Message:

More tests (and they all pass, now). Also:

  1. The semantic where Table.db was inspected to see if the table had already been created has been replaced by Table.created. This allows Table objects to hold a ref to their db before they are created. The 'db' arg to Table constructor is now mandatory.
  2. The Column signature has changed, placing the name and qname at the end. Table.__setitem__ now sets those if they haven't already been set.
  3. Some Database method names have changed:
    • "column_name" is now "_column_name" (and takes a Table.name now, instead of a tablekey).
    • "make_column" is now "column" (and takes no keys).
    • "make_table" is now called "table".
    • "make_index" has been replaced by Table.add_index.
  4. Fixed an ID bug in Database.save.
  5. Fixed Firebird.insert.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/geniusql/__init__.py

    r3 r4  
    5050     
    5151    opts = dict([(str(k), v) for k, v in options.iteritems()]) 
     52    opts.pop('name', None) 
    5253     
    5354    return cls(name, **opts) 
     
    101102        """Drop the specified index.""" 
    102103        t = self.table 
    103         if t.db is not None
     104        if t.created
    104105            t.db.lock("Creating index. Transactions not allowed.") 
    105106            try: 
     
    114115        """Drop the specified index.""" 
    115116        t = self.table 
    116         if t.db is not None
     117        if t.created
    117118            t.db.lock("Dropping index. Transactions not allowed.") 
    118119            try: 
     
    142143    """ 
    143144     
    144     def __init__(self, name, qname, dbtype, default=None, hints=None, key=False): 
     145    def __init__(self, dbtype, default=None, hints=None, key=False, 
     146                 name=None, qname=None): 
     147        self.dbtype = dbtype 
    145148        self.name = name 
    146149        self.qname = qname 
    147         self.dbtype = dbtype 
    148150        self.default = default 
    149151        if hints is None: 
    150152            hints = {} 
     153        else: 
     154            hints = hints.copy() 
    151155        self.hints = hints 
    152156        self.key = key 
     
    196200    indexsetclass = IndexSet 
    197201     
    198     def __new__(cls, name, qname, db=None): 
     202    def __new__(cls, name, qname, db, created=False): 
    199203        return dict.__new__(cls) 
    200204     
    201     def __init__(self, name, qname, db=None): 
     205    def __init__(self, name, qname, db, created=False): 
    202206        dict.__init__(self) 
     207         
    203208        self.name = name 
    204209        self.qname = qname 
    205210        self.db = db 
     211        self.created = created 
     212         
    206213        self.indices = self.indexsetclass(self) 
    207214        self.references = {} 
     
    242249     
    243250    def __setitem__(self, key, column): 
    244         if self.db is None: 
     251        if column.name is None: 
     252            column.name = self.db._column_name(self.name, key) 
     253            column.qname = self.db.quote(column.name) 
     254         
     255        if not self.created: 
    245256            dict.__setitem__(self, key, column) 
    246257            return 
     
    268279            del self.indices[key] 
    269280         
    270         if self.db is None
     281        if not self.created
    271282            dict.__delitem__(self, key) 
    272283            return 
     
    292303        oldcol = self[oldkey] 
    293304         
    294         if self.db is None
     305        if not self.created
    295306            dict.__delitem__(self, oldkey) 
    296307            dict.__setitem__(self, newkey, oldcol) 
     
    298309         
    299310        oldname = oldcol.name 
    300         newname = self.db.column_name(self.name, newkey) 
     311        newname = self.db._column_name(self.name, newkey) 
    301312         
    302313        if oldname != newname: 
     
    313324        dict.__delitem__(self, oldkey) 
    314325        dict.__setitem__(self, newkey, newcol) 
     326     
     327    def add_index(self, columnkey): 
     328        """Add and return a new Index for the given column key. 
     329         
     330        The new Index object will possess the same key as the column. 
     331        In general, the actual SQL name of the new Index will be of 
     332        the form: "i" + table.name + column.name. 
     333        """ 
     334        colname = self[columnkey].name 
     335        name = self.db.table_name("i" + self.name + colname) 
     336        i = Index(name, self.db.quote(name), self.name, colname) 
     337        self.indices[columnkey] = i 
     338        return i 
    315339 
    316340 
     
    544568            del self[key] 
    545569         
    546         # Set table.db to self, which should "turn on" 
     570        # Set table.created to True, which should "turn on" 
    547571        # any future ALTER TABLE statements. 
    548         table.db = self 
     572        table.created = True 
    549573         
    550574        self.lock("Creating storage. Transactions not allowed.") 
     
    592616        # Override this to do the actual rename at the DB level. 
    593617        raise NotImplementedError 
     618        newtable.created = True 
    594619     
    595620    def rename(self, oldkey, newkey): 
     
    639664        return key 
    640665     
    641     def column_name(self, tablekey, columnkey): 
    642         """Return the SQL column name for the given table and column keys.""
     666    def _column_name(self, tablename, columnkey): 
     667        "Return the SQL column name for the given table name and column key.
    643668        # If you want to use a map from your ORM's property names 
    644669        # to DB column names, override this method (that's why 
     
    646671        return self.sql_name(columnkey) 
    647672     
    648     def make_column(self, tablekey, columnkey, pytype=unicode, default=None, hints=None): 
    649         """Return a Column object from the given table and column keys.""" 
    650         name = self.column_name(tablekey, columnkey) 
    651         if hints is None: 
    652             hints = {} 
    653         else: 
    654             hints = hints.copy() 
    655         col = Column(name, self.quote(name), None, default, hints) 
     673    def column(self, pytype=unicode, default=None, hints=None, 
     674               key=False, autoincrement=False): 
     675        """Return a Column object from the given arguments.""" 
     676        col = Column(None, default, hints) 
    656677        col.dbtype = self.typeadapter.coerce(col, pytype) 
    657678        pytype2 = self.python_type(col.dbtype) 
    658679        col.imperfect_type = not self.isrelatedtype(pytype, pytype2) 
     680        col.key = key 
     681        col.autoincrement = autoincrement 
    659682        return col 
    660683     
     
    665688        return self.sql_name(self.Prefix + key) 
    666689     
    667     def make_table(self, name): 
     690    def table(self, name): 
    668691        """Create and return a Table object for the given name.""" 
    669692        name = self.table_name(name) 
    670         return self.tableclass(name, self.quote(name)) 
    671      
    672     def make_index(self, tablekey, columnkey): 
    673         name = self.table_name("i" + tablekey + columnkey) 
    674         return Index(name, self.quote(name), self.table_name(tablekey), 
    675                      self.column_name(tablekey, columnkey)) 
     693        return self.tableclass(name, self.quote(name), self) 
    676694     
    677695    #                             Connecting                              # 
     
    935953        for key, val in inputs.iteritems(): 
    936954            col = t[key] 
    937             val = coerce(val, col.dbtype) 
    938             parms.append('%s = %s' % (col.qname, val)) 
     955            if col.autoincrement: 
     956                # Skip this field, since we're using a sequencer 
     957                pass 
     958            else: 
     959                val = coerce(val, col.dbtype) 
     960                parms.append('%s = %s' % (col.qname, val)) 
    939961         
    940962        if parms: 
  • trunk/geniusql/providers/firebird.py

    r3 r4  
    656656        return ("KInterbasDB Version: %r\nServer Version: %r" 
    657657                % (kinterbasdb.__version__, svcCon.getServerVersion())) 
    658  
    659  
     658     
     659    def insert(self, tablekey, **inputs): 
     660        """Insert a row and return {idcolkey: newid}.""" 
     661        t = self[tablekey] 
     662         
     663        newids = {} 
     664        fields = [] 
     665        values = [] 
     666        for key, col in t.iteritems(): 
     667            if col.autoincrement: 
     668                # This advances the generator and returns its new value. 
     669                data, _ = self.fetch("SELECT GEN_ID(%s, 1) FROM RDB$DATABASE;" 
     670                                     % col.sequence_name) 
     671                val, = data[0] 
     672                newids[key] = val 
     673                 
     674                val = self.adaptertosql.coerce(val, col.dbtype) 
     675                fields.append(col.qname) 
     676                values.append(val) 
     677            elif key in inputs: 
     678                val = self.adaptertosql.coerce(inputs[key], col.dbtype) 
     679                fields.append(col.qname) 
     680                values.append(val) 
     681         
     682        transconn = self.get_transaction() 
     683         
     684        fields = ", ".join(fields) 
     685        values = ", ".join(values) 
     686        self.execute('INSERT INTO %s (%s) VALUES (%s);' % 
     687                     (t.qname, fields, values), transconn) 
     688         
     689        return newids 
     690         
     691         
     692        fields = ", ".join(fields) 
     693        values = ", ".join(values) 
     694        self.db.execute('INSERT INTO %s (%s) VALUES (%s);' % 
     695                        (t.qname, fields, values)) 
     696 
     697 
  • trunk/geniusql/providers/mysql.py

    r3 r4  
    161161 
    162162 
     163connargs = ["host", "user", "passwd", "db", "port", "unix_socket", 
     164            "conv", "connect_time", "compress", "named_pipe", 
     165            "init_command", "read_default_file", "read_default_group", 
     166            "cursorclass", "client_flag", 
     167            ] 
     168 
    163169class MySQLDatabase(geniusql.Database): 
    164170     
     
    185191        geniusql.Database.__init__(self, name, **kwargs) 
    186192         
     193        self.connargs = dict([(k, v) for k, v in kwargs.iteritems() 
     194                              if k in connargs]) 
     195         
    187196        self.decompiler = MySQLDecompiler 
    188197         
     
    229238            del self[key] 
    230239         
    231         # Set table.db to self, which should "turn on" 
     240        # Set table.created to True, which should "turn on" 
    232241        # any future ALTER TABLE statements. 
    233         table.db = self 
     242        table.created = True 
    234243         
    235244        fields = [] 
  • trunk/geniusql/providers/sqlite.py

    r3 r4  
    386386        oldname = oldcol.name 
    387387        db = self.db 
    388         newname = db.column_name(self.name, newkey) 
     388        newname = db._column_name(self.name, newkey) 
    389389         
    390390        if oldname != newname: 
     
    490490            if not os.path.isabs(name): 
    491491                name = os.path.join(os.getcwd(), name) 
     492        kwargs['mode'] = int(kwargs.pop('mode', '0755'), 8) 
    492493        geniusql.Database.__init__(self, name, **kwargs) 
    493494     
  • trunk/geniusql/test/test.py

    r3 r4  
    6868         
    6969        for testmod in self.tests: 
    70             if testmod.startswith("test_store"): 
    71                 print 
    72                 print "Testing %s storage..." % testmod[10:] 
    73                 mod = __import__(testmod, globals(), locals(), ['']) 
    74                 if hasattr(mod, 'proxied_opts'): 
    75                     mod.proxied_opts['Prefix'] = 'test' 
    76                 elif hasattr(mod, 'opts'): 
    77                     mod.opts['Prefix'] = 'test' 
    78                 mod.run() 
    79             else: 
    80                 suite = unittest.TestLoader().loadTestsFromName(testmod) 
    81                 tools.TestRunner.run(suite) 
     70            print 
     71            print "Testing %s..." % testmod[5:] 
     72            mod = __import__(testmod, globals(), locals(), ['']) 
     73            if hasattr(mod, 'opts'): 
     74                mod.opts['Prefix'] = 'test' 
     75            mod.run() 
    8276 
    8377 
    8478def run(): 
    85      
    8679    tools.prefer_parent_path() 
    87      
    8880    testList = [ 
    8981        'test_firebird', 
  • trunk/geniusql/test/test_firebird.py

    r3 r4  
    2424            'password': passwd, 
    2525            } 
    26     SM_class = "firebird" 
     26    DB_class = "firebird" 
    2727     
    2828    del user, passwd 
     
    3232        # Isolate schema changes from one test to the next. 
    3333        reload(zoo_fixture) 
    34         zoo_fixture.init() 
    35         zoo_fixture.run(SM_class, opts) 
     34        zoo_fixture.run(DB_class, opts['name'], opts) 
    3635 
    3736if __name__ == "__main__": 
  • trunk/geniusql/test/test_msaccess.py

    r3 r4  
    2929                return "CURRENCY" 
    3030             
    31         SM_class = "access" 
     31        DB_class = "access" 
    3232        opts = {u'Connect': "PROVIDER=MICROSOFT.JET.OLEDB.4.0;" 
    3333                            "DATA SOURCE=zoo.mdb;", 
     
    4242             
    4343            def test_currency(obj): 
    44                 sm = zoo_fixture.arena.stores['testSM'] 
    45                 fta = sm.db.typeadapter.__class__.__name__ 
     44                db = zoo_fixture.db 
     45                fta = db.typeadapter.__class__.__name__ 
    4646                 
    4747                for c, p in [('Exhibit', 'Acreage'), ('Zoo', 'Admission')]: 
    48                     dbtype = sm.db[c][p].dbtype 
     48                    dbtype = db[c][p].dbtype 
    4949                    if fta == "CurrencyAdapter": 
    5050                        if dbtype != "CURRENCY" and not dbtype.startswith("WCHAR"): 
     
    6262            print 
    6363            print "Standard MSAccess test." 
    64             zoo_fixture.ZooTests.test_currency = test_currency 
    65             zoo_fixture.init() 
    66             zoo_fixture.run(SM_class, opts) 
     64##            zoo_fixture.ZooTests.test_currency = test_currency 
     65            zoo_fixture.run(DB_class, "zoo.mdb", opts) 
    6766            standard_runs.append(True) 
    6867             
     
    7776            print 
    7877            print "MSAccess test - CURRENCY returned as tuple." 
    79             zoo_fixture.ZooTests.test_currency = test_currency 
    80             zoo_fixture.init() 
    81             zoo_fixture.run(SM_class, opts) 
     78##            zoo_fixture.ZooTests.test_currency = test_currency 
     79            zoo_fixture.run(DB_class, "zoo.mdb", opts) 
    8280            altered_runs.append(True) 
    8381             
     
    9290            print 
    9391            print "MSAccess test - CURRENCY returned as Decimal." 
    94             zoo_fixture.ZooTests.test_currency = test_currency 
    95             zoo_fixture.init() 
    96             zoo_fixture.run(SM_class, opts) 
     92##            zoo_fixture.ZooTests.test_currency = test_currency 
     93            zoo_fixture.run(DB_class, "zoo.mdb", opts) 
    9794            altered_runs.append(True) 
    9895 
  • trunk/geniusql/test/test_mysql.py

    r3 r4  
    1515        opts['passwd'] = raw_input("Enter the password for the MySQL '%s' user:" 
    1616                                   % opts['user']) 
    17     SM_class = "mysql" 
     17    DB_class = "mysql" 
    1818     
    1919    def run(): 
     
    2424        opts['encoding'] = "latin1" 
    2525        reload(zoo_fixture) 
    26         zoo_fixture.init() 
    27         zoo_fixture.run(SM_class, opts) 
     26        zoo_fixture.run(DB_class, 'geniusql_test', opts) 
    2827         
    2928        print 
     
    3130        opts['encoding'] = "utf8" 
    3231        reload(zoo_fixture) 
    33         zoo_fixture.init() 
    34         zoo_fixture.run(SM_class, opts) 
     32        zoo_fixture.run(DB_class, 'geniusql_test', opts) 
    3533 
    3634if __name__ == "__main__": 
  • trunk/geniusql/test/test_psycopg.py

    r3 r4  
    2222                         "user=%s password=%s" % (user, passwd)), 
    2323            } 
    24     SM_class = "psycopg" 
     24    DB_class = "psycopg" 
    2525     
    2626    del user, passwd 
     
    3333        opts['encoding'] = "SQL_ASCII" 
    3434        reload(zoo_fixture) 
    35         zoo_fixture.init() 
    36         zoo_fixture.run(SM_class, opts) 
     35        zoo_fixture.run(DB_class, 'geniusql_test', opts) 
    3736         
    3837        print 
     
    4039        opts['encoding'] = "UNICODE" 
    4140        reload(zoo_fixture) 
    42         zoo_fixture.init() 
    43         zoo_fixture.run(SM_class, opts) 
     41        zoo_fixture.run(DB_class, 'geniusql_test', opts) 
    4442 
    4543if __name__ == "__main__": 
  • trunk/geniusql/test/test_sqlite.py

    r3 r4  
    2121 
    2222if _sqlite: 
    23     SM_class = "sqlite" 
     23    DB_class = "sqlite" 
    2424    opts = {"Database": dbpath} 
    2525     
     
    2828        # Isolate schema changes from one test to the next. 
    2929        reload(zoo_fixture) 
    30         zoo_fixture.init() 
    31         zoo_fixture.run(SM_class, opts) 
     30        zoo_fixture.run(DB_class, opts['Database'], opts) 
    3231         
    3332        print 
     
    3534        opts['Perfect Dates'] = True 
    3635        reload(zoo_fixture) 
    37         zoo_fixture.init() 
    38         zoo_fixture.run(SM_class, opts) 
     36        zoo_fixture.run(DB_class, opts['Database'], opts) 
    3937        opts['Perfect Dates'] = False 
    4038         
     
    4341        opts['Database'] = ':memory:' 
    4442        reload(zoo_fixture) 
    45         zoo_fixture.init() 
    46         zoo_fixture.run(SM_class, opts) 
     43        zoo_fixture.run(DB_class, opts['Database'], opts) 
    4744         
    4845        print 
     
    5148        opts['Type Adapter'] = "geniusql.providers.sqlite.TypeAdapterSQLiteTypeless" 
    5249        reload(zoo_fixture) 
    53         zoo_fixture.init() 
    54         zoo_fixture.run(SM_class, opts) 
     50        zoo_fixture.run(DB_class, opts['Database'], opts) 
    5551 
    5652if __name__ == "__main__": 
  • trunk/geniusql/test/test_sqlserver.py

    r3 r4  
    88                      "The MSAccess test will not be run.") 
    99else: 
    10     from geniusq.providers import ado 
     10    from geniusql.providers import ado 
    1111    try: 
    1212        ado.gen_py() 
     
    2323                u'CommandTimeout': 10, 
    2424                } 
    25         SM_class = "sqlserver" 
     25        DB_class = "sqlserver" 
    2626         
    2727        def run(): 
     
    2929            # Isolate schema changes from one test to the next. 
    3030            reload(zoo_fixture) 
    31             zoo_fixture.init() 
    32             zoo_fixture.run(SM_class, opts) 
     31            zoo_fixture.run(DB_class, "geniusql_test", opts) 
    3332 
    3433if __name__ == "__main__": 
  • trunk/geniusql/test/zoo_fixture.py

    r3 r4  
    3535     
    3636    def test_1_create_tables(self): 
    37         Animal = db.make_table('Animal') 
    38          
    39         Animal['ID'] = c = db.make_column('Animal', 'ID', int) 
    40         c.autoincrement = True 
    41         c.key = True 
    42         Animal.indices['ID'] = db.make_index('Animal', 'ID') 
    43          
    44         Animal['ZooID'] = db.make_column('Animal', 'ZooID', int) 
    45         Animal.indices['ZooID'] = db.make_index('Animal', 'ZooID') 
    46          
    47         Animal['Species'] = db.make_column('Animal', 'Species', hints={'bytes': 100}) 
    48         Animal['Legs'] = db.make_column('Animal', 'Legs', int, default=4) 
    49         Animal['PreviousZoos'] = db.make_column('Animal', 'PreviousZoos', list, hints={'bytes': 8000}) 
    50         Animal['LastEscape'] = db.make_column('Animal', 'LastEscape', datetime.datetime) 
    51         Animal['Lifespan'] = db.make_column('Animal', 'Lifespan', float, hints={'precision': 4}) 
    52         Animal['Age'] = db.make_column('Animal', 'Age', float, default=1, hints={'precision': 4}) 
    53         Animal['MotherID'] = db.make_column('Animal', 'MotherID', int) 
    54         Animal['PreferredFoodID'] = db.make_column('Animal', 'PreferredFoodID', int) 
    55         Animal['AlternateFoodID'] = db.make_column('Animal', 'AlternateFoodID', int) 
    56          
     37        Animal = db.table('Animal') 
     38        Animal['ID'] = db.column(int, autoincrement=True, key=True) 
     39        Animal['ZooID'] = db.column(int) 
     40        Animal['Species'] = db.column(hints={'bytes': 100}) 
     41        Animal['Legs'] = db.column(int, default=4) 
     42        Animal['PreviousZoos'] = db.column(list, hints={'bytes': 8000}) 
     43        Animal['LastEscape'] = db.column(datetime.datetime) 
     44        Animal['Lifespan'] = db.column(float, hints={'precision': 4}) 
     45        Animal['Age'] = db.column(float, default=1, hints={'precision': 4}) 
     46        Animal['MotherID'] = db.column(int) 
     47        Animal['PreferredFoodID'] = db.column(int) 
     48        Animal['AlternateFoodID'] = db.column(int) 
     49        Animal.add_index('ID') 
     50        Animal.add_index('ZooID') 
    5751        Animal.references['Animal'] = ('ID', 'Animal', 'MotherID') 
    58          
    5952        db['Animal'] = Animal 
    6053         
    61 ##        class Zoo(Unit): 
    62 ##            Name = UnitProperty() 
    63 ##            Founded = UnitProperty(datetime.date) 
    64 ##            Opens = UnitProperty(datetime.time) 
    65 ##            LastEscape = UnitProperty(datetime.datetime) 
    66 ##             
    67 ##            if typerefs.fixedpoint: 
    68 ##                # Explicitly set precision and scale so test_storemsaccess 
    69 ##                # can test CURRENCY type 
    70 ##                Admission = UnitProperty(typerefs.fixedpoint.FixedPoint, 
    71 ##                                         hints={'precision': 4, 'scale': 2}) 
    72 ##            else: 
    73 ##                Admission = UnitProperty(float) 
    74 ## 
    75 ##        Zoo.one_to_many('ID', Animal, 'ZooID') 
    76 ## 
    77 ##        class AlternateFoodAssociation(UnitAssociation): 
    78 ##            to_many = False 
    79 ##            register = False 
    80 ##             
    81 ##            def related(self, unit, expr=None): 
    82 ##                food = unit.sandbox.unit(Food, ID=unit.AlternateFoodID) 
    83 ##                return food 
    84 ## 
    85 ##        class Food(Unit): 
    86 ##            """A food item.""" 
    87 ##            Name = UnitProperty() 
    88 ##            NutritionValue = UnitProperty(int) 
    89 ## 
    90 ##        Food.one_to_many('ID', Animal, 'PreferredFoodID') 
    91 ## 
    92 ##        descriptor = AlternateFoodAssociation('AlternateFoodID', Food, 'ID') 
    93 ##        descriptor.nearClass = Animal 
    94 ##        Animal._associations['Alternate Food'] = descriptor 
    95 ##        Animal.AlternateFood = descriptor 
    96 ##        del descriptor 
    97 ## 
     54        Zoo = db.table('Zoo') 
     55        Zoo['ID'] = db.column(int, autoincrement=True, key=True) 
     56        Zoo['Name'] = db.column() 
     57        Zoo['Founded'] = db.column(datetime.date) 
     58        Zoo['Opens'] = db.column(datetime.time) 
     59        Zoo['LastEscape'] = db.column(datetime.datetime) 
     60         
     61        if typerefs.fixedpoint: 
     62            # Explicitly set precision and scale so test_msaccess 
     63            # can test CURRENCY type 
     64            Zoo['Admission'] = db.column(typerefs.fixedpoint.FixedPoint, 
     65                                         hints={'precision': 4, 'scale': 2}) 
     66        else: 
     67            Zoo['Admission'] = db.column(float) 
     68         
     69        Zoo.add_index('ID') 
     70        Zoo.references['Animal'] = ('ID', 'Animal', 'ZooID') 
     71        db['Zoo'] = Zoo 
     72         
     73        Food = db.table('Food') 
     74        Food['ID'] = db.column(int, autoincrement=True, key=True) 
     75        Food['Name'] = db.column() 
     76        Food['NutritionValue'] = db.column(int) 
     77        Food.add_index('ID') 
     78        Food.references['Animal'] = ('ID', 'Animal', 'PreferredFoodID') 
     79        Animal.references['Alternate Food'] = ('AlternateFoodID', 'Food', 'ID') 
     80        db['Food'] = Food 
     81         
    9882##        class Vet(Unit): 
    9983##            """A Veterinarian.""" 
     
    161145     
    162146    def test_2_populate(self): 
    163 ##        # Notice this also tests that: a Unit which is only 
    164 ##        # dirtied via __init__ is still saved. 
    165 ##        WAP = Zoo(Name = 'Wild Animal Park', 
    166 ##                  Founded = datetime.date(2000, 1, 1), 
    167 ##                  # 59 can give rounding errors with divmod, which 
    168 ##                  # AdapterFromADO needs to correct. 
    169 ##                  Opens = datetime.time(8, 15, 59), 
    170 ##                  LastEscape = datetime.datetime(2004, 7, 29, 5, 6, 7), 
    171 ##                  Admission = "4.95", 
    172 ##                  ) 
    173 ##        box.memorize(WAP) 
    174 ##        # The object should get an ID automatically. 
    175 ##        self.assertNotEqual(WAP.ID, None) 
    176 ##         
    177 ##        SDZ = Zoo(Name = 'San Diego Zoo', 
    178 ##                  # This early date should play havoc with a number 
    179 ##                  # of implementations. 
    180 ##                  Founded = datetime.date(1835, 9, 13), 
    181 ##                  Opens = datetime.time(9, 0, 0), 
    182 ##                  Admission = "0", 
    183 ##                  ) 
    184 ##        box.memorize(SDZ) 
    185 ##        # The object should get an ID automatically. 
    186 ##        self.assertNotEqual(SDZ.ID, None) 
    187 ##         
    188 ##        Biodome = Zoo(Name = u'Montr\xe9al Biod\xf4me', 
    189 ##                      Founded = datetime.date(1992, 6, 19), 
    190 ##                      Opens = datetime.time(9, 0, 0), 
    191 ##                      Admission = "11.75", 
    192 ##                      ) 
    193 ##        box.memorize(Biodome) 
    194 ##         
    195 ##        seaworld = Zoo(Name = 'Sea_World', Admission = "60") 
    196 ##        box.memorize(seaworld) 
    197 ####         
    198 ####        mostly_empty = Zoo(Name = 'The Mostly Empty Zoo' + (" " * 255)) 
    199 ####        box.memorize(mostly_empty) 
    200 ##         
     147        newids = db.insert('Zoo', Name='Wild Animal Park', 
     148                           Founded=datetime.date(2000, 1, 1), 
     149                           # 59 can give rounding errors with divmod, which 
     150                           # AdapterFromADO needs to correct. 
     151                           Opens=datetime.time(8, 15, 59), 
     152                           LastEscape=datetime.datetime(2004, 7, 29, 5, 6, 7), 
     153                           Admission=4.95, 
     154                           ) 
     155        wapid=int(newids['ID']) 
     156         
     157        db.insert('Zoo', Name = 'San Diego Zoo', 
     158                  # This early date should play havoc with a number 
     159                  # of implementations. 
     160                  Founded = datetime.date(1835, 9, 13), 
     161                  Opens = datetime.time(9, 0, 0), 
     162                  Admission = 0, 
     163                  ) 
     164         
     165        db.insert('Zoo', Name = u'Montr\xe9al Biod\xf4me', 
     166                  Founded = datetime.date(1992, 6, 19), 
     167                  Opens = datetime.time(9, 0, 0), 
     168                  Admission = 11.75, 
     169                  ) 
     170         
     171        db.insert('Zoo', Name = 'Sea_World', Admission = 60) 
     172         
    201173        # Animals 
    202174        newids = db.insert('Animal', Species='Leopard', Lifespan=73.5) 
    203         self.assertEqual(newids['ID'], 1) 
    204          
    205 ##        leopard.add(WAP) 
    206         db.save('Animal', ID=int(newids['ID']), 
     175        leopardid = int(newids['ID']) 
     176        self.assertEqual(leopardid, 1) 
     177        db.save('Animal', ID=leopardid, ZooID=wapid, 
    207178                LastEscape=datetime.datetime(2004, 12, 21, 8, 15, 0, 999907)) 
    208 ##         
    209 ##        lion = Animal(Species='Lion', ZooID=WAP.ID) 
    210 ##        box.memorize(lion) 
    211 ##         
    212 ##        box.memorize(Animal(Species='Slug', Legs=1, Lifespan=.75, 
    213 ##                            # Test our 8000-byte limit 
    214 ##                            PreviousZoos=["f" * (8000 - 14)])) 
    215 ##         
    216 ##        tiger = Animal(Species='Tiger', PreviousZoos=['animal\\universe']) 
    217 ##        box.memorize(tiger) 
     179         
     180        db.insert('Animal', Species='Lion', ZooID=wapid) 
     181        db.insert('Animal', Species='Slug', Legs=1, Lifespan=.75, 
     182                  # Test our 8000-byte limit 
     183                  PreviousZoos=["f" * (8000 - 14)]) 
     184         
     185        db.insert('Animal', Species='Tiger', PreviousZoos=['animal\\universe']) 
    218186##         
    219187##        # Override Legs.default with itself just to make sure it works.