Hello community,

here is the log from the commit of package python-BTrees for openSUSE:Factory 
checked in at 2020-01-16 18:14:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-BTrees (Old)
 and      /work/SRC/openSUSE:Factory/.python-BTrees.new.26092 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-BTrees"

Thu Jan 16 18:14:37 2020 rev:9 rq:764041 version:4.6.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-BTrees/python-BTrees.changes      
2019-10-16 09:13:56.463675439 +0200
+++ /work/SRC/openSUSE:Factory/.python-BTrees.new.26092/python-BTrees.changes   
2020-01-16 18:14:44.228754081 +0100
@@ -1,0 +2,6 @@
+Mon Jan 13 14:30:27 UTC 2020 - Marketa Calabkova <mcalabk...@suse.com>
+
+- update to 4.6.1
+  * Add support for Python 3.8.
+
+-------------------------------------------------------------------

Old:
----
  BTrees-4.6.0.tar.gz

New:
----
  BTrees-4.6.1.tar.gz

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

Other differences:
------------------
++++++ python-BTrees.spec ++++++
--- /var/tmp/diff_new_pack.gSiAFw/_old  2020-01-16 18:14:45.248754658 +0100
+++ /var/tmp/diff_new_pack.gSiAFw/_new  2020-01-16 18:14:45.252754659 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-BTrees
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 # Copyright (c) 2015 LISA GmbH, Bingen, Germany.
 #
 # All modifications and additions to the file contributed by third parties
@@ -19,7 +19,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-BTrees
-Version:        4.6.0
+Version:        4.6.1
 Release:        0
 Summary:        Persistent B-tree object containers for Python
 License:        ZPL-2.1

++++++ BTrees-4.6.0.tar.gz -> BTrees-4.6.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/.travis.yml new/BTrees-4.6.1/.travis.yml
--- old/BTrees-4.6.0/.travis.yml        2019-07-30 10:36:48.000000000 +0200
+++ new/BTrees-4.6.1/.travis.yml        2019-11-07 17:39:45.000000000 +0100
@@ -1,88 +1,103 @@
 language: python
-dist: xenial
-matrix:
-    include:
-        - os: linux
-          python: 2.7
-        - os: linux
-          python: 2.7
-          env: PURE_PYTHON=1
-        - os: linux
-          python: 3.5
-        - os: linux
-          python: 3.6
-          env: WITH_COVERAGE=1
-        - os: linux
-          python: 3.6
-          env:
-            - PURE_PYTHON=1
-            - WITH_COVERAGE=1
-        - os: linux
-          python: 3.7
-        - os: linux
-          python: pypy
-        - os: linux
-          python: pypy3
-        # It's important to use 'macpython' builds to get the least
-        # restrictive wheel tag. It's also important to avoid
-        # 'homebrew 3' because it floats instead of being a specific version.
-        - os: osx
-          language: generic
-          env: TERRYFY_PYTHON='macpython 2.7'
-        - os: osx
-          language: generic
-          env: TERRYFY_PYTHON='macpython 3.5'
-        - os: osx
-          language: generic
-          env: TERRYFY_PYTHON='macpython 3.6.1'
-        - os: osx
-          language: generic
-          env: TERRYFY_PYTHON='macpython 3.7.0'
-        - services:
-            - docker
-          env: DOCKER_IMAGE=quay.io/pypa/manylinux1_x86_64
-          before_install:
-            - if [[ $TRAVIS_TAG ]]; then bash .manylinux.sh; fi
-            - exit 0
-        - services:
-            - docker
-          env:
-            - DOCKER_IMAGE=quay.io/pypa/manylinux1_i686
-            - PRE_CMD=linux32
-          before_install:
-            - if [[ $TRAVIS_TAG ]]; then bash .manylinux.sh; fi
-            - exit 0
+
+env:
+  global:
+    - TWINE_USERNAME: zope.wheelbuilder
+    # this sets $PYPIPASSWORD
+    - secure: 
"Oh5gRJ+Fo8ZNmCkdrffpx201EPyTr9iUXmv6VqJMTebrzQpFdSWUVcANRmAzyfdyk3Wo0IjifVfWsKc+hvtbFmXZiLRFyEgoCUmzeWVumjebg2xxm0PbFHcRQgl4daBXxB0iqWkP8wXZ3daytuL74sYcbHizMYyhc7AxFbANsZc="
+
+python:
+  - 2.7
+  - 3.5
+  - 3.6
+  - 3.7
+  - 3.8
+  - pypy
+  - pypy3
+
+jobs:
+  include:
+
+    # Special Linux builds
+    - name: "Python: 2.7, pure (no C extensions)"
+      python: 2.7
+      env: PURE_PYTHON=1
+    - name: "Python: 3.6, pure (no C extensions), with coverage"
+      python: 3.6
+      env: PURE_PYTHON=1 WITH_COVERAGE=1
+    - name: "Python: 3.6, with coverage"
+      python: 3.6
+      env: WITH_COVERAGE=1
+
+    # manylinux wheel builds
+    - name: 64-bit manylinux wheels (all Pythons)
+      services: docker
+      env: DOCKER_IMAGE=quay.io/pypa/manylinux1_x86_64
+      install: docker pull $DOCKER_IMAGE
+      script: bash .manylinux.sh
+
+    - name: 32-bit manylinux wheels (all Pythons)
+      services: docker
+      env: DOCKER_IMAGE=quay.io/pypa/manylinux1_i686 PRE_CMD=linux32
+      install: docker pull $DOCKER_IMAGE
+      script: bash .manylinux.sh
+
+    # It's important to use 'macpython' builds to get the least
+    # restrictive wheel tag. It's also important to avoid
+    # 'homebrew 3' because it floats instead of being a specific version.
+    - name: Python 2.7 wheels for MacOS
+      os: osx
+      language: generic
+      env: TERRYFY_PYTHON='macpython 2.7'
+    - name: Python 3.5 wheels for MacOS
+      os: osx
+      language: generic
+      env: TERRYFY_PYTHON='macpython 3.5'
+    - name: Python 3.6 wheels for MacOS
+      os: osx
+      language: generic
+      env: TERRYFY_PYTHON='macpython 3.6.1'
+    - name: Python 3.7 wheels for MacOS
+      os: osx
+      language: generic
+      env: TERRYFY_PYTHON='macpython 3.7.0'
 
 before_install:
-    - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then git clone 
https://github.com/MacPython/terryfy; fi
-    - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then source 
terryfy/travis_tools.sh; fi
-    - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then get_python_environment 
$TERRYFY_PYTHON venv; fi
+  - |
+    if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
+      git clone https://github.com/MacPython/terryfy
+      source terryfy/travis_tools.sh
+      get_python_environment $TERRYFY_PYTHON venv
+    fi
+
 install:
-    - pip install -U pip setuptools
-    - if [[ "$WITH_COVERAGE" == "1" ]]; then pip install coveralls coverage; fi
-    - pip install -e .[test,ZODB]
+  - pip install -U pip setuptools
+  - if [[ "$WITH_COVERAGE" == "1" ]]; then pip install coveralls coverage; fi
+  - pip install -e .[test,ZODB]
+
 script:
-    - |
-      if [[ "$WITH_COVERAGE" == "1" ]]; then
-        coverage run -m zope.testrunner --test-path=. --auto-color 
--auto-progress --verbose;
-      else
-        zope-testrunner --test-path=. --auto-color --auto-progress --verbose;
-      fi
-notifications:
-    email: false
+  - |
+    if [[ "$WITH_COVERAGE" == "1" ]]; then
+      coverage run -m zope.testrunner --test-path=. --auto-color 
--auto-progress --verbose
+    else
+      zope-testrunner --test-path=. --auto-color --auto-progress --verbose
+    fi
+
 after_success:
-    - if [[ "$WITH_COVERAGE" == "1" ]]; then coveralls; fi
-    - echo [distutils]                                  > ~/.pypirc
-    - echo index-servers = pypi                        >> ~/.pypirc
-    - echo [pypi]                                      >> ~/.pypirc
-    - echo username=zope.wheelbuilder                  >> ~/.pypirc
-    - echo password=$PYPIPASSWORD                      >> ~/.pypirc
-    - if [[ $TRAVIS_TAG && "$TRAVIS_OS_NAME" == "osx" ]]; then pip install 
twine; fi
-    - if [[ $TRAVIS_TAG && "$TRAVIS_OS_NAME" == "osx" ]]; then python setup.py 
bdist_wheel; fi
-    - if [[ $TRAVIS_TAG && "$TRAVIS_OS_NAME" == "osx" ]]; then twine upload 
dist/*; fi
+  - if [[ "$WITH_COVERAGE" == "1" ]]; then coveralls; fi
+  - |
+    if [[ $TRAVIS_TAG && "$TRAVIS_OS_NAME" == "osx" ]]; then
+      pip install twine
+      python setup.py bdist_wheel
+      TWINE_PASSWORD=$PYPIPASSWORD twine upload --skip-existing dist/*
+    fi
+  - |
+    if [[ $TRAVIS_TAG && -n "$DOCKER_IMAGE" ]]; then
+      pip install twine
+      TWINE_PASSWORD=$PYPIPASSWORD twine upload --skip-existing wheelhouse/*
+    fi
 
-env:
-    global:
-        secure: 
"Oh5gRJ+Fo8ZNmCkdrffpx201EPyTr9iUXmv6VqJMTebrzQpFdSWUVcANRmAzyfdyk3Wo0IjifVfWsKc+hvtbFmXZiLRFyEgoCUmzeWVumjebg2xxm0PbFHcRQgl4daBXxB0iqWkP8wXZ3daytuL74sYcbHizMYyhc7AxFbANsZc="
+notifications:
+  email: false
 
 cache: pip
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/BTrees.egg-info/PKG-INFO 
new/BTrees-4.6.1/BTrees.egg-info/PKG-INFO
--- old/BTrees-4.6.0/BTrees.egg-info/PKG-INFO   2019-07-30 10:36:54.000000000 
+0200
+++ new/BTrees-4.6.1/BTrees.egg-info/PKG-INFO   2019-11-07 17:39:48.000000000 
+0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: BTrees
-Version: 4.6.0
+Version: 4.6.1
 Summary: Scalable persistent object containers
 Home-page: https://github.com/zopefoundation/BTrees
 Author: Zope Foundation
@@ -39,6 +39,12 @@
         ``BTrees`` Changelog
         ====================
         
+        4.6.1 (2019-11-07)
+        ------------------
+        
+        - Add support for Python 3.8.
+        
+        
         4.6.0 (2019-07-30)
         ------------------
         
@@ -338,6 +344,7 @@
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Framework :: ZODB
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/BTrees.egg-info/SOURCES.txt 
new/BTrees-4.6.1/BTrees.egg-info/SOURCES.txt
--- old/BTrees-4.6.0/BTrees.egg-info/SOURCES.txt        2019-07-30 
10:36:54.000000000 +0200
+++ new/BTrees-4.6.1/BTrees.egg-info/SOURCES.txt        2019-11-07 
17:39:48.000000000 +0100
@@ -87,5 +87,6 @@
 docs/conf.py
 docs/index.rst
 docs/make.bat
+docs/overview.rst
 docs/_static/placeholder.txt
 docs/_templates/placeholder.txt
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/CHANGES.rst new/BTrees-4.6.1/CHANGES.rst
--- old/BTrees-4.6.0/CHANGES.rst        2019-07-30 10:36:48.000000000 +0200
+++ new/BTrees-4.6.1/CHANGES.rst        2019-11-07 17:39:45.000000000 +0100
@@ -1,6 +1,12 @@
 ``BTrees`` Changelog
 ====================
 
+4.6.1 (2019-11-07)
+------------------
+
+- Add support for Python 3.8.
+
+
 4.6.0 (2019-07-30)
 ------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/PKG-INFO new/BTrees-4.6.1/PKG-INFO
--- old/BTrees-4.6.0/PKG-INFO   2019-07-30 10:36:54.000000000 +0200
+++ new/BTrees-4.6.1/PKG-INFO   2019-11-07 17:39:49.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: BTrees
-Version: 4.6.0
+Version: 4.6.1
 Summary: Scalable persistent object containers
 Home-page: https://github.com/zopefoundation/BTrees
 Author: Zope Foundation
@@ -39,6 +39,12 @@
         ``BTrees`` Changelog
         ====================
         
+        4.6.1 (2019-11-07)
+        ------------------
+        
+        - Add support for Python 3.8.
+        
+        
         4.6.0 (2019-07-30)
         ------------------
         
@@ -338,6 +344,7 @@
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Framework :: ZODB
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/docs/api.rst 
new/BTrees-4.6.1/docs/api.rst
--- old/BTrees-4.6.0/docs/api.rst       2019-07-30 10:36:48.000000000 +0200
+++ new/BTrees-4.6.1/docs/api.rst       2019-11-07 17:39:45.000000000 +0100
@@ -1,5 +1,5 @@
-:mod:`BTrees` API Reference
-===========================
+API Reference
+=============
 
 
 Protocol APIs
@@ -106,3 +106,7 @@
      :members:
 
      .. automethod:: __call__
+
+
+.. automodule:: BTrees.check
+    :members:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/docs/conf.py 
new/BTrees-4.6.1/docs/conf.py
--- old/BTrees-4.6.0/docs/conf.py       2019-07-30 10:36:48.000000000 +0200
+++ new/BTrees-4.6.1/docs/conf.py       2019-11-07 17:39:45.000000000 +0100
@@ -98,7 +98,7 @@
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-html_theme = 'default'
+html_theme = 'sphinx_rtd_theme'
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
@@ -250,4 +250,8 @@
 
 
 # Example configuration for intersphinx: refer to the Python standard library.
-intersphinx_mapping = {'http://docs.python.org/': None}
+intersphinx_mapping = {
+    "python": ('https://docs.python.org/3/', None),
+    "persistent": ('https://persistent.readthedocs.io/en/latest/', None),
+    "ZODB": ("http://www.zodb.org/en/latest/";, None),
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/docs/index.rst 
new/BTrees-4.6.1/docs/index.rst
--- old/BTrees-4.6.0/docs/index.rst     2019-07-30 10:36:48.000000000 +0200
+++ new/BTrees-4.6.1/docs/index.rst     2019-11-07 17:39:45.000000000 +0100
@@ -11,452 +11,12 @@
 .. toctree::
    :maxdepth: 2
 
+   overview
    api
 
-Overview
---------
-
-When programming with the ZODB, Python dictionaries aren't always what you
-need.  The most important case is where you want to store a very large
-mapping.  When a Python dictionary is accessed in a ZODB, the whole
-dictionary has to be unpickled and brought into memory.  If you're storing
-something very large, such as a 100,000-entry user database, unpickling
-such a large object will be slow.  BTrees are a balanced tree data
-structure that behave like a mapping but distribute keys throughout a
-number of tree nodes.  The nodes are stored in sorted order (this has
-important consequences -- see below).  Nodes are then only unpickled and
-brought into memory as they're accessed, so the entire tree doesn't have to
-occupy memory (unless you really are touching every single key).
-
-The BTrees package provides a large collection of related data structures.
-There are variants of the data structures specialized to integers, which
-are faster and use less memory.  There are five modules that handle the
-different variants.  The first two letters of the module name specify the
-types of the keys and values in mappings -- O for any object, I for 32-bit
-signed integer, and (new in ZODB 3.4) F for 32-bit C float.  For example,
-the :mod:`BTrees.IOBTree` module provides a mapping with integer keys and
-arbitrary objects as values.
-
-The four data structures provide by each module are a BTree, a Bucket, a
-TreeSet, and a Set.  The BTree and Bucket types are mappings and support
-all the usual mapping methods, e.g. :func:`update` and :func:`keys`.  The
-TreeSet and Set types are similar to mappings but they have no values; they
-support the methods that make sense for a mapping with no keys, e.g.
-:func:`keys` but not :func:`items`.  The Bucket and Set types are the
-individual building blocks for BTrees and TreeSets, respectively.  A Bucket
-or Set can be used when you are sure that it will have few elements.  If
-the data structure will grow large, you should use a BTree or TreeSet. Like
-Python lists, Buckets and Sets are allocated in one contiguous piece, and
-insertions and deletions can take time proportional to the number of
-existing elements.  Also like Python lists, a Bucket or Set is a single
-object, and is pickled and unpickled in its entirety.  BTrees and TreeSets
-are multi-level tree structures with much better (logarithmic) worst- case
-time bounds, and the tree structure is built out of multiple objects, which
-ZODB can load individually as needed.
-
-The five modules are named :mod:`OOBTree`, :mod:`IOBTree`, :mod:`OIBTree`,
-:mod:`IIBTree`, and (new in ZODB 3.4) :mod:`IFBTree`.  The two letter
-prefixes are repeated in the data types names.  The :mod:`BTrees.OOBTree`
-module defines the following types: :class:`OOBTree`, :class:`OOBucket`,
-:class:`OOSet`, and :class:`OOTreeSet`. Similarly, the other four modules
-each define their own variants of those four types.
-
-The :func:`keys`, :func:`values`, and :func:`items` methods on BTree and
-TreeSet types do not materialize a list with all of the data.  Instead,
-they return lazy sequences that fetch data from the BTree as needed.  They
-also support optional arguments to specify the minimum and maximum values
-to return, often called "range searching".  Because all these types are
-stored in sorted order, range searching is very efficient.
-
-The :func:`keys`, :func:`values`, and :func:`items` methods on Bucket and
-Set types do return lists with all the data. Starting in ZODB 3.3, there
-are also :func:`iterkeys`, :func:`itervalues`, and :func:`iteritems`
-methods that return iterators (in the Python 2.2 sense).  Those methods
-also apply to BTree and TreeSet objects.
-
-A BTree object supports all the methods you would expect of a mapping, with
-a few extensions that exploit the fact that the keys are sorted. The
-example below demonstrates how some of the methods work.  The extra methods
-are :func:`minKey` and :func:`maxKey`, which find the minimum and maximum
-key value subject to an optional bound argument, and :func:`byValue`, which
-should probably be ignored (it's hard to explain exactly what it does, and
-as a result it's almost never used -- best to consider it deprecated).  The
-various methods for enumerating keys, values and items also accept minimum
-and maximum key arguments ("range search"), and (new in ZODB 3.3) optional
-Boolean arguments to control whether a range search is inclusive or
-exclusive of the range's endpoints.
-
-.. doctest::
-
-   >>> from BTrees.OOBTree import OOBTree
-   >>> t = OOBTree()
-   >>> t.update({1: "red", 2: "green", 3: "blue", 4: "spades"})
-   >>> len(t)
-   4
-   >>> t[2]
-   'green'
-   >>> s = t.keys() # this is a "lazy" sequence object
-   >>> s
-   <OOBTreeItems object at ...>
-   >>> len(s)  # it acts like a Python list
-   4
-   >>> s[-2]
-   3
-   >>> list(s) # materialize the full list
-   [1, 2, 3, 4]
-   >>> list(t.values())
-   ['red', 'green', 'blue', 'spades']
-   >>> list(t.values(1, 2)) # values at keys in 1 to 2 inclusive
-   ['red', 'green']
-   >>> list(t.values(2))    # values at keys >= 2
-   ['green', 'blue', 'spades']
-   >>> list(t.values(min=1, max=4))  # keyword args new in ZODB 3.3
-   ['red', 'green', 'blue', 'spades']
-   >>> list(t.values(min=1, max=4, excludemin=True, excludemax=True))
-   ['green', 'blue']
-   >>> t.minKey()     # smallest key
-   1
-   >>> t.minKey(1.5)  # smallest key >= 1.5
-   2
-   >>> for k in t.keys():
-   ...     print k,
-   1 2 3 4
-   >>> for k in t:    # new in ZODB 3.3
-   ...     print k,
-   1 2 3 4
-   >>> for pair in t.iteritems():  # new in ZODB 3.3
-   ...     print pair,
-   ...
-   (1, 'red') (2, 'green') (3, 'blue') (4, 'spades')
-   >>> t.has_key(4)  # returns a true value, but exactly what undefined
-   2
-   >>> t.has_key(5)
-   0
-   >>> 4 in t  # new in ZODB 3.3
-   True
-   >>> 5 in t  # new in ZODB 3.3
-   False
-   >>>
-
-
-Each of the modules also defines some functions that operate on BTrees --
-:func:`difference`, :func:`union`, and :func:`intersection`.  The
-:func:`difference` function returns a Bucket, while the other two methods 
return
-a Set. If the keys are integers, then the module also defines
-:func:`multiunion`.  If the values are integers or floats, then the module also
-defines :func:`weightedIntersection` and :func:`weightedUnion`.  The function
-doc strings describe each function briefly.
-
-.. % XXX I'm not sure all of the following is actually correct.  The
-.. % XXX set functions have complicated behavior.
-
-``BTrees/Interfaces.py`` defines the operations, and is the official
-documentation.  Note that the interfaces don't define the concrete types
-returned by most operations, and you shouldn't rely on the concrete types that
-happen to be returned:  stick to operations guaranteed by the interface.  In
-particular, note that the interfaces don't specify anything about comparison
-behavior, and so nothing about it is guaranteed.  In ZODB 3.3, for example, two
-BTrees happen to use Python's default object comparison, which amounts to
-comparing the (arbitrary but fixed) memory addresses of the BTrees. This may or
-may not be true in future releases. If the interfaces don't specify a behavior,
-then whether that behavior appears to work, and exactly happens if it does
-appear to work, are undefined and should not be relied on.
-
-
-Total Ordering and Persistence
-------------------------------
-
-The BTree-based data structures differ from Python dicts in several fundamental
-ways.  One of the most important is that while dicts require that keys support
-hash codes and equality comparison, the BTree-based structures don't use hash
-codes and require a total ordering on keys.
-
-Total ordering means three things:
-
-#. Reflexive.  For each *x*, ``x == x`` is true.
-
-#. Trichotomy.  For each *x* and *y*, exactly one of ``x < y``, ``x == y``, and
-   ``x > y`` is true.
-
-#. Transitivity.  Whenever ``x <= y`` and ``y <= z``, it's also true that ``x 
<=
-   z``.
-
-The default comparison functions for most objects that come with Python satisfy
-these rules, with some crucial cautions explained later.  Complex numbers are 
an
-example of an object whose default comparison function does not satisfy these
-rules:  complex numbers only support ``==`` and ``!=`` comparisons, and raise 
an
-exception if you try to compare them in any other way.  They don't satisfy the
-trichotomy rule, and must not be used as keys in BTree-based data structures
-(although note that complex numbers can be used as keys in Python dicts, which
-do not require a total ordering).
-
-Examples of objects that are wholly safe to use as keys in BTree-based
-structures include ints, longs, floats, 8-bit strings, Unicode strings, and
-tuples composed (possibly recursively) of objects of wholly safe types.
-
-It's important to realize that even if two types satisfy the rules on their 
own,
-mixing objects of those types may not.  For example, 8-bit strings and Unicode
-strings both supply total orderings, but mixing the two loses trichotomy; e.g.,
-``'x' < chr(255)`` and ``u'x' == 'x'``, but trying to compare ``chr(255)`` to
-``u'x'`` raises an exception.  Partly for this reason (another is given later),
-it can be dangerous to use keys with multiple types in a single BTree-based
-structure.  Don't try to do that, and you don't have to worry about it.
-
-Another potential problem is mutability:  when a key is inserted in a BTree-
-based structure, it must retain the same order relative to the other keys over
-time.  This is easy to run afoul of if you use mutable objects as keys.  For
-example, lists supply a total ordering, and then 
-
-.. doctest::
-
-   >>> L1, L2, L3 = [1], [2], [3]
-   >>> from BTrees.OOBTree import OOSet
-   >>> s = OOSet((L2, L3, L1))  # this is fine, so far
-   >>> list(s.keys())           # note that the lists are in sorted order
-   [[1], [2], [3]]
-   >>> s.has_key([3])           # and [3] is in the set
-   1
-   >>> L2[0] = 5                # horrible -- the set is insane now
-   >>> s.has_key([3])           # for example, it's insane this way
-   0
-   >>> s
-   OOSet([[1], [5], [3]])
-   >>>
-
-Key lookup relies on that the keys remain in sorted order (an efficient form of
-binary search is used).  By mutating key L2 after inserting it, we destroyed 
the
-invariant that the OOSet is sorted.  As a result, all future operations on this
-set are unpredictable.
-
-A subtler variant of this problem arises due to persistence:  by default, 
Python
-does several kinds of comparison by comparing the memory addresses of two
-objects.  Because Python never moves an object in memory, this does supply a
-usable (albeit arbitrary) total ordering across the life of a program run (an
-object's memory address doesn't change).  But if objects compared in this way
-are used as keys of a BTree-based structure that's stored in a database, when
-the objects are loaded from the database again they will almost certainly wind
-up at different memory addresses.  There's no guarantee then that if key K1 had
-a memory address smaller than the memory address of key K2 at the time K1 and 
K2
-were inserted in a BTree, K1's address will also be smaller than K2's when that
-BTree is loaded from a database later.  The result will be an insane BTree,
-where various operations do and don't work as expected, seemingly at random.
-
-Now each of the types identified above as "wholly safe to use" never compares
-two instances of that type by memory address, so there's nothing to worry about
-here if you use keys of those types.  The most common mistake is to use keys
-that are instances of a user-defined class that doesn't supply its own
-:meth:`__cmp__` method.  Python compares such instances by memory address.  
This
-is fine if such instances are used as keys in temporary BTree-based structures
-used only in a single program run.  It can be disastrous if that BTree-based
-structure is stored to a database, though. 
-
-.. doctest::
-   :options: +SKIP
-
-   >>> class C:
-   ...     pass
-   ...
-   >>> a, b = C(), C()
-   >>> print a < b   # this may print 0 if you try it
-   True
-   >>> del a, b
-   >>> a, b = C(), C()
-   >>> print a < b   # and this may print 0 or 1
-   False
-   >>>
-
-That example illustrates that comparison of instances of classes that don't
-define :meth:`__cmp__` yields arbitrary results (but consistent results within 
a
-single program run).
-
-Another problem occurs with instances of classes that do define 
:meth:`__cmp__`,
-but define it incorrectly.  It's possible but rare for a custom :meth:`__cmp__`
-implementation to violate one of the three required formal properties directly.
-It's more common for it to "fall back" to address-based comparison by mistake.
-For example, 
-
-.. doctest::
-
-   class Mine:
-       def __cmp__(self, other):
-           if other.__class__ is Mine:
-               return cmp(self.data, other.data)
-           else:
-               return cmp(self.data, other)
-
-It's quite possible there that the :keyword:`else` clause allows a result to be
-computed based on memory address.  The bug won't show up until a BTree-based
-structure uses objects of class :class:`Mine` as keys, and also objects of 
other
-types as keys, and the structure is loaded from a database, and a sequence of
-comparisons happens to execute the :keyword:`else` clause in a case where the
-relative order of object memory addresses happened to change.
-
-This is as difficult to track down as it sounds, so best to stay far away from
-the possibility.
-
-You'll stay out of trouble by follwing these rules, violating them only with
-great care:
-
-#. Use objects of simple immutable types as keys in BTree-based data 
structures.
-
-#. Within a single BTree-based data structure, use objects of a single type as
-   keys.  Don't use multiple key types in a single structure.
-
-#. If you want to use class instances as keys, and there's any possibility that
-   the structure may be stored in a database, it's crucial that the class 
define a
-   :meth:`__cmp__` method, and that the method is carefully implemented.
-
-   Any part of a comparison implementation that relies (explicitly or 
implicitly)
-   on an address-based comparison result will eventually cause serious failure.
-
-#. Do not use :class:`Persistent` objects as keys, or objects of a subclass of
-   :class:`Persistent`.
-
-That last item may be surprising.  It stems from details of how conflict
-resolution is implemented:  the states passed to conflict resolution do not
-materialize persistent subobjects (if a persistent object P is a key in a 
BTree,
-then P is a subobject of the bucket containing P).  Instead, if an object O
-references a persistent subobject P directly, and O is involved in a conflict,
-the states passed to conflict resolution contain an instance of an internal
-:class:`PersistentReference` stub class everywhere O references P. Two
-:class:`PersistentReference` instances compare equal if and only if they
-"represent" the same persistent object; when they're not equal, they compare by
-memory address, and, as explained before, memory-based comparison must never
-happen in a sane persistent BTree.  Note that it doesn't help in this case if
-your :class:`Persistent` subclass defines a sane :meth:`__cmp__` method:
-conflict resolution doesn't know about your class, and so also doesn't know
-about its :meth:`__cmp__` method.  It only sees instances of the internal
-:class:`PersistentReference` stub class.
-
-
-Iteration and Mutation
-----------------------
-
-As with a Python dictionary or list, you should not mutate a BTree-based data
-structure while iterating over it, except that it's fine to replace the value
-associated with an existing key while iterating.  You won't create internal
-damage in the structure if you try to remove, or add new keys, while iterating,
-but the results are undefined and unpredictable.  A weak attempt is made to
-raise :exc:`RuntimeError` if the size of a BTree-based structure changes while
-iterating, but it doesn't catch most such cases, and is also unreliable.
-Example
-
-.. doctest::
-   :options: +SKIP
-
-   >>> from BTrees.IIBTree import *
-   >>> s = IISet(range(10))
-   >>> list(s)
-   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-   >>> for i in s:  # the output is undefined
-   ...     print i,
-   ...     s.remove(i)
-   0 2 4 6 8
-   Traceback (most recent call last):
-     File "<stdin>", line 1, in ?
-   RuntimeError: the bucket being iterated changed size
-   >>> list(s)      # this output is also undefined
-   [1, 3, 5, 7, 9]
-   >>>
-
-Also as with Python dictionaries and lists, the safe and predictable way to
-mutate a BTree-based structure while iterating over it is to iterate over a 
copy
-of the keys.  Example
-
-.. doctest::
-
-   >>> from BTrees.IIBTree import *
-   >>> s = IISet(range(10))
-   >>> for i in list(s.keys()):  # this is well defined
-   ...     print i,
-   ...     s.remove(i)
-   0 1 2 3 4 5 6 7 8 9
-   >>> list(s)
-   []
-   >>>
-
-BTree node sizes
-----------------
-
-BTrees (and TreeSets) are made up of a tree of Buckets (and Sets) and
-internal nodes.  There are maximum sizes of these notes configured for
-the various key and value types:
-
-======== ========== ========================== =============================
-Key Type Value Type Maximum Bucket or Set Size Maximum BTree or TreeSet Size
-======== ========== ========================== =============================
-Integer  Float      120                        500
-Integer  Integer    120                        500
-Integer  Object     60                         500
-Long     Float      120                        500
-Long     Long       120                        500
-Long     Object     60                         500
-Object   Integer    60                         250
-Object   Long       60                         250
-Object   Object     30                         250
-======== ========== ========================== =============================
-
-For your application, especially when using object keys or values, you
-may want to override the default sizes.  You can do this by
-subclassing any of the BTree (or TreeSet) classes and specifying new
-values for ``max_leaf_size`` or ``max_internal_size`` in your subclass::
-
-     import BTrees.OOBTree
-
-     class MyBTree(BTrees.OOBTree.BTree):
-         max_leaf_size = 500
-         max_internal_size = 1000
-
-``max_leaf_size`` is used for leaf nodes in a BTree, either Buckets or
-Sets.  ``max_internal_size`` is used for internal nodes, either BTrees
-or TreeSets.
-
-BTree Diagnostic Tools
-----------------------
-
-A BTree (or TreeSet) is a complex data structure, really a graph of variable-
-size nodes, connected in multiple ways via three distinct kinds of C pointers.
-There are some tools available to help check internal consistency of a BTree as
-a whole.
-
-Most generally useful is the :mod:`BTrees.check` module.  The
-:func:`check.check` function examines a BTree (or Bucket, Set, or TreeSet) for
-value-based consistency, such as that the keys are in strictly increasing 
order.
-See the function docstring for details. The :func:`check.display` function
-displays the internal structure of a BTree.
-
-BTrees and TreeSets also have a :meth:`_check` method.  This verifies that the
-(possibly many) internal pointers in a BTree or TreeSet are mutually 
consistent,
-and raises :exc:`AssertionError` if they're not.
-
-If a :func:`check.check` or :meth:`_check` call fails, it may point to a bug in
-the implementation of BTrees or conflict resolution, or may point to database
-corruption.
-
-Repairing a damaged BTree is usually best done by making a copy of it. For
-example, if *self.data* is bound to a corrupted IOBTree, 
-
-.. doctest::
-
-   self.data = IOBTree(self.data)
-
-usually suffices.  If object identity needs to be preserved, 
-
-.. doctest::
-
-   acopy = IOBTree(self.data)
-   self.data.clear()
-   self.data.update(acopy)
-
-does the same, but leaves *self.data* bound to the same object.
-
-
-
-
 Indices and tables
 ==================
 
 * :ref:`genindex`
 * :ref:`modindex`
 * :ref:`search`
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/docs/overview.rst 
new/BTrees-4.6.1/docs/overview.rst
--- old/BTrees-4.6.0/docs/overview.rst  1970-01-01 01:00:00.000000000 +0100
+++ new/BTrees-4.6.1/docs/overview.rst  2019-11-07 17:39:45.000000000 +0100
@@ -0,0 +1,447 @@
+Overview
+========
+
+When programming with the ZODB, Python dictionaries aren't always what you
+need.  The most important case is where you want to store a very large
+mapping.  When a Python dictionary is accessed in a ZODB, the whole
+dictionary has to be unpickled and brought into memory.  If you're storing
+something very large, such as a 100,000-entry user database, unpickling
+such a large object will be slow. BTrees are a balanced tree data
+structure that behave like a mapping but distribute keys throughout a
+number of tree nodes.  The nodes are stored in sorted order (this has
+important consequences -- see below).  Nodes are then only unpickled and
+brought into memory as they're accessed, so the entire tree doesn't have to
+occupy memory (unless you really are touching every single key).
+
+The BTrees package provides a large collection of related data structures.
+There are variants of the data structures specialized to integers, which
+are faster and use less memory.  There are five modules that handle the
+different variants.  The first two letters of the module name specify the
+types of the keys and values in mappings -- O for any object, I for 32-bit
+signed integer, and (new in ZODB 3.4) F for 32-bit C float.  For example,
+the :mod:`BTrees.IOBTree` module provides a mapping with integer keys and
+arbitrary objects as values.
+
+The four data structures provide by each module are a BTree, a Bucket, a
+TreeSet, and a Set.  The BTree and Bucket types are mappings and support
+all the usual mapping methods, e.g. 
:func:`~BTrees.Interfaces.ISetMutable.update` and 
:func:`~BTrees.Interfaces.IKeyed.keys`.  The
+TreeSet and Set types are similar to mappings but they have no values; they
+support the methods that make sense for a mapping with no keys, e.g.
+:func:`~BTrees.Interfaces.IKeyed.keys` but not 
:func:`~BTrees.Interfaces.IMinimalDictionary.items`.  The Bucket and Set types 
are the
+individual building blocks for BTrees and TreeSets, respectively.  A Bucket
+or Set can be used when you are sure that it will have few elements.  If
+the data structure will grow large, you should use a BTree or TreeSet. Like
+Python lists, Buckets and Sets are allocated in one contiguous piece, and
+insertions and deletions can take time proportional to the number of
+existing elements.  Also like Python lists, a Bucket or Set is a single
+object, and is pickled and unpickled in its entirety.  BTrees and TreeSets
+are multi-level tree structures with much better (logarithmic) worst- case
+time bounds, and the tree structure is built out of multiple objects, which
+ZODB can load individually as needed.
+
+The five modules are named :mod:`~BTrees.OOBTree`, :mod:`~BTrees.IOBTree`, 
:mod:`~BTrees.OIBTree`,
+:mod:`~BTrees.IIBTree`, and (new in ZODB 3.4) :mod:`~BTrees.IFBTree`.  The two 
letter
+prefixes are repeated in the data types names.  The :mod:`~BTrees.OOBTree`
+module defines the following types: :class:`~BTrees.OOBTree.OOBTree`, 
:class:`~BTrees.OOBTree.OOBucket`,
+:class:`~BTrees.OOBTree.OOSet`, and :class:`~BTrees.OOBTree.OOTreeSet`. 
Similarly, the other four modules
+each define their own variants of those four types.
+
+The :func:`keys`, :func:`values`, and :func:`items` methods on BTree and
+TreeSet types do not materialize a list with all of the data.  Instead,
+they return lazy sequences that fetch data from the BTree as needed.  They
+also support optional arguments to specify the minimum and maximum values
+to return, often called "range searching".  Because all these types are
+stored in sorted order, range searching is very efficient.
+
+The :func:`keys`, :func:`values`, and :func:`items` methods on Bucket and
+Set types do return lists with all the data. Starting in ZODB 3.3, there
+are also :func:`iterkeys`, :func:`itervalues`, and :func:`iteritems`
+methods that return iterators (in the Python 2.2 sense).  Those methods
+also apply to BTree and TreeSet objects.
+
+A BTree object supports all the methods you would expect of a mapping, with
+a few extensions that exploit the fact that the keys are sorted. The
+example below demonstrates how some of the methods work.  The extra methods
+are :func:`minKey` and :func:`maxKey`, which find the minimum and maximum
+key value subject to an optional bound argument, and :func:`byValue`, which
+should probably be ignored (it's hard to explain exactly what it does, and
+as a result it's almost never used -- best to consider it deprecated).  The
+various methods for enumerating keys, values and items also accept minimum
+and maximum key arguments ("range search"), and (new in ZODB 3.3) optional
+Boolean arguments to control whether a range search is inclusive or
+exclusive of the range's endpoints.
+
+.. doctest::
+
+   >>> from BTrees.OOBTree import OOBTree
+   >>> t = OOBTree()
+   >>> t.update({1: "red", 2: "green", 3: "blue", 4: "spades"})
+   >>> len(t)
+   4
+   >>> t[2]
+   'green'
+   >>> s = t.keys() # this is a "lazy" sequence object
+   >>> s
+   <OOBTreeItems object at ...>
+   >>> len(s)  # it acts like a Python list
+   4
+   >>> s[-2]
+   3
+   >>> list(s) # materialize the full list
+   [1, 2, 3, 4]
+   >>> list(t.values())
+   ['red', 'green', 'blue', 'spades']
+   >>> list(t.values(1, 2)) # values at keys in 1 to 2 inclusive
+   ['red', 'green']
+   >>> list(t.values(2))    # values at keys >= 2
+   ['green', 'blue', 'spades']
+   >>> list(t.values(min=1, max=4))  # keyword args new in ZODB 3.3
+   ['red', 'green', 'blue', 'spades']
+   >>> list(t.values(min=1, max=4, excludemin=True, excludemax=True))
+   ['green', 'blue']
+   >>> t.minKey()     # smallest key
+   1
+   >>> t.minKey(1.5)  # smallest key >= 1.5
+   2
+   >>> [k for k in t.keys()]
+   [1, 2, 3, 4]
+   >>> [k for k in t]    # new in ZODB 3.3
+   [1, 2, 3, 4]
+   >>> [pair for pair in t.iteritems()]  # new in ZODB 3.3
+   [(1, 'red'), (2, 'green'), (3, 'blue'), (4, 'spades')]
+   >>> t.has_key(4)  # returns a true value, but exactly what undefined
+   2
+   >>> t.has_key(5)
+   0
+   >>> 4 in t  # new in ZODB 3.3
+   True
+   >>> 5 in t  # new in ZODB 3.3
+   False
+   >>>
+
+
+Each of the modules also defines some functions that operate on BTrees --
+:func:`~BTrees._base.difference`, :func:`~BTrees._base.union`, and 
:func:`~BTrees._base.intersection`.  The
+:func:`~BTrees._base.difference` function returns a Bucket, while the other 
two methods return
+a Set. If the keys are integers, then the module also defines
+:func:`~BTrees._base.multiunion`.  If the values are integers or floats, then 
the module also
+defines :func:`~BTrees._base.weightedIntersection` and 
:func:`~BTrees._base.weightedUnion`.  The function
+doc strings describe each function briefly.
+
+.. % XXX I'm not sure all of the following is actually correct.  The
+.. % XXX set functions have complicated behavior.
+
+:mod:`~BTrees.Interfaces` defines the operations, and is the official
+documentation.  Note that the interfaces don't define the concrete types
+returned by most operations, and you shouldn't rely on the concrete types that
+happen to be returned:  stick to operations guaranteed by the interface.  In
+particular, note that the interfaces don't specify anything about comparison
+behavior, and so nothing about it is guaranteed.  In ZODB 3.3, for example, two
+BTrees happen to use Python's default object comparison, which amounts to
+comparing the (arbitrary but fixed) memory addresses of the BTrees. This may or
+may not be true in future releases. If the interfaces don't specify a behavior,
+then whether that behavior appears to work, and exactly happens if it does
+appear to work, are undefined and should not be relied on.
+
+
+Total Ordering and Persistence
+------------------------------
+
+The BTree-based data structures differ from Python dicts in several fundamental
+ways.  One of the most important is that while dicts require that keys support
+hash codes and equality comparison, the BTree-based structures don't use hash
+codes and require a total ordering on keys.
+
+Total ordering means three things:
+
+#. Reflexive.  For each *x*, ``x == x`` is true.
+
+#. Trichotomy.  For each *x* and *y*, exactly one of ``x < y``, ``x == y``, and
+   ``x > y`` is true.
+
+#. Transitivity.  Whenever ``x <= y`` and ``y <= z``, it's also true that ``x 
<=
+   z``.
+
+The default comparison functions for most objects that come with Python satisfy
+these rules, with some crucial cautions explained later.  Complex numbers are 
an
+example of an object whose default comparison function does not satisfy these
+rules:  complex numbers only support ``==`` and ``!=`` comparisons, and raise 
an
+exception if you try to compare them in any other way.  They don't satisfy the
+trichotomy rule, and must not be used as keys in BTree-based data structures
+(although note that complex numbers can be used as keys in Python dicts, which
+do not require a total ordering).
+
+Examples of objects that are wholly safe to use as keys in BTree-based
+structures include ints, longs, floats, 8-bit strings, Unicode strings, and
+tuples composed (possibly recursively) of objects of wholly safe types.
+
+It's important to realize that even if two types satisfy the rules on their 
own,
+mixing objects of those types may not.  For example, 8-bit strings and Unicode
+strings both supply total orderings, but mixing the two loses trichotomy; e.g.,
+``'x' < chr(255)`` and ``u'x' == 'x'``, but trying to compare ``chr(255)`` to
+``u'x'`` raises an exception.  Partly for this reason (another is given later),
+it can be dangerous to use keys with multiple types in a single BTree-based
+structure.  Don't try to do that, and you don't have to worry about it.
+
+Another potential problem is mutability:  when a key is inserted in a BTree-
+based structure, it must retain the same order relative to the other keys over
+time.  This is easy to run afoul of if you use mutable objects as keys.  For
+example, lists supply a total ordering, and then
+
+.. doctest::
+
+   >>> L1, L2, L3 = [1], [2], [3]
+   >>> from BTrees.OOBTree import OOSet
+   >>> s = OOSet((L2, L3, L1))  # this is fine, so far
+   >>> list(s.keys())           # note that the lists are in sorted order
+   [[1], [2], [3]]
+   >>> s.has_key([3])           # and [3] is in the set
+   1
+   >>> L2[0] = 5                # horrible -- the set is insane now
+   >>> s.has_key([3])           # for example, it's insane this way
+   0
+   >>> s
+   OOSet([[1], [5], [3]])
+   >>>
+
+Key lookup relies on that the keys remain in sorted order (an efficient form of
+binary search is used).  By mutating key L2 after inserting it, we destroyed 
the
+invariant that the OOSet is sorted.  As a result, all future operations on this
+set are unpredictable.
+
+A subtler variant of this problem arises due to persistence:  by default, 
Python
+does several kinds of comparison by comparing the memory addresses of two
+objects.  Because Python never moves an object in memory, this does supply a
+usable (albeit arbitrary) total ordering across the life of a program run (an
+object's memory address doesn't change).  But if objects compared in this way
+are used as keys of a BTree-based structure that's stored in a database, when
+the objects are loaded from the database again they will almost certainly wind
+up at different memory addresses.  There's no guarantee then that if key K1 had
+a memory address smaller than the memory address of key K2 at the time K1 and 
K2
+were inserted in a BTree, K1's address will also be smaller than K2's when that
+BTree is loaded from a database later.  The result will be an insane BTree,
+where various operations do and don't work as expected, seemingly at random.
+
+Now each of the types identified above as "wholly safe to use" never compares
+two instances of that type by memory address, so there's nothing to worry about
+here if you use keys of those types.  The most common mistake is to use keys
+that are instances of a user-defined class that doesn't supply its own
+:meth:`__cmp__` method.  Python compares such instances by memory address.  
This
+is fine if such instances are used as keys in temporary BTree-based structures
+used only in a single program run.  It can be disastrous if that BTree-based
+structure is stored to a database, though.
+
+.. doctest::
+   :options: +SKIP
+
+   >>> class C:
+   ...     pass
+   ...
+   >>> a, b = C(), C()
+   >>> print(a < b)   # this may print 0 if you try it
+   True
+   >>> del a, b
+   >>> a, b = C(), C()
+   >>> print(a < b)   # and this may print 0 or 1
+   False
+   >>>
+
+That example illustrates that comparison of instances of classes that don't
+define :meth:`__cmp__` yields arbitrary results (but consistent results within 
a
+single program run).
+
+Another problem occurs with instances of classes that do define 
:meth:`__cmp__`,
+but define it incorrectly.  It's possible but rare for a custom :meth:`__cmp__`
+implementation to violate one of the three required formal properties directly.
+It's more common for it to "fall back" to address-based comparison by mistake.
+For example,
+
+.. doctest::
+
+   >>> class Mine:
+   ...     def __cmp__(self, other):
+   ...         if other.__class__ is Mine:
+   ...             return cmp(self.data, other.data)
+   ...         else:
+   ...             return cmp(self.data, other)
+
+It's quite possible there that the :keyword:`else` clause allows a result to be
+computed based on memory address.  The bug won't show up until a BTree-based
+structure uses objects of class :class:`Mine` as keys, and also objects of 
other
+types as keys, and the structure is loaded from a database, and a sequence of
+comparisons happens to execute the :keyword:`else` clause in a case where the
+relative order of object memory addresses happened to change.
+
+This is as difficult to track down as it sounds, so best to stay far away from
+the possibility.
+
+You'll stay out of trouble by follwing these rules, violating them only with
+great care:
+
+#. Use objects of simple immutable types as keys in BTree-based data 
structures.
+
+#. Within a single BTree-based data structure, use objects of a single type as
+   keys.  Don't use multiple key types in a single structure.
+
+#. If you want to use class instances as keys, and there's any possibility that
+   the structure may be stored in a database, it's crucial that the class 
define a
+   :meth:`__cmp__` method, and that the method is carefully implemented.
+
+   Any part of a comparison implementation that relies (explicitly or 
implicitly)
+   on an address-based comparison result will eventually cause serious failure.
+
+#. Do not use :class:`~persistent.Persistent` objects as keys, or objects of a 
subclass of
+   :class:`~persistent.Persistent`.
+
+That last item may be surprising.  It stems from details of how conflict
+resolution is implemented:  the states passed to conflict resolution do not
+materialize persistent subobjects (if a persistent object P is a key in a 
BTree,
+then P is a subobject of the bucket containing P).  Instead, if an object O
+references a persistent subobject P directly, and O is involved in a conflict,
+the states passed to conflict resolution contain an instance of an internal
+:class:`~persistent.PersistentReference` stub class everywhere O references P. 
Two
+:class:`~persistent.PersistentReference` instances compare equal if and only 
if they
+"represent" the same persistent object; when they're not equal, they compare by
+memory address, and, as explained before, memory-based comparison must never
+happen in a sane persistent BTree.  Note that it doesn't help in this case if
+your :class:`~persistent.Persistent` subclass defines a sane :meth:`__cmp__` 
method:
+conflict resolution doesn't know about your class, and so also doesn't know
+about its :meth:`__cmp__` method.  It only sees instances of the internal
+:class:`~persistent.PersistentReference` stub class.
+
+
+Iteration and Mutation
+----------------------
+
+As with a Python dictionary or list, you should not mutate a BTree-based data
+structure while iterating over it, except that it's fine to replace the value
+associated with an existing key while iterating.  You won't create internal
+damage in the structure if you try to remove, or add new keys, while iterating,
+but the results are undefined and unpredictable.  A weak attempt is made to
+raise :exc:`RuntimeError` if the size of a BTree-based structure changes while
+iterating, but it doesn't catch most such cases, and is also unreliable.
+Example
+
+.. doctest::
+   :options: +SKIP
+
+   >>> from BTrees.IIBTree import *
+   >>> s = IISet(range(10))
+   >>> list(s)
+   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+   >>> for i in s:  # the output is undefined
+   ...     print(i)
+   ...     s.remove(i)
+   0
+   2
+   4
+   6
+   8
+   Traceback (most recent call last):
+     File "<stdin>", line 1, in ?
+   RuntimeError: the bucket being iterated changed size
+   >>> list(s)      # this output is also undefined
+   [1, 3, 5, 7, 9]
+   >>>
+
+Also as with Python dictionaries and lists, the safe and predictable way to
+mutate a BTree-based structure while iterating over it is to iterate over a 
copy
+of the keys.  Example
+
+.. doctest::
+
+   >>> from BTrees.IIBTree import *
+   >>> s = IISet(range(10))
+   >>> for i in list(s.keys()):  # this is well defined
+   ...     print(i)
+   ...     s.remove(i)
+   0
+   1
+   2
+   3
+   4
+   5
+   6
+   7
+   8
+   9
+   >>> list(s)
+   []
+   >>>
+
+BTree node sizes
+----------------
+
+BTrees (and TreeSets) are made up of a tree of Buckets (and Sets) and
+internal nodes.  There are maximum sizes of these notes configured for
+the various key and value types:
+
+======== ========== ========================== =============================
+Key Type Value Type Maximum Bucket or Set Size Maximum BTree or TreeSet Size
+======== ========== ========================== =============================
+Integer  Float      120                        500
+Integer  Integer    120                        500
+Integer  Object     60                         500
+Long     Float      120                        500
+Long     Long       120                        500
+Long     Object     60                         500
+Object   Integer    60                         250
+Object   Long       60                         250
+Object   Object     30                         250
+======== ========== ========================== =============================
+
+For your application, especially when using object keys or values, you
+may want to override the default sizes.  You can do this by
+subclassing any of the BTree (or TreeSet) classes and specifying new
+values for ``max_leaf_size`` or ``max_internal_size`` in your subclass::
+
+     >>> import BTrees.OOBTree
+
+     >>> class MyBTree(BTrees.OOBTree.BTree):
+     ...     max_leaf_size = 500
+     ...     max_internal_size = 1000
+
+``max_leaf_size`` is used for leaf nodes in a BTree, either Buckets or
+Sets.  ``max_internal_size`` is used for internal nodes, either BTrees
+or TreeSets.
+
+BTree Diagnostic Tools
+----------------------
+
+A BTree (or TreeSet) is a complex data structure, really a graph of variable-
+size nodes, connected in multiple ways via three distinct kinds of C pointers.
+There are some tools available to help check internal consistency of a BTree as
+a whole.
+
+Most generally useful is the :mod:`~BTrees.check` module.  The
+:func:`~BTrees.check.check` function examines a BTree (or Bucket, Set, or 
TreeSet) for
+value-based consistency, such as that the keys are in strictly increasing 
order.
+See the function docstring for details. The :func:`~BTrees.check.display` 
function
+displays the internal structure of a BTree.
+
+BTrees and TreeSets also have a :meth:`_check` method.  This verifies that the
+(possibly many) internal pointers in a BTree or TreeSet are mutually 
consistent,
+and raises :exc:`AssertionError` if they're not.
+
+If a :func:`~BTrees.check.check` or :meth:`_check` call fails, it may point to 
a bug in
+the implementation of BTrees or conflict resolution, or may point to database
+corruption.
+
+Repairing a damaged BTree is usually best done by making a copy of it. For
+example, if *self.data* is bound to a corrupted IOBTree,
+
+.. doctest::
+   :options: +SKIP
+
+   >>> self.data = IOBTree(self.data)
+
+usually suffices.  If object identity needs to be preserved,
+
+.. doctest::
+   :options: +SKIP
+
+   >>> acopy = IOBTree(self.data)
+   >>> self.data.clear()
+   >>> self.data.update(acopy)
+
+does the same, but leaves *self.data* bound to the same object.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/setup.py new/BTrees-4.6.1/setup.py
--- old/BTrees-4.6.0/setup.py   2019-07-30 10:36:48.000000000 +0200
+++ new/BTrees-4.6.1/setup.py   2019-11-07 17:39:45.000000000 +0100
@@ -12,7 +12,7 @@
 #
 ##############################################################################
 from __future__ import print_function
-version = '4.6.0'
+version = '4.6.1'
 
 import os
 import sys
@@ -159,6 +159,7 @@
           "Programming Language :: Python :: 3.5",
           "Programming Language :: Python :: 3.6",
           "Programming Language :: Python :: 3.7",
+          "Programming Language :: Python :: 3.8",
           "Programming Language :: Python :: Implementation :: CPython",
           "Programming Language :: Python :: Implementation :: PyPy",
           "Framework :: ZODB",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/BTrees-4.6.0/tox.ini new/BTrees-4.6.1/tox.ini
--- old/BTrees-4.6.0/tox.ini    2019-07-30 10:36:48.000000000 +0200
+++ new/BTrees-4.6.1/tox.ini    2019-11-07 17:39:45.000000000 +0100
@@ -3,7 +3,7 @@
 # Jython support pending 2.7 support, due 2012-07-15 or so.  See:
 # http://fwierzbicki.blogspot.com/2012/03/adconion-to-fund-jython-27.html
 #   py27,jython,pypy,coverage,docs
-    py27,py27-pure,py35,py35-pure,py36,py37,pypy,pypy3,w_zodb,coverage,docs
+    
py27,py27-pure,py35,py35-pure,py36,py37,py38,pypy,pypy3,w_zodb,coverage,docs
 
 [testenv]
 usedevelop = true
@@ -36,9 +36,11 @@
 
 [testenv:docs]
 basepython =
-    python2.7
+    python3.7
 commands =
     sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
     sphinx-build -b doctest -d docs/_build/doctrees docs docs/_build/doctest
+deps =
+    --requirement doc-requirements.txt
 extras =
     docs


Reply via email to