akumoth/peewee-issues huggingface dataset:
Issue: Cannot prefetch on MySQL when using limit
Author: Webovani
State: closed
Created: 2018-02-12 16:22:26

```python
from peewee import *

database = MySQLDatabase(...)

class BaseModel(Model):
    class Meta:
        database = database

class Shop(BaseModel):
    name = CharField()

class Branch(BaseModel):
    shop = ForeignKeyField(Shop, backref='branches')

shops = Shop.select().limit(10)
shops = prefetch(shops, Branch)
```

This will fail with error:
`peewee.NotSupportedError: (1235, "This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'")`

It doesn't seem to be supported even on MySQL 8. 

This could be solved by using JOIN on subquery, but I don't see how to do that in a reasonable way.

The way prefetch is implemented, it does not use joins. Instead, it nests dependent clauses in subqueries. So your example would:

```sql
-- Get branches corresponding to shops in the outer query.
SELECT "t1"."id", "t1"."shop_id" 
FROM "branch" AS "t1" 
WHERE ("t1"."shop_id" IN (SELECT "t2"."id" FROM "shop" AS "t2" LIMIT 10));

-- Get the shops themselves.
SELECT "t1"."id", "t1"."name" FROM "shop" AS "t1" LIMIT 10;
```

It should be possible to write it instead as:

```sql
SELECT "t1"."id", "t1"."shop_id"
FROM "branch" AS "t1"
INNER JOIN "shop" AS "t2" ON ("t1"."shop_id" = "t2"."id")
-- but what do we do with the limit?
-- if there were tons of branches we could end up reading way more data than we need
-- given the LIMIT on the outer query.
```

So instead, maybe something like:

```sql
SELECT "t1"."id", "t1"."shop_id"
FROM "branch" AS "t1"
INNER JOIN (SELECT "t2"."id" FROM "shop" AS "t2" LIMIT 10) as subq ON (subq.id = t1.shop_id)
```

But I'm thinking if MySQL doesn't support the first form, it probably doesn't support this form either?

```sql
SELECT "t1"."id", "t1"."shop_id"
FROM "branch" AS "t1"
INNER JOIN (SELECT "t2"."id" FROM "shop" AS "t2" LIMIT 10) as subq ON (subq.id = t1.shop_id)
```

This form IS supported and works as expected. 

It is equivalent to the `IN subq`, but sadly MySQL query planner is really lame and doesn't get it... Just MySQL things.
Issue: Cannot connect using postgres.
Author: mtairu
State: closed
Created: 2018-02-12 00:48:43

Cannot connect using postgres.

```
db = PostgresqlDatabase('extra', user='extra',
                                          password='GBQ9x%@S', host='localhost')

def connect():
    try:
        db._connect()
    except BaseException as e:
        return e
connect()
```

_AttributeError("'NoneType' object has no attribute 'connect'")_



Install psycopg2 yo.

Thanks bro.
Issue: NoneType object has no attribute 'connect' while connecting to MySQL server
Author: eliaperantoni
State: closed
Created: 2018-02-11 00:19:39

I've created a MySQL server on my server but whenever I try to connect to it in PeeWee I get this error:

```
>>> from peewee import *
>>> db = MySQLDatabase('tormecapp', user='tormecapp', password='************')
>>> db.connect()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/eliap/.local/lib/python3.5/site-packages/peewee.py", line 2434, in connect
    self._state.set_connection(self._connect())
  File "/home/eliap/.local/lib/python3.5/site-packages/peewee.py", line 3108, in _connect
    return mysql.connect(db=self.database, **self.connect_params)
AttributeError: 'NoneType' object has no attribute 'connect'
```

I'm doing this on the same machine as the MySQL server
This works:
`mysql -u tormecapp -p tormecapp`
so why doesn't peewee as well?

You need to install a MySQL python driver like pymysql.

    pip install pymysql

It worked! Thanks :grinning:
Issue: [Feature Request] Support Signals in `insert`/`update`/`delete` in Postgres using `returning`
Author: logannc
State: closed
Created: 2018-02-09 19:49:08

It would appear that Postgres can support signals using `returning`.

