Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-tinydb for openSUSE:Factory 
checked in at 2022-03-22 19:40:28
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-tinydb (Old)
 and      /work/SRC/openSUSE:Factory/.python-tinydb.new.25692 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-tinydb"

Tue Mar 22 19:40:28 2022 rev:12 rq:963919 version:4.7.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-tinydb/python-tinydb.changes      
2021-11-21 23:52:40.354158062 +0100
+++ /work/SRC/openSUSE:Factory/.python-tinydb.new.25692/python-tinydb.changes   
2022-03-22 19:40:33.383112328 +0100
@@ -1,0 +2,22 @@
+Tue Mar 22 08:34:06 UTC 2022 - Ben Greiner <[email protected]>
+
+- Update to  4.7.0
+  * Feature: Allow inserting Document instances using
+    Table.insert_multiple (see #455).
+  * Performance: Only convert document IDs of a table when
+    returning documents. This improves performance the Table.count
+    and Table.get operations and also for Table.search when only
+    returning a few documents (see #460).
+  * Internal change: Run all Table tests JSONStorage in addition to
+    MemoryStorage.
+  * Fix: Make using callables as queries work again (see #454)
+  * Feature: Add map() query operation to apply a transformation to
+    a document or field when evaluating a query (see PR #445).
+  * Note: This may break code that queries for a field named map
+    using the Query APIs property access syntax
+  * Feature: Add support for typing-extensions v4
+- Disable mypy tests for GNUHealth submission into 15.4
+  jsc#SLE-23990
+- This package needs typing-extensions if used with Python 3.6
+
+-------------------------------------------------------------------

Old:
----
  tinydb-4.5.2.tar.gz
  v4.5.2.tar.gz

New:
----
  tinydb-4.7.0-gh.tar.gz
  tinydb-4.7.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-tinydb.spec ++++++
--- /var/tmp/diff_new_pack.Q0Qycx/_old  2022-03-22 19:40:33.955112928 +0100
+++ /var/tmp/diff_new_pack.Q0Qycx/_new  2022-03-22 19:40:33.959112932 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-tinydb
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,10 +16,10 @@
 #
 
 
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
+%{?!python_module:%define python_module() python3-%{**}}
 %define skip_python2 1
 Name:           python-tinydb
-Version:        4.5.2
+Version:        4.7.0
 Release:        0
 Summary:        A document-oriented database
 License:        MIT
@@ -27,14 +27,21 @@
 URL:            https://github.com/msiemens/tinydb
 Source:         
https://files.pythonhosted.org/packages/source/t/tinydb/tinydb-%{version}.tar.gz
 # https://github.com/msiemens/tinydb/issues/324
-Source1:        
https://github.com/msiemens/tinydb/archive/refs/tags/v%{version}.tar.gz
+Source1:        
https://github.com/msiemens/tinydb/archive/refs/tags/v%{version}.tar.gz#/tinydb-%{version}-gh.tar.gz
 BuildRequires:  %{python_module PyYAML}
-BuildRequires:  %{python_module pytest-mypy}
 BuildRequires:  %{python_module pytest}
 BuildRequires:  %{python_module setuptools}
+#BuildRequires:  %%{python_module typing-extensions >= 3.10 if %%python-base < 
3.7}
+%if 0%{suse_version} < 1550
+# For submission to 15.4, which still has not the boolean rpm requirements 
support in prjconf
+BuildRequires:  %{python_module typing-extensions >= 3.10}
+%endif
 BuildRequires:  dos2unix
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
+%if 0%{?python_version_nodots} < 37
+Requires:       python-typing-extensions >= 3.10
+%endif
 BuildArch:      noarch
 %python_subpackages
 
@@ -45,14 +52,11 @@
 external database server.
 
 %prep
-%setup -q -n tinydb-%{version} -b1
-sed -i '/pytest-cov/d' setup.py
+%setup -q -n tinydb-%{version}
 chmod a-x LICENSE
 dos2unix LICENSE
-
-# Disable broken ujson support
-# https://github.com/msiemens/tinydb/issues/262
-sed -i 's/ujson/ujson_is_broken/' tinydb/storages.py
+# only extract tests, use the sdist for the rest. We could use poetry-core and 
the github archive only if it wasn't for SLE/Leap
+tar -zx -C .. -f %{SOURCE1} tinydb-%{version}/tests
 
 %build
 %python_build
@@ -62,12 +66,12 @@
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
-mv pytest.ini{,.notused}
 %pytest
 
 %files %{python_files}
 %license LICENSE
 %doc README.rst
-%{python_sitelib}/tinydb*
+%{python_sitelib}/tinydb
+%{python_sitelib}/tinydb-%{version}*-info
 
 %changelog

++++++ tinydb-4.5.2.tar.gz -> tinydb-4.7.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/PKG-INFO new/tinydb-4.7.0/PKG-INFO
--- old/tinydb-4.5.2/PKG-INFO   2021-09-23 20:07:31.814720000 +0200
+++ new/tinydb-4.7.0/PKG-INFO   2022-02-19 17:17:56.142034500 +0100
@@ -1,20 +1,20 @@
 Metadata-Version: 2.1
 Name: tinydb
-Version: 4.5.2
+Version: 4.7.0
 Summary: TinyDB is a tiny, document oriented database optimized for your 
happiness :)
 Home-page: https://github.com/msiemens/tinydb
 License: MIT
 Keywords: database,nosql
 Author: Markus Siemens
 Author-email: [email protected]
-Requires-Python: >=3.5,<4.0
+Requires-Python: >=3.6,<4.0
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Intended Audience :: Developers
 Classifier: Intended Audience :: System Administrators
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
 Classifier: Programming Language :: Python :: 3.8
@@ -25,7 +25,7 @@
 Classifier: Topic :: Database :: Database Engines/Servers
 Classifier: Topic :: Utilities
 Classifier: Typing :: Typed
-Requires-Dist: typing-extensions (>=3.10.0,<4.0.0); python_version <= "3.7"
+Requires-Dist: typing-extensions (>=3.10.0,<5.0.0); python_version <= "3.7"
 Project-URL: Changelog, 
https://github.com/msiemens/tinydb/en/latest/changelog.html
 Project-URL: Documentation, https://tinydb.readthedocs.org/
 Project-URL: Issues, https://github.com/msiemens/tinydb/issues
@@ -85,7 +85,7 @@
 Supported Python Versions
 *************************
 
-TinyDB has been tested with Python 3.6 - 3.9 and PyPy3.
+TinyDB has been tested with Python 3.6 - 3.10 and PyPy3.
 
 Example Code
 ************
@@ -115,6 +115,10 @@
     >>> db.search((User.name == 'John') | (User.name == 'Bob'))
     [{'name': 'John', 'age': 22}, {'name': 'John', 'age': 37}, {'name': 'Bob', 
'age': 42}]
 
+    >>> # Apply transformation to field with `map`
+    >>> db.search((User.age.map(lambda x: x + x) == 44))
+    >>> [{'name': 'John', 'age': 22}]
+
     >>> # More possible comparisons:  !=  <  >  <=  >=
     >>> # More possible checks: where(...).matches(regex), 
where(...).test(your_test_func)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/README.rst new/tinydb-4.7.0/README.rst
--- old/tinydb-4.5.2/README.rst 2021-09-23 20:06:56.807656300 +0200
+++ new/tinydb-4.7.0/README.rst 2022-02-19 17:17:13.947860200 +0100
@@ -52,7 +52,7 @@
 Supported Python Versions
 *************************
 
-TinyDB has been tested with Python 3.6 - 3.9 and PyPy3.
+TinyDB has been tested with Python 3.6 - 3.10 and PyPy3.
 
 Example Code
 ************
@@ -82,6 +82,10 @@
     >>> db.search((User.name == 'John') | (User.name == 'Bob'))
     [{'name': 'John', 'age': 22}, {'name': 'John', 'age': 37}, {'name': 'Bob', 
'age': 42}]
 
+    >>> # Apply transformation to field with `map`
+    >>> db.search((User.age.map(lambda x: x + x) == 44))
+    >>> [{'name': 'John', 'age': 22}]
+
     >>> # More possible comparisons:  !=  <  >  <=  >=
     >>> # More possible checks: where(...).matches(regex), 
where(...).test(your_test_func)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/pyproject.toml 
new/tinydb-4.7.0/pyproject.toml
--- old/tinydb-4.5.2/pyproject.toml     2021-09-23 20:06:56.811656200 +0200
+++ new/tinydb-4.7.0/pyproject.toml     2022-02-19 17:17:13.947860200 +0100
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "tinydb"
-version = "4.5.2"
+version = "4.7.0"
 description = "TinyDB is a tiny, document oriented database optimized for your 
happiness :)"
 authors = ["Markus Siemens <[email protected]>"]
 license = "MIT"
@@ -25,6 +25,7 @@
     "Programming Language :: Python :: 3.7",
     "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
+    "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: Implementation :: CPython",
     "Programming Language :: Python :: Implementation :: PyPy",
     "Operating System :: OS Independent",
@@ -40,18 +41,18 @@
 "Issues" = "https://github.com/msiemens/tinydb/issues";
 
 [tool.poetry.dependencies]
-python = "^3.5"
-typing-extensions = { version = "^3.10.0", python = "<=3.7" }
+python = "^3.6"
+typing-extensions = { version = "^3.10.0 || ^4.0.0", python = "<=3.7" }
 
 [tool.poetry.dev-dependencies]
-pytest = "^5.2.2"
+pytest = "^6.2.5"
 pytest-codestyle = "^1.4.0"
 pytest-cov = "^2.8.1"
 pycodestyle = "^2.5.0"
 sphinx = "^2.2.1"
 coveralls = "^1.8.2"
 pyyaml = "^5.1.2"
-pytest-mypy = { version = "^0.4.1", markers = "platform_python_implementation 
!= 'PyPy'" }
+pytest-mypy = { version = "^0.8.1", markers = "platform_python_implementation 
!= 'PyPy'" }
 types-PyYAML = "^5.4.3"
 typing-extensions = { version = "^3.10.0" }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/setup.py new/tinydb-4.7.0/setup.py
--- old/tinydb-4.5.2/setup.py   2021-09-23 20:07:31.813995800 +0200
+++ new/tinydb-4.7.0/setup.py   2022-02-19 17:17:56.141590000 +0100
@@ -8,13 +8,13 @@
 {'': ['*']}
 
 extras_require = \
-{':python_version <= "3.7"': ['typing-extensions>=3.10.0,<4.0.0']}
+{':python_version <= "3.7"': ['typing-extensions>=3.10.0,<5.0.0']}
 
 setup_kwargs = {
     'name': 'tinydb',
-    'version': '4.5.2',
+    'version': '4.7.0',
     'description': 'TinyDB is a tiny, document oriented database optimized for 
your happiness :)',
-    'long_description': ".. image:: 
https://raw.githubusercontent.com/msiemens/tinydb/master/artwork/logo.png\n    
:scale: 100%\n    :height: 150px\n\n|Build Status| |Coverage| 
|Version|\n\nQuick Links\n***********\n\n- `Example Code`_\n- `Supported Python 
Versions`_\n- `Documentation <http://tinydb.readthedocs.org/>`_\n- `Changelog 
<https://tinydb.readthedocs.io/en/latest/changelog.html>`_\n- `Extensions 
<https://tinydb.readthedocs.io/en/latest/extensions.html>`_\n- 
`Contributing`_\n\nIntroduction\n************\n\nTinyDB is a lightweight 
document oriented database optimized for your happiness :)\nIt's written in 
pure Python and has no external dependencies. The target are\nsmall apps that 
would be blown away by a SQL-DB or an external database server.\n\nTinyDB 
is:\n\n- **tiny:** The current source code has 1800 lines of code (with about 
40%\n  documentation) and 1600 lines tests.\n\n- **document oriented:** Like 
MongoDB_, you can store any document\n  (represented as ``dict``) in 
 TinyDB.\n\n- **optimized for your happiness:** TinyDB is designed to be simple 
and\n  fun to use by providing a simple and clean API.\n\n- **written in pure 
Python:** TinyDB neither needs an external server (as\n  e.g. `PyMongo 
<https://api.mongodb.org/python/current/>`_) nor any dependencies\n  from 
PyPI.\n\n- **works on Python 3.6+ and PyPy3:** TinyDB works on all modern 
versions of Python\n  and PyPy.\n\n- **powerfully extensible:** You can easily 
extend TinyDB by writing new\n  storages or modify the behaviour of storages 
with Middlewares.\n\n- **100% test coverage:** No explanation needed.\n\nTo 
dive straight into all the details, head over to the `TinyDB 
docs\n<https://tinydb.readthedocs.io/>`_. You can also discuss everything 
related\nto TinyDB like general development, extensions or showcase your 
TinyDB-based\nprojects on the `discussion forum 
<http://forum.m-siemens.de/.>`_.\n\nSupported Python 
Versions\n*************************\n\nTinyDB has been tested with Python 3.6 - 
 3.9 and PyPy3.\n\nExample Code\n************\n\n.. code-block:: python\n\n    
>>> from tinydb import TinyDB, Query\n    >>> db = TinyDB('/path/to/db.json')\n 
   >>> db.insert({'int': 1, 'char': 'a'})\n    >>> db.insert({'int': 1, 'char': 
'b'})\n\nQuery Language\n==============\n\n.. code-block:: python\n\n    >>> 
User = Query()\n    >>> # Search for a field value\n    >>> db.search(User.name 
== 'John')\n    [{'name': 'John', 'age': 22}, {'name': 'John', 'age': 37}]\n\n  
  >>> # Combine two queries with logical and\n    >>> db.search((User.name == 
'John') & (User.age <= 30))\n    [{'name': 'John', 'age': 22}]\n\n    >>> # 
Combine two queries with logical or\n    >>> db.search((User.name == 'John') | 
(User.name == 'Bob'))\n    [{'name': 'John', 'age': 22}, {'name': 'John', 
'age': 37}, {'name': 'Bob', 'age': 42}]\n\n    >>> # More possible comparisons: 
 !=  <  >  <=  >=\n    >>> # More possible checks: where(...).matches(regex), 
