Issue: CentOS 7 install issues
Author: dmlb2000
State: closed
Created: 2018-07-18 16:44:10

I'm trying to install peewee using pip on CentOS and version 3.6.1 is having issues on that platform.

Steps to reproduce:

```
docker run -it --rm centos:7 /bin/bash -l
yum -y install centos-release-scl
yum -y install rh-python36 rh-python36-python-devel rh-python36-python-pip sqlite-devel gcc glibc-devel sqlite tar gzip bzip2 zip
. /opt/rh/rh-python36/enable
pip install peewee
```

The docker bit is just to get a basic CentOS 7 environment with appropriate software installed.

Versions to consider

```
[root@08434b5d4c55 /]# python --version
Python 3.6.3
[root@08434b5d4c55 /]# pip --version
pip 9.0.1 from /opt/rh/rh-python36/root/usr/lib/python3.6/site-packages (python 3.6)
[root@08434b5d4c55 /]# rpm -q sqlite-devel
sqlite-devel-3.7.17-8.el7.x86_64
```

The bad install output

```
[root@08434b5d4c55 /]# pip install peewee
Collecting peewee
  Downloading https://files.pythonhosted.org/packages/49/a5/29e54aa8f42a5dfa715a4f26521c12dee1de26ef672d26164649b0b88a29/peewee-3.6.3.tar.gz (2.1MB)
    100% |################################| 2.1MB 926kB/s
Installing collected packages: peewee
  Running setup.py install for peewee ... error
    Complete output from command /opt/rh/rh-python36/root/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-owa4pi0i/peewee/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-t6p4axgv-record/install-record.txt --single-version-externally-managed --compile:
    running install
    running build
    running build_py
    creating build
    creating build/lib.linux-x86_64-3.6
    copying peewee.py -> build/lib.linux-x86_64-3.6
    copying pwiz.py -> build/lib.linux-x86_64-3.6
    creating build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/__init__.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/dataset.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/db_url.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/migrate.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/hybrid.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/flask_utils.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/sqliteq.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/sqlite_ext.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/test_utils.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/kv.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/sqlite_udf.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/postgres_ext.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/reflection.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/apsw_ext.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/fields.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/sqlcipher_ext.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/signals.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/shortcuts.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/pool.py -> build/lib.linux-x86_64-3.6/playhouse
    copying playhouse/mysql_ext.py -> build/lib.linux-x86_64-3.6/playhouse
    running build_ext
    building 'playhouse._speedups' extension
    creating build/temp.linux-x86_64-3.6
    creating build/temp.linux-x86_64-3.6/playhouse
    gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -I/opt/rh/rh-python36/root/usr/include -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/opt/rh/rh-python36/root/usr/include/python3.6m -c playhouse/_speedups.c -o build/temp.linux-x86_64-3.6/playhouse/_speedups.o
    gcc -pthread -shared -L/opt/rh/rh-python36/root/usr/lib64-Wl,-z,relro -Wl,-rpath,/opt/rh/rh-python36/root/usr/lib64 -Wl,--enable-new-dtags build/temp.linux-x86_64-3.6/playhouse/_speedups.o -L/opt/rh/rh-python36/root/usr/lib64 -lpython3.6m -o build/lib.linux-x86_64-3.6/playhouse/_speedups.cpython-36m-x86_64-linux-gnu.so
    building 'playhouse._sqlite_udf' extension
    gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -I/opt/rh/rh-python36/root/usr/include -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/opt/rh/rh-python36/root/usr/include/python3.6m -c playhouse/_sqlite_udf.c -o build/temp.linux-x86_64-3.6/playhouse/_sqlite_udf.o
    gcc -pthread -shared -L/opt/rh/rh-python36/root/usr/lib64-Wl,-z,relro -Wl,-rpath,/opt/rh/rh-python36/root/usr/lib64 -Wl,--enable-new-dtags build/temp.linux-x86_64-3.6/playhouse/_sqlite_udf.o -L/opt/rh/rh-python36/root/usr/lib64 -lpython3.6m -o build/lib.linux-x86_64-3.6/playhouse/_sqlite_udf.cpython-36m-x86_64-linux-gnu.so
    building 'playhouse._sqlite_ext' extension
    gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -I/opt/rh/rh-python36/root/usr/include -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/opt/rh/rh-python36/root/usr/include/python3.6m -c playhouse/_sqlite_ext.c -o build/temp.linux-x86_64-3.6/playhouse/_sqlite_ext.o
    playhouse/_sqlite_ext.c: In function '__pyx_f_9playhouse_11_sqlite_ext_pwBestIndex':
    playhouse/_sqlite_ext.c:5015:25: warning: assignment from incompatible pointer type [enabled by default]
         __pyx_v_pConstraint = (&(__pyx_v_pIdxInfo->aConstraint[__pyx_v_i]));
                             ^
    playhouse/_sqlite_ext.c:5178:23: error: 'sqlite3_index_info' has no member named 'estimatedRows'
           __pyx_v_pIdxInfo->estimatedRows = 10;
                           ^
    playhouse/_sqlite_ext.c:5207:23: error: 'sqlite3_index_info' has no member named 'estimatedRows'
           __pyx_v_pIdxInfo->estimatedRows = __Pyx_pow_long(10, ((long)(__pyx_v_nParams - __pyx_v_nArg)));
                           ^
    playhouse/_sqlite_ext.c:5318:21: error: 'sqlite3_index_info' has no member named 'estimatedRows'
         __pyx_v_pIdxInfo->estimatedRows = 0x186A0;
                         ^
    playhouse/_sqlite_ext.c: In function '__pyx_f_9playhouse_11_sqlite_ext_18_TableFunctionImpl_create_module':
    playhouse/_sqlite_ext.c:5519:33: warning: assignment from incompatible pointer type [enabled by default]
       __pyx_v_self->module.xConnect = __pyx_f_9playhouse_11_sqlite_ext_pwConnect;
                                     ^
    playhouse/_sqlite_ext.c: In function '__pyx_pf_9playhouse_11_sqlite_ext_16ConnectionHelper_8set_update_hook':
    playhouse/_sqlite_ext.c:16566:5: warning: passing argument 2 of 'sqlite3_update_hook' from incompatible pointer type [enabled by default]
         sqlite3_update_hook(__pyx_v_self->conn->db, __pyx_f_9playhouse_11_sqlite_ext__update_callback, ((void *)__pyx_v_fn));
         ^
    In file included from playhouse/_sqlite_ext.c:531:0:
    /usr/include/sqlite3.h:4826:18: note: expected 'void (*)(void *, int,  const char *, const char *, sqlite3_int64)' but argument is of type 'void (*)(void *, int,  char *, char *, sqlite3_int64)'
     SQLITE_API void *sqlite3_update_hook(
                      ^
    playhouse/_sqlite_ext.c: In function '__pyx_pf_9playhouse_11_sqlite_ext_16ConnectionHelper_10set_busy_handler':
    playhouse/_sqlite_ext.c:16678:108: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
       sqlite3_busy_handler(__pyx_v_self->conn->db, __pyx_f_9playhouse_11_sqlite_ext__aggressive_busy_handler, ((void *)__pyx_v_n));
                                                                                                                ^
    playhouse/_sqlite_ext.c: In function '__pyx_f_9playhouse_11_sqlite_ext__aggressive_busy_handler':
    playhouse/_sqlite_ext.c:18608:26: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
       __pyx_v_busyTimeout = ((int)__pyx_v_ptr);
                              ^
    playhouse/_sqlite_ext.c: At top level:
    playhouse/_sqlite_ext.c:6501:18: warning: '__pyx_f_9playhouse_11_sqlite_ext_validate_and_format_datetime' defined but not used [-Wunused-function]
     static PyObject *__pyx_f_9playhouse_11_sqlite_ext_validate_and_format_datetime(PyObject *__pyx_v_lookup, PyObject *__pyx_v_date_str) {
                      ^
    error: command 'gcc' failed with exit status 1

    ----------------------------------------
Command "/opt/rh/rh-python36/root/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-owa4pi0i/peewee/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-t6p4axgv-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-owa4pi0i/peewee/
You are using pip version 9.0.1, however version 10.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.
```


The `estimatedRows` struct field was added in SQLite 3.8.2. Apparently CentOS 7 ships with some old-as-fuck SQLite and that's causing the problem.

I know lots of folks like to ship an embedded sqlite with the software? maybe that's an option?

Unfortunately, Peewee's SQLite C extension utilizes the `estimatedRows` struct field to try and provide hints to the query planner in the virtual table `TableFunction` implementation, so it cannot simply be omitted from the struct definition.

I think your options are:

* Use a newer SQLite3
* Do not compile the SQLite C extensions (`export NO_SQLITE=1` should do the trick).

> I know lots of folks like to ship an embedded sqlite with the software

That's not an attractive option for a project like this. You are welcome to create a separate package which includes a SQLite3 along with Peewee, of course.