diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-11-22 20:04:19 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2013-11-22 20:04:19 -0500 |
| commit | 6b79d2ea7951abc2bb6083b541db0fbf71590dd3 (patch) | |
| tree | 4c1edc6856fe743b44e69c1f70750d469b642ed5 /lib/sqlalchemy/sql | |
| parent | f112dc1d533033f19186eb65227aba1660d03102 (diff) | |
| download | sqlalchemy-6b79d2ea7951abc2bb6083b541db0fbf71590dd3.tar.gz | |
- The precision used when coercing a returned floating point value to
Python ``Decimal`` via string is now configurable. The
flag ``decimal_return_scale`` is now supported by all :class:`.Numeric`
and :class:`.Float` types, which will ensure this many digits are taken
from the native floating point value when it is converted to string.
If not present, the type will make use of the value of ``.scale``, if
the type supports this setting and it is non-None. Otherwise the original
default length of 10 is used. [ticket:2867]
Diffstat (limited to 'lib/sqlalchemy/sql')
| -rw-r--r-- | lib/sqlalchemy/sql/sqltypes.py | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/lib/sqlalchemy/sql/sqltypes.py b/lib/sqlalchemy/sql/sqltypes.py index 8f22ae81c..7cf5a6dca 100644 --- a/lib/sqlalchemy/sql/sqltypes.py +++ b/lib/sqlalchemy/sql/sqltypes.py @@ -409,6 +409,7 @@ class BigInteger(Integer): __visit_name__ = 'big_integer' + class Numeric(_DateAffinity, TypeEngine): """A type for fixed precision numbers. @@ -453,7 +454,10 @@ class Numeric(_DateAffinity, TypeEngine): __visit_name__ = 'numeric' - def __init__(self, precision=None, scale=None, asdecimal=True): + _default_decimal_return_scale = 10 + + def __init__(self, precision=None, scale=None, + decimal_return_scale=None, asdecimal=True): """ Construct a Numeric. @@ -468,6 +472,18 @@ class Numeric(_DateAffinity, TypeEngine): datatypes - the Numeric type will ensure that return values are one or the other across DBAPIs consistently. + :param decimal_return_scale: Default scale to use when converting + from floats to Python decimals. Floating point values will typically + be much longer due to decimal inaccuracy, and most floating point + database types don't have a notion of "scale", so by default the + float type looks for the first ten decimal places when converting. + Specfiying this value will override that length. Types which + do include an explicit ".scale" value, such as the base :class:`.Numeric` + as well as the MySQL float types, will use the value of ".scale" + as the default for decimal_return_scale, if not otherwise specified. + + .. versionadded:: 0.9.0 + When using the ``Numeric`` type, care should be taken to ensure that the asdecimal setting is apppropriate for the DBAPI in use - when Numeric applies a conversion from Decimal->float or float-> @@ -487,6 +503,10 @@ class Numeric(_DateAffinity, TypeEngine): """ self.precision = precision self.scale = scale + self.decimal_return_scale = decimal_return_scale \ + if decimal_return_scale is not None \ + else self.scale if self.scale is not None \ + else self._default_decimal_return_scale self.asdecimal = asdecimal def get_dbapi_type(self, dbapi): @@ -525,12 +545,10 @@ class Numeric(_DateAffinity, TypeEngine): 'storage.' % (dialect.name, dialect.driver)) # we're a "numeric", DBAPI returns floats, convert. - if self.scale is not None: - return processors.to_decimal_processor_factory( - decimal.Decimal, self.scale) - else: - return processors.to_decimal_processor_factory( - decimal.Decimal) + return processors.to_decimal_processor_factory( + decimal.Decimal, + self.scale if self.scale is not None + else self._default_decimal_return_scale) else: if dialect.supports_native_decimal: return processors.to_float @@ -576,7 +594,8 @@ class Float(Numeric): scale = None - def __init__(self, precision=None, asdecimal=False, **kwargs): + def __init__(self, precision=None, asdecimal=False, + decimal_return_scale=None, **kwargs): """ Construct a Float. @@ -587,6 +606,17 @@ class Float(Numeric): defaults to ``False``. Note that setting this flag to ``True`` results in floating point conversion. + :param decimal_return_scale: Default scale to use when converting + from floats to Python decimals. Floating point values will typically + be much longer due to decimal inaccuracy, and most floating point + database types don't have a notion of "scale", so by default the + float type looks for the first ten decimal places when converting. + Specfiying this value will override that length. Note that the + MySQL float types, which do include "scale", will use "scale" + as the default for decimal_return_scale, if not otherwise specified. + + .. versionadded:: 0.9.0 + :param \**kwargs: deprecated. Additional arguments here are ignored by the default :class:`.Float` type. For database specific floats that support additional arguments, see that dialect's @@ -596,13 +626,17 @@ class Float(Numeric): """ self.precision = precision self.asdecimal = asdecimal + self.decimal_return_scale = decimal_return_scale \ + if decimal_return_scale is not None \ + else self._default_decimal_return_scale if kwargs: util.warn_deprecated("Additional keyword arguments " "passed to Float ignored.") def result_processor(self, dialect, coltype): if self.asdecimal: - return processors.to_decimal_processor_factory(decimal.Decimal) + return processors.to_decimal_processor_factory( + decimal.Decimal, self.decimal_return_scale) else: return None |