where(...).test(your_test_func)\n\nTables\n======\n\n.. c
 ode-block:: python\n\n    >>> table = db.table('name')\n    >>> 
table.insert({'value': True})\n    >>> table.all()\n    [{'value': 
True}]\n\nUsing Middlewares\n=================\n\n.. code-block:: python\n\n    
>>> from tinydb.storages import JSONStorage\n    >>> from tinydb.middlewares 
import CachingMiddleware\n    >>> db = TinyDB('/path/to/db.json', 
storage=CachingMiddleware(JSONStorage))\n\n\nContributing\n************\n\nWhether
 reporting bugs, discussing improvements and new ideas or writing\nextensions: 
Contributions to TinyDB are welcome! Here's how to get started:\n\n1. Check for 
open issues or open a fresh issue to start a discussion around\n   a feature 
idea or a bug\n2. Fork `the repository <https://github.com/msiemens/tinydb/>`_ 
on Github,\n   create a new branch off the `master` branch and start making 
your changes\n   (known as `GitHub Flow 
<https://guides.github.com/introduction/flow/index.html>`_)\n3. Write a test 
which shows that the bug was fixed or that the featur
 e works\n   as expected\n4. Send a pull request and bug the maintainer until 
it gets merged and\n   published ???\n\n.. |Build Status| image:: 
https://img.shields.io/azure-devops/build/msiemens/3e5baa75-12ec-43ac-9728-89823ee8c7e2/2.svg?style=flat-square\n
   :target: https://dev.azure.com/msiemens/github/_build?definitionId=2\n.. 