It should be able to easily support `post_*` signals using returning. The performance penalty should be worth the consistency in `update` vs. `save`.

Supporting `pre_*` signals would be a bit painful as you'd need to execute the save/insert using returning in an atomic block, reverting it before the block ends, fire the `pre_*` signal, replay the query, and then finally fire the `post_*` signal. The performance penalty here has the potential to be severe.

Thoughts? Would a PR be welcomed?

I'm unsure that this can be done cleanly and correctly, so I'm not inclined to implement or merge an implementation.

Briefly, what are your concerns?

Where would you install the signal hooks? What would they do? How would you make them work on SQLite and MySQL, which do not have `returning` clause support?

They can be installed the same way they are now. They could function the same way, by mapping the signal handler over the iterable or providing a hook for passing the collection. 

They wouldn't work on SQLite or MySQL, just like `returning` doesn't work on them.

Going to close this as I'm not interested in the feature, but feel free to implement it in a third-party module.
Issue: Can't change schema via `Model._meta.schema` (regression from 2.X)
Author: vikt0rs
State: closed
Created: 2018-02-08 15:34:56

I'm working to work with several DB schemas and use `Model._meta.schema` to switch them, as shown in attached script. But for some reasons schema switch doesn't work in peewee 3.X. See console output. Please, suggest is it a bug or there is a better way to do it.

Thanks!

Console output

```
$ pip freeze | grep peewee
peewee==2.10.2
peewee-async==0.5.10
$ python test_schema_change.py
('SELECT "t1"."document_uuid", "t1"."name" FROM "user_1"."documents_metadata" AS t1 WHERE ("t1"."name" = %s)', ['test'])
('SELECT "t1"."document_uuid", "t1"."name" FROM "user_2"."documents_metadata" AS t1 WHERE ("t1"."name" = %s)', ['test'])
$ pip install peewee==3.0.15
Collecting peewee==3.0.15
Installing collected packages: peewee
  Found existing installation: peewee 2.10.2
    Uninstalling peewee-2.10.2:
      Successfully uninstalled peewee-2.10.2
Successfully installed peewee-3.0.15
$ python test_schema_change.py
('SELECT "t1"."document_uuid", "t1"."name" FROM "user_1"."documents_metadata" AS "t1" WHERE ("t1"."name" = %s)', ['test'])
('SELECT "t1"."document_uuid", "t1"."name" FROM "user_1"."documents_metadata" AS "t1" WHERE ("t1"."name" = %s)', ['test'])
```

Executed script

```
from contextlib import contextmanager
import peewee

DB = peewee.PostgresqlDatabase(
    "my_documents",
    user="username", password="top_secret"
)

class DocumentsModel(peewee.Model):

    uuid = peewee.UUIDField(primary_key=True, db_column="document_uuid")
    name = peewee.CharField(256)

    class Meta:
        db_table = "documents_metadata"
        database = DB


@contextmanager
def context(schema_name):
    with DB.atomic() as transaction:
        DocumentsModel._meta.schema = schema_name
        yield transaction
        DocumentsModel._meta.schema = None


with context('user_1'):
    print(DocumentsModel.filter(name="test").sql())

with context('user_2'):
    print(DocumentsModel.filter(name="test").sql())
```

For now, can you try this change for 3.x?

```python
@contextmanager
def context(schema_name):
    with DB.atomic() as transaction:
        del DocumentsModel._meta.table  # Don't worry, this won't delete any data.
        DocumentsModel._meta.schema = schema_name
        yield transaction
        DocumentsModel._meta.schema = None
```

yes, this works for peewee==3.0.15 and fails on 2.X, thanks for suggestion

Pushed 3.0.16, which contains fix for this issue.

Thanks!
Issue: Pragmas gets unset on init
Author: codito
State: closed
Created: 2018-02-08 02:05:09

This scenario uses runtime database configuration. The `pragmas` configuration is reset to empty upon doing a `SqliteDatabase.init(name)`. It's happening since `init` now takes `pragmas` as an input argument which defaults to `None`. It's a behavior change from peewee 2. Is it by design?

