From: Golemon, B. <Buc...@am...> - 2008-06-30 20:21:58
|
Here are my test results for the SO test suite. Some sources of errors: * Many of the asserts use a string where the MySQLdb cursor returns and integer. * col.py does not allow for the cursor returning a datetime.timedelta object. (I didn't know this ever happened either.) * There are a few instances where a column is typed as 'text' and then used as a key, but mysql doesn't allow this unless you specify a prefix. The blob/text types shouldn't be used for simple fields like 'name'. * A couple asserts compare the row return value to a list, but the row is a tuple and will never compare equal with a list. There's only two tests that looks like they really did fail: testInnerAggregate test_asDict I'd try to fix them myself, but I'd probably break more than I fixed... Here's the full log: ============================= test process starts ============================= executable: /tools/aticad/1.0/external/python-2.4.1/bin/python (2.4.1-final-0) using py lib: /tool/tools/aticad/1.0/external/python-2.4.1/lib/python2.4/site-packages /py-0.9.1-py2.4.egg/py <rev unknown> test_NoneValuedResultItem.py[1] . test_SQLMultipleJoin.py[2] .. test_SQLRelatedJoin.py[2] .. test_SingleJoin.py[1] . test_aggregates.py[3] F.F test_aliases.py[3] ... test_asdict.py[1] F test_auto.py[5] ..... test_auto_old.py[1] . test_basic.py[17] ................. test_blob.py[1] . test_boundattributes.py[0] test_cache.py[3] ... test_combining_joins.py[1] . test_comparison.py[1] F test_constraints.py[1] . test_converters.py[31] ............................... test_create_drop.py[1] . test_csvexport.py[3] ... test_cyclic_reference.py[1] . test_datetime.py[2] .F test_decimal.py[2] .. test_declarative.py[2] .. test_default_style.py - FAILED TO LOAD MODULE test_delete.py[5] ..... test_distinct.py[1] . test_empty.py[1] . test_enum.py[4] .... test_events.py[6] ...... test_exceptions.py[1] F test_expire.py[1] . test_foreignKey.py[2] .. test_groupBy.py[2] FF test_indexes.py[4] ..FF test_inheritance.py[2] .. test_joins.py[5] ..... test_joins_conditional.py[7] ....... test_lazy.py[1] . test_new_joins.py[5] ..... test_parse.py[1] . test_paste.py[0] test_picklecol.py[1] . test_reparent_sqlmeta.py[1] . test_select.py[15] ............... test_select_through.py[5] ..... test_setters.py[1] . test_slice.py[6] ...... test_sorting.py[4] .... test_sqlbuilder.py[1] . test_sqlbuilder_dbspecific.py[13] ............. test_sqlbuilder_importproxy.py[4] .... test_sqlbuilder_joins_instances.py[7] ....... test_sqlite_factory.py[3] ... test_sqlite_threaded.py[1] . test_sqlobject_admin.py - FAILED TO LOAD MODULE test_string_id.py[1] F test_stringid.py[1] . test_style.py[1] . test_subqueries.py[9] ......... test_transactions.py[4] .... test_unicode.py[2] .. test_validation.py[3] ... test_views.py[11] ....FF.F... ________________________________________________________________________ _______ __________________________ entrypoint: test_integer ___________________________ def test_integer(): setupClass(IntAccumulator) IntAccumulator(value=1) IntAccumulator(value=2) IntAccumulator(value=3) assert IntAccumulator.select().min(IntAccumulator.q.value) == 1 E assert IntAccumulator.select().avg(IntAccumulator.q.value) == 2 > assert '2.0000' == 2 + where '2.0000' = <SelectResults at 2a9ae10b10>.avg(int_accumulator.value) + where <SelectResults at 2a9ae10b10> = IntAccumulator.select() + and int_accumulator = IntAccumulator.q [/home/bgolemon/SQLObject/sqlobject/tests/test_aggregates.py:22] ________________________________________________________________________ _______ ____________________________ entrypoint: test_many ____________________________ def test_many(): setupClass(IntAccumulator) IntAccumulator(value=1) IntAccumulator(value=1) IntAccumulator(value=2) IntAccumulator(value=2) IntAccumulator(value=3) IntAccumulator(value=3) attribute = IntAccumulator.q.value assert IntAccumulator.select().accumulateMany( ("MIN", attribute), ("AVG", attribute), ("MAX", attribute), E ("COUNT", attribute), ("SUM", attribute) > AssertionError: (inconsistently failed then succeeded) [/home/bgolemon/SQLObject/sqlobject/tests/test_aggregates.py:61] ________________________________________________________________________ _______ ___________________________ entrypoint: test_asDict ___________________________ def test_asDict(): setupClass(TestAsDict) t1 = TestAsDict(name='one', name2='1') E assert t1.sqlmeta.asDict() == dict(name='one', name2='1', id=1) > assert {'id': 4L, 'name': 'one', 'name2': '1'} == {'id': 1, 'name': 'one', 'name2': '1'} + where {'id': 4L, 'name': 'one', 'name2': '1'} = <sqlobject.declarative.sqlmeta object at 0x2a9ae28810>.asDict() + where <sqlobject.declarative.sqlmeta object at 0x2a9ae28810> = <TestAsDict 4L name='one' name2='1'>.sqlmeta + and {'id': 1, 'name': 'one', 'name2': '1'} = dict(name='one', name2='1', id=1) [/home/bgolemon/SQLObject/sqlobject/tests/test_asdict.py:15] ________________________________________________________________________ _______ _____________________________ entrypoint: test_eq _____________________________ def test_eq(): setupClass(TestComparison) t1 = TestComparison() t2 = TestComparison() TestComparison._connection.cache.clear() > t3 = TestComparison.get(1) [/home/bgolemon/SQLObject/sqlobject/tests/test_comparison.py:13] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def get(cls, id, connection=None, selectResults=None): assert id is not None, 'None is not a possible id for %s' % cls.__name__ id = cls.sqlmeta.idType(id) if connection is None: cache = cls._connection.cache else: cache = connection.cache # This whole sequence comes from Cache.CacheFactory's # behavior, where a None returned means a cache miss. val = cache.get(id, cls) if val is None: try: val = cls(_SO_fetch_no_create=1) val._SO_validatorState = SQLObjectState(val) > val._init(id, connection, selectResults) [/home/bgolemon/SQLObject/sqlobject/main.py:891] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _init(self, id, connection=None, selectResults=None): assert id is not None # This function gets called only when the object is # created, unlike __init__ which would be called # anytime the object was returned from cache. self.id = id self._SO_writeLock = threading.Lock() # If no connection was given, we'll inherit the class # instance variable which should have a _connection # attribute. if connection is not None: self._connection = connection # Sometimes we need to know if this instance is # global or tied to a particular connection. # This flag tells us that: self.sqlmeta._perConnection = True if not selectResults: dbNames = [col.dbName for col in self.sqlmeta.columnList] selectResults = self._connection._SO_selectOne(self, dbNames) if not selectResults: E raise SQLObjectNotFound, "The object %s by the ID %s does not exist" % (self.__class__.__name__, self.id) > SQLObjectNotFound: The object TestComparison by the ID 1 does not exist [/home/bgolemon/SQLObject/sqlobject/main.py:932] ________________________________________________________________________ _______ _________________________ entrypoint: test_mxDateTime _________________________ def test_mxDateTime(): setupClass(DateTime2) _now = now() > dt2 = DateTime2(col1=_now, col2=_now, col3=Time(_now.hour, _now.minute, int(_now.second))) [/home/bgolemon/SQLObject/sqlobject/tests/test_datetime.py:60] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def __init__(self, **kw): # If we are the outmost constructor of a hiearchy of # InheritableSQLObjects (or simlpy _the_ constructor of a "normal" # SQLObject), we create a threadlocal list that collects the # RowCreatedSignals, and executes them if this very constructor is left try: _postponed_local.postponed_calls postponed_created = False except AttributeError: _postponed_local.postponed_calls = [] postponed_created = True try: # We shadow the sqlmeta class with an instance of sqlmeta # that points to us (our sqlmeta buddy object; where the # sqlmeta class is our class's buddy class) self.sqlmeta = self.__class__.sqlmeta(self) # The get() classmethod/constructor uses a magic keyword # argument when it wants an empty object, fetched from the # database. So we have nothing more to do in that case: if kw.has_key('_SO_fetch_no_create'): return post_funcs = [] self.sqlmeta.send(events.RowCreateSignal, kw, post_funcs) # Pass the connection object along if we were given one. if kw.has_key('connection'): self._connection = kw['connection'] self.sqlmeta._perConnection = True del kw['connection'] self._SO_writeLock = threading.Lock() if kw.has_key('id'): id = self.sqlmeta.idType(kw['id']) del kw['id'] else: id = None > self._create(id, **kw) [/home/bgolemon/SQLObject/sqlobject/main.py:1204] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _create(self, id, **kw): self.sqlmeta._creating = True self._SO_createValues = {} self._SO_validatorState = SQLObjectState(self) # First we do a little fix-up on the keywords we were # passed: for column in self.sqlmeta.columnList: # Then we check if the column wasn't passed in, and # if not we try to get the default. if not kw.has_key(column.name) and not kw.has_key(column.foreignName): default = column.default # If we don't get it, it's an error: # If we specified an SQL DEFAULT, then we should use that if default is NoDefault: if column.defaultSQL is None: raise TypeError, "%s() did not get expected keyword argument '%s'" % (self.__class__.__name__, column.name) else: # There is defaultSQL for the column - do not put # the column to kw so that the backend creates the value continue # Otherwise we put it in as though they did pass # that keyword: kw[column.name] = default self.set(**kw) # Then we finalize the process: > self._SO_finishCreate(id) [/home/bgolemon/SQLObject/sqlobject/main.py:1252] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _SO_finishCreate(self, id=None): # Here's where an INSERT is finalized. # These are all the column values that were supposed # to be set, but were delayed until now: setters = self._SO_createValues.items() # Here's their database names: names = [self.sqlmeta.columns[v[0]].dbName for v in setters] values = [v[1] for v in setters] # Get rid of _SO_create*, we aren't creating anymore. # Doesn't have to be threadsafe because we're still in # new(), which doesn't need to be threadsafe. self.dirty = False if not self.sqlmeta.lazyUpdate: del self._SO_createValues else: self._SO_createValues = {} del self.sqlmeta._creating # Do the insert -- most of the SQL in this case is left # up to DBConnection, since getting a new ID is # non-standard. id = self._connection.queryInsertID(self, id, names, values) cache = self._connection.cache cache.created(id, self.__class__, self) > self._init(id) [/home/bgolemon/SQLObject/sqlobject/main.py:1279] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _init(self, id, connection=None, selectResults=None): assert id is not None # This function gets called only when the object is # created, unlike __init__ which would be called # anytime the object was returned from cache. self.id = id self._SO_writeLock = threading.Lock() # If no connection was given, we'll inherit the class # instance variable which should have a _connection # attribute. if connection is not None: self._connection = connection # Sometimes we need to know if this instance is # global or tied to a particular connection. # This flag tells us that: self.sqlmeta._perConnection = True if not selectResults: dbNames = [col.dbName for col in self.sqlmeta.columnList] selectResults = self._connection._SO_selectOne(self, dbNames) if not selectResults: raise SQLObjectNotFound, "The object %s by the ID %s does not exist" % (self.__class__.__name__, self.id) > self._SO_selectInit(selectResults) [/home/bgolemon/SQLObject/sqlobject/main.py:933] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _SO_selectInit(self, row): for col, colValue in zip(self.sqlmeta.columnList, row): if col.to_python: > colValue = col.to_python(colValue, self._SO_validatorState) [/home/bgolemon/SQLObject/sqlobject/main.py:1136] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def to_python(self, value, state): if value is None: return None if isinstance(value, (DateTimeType, TimeType, sqlbuilder.SQLExpression)): return value if isinstance(value, datetime.datetime): return DateTime.DateTime(value.year, value.month, value.day, value.hour, value.minute, value.second) elif isinstance(value, datetime.date): return DateTime.Date(value.year, value.month, value.day) elif isinstance(value, datetime.time): return DateTime.Time(value.hour, value.minute, value.second) try: stime = time.strptime(value, self.format) except: raise validators.Invalid("expected a date/time string of the '%s' format in the DateTimeCol '%s', got %s %r instead" % \ E (self.format, self.name, type(value), value), value, state) > Invalid: expected a date/time string of the '%H:%M:%S' format in the DateTimeCol 'col3', got <type 'datetime.timedelta'> datetime.timedelta(0, 42857) instead [/home/bgolemon/SQLObject/sqlobject/col.py:1081] ________________________________________________________________________ _______ ________________________________ entrypoint: _________________________________ """ from sqlobject import * from sqlobject.tests.dbtest import * from sqlobject.styles import Style, MixedCaseUnderscoreStyle, MixedCaseStyle > class SOStyleTest(SQLObject): [/home/bgolemon/SQLObject/sqlobject/tests/test_default_style.py:9] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ class SOStyleTest(SQLObject): a = StringCol() st2 = ForeignKey('SOStyleTest2') > class sqlmeta(sqlmeta): [/home/bgolemon/SQLObject/sqlobject/tests/test_default_style.py:12] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ class sqlmeta(sqlmeta): E style = AnotherStyle() > NameError: name 'AnotherStyle' is not defined [/home/bgolemon/SQLObject/sqlobject/tests/test_default_style.py:13] ________________________________________________________________________ _______ _________________________ entrypoint: test_exceptions _________________________ def test_exceptions(): if not supports("exceptions"): return > setupClass(TestException) [/home/bgolemon/SQLObject/sqlobject/tests/test_exceptions.py:15] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def setupClass(soClasses, force=False): """ Makes sure the classes have a corresponding and correct table. This won't recreate the table if it already exists. It will check that the table is properly defined (in case you change your table definition). You can provide a single class or a list of classes; if a list then classes will be created in the order you provide, and destroyed in the opposite order. So if class A depends on class B, then do setupClass([B, A]) and B won't be destroyed or cleared until after A is destroyed or cleared. If force is true, then the database will be recreated no matter what. """ global hub if not isinstance(soClasses, (list, tuple)): soClasses = [soClasses] connection = getConnection() for soClass in soClasses: ## This would be an alternate way to register connections... #try: # hub #except NameError: # hub = sqlobject.dbconnection.ConnectionHub() #soClass._connection = hub #hub.threadConnection = connection #hub.processConnection = connection soClass._connection = connection > installOrClear(soClasses, force=force) [/home/bgolemon/SQLObject/sqlobject/tests/dbtest.py:82] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def installOrClear(cls, soClasses, force=False): cls.setup() reversed = list(soClasses)[:] reversed.reverse() # If anything needs to be dropped, they all must be dropped # But if we're forcing it, then we'll always drop if force: any_drops = True else: any_drops = False for soClass in reversed: table = soClass.sqlmeta.table if not soClass._connection.tableExists(table): continue items = list(cls.selectBy( tableName=table, connectionURI=soClass._connection.uri())) if items: instance = items[0] sql = instance.createSQL else: sql = None newSQL, constraints = soClass.createTableSQL() if sql != newSQL: if sql is not None: instance.destroySelf() any_drops = True break for soClass in reversed: if soClass._connection.tableExists(soClass.sqlmeta.table): if any_drops: cls.drop(soClass) else: cls.clear(soClass) for soClass in soClasses: table = soClass.sqlmeta.table if not soClass._connection.tableExists(table): > cls.install(soClass) [/home/bgolemon/SQLObject/sqlobject/tests/dbtest.py:163] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def install(cls, soClass): """ Creates the given table in its database. """ sql = getattr(soClass, soClass._connection.dbName + 'Create', None) all_extra = [] if sql: soClass._connection.query(sql) else: sql, extra_sql = soClass.createTableSQL() > soClass.createTable(applyConstraints=False) [/home/bgolemon/SQLObject/sqlobject/tests/dbtest.py:177] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def createTable(cls, ifNotExists=False, createJoinTables=True, createIndexes=True, applyConstraints=True, connection=None): conn = connection or cls._connection if ifNotExists and cls.tableExists(connection=conn): return extra_sql = [] post_funcs = [] cls.sqlmeta.send(events.CreateTableSignal, cls, connection, extra_sql, post_funcs) > constraints = conn.createTable(cls) [/home/bgolemon/SQLObject/sqlobject/main.py:1396] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def createTable(self, soClass): createSql, constraints = self.createTableSQL(soClass) > self.query(createSql) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:432] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def query(self, s): > return self._runWithConnection(self._query, s) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:336] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _runWithConnection(self, meth, *args): conn = self.getConnection() try: > val = meth(conn, *args) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:249] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _query(self, conn, s): if self.debug: self.printDebug(conn, s, 'Query') > self._executeRetry(conn, conn.cursor(), s) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:333] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _executeRetry(self, conn, cursor, query): # When a server connection is lost and a query is attempted, most of # the time the query will raise a SERVER_LOST exception, then at the # second attempt to execute it, the mysql lib will reconnect and # succeed. However is a few cases, the first attempt raises the # SERVER_GONE exception, the second attempt the SERVER_LOST exception # and only the third succeeds. Thus the 3 in the loop count. # If it doesn't reconnect even after 3 attempts, while the database is # up and running, it is because a 5.0.3 (or newer) server is used # which no longer permits autoreconnects by default. In that case a # reconnect flag must be set when making the connection to indicate # that autoreconnecting is desired. In MySQLdb 1.2.2 or newer this is # done by calling ping(True) on the connection. for count in range(3): try: return cursor.execute(query) except MySQLdb.OperationalError, e: if e.args[0] in (MySQLdb.constants.CR.SERVER_GONE_ERROR, MySQLdb.constants.CR.SERVER_LOST): if count == 2: raise OperationalError(ErrorMessage(e)) if self.debug: self.printDebug(conn, str(e), 'ERROR') else: E raise OperationalError(ErrorMessage(e)) > OperationalError: BLOB/TEXT column 'name' used in key specification without a key length [/home/bgolemon/SQLObject/sqlobject/mysql/mysqlconnection.py:119] ________________________________________________________________________ _______ __________________________ entrypoint: test_groupBy ___________________________ def test_groupBy(): setupClass(GroupbyTest) GroupbyTest(name='a', value=1) GroupbyTest(name='a', value=2) GroupbyTest(name='b', value=1) connection = getConnection() select = Select([GroupbyTest.q.name, func.COUNT(GroupbyTest.q.value)], groupBy=GroupbyTest.q.name, orderBy=GroupbyTest.q.name) sql = connection.sqlrepr(select) rows = connection.queryAll(sql) E assert rows == [('a', 2), ('b', 1)] > assert (('a', 2L), ('b', 1L)) == [('a', 2), ('b', 1)] [/home/bgolemon/SQLObject/sqlobject/tests/test_groupBy.py:25] ________________________________________________________________________ _______ ________________________ entrypoint: test_groupBy_list ________________________ def test_groupBy_list(): setupClass(GroupbyTest) GroupbyTest(name='a', value=1) GroupbyTest(name='a', value=2) GroupbyTest(name='b', value=1) connection = getConnection() select = Select([GroupbyTest.q.name, GroupbyTest.q.value], groupBy=[GroupbyTest.q.name, GroupbyTest.q.value], orderBy=[GroupbyTest.q.name, GroupbyTest.q.value]) sql = connection.sqlrepr(select) rows = connection.queryAll(sql) E assert rows == [('a', 1), ('a', 2), ('b', 1)] > assert (('a', 1L), ('a', 2L), ('b', 1L)) == [('a', 1), ('a', 2), ('b', 1)] [/home/bgolemon/SQLObject/sqlobject/tests/test_groupBy.py:39] ________________________________________________________________________ _______ ________________________ entrypoint: test_index_get_1 _________________________ def test_index_get_1(): > setupClass(PersonIndexGet, force=True) [/home/bgolemon/SQLObject/sqlobject/tests/test_indexes.py:53] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def setupClass(soClasses, force=False): """ Makes sure the classes have a corresponding and correct table. This won't recreate the table if it already exists. It will check that the table is properly defined (in case you change your table definition). You can provide a single class or a list of classes; if a list then classes will be created in the order you provide, and destroyed in the opposite order. So if class A depends on class B, then do setupClass([B, A]) and B won't be destroyed or cleared until after A is destroyed or cleared. If force is true, then the database will be recreated no matter what. """ global hub if not isinstance(soClasses, (list, tuple)): soClasses = [soClasses] connection = getConnection() for soClass in soClasses: ## This would be an alternate way to register connections... #try: # hub #except NameError: # hub = sqlobject.dbconnection.ConnectionHub() #soClass._connection = hub #hub.threadConnection = connection #hub.processConnection = connection soClass._connection = connection > installOrClear(soClasses, force=force) [/home/bgolemon/SQLObject/sqlobject/tests/dbtest.py:82] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def installOrClear(cls, soClasses, force=False): cls.setup() reversed = list(soClasses)[:] reversed.reverse() # If anything needs to be dropped, they all must be dropped # But if we're forcing it, then we'll always drop if force: any_drops = True else: any_drops = False for soClass in reversed: table = soClass.sqlmeta.table if not soClass._connection.tableExists(table): continue items = list(cls.selectBy( tableName=table, connectionURI=soClass._connection.uri())) if items: instance = items[0] sql = instance.createSQL else: sql = None newSQL, constraints = soClass.createTableSQL() if sql != newSQL: if sql is not None: instance.destroySelf() any_drops = True break for soClass in reversed: if soClass._connection.tableExists(soClass.sqlmeta.table): if any_drops: cls.drop(soClass) else: cls.clear(soClass) for soClass in soClasses: table = soClass.sqlmeta.table if not soClass._connection.tableExists(table): > cls.install(soClass) [/home/bgolemon/SQLObject/sqlobject/tests/dbtest.py:163] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def install(cls, soClass): """ Creates the given table in its database. """ sql = getattr(soClass, soClass._connection.dbName + 'Create', None) all_extra = [] if sql: soClass._connection.query(sql) else: sql, extra_sql = soClass.createTableSQL() > soClass.createTable(applyConstraints=False) [/home/bgolemon/SQLObject/sqlobject/tests/dbtest.py:177] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def createTable(cls, ifNotExists=False, createJoinTables=True, createIndexes=True, applyConstraints=True, connection=None): conn = connection or cls._connection if ifNotExists and cls.tableExists(connection=conn): return extra_sql = [] post_funcs = [] cls.sqlmeta.send(events.CreateTableSignal, cls, connection, extra_sql, post_funcs) constraints = conn.createTable(cls) if applyConstraints: for constraint in constraints: conn.query(constraint) else: extra_sql.extend(constraints) if createJoinTables: cls.createJoinTables(ifNotExists=ifNotExists, connection=conn) if createIndexes: cls.createIndexes(ifNotExists=ifNotExists, > connection=conn) [/home/bgolemon/SQLObject/sqlobject/main.py:1407] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def createIndexes(cls, ifNotExists=False, connection=None): conn = connection or cls._connection for index in cls.sqlmeta.indexes: if not index: continue > conn._SO_createIndex(cls, index) [/home/bgolemon/SQLObject/sqlobject/main.py:1450] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _SO_createIndex(self, soClass, index): > self.query(self.createIndexSQL(soClass, index)) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:425] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def query(self, s): > return self._runWithConnection(self._query, s) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:336] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _runWithConnection(self, meth, *args): conn = self.getConnection() try: > val = meth(conn, *args) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:249] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _query(self, conn, s): if self.debug: self.printDebug(conn, s, 'Query') > self._executeRetry(conn, conn.cursor(), s) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:333] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _executeRetry(self, conn, cursor, query): # When a server connection is lost and a query is attempted, most of # the time the query will raise a SERVER_LOST exception, then at the # second attempt to execute it, the mysql lib will reconnect and # succeed. However is a few cases, the first attempt raises the # SERVER_GONE exception, the second attempt the SERVER_LOST exception # and only the third succeeds. Thus the 3 in the loop count. # If it doesn't reconnect even after 3 attempts, while the database is # up and running, it is because a 5.0.3 (or newer) server is used # which no longer permits autoreconnects by default. In that case a # reconnect flag must be set when making the connection to indicate # that autoreconnecting is desired. In MySQLdb 1.2.2 or newer this is # done by calling ping(True) on the connection. for count in range(3): try: return cursor.execute(query) except MySQLdb.OperationalError, e: if e.args[0] in (MySQLdb.constants.CR.SERVER_GONE_ERROR, MySQLdb.constants.CR.SERVER_LOST): if count == 2: raise OperationalError(ErrorMessage(e)) if self.debug: self.printDebug(conn, str(e), 'ERROR') else: E raise OperationalError(ErrorMessage(e)) > OperationalError: BLOB/TEXT column 'first_name' used in key specification without a key length [/home/bgolemon/SQLObject/sqlobject/mysql/mysqlconnection.py:119] ________________________________________________________________________ _______ ________________________ entrypoint: test_index_get_2 _________________________ def test_index_get_2(): > setupClass([PersonIndexGet2, AddressIndexGet2]) [/home/bgolemon/SQLObject/sqlobject/tests/test_indexes.py:104] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def setupClass(soClasses, force=False): """ Makes sure the classes have a corresponding and correct table. This won't recreate the table if it already exists. It will check that the table is properly defined (in case you change your table definition). You can provide a single class or a list of classes; if a list then classes will be created in the order you provide, and destroyed in the opposite order. So if class A depends on class B, then do setupClass([B, A]) and B won't be destroyed or cleared until after A is destroyed or cleared. If force is true, then the database will be recreated no matter what. """ global hub if not isinstance(soClasses, (list, tuple)): soClasses = [soClasses] connection = getConnection() for soClass in soClasses: ## This would be an alternate way to register connections... #try: # hub #except NameError: # hub = sqlobject.dbconnection.ConnectionHub() #soClass._connection = hub #hub.threadConnection = connection #hub.processConnection = connection soClass._connection = connection > installOrClear(soClasses, force=force) [/home/bgolemon/SQLObject/sqlobject/tests/dbtest.py:82] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def installOrClear(cls, soClasses, force=False): cls.setup() reversed = list(soClasses)[:] reversed.reverse() # If anything needs to be dropped, they all must be dropped # But if we're forcing it, then we'll always drop if force: any_drops = True else: any_drops = False for soClass in reversed: table = soClass.sqlmeta.table if not soClass._connection.tableExists(table): continue items = list(cls.selectBy( tableName=table, connectionURI=soClass._connection.uri())) if items: instance = items[0] sql = instance.createSQL else: sql = None newSQL, constraints = soClass.createTableSQL() if sql != newSQL: if sql is not None: instance.destroySelf() any_drops = True break for soClass in reversed: if soClass._connection.tableExists(soClass.sqlmeta.table): if any_drops: cls.drop(soClass) else: cls.clear(soClass) for soClass in soClasses: table = soClass.sqlmeta.table if not soClass._connection.tableExists(table): > cls.install(soClass) [/home/bgolemon/SQLObject/sqlobject/tests/dbtest.py:163] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def install(cls, soClass): """ Creates the given table in its database. """ sql = getattr(soClass, soClass._connection.dbName + 'Create', None) all_extra = [] if sql: soClass._connection.query(sql) else: sql, extra_sql = soClass.createTableSQL() > soClass.createTable(applyConstraints=False) [/home/bgolemon/SQLObject/sqlobject/tests/dbtest.py:177] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def createTable(cls, ifNotExists=False, createJoinTables=True, createIndexes=True, applyConstraints=True, connection=None): conn = connection or cls._connection if ifNotExists and cls.tableExists(connection=conn): return extra_sql = [] post_funcs = [] cls.sqlmeta.send(events.CreateTableSignal, cls, connection, extra_sql, post_funcs) > constraints = conn.createTable(cls) [/home/bgolemon/SQLObject/sqlobject/main.py:1396] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def createTable(self, soClass): createSql, constraints = self.createTableSQL(soClass) > self.query(createSql) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:432] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def query(self, s): > return self._runWithConnection(self._query, s) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:336] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _runWithConnection(self, meth, *args): conn = self.getConnection() try: > val = meth(conn, *args) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:249] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _query(self, conn, s): if self.debug: self.printDebug(conn, s, 'Query') > self._executeRetry(conn, conn.cursor(), s) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:333] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _executeRetry(self, conn, cursor, query): # When a server connection is lost and a query is attempted, most of # the time the query will raise a SERVER_LOST exception, then at the # second attempt to execute it, the mysql lib will reconnect and # succeed. However is a few cases, the first attempt raises the # SERVER_GONE exception, the second attempt the SERVER_LOST exception # and only the third succeeds. Thus the 3 in the loop count. # If it doesn't reconnect even after 3 attempts, while the database is # up and running, it is because a 5.0.3 (or newer) server is used # which no longer permits autoreconnects by default. In that case a # reconnect flag must be set when making the connection to indicate # that autoreconnecting is desired. In MySQLdb 1.2.2 or newer this is # done by calling ping(True) on the connection. for count in range(3): try: return cursor.execute(query) except MySQLdb.OperationalError, e: if e.args[0] in (MySQLdb.constants.CR.SERVER_GONE_ERROR, MySQLdb.constants.CR.SERVER_LOST): if count == 2: raise OperationalError(ErrorMessage(e)) if self.debug: self.printDebug(conn, str(e), 'ERROR') else: E raise OperationalError(ErrorMessage(e)) > OperationalError: BLOB/TEXT column 'name' used in key specification without a key length [/home/bgolemon/SQLObject/sqlobject/mysql/mysqlconnection.py:119] ________________________________________________________________________ _______ ________________________________ entrypoint: _________________________________ """ from sqlobject import * > sqlhub.processConnection = connectionForURI('postgres://pgsql@/db_test') [/home/bgolemon/SQLObject/sqlobject/tests/test_sqlobject_admin.py:7] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def connectionForURI(self, uri, **args): if args: if '?' not in uri: uri += '?' uri += urllib.urlencode(args) if self.cachedURIs.has_key(uri): return self.cachedURIs[uri] if uri.find(':') != -1: scheme, rest = uri.split(':', 1) connCls = self.dbConnectionForScheme(scheme) > conn = connCls.connectionFromURI(uri) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:922] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def connectionFromURI(cls, uri): user, password, host, port, path, args = cls._parseURI(uri) path = path.strip('/') if (host is None) and path.count('/'): # Non-default unix socket path_parts = path.split('/') host = '/' + '/'.join(path_parts[:-1]) path = path_parts[-1] > return cls(host=host, port=port, db=path, user=user, password=password, **args) [/home/bgolemon/SQLObject/sqlobject/postgres/pgconnection.py:97] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def __init__(self, dsn=None, host=None, port=None, db=None, user=None, password=None, usePygresql=False, unicodeCols=False, **kw): global psycopg, pgdb self.usePygresql = usePygresql if usePygresql: if pgdb is None: import pgdb self.module = pgdb else: if psycopg is None: try: import psycopg2 as psycopg except ImportError: E import psycopg > ImportError: No module named psycopg [/home/bgolemon/SQLObject/sqlobject/postgres/pgconnection.py:29] ________________________________________________________________________ _______ _________________________ entrypoint: test_string_id __________________________ def test_string_id(): conn = getConnection() TestStringID.setConnection(conn) TestStringID.dropTable(ifExists=True) assert not conn.tableExists(TestStringID.sqlmeta.table) > TestStringID.createTable() [/home/bgolemon/SQLObject/sqlobject/tests/test_string_id.py:15] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def createTable(cls, ifNotExists=False, createJoinTables=True, createIndexes=True, applyConstraints=True, connection=None): conn = connection or cls._connection if ifNotExists and cls.tableExists(connection=conn): return extra_sql = [] post_funcs = [] cls.sqlmeta.send(events.CreateTableSignal, cls, connection, extra_sql, post_funcs) > constraints = conn.createTable(cls) [/home/bgolemon/SQLObject/sqlobject/main.py:1396] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def createTable(self, soClass): createSql, constraints = self.createTableSQL(soClass) > self.query(createSql) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:432] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def query(self, s): > return self._runWithConnection(self._query, s) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:336] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _runWithConnection(self, meth, *args): conn = self.getConnection() try: > val = meth(conn, *args) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:249] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _query(self, conn, s): if self.debug: self.printDebug(conn, s, 'Query') > self._executeRetry(conn, conn.cursor(), s) [/home/bgolemon/SQLObject/sqlobject/dbconnection.py:333] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def _executeRetry(self, conn, cursor, query): # When a server connection is lost and a query is attempted, most of # the time the query will raise a SERVER_LOST exception, then at the # second attempt to execute it, the mysql lib will reconnect and # succeed. However is a few cases, the first attempt raises the # SERVER_GONE exception, the second attempt the SERVER_LOST exception # and only the third succeeds. Thus the 3 in the loop count. # If it doesn't reconnect even after 3 attempts, while the database is # up and running, it is because a 5.0.3 (or newer) server is used # which no longer permits autoreconnects by default. In that case a # reconnect flag must be set when making the connection to indicate # that autoreconnecting is desired. In MySQLdb 1.2.2 or newer this is # done by calling ping(True) on the connection. for count in range(3): try: return cursor.execute(query) except MySQLdb.OperationalError, e: if e.args[0] in (MySQLdb.constants.CR.SERVER_GONE_ERROR, MySQLdb.constants.CR.SERVER_LOST): if count == 2: raise OperationalError(ErrorMessage(e)) if self.debug: self.printDebug(conn, str(e), 'ERROR') else: E raise OperationalError(ErrorMessage(e)) > OperationalError: BLOB/TEXT column 'test_id_here' used in key specification without a key length [/home/bgolemon/SQLObject/sqlobject/mysql/mysqlconnection.py:119] ________________________________________________________________________ _______ ____________________________ entrypoint: testGetVP ____________________________ def testGetVP(): checkAttr(ViewPhone, phones[0].id, 'number', phones[0].number) > checkAttr(ViewPhone, phones[0].id, 'minutes', phones[0].calls.sum(PhoneCall.q.minutes)) [/home/bgolemon/SQLObject/sqlobject/tests/test_views.py:102] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def checkAttr(cls, id, attr, value): E assert getattr(cls.get(id), attr) == value > assert 25 == '25' + where 25 = getattr(<ViewPhone 7 minutes=25 numberOfCalls=2L number='1234567890' phoneNumberID=7L>, 'minutes') + where <ViewPhone 7 minutes=25 numberOfCalls=2L number='1234567890' phoneNumberID=7L> = <class 'sqlobject.tests.test_views.ViewPhone'>.get(7L) [/home/bgolemon/SQLObject/sqlobject/tests/test_views.py:90] ________________________________________________________________________ _______ ___________________________ entrypoint: testGetVPM ____________________________ def testGetVPM(): checkAttr(ViewPhoneMore, phones[0].id, 'number', phones[0].number) > checkAttr(ViewPhoneMore, phones[0].id, 'minutesCalled', phones[0].incoming.sum(PhoneCall.q.minutes)) [/home/bgolemon/SQLObject/sqlobject/tests/test_views.py:107] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def checkAttr(cls, id, attr, value): E assert getattr(cls.get(id), attr) == value > assert 35 == '35' + where 35 = getattr(<ViewPhoneMore 7 number='1234567890' timesCalled=2L timesCalledLong=1L minutesCalled=35>, 'minutesCalled') + where <ViewPhoneMore 7 number='1234567890' timesCalled=2L timesCalledLong=1L minutesCalled=35> = <class 'sqlobject.tests.test_views.ViewPhoneMore'>.get(7L) [/home/bgolemon/SQLObject/sqlobject/tests/test_views.py:90] ________________________________________________________________________ _______ _______________________ entrypoint: testInnerAggregate ________________________ def testInnerAggregate(): > checkAttr(ViewPhoneInnerAggregate, phones[0].id, 'twiceMinutes', phones[0].calls.sum(PhoneCall.q.minutes)*2) [/home/bgolemon/SQLObject/sqlobject/tests/test_views.py:118] _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ def checkAttr(cls, id, attr, value): E assert getattr(cls.get(id), attr) == value > assert 50 == '2525' + where 50 = getattr(<ViewPhoneInnerAggregate 7 numberOfCalls=2L minutes=25 number='1234567890' phoneNumberID=7L twiceMinutes=50>, 'twiceMinutes') + where <ViewPhoneInnerAggregate 7 numberOfCalls=2L minutes=25 number='1234567890' phoneNumberID=7L twiceMinutes=50> = <class 'sqlobject.tests.test_views.ViewPhoneInnerAggregate'>.get(7L) [/home/bgolemon/SQLObject/sqlobject/tests/test_views.py:90] ________________________________________________________________________ _______ =========== tests finished: 213 passed, 16 failed in 158.12 seconds =========== --Buck |
From: Oleg B. <ph...@ph...> - 2008-06-30 21:20:26
|
Hello! Please bear in mind that I use Postgres and SQLite; I stopped using MySQL long time ago, so I cannot fix MySQL-related problems. I have to rely on other people's patches. On Mon, Jun 30, 2008 at 01:21:16PM -0700, Golemon, Buck wrote: > Here are my test results for the SO test suite. Some sources of errors: > > * Many of the asserts use a string where the MySQLdb cursor returns and > integer. Do you mean this one? > assert IntAccumulator.select().min(IntAccumulator.q.value) == 1 > E assert IntAccumulator.select().avg(IntAccumulator.q.value) == 2 > > assert '2.0000' == 2 > + where '2.0000' = <SelectResults at > 2a9ae10b10>.avg(int_accumulator.value) > + where <SelectResults at 2a9ae10b10> = IntAccumulator.select() > + and int_accumulator = IntAccumulator.q > [/home/bgolemon/SQLObject/sqlobject/tests/test_aggregates.py:22] I interpret this the other way around - MySQLdb returns strings where it have to return integers. > * col.py does not allow for the cursor returning a datetime.timedelta > object. (I > didn't know this ever happened either.) In DateTime column? > * There are a few instances where a column is typed as 'text' and then > used as a > key, but mysql doesn't allow this unless you specify a prefix. The > blob/text > types shouldn't be used for simple fields like 'name'. Limit the length of the fields: StringCol(length=255). > * A couple asserts compare the row return value to a list, but the row > is a > tuple and will never compare equal with a list. Don't hesitate to convert returned values to lists (or tuples). > I'd try to fix them myself, but I'd probably break more than I fixed... Please post a patch or submit it to the SF tracker so we can discuss and improve it. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |
From: Golemon, B. <Buc...@am...> - 2008-07-01 00:20:07
|
Thanks for looking at this. I've submitted some tests for the default styles in the tracker. http://sourceforge.net/tracker/index.php?func=detail&aid=2007233&group_i d=74338&atid=540674 --Buck -----Original Message----- From: sql...@li... [mailto:sql...@li...] On Behalf Of Oleg Broytmann Sent: Monday, June 30, 2008 2:20 PM To: sql...@li... Subject: Re: [SQLObject] SO test results Hello! Please bear in mind that I use Postgres and SQLite; I stopped using MySQL long time ago, so I cannot fix MySQL-related problems. I have to rely on other people's patches. On Mon, Jun 30, 2008 at 01:21:16PM -0700, Golemon, Buck wrote: > Here are my test results for the SO test suite. Some sources of errors: > > * Many of the asserts use a string where the MySQLdb cursor returns and > integer. Do you mean this one? > assert IntAccumulator.select().min(IntAccumulator.q.value) == 1 > E assert IntAccumulator.select().avg(IntAccumulator.q.value) == 2 > > assert '2.0000' == 2 > + where '2.0000' = <SelectResults at > 2a9ae10b10>.avg(int_accumulator.value) > + where <SelectResults at 2a9ae10b10> = IntAccumulator.select() > + and int_accumulator = IntAccumulator.q > [/home/bgolemon/SQLObject/sqlobject/tests/test_aggregates.py:22] I interpret this the other way around - MySQLdb returns strings where it have to return integers. > * col.py does not allow for the cursor returning a datetime.timedelta > object. (I > didn't know this ever happened either.) In DateTime column? > * There are a few instances where a column is typed as 'text' and then > used as a > key, but mysql doesn't allow this unless you specify a prefix. The > blob/text > types shouldn't be used for simple fields like 'name'. Limit the length of the fields: StringCol(length=255). > * A couple asserts compare the row return value to a list, but the row > is a > tuple and will never compare equal with a list. Don't hesitate to convert returned values to lists (or tuples). > I'd try to fix them myself, but I'd probably break more than I fixed... Please post a patch or submit it to the SF tracker so we can discuss and improve it. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. ------------------------------------------------------------------------ - Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ sqlobject-discuss mailing list sql...@li... https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss |
From: Golemon, B. <Buc...@am...> - 2008-07-01 02:13:07
|
Given a graph of tables with ForeignKeys and MultipleJoins, what's the best/easiest way to find how to join two arbitrary tables? Thanks! --Buck |
From: Oleg B. <ph...@ph...> - 2008-07-01 06:16:26
|
On Mon, Jun 30, 2008 at 07:12:42PM -0700, Golemon, Buck wrote: > Given a graph of tables with ForeignKeys and MultipleJoins, what's the > best/easiest way to find how to join two arbitrary tables? Either to do it manually, or using magic attribute .throughTo (which I don't fully understand myself). See http://sqlobject.org/News.html#sqlobject-0-10-0 , tests/test_select_through.py, tests/test_sqlbuilder_joins_instances.py. Oleg. -- Oleg Broytmann http://phd.pp.ru/ ph...@ph... Programmers don't die, they just GOSUB without RETURN. |