|Coverage| image:: 
http://img.shields.io/coveralls/msiemens/tinydb.svg?style=flat-square\n   
:target: https://coveralls.io/r/msiemens/tinydb\n.. |Version| image:: 
http://img.shields.io/pypi/v/tinydb.svg?style=flat-square\n   :target: 
https://pypi.python.org/pypi/tinydb/\n.. _Buzhug: 
http://buzhug.sourceforge.net/\n.. _CodernityDB: 
https://github.com/perchouli/codernitydb\n.. _MongoDB: http://mongodb.org/\n";,
+    'long_description': ".. image:: 
https://raw.githubusercontent.com/msiemens/tinydb/master/artwork/logo.png\n    
:scale: 100%\n    :height: 150px\n\n|Build Status| |Coverage| 
|Version|\n\nQuick Links\n***********\n\n- `Example Code`_\n- `Supported Python 
Versions`_\n- `Documentation <http://tinydb.readthedocs.org/>`_\n- `Changelog 
<https://tinydb.readthedocs.io/en/latest/changelog.html>`_\n- `Extensions 
<https://tinydb.readthedocs.io/en/latest/extensions.html>`_\n- 
`Contributing`_\n\nIntroduction\n************\n\nTinyDB is a lightweight 
document oriented database optimized for your happiness :)\nIt's written in 
pure Python and has no external dependencies. The target are\nsmall apps that 
would be blown away by a SQL-DB or an external database server.\n\nTinyDB 
is:\n\n- **tiny:** The current source code has 1800 lines of code (with about 
40%\n  documentation) and 1600 lines tests.\n\n- **document oriented:** Like 
MongoDB_, you can store any document\n  (represented as ``dict``) in 
 TinyDB.\n\n- **optimized for your happiness:** TinyDB is designed to be simple 
