@@ -425,29 +425,12 @@ def test_date_and_index(self):
425
425
"IntDateCol loaded with incorrect type" )
426
426
427
427
428
- class TestSQLAlchemy (PandasSQLTest ):
429
-
430
- '''
431
- Test the sqlalchemy backend against an in-memory sqlite database .
428
+ class _TestSQLAlchemy (PandasSQLTest ):
429
+ """
430
+ Base class for testing the sqlalchemy backend. Subclasses for specific
431
+ database types are created below .
432
432
Assume that sqlalchemy takes case of the DB specifics
433
- '''
434
- flavor = 'sqlite'
435
-
436
- def connect (self ):
437
- return sqlalchemy .create_engine ('sqlite:///:memory:' )
438
-
439
- def setUp (self ):
440
- # Skip this test if SQLAlchemy not available
441
- if not SQLALCHEMY_INSTALLED :
442
- raise nose .SkipTest ('SQLAlchemy not installed' )
443
-
444
- self .conn = self .connect ()
445
- self .pandasSQL = sql .PandasSQLAlchemy (self .conn )
446
-
447
- self ._load_iris_data ()
448
- self ._load_raw_sql ()
449
-
450
- self ._load_test1_data ()
433
+ """
451
434
452
435
def test_read_sql (self ):
453
436
self ._read_sql_iris ()
@@ -513,32 +496,31 @@ def test_read_table_absent(self):
513
496
ValueError , sql .read_table , "this_doesnt_exist" , con = self .conn )
514
497
515
498
def test_default_type_convertion (self ):
516
- """ Test default type conversion"""
517
499
df = sql .read_table ("types_test_data" , self .conn )
518
- self .assertTrue (
519
- issubclass (df .FloatCol .dtype .type , np .floating ), "FloatCol loaded with incorrect type" )
520
- self .assertTrue (
521
- issubclass (df .IntCol .dtype .type , np .integer ), "IntCol loaded with incorrect type" )
522
- self .assertTrue (
523
- issubclass (df .BoolCol .dtype .type , np .integer ), "BoolCol loaded with incorrect type" )
500
+
501
+ self .assertTrue (issubclass (df .FloatCol .dtype .type , np .floating ),
502
+ "FloatCol loaded with incorrect type" )
503
+ self .assertTrue (issubclass (df .IntCol .dtype .type , np .integer ),
504
+ "IntCol loaded with incorrect type" )
505
+ self .assertTrue (issubclass (df .BoolCol .dtype .type , np .bool_ ),
506
+ "BoolCol loaded with incorrect type" )
524
507
525
508
# Int column with NA values stays as float
526
509
self .assertTrue (issubclass (df .IntColWithNull .dtype .type , np .floating ),
527
510
"IntColWithNull loaded with incorrect type" )
528
- # Non-native Bool column with NA values stays as float
529
- self .assertTrue (issubclass (df .BoolColWithNull .dtype .type , np .floating ),
511
+ # Bool column with NA values becomes object
512
+ self .assertTrue (issubclass (df .BoolColWithNull .dtype .type , np .object ),
530
513
"BoolColWithNull loaded with incorrect type" )
531
514
532
515
def test_default_date_load (self ):
533
516
df = sql .read_table ("types_test_data" , self .conn )
534
517
535
518
# IMPORTANT - sqlite has no native date type, so shouldn't parse, but
536
519
# MySQL SHOULD be converted.
537
- self .assertFalse (
520
+ self .assertTrue (
538
521
issubclass (df .DateCol .dtype .type , np .datetime64 ), "DateCol loaded with incorrect type" )
539
522
540
523
def test_date_parsing (self ):
541
- """ Test date parsing """
542
524
# No Parsing
543
525
df = sql .read_table ("types_test_data" , self .conn )
544
526
@@ -573,6 +555,54 @@ def test_date_parsing(self):
573
555
"IntDateCol loaded with incorrect type" )
574
556
575
557
558
+ class TestSQLAlchemy (_TestSQLAlchemy ):
559
+ """
560
+ Test the sqlalchemy backend against an in-memory sqlite database.
561
+ """
562
+ flavor = 'sqlite'
563
+
564
+ def connect (self ):
565
+ return sqlalchemy .create_engine ('sqlite:///:memory:' )
566
+
567
+ def setUp (self ):
568
+ # Skip this test if SQLAlchemy not available
569
+ if not SQLALCHEMY_INSTALLED :
570
+ raise nose .SkipTest ('SQLAlchemy not installed' )
571
+
572
+ self .conn = self .connect ()
573
+ self .pandasSQL = sql .PandasSQLAlchemy (self .conn )
574
+
575
+ self ._load_iris_data ()
576
+ self ._load_raw_sql ()
577
+
578
+ self ._load_test1_data ()
579
+
580
+ def test_default_type_convertion (self ):
581
+ df = sql .read_table ("types_test_data" , self .conn )
582
+
583
+ self .assertTrue (issubclass (df .FloatCol .dtype .type , np .floating ),
584
+ "FloatCol loaded with incorrect type" )
585
+ self .assertTrue (issubclass (df .IntCol .dtype .type , np .integer ),
586
+ "IntCol loaded with incorrect type" )
587
+ # sqlite has no boolean type, so integer type is returned
588
+ self .assertTrue (issubclass (df .BoolCol .dtype .type , np .integer ),
589
+ "BoolCol loaded with incorrect type" )
590
+
591
+ # Int column with NA values stays as float
592
+ self .assertTrue (issubclass (df .IntColWithNull .dtype .type , np .floating ),
593
+ "IntColWithNull loaded with incorrect type" )
594
+ # Non-native Bool column with NA values stays as float
595
+ self .assertTrue (issubclass (df .BoolColWithNull .dtype .type , np .floating ),
596
+ "BoolColWithNull loaded with incorrect type" )
597
+
598
+ def test_default_date_load (self ):
599
+ df = sql .read_table ("types_test_data" , self .conn )
600
+
601
+ # IMPORTANT - sqlite has no native date type, so shouldn't parse, but
602
+ self .assertFalse (issubclass (df .DateCol .dtype .type , np .datetime64 ),
603
+ "DateCol loaded with incorrect type" )
604
+
605
+
576
606
# --- Test SQLITE fallback
577
607
class TestSQLite (PandasSQLTest ):
578
608
@@ -682,7 +712,7 @@ def tearDown(self):
682
712
self .conn .close ()
683
713
684
714
685
- class TestMySQLAlchemy (TestSQLAlchemy ):
715
+ class TestMySQLAlchemy (_TestSQLAlchemy ):
686
716
flavor = 'mysql'
687
717
688
718
def connect (self ):
@@ -713,16 +743,8 @@ def tearDown(self):
713
743
for table in c .fetchall ():
714
744
self .conn .execute ('DROP TABLE %s' % table [0 ])
715
745
716
- def test_default_date_load (self ):
717
- df = sql .read_table ("types_test_data" , self .conn )
718
-
719
- # IMPORTANT - sqlite has no native date type, so shouldn't parse,
720
- # but MySQL SHOULD be converted.
721
- self .assertTrue (
722
- issubclass (df .DateCol .dtype .type , np .datetime64 ), "DateCol loaded with incorrect type" )
723
746
724
-
725
- class TestPostgreSQLAlchemy (TestSQLAlchemy ):
747
+ class TestPostgreSQLAlchemy (_TestSQLAlchemy ):
726
748
flavor = 'postgresql'
727
749
728
750
def connect (self ):
@@ -754,14 +776,6 @@ def tearDown(self):
754
776
" WHERE table_schema = 'public'" )
755
777
for table in c .fetchall ():
756
778
self .conn .execute ("DROP TABLE %s" % table [0 ])
757
-
758
- def test_default_date_load (self ):
759
- df = sql .read_table ("types_test_data" , self .conn )
760
-
761
- # IMPORTANT - sqlite has no native date type, so shouldn't parse,
762
- # but PostgreSQL SHOULD be converted.
763
- self .assertTrue (issubclass (df .DateCol .dtype .type , np .datetime64 ),
764
- "DateCol loaded with incorrect type" )
765
779
766
780
if __name__ == '__main__' :
767
781
nose .runmodule (argv = [__file__ , '-vvs' , '-x' , '--pdb' , '--pdb-failure' ],
0 commit comments