Hello community,

here is the log from the commit of package python-lmdb for openSUSE:Factory 
checked in at 2020-08-18 12:00:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-lmdb (Old)
 and      /work/SRC/openSUSE:Factory/.python-lmdb.new.3399 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-lmdb"

Tue Aug 18 12:00:30 2020 rev:6 rq:827393 version:0.99

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-lmdb/python-lmdb.changes  2019-11-26 
17:04:23.340006565 +0100
+++ /work/SRC/openSUSE:Factory/.python-lmdb.new.3399/python-lmdb.changes        
2020-08-18 12:02:52.731422124 +0200
@@ -1,0 +2,13 @@
+Mon Aug 17 16:04:47 UTC 2020 - Michael Ströder <[email protected]>
+
+- Update to v0.99
+  * Fix lmdb.tool encoding issues.
+  * Fix -l lmdb invocation issue.
+  * Minor documentation improvements.
+  * Update LMDB to version 0.9.24.
+  * Update for Python 3.9 (current release candidate) support.
+  * Resolve a bug when using cursor.putmulti and append=True on dupsort DBs.
+  * Allow _Database.flags method to take no arguments since the one argument
+    wasn't being used.
+
+-------------------------------------------------------------------

Old:
----
  lmdb-0.98.tar.gz

New:
----
  lmdb-0.99.tar.gz

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

Other differences:
------------------
++++++ python-lmdb.spec ++++++
--- /var/tmp/diff_new_pack.m5h7WL/_old  2020-08-18 12:02:53.739422262 +0200
+++ /var/tmp/diff_new_pack.m5h7WL/_new  2020-08-18 12:02:53.739422262 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-lmdb
 #
-# Copyright (c) 2019 SUSE LLC
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-lmdb
-Version:        0.98
+Version:        0.99
 Release:        0
 Summary:        Universal Python binding for the LMDB 'Lightning' Database
 License:        OLDAP-2.8

++++++ lmdb-0.98.tar.gz -> lmdb-0.99.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/ChangeLog new/lmdb-0.99/ChangeLog
--- old/lmdb-0.98/ChangeLog     2019-11-06 18:52:32.000000000 +0100
+++ new/lmdb-0.99/ChangeLog     2020-08-13 14:05:07.000000000 +0200
@@ -1,3 +1,20 @@
+2020-08-13 v0.99
+* Fix lmdb.tool encoding issues.
+
+* Fix -l lmdb invocation issue.
+
+* Minor documentation improvements.
+
+* Update LMDB to version 0.9.24.
+
+* Update for Python 3.9 (current release candidate) support.
+
+* Resolve a bug when using cursor.putmulti and append=True on dupsort DBs.
+
+* Allow _Database.flags method to take no arguments since the one argument
+  wasn't being used.
+
+
 2019-11-06 v0.98
 * Fix that a duplicate argument to a lmdb method would cause an assert.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/PKG-INFO new/lmdb-0.99/PKG-INFO
--- old/lmdb-0.98/PKG-INFO      2019-11-06 22:40:10.000000000 +0100
+++ new/lmdb-0.99/PKG-INFO      2020-08-13 14:37:31.504410500 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: lmdb
-Version: 0.98
+Version: 0.99
 Summary: Universal Python binding for the LMDB 'Lightning' Database
 Home-page: http://github.com/jnwatson/py-lmdb/
 Author: David Wilson
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/README.md new/lmdb-0.99/README.md
--- old/lmdb-0.98/README.md     2019-11-06 18:52:32.000000000 +0100
+++ new/lmdb-0.99/README.md     2020-08-13 14:05:07.000000000 +0200
@@ -15,6 +15,18 @@
 the tests under your desired target Python release, as the Travis CI build has
 a bad habit of breaking due to external factors approximately every 3 months.
 
+# Python Version Support Statement
+
+This project has been around for a while.  Previously, it supported all the 
way back to before 2.5.  Currently py-lmdb
+supports Python 2.7, Python >= 3.4, and pypy.
+
+Python 2.7 is now end-of-life.  If you are still using Python 2.7, you should 
strongly considering porting to Python
+3.
+
+That said, this project will continue to support running on Python 2.7 until 
Travis CI or Appveyor remove support for
+it.
+
 # Sponsored by The Vertex Project
 