and\n  fun to use by providing a simple and clean API.\n\n- **written in pure 
Python:** TinyDB neither needs an external server (as\n  e.g. `PyMongo 
<https://api.mongodb.org/python/current/>`_) nor any dependencies\n  from 
PyPI.\n\n- **works on Python 3.6+ and PyPy3:** TinyDB works on all modern 
versions of Python\n  and PyPy.\n\n- **powerfully extensible:** You can easily 
extend TinyDB by writing new\n  storages or modify the behaviour of storages 
with Middlewares.\n\n- **100% test coverage:** No explanation needed.\n\nTo 
dive straight into all the details, head over to the `TinyDB 
docs\n<https://tinydb.readthedocs.io/>`_. You can also discuss everything 
related\nto TinyDB like general development, extensions or showcase your 
TinyDB-based\nprojects on the `discussion forum 
<http://forum.m-siemens.de/.>`_.\n\nSupported Python 
Versions\n*************************\n\nTinyDB has been tested with Python 3.6 - 
 3.10 and PyPy3.\n\nExample Code\n************\n\n.. code-block:: python\n\n    
>>> from tinydb import TinyDB, Query\n    >>> db = TinyDB('/path/to/db.json')\n 
   >>> db.insert({'int': 1, 'char': 'a'})\n    >>> db.insert({'int': 1, 'char': 
'b'})\n\nQuery Language\n==============\n\n.. code-block:: python\n\n    >>> 
User = Query()\n    >>> # Search for a field value\n    >>> db.search(User.name 
== 'John')\n    [{'name': 'John', 'age': 22}, {'name': 'John', 'age': 37}]\n\n  
  >>> # Combine two queries with logical and\n    >>> db.search((User.name == 
'John') & (User.age <= 30))\n    [{'name': 'John', 'age': 22}]\n\n    >>> # 
Combine two queries with logical or\n    >>> db.search((User.name == 'John') | 
(User.name == 'Bob'))\n    [{'name': 'John', 'age': 22}, {'name': 'John', 
'age': 37}, {'name': 'Bob', 'age': 42}]\n\n    >>> # Apply transformation to 
field with `map`\n    >>> db.search((User.age.map(lambda x: x + x) == 44))\n    
>>> [{'name': 'John', 'age': 22}]\n\n    >>> # More possi
 ble comparisons:  !=  <  >  <=  >=\n    >>> # More possible checks: 
where(...).matches(regex), 
where(...).test(your_test_func)\n\nTables\n======\n\n.. code-block:: python\n\n 
   >>> table = db.table('name')\n    >>> table.insert({'value': True})\n    >>> 
table.all()\n    [{'value': True}]\n\nUsing 
Middlewares\n=================\n\n.. code-block:: python\n\n    >>> from 
tinydb.storages import JSONStorage\n    >>> from tinydb.middlewares import 
CachingMiddleware\n    >>> db = TinyDB('/path/to/db.json', 
storage=CachingMiddleware(JSONStorage))\n\n\nContributing\n************\n\nWhether
 reporting bugs, discussing improvements and new ideas or writing\nextensions: 
