# coding: utf-8 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, Numeric, Float from ..schema import Table, Column from ... import testing import decimal import datetime class _UnicodeFixture(object): __requires__ = 'unicode_data', data = u"Alors vous imaginez ma surprise, au lever du jour, "\ u"quand une drôle de petite voix m’a réveillé. Elle "\ u"disait: « S’il vous plaît… dessine-moi un mouton! »" @classmethod def define_tables(cls, metadata): Table('unicode_table', metadata, Column('id', Integer, primary_key=True, test_needs_autoincrement=True), Column('unicode_data', cls.datatype), ) def test_round_trip(self): unicode_table = self.tables.unicode_table config.db.execute( unicode_table.insert(), { 'unicode_data': self.data, } ) row = config.db.execute( select([ unicode_table.c.unicode_data, ]) ).first() eq_( row, (self.data, ) ) assert isinstance(row[0], unicode) def test_round_trip_executemany(self): unicode_table = self.tables.unicode_table config.db.execute( unicode_table.insert(), [ { 'unicode_data': self.data, } for i in xrange(3) ] ) rows = config.db.execute( select([ unicode_table.c.unicode_data, ]) ).fetchall() eq_( rows, [(self.data, ) for i in xrange(3)] ) for row in rows: assert isinstance(row[0], unicode) def _test_empty_strings(self): unicode_table = self.tables.unicode_table config.db.execute( unicode_table.insert(), {"unicode_data": u''} ) row = config.db.execute( select([unicode_table.c.unicode_data]) ).first() eq_(row, (u'',)) class UnicodeVarcharTest(_UnicodeFixture, fixtures.TablesTest): __requires__ = 'unicode_data', datatype = Unicode(255) @requirements.empty_strings_varchar def test_empty_strings_varchar(self): self._test_empty_strings() class UnicodeTextTest(_UnicodeFixture, fixtures.TablesTest): __requires__ = 'unicode_data', 'text_type' datatype = UnicodeText() @requirements.empty_strings_text def test_empty_strings_text(self): self._test_empty_strings() class TextTest(fixtures.TablesTest): @classmethod def define_tables(cls, metadata): Table('text_table', metadata, Column('id', Integer, primary_key=True, test_needs_autoincrement=True), Column('text_data', Text), ) def test_text_roundtrip(self): text_table = self.tables.text_table config.db.execute( text_table.insert(), {"text_data": 'some text'} ) row = config.db.execute( select([text_table.c.text_data]) ).first() eq_(row, ('some text',)) def test_text_empty_strings(self): text_table = self.tables.text_table config.db.execute( text_table.insert(), {"text_data": ''} ) row = config.db.execute( select([text_table.c.text_data]) ).first() eq_(row, ('',)) class StringTest(fixtures.TestBase): @requirements.unbounded_varchar def test_nolength_string(self): metadata = MetaData() foo = Table('foo', metadata, Column('one', String) ) foo.create(config.db) foo.drop(config.db) class _DateFixture(object): compare = None @classmethod def define_tables(cls, metadata): Table('date_table', metadata, Column('id', Integer, primary_key=True, test_needs_autoincrement=True), Column('date_data', cls.datatype), ) def test_round_trip(self): date_table = self.tables.date_table config.db.execute( date_table.insert(), {'date_data': self.data} ) row = config.db.execute( select([ date_table.c.date_data, ]) ).first() compare = self.compare or self.data eq_(row, (compare, )) assert isinstance(row[0], type(compare)) def test_null(self): date_table = self.tables.date_table config.db.execute( date_table.insert(), {'date_data': None} ) row = config.db.execute( select([ date_table.c.date_data, ]) ).first() eq_(row, (None,)) class DateTimeTest(_DateFixture, fixtures.TablesTest): __requires__ = 'datetime', datatype = DateTime data = datetime.datetime(2012, 10, 15, 12, 57, 18) class DateTimeMicrosecondsTest(_DateFixture, fixtures.TablesTest): __requires__ = 'datetime_microseconds', datatype = DateTime data = datetime.datetime(2012, 10, 15, 12, 57, 18, 396) class TimeTest(_DateFixture, fixtures.TablesTest): __requires__ = 'time', datatype = Time data = datetime.time(12, 57, 18) class TimeMicrosecondsTest(_DateFixture, fixtures.TablesTest): __requires__ = 'time_microseconds', datatype = Time data = datetime.time(12, 57, 18, 396) class DateTest(_DateFixture, fixtures.TablesTest): __requires__ = 'date', datatype = Date data = datetime.date(2012, 10, 15) class DateTimeCoercedToDateTimeTest(_DateFixture, fixtures.TablesTest): __requires__ = 'date', datatype = Date data = datetime.datetime(2012, 10, 15, 12, 57, 18) compare = datetime.date(2012, 10, 15) class DateTimeHistoricTest(_DateFixture, fixtures.TablesTest): __requires__ = 'datetime_historic', datatype = DateTime data = datetime.datetime(1850, 11, 10, 11, 52, 35) class DateHistoricTest(_DateFixture, fixtures.TablesTest): __requires__ = 'date_historic', 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')