]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
port numeric tests to dialect suite
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 7 Feb 2013 01:20:07 +0000 (20:20 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 7 Feb 2013 01:20:07 +0000 (20:20 -0500)
lib/sqlalchemy/testing/requirements.py
lib/sqlalchemy/testing/suite/test_types.py
test/requirements.py
test/sql/test_types.py

index e6e21d2cb70b703f167514ec268f4253a8bb154c..6cc1de96df3d68d77fb66a35cea104432e2ebc63 100644 (file)
@@ -231,6 +231,10 @@ class SuiteRequirements(Requirements):
                     self.config.db.dialect.sequences_optional
             ], "no sequence support, or sequences not optional")
 
+
+
+
+
     @property
     def reflects_pk_names(self):
         return exclusions.closed()
@@ -328,6 +332,40 @@ class SuiteRequirements(Requirements):
 
         return exclusions.open()
 
+    @property
+    def precision_numerics_general(self):
+        """target backend has general support for moderately high-precision
+        numerics."""
+        return exclusions.open()
+
+    @property
+    def precision_numerics_enotation_small(self):
+        """target backend supports Decimal() objects using E notation
+        to represent very small values."""
+        return exclusions.closed()
+
+    @property
+    def precision_numerics_enotation_large(self):
+        """target backend supports Decimal() objects using E notation
+        to represent very large values."""
+        return exclusions.closed()
+
+    @property
+    def precision_numerics_many_significant_digits(self):
+        """target backend supports values with many digits on both sides,
+        such as 319438950232418390.273596, 87673.594069654243
+
+        """
+        return exclusions.closed()
+
+    @property
+    def precision_numerics_retains_significant_digits(self):
+        """A precision numeric type will return empty significant digits,
+        i.e. a value such as 10.000 will come back in Decimal form with
+        the .000 maintained."""
+
+        return exclusions.closed()
+
     @property
     def text_type(self):
         """Target database must support an unbounded Text() "
index 5ad26c2f2fb6ee0765959de1876b5eb64227131d..0716b1b9140cb55b22e7c8f078c7e0c2d4a5db21 100644 (file)
@@ -4,8 +4,11 @@ from .. import fixtures, config
 from ..assertions import eq_
 from ..config import requirements
 from sqlalchemy import Integer, Unicode, UnicodeText, select
-from sqlalchemy import Date, DateTime, Time, MetaData, String, Text
+from sqlalchemy import Date, DateTime, Time, MetaData, String, \
+            Text, Numeric, Float
 from ..schema import Table, Column
+from ... import testing
+import decimal
 import datetime
 
 
@@ -243,9 +246,148 @@ class DateHistoricTest(_DateFixture, fixtures.TablesTest):
     datatype = Date
     data = datetime.date(1727, 4, 1)
 
+class NumericTest(fixtures.TestBase):
+
+    @testing.emits_warning(r".*does \*not\* support Decimal objects natively")
+    @testing.provide_metadata
+    def _do_test(self, type_, input_, output, filter_=None, check_scale=False):
+        metadata = self.metadata
+        t = Table('t', metadata, Column('x', type_))
+        t.create()
+        t.insert().execute([{'x':x} for x in input_])
+
+        result = set([row[0] for row in t.select().execute()])
+        output = set(output)
+        if filter_:
+            result = set(filter_(x) for x in result)
+            output = set(filter_(x) for x in output)
+        eq_(result, output)
+        if check_scale:
+            eq_(
+                [str(x) for x in result],
+                [str(x) for x in output],
+            )
+
+    def test_numeric_as_decimal(self):
+        self._do_test(
+            Numeric(precision=8, scale=4),
+            [15.7563, decimal.Decimal("15.7563"), None],
+            [decimal.Decimal("15.7563"), None],
+        )
+
+    def test_numeric_as_float(self):
+        self._do_test(
+            Numeric(precision=8, scale=4, asdecimal=False),
+            [15.7563, decimal.Decimal("15.7563"), None],
+            [15.7563, None],
+        )
+
+    def test_float_as_decimal(self):
+        self._do_test(
+            Float(precision=8, asdecimal=True),
+            [15.7563, decimal.Decimal("15.7563"), None],
+            [decimal.Decimal("15.7563"), None],
+        )
+
+    def test_float_as_float(self):
+        self._do_test(
+            Float(precision=8),
+            [15.7563, decimal.Decimal("15.7563")],
+            [15.7563],
+            filter_=lambda n: n is not None and round(n, 5) or None
+        )
+
+    @testing.requires.precision_numerics_general
+    def test_precision_decimal(self):
+        numbers = set([
+            decimal.Decimal("54.234246451650"),
+            decimal.Decimal("0.004354"),
+            decimal.Decimal("900.0"),
+        ])
+
+        self._do_test(
+            Numeric(precision=18, scale=12),
+            numbers,
+            numbers,
+        )
+
+    @testing.requires.precision_numerics_enotation_large
+    def test_enotation_decimal(self):
+        """test exceedingly small decimals.
+
+        Decimal reports values with E notation when the exponent
+        is greater than 6.
+
+        """
+
+        numbers = set([
+            decimal.Decimal('1E-2'),
+            decimal.Decimal('1E-3'),
+            decimal.Decimal('1E-4'),
+            decimal.Decimal('1E-5'),
+            decimal.Decimal('1E-6'),
+            decimal.Decimal('1E-7'),
+            decimal.Decimal('1E-8'),
+            decimal.Decimal("0.01000005940696"),
+            decimal.Decimal("0.00000005940696"),
+            decimal.Decimal("0.00000000000696"),
+            decimal.Decimal("0.70000000000696"),
+            decimal.Decimal("696E-12"),
+        ])
+        self._do_test(
+            Numeric(precision=18, scale=14),
+            numbers,
+            numbers
+        )
+
+    @testing.requires.precision_numerics_enotation_large
+    def test_enotation_decimal_large(self):
+        """test exceedingly large decimals.
+
+        """
+
+        numbers = set([
+            decimal.Decimal('4E+8'),
+            decimal.Decimal("5748E+15"),
+            decimal.Decimal('1.521E+15'),
+            decimal.Decimal('00000000000000.1E+12'),
+        ])
+        self._do_test(
+            Numeric(precision=25, scale=2),
+            numbers,
+            numbers
+        )
+
+    @testing.requires.precision_numerics_many_significant_digits
+    def test_many_significant_digits(self):
+        numbers = set([
+            decimal.Decimal("31943874831932418390.01"),
+            decimal.Decimal("319438950232418390.273596"),
+            decimal.Decimal("87673.594069654243"),
+        ])
+        self._do_test(
+            Numeric(precision=38, scale=12),
+            numbers,
+            numbers
+        )
+
+    @testing.requires.precision_numerics_retains_significant_digits
+    def test_numeric_no_decimal(self):
+        numbers = set([
+            decimal.Decimal("1.000")
+        ])
+        self._do_test(
+            Numeric(precision=5, scale=3),
+            numbers,
+            numbers,
+            check_scale=True
+        )
+
+
 
 __all__ = ('UnicodeVarcharTest', 'UnicodeTextTest',
             'DateTest', 'DateTimeTest', 'TextTest',
+            'NumericTest',
             'DateTimeHistoricTest', 'DateTimeCoercedToDateTimeTest',
             'TimeMicrosecondsTest', 'TimeTest', 'DateTimeMicrosecondsTest',
             'DateHistoricTest', 'StringTest')
index 8dde55d6af5806d2ff98fb03cfbafff93802644e..738429158d8945bd89fc1a03ea50828c27d3e19f 100644 (file)
@@ -465,6 +465,61 @@ class DefaultRequirements(SuiteRequirements):
         return skip_if(['mssql', 'mysql', 'firebird', '+zxjdbc',
                     'oracle', 'sybase'])
 
+    @property
+    def precision_numerics_general(self):
+        """target backend has general support for moderately high-precision
+        numerics."""
+        return fails_if('mssql+pymssql', 'FIXME: improve pymssql dec handling')
+
+    @property
+    def precision_numerics_enotation_small(self):
+        """target backend supports Decimal() objects using E notation
+        to represent very small values."""
+        return fails_if('mssql+pymssql', 'FIXME: improve pymssql dec handling')
+
+    @property
+    def precision_numerics_enotation_large(self):
+        """target backend supports Decimal() objects using E notation
+        to represent very large values."""
+
+        return fails_if(
+                ("sybase+pyodbc", None, None,
+                    "Don't know how do get these values through FreeTDS + Sybase"),
+                ("firebird", None, None, "Precision must be from 1 to 18"),
+            )
+
+    @property
+    def precision_numerics_many_significant_digits(self):
+        """target backend supports values with many digits on both sides,
+        such as 319438950232418390.273596, 87673.594069654243
+
+        """
+        return fails_if(
+                    [('sqlite', None, None, 'TODO'),
+                    ("firebird", None, None, "Precision must be from 1 to 18"),
+                    ("sybase+pysybase", None, None, "TODO"),
+                    ('mssql+pymssql', None, None, 'FIXME: improve pymssql dec handling')]
+                )
+
+    @property
+    def precision_numerics_retains_significant_digits(self):
+        """A precision numeric type will return empty significant digits,
+        i.e. a value such as 10.000 will come back in Decimal form with
+        the .000 maintained."""
+
+        return fails_if(
+                [
+                    ('oracle', None, None,
+            "this may be a bug due to the difficulty in handling "
+            "oracle precision numerics"),
+                    ('postgresql+pg8000', None, None,
+        "pg-8000 does native decimal but truncates the decimals."),
+                    ("firebird", None, None,
+        "database and/or driver truncates decimal places.")
+                ]
+                )
+
+
     @property
     def python2(self):
         return skip_if(
index 8987743d4a8ef17b424604d75dd1e7eaee81f45e..0e6f1b5f037c46f398c915ed8911f6b1f307d70a 100644 (file)
@@ -1326,168 +1326,6 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
 
 
 
-class NumericTest(fixtures.TestBase):
-    def setup(self):
-        global metadata
-        metadata = MetaData(testing.db)
-
-    def teardown(self):
-        metadata.drop_all()
-
-    @testing.emits_warning(r".*does \*not\* support Decimal objects natively")
-    def _do_test(self, type_, input_, output, filter_=None, check_scale=False):
-        t = Table('t', metadata, Column('x', type_))
-        t.create()
-        t.insert().execute([{'x':x} for x in input_])
-
-        result = set([row[0] for row in t.select().execute()])
-        output = set(output)
-        if filter_:
-            result = set(filter_(x) for x in result)
-            output = set(filter_(x) for x in output)
-        #print result
-        #print output
-        eq_(result, output)
-        if check_scale:
-            eq_(
-                [str(x) for x in result],
-                [str(x) for x in output],
-            )
-
-    def test_numeric_as_decimal(self):
-        self._do_test(
-            Numeric(precision=8, scale=4),
-            [15.7563, decimal.Decimal("15.7563"), None],
-            [decimal.Decimal("15.7563"), None],
-        )
-
-    def test_numeric_as_float(self):
-        if testing.against("oracle+cx_oracle"):
-            filter_ = lambda n:n is not None and round(n, 5) or None
-        else:
-            filter_ = None
-
-        self._do_test(
-            Numeric(precision=8, scale=4, asdecimal=False),
-            [15.7563, decimal.Decimal("15.7563"), None],
-            [15.7563, None],
-            filter_ = filter_
-        )
-
-    def test_float_as_decimal(self):
-        self._do_test(
-            Float(precision=8, asdecimal=True),
-            [15.7563, decimal.Decimal("15.7563"), None],
-            [decimal.Decimal("15.7563"), None],
-            filter_ = lambda n:n is not None and round(n, 5) or None
-        )
-
-    def test_float_as_float(self):
-        self._do_test(
-            Float(precision=8),
-            [15.7563, decimal.Decimal("15.7563")],
-            [15.7563],
-            filter_ = lambda n:n is not None and round(n, 5) or None
-        )
-
-    @testing.fails_on('mssql+pymssql', 'FIXME: improve pymssql dec handling')
-    def test_precision_decimal(self):
-        numbers = set([
-            decimal.Decimal("54.234246451650"),
-            decimal.Decimal("0.004354"),
-            decimal.Decimal("900.0"),
-        ])
-
-        self._do_test(
-            Numeric(precision=18, scale=12),
-            numbers,
-            numbers,
-        )
-
-    @testing.fails_on('mssql+pymssql', 'FIXME: improve pymssql dec handling')
-    def test_enotation_decimal(self):
-        """test exceedingly small decimals.
-
-        Decimal reports values with E notation when the exponent
-        is greater than 6.
-
-        """
-
-        numbers = set([
-            decimal.Decimal('1E-2'),
-            decimal.Decimal('1E-3'),
-            decimal.Decimal('1E-4'),
-            decimal.Decimal('1E-5'),
-            decimal.Decimal('1E-6'),
-            decimal.Decimal('1E-7'),
-            decimal.Decimal('1E-8'),
-            decimal.Decimal("0.01000005940696"),
-            decimal.Decimal("0.00000005940696"),
-            decimal.Decimal("0.00000000000696"),
-            decimal.Decimal("0.70000000000696"),
-            decimal.Decimal("696E-12"),
-        ])
-        self._do_test(
-            Numeric(precision=18, scale=14),
-            numbers,
-            numbers
-        )
-
-    @testing.fails_on("sybase+pyodbc",
-                        "Don't know how do get these values through FreeTDS + Sybase")
-    @testing.fails_on("firebird", "Precision must be from 1 to 18")
-    def test_enotation_decimal_large(self):
-        """test exceedingly large decimals.
-
-        """
-
-        numbers = set([
-            decimal.Decimal('4E+8'),
-            decimal.Decimal("5748E+15"),
-            decimal.Decimal('1.521E+15'),
-            decimal.Decimal('00000000000000.1E+12'),
-        ])
-        self._do_test(
-            Numeric(precision=25, scale=2),
-            numbers,
-            numbers
-        )
-
-    @testing.fails_on('sqlite', 'TODO')
-    @testing.fails_on("firebird", "Precision must be from 1 to 18")
-    @testing.fails_on("sybase+pysybase", "TODO")
-    @testing.fails_on('mssql+pymssql', 'FIXME: improve pymssql dec handling')
-    def test_many_significant_digits(self):
-        numbers = set([
-            decimal.Decimal("31943874831932418390.01"),
-            decimal.Decimal("319438950232418390.273596"),
-            decimal.Decimal("87673.594069654243"),
-        ])
-        self._do_test(
-            Numeric(precision=38, scale=12),
-            numbers,
-            numbers
-        )
-
-    @testing.fails_on('oracle+cx_oracle',
-        "this may be a bug due to the difficulty in handling "
-        "oracle precision numerics"
-    )
-    @testing.fails_on('postgresql+pg8000',
-        "pg-8000 does native decimal but truncates the decimals.")
-    @testing.fails_on("firebird",
-        "database and/or driver truncates decimal places."
-        )
-    def test_numeric_no_decimal(self):
-        numbers = set([
-            decimal.Decimal("1.000")
-        ])
-        self._do_test(
-            Numeric(precision=5, scale=3),
-            numbers,
-            numbers,
-            check_scale=True
-        )
 
 class NumericRawSQLTest(fixtures.TestBase):
     """Test what DBAPIs and dialects return without any typing