### Peewee 3.0.13
```python
Python 3.6.4 (default, Jan  5 2018, 02:35:40)                                                                                                                  
[GCC 7.2.1 20171224] on linux                                                                                                                                  
Type "help", "copyright", "credits" or "license" for more information.
>>> from peewee import SqliteDatabase                                                                                                                          
>>> db = SqliteDatabase(None, pragmas=(('foreign_keys', 'on'),))                                                                                                    
>>> print(db._pragmas)                                                                                                                                         
(('foreign_keys', 'on'),)                                                                                                                                      
>>> db.init(':memory:')                                                                                                                                        
>>> print(db._pragmas)                                                                                                                                         
()                                                                                                                                                             
```

### Peewee 2.10.2
```python
Python 3.6.4 (default, Jan  5 2018, 02:35:40)                                                                                                                  
[GCC 7.2.1 20171224] on linux                                                                                                                                  
Type "help", "copyright", "credits" or "license" for more information.
>>> from peewee import SqliteDatabase      
>>> db = SqliteDatabase(None, pragmas=(('foreign_keys', 'on'),))
>>> print(db._pragmas)
(('foreign_keys', 'on'),)
>>> db.init(':memory:')
>>> print(db._pragmas)
(('foreign_keys', 'on'),)
>>> 
```

Thanks for reporting.

Fixed, pushed new version to PyPI - 3.0.15. Thanks again for letting me know.

Thanks a ton! Confirmed the issue is fixed with 3.0.15.
Issue: Can't create model instance without primary key
Author: aachurin
State: closed
Created: 2018-02-07 19:09:55

```python
class Model1(TestModel):
            test1 = CharField(max_length=10)
            class Meta:
                primary_key = False

Model1.create(test1='1')  # fails.
```

```
Traceback (most recent call last):
  File "tests.py", line 412, in test_add_primary_key
    Model1.create(test1='1')
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 5049, in create
    inst.save(force_insert=True)
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 5165, in save
    self.insert(**field_dict).execute()
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 1447, in inner
    return method(self, database, *args, **kwargs)
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 1518, in execute
    return self._execute(database)
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 2150, in _execute
    return super(Insert, self)._execute(database)
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 1929, in _execute
    return self.handle_result(database, cursor)
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 2153, in handle_result
    return database.last_insert_id(cursor, self._query_type)
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 2931, in last_insert_id
    return cursor if query_type else cursor[0][0]
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 3345, in __getitem__
    self.fill_cache(item if item > 0 else 0)
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 3390, in fill_cache
    iterator.next()
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 3446, in next
    self.cursor_wrapper.iterate()
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 3365, in iterate
    self.initialize()  # Lazy initialization.
  File "/Users/peewee_test/lib/python3.6/site-packages/peewee-3.0.11-py3.6.egg/peewee.py", line 5842, in _initialize_columns
    node = node.unwrap()
AttributeError: 'bool' object has no attribute 'unwrap'
```

Ewww, thank you.

thx

3.0.14 on PyPI.
Issue: Alternative for prepared()
Author: faisalraja
State: closed
Created: 2018-02-07 18:12:40

What should I be using for prepared on version 3? I noticed it's not available anymore and I didn't see it in backwards breaking changes docs. I use it to copy the _data now __data__ whenever prepared is called.

Thanks

There isn't really a comparable API anymore.

I was about to submit a new issue but found this one, which seems to be the same, so I'll post mine here: 