Contributions to TinyDB are welcome! Here's how to get started:\n\n1. Check for 
open issues or open a fresh issue to start a discussion around\n   a feature 
idea or a bug\n2. Fork `the repository <https://github.com/msiemens/tinydb/>`_ 
on Github,\n   create a new branch off the `master` branch and start making 
your changes\n   (
 known as `GitHub Flow 
<https://guides.github.com/introduction/flow/index.html>`_)\n3. Write a test 
which shows that the bug was fixed or that the feature works\n   as 
expected\n4. Send a pull request and bug the maintainer until it gets merged 
and\n   published ???\n\n.. |Build Status| image:: 
https://img.shields.io/azure-devops/build/msiemens/3e5baa75-12ec-43ac-9728-89823ee8c7e2/2.svg?style=flat-square\n
   :target: https://dev.azure.com/msiemens/github/_build?definitionId=2\n.. 
|Coverage| image:: 
http://img.shields.io/coveralls/msiemens/tinydb.svg?style=flat-square\n   
:target: https://coveralls.io/r/msiemens/tinydb\n.. |Version| image:: 
http://img.shields.io/pypi/v/tinydb.svg?style=flat-square\n   :target: 
https://pypi.python.org/pypi/tinydb/\n.. _Buzhug: 
http://buzhug.sourceforge.net/\n.. _CodernityDB: 
https://github.com/perchouli/codernitydb\n.. _MongoDB: http://mongodb.org/\n";,
     'author': 'Markus Siemens',
     'author_email': '[email protected]',
     'maintainer': None,
@@ -23,7 +23,7 @@
     'packages': packages,
     'package_data': package_data,
     'extras_require': extras_require,
-    'python_requires': '>=3.5,<4.0',
+    'python_requires': '>=3.6,<4.0',
 }
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/tinydb/database.py 
new/tinydb-4.7.0/tinydb/database.py
--- old/tinydb-4.5.2/tinydb/database.py 2021-09-23 20:06:56.811656200 +0200
+++ new/tinydb-4.7.0/tinydb/database.py 2022-02-19 17:17:13.951860400 +0100
@@ -9,7 +9,7 @@
 from .utils import with_typehint
 
 # The table's base class. This is used to add type hinting from the Table
-# class to TinyDB. Currently this supports PyCharm, Pyright/VS Code and MyPy.
+# class to TinyDB. Currently, this supports PyCharm, Pyright/VS Code and MyPy.
 TableBase: Type[Table] = with_typehint(Table)
 
 
@@ -91,10 +91,10 @@
         storage = kwargs.pop('storage', self.default_storage_class)
 
         # Prepare the storage
-        self._storage = storage(*args, **kwargs)  # type: Storage
+        self._storage: Storage = storage(*args, **kwargs)
 
         self._opened = True
