Issue: `peewee` for WebAssembly (JupyterLite + XEUS-Python + emscripten-forge)
Author: michaelweinold
State: closed
Created: 2023-04-24 18:06:14

## Overview

To bring the [Brightway life-cycle assessment python package](https://documentation.brightway.dev/) to the browser, [we](https://github.com/brightway-lca) recently added `peewee` to the WebAssembly [`emscripten-forge`](https://github.com/emscripten-forge/recipes) package repository. This was necessary since `peewee` comes with C extensions (more specifically, it is using [`psycopg2cffi`](https://github.com/coleifer/peewee/blob/c825a0fb11b1dae1f88d93c67f2fbcb4a34d4ad4/peewee.py#L43)).

`emscripten-forge` is an alternative to the monolythic [Pyodide](https://pyodide.org/en/stable/index.html) Python WebAssembly distribution that is best described [in this article by the core development team.](https://blog.jupyter.org/mamba-meets-jupyterlite-88ef49ac4dc8)

## Error

Unfortunately, I get an error when running it in a [JupyterLite](https://jupyterlite.readthedocs.io/en/latest/) XEUX-Python hub. While this is likely out-of-scope for the developers of `peewee`, I would be very grateful for any hints on the potential root cause. It might be realated to [the filesystem of JupyterLite](https://jupyterlite.readthedocs.io/en/latest/search.html?q=filesystem).

```
from peewee import *

# Define a database object
db = SqliteDatabase('my_database.db')

# Define a model class
class Person(Model):
    name = CharField()
    age = IntegerField()

    class Meta:
        database = db

# Create the table in the database
db.connect()
db.create_tables([Person])
person1 = Person(name='Alice', age=25)
person1.save()
```

returnes:

```
DatabaseError: database disk image is malformed
```

<details>
  <summary>Full Error Message</summary>

  ```
---------------------------------------------------------------------------
DatabaseError                             Traceback (most recent call last)
/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in execute_sql(self, sql, params, commit)
   3235             cursor = self.cursor()
-> 3236             cursor.execute(sql, params or ())
   3237         return cursor

DatabaseError: database disk image is malformed

During handling of the above exception, another exception occurred:

DatabaseError                             Traceback (most recent call last)
/tmp/xpython_42/2390659374.py in <cell line: 2>()
      1 person1 = Person(name='Alice', age=25)
----> 2 person1.save()

/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in save(self, force_insert, only)
   6745             rows = self.update(**field_dict).where(self._pk_expr()).execute()
   6746         elif pk_field is not None:
-> 6747             pk = self.insert(**field_dict).execute()
   6748             if pk is not None and (self._meta.auto_increment or
   6749                                    pk_value is None):

/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in inner(self, database, *args, **kwargs)
   1960             raise InterfaceError('Query must be bound to a database in order '
   1961                                  'to call "%s".' % method.__name__)
-> 1962         return method(self, database, *args, **kwargs)
   1963     return inner
   1964 

/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in execute(self, database)
   2031     @database_required
   2032     def execute(self, database):
-> 2033         return self._execute(database)
   2034 
   2035     def _execute(self, database):

/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in _execute(self, database)
   2836             self._returning = (self.table._primary_key,)
   2837         try:
-> 2838             return super(Insert, self)._execute(database)
   2839         except self.DefaultValuesException:
   2840             pass

/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in _execute(self, database)
   2549             cursor = self.execute_returning(database)
   2550         else:
-> 2551             cursor = database.execute(self)
   2552         return self.handle_result(database, cursor)
   2553 

/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in execute(self, query, commit, **context_options)
   3242         ctx = self.get_sql_context(**context_options)
   3243         sql, params = ctx.sql(query).query()
-> 3244         return self.execute_sql(sql, params)
   3245 
   3246     def get_context_options(self):

/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in execute_sql(self, sql, params, commit)
   3232             __deprecated__('"commit" has been deprecated and is a no-op.')
   3233         logger.debug((sql, params))
-> 3234         with __exception_wrapper__:
   3235             cursor = self.cursor()
   3236             cursor.execute(sql, params or ())

/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in __exit__(self, exc_type, exc_value, traceback)
   3008             new_type = self.exceptions[exc_type.__name__]
   3009             exc_args = exc_value.args
-> 3010             reraise(new_type, new_type(exc_value, *exc_args), traceback)
   3011 
   3012 

/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in reraise(tp, value, tb)
    190     def reraise(tp, value, tb=None):
    191         if value.__traceback__ is not tb:
--> 192             raise value.with_traceback(tb)
    193         raise value
    194 

/tmp/xeus-python-kernel/envs/xeus-python-kernel/lib/python3.10/site-packages/peewee.py in execute_sql(self, sql, params, commit)
   3234         with __exception_wrapper__:
   3235             cursor = self.cursor()
-> 3236             cursor.execute(sql, params or ())
   3237         return cursor
   3238 

DatabaseError: database disk image is malformed
  ```
</details>

## Reproduce Error

Access the JupyterLite Hub and open `peewee_test.ipynb` at https://michaelweinold.github.io/hub/

## Related

- https://github.com/emscripten-forge/recipes/issues/295
- https://github.com/emscripten-forge/recipes/pull/322

1. peewee does not necessarily require c extensions
2. psycopg2cffi is only needed if you want to use postgres and is primarily aimed at pypy users who don't have c extensions, so I'm completely at a loss why this particular bit seemed so important to you.
3. the error is not coming from peewee but seems related to however you're abstracting the file-system for use by sqlite. The error is coming from sqlite and seems to indicate some problem with the file.