I had implemented a decently functional change-tracking system to my peewee v2 integration, which allows me to log/record any changes made to models that this feature is enabled for. In order to do this, I leveraged the `post_init` signal (though for reasons I can't remember, I basically merged the `playhouse.signals` code into my base model to call instance methods (e.g. `self._post_init()`) rather than signals).

I recently started migrating to peewee v3 and I found that this signal was removed, and I can't find a convenient way to replicate it. 

This signal is important because I use it to store the initial data of the model, by copying `self._data` (or `self.__data__` in v3) to a separate dict. Then when the model is saved, I compare these old/original values against the current `self._data`/`self.__data__` to determine the differences, generating any relevant "change history" records.

Would it be possible to restore this signal or similar functionality (e.g. `self.prepared()`)? Or do you have any suggestions on how I could build this out? This is the only thing holding me back from migrating to v3 (I'm a big fan of all the other changes/updates). 

Well, as I wrote, there isn't really a comparable API anymore. You should probably isolate the places in your codebase where changes can occur and do the tracking there. Implementing a service layer is one option.

Ok bummer. Definitely not a fan of separate service layers. I like having only one way to CRUD (e.g. [wicked domain models](https://vimeo.com/43598193)), which is why hooking into these signals made change tracking so easy/transparent. I will think of something...

I can't remember how exactly I did it since I left the company that I used it for. But the way I did it is I override __setattr__ (again not 100% sure I haven't used peewee & python in a while) with my BaseAuditModel that inherits ndb.Model. Then when a set happens, I check if __originalValue__ is None then copy __data__ to __originalValue__ then call parent set.

> I can't remember how exactly I did it since I left the company that I used it for. But the way I did it is I override **setattr** (again not 100% sure I haven't used peewee & python in a while) with my BaseAuditModel that inherits ndb.Model. Then when a set happens, I check if **originalValue** is None then copy **data** to **originalValue** then call parent set.

Ah that's a good approach. Thanks!
Issue: Feature: Type annotation
Author: cLupus
State: closed
Created: 2018-02-07 08:27:54

Hi,
Is there any plans of adding type annotation (hinting) to peewee?

@cLupus this would limit the versions of Python which peewee can run on ...
This should probably be added after 3.5 and 3.4 are EOL.

Does that include [snubs (mypy)](http://mypy.readthedocs.io/en/stable/basics.html#library-stubs-and-the-typeshed-repo) as well, @oz123 ?

I'm of the opinion that type annotation/hinting is absolutely un-pythonic and just adds noise to what would otherwise be very clean/readable code. Python's a dynamic language. If you want Python + types, there's other, statically-typed languages available...but I'm not interested in them.

Type annotations do not make the code statically typed, and they are absolutely not noise. For example they let me save hours every day at work by virtue of letting me check what to give to any parameter without leaving the editor instead of having to switch to the browser to read the documentation (because docstrings are sadly also missing), and type checkers have also spared me hours of debugging by letting me find mistakes well before they could become bugs. Type annotations help massively with auto-completion too.

The situation since 2018 has changed dramatically and annotations are a tried and true, useful tool at this point, and pretty much considered an expected luxury by active, popular libraries. I think Peewee's API is nice enough that it deserves to be (more) popular, and type annotations can be a deal maker for many.

On the topic of compatibility, there is the possibility of publishing type annotations through a separate package (e.g. `peewee-stubs`) by following [PEP 561](https://peps.python.org/pep-0561/), if for some reason placing them directly in the code isn't deemed feasible.

I propose reopening this issue and I'm willing to help with the implementation myself.
Issue: Broken backward compatibility: missing **playhouse.shortcuts.RetryOperationalError**
Author: nad2000
State: closed
Created: 2018-02-07 01:50:41

```
  File "/home/rcir178/NZ-ORCID-Hub/orcid_hub/__init__.py", line 28, in <module>
    from playhouse.shortcuts import RetryOperationalError
ImportError: cannot import name 'RetryOperationalError'
ERROR: could not load /home/rcir178/NZ-ORCID-Hub/tests/conftest.py
```

The documentation still refers to it: 

I don't see it in the documentation, it's been removed.

My old code run on peewee 3.1.5 raise ImportError: cannot import name RetryOperationalError
how to use RetryOperationalError on 3.1.5, the docs can't find anything about it

It was removed in 3.0.
Issue: slight change needed for flask-admin/contrib/peewee/forms.py
Author: jefmud
State: closed
Created: 2018-02-06 15:39:32

Charles-- Peewee is great; simple and expressive  (it was introduced to me by Kenneth Love).

I noticed this small issue with interoperability with flask-admin, see below.

Issue: (flask-admin) slight change needed for flask-admin/contrib/peewee/form.py

The latest version of peewee (3.0) no longer includes BaseModel.   So... this import should be changed for compatibility or simply substitute Model for BaseModel.

Do you agree?

```python
### original ####
from peewee import (CharField, DateTimeField, DateField, TimeField,
                    PrimaryKeyField, ForeignKeyField, BaseModel)
```
```python
### change to #####
from peewee import (CharField, DateTimeField, DateField, TimeField,
                    PrimaryKeyField, ForeignKeyField)

from peewee import Model as BaseModel
```

I'm not sure why `flask-admin` was importing `BaseModel`...it's changed in 3.0 to `ModelBase`. So the following should work:

```python
from peewee import (CharField, DateTimeField, DateField, TimeField,
                    PrimaryKeyField, ForeignKeyField)
try:
    from peewee import BaseModel
except ImportError:
    from peewee import ModelBase as BaseModel
```

`peewee.BaseModel` (and latterly `peewee.ModelBase`) is the metaclass that is used to create `Model` classes. It's an internal implementation thing, so I'm not sure why it's being imported by flask-admin.

They are checking something with "is_instance()" against the BaseModel

On Tue, Feb 6, 2018 at 10:56 AM, Charles Leifer <notifications@github.com>
wrote:

> peewee.BaseModel (and latterly peewee.ModelBase) is the metaclass that is
> used to create Model classes. It's an internal implementation thing, so
> I'm not sure why it's being imported by flask-admin.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/coleifer/peewee/issues/1475#issuecomment-363467201>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/ADyqBIioDqlqVzFdl_10Q4_EguxmbPiDks5tSHYjgaJpZM4R7QH4>
> .
>



-- 
Jeff Muday
Instructional Technology Analyst
Wake Forest University
1834 Wake Forest Rd.
Winston Hall Rm. 27
Winston Salem, NC 27106
mudayja @ wfu . edu
p 336.758.6171
f  336.758.6004
Issue: `instance.save()` returns zero.
Author: ShipraShalini
State: closed
Created: 2018-02-06 09:00:21

I am using `peewee` 3.0.8/3.0.13  and sqlite3 with [fabric](https://github.com/fabric/fabric/), to store build data.
My model is:
```Python
class AutoFloatField(AutoField):

    def db_value(self, value):
        return value * 10

    def python_value(self, value):
        return value/10

class Build(BaseModel):
    id = AutoFloatField()
    deployed_by = CharField(null=True)
    started_at = DateTimeField(default=datetime.utcnow)
    finished_at = DateTimeField(null=True)
    success = BooleanField(default=False)
```
First I create the instance with `deployed_by` and `started_at`, 
```Python
instance = Build.create(deployed_by='abc')
```
then I update it with `finished_at` and `success`:

```Python
    instance.success = True
    instance.finished_at = datetime.utcnow()
    instance.save()
```
`model_to_dict`  and `instance.dirty_fields` just before `.save()` returns:
```
{
	'deployed_by': 'abc',
	'finished_at': datetime.datetime(2018, 2, 6, 8, 47, 29, 313833),
	'id': 10,
	'started_at': datetime.datetime(2018, 2, 6, 8, 47, 11, 633645),
	'success': True
}

[<peewee.DateTimeField object at 0x7f2d2e7dee10>, <peewee.BooleanField object at 0x7f2d2e7dedd0>]
```

But ` instance.save()` returns zero and the instance is not updated but `instance.dirty_fields` returns empty list.

` instance.save()` works fine in console.

Apologies. My mistake.
Changing `AutoFloatField` to the following fixed it.

```Python
class AutoFloatField(AutoField):

    def python_value(self, value):
        return value/10
```
But with `PostgresqlExtDatabase` both `python_value` and `db_value` are required. :/
Issue: alias() not reflected in get()
Author: rw102
State: closed
Created: 2018-02-06 01:18:53

`Table.select(Table.column.alias('alias')).where(Table.id == 1).dicts().get()`
Until 3.0.2 this correctly returns :
`{'alias' : value}`
From 3.0.3 onwards, it returns :
`{'column': value}`

The same also happens when returning objects. 

Wrote a failing test, will work up a fix.

Pushed a new release 3.0.13.