Merge pull request #248 from pganssle/tzlocal-improvements

Add ambiguous time support to tzlocal()
diff --git a/dateutil/parser.py b/dateutil/parser.py
index 6738791..147b3f2 100644
--- a/dateutil/parser.py
+++ b/dateutil/parser.py
@@ -56,6 +56,10 @@
         if isinstance(instream, text_type):
             instream = StringIO(instream)
 
+        if getattr(instream, 'read', None) is None:
+            raise TypeError('Parser must be a string or character stream, not '
+                            '{itype}'.format(itype=instream.__class__.__name__))
+
         self.instream = instream
         self.charstack = []
         self.tokenstack = []
diff --git a/dateutil/test/test_parser.py b/dateutil/test/test_parser.py
index 20a4e78..1115bbf 100644
--- a/dateutil/test/test_parser.py
+++ b/dateutil/test/test_parser.py
@@ -7,7 +7,9 @@
 from dateutil.tz import tzoffset
 from dateutil.parser import *
 
+import six
 from six import assertRaisesRegex, PY3
+from six.moves import StringIO
 
 class ParserTest(unittest.TestCase):
 
@@ -30,6 +32,74 @@
         with self.assertRaises(ValueError):
             parse('')
 
+    def testNone(self):
+        with self.assertRaises(TypeError):
+            parse(None)
+
+    def testInvalidType(self):
+        with self.assertRaises(TypeError):
+            parse(13)
+
+    def testDuckTyping(self):
+        # We want to support arbitrary classes that implement the stream
+        # interface.
+
+        class StringPassThrough(object):
+            def __init__(self, stream):
+                self.stream = stream
+
+            def read(self, *args, **kwargs):
+                return self.stream.read(*args, **kwargs)
+
+
+        dstr = StringPassThrough(StringIO('2014 January 19'))
+
+        self.assertEqual(parse(dstr), datetime(2014, 1, 19))
+
+    def testParseStream(self):
+        dstr = StringIO('2014 January 19')
+
+        self.assertEqual(parse(dstr), datetime(2014, 1, 19))
+
+    def testParseStr(self):
+        self.assertEqual(parse(self.str_str),
+                         parse(self.uni_str))
+
+    def testParserParseStr(self):
+        from dateutil.parser import parser
+
+        self.assertEqual(parser().parse(self.str_str),
+                         parser().parse(self.uni_str))
+
+    def testParseUnicodeWords(self):
+
+        class rus_parserinfo(parserinfo):
+            MONTHS = [("янв", "Январь"),
+                      ("фев", "Февраль"),
+                      ("мар", "Март"),
+                      ("апр", "Апрель"),
+                      ("май", "Май"),
+                      ("июн", "Июнь"),
+                      ("июл", "Июль"),
+                      ("авг", "Август"),
+                      ("сен", "Сентябрь"),
+                      ("окт", "Октябрь"),
+                      ("ноя", "Ноябрь"),
+                      ("дек", "Декабрь")]
+
+        self.assertEqual(parse('10 Сентябрь 2015 10:20',
+                               parserinfo=rus_parserinfo()),
+                         datetime(2015, 9, 10, 10, 20))
+
+    def testParseWithNulls(self):
+        # This relies on the from __future__ import unicode_literals, because
+        # explicitly specifying a unicode literal is a syntax error in Py 3.2
+        # May want to switch to u'...' if we ever drop Python 3.2 support.
+        pstring = '\x00\x00August 29, 1924'
+
+        self.assertEqual(parse(pstring),
+                         datetime(1924, 8, 29))
+
     def testDateCommandFormat(self):
         self.assertEqual(parse("Thu Sep 25 10:36:28 BRST 2003",
                                tzinfos=self.tzinfos),
@@ -738,45 +808,6 @@
         dt = myparser.parse("01/Foo/2007")
         self.assertEqual(dt, datetime(2007, 1, 1))
 
-    def testParseStr(self):
-        self.assertEqual(parse(self.str_str),
-                         parse(self.uni_str))
-
-    def testParserParseStr(self):
-        from dateutil.parser import parser
-
-        self.assertEqual(parser().parse(self.str_str),
-                         parser().parse(self.uni_str))
-
-    def testParseUnicodeWords(self):
-
-        class rus_parserinfo(parserinfo):
-            MONTHS = [("янв", "Январь"),
-                      ("фев", "Февраль"),
-                      ("мар", "Март"),
-                      ("апр", "Апрель"),
-                      ("май", "Май"),
-                      ("июн", "Июнь"),
-                      ("июл", "Июль"),
-                      ("авг", "Август"),
-                      ("сен", "Сентябрь"),
-                      ("окт", "Октябрь"),
-                      ("ноя", "Ноябрь"),
-                      ("дек", "Декабрь")]
-
-        self.assertEqual(parse('10 Сентябрь 2015 10:20',
-                               parserinfo=rus_parserinfo()),
-                         datetime(2015, 9, 10, 10, 20))
-
-    def testParseWithNulls(self):
-        # This relies on the from __future__ import unicode_literals, because
-        # explicitly specifying a unicode literal is a syntax error in Py 3.2
-        # May want to switch to u'...' if we ever drop Python 3.2 support.
-        pstring = '\x00\x00August 29, 1924'
-
-        self.assertEqual(parse(pstring),
-                         datetime(1924, 8, 29))
-
     def testNoYearFirstNoDayFirst(self):
         dtstr = '090107'