-My current employer, [The Vertex Project](https://vertex.link/) is generously 
sponsoring my time to maintain py-lmdb.  If you like open source and systems 
programming in Python, check us out.  We could definitely use some more hands.
+My current employer, [The Vertex Project](https://vertex.link/) is generously 
sponsoring my time to maintain py-lmdb.
+If you like open source and systems programming in Python, check us out.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/docs/conf.py new/lmdb-0.99/docs/conf.py
--- old/lmdb-0.98/docs/conf.py  2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/docs/conf.py  2020-08-13 14:05:07.000000000 +0200
@@ -43,7 +43,7 @@
 
 # General information about the project.
 project = u'lmdb'
-copyright = u'2013, David Wilson'
+copyright = u'2013-2019 David Wilson, 2019-2020 Nic Watson'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
@@ -107,7 +107,7 @@
 # further.  For a list of options available for each theme, see the
 # documentation.
 html_theme_options = {
-    'github_repo': 'https://github.com/dw/py-lmdb/'
+    'github_repo': 'https://github.com/jnwatson/py-lmdb/'
 }
 
 # Add any paths that contain custom themes here, relative to this directory.
@@ -196,7 +196,7 @@
 # (source start file, target name, title, author, documentclass 
[howto/manual]).
 latex_documents = [
   ('index', 'lmdb.tex', u'lmdb Documentation',
-   u'David Wilson', 'manual'),
+   u'David Wilson and Nic Watson', 'manual'),
 ]
 
 # The name of an image file (relative to this directory) to place at the top of
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/docs/index.rst new/lmdb-0.99/docs/index.rst
--- old/lmdb-0.98/docs/index.rst        2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/docs/index.rst        2020-08-13 14:05:07.000000000 +0200
@@ -284,10 +284,9 @@
 
 .. caution::
 
-    This option may cause filesystems that don't support sparse files, such as
-    OSX, to immediately preallocate `map_size=` bytes of underlying storage
-    when the environment is opened or closed for the first time.
-
+    A filesystem failure (such as running out of space), will crash the Python
+    process if this option is enabled.  (This is a general OS limitation, and
+    not limited to LMDB).
 
 Resource Management
 +++++++++++++++++++
@@ -407,6 +406,11 @@
 .. autoclass:: lmdb.Environment
     :members:
 
+Database class
+##############
+
+.. autoclass:: lmdb._Database
+    :members:
 
 Transaction class
 #################
@@ -414,14 +418,12 @@
 .. autoclass:: lmdb.Transaction
     :members:
 
-
 Cursor class
 ############
 
 .. autoclass:: lmdb.Cursor
     :members:
 
-
 Exceptions
 ##########
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lib/lmdb.h new/lmdb-0.99/lib/lmdb.h
--- old/lmdb-0.98/lib/lmdb.h    2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/lib/lmdb.h    2020-08-13 14:05:07.000000000 +0200
@@ -135,7 +135,7 @@
  *
  *     @author Howard Chu, Symas Corporation.
  *
- *     @copyright Copyright 2011-2018 Howard Chu, Symas Corp. All rights 
reserved.
+ *     @copyright Copyright 2011-2019 Howard Chu, Symas Corp. All rights 
reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted only as authorized by the OpenLDAP
@@ -200,7 +200,7 @@
 /** Library minor version */
 #define MDB_VERSION_MINOR      9
 /** Library patch version */
-#define MDB_VERSION_PATCH      22
+#define MDB_VERSION_PATCH      24
 
 /** Combine args a,b,c into a single integer for easy version comparisons */
 #define MDB_VERINT(a,b,c)      (((a) << 24) | ((b) << 16) | (c))
@@ -210,7 +210,7 @@
        MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
 
 /** The release date of this library version */
-#define MDB_VERSION_DATE       "March 21, 2018"
+#define MDB_VERSION_DATE       "July 24, 2019"
 
 /** A stringifier for the version info */
 #define MDB_VERSTR(a,b,c,d)    "LMDB " #a "." #b "." #c ": (" d ")"
@@ -370,7 +370,7 @@
        MDB_GET_BOTH,                   /**< Position at key/data pair. Only 
for #MDB_DUPSORT */
        MDB_GET_BOTH_RANGE,             /**< position at key, nearest data. 
Only for #MDB_DUPSORT */
        MDB_GET_CURRENT,                /**< Return key/data at current cursor 
position */
-       MDB_GET_MULTIPLE,               /**< Return key and up to a page of 
duplicate data items
+       MDB_GET_MULTIPLE,               /**< Return up to a page of duplicate 
data items
                                                                from current 
cursor position. Move cursor to prepare
                                                                for 
#MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */
        MDB_LAST,                               /**< Position at last key/data 
item */
@@ -379,7 +379,7 @@
        MDB_NEXT,                               /**< Position at next data item 
*/
        MDB_NEXT_DUP,                   /**< Position at next data item of 
current key.
                                                                Only for 
#MDB_DUPSORT */
-       MDB_NEXT_MULTIPLE,              /**< Return key and up to a page of 
duplicate data items
+       MDB_NEXT_MULTIPLE,              /**< Return up to a page of duplicate 
data items
                                                                from next 
cursor position. Move cursor to prepare
                                                                for 
#MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */
        MDB_NEXT_NODUP,                 /**< Position at first data item of 
next key */
@@ -390,7 +390,7 @@
        MDB_SET,                                /**< Position at specified key 
*/
        MDB_SET_KEY,                    /**< Position at specified key, return 
key + data */
        MDB_SET_RANGE,                  /**< Position at first key greater than 
or equal to specified key. */
-       MDB_PREV_MULTIPLE               /**< Position at previous page and 
return key and up to
+       MDB_PREV_MULTIPLE               /**< Position at previous page and 
return up to
                                                                a page of 
duplicate data items. Only for #MDB_DUPFIXED */
 } MDB_cursor_op;
 
