diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-03-30 14:07:27 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-03-30 14:07:27 -0400 |
| commit | b99cd60cb893220d025bca1d40b916f0d7a4754e (patch) | |
| tree | e7257f5bdb043da18b6ef2c8f72a7e5985b37a6c /lib/sqlalchemy | |
| parent | 218c3cb365e7354a312bc3e24e1cb21a2487459c (diff) | |
| download | sqlalchemy-b99cd60cb893220d025bca1d40b916f0d7a4754e.tar.gz | |
- beef up the "augmenting existing types" section
- add docstirngs for everything TypeDecorator [ticket:2086]
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/types.py | 126 |
1 files changed, 125 insertions, 1 deletions
diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py index de74b2031..1a894ce63 100644 --- a/lib/sqlalchemy/types.py +++ b/lib/sqlalchemy/types.py @@ -184,6 +184,13 @@ class TypeEngine(AbstractType): return dialect.type_descriptor(self) def adapt(self, cls, **kw): + """Produce an "adapted" form of this type, given an "impl" class + to work with. + + This method is used internally to associate generic + types with "implementation" types that are specific to a particular + dialect. + """ return util.constructor_copy(self, cls, **kw) def _coerce_compared_value(self, op, value): @@ -216,6 +223,14 @@ class TypeEngine(AbstractType): return self._type_affinity is other._type_affinity def compile(self, dialect=None): + """Produce a string-compiled form of this :class:`.TypeEngine`. + + When called with no arguments, uses a "default" dialect + to produce a string result. + + :param dialect: a :class:`.Dialect` instance. + + """ # arg, return value is inconsistent with # ClauseElement.compile()....this is a mistake. @@ -391,6 +406,19 @@ class TypeDecorator(TypeEngine): __visit_name__ = "type_decorator" def __init__(self, *args, **kwargs): + """Construct a :class:`.TypeDecorator`. + + Arguments sent here are passed to the constructor + of the class assigned to the ``impl`` class level attribute, + where the ``self.impl`` attribute is assigned an instance + of the implementation type. If ``impl`` at the class level + is already an instance, then it's assigned to ``self.impl`` + as is. + + Subclasses can override this to customize the generation + of ``self.impl``. + + """ if not hasattr(self.__class__, 'impl'): raise AssertionError("TypeDecorator implementations " "require a class-level variable " @@ -422,7 +450,10 @@ class TypeDecorator(TypeEngine): return self.impl._type_affinity def type_engine(self, dialect): - """Return a TypeEngine instance for this TypeDecorator. + """Return a dialect-specific :class:`.TypeEngine` instance for this :class:`.TypeDecorator`. + + In most cases this returns a dialect-adapted form of + the :class:`.TypeEngine` type represented by ``self.impl``. """ adapted = dialect.type_descriptor(self) @@ -449,12 +480,47 @@ class TypeDecorator(TypeEngine): return getattr(self.impl, key) def process_bind_param(self, value, dialect): + """Receive a bound parameter value to be converted. + + Subclasses override this method to return the + value that should be passed along to the underlying + :class:`.TypeEngine` object, and from there to the + DBAPI ``execute()`` method. + + :param value: the value. Can be None. + :param dialect: the :class:`.Dialect` in use. + + """ raise NotImplementedError() def process_result_value(self, value, dialect): + """Receive a result-row column value to be converted. + + Subclasses override this method to return the + value that should be passed back to the application, + given a value that is already processed by + the underlying :class:`.TypeEngine` object, originally + from the DBAPI cursor method ``fetchone()`` or similar. + + :param value: the value. Can be None. + :param dialect: the :class:`.Dialect` in use. + + """ raise NotImplementedError() def bind_processor(self, dialect): + """Provide a bound value processing function for the given :class:`.Dialect`. + + This is the method that fulfills the :class:`.TypeEngine` + contract for bound value conversion. :class:`.TypeDecorator` + will wrap a user-defined implementation of + :meth:`process_bind_param` here. + + User-defined code can override this method directly, + though its likely best to use :meth:`process_bind_param` so that + the processing provided by ``self.impl`` is maintained. + + """ if self.__class__.process_bind_param.func_code \ is not TypeDecorator.process_bind_param.func_code: process_param = self.process_bind_param @@ -472,6 +538,18 @@ class TypeDecorator(TypeEngine): return self.impl.bind_processor(dialect) def result_processor(self, dialect, coltype): + """Provide a result value processing function for the given :class:`.Dialect`. + + This is the method that fulfills the :class:`.TypeEngine` + contract for result value conversion. :class:`.TypeDecorator` + will wrap a user-defined implementation of + :meth:`process_result_value` here. + + User-defined code can override this method directly, + though its likely best to use :meth:`process_result_value` so that + the processing provided by ``self.impl`` is maintained. + + """ if self.__class__.process_result_value.func_code \ is not TypeDecorator.process_result_value.func_code: process_value = self.process_result_value @@ -513,17 +591,63 @@ class TypeDecorator(TypeEngine): return self.coerce_compared_value(op, value) def copy(self): + """Produce a copy of this :class:`.TypeDecorator` instance. + + This is a shallow copy and is provided to fulfill part of + the :class:`.TypeEngine` contract. It usually does not + need to be overridden unless the user-defined :class:`.TypeDecorator` + has local state that should be deep-copied. + + """ instance = self.__class__.__new__(self.__class__) instance.__dict__.update(self.__dict__) return instance def get_dbapi_type(self, dbapi): + """Return the DBAPI type object represented by this :class:`.TypeDecorator`. + + By default this calls upon :meth:`.TypeEngine.get_dbapi_type` of the + underlying "impl". + """ return self.impl.get_dbapi_type(dbapi) def copy_value(self, value): + """Given a value, produce a copy of it. + + By default this calls upon :meth:`.TypeEngine.copy_value` + of the underlying "impl". + + :meth:`.copy_value` will return the object + itself, assuming "mutability" is not enabled. + Only the :class:`.MutableType` mixin provides a copy + function that actually produces a new object. + The copying function is used by the ORM when + "mutable" types are used, to memoize the original + version of an object as loaded from the database, + which is then compared to the possibly mutated + version to check for changes. + + Modern implementations should use the + ``sqlalchemy.ext.mutable`` extension described in + :ref:`mutable_toplevel` for intercepting in-place + changes to values. + + """ return self.impl.copy_value(value) def compare_values(self, x, y): + """Given two values, compare them for equality. + + By default this calls upon :meth:`.TypeEngine.compare_values` + of the underlying "impl", which in turn usually + uses the Python equals operator ``==``. + + This function is used by the ORM to compare + an original-loaded value with an intercepted + "changed" value, to determine if a net change + has occurred. + + """ return self.impl.compare_values(x, y) def is_mutable(self): |
