Issue: DB errors are sometimes obscured
Author: MichaelBlume
State: closed
Created: 2013-12-20 21:42:14

when I connect to a DB with bad credentials, select a list of items, and then do a map on that list, the fact that the connection failed doesn't surface until I perform the map, and Python obscures the connection error by just telling me 

TypeError: argument 2 to map() must support iteration'


Can you provide more information?  How can I replicate this?


Here are some examples:

``` python
In [1]: from peewee import *

In [2]: db = PostgresqlDatabase('doesnotexist')

In [3]: db.connect()
OperationalError: FATAL:  database "doesnotexist" does not exist

In [4]: db = PostgresqlDatabase('peewee_test', user='invalid_user')

In [5]: db.connect()
OperationalError: FATAL:  role "invalid_user" does not exist
```


```
Python 2.7.3 (default, Aug  1 2012, 05:14:39) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from peewee import *
>>> 
>>> db = SqliteDatabase('people.db')
>>> 
>>> class Person(Model):
...     name = CharField()
...     birthday = DateField()
...     is_relative = BooleanField()
...     class Meta:
...         database = db
... 
>>> def identity(x):
...   return x
... 
>>> persons_named_bob = Person.select().where(Person.name == "Bob")
>>> map(identity, persons_named_bob)
No handlers could be found for logger "peewee"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument 2 to map() must support iteration
```


Gotcha, thank you for the example.  So there's an error which isn't caught until the query is evaluated.

See the note in the docs: http://peewee.readthedocs.org/en/latest/peewee/cookbook.html#creating-a-database-connection-and-tables

> While it is not necessary to explicitly connect to the database before using it, managing connections explicitly is a good practice. This way if the connection fails, the exception can be caught during the “connect” step, rather than some arbitrary time later when a query is executed.

So putting `db.connect()` before your call to `map` will catch an error creating the connection.


As for `map` swallowing exceptions, that does not appear to be a problem with peewee specifically:

``` python
In [15]: map(identity, None)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-7e3da6cfa2ca> in <module>()
----> 1 map(identity, None)

TypeError: argument 2 to map() must support iteration

In [16]: map(identity, 1.0)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-16-df55ff2dd812> in <module>()
----> 1 map(identity, 1.0)

TypeError: argument 2 to map() must support iteration
```


Ah, I see the problem better now:

```
In [10]: class BadIter(object):
   ....:     def next(self):
   ....:         raise Exception()
   ....:     

In [13]: class BadIterable(object):
   ....:     def __iter__(self):
   ....:         return BadIter()
   ....:     

In [19]: def identity(x):
   ....:     return x
   ....: 

In [20]: map(identity, BadIterable())
---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-20-f77dd3200d2b> in <module>()
----> 1 map(identity, BadIterable())

<ipython-input-10-d95eda570961> in next(self)
      1 class BadIter(object):
      2     def next(self):
----> 3         raise Exception()
      4 

Exception: 

In [21]: class WorseIterable(object):
   ....:     def __iter__(self):
   ....:         raise Exception()
   ....:     

In [22]: map(identity, WorseIterable())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-22-1cbe60ec7e3b> in <module>()
----> 1 map(identity, WorseIterable())

TypeError: argument 2 to map() must support iteration
```

So an exception in `next()` will propagate, but an exception in `__iter__()` will be obscured _by python itself_. I'd just about call that a Python bug.


Looks like it's fixed in Python 3 though, so there's another reason for us all to migrate =)

Thanks!


Sure thing, thanks for the code -- I'm sure this will be useful if this crops up again!