@@ -1510,6 +1510,10 @@
        /** @brief Delete current key/data pair
         *
         * This function deletes the key/data pair to which the cursor refers.
+        * This does not invalidate the cursor, so operations such as MDB_NEXT
+        * can still be used on it.
+        * Both MDB_NEXT and MDB_GET_CURRENT will return the same record after
+        * this operation.
         * @param[in] cursor A cursor handle returned by #mdb_cursor_open()
         * @param[in] flags Options for this operation. This parameter
         * must be set to 0 or one of the values described here.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lib/mdb.c new/lmdb-0.99/lib/mdb.c
--- old/lmdb-0.98/lib/mdb.c     2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/lib/mdb.c     2020-08-13 14:05:07.000000000 +0200
@@ -5,7 +5,7 @@
  *     BerkeleyDB API, but much simplified.
  */
 /*
- * Copyright 2011-2018 Howard Chu, Symas Corp.
+ * Copyright 2011-2019 Howard Chu, Symas Corp.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -3094,10 +3094,41 @@
                 * we may be unable to return them to me_pghead.
                 */
                MDB_page *mp = txn->mt_loose_pgs;
+               MDB_ID2 *dl = txn->mt_u.dirty_list;
+               unsigned x;
                if ((rc = mdb_midl_need(&txn->mt_free_pgs, 
txn->mt_loose_count)) != 0)
                        return rc;
-               for (; mp; mp = NEXT_LOOSE_PAGE(mp))
+               for (; mp; mp = NEXT_LOOSE_PAGE(mp)) {
                        mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno);
+                       /* must also remove from dirty list */
+                       if (txn->mt_flags & MDB_TXN_WRITEMAP) {
+                               for (x=1; x<=dl[0].mid; x++)
+                                       if (dl[x].mid == mp->mp_pgno)
+                                               break;
+                               mdb_tassert(txn, x <= dl[0].mid);
+                       } else {
+                               x = mdb_mid2l_search(dl, mp->mp_pgno);
+                               mdb_tassert(txn, dl[x].mid == mp->mp_pgno);
+                               mdb_dpage_free(env, mp);
+                       }
+                       dl[x].mptr = NULL;
+               }
+               {
+                       /* squash freed slots out of the dirty list */
+                       unsigned y;
+                       for (y=1; dl[y].mptr && y <= dl[0].mid; y++);
+                       if (y <= dl[0].mid) {
+                               for(x=y, y++;;) {
+                                       while (!dl[y].mptr && y <= dl[0].mid) 
y++;
+                                       if (y > dl[0].mid) break;
+                                       dl[x++] = dl[y++];
+                               }
+                               dl[0].mid = x-1;
+                       } else {
+                               /* all slots freed */
+                               dl[0].mid = 0;
+                       }
+               }
                txn->mt_loose_pgs = NULL;
                txn->mt_loose_count = 0;
        }
@@ -3960,9 +3991,9 @@
                 * and won't map more than the file size.
                 * Just set the maxsize right now.
                 */
-               if (SetFilePointer(env->me_fd, sizelo, &sizehi, 0) != 
(DWORD)sizelo
+               if (!(flags & MDB_WRITEMAP) && (SetFilePointer(env->me_fd, 
sizelo, &sizehi, 0) != (DWORD)sizelo
                        || !SetEndOfFile(env->me_fd)
-                       || SetFilePointer(env->me_fd, 0, NULL, 0) != 0)
+                       || SetFilePointer(env->me_fd, 0, NULL, 0) != 0))
                        return ErrCode();
        }
 
