| 1 | # exc.py - ORM exceptions |
|---|
| 2 | # Copyright (C) the SQLAlchemy authors and contributors |
|---|
| 3 | # |
|---|
| 4 | # This module is part of SQLAlchemy and is released under |
|---|
| 5 | # the MIT License: http://www.opensource.org/licenses/mit-license.php |
|---|
| 6 | |
|---|
| 7 | """SQLAlchemy ORM exceptions.""" |
|---|
| 8 | |
|---|
| 9 | import sqlalchemy as sa |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | NO_STATE = (AttributeError, KeyError) |
|---|
| 13 | """Exception types that may be raised by instrumentation implementations.""" |
|---|
| 14 | |
|---|
| 15 | class ConcurrentModificationError(sa.exc.SQLAlchemyError): |
|---|
| 16 | """Rows have been modified outside of the unit of work.""" |
|---|
| 17 | |
|---|
| 18 | |
|---|
| 19 | class FlushError(sa.exc.SQLAlchemyError): |
|---|
| 20 | """A invalid condition was detected during flush().""" |
|---|
| 21 | |
|---|
| 22 | |
|---|
| 23 | class UnmappedError(sa.exc.InvalidRequestError): |
|---|
| 24 | """TODO""" |
|---|
| 25 | |
|---|
| 26 | |
|---|
| 27 | class UnmappedInstanceError(UnmappedError): |
|---|
| 28 | """An mapping operation was requested for an unknown instance.""" |
|---|
| 29 | |
|---|
| 30 | def __init__(self, obj, msg=None): |
|---|
| 31 | if not msg: |
|---|
| 32 | try: |
|---|
| 33 | mapper = sa.orm.class_mapper(type(obj)) |
|---|
| 34 | name = _safe_cls_name(type(obj)) |
|---|
| 35 | msg = ("Class %r is mapped, but this instance lacks " |
|---|
| 36 | "instrumentation. Possible causes: instance created " |
|---|
| 37 | "before sqlalchemy.orm.mapper(%s) was called, or " |
|---|
| 38 | "instance was pickled/depickled without instrumentation" |
|---|
| 39 | "information." % (name, name)) |
|---|
| 40 | except UnmappedClassError: |
|---|
| 41 | msg = _default_unmapped(type(obj)) |
|---|
| 42 | if isinstance(obj, type): |
|---|
| 43 | msg += ( |
|---|
| 44 | '; was a class (%s) supplied where an instance was ' |
|---|
| 45 | 'required?' % _safe_cls_name(obj)) |
|---|
| 46 | UnmappedError.__init__(self, msg) |
|---|
| 47 | |
|---|
| 48 | |
|---|
| 49 | class UnmappedClassError(UnmappedError): |
|---|
| 50 | """An mapping operation was requested for an unknown class.""" |
|---|
| 51 | |
|---|
| 52 | def __init__(self, cls, msg=None): |
|---|
| 53 | if not msg: |
|---|
| 54 | msg = _default_unmapped(cls) |
|---|
| 55 | UnmappedError.__init__(self, msg) |
|---|
| 56 | |
|---|
| 57 | |
|---|
| 58 | class ObjectDeletedError(sa.exc.InvalidRequestError): |
|---|
| 59 | """An refresh() operation failed to re-retrieve an object's row.""" |
|---|
| 60 | |
|---|
| 61 | |
|---|
| 62 | class UnmappedColumnError(sa.exc.InvalidRequestError): |
|---|
| 63 | """Mapping operation was requested on an unknown column.""" |
|---|
| 64 | |
|---|
| 65 | |
|---|
| 66 | class NoResultFound(sa.exc.InvalidRequestError): |
|---|
| 67 | """A database result was required but none was found.""" |
|---|
| 68 | |
|---|
| 69 | |
|---|
| 70 | class MultipleResultsFound(sa.exc.InvalidRequestError): |
|---|
| 71 | """A single database result was required but more than one were found.""" |
|---|
| 72 | |
|---|
| 73 | |
|---|
| 74 | # Legacy compat until 0.6. |
|---|
| 75 | sa.exc.ConcurrentModificationError = ConcurrentModificationError |
|---|
| 76 | sa.exc.FlushError = FlushError |
|---|
| 77 | sa.exc.UnmappedColumnError |
|---|
| 78 | |
|---|
| 79 | def _safe_cls_name(cls): |
|---|
| 80 | try: |
|---|
| 81 | cls_name = '.'.join((cls.__module__, cls.__name__)) |
|---|
| 82 | except AttributeError: |
|---|
| 83 | cls_name = getattr(cls, '__name__', None) |
|---|
| 84 | if cls_name is None: |
|---|
| 85 | cls_name = repr(cls) |
|---|
| 86 | return cls_name |
|---|
| 87 | |
|---|
| 88 | def _default_unmapped(cls): |
|---|
| 89 | try: |
|---|
| 90 | mappers = sa.orm.attributes.manager_of_class(cls).mappers |
|---|
| 91 | except NO_STATE: |
|---|
| 92 | mappers = {} |
|---|
| 93 | except TypeError: |
|---|
| 94 | mappers = {} |
|---|
| 95 | name = _safe_cls_name(cls) |
|---|
| 96 | |
|---|
| 97 | if not mappers: |
|---|
| 98 | return "Class '%s' is not mapped" % name |
|---|