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