Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-peewee for openSUSE:Factory checked in at 2023-08-22 08:56:17 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-peewee (Old) and /work/SRC/openSUSE:Factory/.python-peewee.new.1766 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-peewee" Tue Aug 22 08:56:17 2023 rev:23 rq:1105035 version:3.16.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-peewee/python-peewee.changes 2023-08-14 22:35:39.064374682 +0200 +++ /work/SRC/openSUSE:Factory/.python-peewee.new.1766/python-peewee.changes 2023-08-22 08:56:21.990583896 +0200 @@ -1,0 +2,14 @@ +Wed Aug 16 14:40:36 UTC 2023 - ecsos <ec...@opensuse.org> + +- Update to 3.16.3 + - Support for Cython 3.0. + - Add flag to ManyToManyField to prevent setting/getting values + on unsaved instances. This is worthwhile, since reading or + writing a many-to-many has no meaning when the instance is unsaved. + - Adds a star() helper to Source base-class for selecting all columns. + - Fix missing binary types for mysql-connector and mariadb-connector. + - Add extract() method to MySQL JSONField for extracting a jsonpath. +- Add %{?sle15_python_module_pythons} +- unbind to cython < 3 + +------------------------------------------------------------------- Old: ---- peewee-3.16.2.tar.gz New: ---- peewee-3.16.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-peewee.spec ++++++ --- /var/tmp/diff_new_pack.ZcGVpL/_old 2023-08-22 08:56:23.646587042 +0200 +++ /var/tmp/diff_new_pack.ZcGVpL/_new 2023-08-22 08:56:23.654587057 +0200 @@ -16,15 +16,15 @@ # -%{?!python_module:%define python_module() python-%{**} python3-%{**}} +%{?sle15_python_module_pythons} Name: python-peewee -Version: 3.16.2 +Version: 3.16.3 Release: 0 Summary: An expressive ORM that supports multiple SQL backends License: BSD-3-Clause URL: https://github.com/coleifer/peewee Source: https://github.com/coleifer/peewee/archive/refs/tags/%{version}.tar.gz#/peewee-%{version}.tar.gz -BuildRequires: %{python_module Cython < 3.0.0} +BuildRequires: %{python_module Cython} BuildRequires: %{python_module Flask} BuildRequires: %{python_module PyMySQL} BuildRequires: %{python_module apsw} ++++++ peewee-3.16.2.tar.gz -> peewee-3.16.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/.github/workflows/tests.yaml new/peewee-3.16.3/.github/workflows/tests.yaml --- old/peewee-3.16.2/.github/workflows/tests.yaml 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/.github/workflows/tests.yaml 2023-08-14 16:15:01.000000000 +0200 @@ -24,7 +24,7 @@ strategy: fail-fast: false matrix: - python-version: [2.7, 3.7, 3.9, "3.10"] + python-version: [3.7, 3.9, "3.10"] peewee-backend: - "sqlite" - "postgresql" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/CHANGELOG.md new/peewee-3.16.3/CHANGELOG.md --- old/peewee-3.16.2/CHANGELOG.md 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/CHANGELOG.md 2023-08-14 16:15:01.000000000 +0200 @@ -168,7 +168,7 @@ UPDATE queries - see #2152. Additionally, this release adds better support for using the new `RETURNING` -syntax with Sqlite automatically. Specify `returing_clause=True` when +syntax with Sqlite automatically. Specify `returning_clause=True` when initializing your `SqliteDatabase` and all bulk inserts will automatically specify a `RETURNING` clause, returning the newly-inserted primary keys. This functionality requires Sqlite 3.35 or newer. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/docs/peewee/database.rst new/peewee-3.16.3/docs/peewee/database.rst --- old/peewee-3.16.2/docs/peewee/database.rst 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/docs/peewee/database.rst 2023-08-14 16:15:01.000000000 +0200 @@ -1449,32 +1449,20 @@ FastAPI ^^^^^^^ -Similar to Flask, FastAPI provides two event based hooks which we will use to open and -close our db connection. We'll open the connection when a request is received, -then close it when the response is returned. - -.. code-block:: python - - from fastapi import FastAPI - from peewee import * - - db = SqliteDatabase('my_app.db') - app = FastAPI() - - # This hook ensures that a connection is opened to handle any queries - # generated by the request. - @app.on_event("startup") - def startup(): - db.connect() - - - # This hook ensures that the connection is closed when we've finished - # processing the request. - @app.on_event("shutdown") - def shutdown(): - if not db.is_closed(): - db.close() +FastAPI is an asyncio-compatible framework. Peewee relies on thread locals +(which are also compatible with gevent) to manage the connection state across +requests. For use with asyncio, some overrides are necessary to replace the +thread-local behavior with an asyncio-compatible context-local. +For a full treatment of using Peewee with FastAPI, consult the FastAPI +documentation here: + +https://fastapi.tiangolo.com/advanced/sql-databases-peewee/ + +The above document covers: + +* Adding asyncio context-aware connection state tracking +* Per-request connection handling Other frameworks ^^^^^^^^^^^^^^^^ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/docs/peewee/playhouse.rst new/peewee-3.16.3/docs/peewee/playhouse.rst --- old/peewee-3.16.2/docs/peewee/playhouse.rst 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/docs/peewee/playhouse.rst 2023-08-14 16:15:01.000000000 +0200 @@ -1646,6 +1646,12 @@ Extends :py:class:`TextField` and implements transparent JSON encoding and decoding in Python. + .. py:method:: extract(path) + + :param str path: a JSON path, e.g. ``$.key1`` + + Extract a value from a JSON document at the given path. + .. py:function:: Match(columns, expr[, modifier=None]) :param columns: a single :py:class:`Field` or a tuple of multiple fields. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/peewee.py new/peewee-3.16.3/peewee.py --- old/peewee-3.16.2/peewee.py 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/peewee.py 2023-08-14 16:15:01.000000000 +0200 @@ -70,7 +70,7 @@ mysql = None -__version__ = '3.16.2' +__version__ = '3.16.3' __all__ = [ 'AnyField', 'AsIs', @@ -717,6 +717,7 @@ class Node(object): _coerce = True + __isabstractmethod__ = False # Avoid issue w/abc and __getattr__, eg fn.X def clone(self): obj = self.__class__.__new__(self.__class__) @@ -794,6 +795,10 @@ columns = (SQL('*'),) return Select((self,), columns) + @property + def star(self): + return NodeList((QualifiedNames(self), SQL('.*')), glue='') + def join(self, dest, join_type=JOIN.INNER, on=None): return Join(self, dest, join_type, on) @@ -5037,6 +5042,12 @@ def __repr__(self): return repr(self._buffer) + if sys.version_info[0] < 3: + def __str__(self): + return bytes_type(self._buffer) + else: + def __bytes__(self): + return bytes_type(self._buffer) class BigBitFieldAccessor(FieldAccessor): @@ -5563,6 +5574,9 @@ return [getattr(obj, self.dest_fk.name) for obj in backref] src_id = getattr(instance, self.src_fk.rel_field.name) + if src_id is None and self.field._prevent_unsaved: + raise ValueError('Cannot get many-to-many "%s" for unsaved ' + 'instance "%s".' % (self.field, instance)) return (ManyToManyQuery(instance, self, self.rel_model) .join(self.through_model) .join(self.model) @@ -5571,6 +5585,10 @@ return self.field def __set__(self, instance, value): + src_id = getattr(instance, self.src_fk.rel_field.name) + if src_id is None and self.field._prevent_unsaved: + raise ValueError('Cannot set many-to-many "%s" for unsaved ' + 'instance "%s".' % (self.field, instance)) query = self.__get__(instance, force_query=True) query.add(value, clear_existing=True) @@ -5579,7 +5597,7 @@ accessor_class = ManyToManyFieldAccessor def __init__(self, model, backref=None, through_model=None, on_delete=None, - on_update=None, _is_backref=False): + on_update=None, prevent_unsaved=True, _is_backref=False): if through_model is not None: if not (isinstance(through_model, DeferredThroughModel) or is_model(through_model)): @@ -5593,6 +5611,7 @@ self._through_model = through_model self._on_delete = on_delete self._on_update = on_update + self._prevent_unsaved = prevent_unsaved self._is_backref = _is_backref def _get_descriptor(self): @@ -7944,8 +7963,8 @@ isinstance(subquery, ModelAlias): subquery = subquery.select() subquery_model = subquery.model - fks = backrefs = None for j in reversed(range(i + 1)): + fks = backrefs = None fixed = fixed_queries[j] last_query = fixed.query last_model = last_obj = fixed.model @@ -7961,7 +7980,7 @@ (target_model is None)): break - if not fks and not backrefs: + else: tgt_err = ' using %s' % target_model if target_model else '' raise AttributeError('Error: unable to find foreign key for ' 'query: %s%s' % (subquery, tgt_err)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/playhouse/_sqlite_ext.pyx new/peewee-3.16.3/playhouse/_sqlite_ext.pyx --- old/peewee-3.16.2/playhouse/_sqlite_ext.pyx 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/playhouse/_sqlite_ext.pyx 2023-08-14 16:15:01.000000000 +0200 @@ -386,7 +386,7 @@ # We define an xConnect function, but leave xCreate NULL so that the # table-function can be called eponymously. cdef int pwConnect(sqlite3 *db, void *pAux, int argc, const char *const*argv, - sqlite3_vtab **ppVtab, char **pzErr) with gil: + sqlite3_vtab **ppVtab, char **pzErr) noexcept with gil: cdef: int rc object table_func_cls = <object>pAux @@ -407,7 +407,7 @@ return rc -cdef int pwDisconnect(sqlite3_vtab *pBase) with gil: +cdef int pwDisconnect(sqlite3_vtab *pBase) noexcept with gil: cdef: peewee_vtab *pVtab = <peewee_vtab *>pBase object table_func_cls = <object>(pVtab.table_func_cls) @@ -419,7 +419,8 @@ # The xOpen method is used to initialize a cursor. In this method we # instantiate the TableFunction class and zero out a new cursor for iteration. -cdef int pwOpen(sqlite3_vtab *pBase, sqlite3_vtab_cursor **ppCursor) with gil: +cdef int pwOpen(sqlite3_vtab *pBase, sqlite3_vtab_cursor **ppCursor) \ + noexcept with gil: cdef: peewee_vtab *pVtab = <peewee_vtab *>pBase peewee_cursor *pCur = <peewee_cursor *>0 @@ -443,7 +444,7 @@ return SQLITE_OK -cdef int pwClose(sqlite3_vtab_cursor *pBase) with gil: +cdef int pwClose(sqlite3_vtab_cursor *pBase) noexcept with gil: cdef: peewee_cursor *pCur = <peewee_cursor *>pBase object table_func = <object>pCur.table_func @@ -454,7 +455,7 @@ # Iterate once, advancing the cursor's index and assigning the row data to the # `row_data` field on the peewee_cursor struct. -cdef int pwNext(sqlite3_vtab_cursor *pBase) with gil: +cdef int pwNext(sqlite3_vtab_cursor *pBase) noexcept with gil: cdef: peewee_cursor *pCur = <peewee_cursor *>pBase object table_func = <object>pCur.table_func @@ -483,7 +484,7 @@ # Return the requested column from the current row. cdef int pwColumn(sqlite3_vtab_cursor *pBase, sqlite3_context *ctx, - int iCol) with gil: + int iCol) noexcept with gil: cdef: bytes bval peewee_cursor *pCur = <peewee_cursor *>pBase @@ -502,7 +503,7 @@ return python_to_sqlite(ctx, row_data[iCol]) -cdef int pwRowid(sqlite3_vtab_cursor *pBase, sqlite3_int64 *pRowid): +cdef int pwRowid(sqlite3_vtab_cursor *pBase, sqlite3_int64 *pRowid) noexcept: cdef: peewee_cursor *pCur = <peewee_cursor *>pBase pRowid[0] = <sqlite3_int64>pCur.idx @@ -510,7 +511,7 @@ # Return a boolean indicating whether the cursor has been consumed. -cdef int pwEof(sqlite3_vtab_cursor *pBase): +cdef int pwEof(sqlite3_vtab_cursor *pBase) noexcept: cdef: peewee_cursor *pCur = <peewee_cursor *>pBase return 1 if pCur.stopped else 0 @@ -520,7 +521,8 @@ # get access to the parameters that the function was called with, and call the # TableFunction's `initialize()` function. cdef int pwFilter(sqlite3_vtab_cursor *pBase, int idxNum, - const char *idxStr, int argc, sqlite3_value **argv) with gil: + const char *idxStr, int argc, sqlite3_value **argv) \ + noexcept with gil: cdef: peewee_cursor *pCur = <peewee_cursor *>pBase object table_func = <object>pCur.table_func @@ -572,7 +574,7 @@ # SQLite will (in some cases, repeatedly) call the xBestIndex method to try and # find the best query plan. cdef int pwBestIndex(sqlite3_vtab *pBase, sqlite3_index_info *pIdxInfo) \ - with gil: + noexcept with gil: cdef: int i int col_idx diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/playhouse/migrate.py new/peewee-3.16.3/playhouse/migrate.py --- old/peewee-3.16.2/playhouse/migrate.py 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/playhouse/migrate.py 2023-08-14 16:15:01.000000000 +0200 @@ -836,7 +836,7 @@ @operation def drop_column(self, table, column_name, cascade=True, legacy=False): - if sqlite3.version_info >= (3, 25, 0) and not legacy: + if sqlite3.sqlite_version_info >= (3, 25, 0) and not legacy: ctx = self.make_context() (self._alter_table(ctx, table) .literal(' DROP COLUMN ') @@ -846,7 +846,7 @@ @operation def rename_column(self, table, old_name, new_name, legacy=False): - if sqlite3.version_info >= (3, 25, 0) and not legacy: + if sqlite3.sqlite_version_info >= (3, 25, 0) and not legacy: return (self ._alter_table(self.make_context(), table) .literal(' RENAME COLUMN ') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/playhouse/mysql_ext.py new/peewee-3.16.3/playhouse/mysql_ext.py --- old/peewee-3.16.2/playhouse/mysql_ext.py 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/playhouse/mysql_ext.py 2023-08-14 16:15:01.000000000 +0200 @@ -12,6 +12,7 @@ from peewee import ImproperlyConfigured from peewee import Insert from peewee import MySQLDatabase +from peewee import Node from peewee import NodeList from peewee import SQL from peewee import TextField @@ -36,6 +37,9 @@ raise InterfaceError('Error, database connection not opened.') return self._state.conn.cursor(buffered=True) + def get_binary_type(self): + return mysql_connector.Binary + class MariaDBConnectorDatabase(MySQLDatabase): def _connect(self): @@ -75,17 +79,33 @@ return cursor.lastrowid return cursor + def get_binary_type(self): + return mariadb.Binary + class JSONField(TextField): field_type = 'JSON' - def db_value(self, value): - if value is not None: - return json.dumps(value) + def __init__(self, json_dumps=None, json_loads=None, **kwargs): + self._json_dumps = json_dumps or json.dumps + self._json_loads = json_loads or json.loads + super(JSONField, self).__init__(**kwargs) def python_value(self, value): if value is not None: - return json.loads(value) + try: + return self._json_loads(value) + except (TypeError, ValueError): + return value + + def db_value(self, value): + if value is not None: + if not isinstance(value, Node): + value = self._json_dumps(value) + return value + + def extract(self, path): + return fn.json_extract(self, path) def Match(columns, expr, modifier=None): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/tests/base.py new/peewee-3.16.3/tests/base.py --- old/peewee-3.16.2/tests/base.py 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/tests/base.py 2023-08-14 16:15:01.000000000 +0200 @@ -107,7 +107,7 @@ IS_MYSQL_ADVANCED_FEATURES = True elif server_info[0] == 0: logger.warning('Could not determine mysql server version.') - if server_info[0] == 8 or ((5, 7) <= server_info[:2] <= (6, 0)): + if server_info[0] >= 8 or ((5, 7) <= server_info[:2] <= (6, 0)): # Needs actual MySQL - not MariaDB. IS_MYSQL_JSON = True db.close() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/tests/fields.py new/peewee-3.16.3/tests/fields.py --- old/peewee-3.16.2/tests/fields.py 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/tests/fields.py 2023-08-14 16:15:01.000000000 +0200 @@ -692,6 +692,30 @@ else: self.assertFalse(b_db.data.is_set(x)) + def test_bigbit_field_bulk_create(self): + b1, b2, b3 = Bits(), Bits(), Bits() + b1.data.set_bit(1) + b2.data.set_bit(2) + b3.data.set_bit(3) + Bits.bulk_create([b1, b2, b3]) + self.assertEqual(len(Bits), 3) + for b in Bits.select(): + self.assertEqual(sum(1 if b.data.is_set(i) else 0 + for i in (1, 2, 3)), 1) + + def test_bigbit_field_bulk_update(self): + b1, b2, b3 = Bits.create(), Bits.create(), Bits.create() + + b1.data.set_bit(11) + b2.data.set_bit(12) + b3.data.set_bit(13) + Bits.bulk_update([b1, b2, b3], fields=[Bits.data]) + + mapping = {b1.id: 11, b2.id: 12, b3.id: 13} + for b in Bits.select(): + bit = mapping[b.id] + self.assertTrue(b.data.is_set(bit)) + class BlobModel(TestModel): data = BlobField() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/tests/manytomany.py new/peewee-3.16.3/tests/manytomany.py --- old/peewee-3.16.2/tests/manytomany.py 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/tests/manytomany.py 2023-08-14 16:15:01.000000000 +0200 @@ -602,3 +602,50 @@ def test_empty(self): al = AccountList.create(name='empty') self.assertEqual(list(al.accounts), []) + + +class Permission(TestModel): + name = TextField() + +DeniedThroughDeferred = DeferredThroughModel() + +class Visitor(TestModel): + name = TextField() + allowed = ManyToManyField(Permission) + denied = ManyToManyField(Permission, through_model=DeniedThroughDeferred) + +class DeniedThrough(TestModel): + permission = ForeignKeyField(Permission) + visitor = ForeignKeyField(Visitor) + +DeniedThroughDeferred.set_model(DeniedThrough) + + +class TestMultipleManyToManySameTables(ModelTestCase): + database = get_in_memory_db() + requires = [Permission, Visitor, Visitor.allowed.through_model, + Visitor.denied.through_model] + + def test_multiple_manytomany_same_tables(self): + p1, p2, p3 = [Permission.create(name=n) for n in ('p1', 'p2', 'p3')] + v1, v2, v3 = [Visitor.create(name=n) for n in ('v1', 'v2', 'v3')] + + v1.allowed.add([p1, p2, p3]) + v2.allowed.add(p2) + v2.denied.add([p1, p3]) + v3.allowed.add(p3) + v3.denied.add(p1) + + accum = [] + for v in Visitor.select().order_by(Visitor.name): + allowed, denied = [], [] + for p in v.allowed.order_by(Permission.name): + allowed.append(p.name) + for p in v.denied.order_by(Permission.name): + denied.append(p.name) + accum.append((v.name, allowed, denied)) + + self.assertEqual(accum, [ + ('v1', ['p1', 'p2', 'p3'], []), + ('v2', ['p2'], ['p1', 'p3']), + ('v3', ['p3'], ['p1'])]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/tests/migrations.py new/peewee-3.16.3/tests/migrations.py --- old/peewee-3.16.2/tests/migrations.py 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/tests/migrations.py 2023-08-14 16:15:01.000000000 +0200 @@ -580,7 +580,8 @@ self.assertEqual(foreign_key.dest_table, 'person') def test_drop_foreign_key(self): - migrate(self.migrator.drop_column('page', 'user_id')) + kw = {'legacy': True} if IS_SQLITE else {} + migrate(self.migrator.drop_column('page', 'user_id', **kw)) columns = self.database.get_columns('page') self.assertEqual( sorted(column.name for column in columns), @@ -664,19 +665,19 @@ @requires_sqlite def test_valid_column_required(self): self.assertRaises( - ValueError, + (OperationalError, ValueError), migrate, self.migrator.drop_column('page', 'column_does_not_exist')) self.assertRaises( - ValueError, + (OperationalError, ValueError), migrate, self.migrator.rename_column('page', 'xx', 'yy')) @requires_sqlite @requires_models(IndexModel) def test_table_case_insensitive(self): - migrate(self.migrator.drop_column('PaGe', 'name')) + migrate(self.migrator.drop_column('PaGe', 'name', legacy=True)) column_names = self.get_column_names('page') self.assertEqual(column_names, set(['id', 'user_id'])) @@ -685,7 +686,8 @@ column_names = self.get_column_names('page') self.assertEqual(column_names, set(['id', 'user_id', 'testing'])) - migrate(self.migrator.drop_column('indeX_mOdel', 'first_name')) + migrate(self.migrator.drop_column('indeX_mOdel', 'first_name', + legacy=True)) indexes = self.migrator.database.get_indexes('index_model') self.assertEqual(len(indexes), 1) self.assertEqual(indexes[0].name, 'index_model_data') @@ -759,7 +761,8 @@ migrate(self.migrator.rename_column( 'index_model', 'first_name', - 'first')) + 'first', + legacy=True)) queries = [x.msg for x in self.history] self.assertEqual(queries, [ @@ -818,7 +821,7 @@ self.reset_sql_history() new_fk = ForeignKeyField(User, User.id, null=True, on_delete='CASCADE') migrate( - self.migrator.drop_column('page', 'user_id'), + self.migrator.drop_column('page', 'user_id', legacy=True), self.migrator.add_column('page', 'user_id', new_fk)) queries = [x.msg for x in self.history] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/tests/mysql_ext.py new/peewee-3.16.3/tests/mysql_ext.py --- old/peewee-3.16.2/tests/mysql_ext.py 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/tests/mysql_ext.py 2023-08-14 16:15:01.000000000 +0200 @@ -20,6 +20,10 @@ mariadb = mariadb_db = None else: mariadb_db = db_loader('mariadb') +try: + import mysql.connector as mysql_connector +except ImportError: + mysql_connector = None mysql_ext_db = db_loader('mysqlconnector') @@ -42,6 +46,7 @@ @requires_mysql +@skip_if(mysql_connector is None, 'mysql-connector not installed') class TestMySQLConnector(ModelTestCase): database = mysql_ext_db requires = [Person, Note] @@ -109,6 +114,9 @@ kj_db = KJ['k%s' % i] self.assertEqual(kj_db.data, value) + kj = KJ.select().where(KJ.data.extract('$.k1') == 'v1').get() + self.assertEqual(kj.key, 'k7') + with self.assertRaises(IntegrityError): KJ.create(key='kx', data=None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/tests/regressions.py new/peewee-3.16.3/tests/regressions.py --- old/peewee-3.16.2/tests/regressions.py 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/tests/regressions.py 2023-08-14 16:15:01.000000000 +0200 @@ -1365,9 +1365,10 @@ def test_fk_migration(self): migrator = SchemaMigrator.from_database(self.database) + kw = {'legacy': True} if IS_SQLITE else {} migrate(migrator.drop_column( FKMB._meta.table_name, - FKMB.fkma.column_name)) + FKMB.fkma.column_name, **kw)) migrate(migrator.add_column( FKMB._meta.table_name, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/peewee-3.16.2/tests/sql.py new/peewee-3.16.3/tests/sql.py --- old/peewee-3.16.2/tests/sql.py 2023-04-21 22:17:23.000000000 +0200 +++ new/peewee-3.16.3/tests/sql.py 2023-08-14 16:15:01.000000000 +0200 @@ -161,6 +161,26 @@ 'FROM "point" AS "t1" ' 'ORDER BY "t1"."x", "t1"."y"'), []) + def test_star(self): + query = User.select(User.star) + self.assertSQL(query, ('SELECT "t1".* FROM "users" AS "t1"'), []) + + query = (Tweet + .select(Tweet.star, User.star) + .join(User, on=(Tweet.c.user_id == User.c.id))) + self.assertSQL(query, ( + 'SELECT "t1".*, "t2".* ' + 'FROM "tweets" AS "t1" ' + 'INNER JOIN "users" AS "t2" ON ("t1"."user_id" = "t2"."id")'), []) + + query = (Tweet + .select(Tweet.star, User.c.id) + .join(User, on=(Tweet.c.user_id == User.c.id))) + self.assertSQL(query, ( + 'SELECT "t1".*, "t2"."id" ' + 'FROM "tweets" AS "t1" ' + 'INNER JOIN "users" AS "t2" ON ("t1"."user_id" = "t2"."id")'), []) + def test_from_clause(self): query = (Note .select(Note.content, Person.name)