-        self._tables = {}  # type: Dict[str, Table]
+        self._tables: Dict[str, Table] = {}
 
     def __repr__(self):
         args = [
@@ -116,7 +116,7 @@
         created using the :attr:`~tinydb.database.TinyDB.table_class` class.
         Otherwise, the previously created table instance wil be returned.
 
-        All futher options besides the name are passed to the table class which
+        All further options besides the name are passed to the table class 
which
         by default is :class:`~tinydb.table.Table`. Check its documentation
         for further parameters you can pass.
 
@@ -154,7 +154,7 @@
         # To get a set of table names, we thus construct a set of this main
         # dict which returns a set of the dict keys which are the table names.
         #
-        # Storage.read() may return ``None`` if the database file is empty
+        # Storage.read() may return ``None`` if the database file is empty,
         # so we need to consider this case to and return an empty set in this
         # case.
 
@@ -169,7 +169,7 @@
         # to the storage thereby returning to the initial state with no tables.
         self.storage.write({})
 
-        # After that we need to remeber to empty the ``_tables`` dict so we'll
+        # After that we need to remember to empty the ``_tables`` dict, so 
we'll
         # create new table instances when a table is accessed again.
         self._tables.clear()
 
@@ -269,6 +269,6 @@
 
     def __iter__(self) -> Iterator[Document]:
         """
-        Return an iterater for the default table's documents.
+        Return an iterator for the default table's documents.
         """
         return iter(self.table(self.default_table_name))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/tinydb/middlewares.py 
new/tinydb-4.7.0/tinydb/middlewares.py
--- old/tinydb-4.5.2/tinydb/middlewares.py      2021-09-23 20:06:56.811656200 
+0200
+++ new/tinydb-4.7.0/tinydb/middlewares.py      2022-02-19 17:17:13.951860400 
+0100
@@ -48,10 +48,10 @@
         be the storage (or Middleware) instance. Returning the instance is
         simple, but we also got the underlying (*real*) StorageClass as an
         __init__ argument that still is not an instance.
-        So, we initialize it in __call__ forwarding any arguments we recieve
+        So, we initialize it in __call__ forwarding any arguments we receive
         from TinyDB (``TinyDB(arg1, kwarg1=value, storage=...)``).
 
-        In case of nested Middlewares, calling the instance as if it was an
+        In case of nested Middlewares, calling the instance as if it was a
         class results in calling ``__call__`` what initializes the next
         nested Middleware that itself will initialize the next Middleware and
         so on.
@@ -63,7 +63,7 @@
 
     def __getattr__(self, name):
         """
-        Forward all unknown attribute calls to the underlying storage so we
+        Forward all unknown attribute calls to the underlying storage, so we
         remain as transparent as possible.
         """
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/tinydb/operations.py 
new/tinydb-4.7.0/tinydb/operations.py
--- old/tinydb-4.5.2/tinydb/operations.py       2021-09-23 20:06:56.811656200 
+0200
+++ new/tinydb-4.7.0/tinydb/operations.py       2022-02-19 17:17:13.951860400 
+0100
@@ -31,7 +31,7 @@
 
 def subtract(field, n):
     """
-    Substract ``n`` to a given field in the document.
+    Subtract ``n`` to a given field in the document.
     """
     def transform(doc):
         doc[field] -= n
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/tinydb/queries.py 
new/tinydb-4.7.0/tinydb/queries.py
--- old/tinydb-4.5.2/tinydb/queries.py  2021-09-23 20:06:56.811656200 +0200
+++ new/tinydb-4.7.0/tinydb/queries.py  2022-02-19 17:17:13.951860400 +0100
@@ -18,7 +18,7 @@
 
 import re
 import sys
-from typing import Mapping, Tuple, Callable, Any, Union, List
+from typing import Mapping, Tuple, Callable, Any, Union, List, Optional
 
 from .utils import freeze
 
@@ -44,6 +44,10 @@
        boolean that indicates whether the value matches the query, and
     2. it must have a stable hash that will be used for query caching.
 
+    In addition, to mark a query as non-cacheable (e.g. if it involves
+    some remote lookup) it needs to have a method called ``is_cacheable``
+    that returns ``False``.
+
     This query protocol is used to make MyPy correctly support the query
     pattern that TinyDB uses.
 
@@ -71,23 +75,26 @@
     instance can be used as a key in a dictionary.
     """
 
-    def __init__(self, test: Callable[[Mapping], bool], hashval: Tuple):
+    def __init__(self, test: Callable[[Mapping], bool], hashval: 
Optional[Tuple]):
         self._test = test
         self._hash = hashval
 
+    def is_cacheable(self) -> bool:
+        return self._hash is not None
+
     def __call__(self, value: Mapping) -> bool:
         """
         Evaluate the query to check if it matches a specified value.
 
         :param value: The value to check.
-        :return: Wether the value matchs this query.
+        :return: Whether the value matches this query.
         """
         return self._test(value)
 
     def __hash__(self):
         # We calculate the query hash by using the ``hashval`` object which
-        # describes this query uniquely so we can calculate a stable hash value
-        # by simply hashing it
+        # describes this query uniquely, so we can calculate a stable hash
+        # value by simply hashing it
         return hash(self._hash)
 
     def __repr__(self):
@@ -105,26 +112,32 @@
         # We use a frozenset for the hash as the AND operation is commutative
         # (a & b == b & a) and the frozenset does not consider the order of
         # elements
-        return QueryInstance(lambda value: self(value) and other(value),
-                             ('and', frozenset([self._hash, other._hash])))
+        if self.is_cacheable() and other.is_cacheable():
+            hashval = ('and', frozenset([self._hash, other._hash]))
+        else:
+            hashval = None
+        return QueryInstance(lambda value: self(value) and other(value), 
hashval)
 
     def __or__(self, other: 'QueryInstance') -> 'QueryInstance':
         # We use a frozenset for the hash as the OR operation is commutative
         # (a | b == b | a) and the frozenset does not consider the order of
         # elements
-        return QueryInstance(lambda value: self(value) or other(value),
-                             ('or', frozenset([self._hash, other._hash])))
+        if self.is_cacheable() and other.is_cacheable():
+            hashval = ('or', frozenset([self._hash, other._hash]))
+        else:
+            hashval = None
+        return QueryInstance(lambda value: self(value) or other(value), 
hashval)
 
     def __invert__(self) -> 'QueryInstance':
-        return QueryInstance(lambda value: not self(value),
-                             ('not', self._hash))
+        hashval = ('not', self._hash) if self.is_cacheable() else None
+        return QueryInstance(lambda value: not self(value), hashval)
 
 
 class Query(QueryInstance):
     """
     TinyDB Queries.
 
-    Allows to build queries for TinyDB databases. There are two main ways of
+    Allows building queries for TinyDB databases. There are two main ways of
     using queries:
 
     1) ORM-like usage:
@@ -150,12 +163,12 @@
 
     Queries are executed by calling the resulting object. They expect to get
     the document to test as the first argument and return ``True`` or
-    ``False`` depending on whether the documents matches the query or not.
+    ``False`` depending on whether the documents match the query or not.
     """
 
     def __init__(self) -> None:
         # The current path of fields to access when evaluating the object
-        self._path = ()  # type: Tuple[str, ...]
+        self._path: Tuple[Union[str, Callable], ...] = ()
 
         # Prevent empty queries to be evaluated
         def notest(_):
@@ -182,7 +195,7 @@
         query._path = self._path + (item,)
 
         # ... and update the query hash
-        query._hash = ('path', query._path)
+        query._hash = ('path', query._path) if self.is_cacheable() else None
 
         return query
 
@@ -218,7 +231,10 @@
             try:
                 # Resolve the path
                 for part in self._path:
-                    value = value[part]
+                    if isinstance(part, str):
+                        value = value[part]
+                    else:
+                        value = part(value)
             except (KeyError, TypeError):
                 return False
             else:
@@ -227,7 +243,7 @@
 
         return QueryInstance(
             lambda value: runner(value),
-            hashval
+            (hashval if self.is_cacheable() else None)
         )
 
     def __eq__(self, rhs: Any):
@@ -487,6 +503,21 @@
             ()
         )
 
+    def map(self, fn: Callable[[Any], Any]) -> 'Query':
+        """
+        Add a function to the query path. Similar to __getattr__ but for
+        arbitrary functions.
+        """
+        query = type(self)()
+
+        # Now we add the callable to the query path ...
+        query._path = self._path + (fn,)
+
+        # ... and kill the hash - callable objects can be mutable, so it's
+        # harmful to cache their results.
+        query._hash = None
+
+        return query
 
 def where(key: str) -> Query:
     """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/tinydb/storages.py 