@@ -5063,7 +5094,7 @@
        if (env->me_fd != INVALID_HANDLE_VALUE)
                (void) close(env->me_fd);
        if (env->me_txns) {
-               MDB_PID_T pid = env->me_pid;
+               MDB_PID_T pid = getpid();
                /* Clearing readers is done in this function because
                 * me_txkey with its destructor must be disabled first.
                 *
@@ -8718,7 +8749,7 @@
                         * the split so the new page is emptier than the old 
page.
                         * This yields better packing during sequential inserts.
                         */
-                       if (nkeys < 20 || nsize > pmax/16 || newindx >= nkeys) {
+                       if (nkeys < 32 || nsize > pmax/16 || newindx >= nkeys) {
                                /* Find split point */
                                psize = 0;
                                if (newindx <= split_indx || newindx >= nkeys) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lib/midl.c new/lmdb-0.99/lib/midl.c
--- old/lmdb-0.98/lib/midl.c    2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/lib/midl.c    2020-08-13 14:05:07.000000000 +0200
@@ -3,7 +3,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2018 The OpenLDAP Foundation.
+ * Copyright 2000-2019 The OpenLDAP Foundation.
  * Portions Copyright 2001-2018 Howard Chu, Symas Corp.
  * All rights reserved.
  *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lib/midl.h new/lmdb-0.99/lib/midl.h
--- old/lmdb-0.98/lib/midl.h    2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/lib/midl.h    2020-08-13 14:05:07.000000000 +0200
@@ -11,7 +11,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * Copyright 2000-2018 The OpenLDAP Foundation.
+ * Copyright 2000-2019 The OpenLDAP Foundation.
  * Portions Copyright 2001-2018 Howard Chu, Symas Corp.
  * All rights reserved.
  *
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lib/py-lmdb/preload.h 
new/lmdb-0.99/lib/py-lmdb/preload.h
--- old/lmdb-0.98/lib/py-lmdb/preload.h 2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/lib/py-lmdb/preload.h 2020-08-13 14:05:07.000000000 +0200
@@ -23,6 +23,8 @@
 #ifndef LMDB_PRELOAD_H
 #define LMDB_PRELOAD_H
 
+#include <stdlib.h>
+
 /**
  * Touch a byte from every page in `x`, causing any read faults necessary for
  * copying the value to occur. This should be called with the GIL released, in
@@ -37,7 +39,7 @@
 static void preload(int rc, void *x, size_t size) {
     if(rc == 0) {
         volatile char j;
-        int i;
+        size_t i;
         for(i = 0; i < size; i += 4096) {
             j = ((volatile char *)x)[i];
         }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lmdb/__init__.py 
new/lmdb-0.99/lmdb/__init__.py
--- old/lmdb-0.98/lmdb/__init__.py      2019-11-06 18:52:32.000000000 +0100
+++ new/lmdb-0.99/lmdb/__init__.py      2020-08-13 14:05:07.000000000 +0200
@@ -19,7 +19,7 @@
 # <http://www.openldap.org/>.
 
 """
-cffi wrapper for OpenLDAP's "Lightning" MDB database.
+Python wrapper for OpenLDAP's "Lightning" MDB database.
 
 Please see https://lmdb.readthedocs.io/
 """
@@ -50,5 +50,4 @@
     from lmdb.cffi import __all__
     from lmdb.cffi import __doc__
 
-__version__ = '0.98'
-
+__version__ = '0.99'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lmdb/cffi.py new/lmdb-0.99/lmdb/cffi.py
--- old/lmdb-0.98/lmdb/cffi.py  2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/lmdb/cffi.py  2020-08-13 14:05:07.000000000 +0200
@@ -55,6 +55,7 @@
     'Cursor',
     'Environment',
     'Transaction',
+    '_Database',
     'enable_drop_gil',
     'version',
 ]
@@ -98,7 +99,7 @@
 EMPTY_BYTES = UnicodeType().encode()
 
 
-# Used to track context across CFFI callbcks.
+# Used to track context across CFFI callbacks.
 _callbacks = threading.local()
 
 _CFFI_CDEF = '''
@@ -236,6 +237,7 @@
     #define MDB_VERSION_MISMATCH ...
 
     #define MDB_APPEND ...
+    #define MDB_APPENDDUP ...
     #define MDB_CP_COMPACT ...
     #define MDB_CREATE ...
     #define MDB_DUPFIXED ...
@@ -1031,7 +1033,7 @@
                 create=True, integerkey=False, integerdup=False,
                 dupfixed=False):
         """
-        Open a database, returning an opaque handle. Repeat
+        Open a database, returning an instance of :py:class:`_Database`. Repeat
         :py:meth:`Environment.open_db` calls for the same name will return the
         same handle. As a special case, the main database is always open.
 
@@ -1062,6 +1064,13 @@
         process. Only one thread should call this function; it is not
         mutex-protected in a read-only transaction.
 
+        The `dupsort`, `integerkey`, `integerdup`, and `dupfixed` parameters 
are
+        ignored if the database already exists.  The state of those settings 
are
+        persistent and immutable per database.  See :py:meth:`_Database.flags`
+        to view the state of those options for an opened database.  A 
consequence
+        of the immutability of these flags is that the default non-named 
database
+        will never have these flags set.
+
         Preexisting transactions, other than the current transaction and any
         parents, must not use the new handle, nor must their children.
 
@@ -1135,7 +1144,12 @@
 
 
 class _Database(object):
-    """Internal database handle."""
+    """
+    Internal database handle.  This class is opaque, save a single method.
+
+    Should not be constructed directly.  Use :py:meth:`Environment.open_db`
+    instead.
+    """
     def __init__(self, env, txn, name, reverse_key, dupsort, create,
                  integerkey, integerdup, dupfixed):
         env._deps.add(self)
@@ -1171,9 +1185,12 @@
             raise _error("mdb_dbi_flags", rc)
         self._flags = flags_[0]
 
-    def flags(self, txn):
+    def flags(self, *args):
         """Return the database's associated flags as a dict of _Database
         constructor kwargs."""
+        if len(args) > 1:
+            raise TypeError('flags takes 0 or 1 arguments')
+
         return {
             'reverse_key': bool(self._flags & _lib.MDB_REVERSEKEY),
             'dupsort': bool(self._flags & _lib.MDB_DUPSORT),
@@ -1526,7 +1543,7 @@
     
<http://symas.com/mdb/doc/group__mdb.html#ga9ff5d7bd42557fd5ee235dc1d62613aa>`_
 
         `db`:
-            :py:class:`Database` to navigate.
+            :py:class:`_Database` to navigate.
 
         `txn`:
             :py:class:`Transaction` to navigate.
@@ -2007,8 +2024,8 @@
 
     def set_range_dup(self, key, value):
         """Seek to the first key/value pair greater than or equal to `key`,
-        returning ``True`` on success, or ``False`` to indicate `(key, value)`
-        was past end of database.
+        returning ``True`` on success, or ``False`` to indicate that `value` 
was past the
+        last value of `key` or that `(key, value)` was past the end end of 
database.
 
         Only meaningful for databases opened with `dupsort=True`.
 
@@ -2144,7 +2161,10 @@
         if not overwrite:
             flags |= _lib.MDB_NOOVERWRITE
         if append:
-            flags |= _lib.MDB_APPEND
+            if self.txn._db._flags & _lib.MDB_DUPSORT:
+                flags |= _lib.MDB_APPENDDUP
+            else:
+                flags |= _lib.MDB_APPEND
 
         added = 0
         skipped = 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lmdb/cpython.c new/lmdb-0.99/lmdb/cpython.c
--- old/lmdb-0.98/lmdb/cpython.c        2019-11-06 18:52:32.000000000 +0100
+++ new/lmdb-0.99/lmdb/cpython.c        2020-08-13 14:05:07.000000000 +0200
@@ -861,33 +861,35 @@
         self = env->spare_txns;
         DEBUG("found freelist txn; self=%p self->txn=%p", self, self->txn)
         env->spare_txns = self->spare_next;
-        env->max_spare_txns++;
-        self->flags &= ~TRANS_SPARE;
-        _Py_NewReference((PyObject *)self);
-        UNLOCKED(rc, mdb_txn_renew(self->txn));
 
+        UNLOCKED(rc, mdb_txn_renew(self->txn));
         if(rc) {
             mdb_txn_abort(self->txn);
-            self->txn = NULL;
+            PyObject_Del(self);
+            return err_set("mdb_txn_begin", rc);
         }
+
+        env->max_spare_txns++;
+        self->flags &= ~TRANS_SPARE;
+
     } else {
+        MDB_txn *txn;
         if(write && env->readonly) {
             const char *msg = "Cannot start write transaction with read-only 
env";
             return err_set(msg, EACCES);
         }
 
+        flags = write ? 0 : MDB_RDONLY;
+        UNLOCKED(rc, mdb_txn_begin(env->env, parent_txn, flags, &txn));
+        if(rc) {
+            return err_set("mdb_txn_begin", rc);
+        }
+
         if(! ((self = PyObject_New(TransObject, &PyTransaction_Type)))) {
+            mdb_txn_abort(txn);
             return NULL;
         }
-
-        flags = write ? 0 : MDB_RDONLY;
-        UNLOCKED(rc, mdb_txn_begin(env->env, parent_txn, flags, &self->txn));
-    }
-
-    if(rc) {
-        _Py_ForgetReference((PyObject *)self);
-        PyObject_Del(self);
-        return err_set("mdb_txn_begin", rc);
+        self->txn = txn;
     }
 
     OBJECT_INIT(self)
@@ -917,6 +919,7 @@
 make_cursor(DbObject *db, TransObject *trans)
 {
     CursorObject *self;
+    MDB_cursor *curs;
     int rc;
 
     if(! trans->valid) {
@@ -928,20 +931,26 @@
         return NULL;
     }
 
-    self = PyObject_New(CursorObject, &PyCursor_Type);
-    UNLOCKED(rc, mdb_cursor_open(trans->txn, db->dbi, &self->curs));
+    UNLOCKED(rc, mdb_cursor_open(trans->txn, db->dbi, &curs));
     if(rc) {
-        _Py_ForgetReference((PyObject *)self);
-        PyObject_Del(self);
         return err_set("mdb_cursor_open", rc);
     }
 
+    self = PyObject_New(CursorObject, &PyCursor_Type);
+    if (!self) {
+        mdb_cursor_close(curs);
+        return NULL;
+    }
+
     DEBUG("sizeof cursor = %d", (int) sizeof *self)
     OBJECT_INIT(self)
     LINK_CHILD(trans, self)
+    self->curs = curs;
     self->positioned = 0;
     self->key.mv_size = 0;
+    self->key.mv_data = NULL;
     self->val.mv_size = 0;
+    self->val.mv_data = NULL;
     self->trans = trans;
     self->last_mutation = trans->mutations;
     self->dbi_flags = db->flags;
@@ -1041,23 +1050,11 @@
     PyObject *dct;
     unsigned int f;
 
-    struct db_flags {
-        TransObject *txn;
-    } arg = {NULL};
-
-    static const struct argspec argspec[] = {
-        {"txn", ARG_TRANS, OFFSET(db_flags, txn)}
-    };
-
-    static PyObject *cache = NULL;
-    if(parse_args(self->valid, SPECSIZE(), argspec, &cache, args, kwds, &arg)) 
{
-        return NULL;
-    }
-    if(! arg.txn) {
-        return type_error("'txn' argument required");
-    }
-    if(! arg.txn->valid) {
-        return err_invalid();
+    if (args) {
+        Py_ssize_t size = PyTuple_GET_SIZE(args);
+        if(size > 1) {
+            return type_error("too many positional arguments.");
+        }
     }
 
     dct = PyDict_New();
@@ -2244,7 +2241,7 @@
         flags |= MDB_NOOVERWRITE;
     }
     if(arg.append) {
-        flags |= MDB_APPEND;
+        flags |= (self->trans->db->flags & MDB_DUPSORT) ? MDB_APPENDDUP : 
MDB_APPEND;
     }
 
     if(! ((iter = PyObject_GetIter(arg.items)))) {
@@ -2581,14 +2578,17 @@
 new_iterator(CursorObject *cursor, IterValFunc val_func, MDB_cursor_op op)
 {
     IterObject *iter = PyObject_New(IterObject, &PyIterator_Type);
-    if(iter) {
-        iter->val_func = val_func;
-        iter->curs = cursor;
-        Py_INCREF(cursor);
-        iter->started = 0;
-        iter->op = op;
+    if (!iter) {
+        return NULL;
     }
-    DEBUG("new_iterator: %#p", (void *)iter)
+
+    iter->val_func = val_func;
+    iter->curs = cursor;
+    Py_INCREF(cursor);
+    iter->started = 0;
+    iter->op = op;
+
+    DEBUG("new_iterator: %p", (void *)iter)
     return (PyObject *) iter;
 }
 
@@ -2992,15 +2992,17 @@
         self->spare_next = self->env->spare_txns;
         self->env->spare_txns = self;
         self->env->max_spare_txns--;
+        Py_INCREF(self);
 
         Py_CLEAR(self->db);
         UNLINK_CHILD(self->env, self)
         Py_CLEAR(self->env);
-    } else {
-        MDEBUG("deleting trans")
-        trans_clear(self);
-        PyObject_Del(self);
+        return;
     }
+
+    MDEBUG("deleting trans")
+    trans_clear(self);
+    PyObject_Del(self);
 }
 
 /**
@@ -3618,15 +3620,18 @@
     int i;
     for(i = 0; types[i]; i++) {
         PyTypeObject *type = types[i];
+        char const * name = type->tp_name;
 
         if(PyType_Ready(type)) {
             return -1;
         }
-        if(PyObject_SetAttrString(mod, type->tp_name, (PyObject *)type)) {
+        if(PyObject_SetAttrString(mod, name, (PyObject *)type)) {
             return -1;
         }
 
-        if(type->tp_name[0] != '_' && append_string(__all__, type->tp_name)) {
+        /* As a special case, export _Database */
+        if((name[0] != '_' || 0 == strcmp(name, "_Database")) &&
+           append_string(__all__, name)) {
             return -1;
         }
     }
Binary files old/lmdb-0.98/lmdb/cpython.cpython-39d-x86_64-linux-gnu.so and 
new/lmdb-0.99/lmdb/cpython.cpython-39d-x86_64-linux-gnu.so differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lmdb/tool.py new/lmdb-0.99/lmdb/tool.py
--- old/lmdb-0.98/lmdb/tool.py  2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/lmdb/tool.py  2020-08-13 14:05:07.000000000 +0200
@@ -251,7 +251,7 @@
         die('"copyfd" command takes no arguments (see --help)')
 
     try:
-        fp = os.fdopen(opts.out_fd, 'w', 0)
+        os.fdopen(opts.out_fd, 'w', 0)
     except OSError:
         e = sys.exc_info()[1]
         die('Bad --out-fd %d: %s', opts.out_fd, e)
@@ -509,8 +509,8 @@
     dbs = []
     for arg in args:
         name = None if arg == ':main:' else arg
-        src_db = ENV.open_db(name)
-        dst_db = target_env.open_db(name)
+        src_db = ENV.open_db(_to_bytes(name))
+        dst_db = target_env.open_db(_to_bytes(name))
         dbs.append((arg, src_db, dst_db))
 
     if not dbs:
@@ -590,7 +590,7 @@
         s = fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ, '1234')
         height, width = struct.unpack('hh', s)
         return width, height
-    except:
+    except Exception:
         return default
 
 
@@ -599,9 +599,9 @@
     _TERM_WIDTH, _TERM_HEIGHT = _get_term_width()
 
 
-def main():
+def main(argv=None):
     parser = make_parser()
-    opts, args = parser.parse_args()
+    opts, args = parser.parse_args(argv)
 
     if not args:
         die('Please specify a command (see --help)')
@@ -614,7 +614,7 @@
 
     if opts.db:
         global DB
-        DB = ENV.open_db(opts.db)
+        DB = ENV.open_db(_to_bytes(opts.db))
 
     if hasattr(signal, 'SIGWINCH'):  # Disable on win32.
         signal.signal(signal.SIGWINCH, _on_sigwinch)
@@ -628,4 +628,4 @@
 
 
 if __name__ == '__main__':
-    main()
+    main(sys.argv[1:])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lmdb.egg-info/PKG-INFO 
new/lmdb-0.99/lmdb.egg-info/PKG-INFO
--- old/lmdb-0.98/lmdb.egg-info/PKG-INFO        2019-11-06 22:40:10.000000000 
+0100
+++ new/lmdb-0.99/lmdb.egg-info/PKG-INFO        2020-08-13 14:37:31.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: lmdb
-Version: 0.98
+Version: 0.99
 Summary: Universal Python binding for the LMDB 'Lightning' Database
 Home-page: http://github.com/jnwatson/py-lmdb/
 Author: David Wilson
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/lmdb.egg-info/SOURCES.txt 
new/lmdb-0.99/lmdb.egg-info/SOURCES.txt
--- old/lmdb-0.98/lmdb.egg-info/SOURCES.txt     2019-11-06 22:40:10.000000000 
+0100
+++ new/lmdb-0.99/lmdb.egg-info/SOURCES.txt     2020-08-13 14:37:31.000000000 
+0200
@@ -38,6 +38,7 @@
 lmdb/_config.py
 lmdb/cffi.py
 lmdb/cpython.c
+lmdb/cpython.cpython-39d-x86_64-linux-gnu.so
 lmdb/tool.py
 lmdb.egg-info/PKG-INFO
 lmdb.egg-info/SOURCES.txt
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/setup.py new/lmdb-0.99/setup.py
--- old/lmdb-0.98/setup.py      2019-11-06 18:52:32.000000000 +0100
+++ new/lmdb-0.99/setup.py      2020-08-13 14:05:07.000000000 +0200
@@ -44,14 +44,10 @@
 if os.getenv('LMDB_FORCE_CFFI') is not None:
     use_cpython = False
 
-if sys.version[:3] < '2.5':
-    sys.stderr.write('Error: py-lmdb requires at least CPython 2.5\n')
+if sys.version[:3] < '2.7' or (sys.version_info[0] == 3 and sys.version[:3] < 
'3.4'):
+    sys.stderr.write('Error: py-lmdb requires at least CPython 2.7 or 3.4\n')
     raise SystemExit(1)
 
-if sys.version[:3] in ('3.0', '3.1', '3.2'):
-    use_cpython = False
-
-
 #
 # Figure out which LMDB implementation to use.
 #
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/tests/cursor_test.py 
new/lmdb-0.99/tests/cursor_test.py
--- old/lmdb-0.98/tests/cursor_test.py  2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/tests/cursor_test.py  2020-08-13 14:05:07.000000000 +0200
@@ -31,7 +31,6 @@
 from testlib import B
 from testlib import BT
 
-
 class ContextManagerTest(unittest.TestCase):
     def tearDown(self):
         testlib.cleanup()
@@ -50,7 +49,7 @@
         try:
             with txn.cursor() as curs:
                 curs.put(123, 123)
-        except:
+        except Exception:
             pass
         self.assertRaises(Exception, lambda: curs.get(B('foo')))
 
@@ -174,6 +173,21 @@
         self.assertRaises(Exception,
              lambda: self.c.putmulti(range(2)))
 
+    def test_dupsort(self):
+        _, env = testlib.temp_env()
+        db1 = env.open_db(B('db1'), dupsort=True)
+        txn = env.begin(write=True, db=db1)
+        with txn.cursor() as c:
+            tups = [BT('a', 'value1'), BT('b', 'value1'), BT('b', 'value2')]
+            assert (3, 3) == c.putmulti(tups)
+
+    def test_dupsort_append(self):
+        _, env = testlib.temp_env()
+        db1 = env.open_db(B('db1'), dupsort=True)
+        txn = env.begin(write=True, db=db1)
+        with txn.cursor() as c:
+            tups = [BT('a', 'value1'), BT('b', 'value1'), BT('b', 'value2')]
+            assert (3, 3) == c.putmulti(tups, append=True)
 
 class ReplaceTest(CursorTestBase):
     def test_replace(self):
@@ -258,7 +272,7 @@
         self.c.value()
         minflts_after_value = resource.getrusage(resource.RUSAGE_THREAD)[6]
 
-        epsilon = 5
+        epsilon = 20
 
         # Setting the position doesn't prefault the data
         assert minflts_after_key - minflts_before < epsilon
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/tests/env_test.py 
new/lmdb-0.99/tests/env_test.py
--- old/lmdb-0.98/tests/env_test.py     2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/tests/env_test.py     2020-08-13 14:05:07.000000000 +0200
@@ -23,14 +23,12 @@
 from __future__ import absolute_import
 from __future__ import with_statement
 import os
-import signal
 import sys
 import unittest
 import weakref
 
 import testlib
 from testlib import B
-from testlib import BT
 from testlib import OCT
 from testlib import INT_TYPES
 from testlib import UnicodeType
@@ -704,6 +702,9 @@
             key = B('%s-%s' % (flag, val))
             db = env.open_db(key, txn=txn, **{flag: val})
             assert db.flags(txn)[flag] == val
+            assert db.flags(None)[flag] == val
+            assert db.flags()[flag] == val
+            self.assertRaises(TypeError, lambda: db.flags(1, 2, 3))
 
         txn.commit()
         # Test flag persistence.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/tests/package_test.py 
new/lmdb-0.99/tests/package_test.py
--- old/lmdb-0.98/tests/package_test.py 2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/tests/package_test.py 2020-08-13 14:05:07.000000000 +0200
@@ -63,6 +63,7 @@
             'Transaction',
             'TxnFullError',
             'VersionMismatchError',
+            '_Database',
             'enable_drop_gil',
             'version',
         ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/tests/testlib.py 
new/lmdb-0.99/tests/testlib.py
--- old/lmdb-0.98/tests/testlib.py      2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/tests/testlib.py      2020-08-13 14:05:07.000000000 +0200
@@ -29,6 +29,7 @@
 import sys
 import tempfile
 import traceback
+import unittest
 
 try:
     import __builtin__
@@ -37,7 +38,6 @@
 
 import lmdb
 
-
 _cleanups = []
 
 def cleanup():
@@ -50,6 +50,10 @@
 
 atexit.register(cleanup)
 
+class LmdbTest(unittest.TestCase):
+    def tearDown(self):
+        cleanup()
+
 
 def temp_dir(create=True):
     path = tempfile.mkdtemp(prefix='lmdb_test')
@@ -99,12 +103,9 @@
             # PyPy doesn't collect objects with __del__ on first attempt.
             gc.collect()
 
-
-# Handle moronic Python >=3.0 <3.3.
 UnicodeType = getattr(__builtin__, 'unicode', str)
 BytesType = getattr(__builtin__, 'bytes', str)
 
-
 try:
     INT_TYPES = (int, long)
 except NameError:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/tests/tool_test.py 
new/lmdb-0.99/tests/tool_test.py
--- old/lmdb-0.98/tests/tool_test.py    2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/tests/tool_test.py    2020-08-13 14:05:07.000000000 +0200
@@ -21,17 +21,37 @@
 #
 
 from __future__ import absolute_import
+
+import sys
+import shlex
 import unittest
 
 import lmdb
 import lmdb.tool
+import testlib
 
-
-class ToolTest(unittest.TestCase):
-    def test_ok(self):
-        # For now, simply ensure the module can be compiled (3.x compat).
-        pass
-
+def call_tool(cmdline):
+    if sys.platform == 'win32':
+        args = cmdline.split()
+    else:
+        args = shlex.split(cmdline)
+    return lmdb.tool.main(args)
+
+class ToolTest(testlib.LmdbTest):
+    def test_cmd_get(self):
+        frompath, env = testlib.temp_env()
+        db = env.open_db(b'subdb')
+        with env.begin(write=True, db=db) as txn:
+            txn.put(b'foo', b'bar', db=db)
+        env.close()
+        call_tool('-d subdb get --env %s' % (frompath,))
+
+    def test_cmd_rewrite(self):
+        frompath, env = testlib.temp_env()
+        env.open_db(b'subdb')
+        env.close()
+        topath = testlib.temp_dir()
+        call_tool('rewrite -e %s -E %s subdb' % (frompath, topath))
 
 if __name__ == '__main__':
     unittest.main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/lmdb-0.98/tests/txn_test.py 
new/lmdb-0.99/tests/txn_test.py
--- old/lmdb-0.98/tests/txn_test.py     2019-11-06 18:52:11.000000000 +0100
+++ new/lmdb-0.99/tests/txn_test.py     2020-08-13 14:05:07.000000000 +0200
@@ -28,11 +28,8 @@
 
 import testlib
 from testlib import B
-from testlib import BT
-from testlib import OCT
 from testlib import INT_TYPES
 from testlib import BytesType
-from testlib import UnicodeType
 
 import lmdb
 


Reply via email to