From: Mike Bayer Date: Sun, 19 Feb 2006 00:19:16 +0000 (+0000) Subject: exception package added, support throughout X-Git-Tag: rel_0_1_1~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1a68f37fa9aea41d21049307fef840f9b6a0116;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git exception package added, support throughout --- diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py index 29b2dfd608..0c8aa2fe01 100644 --- a/lib/sqlalchemy/__init__.py +++ b/lib/sqlalchemy/__init__.py @@ -7,6 +7,7 @@ from engine import * from types import * from schema import * +from exceptions import * from sql import * import mapping as mapperlib from mapping import * diff --git a/lib/sqlalchemy/ansisql.py b/lib/sqlalchemy/ansisql.py index a9c6bb2071..88bd0f8bd1 100644 --- a/lib/sqlalchemy/ansisql.py +++ b/lib/sqlalchemy/ansisql.py @@ -145,8 +145,6 @@ class ANSICompiler(sql.Compiled): def visit_label(self, label): if len(self.select_stack): self.typemap.setdefault(label.name.lower(), label.obj.type) - if label.obj.type is None: - raise "nonetype" + repr(label.obj) self.strings[label] = self.strings[label.obj] + " AS " + label.name def visit_column(self, column): diff --git a/lib/sqlalchemy/attributes.py b/lib/sqlalchemy/attributes.py index f6abe6b31d..7a9f13c57c 100644 --- a/lib/sqlalchemy/attributes.py +++ b/lib/sqlalchemy/attributes.py @@ -76,7 +76,7 @@ class PropHistory(object): return self.obj.__dict__[self.key] def setattr(self, value): if isinstance(value, list): - raise ("assigning a list to scalar property '%s' on '%s' instance %d" % (self.key, self.obj.__class__.__name__, id(self.obj))) + raise InvalidRequestError("assigning a list to scalar property '%s' on '%s' instance %d" % (self.key, self.obj.__class__.__name__, id(self.obj))) orig = self.obj.__dict__.get(self.key, None) if orig is value: return diff --git a/lib/sqlalchemy/engine.py b/lib/sqlalchemy/engine.py index d553eee2db..1ca9d00fda 100644 --- a/lib/sqlalchemy/engine.py +++ b/lib/sqlalchemy/engine.py @@ -23,13 +23,13 @@ The term "database-specific" will be used to describe any object or function tha corresponding to a particular vendor, such as mysql-specific, sqlite-specific, etc. """ -import sqlalchemy.schema as schema import sqlalchemy.pool -import sqlalchemy.util as util -import sqlalchemy.sql as sql -import StringIO, sys, re +import schema +import exceptions +import util +import sql import sqlalchemy.types as types -import sqlalchemy.databases +import StringIO, sys, re __all__ = ['create_engine', 'engine_descriptors'] @@ -236,7 +236,7 @@ class SQLEngine(schema.SchemaEngine): self.bindtemplate = "%%(%s)s" self.positional = True else: - raise "Unsupported paramstyle '%s'" % self._paramstyle + raise DBAPIError("Unsupported paramstyle '%s'" % self._paramstyle) def type_descriptor(self, typeobj): """provides a database-specific TypeEngine object, given the generic object @@ -609,10 +609,10 @@ class SQLEngine(schema.SchemaEngine): return ResultProxy(cursor, self, typemap=typemap) def _execute(self, c, statement, parameters): - #try: - c.execute(statement, parameters) - #except: - # raise "OK ERROR " + statement + " " + repr(parameters) + try: + c.execute(statement, parameters) + except Exception, e: + raise exceptions.SQLError(statement, parameters, e) self.context.rowcount = c.rowcount def _executemany(self, c, statement, parameters): c.executemany(statement, parameters) @@ -642,7 +642,7 @@ class ResultProxy: def __init__(self, key): self.key = key def convert_result_value(self, arg, engine): - raise "Ambiguous column name '%s' in result set! try 'use_labels' option on select statement." % (self.key) + raise InvalidRequestError("Ambiguous column name '%s' in result set! try 'use_labels' option on select statement." % (self.key)) def __init__(self, cursor, engine, typemap = None): """ResultProxy objects are constructed via the execute() method on SQLEngine.""" @@ -663,7 +663,7 @@ class ResultProxy: else: rec = (types.NULLTYPE, i) if rec[0] is None: - raise "None for metadata " + colname + raise DBAPIError("None for metadata " + colname) if self.props.setdefault(colname, rec) is not rec: self.props[colname] = (ResultProxy.AmbiguousColumn(colname), 0) self.keys.append(colname) diff --git a/lib/sqlalchemy/exceptions.py b/lib/sqlalchemy/exceptions.py new file mode 100644 index 0000000000..6883293ec5 --- /dev/null +++ b/lib/sqlalchemy/exceptions.py @@ -0,0 +1,41 @@ +# exceptions.py - exceptions for SQLAlchemy +# Copyright (C) 2005,2006 Michael Bayer mike_mp@zzzcomputing.com +# +# This module is part of SQLAlchemy and is released under +# the MIT License: http://www.opensource.org/licenses/mit-license.php + + +class SQLAlchemyError(Exception): + """generic error class""" + pass + +class SQLError(SQLAlchemyError): + """raised when the execution of a SQL statement fails. includes accessors + for the underlying exception, as well as the SQL and bind parameters""" + def __init__(self, statement, params, orig): + SQLAlchemyError.__init__(self, "(%s) %s"% (orig.__class__.__name__, str(orig))) + self.statement = statement + self.params = params + self.orig = orig + +class ArgumentError(SQLAlchemyError): + """raised for all those conditions where invalid arguments are sent to constructed + objects. This error generally corresponds to construction time state errors.""" + pass + +class CommitError(SQLAlchemyError): + """raised when an invalid condition is detected upon a commit()""" + pass + +class InvalidRequestError(SQLAlchemyError): + """sqlalchemy was asked to do something it cant do, return nonexistent data, etc. + This error generally corresponds to runtime state errors.""" + pass + +class AssertionError(SQLAlchemyError): + """corresponds to internal state being detected in an invalid state""" + pass + +class DBAPIError(SQLAlchemyError): + """something weird happened with a particular DBAPI version""" + pass \ No newline at end of file diff --git a/lib/sqlalchemy/mapping/__init__.py b/lib/sqlalchemy/mapping/__init__.py index 538559e43c..64258fa654 100644 --- a/lib/sqlalchemy/mapping/__init__.py +++ b/lib/sqlalchemy/mapping/__init__.py @@ -13,6 +13,7 @@ import sqlalchemy.schema as schema import sqlalchemy.engine as engine import sqlalchemy.util as util import objectstore +from exceptions import * import types as types from mapper import * from properties import * @@ -27,7 +28,7 @@ def relation(*args, **kwargs): """provides a relationship of a primary Mapper to a secondary Mapper, which corresponds to a parent-child or associative table relationship.""" if len(args) > 1 and isinstance(args[0], type): - raise ValueError("relation(class, table, **kwargs) is deprecated. Please use relation(class, **kwargs) or relation(mapper, **kwargs).") + raise ArgumentError("relation(class, table, **kwargs) is deprecated. Please use relation(class, **kwargs) or relation(mapper, **kwargs).") return _relation_loader(*args, **kwargs) def _relation_loader(mapper, secondary=None, primaryjoin=None, secondaryjoin=None, lazy=True, **kwargs): @@ -101,7 +102,7 @@ def class_mapper(class_): pass except AttributeError: pass - raise "Class '%s' has no mapper associated with it" % class_.__name__ + raise InvalidRequestError("Class '%s' has no mapper associated with it" % class_.__name__) def assign_mapper(class_, *args, **params): diff --git a/lib/sqlalchemy/mapping/mapper.py b/lib/sqlalchemy/mapping/mapper.py index 24bf11fd8f..5fed7c7f29 100644 --- a/lib/sqlalchemy/mapping/mapper.py +++ b/lib/sqlalchemy/mapping/mapper.py @@ -9,6 +9,7 @@ import sqlalchemy.sql as sql import sqlalchemy.schema as schema import sqlalchemy.engine as engine import sqlalchemy.util as util +from sqlalchemy.exceptions import * import objectstore import sys import weakref @@ -47,7 +48,7 @@ class Mapper(object): self._options = {} if not issubclass(class_, object): - raise TypeError("Class '%s' is not a new-style class" % class_.__name__) + raise ArgumentError("Class '%s' is not a new-style class" % class_.__name__) if isinstance(table, sql.Select): # some db's, noteably postgres, dont want to select from a select @@ -55,7 +56,7 @@ class Mapper(object): # the configured properties on the mapper are not matched against the alias # we make, theres workarounds but it starts to get really crazy (its crazy enough # the SQL that gets generated) so just require an alias - raise TypeError("Mapping against a Select object requires that it has a name. Use an alias to give it a name, i.e. s = select(...).alias('myselect')") + raise ArgumentError("Mapping against a Select object requires that it has a name. Use an alias to give it a name, i.e. s = select(...).alias('myselect')") else: self.table = table @@ -87,7 +88,7 @@ class Mapper(object): except KeyError: l = self.pks_by_table.setdefault(t, util.HashSet(ordered=True)) if not len(t.primary_key): - raise ValueError("Table " + t.name + " has no primary key columns. Specify primary_key argument to mapper.") + raise ArgumentError("Table " + t.name + " has no primary key columns. Specify primary_key argument to mapper.") for k in t.primary_key: l.append(k) @@ -110,14 +111,14 @@ class Mapper(object): try: prop = self.table._get_col_by_original(prop) except KeyError: - raise ValueError("Column '%s' is not represented in mapper's table" % prop._label) + raise ArgumentError("Column '%s' is not represented in mapper's table" % prop._label) self.columns[key] = prop prop = ColumnProperty(prop) elif isinstance(prop, list) and sql.is_column(prop[0]): try: prop = [self.table._get_col_by_original(p) for p in prop] except KeyError, e: - raise ValueError("Column '%s' is not represented in mapper's table" % e.args[0]) + raise ArgumentError("Column '%s' is not represented in mapper's table" % e.args[0]) self.columns[key] = prop[0] prop = ColumnProperty(*prop) self.props[key] = prop @@ -143,7 +144,7 @@ class Mapper(object): prop.columns.append(column) else: if not allow_column_override: - raise ValueError("WARNING: column '%s' not being added due to property '%s'. Specify 'allow_column_override=True' to mapper() to ignore this condition." % (column.key, repr(prop))) + raise ArgumentError("WARNING: column '%s' not being added due to property '%s'. Specify 'allow_column_override=True' to mapper() to ignore this condition." % (column.key, repr(prop))) else: continue @@ -358,7 +359,7 @@ class Mapper(object): continue c = self._get_criterion(key, value) if c is None: - raise "Cant find criterion for property '"+ key + "'" + raise InvalidRequestError("Cant find criterion for property '"+ key + "'") if clause is None: clause = c else: @@ -448,9 +449,9 @@ class Mapper(object): except KeyError: try: prop = self.props[column.key] - raise "Column '%s.%s' is not available, due to conflicting property '%s':%s" % (column.table.name, column.name, column.key, repr(prop)) + raise InvalidRequestError("Column '%s.%s' is not available, due to conflicting property '%s':%s" % (column.table.name, column.name, column.key, repr(prop))) except KeyError: - raise "No column %s.%s is configured on mapper %s..." % (column.table.name, column.name, str(self)) + raise InvalidRequestError("No column %s.%s is configured on mapper %s..." % (column.table.name, column.name, str(self))) return prop[0] def _getattrbycolumn(self, obj, column): @@ -560,7 +561,7 @@ class Mapper(object): self.extension.after_update(self, obj) rows += c.cursor.rowcount if table.engine.supports_sane_rowcount() and rows != len(update): - raise "ConcurrencyError - updated rowcount %d does not match number of objects updated %d" % (rows, len(update)) + raise CommitError("ConcurrencyError - updated rowcount %d does not match number of objects updated %d" % (rows, len(update))) if len(insert): statement = table.insert() for rec in insert: @@ -607,7 +608,7 @@ class Mapper(object): statement = table.delete(clause) c = statement.execute(*delete) if table.engine.supports_sane_rowcount() and c.rowcount != len(delete): - raise "ConcurrencyError - updated rowcount %d does not match number of objects updated %d" % (c.cursor.rowcount, len(delete)) + raise CommitError("ConcurrencyError - updated rowcount %d does not match number of objects updated %d" % (c.cursor.rowcount, len(delete))) def _has_pks(self, table): try: diff --git a/lib/sqlalchemy/mapping/objectstore.py b/lib/sqlalchemy/mapping/objectstore.py index a3aac738b6..aa8e9fe2ec 100644 --- a/lib/sqlalchemy/mapping/objectstore.py +++ b/lib/sqlalchemy/mapping/objectstore.py @@ -83,7 +83,7 @@ class Session(object): return (class_, table.hash_key(), tuple([row[column] for column in primary_key])) get_row_key = staticmethod(get_row_key) - class UOWTrans(object): + class SessionTrans(object): def __init__(self, parent, uow, isactive): self.__parent = parent self.__isactive = isactive @@ -94,20 +94,25 @@ class Session(object): def begin(self): return self.parent.begin() def commit(self): + """commits the transaction noted by this SessionTrans object.""" self.__parent._trans_commit(self) self.__isactive = False def rollback(self): + """rolls back the current UnitOfWork transaction, in the case that begin() + has been called. The changes logged since the begin() call are discarded.""" self.__parent._trans_rollback(self) self.__isactive = False def begin(self): - """begins a new UnitOfWork transaction. the next commit will affect only - objects that are created, modified, or deleted following the begin statement.""" + """begins a new UnitOfWork transaction and returns a tranasaction-holding + object. commit() or rollback() should be called on the returned object. + commit() on the Session will do nothing while a transaction is pending, and further + calls to begin() will return no-op transactional objects.""" if self.parent_uow is not None: - return Session.UOWTrans(self, self.uow, False) + return Session.SessionTrans(self, self.uow, False) self.parent_uow = self.uow self.uow = UnitOfWork(identity_map = self.uow.identity_map) - return Session.UOWTrans(self, self.uow, True) + return Session.SessionTrans(self, self.uow, True) def _trans_commit(self, trans): if trans.uow is self.uow and trans.isactive: @@ -120,10 +125,9 @@ class Session(object): self.parent_uow = None def commit(self, *objects): - """commits the current UnitOfWork transaction. if a transaction was begun - via begin(), commits only those objects that were created, modified, or deleted - since that begin statement. otherwise commits all objects that have been - changed. + """commits the current UnitOfWork transaction. called with + no arguments, this is only used + for "implicit" transactions when there was no begin(). if individual objects are submitted, then only those objects are committed, and the begin/commit cycle is not affected.""" # if an object list is given, commit just those but dont @@ -134,15 +138,6 @@ class Session(object): if self.parent_uow is None: self.uow.commit() - def rollback(self): - """rolls back the current UnitOfWork transaction, in the case that begin() - has been called. The changes logged since the begin() call are discarded.""" - if self.parent_uow is None: - raise "UOW transaction is not begun" - self.uow = self.parent_uow - self.parent_uow = None - self.begin_count = 0 - def register_clean(self, obj): self._bind_to(obj) self.uow.register_clean(obj) @@ -252,7 +247,7 @@ class UOWListElement(attributes.ListElement): def list_value_changed(self, obj, key, item, listval, isdelete): sess = get_session(obj) if not isdelete and sess.deleted.contains(item): - raise "re-inserting a deleted value into a list" + raise InvalidRequestError("re-inserting a deleted value into a list") sess.modified_lists.append(self) if self.deleteremoved and isdelete: sess.register_deleted(item) @@ -461,7 +456,7 @@ class UOWTransaction(object): # things can get really confusing if theres duplicate instances floating around, # so make sure everything is OK if hasattr(obj, '_instance_key') and not self.uow.identity_map.has_key(obj._instance_key): - raise "Detected a mapped object not present in the current thread's Identity Map: '%s'. Use objectstore.import_instance() to place deserialized instances or instances from other threads" % repr(obj._instance_key) + raise InvalidRequestError("Detected a mapped object not present in the current thread's Identity Map: '%s'. Use objectstore.import_instance() to place deserialized instances or instances from other threads" % repr(obj._instance_key)) mapper = object_mapper(obj) self.mappers.append(mapper) @@ -1016,7 +1011,7 @@ def get_session(obj=None): try: return _sessions[hashkey] except KeyError: - raise "Session '%s' referenced by object '%s' no longer exists" % (hashkey, repr(obj)) + raise InvalidRequestError("Session '%s' referenced by object '%s' no longer exists" % (hashkey, repr(obj))) return session_registry() diff --git a/lib/sqlalchemy/mapping/properties.py b/lib/sqlalchemy/mapping/properties.py index f686e588c4..65f9cbdc26 100644 --- a/lib/sqlalchemy/mapping/properties.py +++ b/lib/sqlalchemy/mapping/properties.py @@ -16,6 +16,7 @@ import sqlalchemy.util as util import sqlalchemy.attributes as attributes import mapper import objectstore +from sqlalchemy.exceptions import * class ColumnProperty(MapperProperty): """describes an object attribute that corresponds to a table column.""" @@ -161,7 +162,7 @@ class PropertyLoader(MapperProperty): self.parent = parent if self.secondaryjoin is not None and self.secondary is None: - raise ValueError("Property '" + self.key + "' specified with secondary join condition but no secondary argument") + raise ArgumentError("Property '" + self.key + "' specified with secondary join condition but no secondary argument") # if join conditions were not specified, figure them out based on foreign keys if self.secondary is not None: if self.secondaryjoin is None: @@ -209,7 +210,7 @@ class PropertyLoader(MapperProperty): if not self.mapper.props[self.backref].is_backref: self.is_backref=True elif not objectstore.global_attributes.is_class_managed(parent.class_, key): - raise "Non-primary property created for attribute '%s' on class '%s', but that attribute is not managed! Insure that the primary mapper for this class defines this property" % (key, parent.class_.__name__) + raise ArgumentError("Non-primary property created for attribute '%s' on class '%s', but that attribute is not managed! Insure that the primary mapper for this class defines this property" % (key, parent.class_.__name__)) self.do_init_subclass(key, parent) @@ -231,7 +232,7 @@ class PropertyLoader(MapperProperty): elif self.foreigntable == self.parent.table: return PropertyLoader.MANYTOONE else: - raise "Cant determine relation direction" + raise ArgumentError("Cant determine relation direction") def _find_dependent(self): """searches through the primary join condition to determine which side @@ -245,18 +246,18 @@ class PropertyLoader(MapperProperty): return if isinstance(binary.left, schema.Column) and binary.left.primary_key: if dependent[0] is binary.left.table: - raise "bidirectional dependency not supported...specify foreignkey" + raise ArgumentError("bidirectional dependency not supported...specify foreignkey") dependent[0] = binary.right.table self.foreignkey= binary.right elif isinstance(binary.right, schema.Column) and binary.right.primary_key: if dependent[0] is binary.right.table: - raise "bidirectional dependency not supported...specify foreignkey" + raise ArgumentError("bidirectional dependency not supported...specify foreignkey") dependent[0] = binary.left.table self.foreignkey = binary.left visitor = BinaryVisitor(foo) self.primaryjoin.accept_visitor(visitor) if dependent[0] is None: - raise "cant determine primary foreign key in the join relationship....specify foreignkey= or foreignkey=[]" + raise ArgumentError("cant determine primary foreign key in the join relationship....specify foreignkey= or foreignkey=[]") else: self.foreigntable = dependent[0] @@ -358,7 +359,7 @@ class PropertyLoader(MapperProperty): uowcommit.register_processor(stub, self, self.parent, True) elif self.direction == PropertyLoader.ONETOMANY: if self.post_update: - raise "post_update not yet supported with one-to-many relation" + raise InvalidRequestError("post_update not yet supported with one-to-many relation") uowcommit.register_dependency(self.parent, self.mapper) uowcommit.register_processor(self.parent, self, self.parent, False) uowcommit.register_processor(self.parent, self, self.parent, True) @@ -372,7 +373,7 @@ class PropertyLoader(MapperProperty): uowcommit.register_dependency(self.mapper, self.parent) uowcommit.register_processor(self.mapper, self, self.parent, False) else: - raise " no foreign key ?" + raise AssertionError(" no foreign key ?") def get_object_dependencies(self, obj, uowcommit, passive = True): return uowcommit.uow.attributes.get_history(obj, self.key, passive = passive) @@ -547,13 +548,13 @@ class PropertyLoader(MapperProperty): source = binary.right dest = binary.left else: - raise "Cant determine direction for relationship %s = %s" % (binary.left.fullname, binary.right.fullname) + raise ArgumentError("Cant determine direction for relationship %s = %s" % (binary.left.fullname, binary.right.fullname)) if self.direction == PropertyLoader.ONETOMANY: self.syncrules.append(SyncRule(self.parent, source, dest, dest_mapper=self.mapper)) elif self.direction == PropertyLoader.MANYTOONE: self.syncrules.append(SyncRule(self.mapper, source, dest, dest_mapper=self.parent)) else: - raise "assert failed" + raise AssertionError("assert failed") else: pt = check_for_table(binary, parent_tables) tt = check_for_table(binary, target_tables) @@ -567,7 +568,7 @@ class PropertyLoader(MapperProperty): elif self.direction == PropertyLoader.MANYTOONE: self.syncrules.append(SyncRule(self.mapper, tt, pt, dest_mapper=self.parent)) else: - raise "assert failed" + raise AssertionError("assert failed") elif pt and st: self.syncrules.append(SyncRule(self.parent, pt, st, direction=PropertyLoader.ONETOMANY)) elif tt and st: @@ -579,7 +580,7 @@ class PropertyLoader(MapperProperty): if self.secondaryjoin is not None: self.secondaryjoin.accept_visitor(processor) if len(self.syncrules) == 0: - raise "No syncrules generated for join criterion " + str(self.primaryjoin) + raise ArgumentError("No syncrules generated for join criterion " + str(self.primaryjoin)) def _synchronize(self, obj, child, associationrow, clearkeys): """called during a commit to execute the full list of syncrules on the @@ -799,7 +800,7 @@ class EagerLoader(PropertyLoader): self.mapper.props[prop.key] = p if recursion_stack.has_key(prop): - raise "Circular eager load relationship detected on " + str(self.mapper) + " " + key + repr(self.mapper.props) + raise ArgumentError("Circular eager load relationship detected on " + str(self.mapper) + " " + key + repr(self.mapper.props)) p.do_init_subclass(prop.key, prop.parent, recursion_stack) @@ -852,7 +853,7 @@ class EagerLoader(PropertyLoader): try: for key, value in self.mapper.props.iteritems(): if recursion_stack.has_key(value): - raise "Circular eager load relationship detected on " + str(self.mapper) + " " + key + repr(self.mapper.props) + raise InvalidRequestError("Circular eager load relationship detected on " + str(self.mapper) + " " + key + repr(self.mapper.props)) value.setup(key, statement, recursion_stack=recursion_stack, eagertable=self.eagertarget) finally: del recursion_stack[self] diff --git a/lib/sqlalchemy/mapping/topological.py b/lib/sqlalchemy/mapping/topological.py index e6d4b6b577..95807bf5f2 100644 --- a/lib/sqlalchemy/mapping/topological.py +++ b/lib/sqlalchemy/mapping/topological.py @@ -33,6 +33,7 @@ realized this characteristic of the algorithm. import string, StringIO from sets import * import sqlalchemy.util as util +from sqlalchemy.exceptions import * class QueueDependencySorter(object): """this is a topological sort from wikipedia. its very stable. it creates a straight-line @@ -91,7 +92,7 @@ class QueueDependencySorter(object): n.cycles = Set([n]) continue else: - raise "Self-referential dependency detected " + repr(t) + raise CommitError("Self-referential dependency detected " + repr(t)) childnode = nodes[t[1]] parentnode = nodes[t[0]] self._add_edge(edges, (parentnode, childnode)) @@ -125,7 +126,7 @@ class QueueDependencySorter(object): continue else: # long cycles not allowed - raise "Circular dependency detected " + repr(edges) + repr(queue) + raise CommitError("Circular dependency detected " + repr(edges) + repr(queue)) node = queue.pop() if not hasattr(node, '_cyclical'): output.append(node) @@ -291,7 +292,7 @@ class TreeDependencySorter(object): elif parentnode.is_descendant_of(childnode): # check for a line thats backwards with nodes in between, this is a # circular dependency (although confirmation on this would be helpful) - raise "Circular dependency detected" + raise CommitError("Circular dependency detected") elif not childnode.is_descendant_of(parentnode): # if relationship doesnt exist, connect nodes together root = childnode.get_sibling_ancestor(parentnode) diff --git a/lib/sqlalchemy/schema.py b/lib/sqlalchemy/schema.py index a9c6a4d968..12b3c7707f 100644 --- a/lib/sqlalchemy/schema.py +++ b/lib/sqlalchemy/schema.py @@ -15,8 +15,9 @@ the schema package "plugs in" to the SQL package. """ -from sqlalchemy.util import * -from sqlalchemy.types import * +from util import * +from types import * +from exceptions import * import copy, re, string __all__ = ['SchemaItem', 'Table', 'Column', 'ForeignKey', 'Sequence', 'Index', @@ -76,11 +77,11 @@ class TableSingleton(type): if redefine: table.reload_values(*args) elif not useexisting: - raise "Table '%s.%s' is already defined. specify 'redefine=True' to remap columns, or 'useexisting=True' to use the existing table" % (schema, name) + raise ArgumentError("Table '%s.%s' is already defined. specify 'redefine=True' to remap columns, or 'useexisting=True' to use the existing table" % (schema, name)) return table except KeyError: if mustexist: - raise "Table '%s.%s' not defined" % (schema, name) + raise ArgumentError("Table '%s.%s' not defined" % (schema, name)) table = type.__call__(self, name, engine, **kwargs) engine.tables[key] = table # load column definitions from the database if 'autoload' is defined @@ -248,7 +249,7 @@ class Column(SchemaItem): self.foreign_key = None self._orig = None if len(kwargs): - raise "Unknown arguments passed to Column: " + repr(kwargs.keys()) + raise ArgumentError("Unknown arguments passed to Column: " + repr(kwargs.keys())) original = property(lambda s: s._orig or s) engine = property(lambda s: s.table.engine) @@ -272,7 +273,7 @@ class Column(SchemaItem): def _set_parent(self, table): if getattr(self, 'table', None) is not None: - raise "this Column already has a table!" + raise ArgumentError("this Column already has a table!") if not self.hidden: table.columns[self.key] = self if self.primary_key: @@ -377,7 +378,7 @@ class ForeignKey(SchemaItem): if isinstance(self._colspec, str): m = re.match(r"^([\w_-]+)(?:\.([\w_-]+))?(?:\.([\w_-]+))?$", self._colspec) if m is None: - raise ValueError("Invalid foreign key column specification: " + self._colspec) + raise ArgumentError("Invalid foreign key column specification: " + self._colspec) if m.group(3) is None: (tname, colname) = m.group(1, 2) schema = self.parent.original.table.schema @@ -485,7 +486,7 @@ class Index(SchemaItem): self.table = column.table elif column.table != self.table: # all columns muse be from same table - raise ValueError("All index columns must be from same table. " + raise ArgumentError("All index columns must be from same table. " "%s is from %s not %s" % (column, column.table, self.table)) diff --git a/lib/sqlalchemy/sql.py b/lib/sqlalchemy/sql.py index 03c94c5e33..9b35713849 100644 --- a/lib/sqlalchemy/sql.py +++ b/lib/sqlalchemy/sql.py @@ -6,9 +6,10 @@ """defines the base components of SQL expression trees.""" -import sqlalchemy.schema as schema -import sqlalchemy.util as util -import sqlalchemy.types as sqltypes +import schema +import util +import types as sqltypes +from exceptions import * import string, re, random types = __import__('types') @@ -379,7 +380,7 @@ class ClauseElement(object): engine = self.engine if engine is None: - raise "no SQLEngine could be located within this ClauseElement." + raise InvalidRequestError("no SQLEngine could be located within this ClauseElement.") return engine.compile(self, parameters=parameters, typemap=typemap) @@ -475,7 +476,7 @@ class CompareMixin(object): if _is_literal(obj): if obj is None: if operator != '=': - raise "Only '=' operator can be used with NULL" + raise ArgumentError("Only '=' operator can be used with NULL") return BooleanExpression(self._compare_self(), null(), 'IS') else: obj = self._bind_param(obj) @@ -857,7 +858,7 @@ class Join(FromClause): crit.append(secondary._get_col_by_original(fk.column) == fk.parent) self.foreignkey = fk.parent if len(crit) == 0: - raise "Cant find any foreign key relationships between '%s' (%s) and '%s' (%s)" % (primary.name, repr(primary), secondary.name, repr(secondary)) + raise ArgumentError("Cant find any foreign key relationships between '%s' (%s) and '%s' (%s)" % (primary.name, repr(primary), secondary.name, repr(secondary))) elif len(crit) == 1: return (crit[0]) else: @@ -1043,7 +1044,7 @@ class ColumnImpl(ColumnElement): if engine is None: engine = self.engine if engine is None: - raise "no SQLEngine could be located within this ClauseElement." + raise InvalidRequestError("no SQLEngine could be located within this ClauseElement.") return engine.compile(self.column, parameters=parameters, typemap=typemap) class TableImpl(FromClause): diff --git a/lib/sqlalchemy/util.py b/lib/sqlalchemy/util.py index 633091dd32..301db0ec4d 100644 --- a/lib/sqlalchemy/util.py +++ b/lib/sqlalchemy/util.py @@ -6,6 +6,7 @@ __all__ = ['OrderedProperties', 'OrderedDict', 'generic_repr', 'HashSet'] import thread, weakref, UserList,string, inspect +from exceptions import * def to_list(x): if x is None: @@ -257,7 +258,7 @@ class HistoryArraySet(UserList.UserList): return id(self) def _setrecord(self, item): if self.readonly: - raise "This list is read only" + raise InvalidRequestError("This list is read only") try: val = self.records[item] if val is True or val is None: @@ -270,7 +271,7 @@ class HistoryArraySet(UserList.UserList): return True def _delrecord(self, item): if self.readonly: - raise "This list is read only" + raise InvalidRequestError("This list is read only") try: val = self.records[item] if val is None: @@ -428,7 +429,7 @@ def constructor_args(instance, **kwargs): if hasattr(instance, arg): newparams[arg] = getattr(instance, arg) else: - raise "instance has no attribute '%s'" % arg + raise AssertionError("instance has no attribute '%s'" % arg) return newparams \ No newline at end of file diff --git a/test/cycles.py b/test/cycles.py index 69f632f1f4..863d30fd95 100644 --- a/test/cycles.py +++ b/test/cycles.py @@ -249,7 +249,7 @@ class CycleTest2(AssertMixin): p = Person() p.balls.append(b) p.favorateBall = b - #objectstore.commit() + objectstore.commit() if __name__ == "__main__": diff --git a/test/mapper.py b/test/mapper.py index 8c4a7485fe..2dabc8b670 100644 --- a/test/mapper.py +++ b/test/mapper.py @@ -148,10 +148,10 @@ class MapperTest(MapperSuperTest): # assert that overriding a column raises an error try: m = mapper(User, users, properties = { - 'user_name' : relation(Address, addresses), + 'user_name' : relation(mapper(Address, addresses)), }) - self.assert_(False, "should have raised ValueError") - except ValueError, e: + self.assert_(False, "should have raised ArgumentError") + except ArgumentError, e: self.assert_(True) # assert that allow_column_override cancels the error diff --git a/test/objectstore.py b/test/objectstore.py index a117b4112f..687c9b1028 100644 --- a/test/objectstore.py +++ b/test/objectstore.py @@ -7,7 +7,6 @@ import testbase from tables import * import tables - class HistoryTest(AssertMixin): def setUpAll(self): db.echo = False