new/tinydb-4.7.0/tinydb/storages.py
--- old/tinydb-4.5.2/tinydb/storages.py 2021-09-23 20:06:56.811656200 +0200
+++ new/tinydb-4.7.0/tinydb/storages.py 2022-02-19 17:17:13.951860400 +0100
@@ -114,7 +114,7 @@
         size = self._handle.tell()
 
         if not size:
-            # File is empty so we return ``None`` so TinyDB can properly
+            # File is empty, so we return ``None`` so TinyDB can properly
             # initialize the database
             return None
         else:
@@ -137,7 +137,7 @@
         except io.UnsupportedOperation:
             raise IOError('Cannot write to the database. Access mode is 
"{0}"'.format(self._mode))
 
-        # Ensure the file has been writtens
+        # Ensure the file has been written
         self._handle.flush()
         os.fsync(self._handle.fileno())
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/tinydb/table.py 
new/tinydb-4.7.0/tinydb/table.py
--- old/tinydb-4.5.2/tinydb/table.py    2021-09-23 20:06:56.811656200 +0200
+++ new/tinydb-4.7.0/tinydb/table.py    2022-02-19 17:17:13.951860400 +0100
@@ -27,7 +27,7 @@
     """
     A document stored in the database.
 
-    This class provides a way to access both a document's content as well as
+    This class provides a way to access both a document's content and
     its ID using ``doc.doc_id``.
     """
 
@@ -50,7 +50,7 @@
         once a threshold is reached.
 
         The query cache is updated on every search operation. When writing
-        data, the whole cache is discareded as the query results may have
+        data, the whole cache is discarded as the query results may have
         changed.
 
     .. admonition:: Customization
@@ -160,8 +160,10 @@
 
         # Now, we update the table and add the document
         def updater(table: dict):
-            assert doc_id not in table, 'doc_id '+str(doc_id)+' already exists'
-
+            if doc_id in table:
+                raise ValueError(f'Document with ID {str(doc_id)} '
+                                 f'already exists')
+                
             # By calling ``dict(document)`` we convert the data we got to a
             # ``dict`` instance even if it was a different class that
             # implemented the ``Mapping`` interface
@@ -176,24 +178,39 @@
         """
         Insert multiple documents into the table.
 
-        :param documents: a Iterable of documents to insert
+        :param documents: an Iterable of documents to insert
         :returns: a list containing the inserted documents' IDs
         """
         doc_ids = []
 
         def updater(table: dict):
             for document in documents:
+
                 # Make sure the document implements the ``Mapping`` interface
                 if not isinstance(document, Mapping):
                     raise ValueError('Document is not a Mapping')
 
-                # Get the document ID for this document and store it so we
-                # can return all document IDs later
+                if isinstance(document, Document):
+                    # Check if document does not override an existing document
+                    if document.doc_id in table:
+                        raise ValueError(
+                            f'Document with ID {str(document.doc_id)} '
+                            f'already exists'
+                        )
+
+                    # Store the doc_id, so we can return all document IDs
+                    # later. Then save the document with its doc_id and
+                    # skip the rest of the current loop
+                    doc_id = document.doc_id
+                    doc_ids.append(doc_id)
+                    table[doc_id] = dict(document)
+                    continue
+
+                # Generate new document ID for this document
+                # Store the doc_id, so we can return all document IDs
+                # later, then save the document with the new doc_id
                 doc_id = self._get_next_id()
                 doc_ids.append(doc_id)
-
-                # Convert the document to a ``dict`` (see Table.insert) and
-                # store it
                 table[doc_id] = dict(document)
 
         # See below for details on ``Table._update``
@@ -229,11 +246,33 @@
         if cached_results is not None:
             return cached_results[:]
 
-        # Perform the search by applying the query to all documents
-        docs = [doc for doc in self if cond(doc)]
+        # Perform the search by applying the query to all documents.
+        # Then, only if the document matches the query, convert it
+        # to the document class and document ID class.
+        docs = [
+            self.document_class(doc, self.document_id_class(doc_id))
+            for doc_id, doc in self._read_table().items()
+            if cond(doc)
+        ]
 
-        # Update the query cache
-        self._query_cache[cond] = docs[:]
+        # Only cache cacheable queries.
+        #
+        # This weird `getattr` dance is needed to make MyPy happy as
+        # it doesn't know that a query might have a `is_cacheable` method
+        # that is not declared in the `QueryLike` protocol due to it being
+        # optional.
+        # See: https://github.com/python/mypy/issues/1424
+        #
+        # Note also that by default we expect custom query objects to be
+        # cacheable (which means they need to have a stable hash value).
+        # This is to keep consistency with TinyDB's behavior before
+        # `is_cacheable` was introduced which assumed that all queries
+        # are cacheable.
+        is_cacheable: Callable[[], bool] = getattr(cond, 'is_cacheable',
+                                                   lambda: True)
+        if is_cacheable():
+            # Update the query cache
+            self._query_cache[cond] = docs[:]
 
         return docs
 
@@ -256,7 +295,7 @@
         if doc_id is not None:
             # Retrieve a document specified by its ID
             table = self._read_table()
-            raw_doc = table.get(doc_id, None)
+            raw_doc = table.get(str(doc_id), None)
 
             if raw_doc is None:
                 return None
@@ -266,9 +305,16 @@
 
         elif cond is not None:
             # Find a document specified by a query
-            for doc in self:
+            # The trailing underscore in doc_id_ is needed so MyPy
+            # doesn't think that `doc_id_` (which is a string) needs
+            # to have the same type as `doc_id` which is this function's
+            # parameter and is an optional `int`.
+            for doc_id_, doc in self._read_table().items():
                 if cond(doc):
-                    return doc
+                    return self.document_class(
+                        doc,
+                        self.document_id_class(doc_id_)
+                    )
 
             return None
 
@@ -499,8 +545,8 @@
             # been removed. When removing documents identified by a set of
             # document IDs, it's this list of document IDs we need to return
             # later.
-            # We convert the document ID iterator into a list so we can both
-            # use the document IDs to remove the specified documents as well as
+            # We convert the document ID iterator into a list, so we can both
+            # use the document IDs to remove the specified documents and
             # to return the list of affected document IDs
             removed_ids = list(doc_ids)
 
@@ -577,20 +623,7 @@
         Count the total number of documents in this table.
         """
 
-        # Using self._read_table() will convert all documents into
-        # the document class. But for counting the number of documents
-        # this conversion is not necessary, thus we read the storage
-        # directly here
-
-        tables = self._storage.read()
-
-        if tables is None:
-            return 0
-
-        try:
-            return len(tables[self.name])
-        except KeyError:
-            return 0
+        return len(self._read_table())
 
     def __iter__(self) -> Iterator[Document]:
         """
@@ -602,7 +635,7 @@
         # Iterate all documents and their IDs
         for doc_id, doc in self._read_table().items():
             # Convert documents to the document class
-            yield self.document_class(doc, doc_id)
+            yield self.document_class(doc, self.document_id_class(doc_id))
 
     def _get_next_id(self):
         """
@@ -639,14 +672,13 @@
 
         return next_id
 
-    def _read_table(self) -> Dict[int, Mapping]:
+    def _read_table(self) -> Dict[str, Mapping]:
         """
         Read the table data from the underlying storage.
 
-        Here we read the data from the underlying storage and convert all
-        IDs to the document ID class. Documents themselves are NOT yet
-        transformed into the document class, we may not want to convert
-        *all* documents when returning only one document for example.
+        Documents and doc_ids are NOT yet transformed, as 
+        we may not want to convert *all* documents when returning
+        only one document for example.
         """
 
         # Retrieve the tables from the storage
@@ -663,19 +695,14 @@
             # The table does not exist yet, so it is empty
             return {}
 
-        # Convert all document IDs to the correct document ID class and return
-        # the table data dict
-        return {
-            self.document_id_class(doc_id): doc
-            for doc_id, doc in table.items()
-        }
+        return table
 
     def _update_table(self, updater: Callable[[Dict[int, Mapping]], None]):
         """
-        Perform an table update operation.
+        Perform a table update operation.
 
         The storage interface used by TinyDB only allows to read/write the
-        complete database data, but not modifying only portions of it. Thus
+        complete database data, but not modifying only portions of it. Thus,
         to only update portions of the table data, we first perform a read
         operation, perform the update on the table data and then write
         the updated data back to the storage.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/tinydb/utils.py 
new/tinydb-4.7.0/tinydb/utils.py
--- old/tinydb-4.5.2/tinydb/utils.py    2021-09-23 20:06:56.811656200 +0200
+++ new/tinydb-4.7.0/tinydb/utils.py    2022-02-19 17:17:13.951860400 +0100
@@ -41,18 +41,18 @@
     A least-recently used (LRU) cache with a fixed cache size.
 
     This class acts as a dictionary but has a limited size. If the number of
-    entries in the cache exeeds the cache size, the leat-recently accessed
-    entry will be discareded.
+    entries in the cache exceeds the cache size, the least-recently accessed
+    entry will be discarded.
 
     This is implemented using an ``OrderedDict``. On every access the accessed
     entry is moved to the front by re-inserting it into the ``OrderedDict``.
     When adding an entry and the cache size is exceeded, the last entry will
-    be discareded.
+    be discarded.
     """
 
     def __init__(self, capacity=None):
         self.capacity = capacity
-        self.cache = OrderedDict()  # type: OrderedDict[K, V]
+        self.cache: OrderedDict[K, V] = OrderedDict()
 
     @property
     def lru(self) -> List[K]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tinydb-4.5.2/tinydb/version.py 
new/tinydb-4.7.0/tinydb/version.py
--- old/tinydb-4.5.2/tinydb/version.py  2021-09-23 20:06:56.811656200 +0200
+++ new/tinydb-4.7.0/tinydb/version.py  2022-02-19 17:17:13.951860400 +0100
@@ -1 +1 @@
-__version__ = '4.5.2'
+__version__ = '4.7.0'

Reply via email to