tested django-newsletter
This commit is contained in:
parent
7ed667d043
commit
811b7c5453
@ -22,6 +22,7 @@ urlpatterns = [
|
||||
url(r'^post/(?P<pk>\d+)/remove/$', views.post_remove, name='post_remove'),
|
||||
url(r'^student/(?P<slug>[-\w]+)/remove/$', views.tag_remove, name='tag_remove'),
|
||||
url(r'^tags/', include('taggit_templatetags2.urls')),
|
||||
url(r'^newsletter/', include('newsletter.urls')),
|
||||
]
|
||||
|
||||
if settings.DEBUG:
|
||||
|
3
log.txt
3
log.txt
@ -400,3 +400,6 @@
|
||||
[24/Oct/2018 19:03:28] INFO [mysite:191] <QuerySet [<Post: Third one>]>
|
||||
[24/Oct/2018 19:03:45] INFO [mysite:189] bamberg
|
||||
[24/Oct/2018 19:03:45] INFO [mysite:191] <QuerySet [<Post: Third one>, <Post: here i go again>]>
|
||||
[25/Oct/2018 10:33:13] INFO [mysite:189] bamberg
|
||||
[25/Oct/2018 15:28:52] INFO [mysite:189] hi
|
||||
[25/Oct/2018 15:28:54] INFO [mysite:189]
|
||||
|
@ -44,11 +44,14 @@ INSTALLED_APPS = [
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.sites',
|
||||
'application',
|
||||
'taggit',
|
||||
'taggit_templatetags2',
|
||||
'djcelery',
|
||||
'kombu.transport.django',
|
||||
'sorl.thumbnail',
|
||||
'newsletter',
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
@ -261,4 +264,6 @@ CELERY_TASK_SERIALIZER = 'json'
|
||||
CELERY_RESULT_SERIALIZER = 'json'
|
||||
CELERY_RESULT_BACKEND = 'djcelery.backends.database:DatabaseBackend'
|
||||
CELERYBEAT_SCHEDULER = "djcelery.schedulers.DatabaseScheduler"
|
||||
djcelery.setup_loader()
|
||||
djcelery.setup_loader()
|
||||
|
||||
SITE_ID = 1
|
12
thesisenv/bin/change_tz
Executable file
12
thesisenv/bin/change_tz
Executable file
@ -0,0 +1,12 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'python-card-me==0.9.3','console_scripts','change_tz'
|
||||
__requires__ = 'python-card-me==0.9.3'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('python-card-me==0.9.3', 'console_scripts', 'change_tz')()
|
||||
)
|
11
thesisenv/bin/chardetect
Executable file
11
thesisenv/bin/chardetect
Executable file
@ -0,0 +1,11 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from chardet.cli.chardetect import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
11
thesisenv/bin/fsdump
Executable file
11
thesisenv/bin/fsdump
Executable file
@ -0,0 +1,11 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from ZODB.FileStorage.fsdump import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
11
thesisenv/bin/fsoids
Executable file
11
thesisenv/bin/fsoids
Executable file
@ -0,0 +1,11 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from ZODB.scripts.fsoids import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
11
thesisenv/bin/fsrefs
Executable file
11
thesisenv/bin/fsrefs
Executable file
@ -0,0 +1,11 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from ZODB.scripts.fsrefs import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
11
thesisenv/bin/fstail
Executable file
11
thesisenv/bin/fstail
Executable file
@ -0,0 +1,11 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from ZODB.scripts.fstail import Main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(Main())
|
12
thesisenv/bin/ics_diff
Executable file
12
thesisenv/bin/ics_diff
Executable file
@ -0,0 +1,12 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'python-card-me==0.9.3','console_scripts','ics_diff'
|
||||
__requires__ = 'python-card-me==0.9.3'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('python-card-me==0.9.3', 'console_scripts', 'ics_diff')()
|
||||
)
|
11
thesisenv/bin/repozo
Executable file
11
thesisenv/bin/repozo
Executable file
@ -0,0 +1,11 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from ZODB.scripts.repozo import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
12
thesisenv/bin/runzeo
Executable file
12
thesisenv/bin/runzeo
Executable file
@ -0,0 +1,12 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'ZEO==5.2.0','console_scripts','runzeo'
|
||||
__requires__ = 'ZEO==5.2.0'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('ZEO==5.2.0', 'console_scripts', 'runzeo')()
|
||||
)
|
17
thesisenv/bin/surlex2regex.py
Executable file
17
thesisenv/bin/surlex2regex.py
Executable file
@ -0,0 +1,17 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
from surlex import Surlex
|
||||
import sys
|
||||
from optparse import OptionParser
|
||||
|
||||
def main():
|
||||
parser = OptionParser()
|
||||
parser.set_usage('surlex2regex.py <surlex>')
|
||||
if len(sys.argv) == 1:
|
||||
argv = ['-h']
|
||||
else:
|
||||
argv = sys.argv[1:]
|
||||
options, args = parser.parse_args(argv)
|
||||
print (Surlex(args[0]).translate())
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
11
thesisenv/bin/zconfig
Executable file
11
thesisenv/bin/zconfig
Executable file
@ -0,0 +1,11 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from ZConfig.validator import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
11
thesisenv/bin/zconfig_schema2html
Executable file
11
thesisenv/bin/zconfig_schema2html
Executable file
@ -0,0 +1,11 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import sys
|
||||
|
||||
from ZConfig.schema2html import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(main())
|
12
thesisenv/bin/zdaemon
Executable file
12
thesisenv/bin/zdaemon
Executable file
@ -0,0 +1,12 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'zdaemon==4.2.0','console_scripts','zdaemon'
|
||||
__requires__ = 'zdaemon==4.2.0'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('zdaemon==4.2.0', 'console_scripts', 'zdaemon')()
|
||||
)
|
12
thesisenv/bin/zeo-nagios
Executable file
12
thesisenv/bin/zeo-nagios
Executable file
@ -0,0 +1,12 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'ZEO==5.2.0','console_scripts','zeo-nagios'
|
||||
__requires__ = 'ZEO==5.2.0'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('ZEO==5.2.0', 'console_scripts', 'zeo-nagios')()
|
||||
)
|
12
thesisenv/bin/zeoctl
Executable file
12
thesisenv/bin/zeoctl
Executable file
@ -0,0 +1,12 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'ZEO==5.2.0','console_scripts','zeoctl'
|
||||
__requires__ = 'ZEO==5.2.0'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('ZEO==5.2.0', 'console_scripts', 'zeoctl')()
|
||||
)
|
12
thesisenv/bin/zeopack
Executable file
12
thesisenv/bin/zeopack
Executable file
@ -0,0 +1,12 @@
|
||||
#!/Users/Esthi/thesis_ek/thesisenv/bin/python3
|
||||
# EASY-INSTALL-ENTRY-SCRIPT: 'ZEO==5.2.0','console_scripts','zeopack'
|
||||
__requires__ = 'ZEO==5.2.0'
|
||||
import re
|
||||
import sys
|
||||
from pkg_resources import load_entry_point
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||
sys.exit(
|
||||
load_entry_point('ZEO==5.2.0', 'console_scripts', 'zeopack')()
|
||||
)
|
156
thesisenv/include/site/python3.6/persistent/cPersistence.h
Normal file
156
thesisenv/include/site/python3.6/persistent/cPersistence.h
Normal file
@ -0,0 +1,156 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2001, 2002 Zope Foundation and Contributors.
|
||||
All Rights Reserved.
|
||||
|
||||
This software is subject to the provisions of the Zope Public License,
|
||||
Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CPERSISTENCE_H
|
||||
#define CPERSISTENCE_H
|
||||
|
||||
#include "_compat.h"
|
||||
#include "bytesobject.h"
|
||||
|
||||
#include "ring.h"
|
||||
|
||||
#define CACHE_HEAD \
|
||||
PyObject_HEAD \
|
||||
CPersistentRing ring_home; \
|
||||
int non_ghost_count; \
|
||||
Py_ssize_t total_estimated_size;
|
||||
|
||||
struct ccobject_head_struct;
|
||||
|
||||
typedef struct ccobject_head_struct PerCache;
|
||||
|
||||
/* How big is a persistent object?
|
||||
|
||||
12 PyGC_Head is two pointers and an int
|
||||
8 PyObject_HEAD is an int and a pointer
|
||||
|
||||
12 jar, oid, cache pointers
|
||||
8 ring struct
|
||||
8 serialno
|
||||
4 state + extra
|
||||
4 size info
|
||||
|
||||
(56) so far
|
||||
|
||||
4 dict ptr
|
||||
4 weaklist ptr
|
||||
-------------------------
|
||||
68 only need 62, but obmalloc rounds up to multiple of eight
|
||||
|
||||
Even a ghost requires 64 bytes. It's possible to make a persistent
|
||||
instance with slots and no dict, which changes the storage needed.
|
||||
|
||||
*/
|
||||
|
||||
#define cPersistent_HEAD \
|
||||
PyObject_HEAD \
|
||||
PyObject *jar; \
|
||||
PyObject *oid; \
|
||||
PerCache *cache; \
|
||||
CPersistentRing ring; \
|
||||
char serial[8]; \
|
||||
signed state:8; \
|
||||
unsigned estimated_size:24;
|
||||
|
||||
/* We recently added estimated_size. We originally added it as a new
|
||||
unsigned long field after a signed char state field and a
|
||||
3-character reserved field. This didn't work because there
|
||||
are packages in the wild that have their own copies of cPersistence.h
|
||||
that didn't see the update.
|
||||
|
||||
To get around this, we used the reserved space by making
|
||||
estimated_size a 24-bit bit field in the space occupied by the old
|
||||
3-character reserved field. To fit in 24 bits, we made the units
|
||||
of estimated_size 64-character blocks. This allows is to handle up
|
||||
to a GB. We should never see that, but to be paranoid, we also
|
||||
truncate sizes greater than 1GB. We also set the minimum size to
|
||||
64 bytes.
|
||||
|
||||
We use the _estimated_size_in_24_bits and _estimated_size_in_bytes
|
||||
macros both to avoid repetition and to make intent a little clearer.
|
||||
*/
|
||||
#define _estimated_size_in_24_bits(I) ((I) > 1073741696 ? 16777215 : (I)/64+1)
|
||||
#define _estimated_size_in_bytes(I) ((I)*64)
|
||||
|
||||
#define cPersistent_GHOST_STATE -1
|
||||
#define cPersistent_UPTODATE_STATE 0
|
||||
#define cPersistent_CHANGED_STATE 1
|
||||
#define cPersistent_STICKY_STATE 2
|
||||
|
||||
typedef struct {
|
||||
cPersistent_HEAD
|
||||
} cPersistentObject;
|
||||
|
||||
typedef void (*percachedelfunc)(PerCache *, PyObject *);
|
||||
|
||||
typedef struct {
|
||||
PyTypeObject *pertype;
|
||||
getattrofunc getattro;
|
||||
setattrofunc setattro;
|
||||
int (*changed)(cPersistentObject*);
|
||||
void (*accessed)(cPersistentObject*);
|
||||
void (*ghostify)(cPersistentObject*);
|
||||
int (*setstate)(PyObject*);
|
||||
percachedelfunc percachedel;
|
||||
int (*readCurrent)(cPersistentObject*);
|
||||
} cPersistenceCAPIstruct;
|
||||
|
||||
#define cPersistenceType cPersistenceCAPI->pertype
|
||||
|
||||
#ifndef DONT_USE_CPERSISTENCECAPI
|
||||
static cPersistenceCAPIstruct *cPersistenceCAPI;
|
||||
#endif
|
||||
|
||||
#define cPersistanceModuleName "cPersistence"
|
||||
|
||||
#define PER_TypeCheck(O) PyObject_TypeCheck((O), cPersistenceCAPI->pertype)
|
||||
|
||||
#define PER_USE_OR_RETURN(O,R) {if((O)->state==cPersistent_GHOST_STATE && cPersistenceCAPI->setstate((PyObject*)(O)) < 0) return (R); else if ((O)->state==cPersistent_UPTODATE_STATE) (O)->state=cPersistent_STICKY_STATE;}
|
||||
|
||||
#define PER_CHANGED(O) (cPersistenceCAPI->changed((cPersistentObject*)(O)))
|
||||
|
||||
#define PER_READCURRENT(O, E) \
|
||||
if (cPersistenceCAPI->readCurrent((cPersistentObject*)(O)) < 0) { E; }
|
||||
|
||||
#define PER_GHOSTIFY(O) (cPersistenceCAPI->ghostify((cPersistentObject*)(O)))
|
||||
|
||||
/* If the object is sticky, make it non-sticky, so that it can be ghostified.
|
||||
The value is not meaningful
|
||||
*/
|
||||
#define PER_ALLOW_DEACTIVATION(O) ((O)->state==cPersistent_STICKY_STATE && ((O)->state=cPersistent_UPTODATE_STATE))
|
||||
|
||||
#define PER_PREVENT_DEACTIVATION(O) ((O)->state==cPersistent_UPTODATE_STATE && ((O)->state=cPersistent_STICKY_STATE))
|
||||
|
||||
/*
|
||||
Make a persistent object usable from C by:
|
||||
|
||||
- Making sure it is not a ghost
|
||||
|
||||
- Making it sticky.
|
||||
|
||||
IMPORTANT: If you call this and don't call PER_ALLOW_DEACTIVATION,
|
||||
your object will not be ghostified.
|
||||
|
||||
PER_USE returns a 1 on success and 0 failure, where failure means
|
||||
error.
|
||||
*/
|
||||
#define PER_USE(O) \
|
||||
(((O)->state != cPersistent_GHOST_STATE \
|
||||
|| (cPersistenceCAPI->setstate((PyObject*)(O)) >= 0)) \
|
||||
? (((O)->state==cPersistent_UPTODATE_STATE) \
|
||||
? ((O)->state=cPersistent_STICKY_STATE) : 1) : 0)
|
||||
|
||||
#define PER_ACCESSED(O) (cPersistenceCAPI->accessed((cPersistentObject*)(O)))
|
||||
|
||||
#endif
|
66
thesisenv/include/site/python3.6/persistent/ring.h
Normal file
66
thesisenv/include/site/python3.6/persistent/ring.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2003 Zope Foundation and Contributors.
|
||||
All Rights Reserved.
|
||||
|
||||
This software is subject to the provisions of the Zope Public License,
|
||||
Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
/* Support routines for the doubly-linked list of cached objects.
|
||||
|
||||
The cache stores a headed, doubly-linked, circular list of persistent
|
||||
objects, with space for the pointers allocated in the objects themselves.
|
||||
The cache stores the distinguished head of the list, which is not a valid
|
||||
persistent object. The other list members are non-ghost persistent
|
||||
objects, linked in LRU (least-recently used) order.
|
||||
|
||||
The r_next pointers traverse the ring starting with the least recently used
|
||||
object. The r_prev pointers traverse the ring starting with the most
|
||||
recently used object.
|
||||
|
||||
Obscure: While each object is pointed at twice by list pointers (once by
|
||||
its predecessor's r_next, again by its successor's r_prev), the refcount
|
||||
on the object is bumped only by 1. This leads to some possibly surprising
|
||||
sequences of incref and decref code. Note that since the refcount is
|
||||
bumped at least once, the list does hold a strong reference to each
|
||||
object in it.
|
||||
*/
|
||||
|
||||
typedef struct CPersistentRing_struct
|
||||
{
|
||||
struct CPersistentRing_struct *r_prev;
|
||||
struct CPersistentRing_struct *r_next;
|
||||
} CPersistentRing;
|
||||
|
||||
/* The list operations here take constant time independent of the
|
||||
* number of objects in the list:
|
||||
*/
|
||||
|
||||
/* Add elt as the most recently used object. elt must not already be
|
||||
* in the list, although this isn't checked.
|
||||
*/
|
||||
void ring_add(CPersistentRing *ring, CPersistentRing *elt);
|
||||
|
||||
/* Remove elt from the list. elt must already be in the list, although
|
||||
* this isn't checked.
|
||||
*/
|
||||
void ring_del(CPersistentRing *elt);
|
||||
|
||||
/* elt must already be in the list, although this isn't checked. It's
|
||||
* unlinked from its current position, and relinked into the list as the
|
||||
* most recently used object (which is arguably the tail of the list
|
||||
* instead of the head -- but the name of this function could be argued
|
||||
* either way). This is equivalent to
|
||||
*
|
||||
* ring_del(elt);
|
||||
* ring_add(ring, elt);
|
||||
*
|
||||
* but may be a little quicker.
|
||||
*/
|
||||
void ring_move_to_head(CPersistentRing *ring, CPersistentRing *elt);
|
59
thesisenv/include/site/python3.6/zope.proxy/proxy.h
Normal file
59
thesisenv/include/site/python3.6/zope.proxy/proxy.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef _proxy_H_
|
||||
#define _proxy_H_ 1
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *proxy_object;
|
||||
} ProxyObject;
|
||||
|
||||
#define Proxy_GET_OBJECT(ob) (((ProxyObject *)(ob))->proxy_object)
|
||||
|
||||
typedef struct {
|
||||
PyTypeObject *proxytype;
|
||||
int (*check)(PyObject *obj);
|
||||
PyObject *(*create)(PyObject *obj);
|
||||
PyObject *(*getobject)(PyObject *proxy);
|
||||
} ProxyInterface;
|
||||
|
||||
#ifndef PROXY_MODULE
|
||||
|
||||
/* These are only defined in the public interface, and are not
|
||||
* available within the module implementation. There we use the
|
||||
* classic Python/C API only.
|
||||
*/
|
||||
|
||||
static ProxyInterface *_proxy_api = NULL;
|
||||
|
||||
static int
|
||||
Proxy_Import(void)
|
||||
{
|
||||
if (_proxy_api == NULL) {
|
||||
PyObject *m = PyImport_ImportModule("zope.proxy");
|
||||
if (m != NULL) {
|
||||
PyObject *tmp = PyObject_GetAttrString(m, "_CAPI");
|
||||
if (tmp != NULL) {
|
||||
#if PY_VERSION_HEX < 0x02070000
|
||||
if (PyCObject_Check(tmp))
|
||||
_proxy_api = (ProxyInterface *)
|
||||
PyCObject_AsVoidPtr(tmp);
|
||||
#else
|
||||
if (PyCapsule_CheckExact(tmp))
|
||||
_proxy_api = (ProxyInterface *)
|
||||
PyCapsule_GetPointer(tmp, NULL);
|
||||
#endif
|
||||
Py_DECREF(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (_proxy_api == NULL) ? -1 : 0;
|
||||
}
|
||||
|
||||
#define ProxyType (*_proxy_api->proxytype)
|
||||
#define Proxy_Check(obj) (_proxy_api->check((obj)))
|
||||
#define Proxy_CheckExact(obj) ((obj)->ob_type == ProxyType)
|
||||
#define Proxy_New(obj) (_proxy_api->create((obj)))
|
||||
#define Proxy_GetObject(proxy) (_proxy_api->getobject((proxy)))
|
||||
|
||||
#endif /* PROXY_MODULE */
|
||||
|
||||
#endif /* _proxy_H_ */
|
@ -0,0 +1,697 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: Acquisition
|
||||
Version: 4.5
|
||||
Summary: Acquisition is a mechanism that allows objects to obtain attributes from the containment hierarchy they're in.
|
||||
Home-page: https://github.com/zopefoundation/Acquisition
|
||||
Author: Zope Foundation and Contributors
|
||||
Author-email: zope-dev@zope.org
|
||||
License: ZPL 2.1
|
||||
Description: Environmental Acquisiton
|
||||
========================
|
||||
|
||||
This package implements "environmental acquisiton" for Python, as
|
||||
proposed in the OOPSLA96_ paper by Joseph Gil and David H. Lorenz:
|
||||
|
||||
We propose a new programming paradigm, environmental acquisition in
|
||||
the context of object aggregation, in which objects acquire
|
||||
behaviour from their current containers at runtime. The key idea is
|
||||
that the behaviour of a component may depend upon its enclosing
|
||||
composite(s). In particular, we propose a form of feature sharing in
|
||||
which an object "inherits" features from the classes of objects in
|
||||
its environment. By examining the declaration of classes, it is
|
||||
possible to determine which kinds of classes may contain a
|
||||
component, and which components must be contained in a given kind of
|
||||
composite. These relationships are the basis for language constructs
|
||||
that supports acquisition.
|
||||
|
||||
.. _OOPSLA96: http://www.cs.virginia.edu/~lorenz/papers/oopsla96/>`_:
|
||||
|
||||
.. contents::
|
||||
|
||||
Introductory Example
|
||||
--------------------
|
||||
|
||||
Zope implements acquisition with "Extension Class" mix-in classes. To
|
||||
use acquisition your classes must inherit from an acquisition base
|
||||
class. For example::
|
||||
|
||||
>>> import ExtensionClass, Acquisition
|
||||
|
||||
>>> class C(ExtensionClass.Base):
|
||||
... color = 'red'
|
||||
|
||||
>>> class A(Acquisition.Implicit):
|
||||
... def report(self):
|
||||
... print(self.color)
|
||||
...
|
||||
>>> a = A()
|
||||
>>> c = C()
|
||||
>>> c.a = a
|
||||
|
||||
>>> c.a.report()
|
||||
red
|
||||
|
||||
>>> d = C()
|
||||
>>> d.color = 'green'
|
||||
>>> d.a = a
|
||||
|
||||
>>> d.a.report()
|
||||
green
|
||||
|
||||
>>> try:
|
||||
... a.report()
|
||||
... except AttributeError:
|
||||
... pass
|
||||
... else:
|
||||
... raise AssertionError('AttributeError not raised.')
|
||||
|
||||
The class ``A`` inherits acquisition behavior from
|
||||
``Acquisition.Implicit``. The object, ``a``, "has" the color of
|
||||
objects ``c`` and d when it is accessed through them, but it has no
|
||||
color by itself. The object ``a`` obtains attributes from its
|
||||
environment, where its environment is defined by the access path used
|
||||
to reach ``a``.
|
||||
|
||||
Acquisition Wrappers
|
||||
--------------------
|
||||
|
||||
When an object that supports acquisition is accessed through an
|
||||
extension class instance, a special object, called an acquisition
|
||||
wrapper, is returned. In the example above, the expression ``c.a``
|
||||
returns an acquisition wrapper that contains references to both ``c``
|
||||
and ``a``. It is this wrapper that performs attribute lookup in ``c``
|
||||
when an attribute cannot be found in ``a``.
|
||||
|
||||
Acquisition wrappers provide access to the wrapped objects through the
|
||||
attributes ``aq_parent``, ``aq_self``, ``aq_base``. Continue the
|
||||
example from above::
|
||||
|
||||
>>> c.a.aq_parent is c
|
||||
True
|
||||
>>> c.a.aq_self is a
|
||||
True
|
||||
|
||||
Explicit and Implicit Acquisition
|
||||
---------------------------------
|
||||
|
||||
Two styles of acquisition are supported: implicit and explicit
|
||||
acquisition.
|
||||
|
||||
Implicit acquisition
|
||||
--------------------
|
||||
|
||||
Implicit acquisition is so named because it searches for attributes
|
||||
from the environment automatically whenever an attribute cannot be
|
||||
obtained directly from an object or through inheritance.
|
||||
|
||||
An attribute can be implicitly acquired if its name does not begin
|
||||
with an underscore.
|
||||
|
||||
To support implicit acquisition, your class should inherit from the
|
||||
mix-in class ``Acquisition.Implicit``.
|
||||
|
||||
Explicit Acquisition
|
||||
--------------------
|
||||
|
||||
When explicit acquisition is used, attributes are not automatically
|
||||
obtained from the environment. Instead, the method aq_acquire must be
|
||||
used. For example::
|
||||
|
||||
>>> print(c.a.aq_acquire('color'))
|
||||
red
|
||||
|
||||
To support explicit acquisition, your class should inherit from the
|
||||
mix-in class ``Acquisition.Explicit``.
|
||||
|
||||
Controlling Acquisition
|
||||
-----------------------
|
||||
|
||||
A class (or instance) can provide attribute by attribute control over
|
||||
acquisition. Your should subclass from ``Acquisition.Explicit``, and set
|
||||
all attributes that should be acquired to the special value
|
||||
``Acquisition.Acquired``. Setting an attribute to this value also allows
|
||||
inherited attributes to be overridden with acquired ones. For example::
|
||||
|
||||
>>> class C(Acquisition.Explicit):
|
||||
... id = 1
|
||||
... secret = 2
|
||||
... color = Acquisition.Acquired
|
||||
... __roles__ = Acquisition.Acquired
|
||||
|
||||
The only attributes that are automatically acquired from containing
|
||||
objects are color, and ``__roles__``. Note that the ``__roles__``
|
||||
attribute is acquired even though its name begins with an
|
||||
underscore. In fact, the special ``Acquisition.Acquired`` value can be
|
||||
used in ``Acquisition.Implicit`` objects to implicitly acquire
|
||||
selected objects that smell like private objects.
|
||||
|
||||
Sometimes, you want to dynamically make an implicitly acquiring object
|
||||
acquire explicitly. You can do this by getting the object's
|
||||
aq_explicit attribute. This attribute provides the object with an
|
||||
explicit wrapper that replaces the original implicit wrapper.
|
||||
|
||||
Filtered Acquisition
|
||||
--------------------
|
||||
|
||||
The acquisition method, ``aq_acquire``, accepts two optional
|
||||
arguments. The first of the additional arguments is a "filtering"
|
||||
function that is used when considering whether to acquire an
|
||||
object. The second of the additional arguments is an object that is
|
||||
passed as extra data when calling the filtering function and which
|
||||
defaults to ``None``. The filter function is called with five
|
||||
arguments:
|
||||
|
||||
* The object that the aq_acquire method was called on,
|
||||
|
||||
* The object where an object was found,
|
||||
|
||||
* The name of the object, as passed to aq_acquire,
|
||||
|
||||
* The object found, and
|
||||
|
||||
* The extra data passed to aq_acquire.
|
||||
|
||||
If the filter returns a true object that the object found is returned,
|
||||
otherwise, the acquisition search continues.
|
||||
|
||||
Here's an example::
|
||||
|
||||
>>> from Acquisition import Explicit
|
||||
|
||||
>>> class HandyForTesting(object):
|
||||
... def __init__(self, name):
|
||||
... self.name = name
|
||||
... def __str__(self):
|
||||
... return "%s(%s)" % (self.name, self.__class__.__name__)
|
||||
... __repr__=__str__
|
||||
...
|
||||
>>> class E(Explicit, HandyForTesting): pass
|
||||
...
|
||||
>>> class Nice(HandyForTesting):
|
||||
... isNice = 1
|
||||
... def __str__(self):
|
||||
... return HandyForTesting.__str__(self)+' and I am nice!'
|
||||
... __repr__ = __str__
|
||||
...
|
||||
>>> a = E('a')
|
||||
>>> a.b = E('b')
|
||||
>>> a.b.c = E('c')
|
||||
>>> a.p = Nice('spam')
|
||||
>>> a.b.p = E('p')
|
||||
|
||||
>>> def find_nice(self, ancestor, name, object, extra):
|
||||
... return hasattr(object,'isNice') and object.isNice
|
||||
|
||||
>>> print(a.b.c.aq_acquire('p', find_nice))
|
||||
spam(Nice) and I am nice!
|
||||
|
||||
The filtered acquisition in the last line skips over the first
|
||||
attribute it finds with the name ``p``, because the attribute doesn't
|
||||
satisfy the condition given in the filter.
|
||||
|
||||
Filtered acquisition is rarely used in Zope.
|
||||
|
||||
Acquiring from Context
|
||||
----------------------
|
||||
|
||||
Normally acquisition allows objects to acquire data from their
|
||||
containers. However an object can acquire from objects that aren't its
|
||||
containers.
|
||||
|
||||
Most of the examples we've seen so far show establishing of an
|
||||
acquisition context using getattr semantics. For example, ``a.b`` is a
|
||||
reference to ``b`` in the context of ``a``.
|
||||
|
||||
You can also manually set acquisition context using the ``__of__``
|
||||
method. For example::
|
||||
|
||||
>>> from Acquisition import Implicit
|
||||
>>> class C(Implicit): pass
|
||||
...
|
||||
>>> a = C()
|
||||
>>> b = C()
|
||||
>>> a.color = "red"
|
||||
>>> print(b.__of__(a).color)
|
||||
red
|
||||
|
||||
In this case, ``a`` does not contain ``b``, but it is put in ``b``'s
|
||||
context using the ``__of__`` method.
|
||||
|
||||
Here's another subtler example that shows how you can construct an
|
||||
acquisition context that includes non-container objects::
|
||||
|
||||
>>> from Acquisition import Implicit
|
||||
|
||||
>>> class C(Implicit):
|
||||
... def __init__(self, name):
|
||||
... self.name = name
|
||||
|
||||
>>> a = C("a")
|
||||
>>> a.b = C("b")
|
||||
>>> a.b.color = "red"
|
||||
>>> a.x = C("x")
|
||||
|
||||
>>> print(a.b.x.color)
|
||||
red
|
||||
|
||||
Even though ``b`` does not contain ``x``, ``x`` can acquire the color
|
||||
attribute from ``b``. This works because in this case, ``x`` is accessed
|
||||
in the context of ``b`` even though it is not contained by ``b``.
|
||||
|
||||
Here acquisition context is defined by the objects used to access
|
||||
another object.
|
||||
|
||||
Containment Before Context
|
||||
--------------------------
|
||||
|
||||
If in the example above suppose both a and b have an color attribute::
|
||||
|
||||
>>> a = C("a")
|
||||
>>> a.color = "green"
|
||||
>>> a.b = C("b")
|
||||
>>> a.b.color = "red"
|
||||
>>> a.x = C("x")
|
||||
|
||||
>>> print(a.b.x.color)
|
||||
green
|
||||
|
||||
Why does ``a.b.x.color`` acquire color from ``a`` and not from ``b``?
|
||||
The answer is that an object acquires from its containers before
|
||||
non-containers in its context.
|
||||
|
||||
To see why consider this example in terms of expressions using the
|
||||
``__of__`` method::
|
||||
|
||||
a.x -> x.__of__(a)
|
||||
|
||||
a.b -> b.__of__(a)
|
||||
|
||||
a.b.x -> x.__of__(a).__of__(b.__of__(a))
|
||||
|
||||
Keep in mind that attribute lookup in a wrapper is done by trying to
|
||||
look up the attribute in the wrapped object first and then in the
|
||||
parent object. So in the expressions above proceeds from left to
|
||||
right.
|
||||
|
||||
The upshot of these rules is that attributes are looked up by
|
||||
containment before context.
|
||||
|
||||
This rule holds true also for more complex examples. For example,
|
||||
``a.b.c.d.e.f.g.attribute`` would search for attribute in ``g`` and
|
||||
all its containers first. (Containers are searched in order from the
|
||||
innermost parent to the outermost container.) If the attribute is not
|
||||
found in ``g`` or any of its containers, then the search moves to
|
||||
``f`` and all its containers, and so on.
|
||||
|
||||
Additional Attributes and Methods
|
||||
---------------------------------
|
||||
|
||||
You can use the special method ``aq_inner`` to access an object
|
||||
wrapped only by containment. So in the example above,
|
||||
``a.b.x.aq_inner`` is equivalent to ``a.x``.
|
||||
|
||||
You can find out the acquisition context of an object using the
|
||||
aq_chain method like so:
|
||||
|
||||
>>> [obj.name for obj in a.b.x.aq_chain]
|
||||
['x', 'b', 'a']
|
||||
|
||||
You can find out if an object is in the containment context of another
|
||||
object using the ``aq_inContextOf`` method. For example:
|
||||
|
||||
>>> a.b.aq_inContextOf(a)
|
||||
True
|
||||
|
||||
.. Note: as of this writing the aq_inContextOf examples don't work the
|
||||
way they should be working. According to Jim, this is because
|
||||
aq_inContextOf works by comparing object pointer addresses, which
|
||||
(because they are actually different wrapper objects) doesn't give
|
||||
you the expected results. He acknowledges that this behavior is
|
||||
controversial, and says that there is a collector entry to change
|
||||
it so that you would get the answer you expect in the above. (We
|
||||
just need to get to it).
|
||||
|
||||
Acquisition Module Functions
|
||||
----------------------------
|
||||
|
||||
In addition to using acquisition attributes and methods directly on
|
||||
objects you can use similar functions defined in the ``Acquisition``
|
||||
module. These functions have the advantage that you don't need to
|
||||
check to make sure that the object has the method or attribute before
|
||||
calling it.
|
||||
|
||||
``aq_acquire(object, name [, filter, extra, explicit, default, containment])``
|
||||
Acquires an object with the given name.
|
||||
|
||||
This function can be used to explictly acquire when using explicit
|
||||
acquisition and to acquire names that wouldn't normally be
|
||||
acquired.
|
||||
|
||||
The function accepts a number of optional arguments:
|
||||
|
||||
``filter``
|
||||
A callable filter object that is used to decide if an object
|
||||
should be acquired.
|
||||
|
||||
The filter is called with five arguments:
|
||||
|
||||
* The object that the aq_acquire method was called on,
|
||||
|
||||
* The object where an object was found,
|
||||
|
||||
* The name of the object, as passed to aq_acquire,
|
||||
|
||||
* The object found, and
|
||||
|
||||
* The extra argument passed to aq_acquire.
|
||||
|
||||
If the filter returns a true object that the object found is
|
||||
returned, otherwise, the acquisition search continues.
|
||||
|
||||
``extra``
|
||||
Extra data to be passed as the last argument to the filter.
|
||||
|
||||
``explicit``
|
||||
A flag (boolean value) indicating whether explicit acquisition
|
||||
should be used. The default value is true. If the flag is
|
||||
true, then acquisition will proceed regardless of whether
|
||||
wrappers encountered in the search of the acquisition
|
||||
hierarchy are explicit or implicit wrappers. If the flag is
|
||||
false, then parents of explicit wrappers are not searched.
|
||||
|
||||
This argument is useful if you want to apply a filter without
|
||||
overriding explicit wrappers.
|
||||
|
||||
``default``
|
||||
A default value to return if no value can be acquired.
|
||||
|
||||
``containment``
|
||||
A flag indicating whether the search should be limited to the
|
||||
containment hierarchy.
|
||||
|
||||
In addition, arguments can be provided as keywords.
|
||||
|
||||
``aq_base(object)``
|
||||
Return the object with all wrapping removed.
|
||||
|
||||
``aq_chain(object [, containment])``
|
||||
Return a list containing the object and it's acquisition
|
||||
parents. The optional argument, containment, controls whether the
|
||||
containment or access hierarchy is used.
|
||||
|
||||
``aq_get(object, name [, default, containment])``
|
||||
Acquire an attribute, name. A default value can be provided, as
|
||||
can a flag that limits search to the containment hierarchy.
|
||||
|
||||
``aq_inner(object)``
|
||||
Return the object with all but the innermost layer of wrapping
|
||||
removed.
|
||||
|
||||
``aq_parent(object)``
|
||||
Return the acquisition parent of the object or None if the object
|
||||
is unwrapped.
|
||||
|
||||
``aq_self(object)``
|
||||
Return the object with one layer of wrapping removed, unless the
|
||||
object is unwrapped, in which case the object is returned.
|
||||
|
||||
In most cases it is more convenient to use these module functions
|
||||
instead of the acquisition attributes and methods directly.
|
||||
|
||||
Acquisition and Methods
|
||||
-----------------------
|
||||
|
||||
Python methods of objects that support acquisition can use acquired
|
||||
attributes. When a Python method is called on an object that is
|
||||
wrapped by an acquisition wrapper, the wrapper is passed to the method
|
||||
as the first argument. This rule also applies to user-defined method
|
||||
types and to C methods defined in pure mix-in classes.
|
||||
|
||||
Unfortunately, C methods defined in extension base classes that define
|
||||
their own data structures, cannot use aquired attributes at this
|
||||
time. This is because wrapper objects do not conform to the data
|
||||
structures expected by these methods. In practice, you will seldom
|
||||
find this a problem.
|
||||
|
||||
Conclusion
|
||||
----------
|
||||
|
||||
Acquisition provides a powerful way to dynamically share information
|
||||
between objects. Zope 2 uses acquisition for a number of its key
|
||||
features including security, object publishing, and DTML variable
|
||||
lookup. Acquisition also provides an elegant solution to the problem
|
||||
of circular references for many classes of problems. While acquisition
|
||||
is powerful, you should take care when using acquisition in your
|
||||
applications. The details can get complex, especially with the
|
||||
differences between acquiring from context and acquiring from
|
||||
containment.
|
||||
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
4.5 (2018-10-05)
|
||||
----------------
|
||||
|
||||
- Avoid deprecation warnings by using current API.
|
||||
|
||||
- Add support for Python 3.7.
|
||||
|
||||
4.4.4 (2017-11-24)
|
||||
------------------
|
||||
|
||||
- Add Appveyor configuration to automate building Windows eggs.
|
||||
|
||||
4.4.3 (2017-11-23)
|
||||
------------------
|
||||
|
||||
- Fix the extremely rare potential for a crash when the C extensions
|
||||
are in use. See `issue 21 <https://github.com/zopefoundation/Acquisition/issues/21>`_.
|
||||
|
||||
4.4.2 (2017-05-12)
|
||||
------------------
|
||||
|
||||
- Fix C capsule name to fix import errors.
|
||||
|
||||
- Ensure our dependencies match our expactations about C extensions.
|
||||
|
||||
4.4.1 (2017-05-04)
|
||||
------------------
|
||||
|
||||
- Fix C code under Python 3.4, with missing Py_XSETREF.
|
||||
|
||||
4.4.0 (2017-05-04)
|
||||
------------------
|
||||
|
||||
- Enable the C extension under Python 3.
|
||||
|
||||
- Drop support for Python 3.3.
|
||||
|
||||
4.3.0 (2017-01-20)
|
||||
------------------
|
||||
|
||||
- Make tests compatible with ExtensionClass 4.2.0.
|
||||
|
||||
- Drop support for Python 2.6 and 3.2.
|
||||
|
||||
- Add support for Python 3.5 and 3.6.
|
||||
|
||||
4.2.2 (2015-05-19)
|
||||
------------------
|
||||
|
||||
- Make the pure-Python Acquirer objects cooperatively use the
|
||||
superclass ``__getattribute__`` method, like the C implementation.
|
||||
See https://github.com/zopefoundation/Acquisition/issues/7.
|
||||
|
||||
- The pure-Python implicit acquisition wrapper allows wrapped objects
|
||||
to use ``object.__getattribute__(self, name)``. This differs from
|
||||
the C implementation, but is important for compatibility with the
|
||||
pure-Python versions of libraries like ``persistent``. See
|
||||
https://github.com/zopefoundation/Acquisition/issues/9.
|
||||
|
||||
4.2.1 (2015-04-23)
|
||||
------------------
|
||||
|
||||
- Correct several dangling pointer uses in the C extension,
|
||||
potentially fixing a few interpreter crashes. See
|
||||
https://github.com/zopefoundation/Acquisition/issues/5.
|
||||
|
||||
4.2 (2015-04-04)
|
||||
----------------
|
||||
|
||||
- Add support for PyPy, PyPy3, and Python 3.2, 3.3, and 3.4.
|
||||
|
||||
4.1 (2014-12-18)
|
||||
----------------
|
||||
|
||||
- Bump dependency on ``ExtensionClass`` to match current release.
|
||||
|
||||
4.0.3 (2014-11-02)
|
||||
------------------
|
||||
|
||||
- Skip readme.rst tests when tests are run outside a source checkout.
|
||||
|
||||
4.0.2 (2014-11-02)
|
||||
------------------
|
||||
|
||||
- Include ``*.rst`` files in the release.
|
||||
|
||||
4.0.1 (2014-10-30)
|
||||
------------------
|
||||
|
||||
- Tolerate Unicode attribute names (ASCII only). LP #143358.
|
||||
|
||||
- Make module-level ``aq_acquire`` API respect the ``default`` parameter.
|
||||
LP #1387363.
|
||||
|
||||
- Don't raise an attribute error for ``__iter__`` if the fallback to
|
||||
``__getitem__`` succeeds. LP #1155760.
|
||||
|
||||
|
||||
4.0 (2013-02-24)
|
||||
----------------
|
||||
|
||||
- Added trove classifiers to project metadata.
|
||||
|
||||
4.0a1 (2011-12-13)
|
||||
------------------
|
||||
|
||||
- Raise `RuntimeError: Recursion detected in acquisition wrapper` if an object
|
||||
with a `__parent__` pointer points to a wrapper that in turn points to the
|
||||
original object.
|
||||
|
||||
- Prevent wrappers to be created while accessing `__parent__` on types derived
|
||||
from Explicit or Implicit base classes.
|
||||
|
||||
2.13.9 (2015-02-17)
|
||||
-------------------
|
||||
|
||||
- Tolerate Unicode attribute names (ASCII only). LP #143358.
|
||||
|
||||
- Make module-level ``aq_acquire`` API respect the ``default`` parameter.
|
||||
LP #1387363.
|
||||
|
||||
- Don't raise an attribute error for ``__iter__`` if the fallback to
|
||||
``__getitem__`` succeeds. LP #1155760.
|
||||
|
||||
2.13.8 (2011-06-11)
|
||||
-------------------
|
||||
|
||||
- Fixed a segfault on 64bit platforms when providing the `explicit` argument to
|
||||
the aq_acquire method of an Acquisition wrapper. Thx to LP #675064 for the
|
||||
hint to the solution. The code passed an int instead of a pointer into a
|
||||
function.
|
||||
|
||||
2.13.7 (2011-03-02)
|
||||
-------------------
|
||||
|
||||
- Fixed bug: When an object did not implement ``__unicode__``, calling
|
||||
``unicode(wrapped)`` was calling ``__str__`` with an unwrapped ``self``.
|
||||
|
||||
2.13.6 (2011-02-19)
|
||||
-------------------
|
||||
|
||||
- Add ``aq_explicit`` to ``IAcquisitionWrapper``.
|
||||
|
||||
- Fixed bug: ``unicode(wrapped)`` was not calling a ``__unicode__``
|
||||
method on wrapped objects.
|
||||
|
||||
2.13.5 (2010-09-29)
|
||||
-------------------
|
||||
|
||||
- Fixed unit tests that failed on 64bit Python on Windows machines.
|
||||
|
||||
2.13.4 (2010-08-31)
|
||||
-------------------
|
||||
|
||||
- LP 623665: Fixed typo in Acquisition.h.
|
||||
|
||||
2.13.3 (2010-04-19)
|
||||
-------------------
|
||||
|
||||
- Use the doctest module from the standard library and no longer depend on
|
||||
zope.testing.
|
||||
|
||||
2.13.2 (2010-04-04)
|
||||
-------------------
|
||||
|
||||
- Give both wrapper classes a ``__getnewargs__`` method, which causes the ZODB
|
||||
optimization to fail and create persistent references using the ``_p_oid``
|
||||
alone. This happens to be the persistent oid of the wrapped object. This lets
|
||||
these objects to be persisted correctly, even though they are passed to the
|
||||
ZODB in a wrapped state.
|
||||
|
||||
- Added failing tests for http://dev.plone.org/plone/ticket/10318. This shows
|
||||
an edge-case where AQ wrappers can be pickled using the specific combination
|
||||
of cPickle, pickle protocol one and a custom Pickler class with an
|
||||
``inst_persistent_id`` hook. Unfortunately this is the exact combination used
|
||||
by ZODB3.
|
||||
|
||||
2.13.1 (2010-02-23)
|
||||
-------------------
|
||||
|
||||
- Update to include ExtensionClass 2.13.0.
|
||||
|
||||
- Fix the ``tp_name`` of the ImplicitAcquisitionWrapper and
|
||||
ExplicitAcquisitionWrapper to match their Python visible names and thus have
|
||||
a correct ``__name__``.
|
||||
|
||||
- Expand the ``tp_name`` of our extension types to hold the fully qualified
|
||||
name. This ensures classes have their ``__module__`` set correctly.
|
||||
|
||||
2.13.0 (2010-02-14)
|
||||
-------------------
|
||||
|
||||
- Added support for method cache in Acquisition. Patch contributed by
|
||||
Yoshinori K. Okuji. See https://bugs.launchpad.net/zope2/+bug/486182.
|
||||
|
||||
2.12.4 (2009-10-29)
|
||||
-------------------
|
||||
|
||||
- Fix iteration proxying to pass `self` acquisition-wrapped into both
|
||||
`__iter__` as well as `__getitem__` (this fixes
|
||||
https://bugs.launchpad.net/zope2/+bug/360761).
|
||||
|
||||
- Add tests for the __getslice__ proxying, including open-ended slicing.
|
||||
|
||||
2.12.3 (2009-08-08)
|
||||
-------------------
|
||||
|
||||
- More 64-bit fixes in Py_BuildValue calls.
|
||||
|
||||
- More 64-bit issues fixed: Use correct integer size for slice operations.
|
||||
|
||||
2.12.2 (2009-08-02)
|
||||
-------------------
|
||||
|
||||
- Fixed 64-bit compatibility issues for Python 2.5.x / 2.6.x. See
|
||||
http://www.python.org/dev/peps/pep-0353/ for details.
|
||||
|
||||
2.12.1 (2009-04-15)
|
||||
-------------------
|
||||
|
||||
- Update for iteration proxying: The proxy for `__iter__` must not rely on the
|
||||
object to have an `__iter__` itself, but also support fall-back iteration via
|
||||
`__getitem__` (this fixes https://bugs.launchpad.net/zope2/+bug/360761).
|
||||
|
||||
2.12 (2009-01-25)
|
||||
-----------------
|
||||
|
||||
- Release as separate package.
|
||||
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 6 - Mature
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Framework :: Zope2
|
||||
Classifier: License :: OSI Approved :: Zope Public License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
@ -0,0 +1,25 @@
|
||||
.coveragerc
|
||||
.gitignore
|
||||
CHANGES.rst
|
||||
COPYRIGHT.txt
|
||||
LICENSE.txt
|
||||
MANIFEST.in
|
||||
README.rst
|
||||
buildout.cfg
|
||||
pip-delete-this-directory.txt
|
||||
setup.cfg
|
||||
setup.py
|
||||
tox.ini
|
||||
include/ExtensionClass/ExtensionClass.h
|
||||
include/ExtensionClass/_compat.h
|
||||
src/Acquisition/Acquisition.h
|
||||
src/Acquisition/_Acquisition.c
|
||||
src/Acquisition/__init__.py
|
||||
src/Acquisition/interfaces.py
|
||||
src/Acquisition/tests.py
|
||||
src/Acquisition.egg-info/PKG-INFO
|
||||
src/Acquisition.egg-info/SOURCES.txt
|
||||
src/Acquisition.egg-info/dependency_links.txt
|
||||
src/Acquisition.egg-info/not-zip-safe
|
||||
src/Acquisition.egg-info/requires.txt
|
||||
src/Acquisition.egg-info/top_level.txt
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1,15 @@
|
||||
../Acquisition/Acquisition.h
|
||||
../Acquisition/_Acquisition.c
|
||||
../Acquisition/_Acquisition.cpython-36m-darwin.so
|
||||
../Acquisition/__init__.py
|
||||
../Acquisition/__pycache__/__init__.cpython-36.pyc
|
||||
../Acquisition/__pycache__/interfaces.cpython-36.pyc
|
||||
../Acquisition/__pycache__/tests.cpython-36.pyc
|
||||
../Acquisition/interfaces.py
|
||||
../Acquisition/tests.py
|
||||
PKG-INFO
|
||||
SOURCES.txt
|
||||
dependency_links.txt
|
||||
not-zip-safe
|
||||
requires.txt
|
||||
top_level.txt
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1,2 @@
|
||||
ExtensionClass>=4.2.0
|
||||
zope.interface
|
@ -0,0 +1 @@
|
||||
Acquisition
|
@ -0,0 +1,53 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996-2002 Zope Foundation and Contributors.
|
||||
All Rights Reserved.
|
||||
|
||||
This software is subject to the provisions of the Zope Public License,
|
||||
Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ACQUISITION_H_
|
||||
#define __ACQUISITION_H_
|
||||
|
||||
typedef struct {
|
||||
PyObject *(*AQ_Acquire) (PyObject *obj, PyObject *name, PyObject *filter,
|
||||
PyObject *extra, int explicit, PyObject *deflt,
|
||||
int containment);
|
||||
PyObject *(*AQ_Get) (PyObject *obj, PyObject *name, PyObject *deflt,
|
||||
int containment);
|
||||
int (*AQ_IsWrapper) (PyObject *obj);
|
||||
PyObject *(*AQ_Base) (PyObject *obj);
|
||||
PyObject *(*AQ_Parent) (PyObject *obj);
|
||||
PyObject *(*AQ_Self) (PyObject *obj);
|
||||
PyObject *(*AQ_Inner) (PyObject *obj);
|
||||
PyObject *(*AQ_Chain) (PyObject *obj, int containment);
|
||||
} ACQUISITIONCAPI;
|
||||
|
||||
#ifndef _IN_ACQUISITION_C
|
||||
|
||||
#define aq_Acquire(obj, name, filter, extra, explicit, deflt, containment ) (AcquisitionCAPI == NULL ? NULL : (AcquisitionCAPI->AQ_Acquire(obj, name, filter, extra, explicit, deflt, containment)))
|
||||
#define aq_acquire(obj, name) (AcquisitionCAPI == NULL ? NULL : (AcquisitionCAPI->AQ_Acquire(obj, name, NULL, NULL, 1, NULL, 0)))
|
||||
#define aq_get(obj, name, deflt, containment) (AcquisitionCAPI == NULL ? NULL : (AcquisitionCAPI->AQ_Get(obj, name, deflt, containment)))
|
||||
#define aq_isWrapper(obj) (AcquisitionCAPI == NULL ? -1 : (AcquisitionCAPI->AQ_IsWrapper(obj)))
|
||||
#define aq_base(obj) (AcquisitionCAPI == NULL ? NULL : (AcquisitionCAPI->AQ_Base(obj)))
|
||||
#define aq_parent(obj) (AcquisitionCAPI == NULL ? NULL : (AcquisitionCAPI->AQ_Parent(obj)))
|
||||
#define aq_self(obj) (AcquisitionCAPI == NULL ? NULL : (AcquisitionCAPI->AQ_Self(obj)))
|
||||
#define aq_inner(obj) (AcquisitionCAPI == NULL ? NULL : (AcquisitionCAPI->AQ_Inner(obj)))
|
||||
#define aq_chain(obj, containment) (AcquisitionCAPI == NULL ? NULL : (AcquisitionCAPI->AQ_CHain(obj, containment)))
|
||||
|
||||
static ACQUISITIONCAPI *AcquisitionCAPI = NULL;
|
||||
|
||||
#define aq_init() { \
|
||||
AcquisitionCAPI = PyCapsule_Import("Acquisition.AcquisitionCAPI", 0); \
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
2072
thesisenv/lib/python3.6/site-packages/Acquisition/_Acquisition.c
Normal file
2072
thesisenv/lib/python3.6/site-packages/Acquisition/_Acquisition.c
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
953
thesisenv/lib/python3.6/site-packages/Acquisition/__init__.py
Normal file
953
thesisenv/lib/python3.6/site-packages/Acquisition/__init__.py
Normal file
@ -0,0 +1,953 @@
|
||||
from __future__ import absolute_import, print_function
|
||||
|
||||
# pylint:disable=W0212,R0911,R0912
|
||||
|
||||
|
||||
import os
|
||||
import operator
|
||||
import platform
|
||||
import sys
|
||||
import types
|
||||
import weakref
|
||||
|
||||
import ExtensionClass
|
||||
|
||||
from zope.interface import classImplements
|
||||
|
||||
from .interfaces import IAcquirer
|
||||
from .interfaces import IAcquisitionWrapper
|
||||
|
||||
IS_PYPY = getattr(platform, 'python_implementation', lambda: None)() == 'PyPy'
|
||||
IS_PURE = 'PURE_PYTHON' in os.environ
|
||||
|
||||
|
||||
class Acquired(object):
|
||||
"Marker for explicit acquisition"
|
||||
|
||||
|
||||
_NOT_FOUND = object() # marker
|
||||
|
||||
###
|
||||
# Helper functions
|
||||
###
|
||||
|
||||
|
||||
def _has__of__(obj):
|
||||
"""Check whether an object has an __of__ method for returning itself
|
||||
in the context of a container."""
|
||||
# It is necessary to check both the type (or we get into cycles)
|
||||
# as well as the presence of the method (or mixins of Base pre- or
|
||||
# post-class-creation as done in, e.g.,
|
||||
# zopefoundation/Persistence) can fail.
|
||||
return (isinstance(obj, ExtensionClass.Base) and
|
||||
hasattr(type(obj), '__of__'))
|
||||
|
||||
|
||||
def _apply_filter(predicate, inst, name, result, extra, orig):
|
||||
return predicate(orig, inst, name, result, extra)
|
||||
|
||||
|
||||
if sys.version_info < (3,):
|
||||
import copy_reg
|
||||
|
||||
def _rebound_method(method, wrapper):
|
||||
"""Returns a version of the method with self bound to `wrapper`"""
|
||||
if isinstance(method, types.MethodType):
|
||||
method = types.MethodType(method.im_func, wrapper, method.im_class)
|
||||
return method
|
||||
exec("""def _reraise(tp, value, tb=None):
|
||||
raise tp, value, tb
|
||||
""")
|
||||
else: # pragma: no cover (python 2 is currently our reference)
|
||||
import copyreg as copy_reg
|
||||
|
||||
def _rebound_method(method, wrapper):
|
||||
"""Returns a version of the method with self bound to `wrapper`"""
|
||||
if isinstance(method, types.MethodType):
|
||||
method = types.MethodType(method.__func__, wrapper)
|
||||
return method
|
||||
|
||||
def _reraise(tp, value, tb=None):
|
||||
if value is None:
|
||||
value = tp()
|
||||
if value.__traceback__ is not tb:
|
||||
raise value.with_traceback(tb)
|
||||
raise value
|
||||
|
||||
###
|
||||
# Wrapper object protocol, mostly ported from C directly
|
||||
###
|
||||
|
||||
|
||||
def _Wrapper_findspecial(wrapper, name):
|
||||
"""
|
||||
Looks up the special acquisition attributes of an object.
|
||||
:param str name: The attribute to find, with 'aq' already stripped.
|
||||
"""
|
||||
|
||||
result = _NOT_FOUND
|
||||
|
||||
if name == 'base':
|
||||
result = wrapper._obj
|
||||
while isinstance(result, _Wrapper) and result._obj is not None:
|
||||
result = result._obj
|
||||
elif name == 'parent':
|
||||
result = wrapper._container
|
||||
elif name == 'self':
|
||||
result = wrapper._obj
|
||||
elif name == 'explicit':
|
||||
if type(wrapper)._IS_IMPLICIT:
|
||||
result = ExplicitAcquisitionWrapper(
|
||||
wrapper._obj, wrapper._container)
|
||||
else:
|
||||
result = wrapper
|
||||
elif name == 'acquire':
|
||||
result = object.__getattribute__(wrapper, 'aq_acquire')
|
||||
elif name == 'chain':
|
||||
# XXX: C has a second implementation here
|
||||
result = aq_chain(wrapper)
|
||||
elif name == 'inContextOf':
|
||||
result = object.__getattribute__(wrapper, 'aq_inContextOf')
|
||||
elif name == 'inner':
|
||||
# XXX: C has a second implementation here
|
||||
result = aq_inner(wrapper)
|
||||
elif name == 'uncle':
|
||||
result = 'Bob'
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _Wrapper_acquire(wrapper, name,
|
||||
predicate=None, predicate_extra=None,
|
||||
orig_object=None,
|
||||
explicit=True, containment=True):
|
||||
"""
|
||||
Attempt to acquire the `name` from the parent of the wrapper.
|
||||
|
||||
:raises AttributeError: If the wrapper has no parent or the
|
||||
attribute cannot be found.
|
||||
"""
|
||||
|
||||
if wrapper._container is None:
|
||||
raise AttributeError(name)
|
||||
|
||||
search_self = True
|
||||
search_parent = True
|
||||
|
||||
# If the container has an acquisition wrapper itself, we'll use
|
||||
# _Wrapper_findattr to progress further
|
||||
if isinstance(wrapper._container, _Wrapper):
|
||||
if isinstance(wrapper._obj, _Wrapper):
|
||||
# try to optimize search by recognizing repeated objects in path
|
||||
if wrapper._obj._container is wrapper._container._container:
|
||||
search_parent = False
|
||||
elif wrapper._obj._container is wrapper._container._obj:
|
||||
search_self = False
|
||||
|
||||
# Don't search the container when the container of the container
|
||||
# is the same object as `wrapper`
|
||||
if wrapper._container._container is wrapper._obj:
|
||||
search_parent = False
|
||||
containment = True
|
||||
result = _Wrapper_findattr(wrapper._container, name,
|
||||
predicate=predicate,
|
||||
predicate_extra=predicate_extra,
|
||||
orig_object=orig_object,
|
||||
search_self=search_self,
|
||||
search_parent=search_parent,
|
||||
explicit=explicit,
|
||||
containment=containment)
|
||||
# XXX: Why does this branch of the C code check __of__,
|
||||
# but the next one doesn't?
|
||||
if _has__of__(result):
|
||||
result = result.__of__(wrapper)
|
||||
return result
|
||||
|
||||
# If the container has a __parent__ pointer, we create an
|
||||
# acquisition wrapper for it accordingly. Then we can proceed
|
||||
# with Wrapper_findattr, just as if the container had an
|
||||
# acquisition wrapper in the first place (see above).
|
||||
# NOTE: This mutates the wrapper
|
||||
elif hasattr(wrapper._container, '__parent__'):
|
||||
parent = wrapper._container.__parent__
|
||||
# Don't search the container when the parent of the parent
|
||||
# is the same object as 'self'
|
||||
if parent is wrapper._obj:
|
||||
search_parent = False
|
||||
elif isinstance(parent, _Wrapper) and parent._obj is wrapper._obj:
|
||||
# XXX: C code just does parent._obj, assumes its a wrapper
|
||||
search_parent = False
|
||||
|
||||
wrapper._container = ImplicitAcquisitionWrapper(
|
||||
wrapper._container, parent)
|
||||
return _Wrapper_findattr(wrapper._container, name,
|
||||
predicate=predicate,
|
||||
predicate_extra=predicate_extra,
|
||||
orig_object=orig_object,
|
||||
search_self=search_self,
|
||||
search_parent=search_parent,
|
||||
explicit=explicit,
|
||||
containment=containment)
|
||||
else:
|
||||
# The container is the end of the acquisition chain; if we
|
||||
# can't look up the attributes here, we can't look it up at all
|
||||
result = getattr(wrapper._container, name)
|
||||
if result is not Acquired:
|
||||
if predicate:
|
||||
if _apply_filter(predicate, wrapper._container, name,
|
||||
result, predicate_extra, orig_object):
|
||||
return (result.__of__(wrapper)
|
||||
if _has__of__(result) else result)
|
||||
else:
|
||||
raise AttributeError(name)
|
||||
else:
|
||||
if _has__of__(result):
|
||||
result = result.__of__(wrapper)
|
||||
return result
|
||||
|
||||
# this line cannot be reached
|
||||
raise AttributeError(name) # pragma: no cover
|
||||
|
||||
|
||||
def _Wrapper_findattr(wrapper, name,
|
||||
predicate=None, predicate_extra=None,
|
||||
orig_object=None,
|
||||
search_self=True, search_parent=True,
|
||||
explicit=True, containment=True):
|
||||
"""
|
||||
Search the `wrapper` object for the attribute `name`.
|
||||
|
||||
:param bool search_self: Search `wrapper.aq_self` for the attribute.
|
||||
:param bool search_parent: Search `wrapper.aq_parent` for the attribute.
|
||||
:param bool explicit: Explicitly acquire the attribute from the parent
|
||||
(should be assumed with implicit wrapper)
|
||||
:param bool containment: Use the innermost wrapper (`aq_inner`)
|
||||
for looking up the attribute.
|
||||
"""
|
||||
|
||||
orig_name = name
|
||||
if orig_object is None:
|
||||
orig_object = wrapper
|
||||
|
||||
# First, special names
|
||||
if name.startswith('aq') or name == '__parent__':
|
||||
# __parent__ is an alias of aq_parent
|
||||
if name == '__parent__':
|
||||
name = 'parent'
|
||||
else:
|
||||
name = name[3:]
|
||||
|
||||
result = _Wrapper_findspecial(wrapper, name)
|
||||
if result is not _NOT_FOUND:
|
||||
if predicate:
|
||||
if _apply_filter(predicate, wrapper, orig_name,
|
||||
result, predicate_extra, orig_object):
|
||||
return result
|
||||
else:
|
||||
raise AttributeError(orig_name)
|
||||
return result
|
||||
elif name in ('__reduce__', '__reduce_ex__', '__getstate__',
|
||||
'__of__', '__cmp__', '__eq__', '__ne__', '__lt__',
|
||||
'__le__', '__gt__', '__ge__'):
|
||||
return object.__getattribute__(wrapper, orig_name)
|
||||
|
||||
# If we're doing a containment search, replace the wrapper with aq_inner
|
||||
if containment:
|
||||
while isinstance(wrapper._obj, _Wrapper):
|
||||
wrapper = wrapper._obj
|
||||
|
||||
if search_self and wrapper._obj is not None:
|
||||
if isinstance(wrapper._obj, _Wrapper):
|
||||
if wrapper is wrapper._obj:
|
||||
raise RuntimeError("Recursion detected in acquisition wrapper")
|
||||
try:
|
||||
result = _Wrapper_findattr(wrapper._obj, orig_name,
|
||||
predicate=predicate,
|
||||
predicate_extra=predicate_extra,
|
||||
orig_object=orig_object,
|
||||
search_self=True,
|
||||
search_parent=explicit or isinstance(wrapper._obj, ImplicitAcquisitionWrapper), # NOQA
|
||||
explicit=explicit,
|
||||
containment=containment)
|
||||
if isinstance(result, types.MethodType):
|
||||
result = _rebound_method(result, wrapper)
|
||||
elif _has__of__(result):
|
||||
result = result.__of__(wrapper)
|
||||
return result
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# deal with mixed __parent__ / aq_parent circles
|
||||
elif (isinstance(wrapper._container, _Wrapper) and
|
||||
wrapper._container._container is wrapper):
|
||||
raise RuntimeError("Recursion detected in acquisition wrapper")
|
||||
else:
|
||||
# normal attribute lookup
|
||||
try:
|
||||
result = getattr(wrapper._obj, orig_name)
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
if result is Acquired:
|
||||
return _Wrapper_acquire(wrapper, orig_name,
|
||||
predicate=predicate,
|
||||
predicate_extra=predicate_extra,
|
||||
orig_object=orig_object,
|
||||
explicit=True,
|
||||
containment=containment)
|
||||
|
||||
if isinstance(result, types.MethodType):
|
||||
result = _rebound_method(result, wrapper)
|
||||
elif _has__of__(result):
|
||||
result = result.__of__(wrapper)
|
||||
|
||||
if predicate:
|
||||
if _apply_filter(predicate, wrapper, orig_name,
|
||||
result, predicate_extra, orig_object):
|
||||
return result
|
||||
else:
|
||||
return result
|
||||
|
||||
# lookup has failed, acquire from the parent
|
||||
if search_parent and (not name.startswith('_') or explicit):
|
||||
return _Wrapper_acquire(wrapper, orig_name,
|
||||
predicate=predicate,
|
||||
predicate_extra=predicate_extra,
|
||||
orig_object=orig_object,
|
||||
explicit=explicit,
|
||||
containment=containment)
|
||||
|
||||
raise AttributeError(orig_name)
|
||||
|
||||
|
||||
_NOT_GIVEN = object() # marker
|
||||
_OGA = object.__getattribute__
|
||||
|
||||
# Map from object types with slots to their generated, derived
|
||||
# types (or None if no derived type is needed)
|
||||
_wrapper_subclass_cache = weakref.WeakKeyDictionary()
|
||||
|
||||
|
||||
def _make_wrapper_subclass_if_needed(cls, obj, container):
|
||||
# If the type of an object to be wrapped has __slots__, then we
|
||||
# must create a wrapper subclass that has descriptors for those
|
||||
# same slots. In this way, its methods that use object.__getattribute__
|
||||
# directly will continue to work, even when given an instance of _Wrapper
|
||||
if getattr(cls, '_Wrapper__DERIVED', False):
|
||||
return None
|
||||
type_obj = type(obj)
|
||||
wrapper_subclass = _wrapper_subclass_cache.get(type_obj, _NOT_GIVEN)
|
||||
if wrapper_subclass is _NOT_GIVEN:
|
||||
slotnames = copy_reg._slotnames(type_obj)
|
||||
if slotnames and not isinstance(obj, _Wrapper):
|
||||
new_type_dict = {'_Wrapper__DERIVED': True}
|
||||
|
||||
def _make_property(slotname):
|
||||
return property(lambda s: getattr(s._obj, slotname),
|
||||
lambda s, v: setattr(s._obj, slotname, v),
|
||||
lambda s: delattr(s._obj, slotname))
|
||||
for slotname in slotnames:
|
||||
new_type_dict[slotname] = _make_property(slotname)
|
||||
new_type = type(cls.__name__ + '_' + type_obj.__name__,
|
||||
(cls,),
|
||||
new_type_dict)
|
||||
else:
|
||||
new_type = None
|
||||
wrapper_subclass = _wrapper_subclass_cache[type_obj] = new_type
|
||||
|
||||
return wrapper_subclass
|
||||
|
||||
|
||||
class _Wrapper(ExtensionClass.Base):
|
||||
__slots__ = ('_obj', '_container', '__dict__')
|
||||
_IS_IMPLICIT = None
|
||||
|
||||
def __new__(cls, obj, container):
|
||||
wrapper_subclass = _make_wrapper_subclass_if_needed(cls, obj, container) # NOQA
|
||||
if wrapper_subclass:
|
||||
inst = wrapper_subclass(obj, container)
|
||||
else:
|
||||
inst = super(_Wrapper, cls).__new__(cls)
|
||||
inst._obj = obj
|
||||
inst._container = container
|
||||
if hasattr(obj, '__dict__') and not isinstance(obj, _Wrapper):
|
||||
# Make our __dict__ refer to the same dict as the other object,
|
||||
# so that if it has methods that use `object.__getattribute__`
|
||||
# they still work. Note that because we have slots,
|
||||
# we won't interfere with the contents of that dict.
|
||||
object.__setattr__(inst, '__dict__', obj.__dict__)
|
||||
return inst
|
||||
|
||||
def __init__(self, obj, container):
|
||||
super(_Wrapper, self).__init__()
|
||||
self._obj = obj
|
||||
self._container = container
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
if name == '__parent__' or name == 'aq_parent':
|
||||
object.__setattr__(self, '_container', value)
|
||||
return
|
||||
if name == '_obj' or name == '_container':
|
||||
# should only happen at init time
|
||||
object.__setattr__(self, name, value)
|
||||
return
|
||||
|
||||
# If we are wrapping something, unwrap passed in wrappers
|
||||
if self._obj is None:
|
||||
raise AttributeError(
|
||||
'Attempt to set attribute on empty acquisition wrapper')
|
||||
|
||||
while value is not None and isinstance(value, _Wrapper):
|
||||
value = value._obj
|
||||
|
||||
setattr(self._obj, name, value)
|
||||
|
||||
def __delattr__(self, name):
|
||||
if name == '__parent__' or name == 'aq_parent':
|
||||
self._container = None
|
||||
else:
|
||||
delattr(self._obj, name)
|
||||
|
||||
def __getattribute__(self, name):
|
||||
if name in ('_obj', '_container'):
|
||||
return _OGA(self, name)
|
||||
if (_OGA(self, '_obj') is not None or
|
||||
_OGA(self, '_container') is not None):
|
||||
return _Wrapper_findattr(self, name, None, None, None, True,
|
||||
type(self)._IS_IMPLICIT, False, False)
|
||||
return _OGA(self, name)
|
||||
|
||||
def __of__(self, parent):
|
||||
# Based on __of__ in the C code;
|
||||
# simplify a layer of wrapping.
|
||||
|
||||
# We have to call the raw __of__ method or we recurse on our
|
||||
# own lookup (the C code does not have this issue, it can use
|
||||
# the wrapped __of__ method because it gets here via the
|
||||
# descriptor code path)...
|
||||
wrapper = self._obj.__of__(parent)
|
||||
if (not isinstance(wrapper, _Wrapper) or
|
||||
not isinstance(wrapper._container, _Wrapper)):
|
||||
return wrapper
|
||||
# but the returned wrapper should be based on this object's
|
||||
# wrapping chain
|
||||
wrapper._obj = self
|
||||
|
||||
while (isinstance(wrapper._obj, _Wrapper) and
|
||||
(wrapper._obj._container is wrapper._container._obj)):
|
||||
# Since we mutate the wrapper as we walk up, we must copy
|
||||
# XXX: This comes from the C implementation. Do we really need to
|
||||
# copy?
|
||||
wrapper = type(wrapper)(wrapper._obj, wrapper._container)
|
||||
wrapper._obj = wrapper._obj._obj
|
||||
return wrapper
|
||||
|
||||
def aq_acquire(self, name,
|
||||
filter=None, extra=None,
|
||||
explicit=True,
|
||||
default=_NOT_GIVEN,
|
||||
containment=False):
|
||||
try:
|
||||
return _Wrapper_findattr(self, name,
|
||||
predicate=filter,
|
||||
predicate_extra=extra,
|
||||
orig_object=self,
|
||||
search_self=True,
|
||||
search_parent=explicit or type(self)._IS_IMPLICIT, # NOQA
|
||||
explicit=explicit,
|
||||
containment=containment)
|
||||
except AttributeError:
|
||||
if default is _NOT_GIVEN:
|
||||
raise
|
||||
return default
|
||||
|
||||
acquire = aq_acquire
|
||||
|
||||
def aq_inContextOf(self, o, inner=True):
|
||||
return aq_inContextOf(self, o, inner=inner)
|
||||
|
||||
# Wrappers themselves are not picklable, but if the underlying
|
||||
# object has a _p_oid, then the __getnewargs__ method is allowed
|
||||
def __reduce__(self, *args):
|
||||
raise TypeError("Can't pickle objects in acquisition wrappers.")
|
||||
__reduce_ex__ = __reduce__
|
||||
__getstate__ = __reduce__
|
||||
|
||||
def __getnewargs__(self):
|
||||
return ()
|
||||
|
||||
# Equality and comparisons
|
||||
|
||||
def __hash__(self):
|
||||
# The C implementation doesn't pass the wrapper
|
||||
# to any __hash__ that the object implements,
|
||||
# so it can't access derived attributes.
|
||||
# (If that changes, just add this to __unary_special_methods__
|
||||
# and remove this method)
|
||||
return hash(self._obj)
|
||||
|
||||
# The C implementation forces all comparisons through the
|
||||
# __cmp__ method, if it's implemented. If it's not implemented,
|
||||
# then comparisons are based strictly on the memory addresses
|
||||
# of the underlying object (aq_base). We could mostly emulate
|
||||
# this behaviour on Python 2, but on Python 3 __cmp__ is gone,
|
||||
# so users won't have an expectation to write it.
|
||||
# Because users have never had an expectation that the rich comparison
|
||||
# methods would be called on their wrapped objects (and so would not be
|
||||
# accessing acquired attributes there), we can't/don't want to start
|
||||
# proxying to them?
|
||||
# For the moment, we settle for an emulation of the C behaviour:
|
||||
# define __cmp__ the same way, and redirect the rich comparison operators
|
||||
# to it. (Note that these attributes are also hardcoded in getattribute)
|
||||
def __cmp__(self, other):
|
||||
aq_self = self._obj
|
||||
if hasattr(type(aq_self), '__cmp__'):
|
||||
return _rebound_method(aq_self.__cmp__, self)(other)
|
||||
|
||||
my_base = aq_base(self)
|
||||
other_base = aq_base(other)
|
||||
if my_base is other_base:
|
||||
return 0
|
||||
return -1 if id(my_base) < id(other_base) else 1
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.__cmp__(other) == 0
|
||||
|
||||
def __ne__(self, other):
|
||||
return self.__cmp__(other) != 0
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.__cmp__(other) < 0
|
||||
|
||||
def __le__(self, other):
|
||||
return self.__cmp__(other) <= 0
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.__cmp__(other) > 0
|
||||
|
||||
def __ge__(self, other):
|
||||
return self.__cmp__(other) >= 0
|
||||
|
||||
# Special methods looked up by the type of self._obj,
|
||||
# but which must have the wrapper as self when called
|
||||
|
||||
def __nonzero__(self):
|
||||
aq_self = self._obj
|
||||
type_aq_self = type(aq_self)
|
||||
nonzero = getattr(type_aq_self, '__nonzero__', None)
|
||||
if nonzero is None:
|
||||
# Py3 bool?
|
||||
nonzero = getattr(type_aq_self, '__bool__', None)
|
||||
if nonzero is None:
|
||||
# a len?
|
||||
nonzero = getattr(type_aq_self, '__len__', None)
|
||||
if nonzero:
|
||||
return bool(nonzero(self)) # Py3 is strict about the return type
|
||||
# If nothing was defined, then it's true
|
||||
return True
|
||||
__bool__ = __nonzero__
|
||||
|
||||
def __unicode__(self):
|
||||
f = getattr(self.aq_self, '__unicode__',
|
||||
getattr(self.aq_self, '__str__', object.__str__))
|
||||
return _rebound_method(f, self)()
|
||||
|
||||
def __repr__(self):
|
||||
aq_self = self._obj
|
||||
try:
|
||||
return _rebound_method(aq_self.__repr__, self)()
|
||||
except (AttributeError, TypeError):
|
||||
return repr(aq_self)
|
||||
|
||||
def __str__(self):
|
||||
aq_self = self._obj
|
||||
try:
|
||||
return _rebound_method(aq_self.__str__, self)()
|
||||
except (AttributeError, TypeError): # pragma: no cover (Only Py3)
|
||||
return str(aq_self)
|
||||
|
||||
__binary_special_methods__ = [
|
||||
# general numeric
|
||||
'__add__',
|
||||
'__sub__',
|
||||
'__mul__',
|
||||
'__matmul__',
|
||||
'__floordiv__', # not implemented in C
|
||||
'__mod__',
|
||||
'__divmod__',
|
||||
'__pow__',
|
||||
'__lshift__',
|
||||
'__rshift__',
|
||||
'__and__',
|
||||
'__xor__',
|
||||
'__or__',
|
||||
|
||||
# division; only one of these will be used at any one time
|
||||
'__truediv__',
|
||||
'__div__',
|
||||
|
||||
# reflected numeric
|
||||
'__radd__',
|
||||
'__rsub__',
|
||||
'__rmul__',
|
||||
'__rdiv__',
|
||||
'__rtruediv__',
|
||||
'__rfloordiv__',
|
||||
'__rmod__',
|
||||
'__rdivmod__',
|
||||
'__rpow__',
|
||||
'__rlshift__',
|
||||
'__rrshift__',
|
||||
'__rand__',
|
||||
'__rxor__',
|
||||
'__ror__',
|
||||
|
||||
# in place numeric
|
||||
'__iadd__',
|
||||
'__isub__',
|
||||
'__imul__',
|
||||
'__imatmul__',
|
||||
'__idiv__',
|
||||
'__itruediv__',
|
||||
'__ifloordiv__',
|
||||
'__imod__',
|
||||
'__idivmod__',
|
||||
'__ipow__',
|
||||
'__ilshift__',
|
||||
'__irshift__',
|
||||
'__iand__',
|
||||
'__ixor__',
|
||||
'__ior__',
|
||||
|
||||
# conversion
|
||||
'__coerce__',
|
||||
|
||||
# container
|
||||
'__delitem__',
|
||||
]
|
||||
|
||||
__unary_special_methods__ = [
|
||||
# arithmetic
|
||||
'__neg__',
|
||||
'__pos__',
|
||||
'__abs__',
|
||||
'__invert__',
|
||||
|
||||
# conversion
|
||||
'__complex__',
|
||||
'__int__',
|
||||
'__long__',
|
||||
'__float__',
|
||||
'__oct__',
|
||||
'__hex__',
|
||||
'__index__',
|
||||
# '__len__',
|
||||
|
||||
# strings are special
|
||||
# '__repr__',
|
||||
# '__str__',
|
||||
]
|
||||
|
||||
for _name in __binary_special_methods__:
|
||||
def _make_op(_name):
|
||||
def op(self, other):
|
||||
aq_self = self._obj
|
||||
return getattr(type(aq_self), _name)(self, other)
|
||||
return op
|
||||
locals()[_name] = _make_op(_name)
|
||||
|
||||
for _name in __unary_special_methods__:
|
||||
def _make_op(_name):
|
||||
def op(self):
|
||||
aq_self = self._obj
|
||||
return getattr(type(aq_self), _name)(self)
|
||||
return op
|
||||
locals()[_name] = _make_op(_name)
|
||||
|
||||
del _make_op
|
||||
del _name
|
||||
|
||||
# Container protocol
|
||||
|
||||
def __len__(self):
|
||||
# if len is missing, it should raise TypeError
|
||||
# (AttributeError is acceptable under Py2, but Py3
|
||||
# breaks list conversion if AttributeError is raised)
|
||||
try:
|
||||
l = getattr(type(self._obj), '__len__')
|
||||
except AttributeError:
|
||||
raise TypeError('object has no len()')
|
||||
else:
|
||||
return l(self)
|
||||
|
||||
def __iter__(self):
|
||||
# For things that provide either __iter__ or just __getitem__,
|
||||
# we need to be sure that the wrapper is provided as self
|
||||
if hasattr(self._obj, '__iter__'):
|
||||
return _rebound_method(self._obj.__iter__, self)()
|
||||
if hasattr(self._obj, '__getitem__'):
|
||||
# Unfortunately we cannot simply call iter(self._obj)
|
||||
# and rebind im_self like we do above: the Python runtime
|
||||
# complains:
|
||||
# (TypeError: 'sequenceiterator' expected, got 'Wrapper' instead)
|
||||
|
||||
class WrapperIter(object):
|
||||
__slots__ = ('_wrapper',)
|
||||
|
||||
def __init__(self, o):
|
||||
self._wrapper = o
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self._wrapper.__getitem__(i)
|
||||
it = WrapperIter(self)
|
||||
return iter(it)
|
||||
|
||||
return iter(self._obj)
|
||||
|
||||
def __contains__(self, item):
|
||||
# First, if the type of the object defines __contains__ then
|
||||
# use it
|
||||
aq_self = self._obj
|
||||
aq_contains = getattr(type(aq_self), '__contains__', None)
|
||||
if aq_contains:
|
||||
return aq_contains(self, item)
|
||||
# Next, we should attempt to iterate like the interpreter;
|
||||
# but the C code doesn't do this, so we don't either.
|
||||
# return item in iter(self)
|
||||
raise AttributeError('__contains__')
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
aq_self = self._obj
|
||||
try:
|
||||
setter = type(aq_self).__setitem__
|
||||
except AttributeError:
|
||||
raise AttributeError("__setitem__") # doctests care about the name
|
||||
else:
|
||||
setter(self, key, value)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if isinstance(key, slice) and hasattr(operator, 'getslice'):
|
||||
# Only on Python 2
|
||||
# XXX: This is probably not proxying correctly, but the existing
|
||||
# tests pass with this behaviour
|
||||
return operator.getslice(
|
||||
self._obj,
|
||||
key.start if key.start is not None else 0,
|
||||
key.stop if key.stop is not None else sys.maxint)
|
||||
|
||||
aq_self = self._obj
|
||||
try:
|
||||
getter = type(aq_self).__getitem__
|
||||
except AttributeError:
|
||||
raise AttributeError("__getitem__") # doctests care about the name
|
||||
else:
|
||||
return getter(self, key)
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
try:
|
||||
# Note we look this up on the completely unwrapped
|
||||
# object, so as not to get a class
|
||||
call = getattr(self.aq_base, '__call__')
|
||||
except AttributeError: # pragma: no cover
|
||||
# A TypeError is what the interpreter raises;
|
||||
# AttributeError is allowed to percolate through the
|
||||
# C proxy
|
||||
raise TypeError('object is not callable')
|
||||
else:
|
||||
return _rebound_method(call, self)(*args, **kwargs)
|
||||
|
||||
|
||||
class ImplicitAcquisitionWrapper(_Wrapper):
|
||||
_IS_IMPLICIT = True
|
||||
|
||||
|
||||
class ExplicitAcquisitionWrapper(_Wrapper):
|
||||
_IS_IMPLICIT = False
|
||||
|
||||
def __getattribute__(self, name):
|
||||
# Special case backwards-compatible acquire method
|
||||
if name == 'acquire':
|
||||
return object.__getattribute__(self, name)
|
||||
|
||||
return _Wrapper.__getattribute__(self, name)
|
||||
|
||||
|
||||
class _Acquirer(ExtensionClass.Base):
|
||||
|
||||
def __getattribute__(self, name):
|
||||
try:
|
||||
return super(_Acquirer, self).__getattribute__(name)
|
||||
except AttributeError:
|
||||
# the doctests have very specific error message
|
||||
# requirements (but at least we can preserve the traceback)
|
||||
_, _, tb = sys.exc_info()
|
||||
try:
|
||||
_reraise(AttributeError, AttributeError(name), tb)
|
||||
finally:
|
||||
del tb
|
||||
|
||||
def __of__(self, context):
|
||||
return type(self)._Wrapper(self, context)
|
||||
|
||||
|
||||
class Implicit(_Acquirer):
|
||||
_Wrapper = ImplicitAcquisitionWrapper
|
||||
|
||||
|
||||
ImplicitAcquisitionWrapper._Wrapper = ImplicitAcquisitionWrapper
|
||||
|
||||
|
||||
class Explicit(_Acquirer):
|
||||
_Wrapper = ExplicitAcquisitionWrapper
|
||||
|
||||
|
||||
ExplicitAcquisitionWrapper._Wrapper = ExplicitAcquisitionWrapper
|
||||
|
||||
###
|
||||
# Exported module functions
|
||||
###
|
||||
|
||||
|
||||
def aq_acquire(obj, name,
|
||||
filter=None, extra=None,
|
||||
explicit=True,
|
||||
default=_NOT_GIVEN,
|
||||
containment=False):
|
||||
if isinstance(obj, _Wrapper):
|
||||
return obj.aq_acquire(name,
|
||||
filter=filter, extra=extra,
|
||||
default=default,
|
||||
explicit=explicit or type(obj)._IS_IMPLICIT,
|
||||
containment=containment)
|
||||
|
||||
# Does it have a parent, or do we have a filter?
|
||||
# Then go through the acquisition code
|
||||
if hasattr(obj, '__parent__') or filter is not None:
|
||||
parent = getattr(obj, '__parent__', None)
|
||||
return aq_acquire(ImplicitAcquisitionWrapper(obj, parent),
|
||||
name,
|
||||
filter=filter, extra=extra,
|
||||
default=default,
|
||||
explicit=explicit,
|
||||
containment=containment)
|
||||
|
||||
# no parent and no filter, simple case
|
||||
try:
|
||||
return getattr(obj, name)
|
||||
except AttributeError:
|
||||
if default is _NOT_GIVEN:
|
||||
raise AttributeError(name) # doctests are strict
|
||||
return default
|
||||
|
||||
|
||||
def aq_parent(obj):
|
||||
# needs to be safe to call from __getattribute__ of a wrapper
|
||||
# and reasonably fast
|
||||
if isinstance(obj, _Wrapper):
|
||||
return object.__getattribute__(obj, '_container')
|
||||
# if not a wrapper, deal with the __parent__
|
||||
return getattr(obj, '__parent__', None)
|
||||
|
||||
|
||||
def aq_chain(obj, containment=False):
|
||||
result = []
|
||||
|
||||
while True:
|
||||
if isinstance(obj, _Wrapper):
|
||||
if obj._obj is not None:
|
||||
if containment:
|
||||
while isinstance(obj._obj, _Wrapper):
|
||||
obj = obj._obj
|
||||
result.append(obj)
|
||||
if obj._container is not None:
|
||||
obj = obj._container
|
||||
continue
|
||||
else:
|
||||
result.append(obj)
|
||||
obj = getattr(obj, '__parent__', None)
|
||||
if obj is not None:
|
||||
continue
|
||||
|
||||
break
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def aq_base(obj):
|
||||
result = obj
|
||||
while isinstance(result, _Wrapper):
|
||||
result = result._obj
|
||||
return result
|
||||
|
||||
|
||||
def aq_get(obj, name, default=_NOT_GIVEN, containment=False):
|
||||
|
||||
# Not wrapped. If we have a __parent__ pointer, create a wrapper
|
||||
# and go as usual
|
||||
if not isinstance(obj, _Wrapper) and hasattr(obj, '__parent__'):
|
||||
obj = ImplicitAcquisitionWrapper(obj, obj.__parent__)
|
||||
|
||||
try:
|
||||
# We got a wrapped object, business as usual
|
||||
return (_Wrapper_findattr(obj, name, None, None, obj,
|
||||
True, True, True, containment)
|
||||
if isinstance(obj, _Wrapper)
|
||||
# ok, plain getattr
|
||||
else getattr(obj, name))
|
||||
except AttributeError:
|
||||
if default is _NOT_GIVEN:
|
||||
raise
|
||||
return default
|
||||
|
||||
|
||||
def aq_inner(obj):
|
||||
if not isinstance(obj, _Wrapper):
|
||||
return obj
|
||||
|
||||
result = obj._obj
|
||||
while isinstance(result, _Wrapper):
|
||||
obj = result
|
||||
result = result._obj
|
||||
result = obj
|
||||
return result
|
||||
|
||||
|
||||
def aq_self(obj):
|
||||
if isinstance(obj, _Wrapper):
|
||||
return obj.aq_self
|
||||
return obj
|
||||
|
||||
|
||||
def aq_inContextOf(self, o, inner=True):
|
||||
next = self
|
||||
o = aq_base(o)
|
||||
|
||||
while True:
|
||||
if aq_base(next) is o:
|
||||
return True
|
||||
|
||||
if inner:
|
||||
self = aq_inner(next)
|
||||
if self is None: # pragma: no cover
|
||||
# This branch is normally impossible to hit,
|
||||
# it just mirrors a check in C
|
||||
break
|
||||
else:
|
||||
self = next
|
||||
|
||||
next = aq_parent(self)
|
||||
if next is None:
|
||||
break
|
||||
|
||||
return False
|
||||
|
||||
|
||||
if not (IS_PYPY or IS_PURE): # pragma: no cover
|
||||
# Make sure we can import the C extension of our dependency.
|
||||
from ExtensionClass import _ExtensionClass # NOQA
|
||||
from ._Acquisition import * # NOQA
|
||||
|
||||
classImplements(Explicit, IAcquirer)
|
||||
classImplements(ExplicitAcquisitionWrapper, IAcquisitionWrapper)
|
||||
classImplements(Implicit, IAcquirer)
|
||||
classImplements(ImplicitAcquisitionWrapper, IAcquisitionWrapper)
|
@ -0,0 +1,62 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2005 Zope Foundation and Contributors.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
##############################################################################
|
||||
"""Acquisition z3 interfaces.
|
||||
|
||||
$Id$
|
||||
"""
|
||||
|
||||
from zope.interface import Attribute
|
||||
from zope.interface import Interface
|
||||
|
||||
|
||||
class IAcquirer(Interface):
|
||||
|
||||
"""Acquire attributes from containers.
|
||||
"""
|
||||
|
||||
def __of__(context):
|
||||
"""Get the object in a context.
|
||||
"""
|
||||
|
||||
|
||||
class IAcquisitionWrapper(Interface):
|
||||
|
||||
"""Wrapper object for acquisition.
|
||||
"""
|
||||
|
||||
def aq_acquire(name, filter=None, extra=None, explicit=True, default=0,
|
||||
containment=0):
|
||||
"""Get an attribute, acquiring it if necessary.
|
||||
"""
|
||||
|
||||
def aq_inContextOf(obj, inner=1):
|
||||
"""Test whether the object is currently in the context of the argument.
|
||||
"""
|
||||
|
||||
aq_base = Attribute(
|
||||
"""Get the object unwrapped.""")
|
||||
|
||||
aq_parent = Attribute(
|
||||
"""Get the parent of an object.""")
|
||||
|
||||
aq_self = Attribute(
|
||||
"""Get the object with the outermost wrapper removed.""")
|
||||
|
||||
aq_inner = Attribute(
|
||||
"""Get the object with all but the innermost wrapper removed.""")
|
||||
|
||||
aq_chain = Attribute(
|
||||
"""Get a list of objects in the acquisition environment.""")
|
||||
|
||||
aq_explicit = Attribute(
|
||||
"""Get the object with an explicit acquisition wrapper.""")
|
3349
thesisenv/lib/python3.6/site-packages/Acquisition/tests.py
Normal file
3349
thesisenv/lib/python3.6/site-packages/Acquisition/tests.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,25 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
AuthEncoding is a framework for handling LDAP style password hashes.
|
||||
|
||||
It is used in Zope2 but does not depend on any other Zope package.
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
4.0.0 (2015-09-30)
|
||||
------------------
|
||||
|
||||
- Supporting Python 3.3 up to 3.5 and PyPy2.
|
||||
|
||||
- Added ``SHA256DigestScheme``.
|
||||
|
||||
|
||||
3.0.0 (2015-09-28)
|
||||
------------------
|
||||
|
||||
- Extracted from ``AccessControl 3.0.11``
|
||||
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
pip
|
@ -0,0 +1,54 @@
|
||||
Metadata-Version: 2.0
|
||||
Name: AuthEncoding
|
||||
Version: 4.0.0
|
||||
Summary: Framework for handling LDAP style password hashes.
|
||||
Home-page: https://github.com/zopefoundation/AuthEncoding
|
||||
Author: Zope Foundation and Contributors
|
||||
Author-email: zope-dev@zope.org
|
||||
License: ZPL 2.1
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 6 - Mature
|
||||
Classifier: Environment :: Web Environment
|
||||
Classifier: Framework :: Zope2
|
||||
Classifier: License :: OSI Approved :: Zope Public License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.6
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory :: LDAP
|
||||
Requires-Dist: six
|
||||
Provides-Extra: test
|
||||
Requires-Dist: pytest; extra == 'test'
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
AuthEncoding is a framework for handling LDAP style password hashes.
|
||||
|
||||
It is used in Zope2 but does not depend on any other Zope package.
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
4.0.0 (2015-09-30)
|
||||
------------------
|
||||
|
||||
- Supporting Python 3.3 up to 3.5 and PyPy2.
|
||||
|
||||
- Added ``SHA256DigestScheme``.
|
||||
|
||||
|
||||
3.0.0 (2015-09-28)
|
||||
------------------
|
||||
|
||||
- Extracted from ``AccessControl 3.0.11``
|
||||
|
||||
|
||||
|
@ -0,0 +1,18 @@
|
||||
AuthEncoding-4.0.0.dist-info/DESCRIPTION.rst,sha256=UKoEVLqA6eoGuaGlkVcj4mZJUnzBr3IdyZ4rLj9tBY4,381
|
||||
AuthEncoding-4.0.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
AuthEncoding-4.0.0.dist-info/METADATA,sha256=LMz4ZjZ94m7OrJJAs4_0fs1X4C-gvWPTEw8uGwX-LvY,1588
|
||||
AuthEncoding-4.0.0.dist-info/RECORD,,
|
||||
AuthEncoding-4.0.0.dist-info/RECORD.jws,,
|
||||
AuthEncoding-4.0.0.dist-info/WHEEL,sha256=5wvfB7GvgZAbKBSE9uX9Zbi6LCL-_KgezgHblXhCRnM,113
|
||||
AuthEncoding-4.0.0.dist-info/metadata.json,sha256=yBATAjh7I5YnUKtIQHGhhActRCg60BSsaAeM0r5dPFY,1294
|
||||
AuthEncoding-4.0.0.dist-info/top_level.txt,sha256=r_cFzzt28gdOYPoRX7HjrbsJE6G-ZPK0n3sWbqE4PdQ,13
|
||||
AuthEncoding/AuthEncoding.py,sha256=A82pAZQA-r1NSG7jBf1qDJn4utAQXMHMSF09Do35t0w,7265
|
||||
AuthEncoding/__init__.py,sha256=9fdxLPEIHDUW2ig-pE92y7BkZAHItLvvFpgXTs4byiU,791
|
||||
AuthEncoding/__pycache__/AuthEncoding.cpython-36.pyc,,
|
||||
AuthEncoding/__pycache__/__init__.cpython-36.pyc,,
|
||||
AuthEncoding/__pycache__/compat.cpython-36.pyc,,
|
||||
AuthEncoding/compat.py,sha256=o2nbexNN16x67B8xLKZRQQo_F4LheBnRtKgO---vuPY,347
|
||||
AuthEncoding/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
AuthEncoding/tests/__pycache__/__init__.cpython-36.pyc,,
|
||||
AuthEncoding/tests/__pycache__/test_AuthEncoding.cpython-36.pyc,,
|
||||
AuthEncoding/tests/test_AuthEncoding.py,sha256=zEj6Uz2eC3VPxmafNcy2ZvdSQLfVSu_Yf9X63X2XHfM,3814
|
@ -0,0 +1 @@
|
||||
{"payload": "eyJoYXNoIjogInNoYTI1Nj1FbUpVbjFTUEdYeXhKc2FnMWpxNGJkMnlnYW80TlhzY2hORW5iSEFISHdnIn0", "recipients": [{"header": "eyJhbGciOiAiRWQyNTUxOSIsICJqd2siOiB7Imt0eSI6ICJFZDI1NTE5IiwgInZrIjogInZUZU1lalVPMTV1SkQzY203enZPLV9oc0dMSld4ZlFNMEFFd2R5SUQyeTQifX0", "signature": "D1i5q57sD-x3nU_8L_49SwW7b--DjetQhUpnMDwDDui6PVsLfsAr65teCK_GbT4txrxkqzCHEMV8byYKzz4XDw"}]}
|
@ -0,0 +1,6 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.30.0.a0)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
@ -0,0 +1 @@
|
||||
{"classifiers": ["Development Status :: 6 - Mature", "Environment :: Web Environment", "Framework :: Zope2", "License :: OSI Approved :: Zope Public License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: System :: Systems Administration :: Authentication/Directory :: LDAP"], "extensions": {"python.details": {"contacts": [{"email": "zope-dev@zope.org", "name": "Zope Foundation and Contributors", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "https://github.com/zopefoundation/AuthEncoding"}}}, "extras": ["test"], "generator": "bdist_wheel (0.30.0.a0)", "license": "ZPL 2.1", "metadata_version": "2.0", "name": "AuthEncoding", "run_requires": [{"extra": "test", "requires": ["pytest"]}, {"requires": ["six"]}], "summary": "Framework for handling LDAP style password hashes.", "version": "4.0.0"}
|
@ -0,0 +1 @@
|
||||
AuthEncoding
|
@ -0,0 +1,253 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2002, 2015 Zope Foundation and Contributors.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import binascii
|
||||
import six
|
||||
from binascii import b2a_base64, a2b_base64
|
||||
from hashlib import sha1 as sha
|
||||
from hashlib import sha256
|
||||
from os import getpid
|
||||
import time
|
||||
from .compat import long, b, u
|
||||
|
||||
|
||||
# Use the system PRNG if possible
|
||||
import random
|
||||
try:
|
||||
random = random.SystemRandom()
|
||||
using_sysrandom = True
|
||||
except NotImplementedError:
|
||||
using_sysrandom = False
|
||||
|
||||
|
||||
def _reseed():
|
||||
if not using_sysrandom:
|
||||
# This is ugly, and a hack, but it makes things better than
|
||||
# the alternative of predictability. This re-seeds the PRNG
|
||||
# using a value that is hard for an attacker to predict, every
|
||||
# time a random string is required. This may change the
|
||||
# properties of the chosen random sequence slightly, but this
|
||||
# is better than absolute predictability.
|
||||
random.seed(sha256(
|
||||
"%s%s%s" % (random.getstate(), time.time(), getpid())
|
||||
).digest())
|
||||
|
||||
|
||||
def _choice(c):
|
||||
_reseed()
|
||||
return random.choice(c)
|
||||
|
||||
|
||||
def _randrange(r):
|
||||
_reseed()
|
||||
return random.randrange(r)
|
||||
|
||||
|
||||
def constant_time_compare(val1, val2):
|
||||
"""
|
||||
Returns True if the two strings are equal, False otherwise.
|
||||
|
||||
The time taken is independent of the number of characters that match.
|
||||
"""
|
||||
if len(val1) != len(val2):
|
||||
return False
|
||||
result = 0
|
||||
for x, y in zip(six.iterbytes(val1), six.iterbytes(val2)):
|
||||
result |= x ^ y
|
||||
return result == 0
|
||||
|
||||
|
||||
class PasswordEncryptionScheme: # An Interface
|
||||
|
||||
def encrypt(pw):
|
||||
"""
|
||||
Encrypt the provided plain text password.
|
||||
"""
|
||||
|
||||
def validate(reference, attempt):
|
||||
"""
|
||||
Validate the provided password string. Reference is the
|
||||
correct password, which may be encrypted; attempt is clear text
|
||||
password attempt.
|
||||
"""
|
||||
|
||||
|
||||
_schemes = []
|
||||
|
||||
|
||||
def registerScheme(id, s):
|
||||
'''
|
||||
Registers an LDAP password encoding scheme.
|
||||
'''
|
||||
_schemes.append((id, u'{%s}' % id, s))
|
||||
|
||||
|
||||
def listSchemes():
|
||||
return [id for id, prefix, scheme in _schemes]
|
||||
|
||||
|
||||
class SSHADigestScheme:
|
||||
'''
|
||||
SSHA is a modification of the SHA digest scheme with a salt
|
||||
starting at byte 20 of the base64-encoded string.
|
||||
'''
|
||||
# Source: http://developer.netscape.com/docs/technote/ldap/pass_sha.html
|
||||
|
||||
def generate_salt(self):
|
||||
# Salt can be any length, but not more than about 37 characters
|
||||
# because of limitations of the binascii module.
|
||||
# 7 is what Netscape's example used and should be enough.
|
||||
# All 256 characters are available.
|
||||
salt = b''
|
||||
for n in range(7):
|
||||
salt += six.int2byte(_randrange(256))
|
||||
return salt
|
||||
|
||||
def encrypt(self, pw):
|
||||
return self._encrypt_with_salt(pw, self.generate_salt())
|
||||
|
||||
def validate(self, reference, attempt):
|
||||
try:
|
||||
ref = a2b_base64(reference)
|
||||
except binascii.Error:
|
||||
# Not valid base64.
|
||||
return 0
|
||||
salt = ref[20:]
|
||||
compare = self._encrypt_with_salt(attempt, salt)
|
||||
return constant_time_compare(compare, reference)
|
||||
|
||||
def _encrypt_with_salt(self, pw, salt):
|
||||
pw = b(pw)
|
||||
return b2a_base64(sha(pw + salt).digest() + salt)[:-1]
|
||||
|
||||
registerScheme(u'SSHA', SSHADigestScheme())
|
||||
|
||||
|
||||
class SHADigestScheme:
|
||||
|
||||
def encrypt(self, pw):
|
||||
return self._encrypt(pw)
|
||||
|
||||
def validate(self, reference, attempt):
|
||||
compare = self._encrypt(attempt)
|
||||
return constant_time_compare(compare, reference)
|
||||
|
||||
def _encrypt(self, pw):
|
||||
pw = b(pw)
|
||||
return b2a_base64(sha(pw).digest())[:-1]
|
||||
|
||||
|
||||
registerScheme(u'SHA', SHADigestScheme())
|
||||
|
||||
|
||||
class SHA256DigestScheme:
|
||||
|
||||
def encrypt(self, pw):
|
||||
return b(sha256(b(pw)).hexdigest())
|
||||
|
||||
def validate(self, reference, attempt):
|
||||
a = self.encrypt(attempt)
|
||||
return constant_time_compare(a, reference)
|
||||
|
||||
registerScheme(u'SHA256', SHA256DigestScheme())
|
||||
|
||||
|
||||
# Bogosity on various platforms due to ITAR restrictions
|
||||
try:
|
||||
from crypt import crypt
|
||||
except ImportError:
|
||||
crypt = None
|
||||
|
||||
if crypt is not None:
|
||||
|
||||
class CryptDigestScheme:
|
||||
|
||||
def generate_salt(self):
|
||||
choices = (u"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
u"abcdefghijklmnopqrstuvwxyz"
|
||||
u"0123456789./")
|
||||
return _choice(choices) + _choice(choices)
|
||||
|
||||
def encrypt(self, pw):
|
||||
return b(crypt(self._recode_password(pw), self.generate_salt()))
|
||||
|
||||
def validate(self, reference, attempt):
|
||||
attempt = self._recode_password(attempt)
|
||||
a = b(crypt(attempt, reference[:2].decode('ascii')))
|
||||
return constant_time_compare(a, reference)
|
||||
|
||||
def _recode_password(self, pw):
|
||||
# crypt always requires `str` which has a different meaning among
|
||||
# the Python versions:
|
||||
if six.PY3:
|
||||
return u(pw)
|
||||
return b(pw)
|
||||
|
||||
registerScheme(u'CRYPT', CryptDigestScheme())
|
||||
|
||||
|
||||
class MySQLDigestScheme:
|
||||
|
||||
def encrypt(self, pw):
|
||||
pw = u(pw)
|
||||
nr = long(1345345333)
|
||||
add = 7
|
||||
nr2 = long(0x12345671)
|
||||
for i in pw:
|
||||
if i == ' ' or i == '\t':
|
||||
continue
|
||||
nr ^= (((nr & 63) + add) * ord(i)) + (nr << 8)
|
||||
nr2 += (nr2 << 8) ^ nr
|
||||
add += ord(i)
|
||||
r0 = nr & ((long(1) << 31) - long(1))
|
||||
r1 = nr2 & ((long(1) << 31) - long(1))
|
||||
return (u"%08lx%08lx" % (r0, r1)).encode('ascii')
|
||||
|
||||
def validate(self, reference, attempt):
|
||||
a = self.encrypt(attempt)
|
||||
return constant_time_compare(a, reference)
|
||||
|
||||
registerScheme(u'MYSQL', MySQLDigestScheme())
|
||||
|
||||
|
||||
def pw_validate(reference, attempt):
|
||||
"""Validate the provided password string, which uses LDAP-style encoding
|
||||
notation. Reference is the correct password, attempt is clear text
|
||||
password attempt."""
|
||||
reference = b(reference)
|
||||
for id, prefix, scheme in _schemes:
|
||||
lp = len(prefix)
|
||||
if reference[:lp] == b(prefix):
|
||||
return scheme.validate(reference[lp:], attempt)
|
||||
# Assume cleartext.
|
||||
return constant_time_compare(reference, b(attempt))
|
||||
|
||||
|
||||
def is_encrypted(pw):
|
||||
for id, prefix, scheme in _schemes:
|
||||
lp = len(prefix)
|
||||
if pw[:lp] == b(prefix):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def pw_encrypt(pw, encoding=u'SSHA'):
|
||||
"""Encrypt the provided plain text password using the encoding if provided
|
||||
and return it in an LDAP-style representation."""
|
||||
encoding = u(encoding)
|
||||
for id, prefix, scheme in _schemes:
|
||||
if encoding == id:
|
||||
return b(prefix) + scheme.encrypt(pw)
|
||||
raise ValueError('Not supported: %s' % encoding)
|
||||
|
||||
pw_encode = pw_encrypt # backward compatibility
|
@ -0,0 +1,17 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2002,2015 Zope Foundation and Contributors.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
|
||||
from .AuthEncoding import (is_encrypted, pw_encrypt, pw_validate,
|
||||
registerScheme, listSchemes,
|
||||
constant_time_compare)
|
20
thesisenv/lib/python3.6/site-packages/AuthEncoding/compat.py
Normal file
20
thesisenv/lib/python3.6/site-packages/AuthEncoding/compat.py
Normal file
@ -0,0 +1,20 @@
|
||||
import six
|
||||
|
||||
if six.PY3:
|
||||
long = int
|
||||
else:
|
||||
long = long
|
||||
|
||||
|
||||
def b(arg):
|
||||
"""Convert `arg` to bytes."""
|
||||
if isinstance(arg, six.text_type):
|
||||
arg = arg.encode("latin-1")
|
||||
return arg
|
||||
|
||||
|
||||
def u(arg):
|
||||
"""Convert `arg` to text."""
|
||||
if isinstance(arg, six.binary_type):
|
||||
arg = arg.decode('ascii', 'replace')
|
||||
return arg
|
@ -0,0 +1,101 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2002, 2015 Zope Foundation and Contributors.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
"""Test of AuthEncoding
|
||||
"""
|
||||
|
||||
from AuthEncoding import AuthEncoding
|
||||
from ..compat import b, u
|
||||
import pytest
|
||||
|
||||
|
||||
def testListSchemes():
|
||||
assert len(AuthEncoding.listSchemes()) > 0 # At least one must exist!
|
||||
|
||||
|
||||
@pytest.mark.parametrize('schema_id', AuthEncoding.listSchemes())
|
||||
@pytest.mark.parametrize('password', [u'good_pw', u'gööd_pw', b(u'gööd_pw')])
|
||||
def testGoodPassword(schema_id, password):
|
||||
enc = AuthEncoding.pw_encrypt(password, schema_id)
|
||||
assert enc != password
|
||||
assert AuthEncoding.pw_validate(enc, password)
|
||||
assert AuthEncoding.pw_validate(u(enc), password)
|
||||
assert AuthEncoding.is_encrypted(enc)
|
||||
assert not AuthEncoding.is_encrypted(password)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('schema_id', AuthEncoding.listSchemes())
|
||||
@pytest.mark.parametrize(
|
||||
'password', [u'OK_pa55w0rd \n', u'OK_pä55w0rd \n', b(u'OK_pä55w0rd \n')])
|
||||
def testBadPassword(schema_id, password):
|
||||
enc = AuthEncoding.pw_encrypt(password, schema_id)
|
||||
assert enc != password
|
||||
assert not AuthEncoding.pw_validate(enc, u'xxx')
|
||||
assert not AuthEncoding.pw_validate(enc, b'xxx')
|
||||
assert not AuthEncoding.pw_validate(u(enc), u'xxx')
|
||||
assert not AuthEncoding.pw_validate(enc, enc)
|
||||
if schema_id != u'CRYPT':
|
||||
# crypt truncates passwords and would fail this test.
|
||||
assert not AuthEncoding.pw_validate(enc, password[:-1])
|
||||
assert not AuthEncoding.pw_validate(enc, password[1:])
|
||||
assert AuthEncoding.pw_validate(enc, password)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('schema_id', AuthEncoding.listSchemes())
|
||||
def testShortPassword(schema_id):
|
||||
pw = u'1'
|
||||
enc = AuthEncoding.pw_encrypt(pw, schema_id)
|
||||
assert AuthEncoding.pw_validate(enc, pw)
|
||||
assert not AuthEncoding.pw_validate(enc, enc)
|
||||
assert not AuthEncoding.pw_validate(enc, u'xxx')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('schema_id', AuthEncoding.listSchemes())
|
||||
def testLongPassword(schema_id):
|
||||
pw = u'Pw' * 2000
|
||||
enc = AuthEncoding.pw_encrypt(pw, schema_id)
|
||||
assert AuthEncoding.pw_validate(enc, pw)
|
||||
assert not AuthEncoding.pw_validate(enc, enc)
|
||||
assert not AuthEncoding.pw_validate(enc, u'xxx')
|
||||
if u'CRYPT' not in schema_id:
|
||||
# crypt and bcrypt truncates passwords and would fail these tests.
|
||||
assert not AuthEncoding.pw_validate(enc, pw[:-2])
|
||||
assert not AuthEncoding.pw_validate(enc, pw[2:])
|
||||
|
||||
|
||||
@pytest.mark.parametrize('schema_id', AuthEncoding.listSchemes())
|
||||
def testBlankPassword(schema_id):
|
||||
pw = u''
|
||||
enc = AuthEncoding.pw_encrypt(pw, schema_id)
|
||||
assert enc != pw
|
||||
assert AuthEncoding.pw_validate(enc, pw)
|
||||
assert not AuthEncoding.pw_validate(enc, enc)
|
||||
assert not AuthEncoding.pw_validate(enc, u'xxx')
|
||||
|
||||
|
||||
def testUnencryptedPassword():
|
||||
# Sanity check
|
||||
pw = u'my-password'
|
||||
assert AuthEncoding.pw_validate(pw, pw)
|
||||
assert not AuthEncoding.pw_validate(pw, pw + u'asdf')
|
||||
|
||||
|
||||
def testEncryptWithNotSupportedScheme():
|
||||
with pytest.raises(ValueError) as err:
|
||||
AuthEncoding.pw_encrypt(u'asdf', 'MD1')
|
||||
assert 'Not supported: MD1' == str(err.value)
|
||||
|
||||
|
||||
def testEncryptAcceptsTextAndBinaryEncodingNames():
|
||||
assert (AuthEncoding.pw_encrypt(u'asdf', b'SHA') ==
|
||||
AuthEncoding.pw_encrypt(u'asdf', u'SHA'))
|
@ -0,0 +1 @@
|
||||
pip
|
@ -0,0 +1,348 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: BTrees
|
||||
Version: 4.5.1
|
||||
Summary: Scalable persistent object containers
|
||||
Home-page: https://github.com/zopefoundation/BTrees
|
||||
Author: Zope Foundation
|
||||
Author-email: zodb-dev@zope.org
|
||||
License: ZPL 2.1
|
||||
Platform: any
|
||||
Classifier: Development Status :: 6 - Mature
|
||||
Classifier: License :: OSI Approved :: Zope Public License
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: 3.7
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
Classifier: Framework :: ZODB
|
||||
Classifier: Topic :: Database
|
||||
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||
Classifier: Operating System :: Microsoft :: Windows
|
||||
Classifier: Operating System :: Unix
|
||||
Provides-Extra: test
|
||||
Provides-Extra: ZODB
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: persistent (>=4.1.0)
|
||||
Requires-Dist: zope.interface
|
||||
Provides-Extra: ZODB
|
||||
Requires-Dist: ZODB; extra == 'ZODB'
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: Sphinx; extra == 'docs'
|
||||
Requires-Dist: repoze.sphinx.autointerface; extra == 'docs'
|
||||
Provides-Extra: test
|
||||
Requires-Dist: transaction; extra == 'test'
|
||||
Requires-Dist: zope.testrunner; extra == 'test'
|
||||
|
||||
``BTrees``: scalable persistent components
|
||||
===========================================
|
||||
|
||||
.. image:: https://travis-ci.org/zopefoundation/BTrees.svg?branch=master
|
||||
:target: https://travis-ci.org/zopefoundation/BTrees
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/github/zopefoundation/BTrees?branch=master&svg=true
|
||||
:target: https://ci.appveyor.com/project/mgedmin/BTrees
|
||||
|
||||
.. image:: https://coveralls.io/repos/github/zopefoundation/BTrees/badge.svg?branch=master
|
||||
:target: https://coveralls.io/github/zopefoundation/BTrees?branch=master
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/BTrees.svg
|
||||
:target: https://pypi.org/project/BTrees/
|
||||
:alt: Current version on PyPI
|
||||
|
||||
.. image:: https://img.shields.io/pypi/pyversions/BTrees.svg
|
||||
:target: https://pypi.org/project/BTrees/
|
||||
:alt: Supported Python versions
|
||||
|
||||
|
||||
This package contains a set of persistent object containers built around
|
||||
a modified BTree data structure. The trees are optimized for use inside
|
||||
ZODB's "optimistic concurrency" paradigm, and include explicit resolution
|
||||
of conflicts detected by that mechanism.
|
||||
|
||||
Please see `the Sphinx documentation <http://btrees.readthedocs.io/>`_ for further
|
||||
information.
|
||||
|
||||
|
||||
``BTrees`` Changelog
|
||||
====================
|
||||
|
||||
4.5.1 (2018-08-09)
|
||||
------------------
|
||||
|
||||
- Produce binary wheels for Python 3.7.
|
||||
|
||||
- Use pyproject.toml to specify build dependencies. This requires pip
|
||||
18 or later to build from source.
|
||||
|
||||
|
||||
4.5.0 (2018-04-23)
|
||||
------------------
|
||||
|
||||
- Add support for Python 3.6 and 3.7.
|
||||
- Drop support for Python 3.3.
|
||||
- Raise an ``ImportError`` consistently on Python 3 if the C extension for
|
||||
BTrees is used but the ``persistent`` C extension is not available.
|
||||
Previously this could result in an odd ``AttributeError``. See
|
||||
https://github.com/zopefoundation/BTrees/pull/55
|
||||
- Fix the possibility of a rare crash in the C extension when
|
||||
deallocating items. See https://github.com/zopefoundation/BTrees/issues/75
|
||||
- Respect the ``PURE_PYTHON`` environment variable at runtime even if
|
||||
the C extensions are available. See
|
||||
https://github.com/zopefoundation/BTrees/issues/78
|
||||
- Always attempt to build the C extensions, but make their success
|
||||
optional.
|
||||
- Fix a ``DeprecationWarning`` that could come from I and L objects in
|
||||
Python 2 in pure-Python mode. See https://github.com/zopefoundation/BTrees/issues/79
|
||||
|
||||
4.4.1 (2017-01-24)
|
||||
------------------
|
||||
|
||||
Fixed a packaging bug that caused extra files to be included (some of
|
||||
which caused problems in some platforms).
|
||||
|
||||
4.4.0 (2017-01-11)
|
||||
------------------
|
||||
|
||||
- Allow None as a special key (sorted smaller than all others).
|
||||
|
||||
This is a bit of a return to BTrees 3 behavior in that Nones are
|
||||
allowed as keys again. Other objects with default ordering are
|
||||
still not allowed as keys.
|
||||
|
||||
4.3.2 (2017-01-05)
|
||||
------------------
|
||||
|
||||
- Make the CPython implementation consistent with the pure-Python
|
||||
implementation and only check object keys for default comparison
|
||||
when setting keys. In Python 2 this makes it possible to remove keys
|
||||
that were added using a less restrictive version of BTrees. (In
|
||||
Python 3 keys that are unorderable still cannot be removed.)
|
||||
Likewise, all versions can unpickle trees that already had such
|
||||
keys. See: https://github.com/zopefoundation/BTrees/issues/53 and
|
||||
https://github.com/zopefoundation/BTrees/issues/51
|
||||
|
||||
- Make the Python implementation consistent with the CPython
|
||||
implementation and check object key identity before checking
|
||||
equality and performing comparisons. This can allow fixing trees
|
||||
that have keys that now have broken comparison functions. See
|
||||
https://github.com/zopefoundation/BTrees/issues/50
|
||||
|
||||
- Make the CPython implementation consistent with the pure-Python
|
||||
implementation and no longer raise ``TypeError`` for an object key
|
||||
(in object-keyed trees) with default comparison on ``__getitem__``,
|
||||
``get`` or ``in`` operations. Instead, the results will be a
|
||||
``KeyError``, the default value, and ``False``, respectively.
|
||||
Previously, CPython raised a ``TypeError`` in those cases, while the
|
||||
Python implementation behaved as specified.
|
||||
|
||||
Likewise, non-integer keys in integer-keyed trees
|
||||
will raise ``KeyError``, return the default and return ``False``,
|
||||
respectively, in both implementations. Previously, pure-Python
|
||||
raised a ``KeyError``, returned the default, and raised a
|
||||
``TypeError``, while CPython raised ``TypeError`` in all three cases.
|
||||
|
||||
4.3.1 (2016-05-16)
|
||||
------------------
|
||||
|
||||
- Packaging: fix password used to automate wheel creation on Travis.
|
||||
|
||||
4.3.0 (2016-05-10)
|
||||
------------------
|
||||
|
||||
- Fix unexpected ``OverflowError`` when passing 64bit values to long
|
||||
keys / values on Win64. See:
|
||||
https://github.com/zopefoundation/BTrees/issues/32
|
||||
|
||||
- When testing ``PURE_PYTHON`` environments under ``tox``, avoid poisoning
|
||||
the user's global wheel cache.
|
||||
|
||||
- Ensure that the pure-Python implementation, used on PyPy and when a C
|
||||
compiler isn't available for CPython, pickles identically to the C
|
||||
version. Unpickling will choose the best available implementation.
|
||||
This change prevents interoperability problems and database corruption if
|
||||
both implementations are in use. While it is no longer possible to
|
||||
pickle a Python implementation and have it unpickle to the Python
|
||||
implementation if the C implementation is available, existing Python
|
||||
pickles will still unpickle to the Python implementation (until
|
||||
pickled again). See:
|
||||
https://github.com/zopefoundation/BTrees/issues/19
|
||||
|
||||
- Avoid creating invalid objects when unpickling empty BTrees in a pure-Python
|
||||
environment.
|
||||
|
||||
- Drop support for Python 2.6 and 3.2.
|
||||
|
||||
4.2.0 (2015-11-13)
|
||||
------------------
|
||||
|
||||
- Add support for Python 3.5.
|
||||
|
||||
4.1.4 (2015-06-02)
|
||||
------------------
|
||||
|
||||
- Ensure that pure-Python Bucket and Set objects have a human readable
|
||||
``__repr__`` like the C versions.
|
||||
|
||||
4.1.3 (2015-05-19)
|
||||
------------------
|
||||
|
||||
- Fix ``_p_changed`` when removing items from small pure-Python
|
||||
BTrees/TreeSets and when adding items to small pure-Python Sets. See:
|
||||
https://github.com/zopefoundation/BTrees/issues/13
|
||||
|
||||
|
||||
4.1.2 (2015-04-07)
|
||||
------------------
|
||||
|
||||
- Suppress testing 64-bit values in OLBTrees on 32 bit machines.
|
||||
See: https://github.com/zopefoundation/BTrees/issues/9
|
||||
|
||||
- Fix ``_p_changed`` when adding items to small pure-Python
|
||||
BTrees/TreeSets. See:
|
||||
https://github.com/zopefoundation/BTrees/issues/11
|
||||
|
||||
|
||||
4.1.1 (2014-12-27)
|
||||
------------------
|
||||
|
||||
- Accomodate long values in pure-Python OLBTrees.
|
||||
|
||||
|
||||
4.1.0 (2014-12-26)
|
||||
------------------
|
||||
|
||||
- Add support for PyPy and PyPy3.
|
||||
|
||||
- Add support for Python 3.4.
|
||||
|
||||
- BTree subclasses can define ``max_leaf_size`` or ``max_internal_size``
|
||||
to control maximum sizes for Bucket/Set and BTree/TreeSet nodes.
|
||||
|
||||
- Detect integer overflow on 32-bit machines correctly under Python 3.
|
||||
|
||||
- Update pure-Python and C trees / sets to accept explicit None to indicate
|
||||
max / min value for ``minKey``, ``maxKey``. (PR #3)
|
||||
|
||||
- Update pure-Python trees / sets to accept explicit None to indicate
|
||||
open ranges for ``keys``, ``values``, ``items``. (PR #3)
|
||||
|
||||
|
||||
4.0.8 (2013-05-25)
|
||||
------------------
|
||||
|
||||
- Fix value-based comparison for objects under Py3k: addresses invalid
|
||||
merges of ``[OLI]OBTrees/OBuckets``.
|
||||
|
||||
- Ensure that pure-Python implementation of ``OOBTree.byValue`` matches
|
||||
semantics (reversed-sort) of C implementation.
|
||||
|
||||
|
||||
4.0.7 (2013-05-22)
|
||||
------------------
|
||||
|
||||
- Issue #2: compilation error on 32-bit mode of OS/X.
|
||||
|
||||
- Test ``PURE_PYTHON`` environment variable support: if set, the C
|
||||
extensions will not be built, imported, or tested.
|
||||
|
||||
|
||||
4.0.6 (2013-05-14)
|
||||
------------------
|
||||
|
||||
- Changed the ``ZODB`` extra to require only the real ``ZODB`` package,
|
||||
rather than the ``ZODB3`` metapackage: depending on the version used,
|
||||
the metapackage could pull in stale versions of **this** package and
|
||||
``persistent``.
|
||||
|
||||
- Fixed Python version check in ``setup.py``.
|
||||
|
||||
|
||||
4.0.5 (2013-01-15)
|
||||
------------------
|
||||
|
||||
- Fit the ``repr`` of bucket objects, which could contain garbage
|
||||
characters.
|
||||
|
||||
|
||||
4.0.4 (2013-01-12)
|
||||
------------------
|
||||
|
||||
- Emulate the (private) iterators used by the C extension modules from
|
||||
pure Python. This change is "cosmetic" only: it prevents the ZCML
|
||||
``zope.app.security:permission.zcml`` from failing. The emulated
|
||||
classes are **not** functional, and should be considered implementation
|
||||
details.
|
||||
|
||||
- Accomodate buildout to the fact that we no longer bundle a copy
|
||||
of 'persistent.h'.
|
||||
|
||||
- Fix test failures on Windows: no longer rely on overflows from
|
||||
``sys.maxint``.
|
||||
|
||||
|
||||
4.0.3 (2013-01-04)
|
||||
------------------
|
||||
|
||||
- Added ``setup_requires==['persistent']``.
|
||||
|
||||
|
||||
4.0.2 (2013-01-03)
|
||||
------------------
|
||||
|
||||
- Updated Trove classifiers.
|
||||
|
||||
- Added explicit support for Python 3.2, Python 3.3, and PyPy.
|
||||
Note that the C extensions are not (yet) available on PyPy.
|
||||
|
||||
- Python reference implementations now tested separately from the C
|
||||
verions on all platforms.
|
||||
|
||||
- 100% unit test coverage.
|
||||
|
||||
|
||||
4.0.1 (2012-10-21)
|
||||
------------------
|
||||
|
||||
- Provide local fallback for persistent C header inclusion if the
|
||||
persistent distribution isn't installed. This makes the winbot happy.
|
||||
|
||||
|
||||
4.0.0 (2012-10-20)
|
||||
------------------
|
||||
|
||||
Platform Changes
|
||||
################
|
||||
|
||||
- Dropped support for Python < 2.6.
|
||||
|
||||
- Factored ``BTrees`` as a separate distribution.
|
||||
|
||||
Testing Changes
|
||||
###############
|
||||
|
||||
- All covered platforms tested under ``tox``.
|
||||
|
||||
- Added support for continuous integration using ``tox`` and ``jenkins``.
|
||||
|
||||
- Added ``setup.py dev`` alias (installs ``nose`` and ``coverage``).
|
||||
|
||||
- Dropped dependency on ``zope.testing`` / ``zope.testrunner``: tests now
|
||||
run with ``setup.py test``.
|
||||
|
||||
Documentation Changes
|
||||
#####################
|
||||
|
||||
- Added API reference, generated via Spinx' autodoc.
|
||||
|
||||
- Added Sphinx documentation based on ZODB Guide (snippets are exercised
|
||||
via 'tox').
|
||||
|
||||
- Added ``setup.py docs`` alias (installs ``Sphinx`` and
|
||||
``repoze.sphinx.autointerface``).
|
||||
|
||||
|
@ -0,0 +1,134 @@
|
||||
BTrees-4.5.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
BTrees-4.5.1.dist-info/METADATA,sha256=Nb2ZkIBPwlBQFnLSaGd_6XWqJwn1DIzl5dOR5nri1Mk,11329
|
||||
BTrees-4.5.1.dist-info/RECORD,,
|
||||
BTrees-4.5.1.dist-info/WHEEL,sha256=lx06sLWNl7U6OABNP9EWDqGNT2LbGyG1l5xyFnYYudo,109
|
||||
BTrees-4.5.1.dist-info/entry_points.txt,sha256=OZFBvh0wrCZW2J7tzw2NztqnLWwpv5WcriQ9x7FELPY,6
|
||||
BTrees-4.5.1.dist-info/top_level.txt,sha256=tyKTCytaCG_dQ7OVIUdgV-PZM9ltjveiOYk5u5FesbU,15
|
||||
BTrees/BTreeItemsTemplate.c,sha256=u5_bDWVQljKp87eX_FIQbm1HoVK9QztsB4UkcVZhVKU,24825
|
||||
BTrees/BTreeModuleTemplate.c,sha256=kO71qy4qU0nzS4PzTDzkvdn6cf-8DpzRFSt16WFp1O0,20611
|
||||
BTrees/BTreeTemplate.c,sha256=qJJnOLO9GJZNNzbBLRO1AxloA62cGDtC-2QFFnupbUY,71551
|
||||
BTrees/BucketTemplate.c,sha256=5sSFK-XD19B13bpIVN-rFS8TTcf6OCAYNecFbVdybqw,53068
|
||||
BTrees/Development.txt,sha256=IJCMs8N362vMCr4H67mznKIr5Lb5BuYh5YRBzHDq8xk,16958
|
||||
BTrees/IFBTree.py,sha256=xTd4UoaUmBhvf0wtco-_AZI2G_2bqymFWKRPDKIHX5g,3452
|
||||
BTrees/IIBTree.py,sha256=43-TgRVrwHKzhwZ7myrbRbvUfRIL-EpXWmhKmYfXuZs,3426
|
||||
BTrees/IOBTree.py,sha256=1PKMEHbm6Q0tOT-nEE66p6oiWUYtRXGs4ca6kVTtGck,2776
|
||||
BTrees/Interfaces.py,sha256=-KxR8M0K5NVfWcvKbo5HkcjHZmPQQ0OXvLxXoaysX08,17831
|
||||
BTrees/LFBTree.py,sha256=4qVsFCP6dm-ocZUBMTM97yNkI4MjB14xoBVJPnIpNLk,3453
|
||||
BTrees/LLBTree.py,sha256=EyzLlsd-vdy12c6tVr57dshtR7yBRSq4ovXLbWnMoXw,3446
|
||||
BTrees/LOBTree.py,sha256=yLR9OWzuytSDeb16vQjoJTCTpmZrAq1d5GMxXhRs9tk,2777
|
||||
BTrees/Length.py,sha256=JX5_JLeRIwh79j_r87GnjFosExLwrj8H2eBjdvfb2IY,1937
|
||||
BTrees/MergeTemplate.c,sha256=oLbW1QqeERrfnkg9YXfDUXU4I4OAJZ7jQ1OJcWQ7mqM,12070
|
||||
BTrees/OIBTree.py,sha256=KvFHcH_80Cxy_Qclv8SlGrUVWapudsSGEKsEhOfcvcE,3338
|
||||
BTrees/OLBTree.py,sha256=SXe4IJ0NOAfd3YJbV5L68VJkfdC3ZqzFOv58SRBXiKQ,3330
|
||||
BTrees/OOBTree.py,sha256=n2dZCvzq83FJZ45lTywvYBvT2ozhJZZDraS6jGDZUaA,2524
|
||||
BTrees/SetOpTemplate.c,sha256=T5hDNXFqSW6i1rKtCVErg6W-H8HOYkc5hCh1j6-8uW8,15571
|
||||
BTrees/SetTemplate.c,sha256=GIW_9986HcjjwCXG2XnDz_BNHgsygf1umnv3FD92Gr8,10119
|
||||
BTrees/TreeSetTemplate.c,sha256=z7sOs0RDVCgoufuDIiMb1oBKEKyJpgGtaUY063cF7ZE,8455
|
||||
BTrees/_IFBTree.c,sha256=BIJrf9LcDM_DRKCtnXJqoAnwvDwhnh_3x_l7CQWzZ3g,1136
|
||||
BTrees/_IFBTree.cpython-36m-darwin.so,sha256=-pDtbOXMyRLnyEzGPESPtNezHMVYjIkcI4_8LjbfQ90,186992
|
||||
BTrees/_IIBTree.c,sha256=DXzS4WGNkVYneiEGtX9F0olC750rxFQfcAVzUlaBCT0,1130
|
||||
BTrees/_IIBTree.cpython-36m-darwin.so,sha256=fY6YmOcdTiBl3DeGES-_KBdMLxDgCcGq7zFNfg8_dfc,182652
|
||||
BTrees/_IOBTree.c,sha256=nL6yr4-u6rPo_y8A8TD1irmPVG0t4szMVh4NKumypgI,1141
|
||||
BTrees/_IOBTree.cpython-36m-darwin.so,sha256=vNJgmpO6m0rYNxQfpSe5Qse1d5BNGEIovI72szY6Ogk,182500
|
||||
BTrees/_LFBTree.c,sha256=vZ8O4_6sYU54cSwbcyy1FXUfbypQzuE59tYN6Po10GE,1208
|
||||
BTrees/_LFBTree.cpython-36m-darwin.so,sha256=KuOsXfRQGAFZZjIKv9RCs_EEiiUXmrhZoVOSLZQQMms,187080
|
||||
BTrees/_LLBTree.c,sha256=P31gcA6clVlSgAlBLzJ4hqdZMPqwV6q9pKfEexXRH9Q,1199
|
||||
BTrees/_LLBTree.cpython-36m-darwin.so,sha256=WOhNkol3_nyCdjN7eUsLfz7hYw1ybbSi4Xz0AtvjmSc,186820
|
||||
BTrees/_LOBTree.c,sha256=-bq0twqbE0oqlxyMS6chYBR5ObvLvFQAa0IyFK-l4ro,1178
|
||||
BTrees/_LOBTree.cpython-36m-darwin.so,sha256=wLbc18-MMpOeFIrdQVm932uKHq-nb_2h3c25OfOieO4,182588
|
||||
BTrees/_OIBTree.c,sha256=6SLJqZskZHEQB4OqCIlZZwGRwADi7MOvu-8W3hRJBo4,1141
|
||||
BTrees/_OIBTree.cpython-36m-darwin.so,sha256=E4ToIjjUlcb1BXQ2XexI17hzxGpLkAhzFdTjZoOi4hA,178356
|
||||
BTrees/_OLBTree.c,sha256=Hu0ylTuFWEPivGsL0ClS1YLdvx3fTIS9phtMpSt9zXo,1178
|
||||
BTrees/_OLBTree.cpython-36m-darwin.so,sha256=qoKSvSbbNErXIMNVKYxyapIqDRNiU9M7VSXNxDE19m4,178428
|
||||
BTrees/_OOBTree.c,sha256=e-Wd39TQyfwnX9X-o1mp9S_hIUpWGmUjmGvdH4f3__Q,1150
|
||||
BTrees/_OOBTree.cpython-36m-darwin.so,sha256=7jOL1UtqyRz7YKvmBGma5asRslm4GlRKpf9sLxteCEk,174148
|
||||
BTrees/__init__.py,sha256=SuUBN3IfVFkSbKLece09uEDFg76AwWWD2qx37AaYXxg,1871
|
||||
BTrees/__pycache__/IFBTree.cpython-36.pyc,,
|
||||
BTrees/__pycache__/IIBTree.cpython-36.pyc,,
|
||||
BTrees/__pycache__/IOBTree.cpython-36.pyc,,
|
||||
BTrees/__pycache__/Interfaces.cpython-36.pyc,,
|
||||
BTrees/__pycache__/LFBTree.cpython-36.pyc,,
|
||||
BTrees/__pycache__/LLBTree.cpython-36.pyc,,
|
||||
BTrees/__pycache__/LOBTree.cpython-36.pyc,,
|
||||
BTrees/__pycache__/Length.cpython-36.pyc,,
|
||||
BTrees/__pycache__/OIBTree.cpython-36.pyc,,
|
||||
BTrees/__pycache__/OLBTree.cpython-36.pyc,,
|
||||
BTrees/__pycache__/OOBTree.cpython-36.pyc,,
|
||||
BTrees/__pycache__/__init__.cpython-36.pyc,,
|
||||
BTrees/__pycache__/_base.cpython-36.pyc,,
|
||||
BTrees/__pycache__/_compat.cpython-36.pyc,,
|
||||
BTrees/__pycache__/check.cpython-36.pyc,,
|
||||
BTrees/__pycache__/fsBTree.cpython-36.pyc,,
|
||||
BTrees/__pycache__/utils.cpython-36.pyc,,
|
||||
BTrees/_base.py,sha256=h6CFY1XeQHNJ9lkH6UWwMSTkTWOoOXNLUdUqvNbo1O4,49411
|
||||
BTrees/_compat.h,sha256=7Juyq0L7R692-QxH7QDk3HD7AA3N0eAnwfP4zoqoGJg,1392
|
||||
BTrees/_compat.py,sha256=30krwQo7chtAhl6V-LY0G4723rA43bZSHiERonPCHQc,2902
|
||||
BTrees/_fsBTree.c,sha256=R2xeZeyvlUvJObF-66R2HJOFoPHLO87p3rVpe9byssY,4805
|
||||
BTrees/_fsBTree.cpython-36m-darwin.so,sha256=3YzUd8gVpOREfkVJzM2NaY_cIYgZgmCULvLXSv01Rg8,174228
|
||||
BTrees/check.py,sha256=73Wkf_42KfDQ_LjUlTC9hYC_v3e2gUXOJFkGbqwAAXM,15481
|
||||
BTrees/floatvaluemacros.h,sha256=8--_OkpCuflybs5jaP3B54BWxw38u8vESph4IM545AI,899
|
||||
BTrees/fsBTree.py,sha256=r1_iTqRLCBqKGPPsvj1D0mYoRzN85amNnrJJbjiHWj0,3185
|
||||
BTrees/intkeymacros.h,sha256=M0lCFColrnPHK6qRbbgwqwAITplrCVfIDCcHp7bSE-I,1547
|
||||
BTrees/intvaluemacros.h,sha256=oL_1993h7sS6O716DaKHytbC094xcBO4L1llPqX20Mo,1704
|
||||
BTrees/objectkeymacros.h,sha256=BGhqG4nV122anWw1CNJE3dj2c5LhqKwDcvvx-Y_8QE0,1285
|
||||
BTrees/objectvaluemacros.h,sha256=duuNoUjv-IwKbzEVxZjvvmDCETmzzASeQp1N2188BuM,460
|
||||
BTrees/sorters.c,sha256=_RFLxqdW3ZhfJnMfo7tS0cQ1OuftmTmdwMLoJmH29p4,15218
|
||||
BTrees/tests/__init__.py,sha256=as-9vgC96TSaF9bHM7EBWBANqSJOgJjwWtUT3lvHQZg,52
|
||||
BTrees/tests/__pycache__/__init__.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/common.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/testBTrees.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/testBTreesUnicode.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/testConflict.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_IFBTree.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_IIBTree.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_IOBTree.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_LFBTree.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_LLBTree.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_LOBTree.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_Length.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_OIBTree.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_OLBTree.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_OOBTree.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test__base.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_btreesubclass.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_check.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_fsBTree.cpython-36.pyc,,
|
||||
BTrees/tests/__pycache__/test_utils.cpython-36.pyc,,
|
||||
BTrees/tests/common.py,sha256=ypzQE17QBOIpZNQmiRBtLMUA3nN68ZpMsjhjcnJmrhU,86610
|
||||
BTrees/tests/testBTrees.py,sha256=9kHPN0-V9ZTYE05-KPocMChxWsrG3YtdGDxy_wfmZAg,17407
|
||||
BTrees/tests/testBTreesUnicode.py,sha256=mPQraEu9VPV4mDlMcJRhpKJC0hvK2-IwJ-aZASP-DsM,2554
|
||||
BTrees/tests/testConflict.py,sha256=O6bjf7ApdPaYzYCpmPcMC4yoEeS07dfvO280sKuNBZU,21323
|
||||
BTrees/tests/test_IFBTree.py,sha256=lDac4rWXBtzaIYcbWWPcEshJKvLlwcJRzPzpltUC4rU,10641
|
||||
BTrees/tests/test_IIBTree.py,sha256=ois9MwkJ33ZoryShqIRt6FE51rGPwBRT-fw8ceoZtmo,14197
|
||||
BTrees/tests/test_IOBTree.py,sha256=LwwX727SNAWCf3tP18ZdY1rxNIYUseCKP2O1I860QE0,11531
|
||||
BTrees/tests/test_LFBTree.py,sha256=RE2Fwo1jPPhSE4WI5R8Q0Q65wyRRydEJ5wMKcBcLK2w,8957
|
||||
BTrees/tests/test_LLBTree.py,sha256=ECYj7Fn_em3RMwpd7PYb7Na5IR0FM5_lkrFbP1IkjP8,11760
|
||||
BTrees/tests/test_LOBTree.py,sha256=RnAkGsl6prphDGpd-twb562MDlhYnn8Ka_EagQb1sEI,10124
|
||||
BTrees/tests/test_Length.py,sha256=gyEXtVvSw7O_AMA9Yd2usemR_Qgie3sdr4lsCjkM0wY,3502
|
||||
BTrees/tests/test_OIBTree.py,sha256=eeB1T_nlMb5DQMbD1ASmEwj-TEC7Pb8fSXwpVh-nyEU,10947
|
||||
BTrees/tests/test_OLBTree.py,sha256=Bm6QqM9NdoqhrRqRykjurAqO9Sg8YzUQ4BrZWA8cc8A,10293
|
||||
BTrees/tests/test_OOBTree.py,sha256=bfnhr0zQzvQVMW9FtL1QWT6J38Lt-b1nVYC4r7hZrS8,12573
|
||||
BTrees/tests/test__base.py,sha256=7teTiKJfi-jc-SG1RL4KVhAYmy_H6oC-bCjY3J-2I2Q,114377
|
||||
BTrees/tests/test_btreesubclass.py,sha256=bT0TwSCViQGoG8hRSzNLC6VAw3wlzaP1n80OZGjwREA,1646
|
||||
BTrees/tests/test_check.py,sha256=UdeT_QGMF5ole6fya4853XcxrJSzeW3GSnz2J4RmngQ,12948
|
||||
BTrees/tests/test_fsBTree.py,sha256=88hNt0wIFTizjPaUgHkz2msFO6-eFPOyHSEQKZKci-0,2136
|
||||
BTrees/tests/test_utils.py,sha256=8B0lqFwYoHZalmEUyogHfDlN6IoERBaPjlr0TD-xu50,2703
|
||||
BTrees/utils.py,sha256=Vnpv1X63hp3aBPUeS7EPuZo0NoGCBmuogfu8pAcLgSk,1442
|
||||
terryfy/__init__.py,sha256=RBtPV4__9gzLYGnKiTMv1tGSXLxzFpIuVjARdyHHi0w,31
|
||||
terryfy/__pycache__/__init__.cpython-36.pyc,,
|
||||
terryfy/__pycache__/bdist_wheel.cpython-36.pyc,,
|
||||
terryfy/__pycache__/cp_suff_real_libs.cpython-36.pyc,,
|
||||
terryfy/__pycache__/fuse_suff_real_libs.cpython-36.pyc,,
|
||||
terryfy/__pycache__/monkeyexec.cpython-36.pyc,,
|
||||
terryfy/__pycache__/repath_lib_names.cpython-36.pyc,,
|
||||
terryfy/__pycache__/test_travisparse.cpython-36.pyc,,
|
||||
terryfy/__pycache__/travisparse.cpython-36.pyc,,
|
||||
terryfy/__pycache__/wafutils.cpython-36.pyc,,
|
||||
terryfy/bdist_wheel.py,sha256=uMS-xIbyD81dC8nyKh6NuFNA3qVWY6TVXyzzsV5DBTc,811
|
||||
terryfy/cp_suff_real_libs.py,sha256=11dwW6AePQ2sVB0C4wurs-tr4z1ytRgiHz_PsXGpFiw,720
|
||||
terryfy/fuse_suff_real_libs.py,sha256=wfsxzciiEf1FgTga7MSJ0KXsulUyWvYaul5Z4lIfM0E,1099
|
||||
terryfy/monkeyexec.py,sha256=QFZ5IB5JwsJK-Pc7IFnwrOD1pygE812zYn98kV-6V8A,1708
|
||||
terryfy/repath_lib_names.py,sha256=kv2dHTRRYHjIwNbcfbFNna_6dHC6yyd-orO2BWMfNOk,1018
|
||||
terryfy/test_travisparse.py,sha256=eGxYZSYdzwkxI6B9oYhZB-iGu4ifVla_F4i3Nkq7efo,2148
|
||||
terryfy/travisparse.py,sha256=Io2vjJJz6iBHtSqZGMUm0YZ8RUO3d4y06bgYMC0qWT4,1763
|
||||
terryfy/wafutils.py,sha256=FIxHuY991jWwdrGB_PVjSHLf3aeZpqKWoK_9rJbH8Vk,9118
|
@ -0,0 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.31.1)
|
||||
Root-Is-Purelib: false
|
||||
Tag: cp36-cp36m-macosx_10_6_intel
|
||||
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1,2 @@
|
||||
BTrees
|
||||
terryfy
|
@ -0,0 +1,790 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2001, 2002 Zope Foundation and Contributors.
|
||||
All Rights Reserved.
|
||||
|
||||
This software is subject to the provisions of the Zope Public License,
|
||||
Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#define BTREEITEMSTEMPLATE_C "$Id$\n"
|
||||
|
||||
/* A BTreeItems struct is returned from calling .items(), .keys() or
|
||||
* .values() on a BTree-based data structure, and is also the result of
|
||||
* taking slices of those. It represents a contiguous slice of a BTree.
|
||||
*
|
||||
* The start of the slice is in firstbucket, at offset first. The end of
|
||||
* the slice is in lastbucket, at offset last. Both endpoints are inclusive.
|
||||
* It must possible to get from firstbucket to lastbucket via following
|
||||
* bucket 'next' pointers zero or more times. firstbucket, first, lastbucket,
|
||||
* and last are readonly after initialization. An empty slice is represented
|
||||
* by firstbucket == lastbucket == currentbucket == NULL.
|
||||
*
|
||||
* 'kind' determines whether this slice represents 'k'eys alone, 'v'alues
|
||||
* alone, or 'i'items (key+value pairs). 'kind' is also readonly after
|
||||
* initialization.
|
||||
*
|
||||
* The combination of currentbucket, currentoffset and pseudoindex acts as
|
||||
* a search finger. Offset currentoffset in bucket currentbucket is at index
|
||||
* pseudoindex, where pseudoindex==0 corresponds to offset first in bucket
|
||||
* firstbucket, and pseudoindex==-1 corresponds to offset last in bucket
|
||||
* lastbucket. The function BTreeItems_seek() can be used to set this combo
|
||||
* correctly for any in-bounds index, and uses this combo on input to avoid
|
||||
* needing to search from the start (or end) on each call. Calling
|
||||
* BTreeItems_seek() with consecutive larger positions is very efficent.
|
||||
* Calling it with consecutive smaller positions is more efficient than if
|
||||
* a search finger weren't being used at all, but is still quadratic time
|
||||
* in the number of buckets in the slice.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
PyObject_HEAD
|
||||
Bucket *firstbucket; /* First bucket */
|
||||
Bucket *currentbucket; /* Current bucket (search finger) */
|
||||
Bucket *lastbucket; /* Last bucket */
|
||||
int currentoffset; /* Offset in currentbucket */
|
||||
int pseudoindex; /* search finger index */
|
||||
int first; /* Start offset in firstbucket */
|
||||
int last; /* End offset in lastbucket */
|
||||
char kind; /* 'k', 'v', 'i' */
|
||||
} BTreeItems;
|
||||
|
||||
#define ITEMS(O)((BTreeItems*)(O))
|
||||
|
||||
static PyObject *
|
||||
newBTreeItems(char kind,
|
||||
Bucket *lowbucket, int lowoffset,
|
||||
Bucket *highbucket, int highoffset);
|
||||
|
||||
static void
|
||||
BTreeItems_dealloc(BTreeItems *self)
|
||||
{
|
||||
Py_XDECREF(self->firstbucket);
|
||||
Py_XDECREF(self->lastbucket);
|
||||
Py_XDECREF(self->currentbucket);
|
||||
PyObject_DEL(self);
|
||||
}
|
||||
|
||||
static Py_ssize_t
|
||||
BTreeItems_length_or_nonzero(BTreeItems *self, int nonzero)
|
||||
{
|
||||
Py_ssize_t r;
|
||||
Bucket *b, *next;
|
||||
|
||||
b = self->firstbucket;
|
||||
if (b == NULL)
|
||||
return 0;
|
||||
|
||||
r = self->last + 1 - self->first;
|
||||
|
||||
if (nonzero && r > 0)
|
||||
/* Short-circuit if all we care about is nonempty */
|
||||
return 1;
|
||||
|
||||
if (b == self->lastbucket)
|
||||
return r;
|
||||
|
||||
Py_INCREF(b);
|
||||
PER_USE_OR_RETURN(b, -1);
|
||||
while ((next = b->next))
|
||||
{
|
||||
r += b->len;
|
||||
if (nonzero && r > 0)
|
||||
/* Short-circuit if all we care about is nonempty */
|
||||
break;
|
||||
|
||||
if (next == self->lastbucket)
|
||||
break; /* we already counted the last bucket */
|
||||
|
||||
Py_INCREF(next);
|
||||
PER_UNUSE(b);
|
||||
Py_DECREF(b);
|
||||
b = next;
|
||||
PER_USE_OR_RETURN(b, -1);
|
||||
}
|
||||
PER_UNUSE(b);
|
||||
Py_DECREF(b);
|
||||
|
||||
return r >= 0 ? r : 0;
|
||||
}
|
||||
|
||||
static Py_ssize_t
|
||||
BTreeItems_length(BTreeItems *self)
|
||||
{
|
||||
return BTreeItems_length_or_nonzero(self, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** BTreeItems_seek
|
||||
**
|
||||
** Find the ith position in the BTreeItems.
|
||||
**
|
||||
** Arguments: self The BTree
|
||||
** i the index to seek to, in 0 .. len(self)-1, or in
|
||||
** -len(self) .. -1, as for indexing a Python sequence.
|
||||
**
|
||||
**
|
||||
** Returns 0 if successful, -1 on failure to seek (like out-of-bounds).
|
||||
** Upon successful return, index i is at offset self->currentoffset in bucket
|
||||
** self->currentbucket.
|
||||
*/
|
||||
static int
|
||||
BTreeItems_seek(BTreeItems *self, Py_ssize_t i)
|
||||
{
|
||||
int delta, pseudoindex, currentoffset;
|
||||
Bucket *b, *currentbucket;
|
||||
int error;
|
||||
|
||||
pseudoindex = self->pseudoindex;
|
||||
currentoffset = self->currentoffset;
|
||||
currentbucket = self->currentbucket;
|
||||
if (currentbucket == NULL)
|
||||
goto no_match;
|
||||
|
||||
delta = i - pseudoindex;
|
||||
while (delta > 0) /* move right */
|
||||
{
|
||||
int max;
|
||||
/* Want to move right delta positions; the most we can move right in
|
||||
* this bucket is currentbucket->len - currentoffset - 1 positions.
|
||||
*/
|
||||
PER_USE_OR_RETURN(currentbucket, -1);
|
||||
max = currentbucket->len - currentoffset - 1;
|
||||
b = currentbucket->next;
|
||||
PER_UNUSE(currentbucket);
|
||||
if (delta <= max)
|
||||
{
|
||||
currentoffset += delta;
|
||||
pseudoindex += delta;
|
||||
if (currentbucket == self->lastbucket
|
||||
&& currentoffset > self->last)
|
||||
goto no_match;
|
||||
break;
|
||||
}
|
||||
/* Move to start of next bucket. */
|
||||
if (currentbucket == self->lastbucket || b == NULL)
|
||||
goto no_match;
|
||||
currentbucket = b;
|
||||
pseudoindex += max + 1;
|
||||
delta -= max + 1;
|
||||
currentoffset = 0;
|
||||
}
|
||||
while (delta < 0) /* move left */
|
||||
{
|
||||
int status;
|
||||
/* Want to move left -delta positions; the most we can move left in
|
||||
* this bucket is currentoffset positions.
|
||||
*/
|
||||
if ((-delta) <= currentoffset)
|
||||
{
|
||||
currentoffset += delta;
|
||||
pseudoindex += delta;
|
||||
if (currentbucket == self->firstbucket
|
||||
&& currentoffset < self->first)
|
||||
goto no_match;
|
||||
break;
|
||||
}
|
||||
/* Move to end of previous bucket. */
|
||||
if (currentbucket == self->firstbucket)
|
||||
goto no_match;
|
||||
status = PreviousBucket(¤tbucket, self->firstbucket);
|
||||
if (status == 0)
|
||||
goto no_match;
|
||||
else if (status < 0)
|
||||
return -1;
|
||||
pseudoindex -= currentoffset + 1;
|
||||
delta += currentoffset + 1;
|
||||
PER_USE_OR_RETURN(currentbucket, -1);
|
||||
currentoffset = currentbucket->len - 1;
|
||||
PER_UNUSE(currentbucket);
|
||||
}
|
||||
|
||||
assert(pseudoindex == i);
|
||||
|
||||
/* Alas, the user may have mutated the bucket since the last time we
|
||||
* were called, and if they deleted stuff, we may be pointing into
|
||||
* trash memory now.
|
||||
*/
|
||||
PER_USE_OR_RETURN(currentbucket, -1);
|
||||
error = currentoffset < 0 || currentoffset >= currentbucket->len;
|
||||
PER_UNUSE(currentbucket);
|
||||
if (error)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"the bucket being iterated changed size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Py_INCREF(currentbucket);
|
||||
Py_DECREF(self->currentbucket);
|
||||
self->currentbucket = currentbucket;
|
||||
self->currentoffset = currentoffset;
|
||||
self->pseudoindex = pseudoindex;
|
||||
return 0;
|
||||
|
||||
no_match:
|
||||
IndexError(i);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Return the right kind ('k','v','i') of entry from bucket b at offset i.
|
||||
* b must be activated. Returns NULL on error.
|
||||
*/
|
||||
static PyObject *
|
||||
getBucketEntry(Bucket *b, int i, char kind)
|
||||
{
|
||||
PyObject *result = NULL;
|
||||
|
||||
assert(b);
|
||||
assert(0 <= i && i < b->len);
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case 'k':
|
||||
COPY_KEY_TO_OBJECT(result, b->keys[i]);
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
COPY_VALUE_TO_OBJECT(result, b->values[i]);
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
{
|
||||
PyObject *key;
|
||||
PyObject *value;;
|
||||
|
||||
COPY_KEY_TO_OBJECT(key, b->keys[i]);
|
||||
if (!key)
|
||||
break;
|
||||
|
||||
COPY_VALUE_TO_OBJECT(value, b->values[i]);
|
||||
if (!value)
|
||||
{
|
||||
Py_DECREF(key);
|
||||
break;
|
||||
}
|
||||
|
||||
result = PyTuple_New(2);
|
||||
if (result)
|
||||
{
|
||||
PyTuple_SET_ITEM(result, 0, key);
|
||||
PyTuple_SET_ITEM(result, 1, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_DECREF(key);
|
||||
Py_DECREF(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
PyErr_SetString(PyExc_AssertionError,
|
||||
"getBucketEntry: unknown kind");
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
** BTreeItems_item
|
||||
**
|
||||
** Arguments: self a BTreeItems structure
|
||||
** i Which item to inspect
|
||||
**
|
||||
** Returns: the BTreeItems_item_BTree of self->kind, i
|
||||
** (ie pulls the ith item out)
|
||||
*/
|
||||
static PyObject *
|
||||
BTreeItems_item(BTreeItems *self, Py_ssize_t i)
|
||||
{
|
||||
PyObject *result;
|
||||
|
||||
if (BTreeItems_seek(self, i) < 0)
|
||||
return NULL;
|
||||
|
||||
PER_USE_OR_RETURN(self->currentbucket, NULL);
|
||||
result = getBucketEntry(self->currentbucket, self->currentoffset,
|
||||
self->kind);
|
||||
PER_UNUSE(self->currentbucket);
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
** BTreeItems_slice
|
||||
**
|
||||
** Creates a new BTreeItems structure representing the slice
|
||||
** between the low and high range
|
||||
**
|
||||
** Arguments: self The old BTreeItems structure
|
||||
** ilow The start index
|
||||
** ihigh The end index
|
||||
**
|
||||
** Returns: BTreeItems item
|
||||
*/
|
||||
static PyObject *
|
||||
BTreeItems_slice(BTreeItems *self, Py_ssize_t ilow, Py_ssize_t ihigh)
|
||||
{
|
||||
Bucket *lowbucket;
|
||||
Bucket *highbucket;
|
||||
int lowoffset;
|
||||
int highoffset;
|
||||
Py_ssize_t length = -1; /* len(self), but computed only if needed */
|
||||
|
||||
/* Complications:
|
||||
* A Python slice never raises IndexError, but BTreeItems_seek does.
|
||||
* Python did only part of index normalization before calling this:
|
||||
* ilow may be < 0 now, and ihigh may be arbitrarily large. It's
|
||||
* our responsibility to clip them.
|
||||
* A Python slice is exclusive of the high index, but a BTreeItems
|
||||
* struct is inclusive on both ends.
|
||||
*/
|
||||
|
||||
/* First adjust ilow and ihigh to be legit endpoints in the Python
|
||||
* sense (ilow inclusive, ihigh exclusive). This block duplicates the
|
||||
* logic from Python's list_slice function (slicing for builtin lists).
|
||||
*/
|
||||
if (ilow < 0)
|
||||
ilow = 0;
|
||||
else
|
||||
{
|
||||
if (length < 0)
|
||||
length = BTreeItems_length(self);
|
||||
if (ilow > length)
|
||||
ilow = length;
|
||||
}
|
||||
|
||||
if (ihigh < ilow)
|
||||
ihigh = ilow;
|
||||
else
|
||||
{
|
||||
if (length < 0)
|
||||
length = BTreeItems_length(self);
|
||||
if (ihigh > length)
|
||||
ihigh = length;
|
||||
}
|
||||
assert(0 <= ilow && ilow <= ihigh);
|
||||
assert(length < 0 || ihigh <= length);
|
||||
|
||||
/* Now adjust for that our struct is inclusive on both ends. This is
|
||||
* easy *except* when the slice is empty: there's no good way to spell
|
||||
* that in an inclusive-on-both-ends scheme. For example, if the
|
||||
* slice is btree.items([:0]), ilow == ihigh == 0 at this point, and if
|
||||
* we were to subtract 1 from ihigh that would get interpreted by
|
||||
* BTreeItems_seek as meaning the *entire* set of items. Setting ilow==1
|
||||
* and ihigh==0 doesn't work either, as BTreeItems_seek raises IndexError
|
||||
* if we attempt to seek to ilow==1 when the underlying sequence is empty.
|
||||
* It seems simplest to deal with empty slices as a special case here.
|
||||
*/
|
||||
if (ilow == ihigh) /* empty slice */
|
||||
{
|
||||
lowbucket = highbucket = NULL;
|
||||
lowoffset = 1;
|
||||
highoffset = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(ilow < ihigh);
|
||||
--ihigh; /* exclusive -> inclusive */
|
||||
|
||||
if (BTreeItems_seek(self, ilow) < 0)
|
||||
return NULL;
|
||||
lowbucket = self->currentbucket;
|
||||
lowoffset = self->currentoffset;
|
||||
|
||||
if (BTreeItems_seek(self, ihigh) < 0)
|
||||
return NULL;
|
||||
|
||||
highbucket = self->currentbucket;
|
||||
highoffset = self->currentoffset;
|
||||
}
|
||||
return newBTreeItems(self->kind,
|
||||
lowbucket, lowoffset, highbucket, highoffset);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
BTreeItems_subscript(BTreeItems *self, PyObject* subscript)
|
||||
{
|
||||
Py_ssize_t len = BTreeItems_length_or_nonzero(self, 0);
|
||||
|
||||
if (PyIndex_Check(subscript))
|
||||
{
|
||||
Py_ssize_t i = PyNumber_AsSsize_t(subscript, PyExc_IndexError);
|
||||
if (i == -1 && PyErr_Occurred())
|
||||
return NULL;
|
||||
if (i < 0)
|
||||
i += len;
|
||||
return BTreeItems_item(self, i);
|
||||
}
|
||||
if (PySlice_Check(subscript))
|
||||
{
|
||||
Py_ssize_t start, stop, step, slicelength;
|
||||
|
||||
#ifdef PY3K
|
||||
#define SLICEOBJ(x) (x)
|
||||
#else
|
||||
#define SLICEOBJ(x) (PySliceObject*)(x)
|
||||
#endif
|
||||
|
||||
if (PySlice_GetIndicesEx(SLICEOBJ(subscript), len,
|
||||
&start, &stop, &step, &slicelength) < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (step != 1)
|
||||
{
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"slices must have step size of 1");
|
||||
return NULL;
|
||||
}
|
||||
return BTreeItems_slice(self, start, stop);
|
||||
}
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"Unknown index type: must be int or slice");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Py3K doesn't honor sequence slicing, so implement via mapping */
|
||||
static PyMappingMethods BTreeItems_as_mapping = {
|
||||
(lenfunc)BTreeItems_length, /* mp_length */
|
||||
(binaryfunc)BTreeItems_subscript, /* mp_subscript */
|
||||
};
|
||||
|
||||
static PySequenceMethods BTreeItems_as_sequence =
|
||||
{
|
||||
(lenfunc) BTreeItems_length, /* sq_length */
|
||||
(binaryfunc)0, /* sq_concat */
|
||||
(ssizeargfunc)0, /* sq_repeat */
|
||||
(ssizeargfunc) BTreeItems_item, /* sq_item */
|
||||
#ifndef PY3K
|
||||
/* Py3K doesn't honor this slot */
|
||||
(ssizessizeargfunc) BTreeItems_slice, /* sq_slice */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Number Method items (just for nb_nonzero!) */
|
||||
|
||||
static int
|
||||
BTreeItems_nonzero(BTreeItems *self)
|
||||
{
|
||||
return BTreeItems_length_or_nonzero(self, 1);
|
||||
}
|
||||
|
||||
static PyNumberMethods BTreeItems_as_number_for_nonzero = {
|
||||
0, /* nb_add */
|
||||
0, /* nb_subtract */
|
||||
0, /* nb_multiply */
|
||||
#ifndef PY3K
|
||||
0, /* nb_divide */
|
||||
#endif
|
||||
0, /* nb_remainder */
|
||||
0, /* nb_divmod */
|
||||
0, /* nb_power */
|
||||
0, /* nb_negative */
|
||||
0, /* nb_positive */
|
||||
0, /* nb_absolute */
|
||||
(inquiry)BTreeItems_nonzero /* nb_nonzero */
|
||||
};
|
||||
|
||||
static PyTypeObject BTreeItemsType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
MOD_NAME_PREFIX "BTreeItems", /* tp_name */
|
||||
sizeof(BTreeItems), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor) BTreeItems_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* obsolete tp_getattr */
|
||||
0, /* obsolete tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
&BTreeItems_as_number_for_nonzero, /* tp_as_number */
|
||||
&BTreeItems_as_sequence, /* tp_as_sequence */
|
||||
&BTreeItems_as_mapping, /* tp_as_mapping */
|
||||
(hashfunc)0, /* tp_hash */
|
||||
(ternaryfunc)0, /* tp_call */
|
||||
(reprfunc)0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
/* Space for future expansion */
|
||||
0L,0L,
|
||||
"Sequence type used to iterate over BTree items." /* Documentation string */
|
||||
};
|
||||
|
||||
/* Returns a new BTreeItems object representing the contiguous slice from
|
||||
* offset lowoffset in bucket lowbucket through offset highoffset in bucket
|
||||
* highbucket, inclusive. Pass lowbucket == NULL for an empty slice.
|
||||
* The currentbucket is set to lowbucket, currentoffset ot lowoffset, and
|
||||
* pseudoindex to 0. kind is 'k', 'v' or 'i' (see BTreeItems struct docs).
|
||||
*/
|
||||
static PyObject *
|
||||
newBTreeItems(char kind,
|
||||
Bucket *lowbucket, int lowoffset,
|
||||
Bucket *highbucket, int highoffset)
|
||||
{
|
||||
BTreeItems *self;
|
||||
|
||||
UNLESS (self = PyObject_NEW(BTreeItems, &BTreeItemsType))
|
||||
return NULL;
|
||||
self->kind=kind;
|
||||
|
||||
self->first=lowoffset;
|
||||
self->last=highoffset;
|
||||
|
||||
if (! lowbucket || ! highbucket
|
||||
|| (lowbucket == highbucket && lowoffset > highoffset))
|
||||
{
|
||||
self->firstbucket = 0;
|
||||
self->lastbucket = 0;
|
||||
self->currentbucket = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_INCREF(lowbucket);
|
||||
self->firstbucket = lowbucket;
|
||||
Py_INCREF(highbucket);
|
||||
self->lastbucket = highbucket;
|
||||
Py_INCREF(lowbucket);
|
||||
self->currentbucket = lowbucket;
|
||||
}
|
||||
|
||||
self->currentoffset = lowoffset;
|
||||
self->pseudoindex = 0;
|
||||
|
||||
return OBJECT(self);
|
||||
}
|
||||
|
||||
static int
|
||||
nextBTreeItems(SetIteration *i)
|
||||
{
|
||||
if (i->position >= 0)
|
||||
{
|
||||
if (i->position)
|
||||
{
|
||||
DECREF_KEY(i->key);
|
||||
DECREF_VALUE(i->value);
|
||||
}
|
||||
|
||||
if (BTreeItems_seek(ITEMS(i->set), i->position) >= 0)
|
||||
{
|
||||
Bucket *currentbucket;
|
||||
|
||||
currentbucket = BUCKET(ITEMS(i->set)->currentbucket);
|
||||
UNLESS(PER_USE(currentbucket))
|
||||
{
|
||||
/* Mark iteration terminated, so that finiSetIteration doesn't
|
||||
* try to redundantly decref the key and value
|
||||
*/
|
||||
i->position = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
COPY_KEY(i->key, currentbucket->keys[ITEMS(i->set)->currentoffset]);
|
||||
INCREF_KEY(i->key);
|
||||
|
||||
COPY_VALUE(i->value,
|
||||
currentbucket->values[ITEMS(i->set)->currentoffset]);
|
||||
INCREF_VALUE(i->value);
|
||||
|
||||
i->position ++;
|
||||
|
||||
PER_UNUSE(currentbucket);
|
||||
}
|
||||
else
|
||||
{
|
||||
i->position = -1;
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nextTreeSetItems(SetIteration *i)
|
||||
{
|
||||
if (i->position >= 0)
|
||||
{
|
||||
if (i->position)
|
||||
{
|
||||
DECREF_KEY(i->key);
|
||||
}
|
||||
|
||||
if (BTreeItems_seek(ITEMS(i->set), i->position) >= 0)
|
||||
{
|
||||
Bucket *currentbucket;
|
||||
|
||||
currentbucket = BUCKET(ITEMS(i->set)->currentbucket);
|
||||
UNLESS(PER_USE(currentbucket))
|
||||
{
|
||||
/* Mark iteration terminated, so that finiSetIteration doesn't
|
||||
* try to redundantly decref the key and value
|
||||
*/
|
||||
i->position = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
COPY_KEY(i->key, currentbucket->keys[ITEMS(i->set)->currentoffset]);
|
||||
INCREF_KEY(i->key);
|
||||
|
||||
i->position ++;
|
||||
|
||||
PER_UNUSE(currentbucket);
|
||||
}
|
||||
else
|
||||
{
|
||||
i->position = -1;
|
||||
PyErr_Clear();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Support for the iteration protocol new in Python 2.2. */
|
||||
|
||||
static PyTypeObject BTreeIter_Type;
|
||||
|
||||
/* The type of iterator objects, returned by e.g. iter(IIBTree()). */
|
||||
typedef struct
|
||||
{
|
||||
PyObject_HEAD
|
||||
/* We use a BTreeItems object because it's convenient and flexible.
|
||||
* We abuse it two ways:
|
||||
* 1. We set currentbucket to NULL when the iteration is finished.
|
||||
* 2. We don't bother keeping pseudoindex in synch.
|
||||
*/
|
||||
BTreeItems *pitems;
|
||||
} BTreeIter;
|
||||
|
||||
/* Return a new iterator object, to traverse the keys and/or values
|
||||
* represented by pitems. pitems must not be NULL. Returns NULL if error.
|
||||
*/
|
||||
static BTreeIter *
|
||||
BTreeIter_new(BTreeItems *pitems)
|
||||
{
|
||||
BTreeIter *result;
|
||||
|
||||
assert(pitems != NULL);
|
||||
result = PyObject_New(BTreeIter, &BTreeIter_Type);
|
||||
if (result)
|
||||
{
|
||||
Py_INCREF(pitems);
|
||||
result->pitems = pitems;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* The iterator's tp_dealloc slot. */
|
||||
static void
|
||||
BTreeIter_dealloc(BTreeIter *bi)
|
||||
{
|
||||
Py_DECREF(bi->pitems);
|
||||
PyObject_Del(bi);
|
||||
}
|
||||
|
||||
/* The implementation of the iterator's tp_iternext slot. Returns "the next"
|
||||
* item; returns NULL if error; returns NULL without setting an error if the
|
||||
* iteration is exhausted (that's the way to terminate the iteration protocol).
|
||||
*/
|
||||
static PyObject *
|
||||
BTreeIter_next(BTreeIter *bi, PyObject *args)
|
||||
{
|
||||
PyObject *result = NULL; /* until proven innocent */
|
||||
BTreeItems *items = bi->pitems;
|
||||
int i = items->currentoffset;
|
||||
Bucket *bucket = items->currentbucket;
|
||||
|
||||
if (bucket == NULL) /* iteration termination is sticky */
|
||||
return NULL;
|
||||
|
||||
PER_USE_OR_RETURN(bucket, NULL);
|
||||
if (i >= bucket->len)
|
||||
{
|
||||
/* We never leave this routine normally with i >= len: somebody
|
||||
* else mutated the current bucket.
|
||||
*/
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"the bucket being iterated changed size");
|
||||
/* Arrange for that this error is sticky too. */
|
||||
items->currentoffset = INT_MAX;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
/* Build the result object, from bucket at offset i. */
|
||||
result = getBucketEntry(bucket, i, items->kind);
|
||||
|
||||
/* Advance position for next call. */
|
||||
if (bucket == items->lastbucket && i >= items->last)
|
||||
{
|
||||
/* Next call should terminate the iteration. */
|
||||
Py_DECREF(items->currentbucket);
|
||||
items->currentbucket = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
if (i >= bucket->len)
|
||||
{
|
||||
Py_XINCREF(bucket->next);
|
||||
items->currentbucket = bucket->next;
|
||||
Py_DECREF(bucket);
|
||||
i = 0;
|
||||
}
|
||||
items->currentoffset = i;
|
||||
}
|
||||
|
||||
Done:
|
||||
PER_UNUSE(bucket);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
BTreeIter_getiter(PyObject *it)
|
||||
{
|
||||
Py_INCREF(it);
|
||||
return it;
|
||||
}
|
||||
|
||||
static PyTypeObject BTreeIter_Type = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
MODULE_NAME MOD_NAME_PREFIX "TreeIterator", /* tp_name */
|
||||
sizeof(BTreeIter), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
/* methods */
|
||||
(destructor)BTreeIter_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /*PyObject_GenericGetAttr,*/ /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
||||
0, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)BTreeIter_getiter, /* tp_iter */
|
||||
(iternextfunc)BTreeIter_next, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
};
|
@ -0,0 +1,671 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2001, 2002 Zope Foundation and Contributors.
|
||||
All Rights Reserved.
|
||||
|
||||
This software is subject to the provisions of the Zope Public License,
|
||||
Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#include "Python.h"
|
||||
/* include structmember.h for offsetof */
|
||||
#include "structmember.h"
|
||||
#include "bytesobject.h"
|
||||
|
||||
#ifdef PERSISTENT
|
||||
#include "persistent/cPersistence.h"
|
||||
#else
|
||||
#define PER_USE_OR_RETURN(self, NULL)
|
||||
#define PER_ALLOW_DEACTIVATION(self)
|
||||
#define PER_PREVENT_DEACTIVATION(self)
|
||||
#define PER_DEL(self)
|
||||
#define PER_USE(O) 1
|
||||
#define PER_ACCESSED(O) 1
|
||||
#endif
|
||||
|
||||
#include "_compat.h"
|
||||
|
||||
/* So sue me. This pair gets used all over the place, so much so that it
|
||||
* interferes with understanding non-persistence parts of algorithms.
|
||||
* PER_UNUSE can be used after a successul PER_USE or PER_USE_OR_RETURN.
|
||||
* It allows the object to become ghostified, and tells the persistence
|
||||
* machinery that the object's fields were used recently.
|
||||
*/
|
||||
#define PER_UNUSE(OBJ) do { \
|
||||
PER_ALLOW_DEACTIVATION(OBJ); \
|
||||
PER_ACCESSED(OBJ); \
|
||||
} while (0)
|
||||
|
||||
/* The tp_name slots of the various BTree types contain the fully
|
||||
* qualified names of the types, e.g. zodb.btrees.OOBTree.OOBTree.
|
||||
* The full name is usd to support pickling and because it is not
|
||||
* possible to modify the __module__ slot of a type dynamically. (This
|
||||
* may be a bug in Python 2.2).
|
||||
*
|
||||
* The MODULE_NAME here used to be "BTrees._". We actually want the module
|
||||
* name to point to the Python module rather than the C, so the underline
|
||||
* is now removed.
|
||||
*/
|
||||
#define MODULE_NAME "BTrees." MOD_NAME_PREFIX "BTree."
|
||||
|
||||
static PyObject *sort_str, *reverse_str, *__setstate___str;
|
||||
static PyObject *_bucket_type_str, *max_internal_size_str, *max_leaf_size_str;
|
||||
static PyObject *ConflictError = NULL;
|
||||
|
||||
static void PyVar_Assign(PyObject **v, PyObject *e) { Py_XDECREF(*v); *v=e;}
|
||||
#define ASSIGN(V,E) PyVar_Assign(&(V),(E))
|
||||
#define UNLESS(E) if (!(E))
|
||||
#define OBJECT(O) ((PyObject*)(O))
|
||||
|
||||
#define MIN_BUCKET_ALLOC 16
|
||||
|
||||
#define SameType_Check(O1, O2) (Py_TYPE((O1))==Py_TYPE((O2)))
|
||||
|
||||
#define ASSERT(C, S, R) if (! (C)) { \
|
||||
PyErr_SetString(PyExc_AssertionError, (S)); return (R); }
|
||||
|
||||
|
||||
#ifdef NEED_LONG_LONG_SUPPORT
|
||||
/* Helper code used to support long long instead of int. */
|
||||
|
||||
#ifndef PY_LONG_LONG
|
||||
#error "PY_LONG_LONG required but not defined"
|
||||
#endif
|
||||
|
||||
#ifdef NEED_LONG_LONG_KEYS
|
||||
static int
|
||||
longlong_check(PyObject *ob)
|
||||
{
|
||||
if (INT_CHECK(ob))
|
||||
return 1;
|
||||
|
||||
if (PyLong_Check(ob)) {
|
||||
int overflow;
|
||||
(void)PyLong_AsLongLongAndOverflow(ob, &overflow);
|
||||
if (overflow)
|
||||
goto overflow;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
overflow:
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"longlong_check: long integer out of range");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static PyObject *
|
||||
longlong_as_object(PY_LONG_LONG val)
|
||||
{
|
||||
if ((val > LONG_MAX) || (val < LONG_MIN))
|
||||
return PyLong_FromLongLong(val);
|
||||
return INT_FROM_LONG((long)val);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
longlong_convert(PyObject *ob, PY_LONG_LONG *value)
|
||||
{
|
||||
#ifndef PY3K
|
||||
if (PyInt_Check(ob))
|
||||
{
|
||||
(*value) = (PY_LONG_LONG)PyInt_AS_LONG(ob);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!PyLong_Check(ob))
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "expected integer key");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
PY_LONG_LONG val;
|
||||
int overflow;
|
||||
val = PyLong_AsLongLongAndOverflow(ob, &overflow);
|
||||
if (overflow)
|
||||
goto overflow;
|
||||
(*value) = val;
|
||||
return 1;
|
||||
}
|
||||
overflow:
|
||||
PyErr_SetString(PyExc_ValueError, "long integer out of range");
|
||||
return 0;
|
||||
}
|
||||
#endif /* NEED_LONG_LONG_SUPPORT */
|
||||
|
||||
|
||||
/* Various kinds of BTree and Bucket structs are instances of
|
||||
* "sized containers", and have a common initial layout:
|
||||
* The stuff needed for all Python objects, or all Persistent objects.
|
||||
* int size: The maximum number of things that could be contained
|
||||
* without growing the container.
|
||||
* int len: The number of things currently contained.
|
||||
*
|
||||
* Invariant: 0 <= len <= size.
|
||||
*
|
||||
* A sized container typically goes on to declare one or more pointers
|
||||
* to contiguous arrays with 'size' elements each, the initial 'len' of
|
||||
* which are currently in use.
|
||||
*/
|
||||
#ifdef PERSISTENT
|
||||
#define sizedcontainer_HEAD \
|
||||
cPersistent_HEAD \
|
||||
int size; \
|
||||
int len;
|
||||
#else
|
||||
#define sizedcontainer_HEAD \
|
||||
PyObject_HEAD \
|
||||
int size; \
|
||||
int len;
|
||||
#endif
|
||||
|
||||
/* Nothing is actually of type Sized, but (pointers to) BTree nodes and
|
||||
* Buckets can be cast to Sized* in contexts that only need to examine
|
||||
* the members common to all sized containers.
|
||||
*/
|
||||
typedef struct Sized_s {
|
||||
sizedcontainer_HEAD
|
||||
} Sized;
|
||||
|
||||
#define SIZED(O) ((Sized*)(O))
|
||||
|
||||
/* A Bucket wraps contiguous vectors of keys and values. Keys are unique,
|
||||
* and stored in sorted order. The 'values' pointer may be NULL if the
|
||||
* Bucket is used to implement a set. Buckets serving as leafs of BTrees
|
||||
* are chained together via 'next', so that the entire BTree contents
|
||||
* can be traversed in sorted order quickly and easily.
|
||||
*/
|
||||
typedef struct Bucket_s {
|
||||
sizedcontainer_HEAD
|
||||
struct Bucket_s *next; /* the bucket with the next-larger keys */
|
||||
KEY_TYPE *keys; /* 'len' keys, in increasing order */
|
||||
VALUE_TYPE *values; /* 'len' corresponding values; NULL if a set */
|
||||
} Bucket;
|
||||
|
||||
#define BUCKET(O) ((Bucket*)(O))
|
||||
|
||||
/* A BTree is complicated. See Maintainer.txt.
|
||||
*/
|
||||
|
||||
typedef struct BTreeItem_s {
|
||||
KEY_TYPE key;
|
||||
Sized *child; /* points to another BTree, or to a Bucket of some sort */
|
||||
} BTreeItem;
|
||||
|
||||
typedef struct BTree_s {
|
||||
sizedcontainer_HEAD
|
||||
|
||||
/* firstbucket points to the bucket containing the smallest key in
|
||||
* the BTree. This is found by traversing leftmost child pointers
|
||||
* (data[0].child) until reaching a Bucket.
|
||||
*/
|
||||
Bucket *firstbucket;
|
||||
|
||||
/* The BTree points to 'len' children, via the "child" fields of the data
|
||||
* array. There are len-1 keys in the 'key' fields, stored in increasing
|
||||
* order. data[0].key is unused. For i in 0 .. len-1, all keys reachable
|
||||
* from data[i].child are >= data[i].key and < data[i+1].key, at the
|
||||
* endpoints pretending that data[0].key is minus infinity and
|
||||
* data[len].key is positive infinity.
|
||||
*/
|
||||
BTreeItem *data;
|
||||
long max_internal_size;
|
||||
long max_leaf_size;
|
||||
} BTree;
|
||||
|
||||
static PyTypeObject BTreeType;
|
||||
static PyTypeObject BucketType;
|
||||
|
||||
#define BTREE(O) ((BTree*)(O))
|
||||
|
||||
/* Use BTREE_SEARCH to find which child pointer to follow.
|
||||
* RESULT An int lvalue to hold the index i such that SELF->data[i].child
|
||||
* is the correct node to search next.
|
||||
* SELF A pointer to a BTree node.
|
||||
* KEY The key you're looking for, of type KEY_TYPE.
|
||||
* ONERROR What to do if key comparison raises an exception; for example,
|
||||
* perhaps 'return NULL'.
|
||||
*
|
||||
* See Maintainer.txt for discussion: this is optimized in subtle ways.
|
||||
* It's recommended that you call this at the start of a routine, waiting
|
||||
* to check for self->len == 0 after.
|
||||
*/
|
||||
#define BTREE_SEARCH(RESULT, SELF, KEY, ONERROR) { \
|
||||
int _lo = 0; \
|
||||
int _hi = (SELF)->len; \
|
||||
int _i, _cmp; \
|
||||
for (_i = _hi >> 1; _i > _lo; _i = (_lo + _hi) >> 1) { \
|
||||
TEST_KEY_SET_OR(_cmp, (SELF)->data[_i].key, (KEY)) \
|
||||
ONERROR; \
|
||||
if (_cmp < 0) _lo = _i; \
|
||||
else if (_cmp > 0) _hi = _i; \
|
||||
else /* equal */ break; \
|
||||
} \
|
||||
(RESULT) = _i; \
|
||||
}
|
||||
|
||||
/* SetIteration structs are used in the internal set iteration protocol.
|
||||
* When you want to iterate over a set or bucket or BTree (even an
|
||||
* individual key!),
|
||||
* 1. Declare a new iterator:
|
||||
* SetIteration si = {0,0,0};
|
||||
* Using "{0,0,0}" or "{0,0}" appear most common. Only one {0} is
|
||||
* necssary. At least one must be given so that finiSetIteration() works
|
||||
* correctly even if you don't get around to calling initSetIteration().
|
||||
* 2. Initialize it via
|
||||
* initSetIteration(&si, PyObject *s, useValues)
|
||||
* It's an error if that returns an int < 0. In case of error on the
|
||||
* init call, calling finiSetIteration(&si) is optional. But if the
|
||||
* init call succeeds, you must eventually call finiSetIteration(),
|
||||
* and whether or not subsequent calls to si.next() fail.
|
||||
* 3. Get the first element:
|
||||
* if (si.next(&si) < 0) { there was an error }
|
||||
* If the set isn't empty, this sets si.position to an int >= 0,
|
||||
* si.key to the element's key (of type KEY_TYPE), and maybe si.value to
|
||||
* the element's value (of type VALUE_TYPE). si.value is defined
|
||||
* iff si.usesValue is true.
|
||||
* 4. Process all the elements:
|
||||
* while (si.position >= 0) {
|
||||
* do something with si.key and/or si.value;
|
||||
* if (si.next(&si) < 0) { there was an error; }
|
||||
* }
|
||||
* 5. Finalize the SetIterator:
|
||||
* finiSetIteration(&si);
|
||||
* This is mandatory! si may contain references to iterator objects,
|
||||
* keys and values, and they must be cleaned up else they'll leak. If
|
||||
* this were C++ we'd hide that in the destructor, but in C you have to
|
||||
* do it by hand.
|
||||
*/
|
||||
typedef struct SetIteration_s
|
||||
{
|
||||
PyObject *set; /* the set, bucket, BTree, ..., being iterated */
|
||||
int position; /* initialized to 0; set to -1 by next() when done */
|
||||
int usesValue; /* true iff 'set' has values & we iterate them */
|
||||
KEY_TYPE key; /* next() sets to next key */
|
||||
VALUE_TYPE value; /* next() may set to next value */
|
||||
int (*next)(struct SetIteration_s*); /* function to get next key+value */
|
||||
} SetIteration;
|
||||
|
||||
/* Finish the set iteration protocol. This MUST be called by everyone
|
||||
* who starts a set iteration, unless the initial call to initSetIteration
|
||||
* failed; in that case, and only that case, calling finiSetIteration is
|
||||
* optional.
|
||||
*/
|
||||
static void
|
||||
finiSetIteration(SetIteration *i)
|
||||
{
|
||||
assert(i != NULL);
|
||||
if (i->set == NULL)
|
||||
return;
|
||||
Py_DECREF(i->set);
|
||||
i->set = NULL; /* so it doesn't hurt to call this again */
|
||||
|
||||
if (i->position > 0) {
|
||||
/* next() was called at least once, but didn't finish iterating
|
||||
* (else position would be negative). So the cached key and
|
||||
* value need to be cleaned up.
|
||||
*/
|
||||
DECREF_KEY(i->key);
|
||||
if (i->usesValue) {
|
||||
DECREF_VALUE(i->value);
|
||||
}
|
||||
}
|
||||
i->position = -1; /* stop any stray next calls from doing harm */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
IndexError(int i)
|
||||
{
|
||||
PyObject *v;
|
||||
|
||||
v = INT_FROM_LONG(i);
|
||||
if (!v) {
|
||||
v = Py_None;
|
||||
Py_INCREF(v);
|
||||
}
|
||||
PyErr_SetObject(PyExc_IndexError, v);
|
||||
Py_DECREF(v);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Search for the bucket immediately preceding *current, in the bucket chain
|
||||
* starting at first. current, *current and first must not be NULL.
|
||||
*
|
||||
* Return:
|
||||
* 1 *current holds the correct bucket; this is a borrowed reference
|
||||
* 0 no such bucket exists; *current unaltered
|
||||
* -1 error; *current unaltered
|
||||
*/
|
||||
static int
|
||||
PreviousBucket(Bucket **current, Bucket *first)
|
||||
{
|
||||
Bucket *trailing = NULL; /* first travels; trailing follows it */
|
||||
int result = 0;
|
||||
|
||||
assert(current && *current && first);
|
||||
if (first == *current)
|
||||
return 0;
|
||||
|
||||
do {
|
||||
trailing = first;
|
||||
PER_USE_OR_RETURN(first, -1);
|
||||
first = first->next;
|
||||
|
||||
((trailing)->state==cPersistent_STICKY_STATE
|
||||
&&
|
||||
((trailing)->state=cPersistent_UPTODATE_STATE));
|
||||
|
||||
PER_ACCESSED(trailing);
|
||||
|
||||
if (first == *current) {
|
||||
*current = trailing;
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
} while (first);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void *
|
||||
BTree_Malloc(size_t sz)
|
||||
{
|
||||
void *r;
|
||||
|
||||
ASSERT(sz > 0, "non-positive size malloc", NULL);
|
||||
|
||||
r = malloc(sz);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
BTree_Realloc(void *p, size_t sz)
|
||||
{
|
||||
void *r;
|
||||
|
||||
ASSERT(sz > 0, "non-positive size realloc", NULL);
|
||||
|
||||
if (p)
|
||||
r = realloc(p, sz);
|
||||
else
|
||||
r = malloc(sz);
|
||||
|
||||
UNLESS (r)
|
||||
PyErr_NoMemory();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Shared keyword-argument list for BTree/Bucket
|
||||
* (iter)?(keys|values|items)
|
||||
*/
|
||||
static char *search_keywords[] = {"min", "max",
|
||||
"excludemin", "excludemax",
|
||||
0};
|
||||
|
||||
#include "BTreeItemsTemplate.c"
|
||||
#include "BucketTemplate.c"
|
||||
#include "SetTemplate.c"
|
||||
#include "BTreeTemplate.c"
|
||||
#include "TreeSetTemplate.c"
|
||||
#include "SetOpTemplate.c"
|
||||
#include "MergeTemplate.c"
|
||||
|
||||
static struct PyMethodDef module_methods[] = {
|
||||
{"difference", (PyCFunction) difference_m, METH_VARARGS,
|
||||
"difference(o1, o2) -- "
|
||||
"compute the difference between o1 and o2"
|
||||
},
|
||||
{"union", (PyCFunction) union_m, METH_VARARGS,
|
||||
"union(o1, o2) -- compute the union of o1 and o2\n"
|
||||
},
|
||||
{"intersection", (PyCFunction) intersection_m, METH_VARARGS,
|
||||
"intersection(o1, o2) -- "
|
||||
"compute the intersection of o1 and o2"
|
||||
},
|
||||
#ifdef MERGE
|
||||
{"weightedUnion", (PyCFunction) wunion_m, METH_VARARGS,
|
||||
"weightedUnion(o1, o2 [, w1, w2]) -- compute the union of o1 and o2\n"
|
||||
"\nw1 and w2 are weights."
|
||||
},
|
||||
{"weightedIntersection", (PyCFunction) wintersection_m, METH_VARARGS,
|
||||
"weightedIntersection(o1, o2 [, w1, w2]) -- "
|
||||
"compute the intersection of o1 and o2\n"
|
||||
"\nw1 and w2 are weights."
|
||||
},
|
||||
#endif
|
||||
#ifdef MULTI_INT_UNION
|
||||
{"multiunion", (PyCFunction) multiunion_m, METH_VARARGS,
|
||||
"multiunion(seq) -- compute union of a sequence of integer sets.\n"
|
||||
"\n"
|
||||
"Each element of seq must be an integer set, or convertible to one\n"
|
||||
"via the set iteration protocol. The union returned is an IISet."
|
||||
},
|
||||
#endif
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
static char BTree_module_documentation[] =
|
||||
"\n"
|
||||
MASTER_ID
|
||||
BTREEITEMSTEMPLATE_C
|
||||
"$Id$\n"
|
||||
BTREETEMPLATE_C
|
||||
BUCKETTEMPLATE_C
|
||||
KEYMACROS_H
|
||||
MERGETEMPLATE_C
|
||||
SETOPTEMPLATE_C
|
||||
SETTEMPLATE_C
|
||||
TREESETTEMPLATE_C
|
||||
VALUEMACROS_H
|
||||
BTREEITEMSTEMPLATE_C
|
||||
;
|
||||
|
||||
int
|
||||
init_persist_type(PyTypeObject *type)
|
||||
{
|
||||
#ifdef PY3K
|
||||
((PyObject*)type)->ob_type = &PyType_Type;
|
||||
#else
|
||||
type->ob_type = &PyType_Type;
|
||||
#endif
|
||||
type->tp_base = cPersistenceCAPI->pertype;
|
||||
|
||||
if (PyType_Ready(type) < 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef PY3K
|
||||
static struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_" MOD_NAME_PREFIX "BTree", /* m_name */
|
||||
BTree_module_documentation, /* m_doc */
|
||||
-1, /* m_size */
|
||||
module_methods, /* m_methods */
|
||||
NULL, /* m_reload */
|
||||
NULL, /* m_traverse */
|
||||
NULL, /* m_clear */
|
||||
NULL, /* m_free */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static PyObject*
|
||||
module_init(void)
|
||||
{
|
||||
PyObject *module, *mod_dict, *interfaces, *conflicterr;
|
||||
|
||||
#ifdef KEY_TYPE_IS_PYOBJECT
|
||||
object_ = PyTuple_GetItem(Py_TYPE(Py_None)->tp_bases, 0);
|
||||
if (object_ == NULL)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
sort_str = INTERN("sort");
|
||||
if (!sort_str)
|
||||
return NULL;
|
||||
reverse_str = INTERN("reverse");
|
||||
if (!reverse_str)
|
||||
return NULL;
|
||||
__setstate___str = INTERN("__setstate__");
|
||||
if (!__setstate___str)
|
||||
return NULL;
|
||||
_bucket_type_str = INTERN("_bucket_type");
|
||||
if (!_bucket_type_str)
|
||||
return NULL;
|
||||
|
||||
max_internal_size_str = INTERN("max_internal_size");
|
||||
if (! max_internal_size_str)
|
||||
return NULL;
|
||||
max_leaf_size_str = INTERN("max_leaf_size");
|
||||
if (! max_leaf_size_str)
|
||||
return NULL;
|
||||
|
||||
/* Grab the ConflictError class */
|
||||
interfaces = PyImport_ImportModule("BTrees.Interfaces");
|
||||
if (interfaces != NULL)
|
||||
{
|
||||
conflicterr = PyObject_GetAttrString(interfaces, "BTreesConflictError");
|
||||
if (conflicterr != NULL)
|
||||
ConflictError = conflicterr;
|
||||
Py_DECREF(interfaces);
|
||||
}
|
||||
|
||||
if (ConflictError == NULL)
|
||||
{
|
||||
Py_INCREF(PyExc_ValueError);
|
||||
ConflictError=PyExc_ValueError;
|
||||
}
|
||||
|
||||
/* Initialize the PyPersist_C_API and the type objects. */
|
||||
#ifdef PY3K
|
||||
cPersistenceCAPI = (cPersistenceCAPIstruct *)PyCapsule_Import(
|
||||
"persistent.cPersistence.CAPI", 0);
|
||||
#else
|
||||
cPersistenceCAPI = (cPersistenceCAPIstruct *)PyCObject_Import(
|
||||
"persistent.cPersistence", "CAPI");
|
||||
#endif
|
||||
if (cPersistenceCAPI == NULL) {
|
||||
/* The Capsule API attempts to import 'persistent' and then
|
||||
* walk down to the specified attribute using getattr. If the C
|
||||
* extensions aren't available, this can result in an
|
||||
* AttributeError being raised. Let that percolate up as an
|
||||
* ImportError so it can be caught in the expected way.
|
||||
*/
|
||||
if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_ImportError)) {
|
||||
PyErr_SetString(PyExc_ImportError, "persistent C extension unavailable");
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef PY3K
|
||||
#define _SET_TYPE(typ) ((PyObject*)(&typ))->ob_type = &PyType_Type
|
||||
#else
|
||||
#define _SET_TYPE(typ) (typ).ob_type = &PyType_Type
|
||||
#endif
|
||||
_SET_TYPE(BTreeItemsType);
|
||||
_SET_TYPE(BTreeIter_Type);
|
||||
BTreeIter_Type.tp_getattro = PyObject_GenericGetAttr;
|
||||
BucketType.tp_new = PyType_GenericNew;
|
||||
SetType.tp_new = PyType_GenericNew;
|
||||
BTreeType.tp_new = PyType_GenericNew;
|
||||
TreeSetType.tp_new = PyType_GenericNew;
|
||||
if (!init_persist_type(&BucketType))
|
||||
return NULL;
|
||||
if (!init_persist_type(&BTreeType))
|
||||
return NULL;
|
||||
if (!init_persist_type(&SetType))
|
||||
return NULL;
|
||||
if (!init_persist_type(&TreeSetType))
|
||||
return NULL;
|
||||
|
||||
if (PyDict_SetItem(BTreeType.tp_dict, _bucket_type_str,
|
||||
(PyObject *)&BucketType) < 0)
|
||||
{
|
||||
fprintf(stderr, "btree failed\n");
|
||||
return NULL;
|
||||
}
|
||||
if (PyDict_SetItem(TreeSetType.tp_dict, _bucket_type_str,
|
||||
(PyObject *)&SetType) < 0)
|
||||
{
|
||||
fprintf(stderr, "bucket failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the module and add the functions */
|
||||
#ifdef PY3K
|
||||
module = PyModule_Create(&moduledef);
|
||||
#else
|
||||
module = Py_InitModule4("_" MOD_NAME_PREFIX "BTree",
|
||||
module_methods, BTree_module_documentation,
|
||||
(PyObject *)NULL, PYTHON_API_VERSION);
|
||||
#endif
|
||||
|
||||
/* Add some symbolic constants to the module */
|
||||
mod_dict = PyModule_GetDict(module);
|
||||
if (PyDict_SetItemString(mod_dict, MOD_NAME_PREFIX "Bucket",
|
||||
(PyObject *)&BucketType) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(mod_dict, MOD_NAME_PREFIX "BTree",
|
||||
(PyObject *)&BTreeType) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(mod_dict, MOD_NAME_PREFIX "Set",
|
||||
(PyObject *)&SetType) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(mod_dict, MOD_NAME_PREFIX "TreeSet",
|
||||
(PyObject *)&TreeSetType) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(mod_dict, MOD_NAME_PREFIX "TreeIterator",
|
||||
(PyObject *)&BTreeIter_Type) < 0)
|
||||
return NULL;
|
||||
/* We also want to be able to access these constants without the prefix
|
||||
* so that code can more easily exchange modules (particularly the integer
|
||||
* and long modules, but also others). The TreeIterator is only internal,
|
||||
* so we don't bother to expose that.
|
||||
*/
|
||||
if (PyDict_SetItemString(mod_dict, "Bucket",
|
||||
(PyObject *)&BucketType) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(mod_dict, "BTree",
|
||||
(PyObject *)&BTreeType) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(mod_dict, "Set",
|
||||
(PyObject *)&SetType) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(mod_dict, "TreeSet",
|
||||
(PyObject *)&TreeSetType) < 0)
|
||||
return NULL;
|
||||
#if defined(ZODB_64BIT_INTS) && defined(NEED_LONG_LONG_SUPPORT)
|
||||
if (PyDict_SetItemString(mod_dict, "using64bits", Py_True) < 0)
|
||||
return NULL;
|
||||
#else
|
||||
if (PyDict_SetItemString(mod_dict, "using64bits", Py_False) < 0)
|
||||
return NULL;
|
||||
#endif
|
||||
return module;
|
||||
}
|
||||
|
||||
#ifdef PY3K
|
||||
PyMODINIT_FUNC INITMODULE(void)
|
||||
{
|
||||
return module_init();
|
||||
}
|
||||
#else
|
||||
PyMODINIT_FUNC INITMODULE(void)
|
||||
{
|
||||
module_init();
|
||||
}
|
||||
#endif
|
2474
thesisenv/lib/python3.6/site-packages/BTrees/BTreeTemplate.c
Normal file
2474
thesisenv/lib/python3.6/site-packages/BTrees/BTreeTemplate.c
Normal file
File diff suppressed because it is too large
Load Diff
1957
thesisenv/lib/python3.6/site-packages/BTrees/BucketTemplate.c
Normal file
1957
thesisenv/lib/python3.6/site-packages/BTrees/BucketTemplate.c
Normal file
File diff suppressed because it is too large
Load Diff
429
thesisenv/lib/python3.6/site-packages/BTrees/Development.txt
Normal file
429
thesisenv/lib/python3.6/site-packages/BTrees/Development.txt
Normal file
@ -0,0 +1,429 @@
|
||||
=====================
|
||||
Developer Information
|
||||
=====================
|
||||
|
||||
This document provides information for developers who maintain or extend
|
||||
`BTrees`.
|
||||
|
||||
Macros
|
||||
======
|
||||
|
||||
`BTrees` are defined using a "template", roughly akin to a C++ template. To
|
||||
create a new family of `BTrees`, create a source file that defines macros used
|
||||
to handle differences in key and value types:
|
||||
|
||||
|
||||
Configuration Macros
|
||||
--------------------
|
||||
|
||||
``MASTER_ID``
|
||||
|
||||
A string to hold an RCS/CVS Id key to be included in compiled binaries.
|
||||
|
||||
``MOD_NAME_PREFIX``
|
||||
|
||||
A string (like "IO" or "OO") that provides the prefix used for the module.
|
||||
This gets used to generate type names and the internal module name string.
|
||||
|
||||
``DEFAULT_MAX_BUCKET_SIZE``
|
||||
|
||||
An int giving the maximum bucket size (number of key/value pairs). When a
|
||||
bucket gets larger than this due to an insertion *into a BTREE*, it
|
||||
splits. Inserting into a bucket directly doesn't split, and functions
|
||||
that produce a bucket output (e.g., ``union()``) also have no bound on how
|
||||
large a bucket may get. Someday this will be tunable on `BTree`.
|
||||
instances.
|
||||
|
||||
``DEFAULT_MAX_BTREE_SIZE``
|
||||
|
||||
An ``int`` giving the maximum size (number of children) of an internal
|
||||
btree node. Someday this will be tunable on ``BTree`` instances.
|
||||
|
||||
|
||||
Macros for Keys
|
||||
---------------
|
||||
|
||||
``KEY_TYPE``
|
||||
|
||||
The C type declaration for keys (e.g., ``int`` or ``PyObject*``).
|
||||
|
||||
``KEY_TYPE_IS_PYOBJECT``
|
||||
|
||||
Define if ``KEY_TYPE`` is a ``PyObject*`, else ``undef``.
|
||||
|
||||
``KEY_CHECK(K)``
|
||||
|
||||
Tests whether the ``PyObject* K`` can be converted to the (``C``) key type
|
||||
(``KEY_TYPE``). The macro should return a boolean (zero for false,
|
||||
non-zero for true). When it returns false, its caller should probably set
|
||||
a ``TypeError`` exception.
|
||||
|
||||
``KEY_CHECK_ON_SET(K)``
|
||||
|
||||
Like ``KEY_CHECK``, but only checked during ``__setitem__``.
|
||||
|
||||
``TEST_KEY_SET_OR(V, K, T)``
|
||||
|
||||
Like Python's ``cmp()``. Compares K(ey) to T(arget), where ``K``
|
||||
and ``T`` are ``C`` values of type `KEY_TYPE`. ``V`` is assigned an `int`
|
||||
value depending on the outcome::
|
||||
|
||||
< 0 if K < T
|
||||
== 0 if K == T
|
||||
> 0 if K > T
|
||||
|
||||
This macro acts like an ``if``, where the following statement is executed
|
||||
only if a Python exception has been raised because the values could not be
|
||||
compared.
|
||||
|
||||
``DECREF_KEY(K)``
|
||||
|
||||
``K`` is a value of ``KEY_TYPE``. If ``KEY_TYPE`` is a flavor of
|
||||
``PyObject*``, write this to do ``Py_DECREF(K)``. Else (e.g.,
|
||||
``KEY_TYPE`` is ``int``) make it a nop.
|
||||
|
||||
``INCREF_KEY(K)``
|
||||
|
||||
``K`` is a value of `KEY_TYPE`. If `KEY_TYPE` is a flavor of
|
||||
``PyObject*``, write this to do ``Py_INCREF(K)``. Else (e.g., `KEY_TYPE`
|
||||
is ``int``) make it a nop.
|
||||
|
||||
``COPY_KEY(K, E)``
|
||||
|
||||
Like ``K=E``. Copy a key from ``E`` to ``K``, both of ``KEY_TYPE``. Note
|
||||
that this doesn't ``decref K`` or ``incref E`` when ``KEY_TYPE`` is a
|
||||
``PyObject*``; the caller is responsible for keeping refcounts straight.
|
||||
|
||||
``COPY_KEY_TO_OBJECT(O, K)``
|
||||
|
||||
Roughly like ``O=K``. ``O`` is a ``PyObject*``, and the macro must build
|
||||
a Python object form of ``K``, assign it to ``O``, and ensure that ``O``
|
||||
owns the reference to its new value. It may do this by creating a new
|
||||
Python object based on ``K`` (e.g., ``PyInt_FromLong(K)`` when
|
||||
``KEY_TYPE`` is ``int``), or simply by doing ``Py_INCREF(K)`` if
|
||||
``KEY_TYPE`` is a ``PyObject*``.
|
||||
|
||||
``COPY_KEY_FROM_ARG(TARGET, ARG, STATUS)``
|
||||
|
||||
Copy an argument to the target without creating a new reference to
|
||||
``ARG``. ``ARG`` is a ``PyObject*``, and ``TARGET`` is of type
|
||||
``KEY_TYPE``. If this can't be done (for example, ``KEY_CHECK(ARG)``
|
||||
returns false), set a Python error and set status to ``0``. If there is
|
||||
no error, leave status alone.
|
||||
|
||||
|
||||
Macros for Values
|
||||
-----------------
|
||||
|
||||
``VALUE_TYPE``
|
||||
|
||||
The C type declaration for values (e.g., ``int`` or ``PyObject*``).
|
||||
|
||||
``VALUE_TYPE_IS_PYOBJECT``
|
||||
|
||||
Define if ``VALUE_TYPE`` is a ``PyObject*``, else ``undef``.
|
||||
|
||||
``TEST_VALUE(X, Y)``
|
||||
|
||||
Like Python's ``cmp()``. Compares ``X`` to ``Y``, where ``X`` & ``Y`` are
|
||||
``C`` values of type ``VALUE_TYPE``. The macro returns an ``int``, with
|
||||
value::
|
||||
|
||||
< 0 if X < Y
|
||||
== 0 if X == Y
|
||||
> 0 if X > Y
|
||||
|
||||
Bug: There is no provision for determining whether the comparison attempt
|
||||
failed (set a Python exception).
|
||||
|
||||
``DECREF_VALUE(K)``
|
||||
|
||||
Like ``DECREF_KEY``, except applied to values of ``VALUE_TYPE``.
|
||||
|
||||
``INCREF_VALUE(K)``
|
||||
|
||||
Like ``INCREF_KEY``, except applied to values of ``VALUE_TYPE``.
|
||||
|
||||
``COPY_VALUE(K, E)``
|
||||
|
||||
Like ``COPY_KEY``, except applied to values of ``VALUE_TYPE``.
|
||||
|
||||
``COPY_VALUE_TO_OBJECT(O, K)``
|
||||
|
||||
Like ``COPY_KEY_TO_OBJECT``, except applied to values of ``VALUE_TYPE``.
|
||||
|
||||
``COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS)``
|
||||
|
||||
Like ``COPY_KEY_FROM_ARG``, except applied to values of ``VALUE_TYPE``.
|
||||
|
||||
``NORMALIZE_VALUE(V, MIN)``
|
||||
|
||||
Normalize the value, ``V``, using the parameter ``MIN``. This is almost
|
||||
certainly a YAGNI. It is a no-op for most types. For integers, ``V`` is
|
||||
replaced by ``V/MIN`` only if ``MIN > 0``.
|
||||
|
||||
|
||||
Macros for Set Operations
|
||||
-------------------------
|
||||
|
||||
``MERGE_DEFAULT``
|
||||
|
||||
A value of ``VALUE_TYPE`` specifying the value to associate with set
|
||||
elements when sets are merged with mappings via weighed union or weighted
|
||||
intersection.
|
||||
|
||||
``MERGE(O1, w1, O2, w2)``
|
||||
|
||||
Performs a weighted merge of two values, ``O1`` and ``O2``, using weights
|
||||
``w1`` and ``w2``. The result must be of ``VALUE_TYPE``. Note that
|
||||
weighted unions and weighted intersections are not enabled if this macro
|
||||
is left undefined.
|
||||
|
||||
``MERGE_WEIGHT(O, w)``
|
||||
|
||||
Computes a weighted value for ``O``. The result must be of
|
||||
``VALUE_TYPE``. This is used for "filling out" weighted unions, i.e. to
|
||||
compute a weighted value for keys that appear in only one of the input
|
||||
mappings. If left undefined, ``MERGE_WEIGHT`` defaults to::
|
||||
|
||||
#define MERGE_WEIGHT(O, w) (O)
|
||||
|
||||
``MULTI_INT_UNION``
|
||||
|
||||
The value doesn't matter. If defined, `SetOpTemplate.c` compiles code for
|
||||
a ``multiunion()`` function (compute a union of many input sets at high
|
||||
speed). This currently makes sense only for structures with integer keys.
|
||||
|
||||
|
||||
BTree Clues
|
||||
===========
|
||||
|
||||
More or less random bits of helpful info.
|
||||
|
||||
+ In papers and textbooks, this flavor of BTree is usually called a B+-Tree,
|
||||
where "+" is a superscript.
|
||||
|
||||
+ All keys and all values live in the bucket leaf nodes. Keys in interior
|
||||
(BTree) nodes merely serve to guide a search efficiently toward the correct
|
||||
leaf.
|
||||
|
||||
+ When a key is deleted, it's physically removed from the bucket it's in, but
|
||||
this doesn't propagate back up the tree: since keys in interior nodes only
|
||||
serve to guide searches, it's OK-- and saves time --to leave "stale" keys in
|
||||
interior nodes.
|
||||
|
||||
+ No attempt is made to rebalance the tree after a deletion, unless a bucket
|
||||
thereby becomes entirely empty. "Classic BTrees" do rebalance, keeping all
|
||||
buckets at least half full (provided there are enough keys in the entire
|
||||
tree to fill half a bucket). The tradeoffs are murky. Pathological cases
|
||||
in the presence of deletion do exist. Pathologies include trees tending
|
||||
toward only one key per bucket, and buckets at differing depths (all buckets
|
||||
are at the same depth in a classic BTree).
|
||||
|
||||
+ ``DEFAULT_MAX_BUCKET_SIZE`` and ``DEFAULT_MAX_BTREE_SIZE`` are chosen mostly
|
||||
to "even out" pickle sizes in storage. That's why, e.g., an `IIBTree` has
|
||||
larger values than an `OOBTree`: pickles store ints more efficiently than
|
||||
they can store arbitrary Python objects.
|
||||
|
||||
+ In a non-empty BTree, every bucket node contains at least one key, and every
|
||||
BTree node contains at least one child and a non-NULL firstbucket pointer.
|
||||
However, a BTree node may not contain any keys.
|
||||
|
||||
+ An empty BTree consists solely of a BTree node with ``len==0`` and
|
||||
``firstbucket==NULL``.
|
||||
|
||||
+ Although a BTree can become unbalanced under a mix of inserts and deletes
|
||||
(meaning both that there's nothing stronger that can be said about buckets
|
||||
than that they're not empty, and that buckets can appear at different
|
||||
depths), a BTree node always has children of the same kind: they're all
|
||||
buckets, or they're all BTree nodes.
|
||||
|
||||
|
||||
The ``BTREE_SEARCH`` Macro
|
||||
==========================
|
||||
|
||||
For notational ease, consider a fixed BTree node ``x``, and let
|
||||
|
||||
::
|
||||
|
||||
K(i) mean x->data.key[i]
|
||||
C(i) mean all the keys reachable from x->data.child[i]
|
||||
|
||||
For each ``i`` in ``0`` to ``x->len-1`` inclusive,
|
||||
|
||||
::
|
||||
|
||||
K(i) <= C(i) < K(i+1)
|
||||
|
||||
is a BTree node invariant, where we pretend that ``K(0)`` holds a key smaller
|
||||
than any possible key, and ``K(x->len)`` holds a key larger than any possible
|
||||
key. (Note that ``K(x->len)`` doesn't actually exist, and ``K(0)`` is never
|
||||
used although space for it exists in non-empty BTree nodes.)
|
||||
|
||||
When searching for a key ``k``, then, the child pointer we want to follow is
|
||||
the one at index ``i`` such that ``K(i) <= k < K(i+1)``. There can be at most
|
||||
one such ``i``, since the ``K(i)`` are strictly increasing. And there is at
|
||||
least one such ``i`` provided the tree isn't empty (so that ``0 < len``). For
|
||||
the moment, assume the tree isn't empty (we'll get back to that later).
|
||||
|
||||
The macro's chief loop invariant is
|
||||
|
||||
::
|
||||
|
||||
K(lo) < k < K(hi)
|
||||
|
||||
This holds trivially at the start, since ``lo`` is set to ``0``, and ``hi`` to
|
||||
``x->len``, and we pretend ``K(0)`` is minus infinity and ``K(len)`` is plus
|
||||
infinity. Inside the loop, if ``K(i) < k`` we set ``lo`` to ``i``, and if
|
||||
``K(i) > k`` we set ``hi`` to ``i``. These obviously preserve the invariant.
|
||||
If ``K(i) == k``, the loop breaks and sets the result to ``i``, and since
|
||||
``K(i) == k`` in that case ``i`` is obviously the correct result.
|
||||
|
||||
Other cases depend on how ``i = floor((lo + hi)/2)`` works, exactly. Suppose
|
||||
``lo + d = hi`` for some ``d >= 0``. Then ``i = floor((lo + lo + d)/2) =
|
||||
floor(lo + d/2) = lo + floor(d/2)``. So:
|
||||
|
||||
a. ``[d == 0] (lo == i == hi)`` if and only if ``(lo == hi)``.
|
||||
b. ``[d == 1] (lo == i < hi)`` if and only if ``(lo+1 == hi)``.
|
||||
c. ``[d > 1] (lo < i < hi)`` if and only if ``(lo+1 < hi)``.
|
||||
|
||||
If the node is empty ``(x->len == 0)``, then ``lo==i==hi==0`` at the start,
|
||||
and the loop exits immediately (the first ``i > lo`` test fails), without
|
||||
entering the body.
|
||||
|
||||
Else ``lo < hi`` at the start, and the invariant ``K(lo) < k < K(hi)`` holds.
|
||||
|
||||
If ``lo+1 < hi``, we're in case (c): ``i`` is strictly between ``lo`` and
|
||||
``hi``, so the loop body is entered, and regardless of whether the body sets
|
||||
the new ``lo`` or the new ``hi`` to ``i``, the new ``lo`` is strictly less
|
||||
than the new ``hi``, and the difference between the new ``lo`` and new ``hi``
|
||||
is strictly less than the difference between the old ``lo`` and old ``hi``.
|
||||
So long as the new ``lo + 1`` remains < the new ``hi``, we stay in this case.
|
||||
We can't stay in this case forever, though: because ``hi-lo`` decreases on
|
||||
each trip but remains > ``0``, ``lo+1 == hi`` must eventually become true.
|
||||
(In fact, it becomes true quickly, in about ``log2(x->len)`` trips; the point
|
||||
is more that ``lo`` doesn't equal ``hi`` when the loop ends, it has to end
|
||||
with ``lo+1==hi`` and ``i==lo``).
|
||||
|
||||
Then we're in case (b): ``i==lo==hi-1`` then, and the loop exits. The
|
||||
invariant still holds, with ``lo==i`` and ``hi==lo+1==i+1``::
|
||||
|
||||
K(i) < k < K(i+1)
|
||||
|
||||
so ``i`` is again the correct answer.
|
||||
|
||||
|
||||
Optimization points:
|
||||
--------------------
|
||||
|
||||
+ Division by 2 is done via shift rather via "/2". These are signed ints, and
|
||||
almost all C compilers treat signed int division as truncating, and shifting
|
||||
is not the same as truncation for signed int division. The compiler has no
|
||||
way to know these values aren't negative, so has to generate longer-winded
|
||||
code for "/2". But we know these values aren't negative, and exploit it.
|
||||
|
||||
+ The order of _cmp comparisons matters. We're in an interior BTree node, and
|
||||
are looking at only a tiny fraction of all the keys that exist. So finding
|
||||
the key exactly in this node is unlikely, and checking ``_cmp == 0`` is a
|
||||
waste of time to the same extent. It doesn't matter whether we check for
|
||||
``_cmp < 0`` or ``_cmp > 0`` first, so long as we do both before worrying
|
||||
about equality.
|
||||
|
||||
+ At the start of a routine, it's better to run this macro even if ``x->len``
|
||||
is ``0`` (check for that afterwards). We just called a function and so
|
||||
probably drained the pipeline. If the first thing we do then is read up
|
||||
``self->len`` and check it against ``0``, we just sit there waiting for the
|
||||
data to get read up, and then another immediate test-and-branch, and for a
|
||||
very unlikely case (BTree nodes are rarely empty). It's better to get into
|
||||
the loop right away so the normal case makes progress ASAP.
|
||||
|
||||
|
||||
The ``BUCKET_SEARCH`` Macro
|
||||
===========================
|
||||
|
||||
This has a different job than ``BTREE_SEARCH``: the key ``0`` slot is
|
||||
legitimate in a bucket, and we want to find the index at which the key
|
||||
belongs. If the key is larger than the bucket's largest key, a new slot at
|
||||
index len is where it belongs, else it belongs at the smallest ``i`` with
|
||||
``keys[i]`` >= the key we're looking for. We also need to know whether or not
|
||||
the key is present (``BTREE_SEARCH`` didn't care; it only wanted to find the
|
||||
next node to search).
|
||||
|
||||
The mechanics of the search are quite similar, though. The primary
|
||||
loop invariant changes to (say we're searching for key ``k``)::
|
||||
|
||||
K(lo-1) < k < K(hi)
|
||||
|
||||
where ``K(i)`` means ``keys[i]``, and we pretend ``K(-1)`` is minus infinity
|
||||
and ``K(len)`` is plus infinity.
|
||||
|
||||
If the bucket is empty, ``lo=hi=i=0`` at the start, the loop body is never
|
||||
entered, and the macro sets ``INDEX`` to 0 and ``ABSENT`` to true. That's why
|
||||
``_cmp`` is initialized to 1 (``_cmp`` becomes ``ABSENT``).
|
||||
|
||||
Else the bucket is not empty, lo<hi at the start, and the loop body is
|
||||
entered. The invariant is obviously satisfied then, as ``lo=0`` and
|
||||
``hi=len``.
|
||||
|
||||
If ``K[i]<k``, ``lo`` is set to ``i+1``, preserving that ``K(lo-1) = K[i] <
|
||||
k``.
|
||||
|
||||
If ``K[i]>k``, ``hi`` is set to ``i``, preserving that ``K[hi] = K[i] > k``.
|
||||
|
||||
If the loop exits after either of those, ``_cmp != 0``, so ``ABSENT`` becomes
|
||||
true.
|
||||
|
||||
If ``K[i]=k``, the loop breaks, so that ``INDEX`` becomes ``i``, and
|
||||
``ABSENT`` becomes false (``_cmp=0`` in this case).
|
||||
|
||||
The same case analysis for ``BTREE_SEARCH`` on ``lo`` and ``hi`` holds here:
|
||||
|
||||
a. ``(lo == i == hi)`` if and only if ``(lo == hi)``.
|
||||
b. ``(lo == i < hi)`` if and only if ``(lo+1 == hi)``.
|
||||
c. ``(lo < i < hi)`` if and only if ``(lo+1 < hi)``.
|
||||
|
||||
So long as ``lo+1 < hi``, we're in case (c), and either break with equality
|
||||
(in which case the right results are obviously computed) or narrow the range.
|
||||
If equality doesn't obtain, the range eventually narrows to cases (a) or (b).
|
||||
|
||||
To go from (c) to (a), we must have ``lo+2==hi`` at the start, and
|
||||
``K[i]=K[lo+1]<k``. Then the new lo gets set to ``i+1 = lo+2 = hi``, and the
|
||||
loop exits with ``lo=hi=i`` and ``_cmp<0``. This is correct, because we know
|
||||
that ``k != K(i)`` (loop invariant! we actually know something stronger, that
|
||||
``k < K(hi)``; since ``i=hi``, this implies ``k != K(i)``).
|
||||
|
||||
Else (c) eventually falls into case (b), ``lo+1==hi`` and ``i==lo``. The
|
||||
invariant tells us ``K(lo-1) < k < K(hi) = K(lo+1)``, so if the key is present
|
||||
it must be at ``K(lo)``. ``i==lo`` in this case, so we test ``K(lo)`` against
|
||||
``k``. As always, if equality obtains we do the right thing, else case #b
|
||||
becomes case (a).
|
||||
|
||||
When (b) becomes (a), the last comparison was non-equal, so ``_cmp`` is
|
||||
non-zero, and the loop exits because ``lo==hi==i`` in case (a). The invariant
|
||||
then tells us ``K(lo-1) < k < K(lo)``, so the key is in fact not present, it's
|
||||
correct to exit with ``_cmp`` non-zero, and ``i==lo`` is again the index at
|
||||
which ``k`` belongs.
|
||||
|
||||
|
||||
Optimization points:
|
||||
--------------------
|
||||
|
||||
+ As for ``BTREE_SEARCH``, shifting of signed ints is cheaper than division.
|
||||
|
||||
+ Unlike as for ``BTREE_SEARCH``, there's nothing special about searching an
|
||||
empty bucket, and the macro computes thoroughly sensible results in that
|
||||
case.
|
||||
|
||||
+ The order of ``_cmp`` comparisons differs from ``BTREE_SEARCH``. When
|
||||
searching a bucket, it's much more likely (than when searching a BTree node)
|
||||
that the key is present, so testing ``__cmp==0`` isn't a systematic waste of
|
||||
cycles. At the extreme, if all searches are successful (key present), on
|
||||
average this saves one comparison per search, against leaving the
|
||||
determination of ``_cmp==0`` implicit (as ``BTREE_SEARCH`` does). But even
|
||||
on successful searches, ``__cmp != 0`` is a more popular outcome than
|
||||
``__cmp == 0`` across iterations (unless the bucket has only a few keys), so
|
||||
it's important to check one of the inequality cases first. It turns out
|
||||
it's better on average to check ``K(i) < key`` (than to check ``K(i) >
|
||||
key``), because when it pays it narrows the range more (we get a little
|
||||
boost from setting ``lo=i+1`` in this case; the other case sets ``hi=i``,
|
||||
which isn't as much of a narrowing).
|
112
thesisenv/lib/python3.6/site-packages/BTrees/IFBTree.py
Normal file
112
thesisenv/lib/python3.6/site-packages/BTrees/IFBTree.py
Normal file
@ -0,0 +1,112 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001-2012 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
|
||||
'IFBucket', 'IFSet', 'IFBTree', 'IFTreeSet',
|
||||
'union', 'intersection', 'difference',
|
||||
'weightedUnion', 'weightedIntersection', 'multiunion',
|
||||
)
|
||||
|
||||
from zope.interface import moduleProvides
|
||||
|
||||
from .Interfaces import IIntegerFloatBTreeModule
|
||||
from ._base import Bucket
|
||||
from ._base import MERGE
|
||||
from ._base import MERGE_WEIGHT_numeric
|
||||
from ._base import MERGE_DEFAULT_float
|
||||
from ._base import Set
|
||||
from ._base import Tree as BTree
|
||||
from ._base import TreeSet
|
||||
from ._base import _TreeIterator
|
||||
from ._base import difference as _difference
|
||||
from ._base import intersection as _intersection
|
||||
from ._base import multiunion as _multiunion
|
||||
from ._base import set_operation as _set_operation
|
||||
from ._base import to_int as _to_key
|
||||
from ._base import to_float as _to_value
|
||||
from ._base import union as _union
|
||||
from ._base import weightedIntersection as _weightedIntersection
|
||||
from ._base import weightedUnion as _weightedUnion
|
||||
from ._base import _fix_pickle
|
||||
from ._compat import import_c_extension
|
||||
|
||||
_BUCKET_SIZE = 120
|
||||
_TREE_SIZE = 500
|
||||
using64bits = False
|
||||
|
||||
class IFBucketPy(Bucket):
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class IFSetPy(Set):
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class IFBTreePy(BTree):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class IFTreeSetPy(TreeSet):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class IFTreeIteratorPy(_TreeIterator):
|
||||
pass
|
||||
|
||||
|
||||
# Can't declare forward refs, so fix up afterwards:
|
||||
|
||||
IFBucketPy._mapping_type = IFBucketPy._bucket_type = IFBucketPy
|
||||
IFBucketPy._set_type = IFSetPy
|
||||
|
||||
IFSetPy._mapping_type = IFBucketPy
|
||||
IFSetPy._set_type = IFSetPy._bucket_type = IFSetPy
|
||||
|
||||
IFBTreePy._mapping_type = IFBTreePy._bucket_type = IFBucketPy
|
||||
IFBTreePy._set_type = IFSetPy
|
||||
|
||||
IFTreeSetPy._mapping_type = IFBucketPy
|
||||
IFTreeSetPy._set_type = IFTreeSetPy._bucket_type = IFSetPy
|
||||
|
||||
|
||||
differencePy = _set_operation(_difference, IFSetPy)
|
||||
unionPy = _set_operation(_union, IFSetPy)
|
||||
intersectionPy = _set_operation(_intersection, IFSetPy)
|
||||
multiunionPy = _set_operation(_multiunion, IFSetPy)
|
||||
weightedUnionPy = _set_operation(_weightedUnion, IFSetPy)
|
||||
weightedIntersectionPy = _set_operation(_weightedIntersection, IFSetPy)
|
||||
|
||||
import_c_extension(globals())
|
||||
|
||||
_fix_pickle(globals(), __name__)
|
||||
|
||||
moduleProvides(IIntegerFloatBTreeModule)
|
113
thesisenv/lib/python3.6/site-packages/BTrees/IIBTree.py
Normal file
113
thesisenv/lib/python3.6/site-packages/BTrees/IIBTree.py
Normal file
@ -0,0 +1,113 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001-2012 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
|
||||
'IIBucket', 'IISet', 'IIBTree', 'IITreeSet',
|
||||
'union', 'intersection', 'difference',
|
||||
'weightedUnion', 'weightedIntersection', 'multiunion',
|
||||
)
|
||||
|
||||
from zope.interface import moduleProvides
|
||||
|
||||
from .Interfaces import IIntegerIntegerBTreeModule
|
||||
from ._base import Bucket
|
||||
from ._base import MERGE
|
||||
from ._base import MERGE_WEIGHT_numeric
|
||||
from ._base import MERGE_DEFAULT_int
|
||||
from ._base import Set
|
||||
from ._base import Tree as BTree
|
||||
from ._base import TreeSet
|
||||
from ._base import _TreeIterator
|
||||
from ._base import difference as _difference
|
||||
from ._base import intersection as _intersection
|
||||
from ._base import multiunion as _multiunion
|
||||
from ._base import set_operation as _set_operation
|
||||
from ._base import to_int as _to_key
|
||||
_to_value = _to_key
|
||||
from ._base import union as _union
|
||||
from ._base import weightedIntersection as _weightedIntersection
|
||||
from ._base import weightedUnion as _weightedUnion
|
||||
from ._base import _fix_pickle
|
||||
from ._compat import import_c_extension
|
||||
|
||||
_BUCKET_SIZE = 120
|
||||
_TREE_SIZE = 500
|
||||
using64bits = False
|
||||
|
||||
|
||||
class IIBucketPy(Bucket):
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class IISetPy(Set):
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class IIBTreePy(BTree):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class IITreeSetPy(TreeSet):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class IITreeIteratorPy(_TreeIterator):
|
||||
pass
|
||||
|
||||
|
||||
# Can't declare forward refs, so fix up afterwards:
|
||||
|
||||
IIBucketPy._mapping_type = IIBucketPy._bucket_type = IIBucketPy
|
||||
IIBucketPy._set_type = IISetPy
|
||||
|
||||
IISetPy._mapping_type = IIBucketPy
|
||||
IISetPy._set_type = IISetPy._bucket_type = IISetPy
|
||||
|
||||
IIBTreePy._mapping_type = IIBTreePy._bucket_type = IIBucketPy
|
||||
IIBTreePy._set_type = IISetPy
|
||||
|
||||
IITreeSetPy._mapping_type = IIBucketPy
|
||||
IITreeSetPy._set_type = IITreeSetPy._bucket_type = IISetPy
|
||||
|
||||
|
||||
differencePy = _set_operation(_difference, IISetPy)
|
||||
unionPy = _set_operation(_union, IISetPy)
|
||||
intersectionPy = _set_operation(_intersection, IISetPy)
|
||||
multiunionPy = _set_operation(_multiunion, IISetPy)
|
||||
weightedUnionPy = _set_operation(_weightedUnion, IISetPy)
|
||||
weightedIntersectionPy = _set_operation(_weightedIntersection, IISetPy)
|
||||
|
||||
import_c_extension(globals())
|
||||
|
||||
_fix_pickle(globals(), __name__)
|
||||
|
||||
moduleProvides(IIntegerIntegerBTreeModule)
|
95
thesisenv/lib/python3.6/site-packages/BTrees/IOBTree.py
Normal file
95
thesisenv/lib/python3.6/site-packages/BTrees/IOBTree.py
Normal file
@ -0,0 +1,95 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001-2012 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
|
||||
'IOBucket', 'IOSet', 'IOBTree', 'IOTreeSet',
|
||||
'union', 'intersection', 'difference', 'multiunion',
|
||||
)
|
||||
|
||||
from zope.interface import moduleProvides
|
||||
|
||||
from .Interfaces import IIntegerObjectBTreeModule
|
||||
from ._base import Bucket
|
||||
from ._base import MERGE_WEIGHT_default
|
||||
from ._base import Set
|
||||
from ._base import Tree as BTree
|
||||
from ._base import TreeSet
|
||||
from ._base import _TreeIterator
|
||||
from ._base import difference as _difference
|
||||
from ._base import intersection as _intersection
|
||||
from ._base import multiunion as _multiunion
|
||||
from ._base import set_operation as _set_operation
|
||||
from ._base import to_int as _to_key
|
||||
from ._base import to_ob as _to_value
|
||||
from ._base import union as _union
|
||||
from ._base import _fix_pickle
|
||||
from ._compat import import_c_extension
|
||||
|
||||
_BUCKET_SIZE = 60
|
||||
_TREE_SIZE = 500
|
||||
using64bits = False
|
||||
|
||||
|
||||
class IOBucketPy(Bucket):
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_default
|
||||
|
||||
|
||||
class IOSetPy(Set):
|
||||
_to_key = _to_key
|
||||
|
||||
|
||||
class IOBTreePy(BTree):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_default
|
||||
|
||||
|
||||
class IOTreeSetPy(TreeSet):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
|
||||
class IOTreeIteratorPy(_TreeIterator):
|
||||
pass
|
||||
|
||||
|
||||
# Can't declare forward refs, so fix up afterwards:
|
||||
|
||||
IOBucketPy._mapping_type = IOBucketPy._bucket_type = IOBucketPy
|
||||
IOBucketPy._set_type = IOSetPy
|
||||
|
||||
IOSetPy._mapping_type = IOBucketPy
|
||||
IOSetPy._set_type = IOSetPy._bucket_type = IOSetPy
|
||||
|
||||
IOBTreePy._mapping_type = IOBTreePy._bucket_type = IOBucketPy
|
||||
IOBTreePy._set_type = IOSetPy
|
||||
|
||||
IOTreeSetPy._mapping_type = IOBucketPy
|
||||
IOTreeSetPy._set_type = IOTreeSetPy._bucket_type = IOSetPy
|
||||
|
||||
|
||||
differencePy = _set_operation(_difference, IOSetPy)
|
||||
unionPy = _set_operation(_union, IOSetPy)
|
||||
intersectionPy = _set_operation(_intersection, IOSetPy)
|
||||
multiunionPy = _set_operation(_multiunion, IOSetPy)
|
||||
|
||||
import_c_extension(globals())
|
||||
|
||||
_fix_pickle(globals(), __name__)
|
||||
|
||||
moduleProvides(IIntegerObjectBTreeModule)
|
527
thesisenv/lib/python3.6/site-packages/BTrees/Interfaces.py
Normal file
527
thesisenv/lib/python3.6/site-packages/BTrees/Interfaces.py
Normal file
@ -0,0 +1,527 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
from zope.interface import Interface, Attribute
|
||||
|
||||
|
||||
class ICollection(Interface):
|
||||
|
||||
def clear():
|
||||
"""Remove all of the items from the collection."""
|
||||
|
||||
def __nonzero__():
|
||||
"""Check if the collection is non-empty.
|
||||
|
||||
Return a true value if the collection is non-empty and a
|
||||
false value otherwise.
|
||||
"""
|
||||
|
||||
|
||||
class IReadSequence(Interface):
|
||||
|
||||
def __getitem__(index):
|
||||
"""Return the value at the given index.
|
||||
|
||||
An IndexError is raised if the index cannot be found.
|
||||
"""
|
||||
|
||||
def __getslice__(index1, index2):
|
||||
"""Return a subsequence from the original sequence.
|
||||
|
||||
The subsequence includes the items from index1 up to, but not
|
||||
including, index2.
|
||||
"""
|
||||
|
||||
class IKeyed(ICollection):
|
||||
|
||||
def has_key(key):
|
||||
"""Check whether the object has an item with the given key.
|
||||
|
||||
Return a true value if the key is present, else a false value.
|
||||
"""
|
||||
|
||||
def keys(min=None, max=None, excludemin=False, excludemax=False):
|
||||
"""Return an IReadSequence containing the keys in the collection.
|
||||
|
||||
The type of the IReadSequence is not specified. It could be a list
|
||||
or a tuple or some other type.
|
||||
|
||||
All arguments are optional, and may be specified as keyword
|
||||
arguments, or by position.
|
||||
|
||||
If a min is specified, then output is constrained to keys greater
|
||||
than or equal to the given min, and, if excludemin is specified and
|
||||
true, is further constrained to keys strictly greater than min. A
|
||||
min value of None is ignored. If min is None or not specified, and
|
||||
excludemin is true, the smallest key is excluded.
|
||||
|
||||
If a max is specified, then output is constrained to keys less than
|
||||
or equal to the given max, and, if excludemax is specified and
|
||||
true, is further constrained to keys strictly less than max. A max
|
||||
value of None is ignored. If max is None or not specified, and
|
||||
excludemax is true, the largest key is excluded.
|
||||
"""
|
||||
|
||||
def maxKey(key=None):
|
||||
"""Return the maximum key.
|
||||
|
||||
If a key argument if provided and not None, return the largest key
|
||||
that is less than or equal to the argument. Raise an exception if
|
||||
no such key exists.
|
||||
"""
|
||||
|
||||
def minKey(key=None):
|
||||
"""Return the minimum key.
|
||||
|
||||
If a key argument if provided and not None, return the smallest key
|
||||
that is greater than or equal to the argument. Raise an exception
|
||||
if no such key exists.
|
||||
"""
|
||||
|
||||
|
||||
class ISetMutable(IKeyed):
|
||||
|
||||
def insert(key):
|
||||
"""Add the key (value) to the set.
|
||||
|
||||
If the key was already in the set, return 0, otherwise return 1.
|
||||
"""
|
||||
|
||||
def remove(key):
|
||||
"""Remove the key from the set.
|
||||
|
||||
Raises KeyError if key is not in the set.
|
||||
"""
|
||||
|
||||
def update(seq):
|
||||
"""Add the items from the given sequence to the set."""
|
||||
|
||||
|
||||
class ISized(Interface):
|
||||
"""An object that supports __len__."""
|
||||
|
||||
def __len__():
|
||||
"""Return the number of items in the container."""
|
||||
|
||||
|
||||
class IKeySequence(IKeyed, ISized):
|
||||
|
||||
def __getitem__(index):
|
||||
"""Return the key in the given index position.
|
||||
|
||||
This allows iteration with for loops and use in functions,
|
||||
like map and list, that read sequences.
|
||||
"""
|
||||
|
||||
|
||||
class ISet(IKeySequence, ISetMutable):
|
||||
pass
|
||||
|
||||
|
||||
class ITreeSet(IKeyed, ISetMutable):
|
||||
pass
|
||||
|
||||
class IMinimalDictionary(ISized, IKeyed):
|
||||
|
||||
def get(key, default):
|
||||
"""Get the value associated with the given key.
|
||||
|
||||
Return the default if has_key(key) is false.
|
||||
"""
|
||||
|
||||
def __getitem__(key):
|
||||
"""Get the value associated with the given key.
|
||||
|
||||
Raise KeyError if has_key(key) is false.
|
||||
"""
|
||||
|
||||
def __setitem__(key, value):
|
||||
"""Set the value associated with the given key."""
|
||||
|
||||
def __delitem__(key):
|
||||
"""Delete the value associated with the given key.
|
||||
|
||||
Raise KeyError if has_key(key) is false.
|
||||
"""
|
||||
|
||||
def values(min=None, max=None, excludemin=False, excludemax=False):
|
||||
"""Return an IReadSequence containing the values in the collection.
|
||||
|
||||
The type of the IReadSequence is not specified. It could be a list
|
||||
or a tuple or some other type.
|
||||
|
||||
All arguments are optional, and may be specified as keyword
|
||||
arguments, or by position.
|
||||
|
||||
If a min is specified, then output is constrained to values whose
|
||||
keys are greater than or equal to the given min, and, if excludemin
|
||||
is specified and true, is further constrained to values whose keys
|
||||
are strictly greater than min. A min value of None is ignored. If
|
||||
min is None or not specified, and excludemin is true, the value
|
||||
corresponding to the smallest key is excluded.
|
||||
|
||||
If a max is specified, then output is constrained to values whose
|
||||
keys are less than or equal to the given max, and, if excludemax is
|
||||
specified and true, is further constrained to values whose keys are
|
||||
strictly less than max. A max value of None is ignored. If max is
|
||||
None or not specified, and excludemax is true, the value
|
||||
corresponding to the largest key is excluded.
|
||||
"""
|
||||
|
||||
def items(min=None, max=None, excludemin=False, excludemax=False):
|
||||
"""Return an IReadSequence containing the items in the collection.
|
||||
|
||||
An item is a 2-tuple, a (key, value) pair.
|
||||
|
||||
The type of the IReadSequence is not specified. It could be a list
|
||||
or a tuple or some other type.
|
||||
|
||||
All arguments are optional, and may be specified as keyword
|
||||
arguments, or by position.
|
||||
|
||||
If a min is specified, then output is constrained to items whose
|
||||
keys are greater than or equal to the given min, and, if excludemin
|
||||
is specified and true, is further constrained to items whose keys
|
||||
are strictly greater than min. A min value of None is ignored. If
|
||||
min is None or not specified, and excludemin is true, the item with
|
||||
the smallest key is excluded.
|
||||
|
||||
If a max is specified, then output is constrained to items whose
|
||||
keys are less than or equal to the given max, and, if excludemax is
|
||||
specified and true, is further constrained to items whose keys are
|
||||
strictly less than max. A max value of None is ignored. If max is
|
||||
None or not specified, and excludemax is true, the item with the
|
||||
largest key is excluded.
|
||||
"""
|
||||
|
||||
class IDictionaryIsh(IMinimalDictionary):
|
||||
|
||||
def update(collection):
|
||||
"""Add the items from the given collection object to the collection.
|
||||
|
||||
The input collection must be a sequence of (key, value) 2-tuples,
|
||||
or an object with an 'items' method that returns a sequence of
|
||||
(key, value) pairs.
|
||||
"""
|
||||
|
||||
def byValue(minValue):
|
||||
"""Return a sequence of (value, key) pairs, sorted by value.
|
||||
|
||||
Values < minValue are omitted and other values are "normalized" by
|
||||
the minimum value. This normalization may be a noop, but, for
|
||||
integer values, the normalization is division.
|
||||
"""
|
||||
|
||||
def setdefault(key, d):
|
||||
"""D.setdefault(k, d) -> D.get(k, d), also set D[k]=d if k not in D.
|
||||
|
||||
Return the value like get() except that if key is missing, d is both
|
||||
returned and inserted into the dictionary as the value of k.
|
||||
|
||||
Note that, unlike as for Python's dict.setdefault(), d is not
|
||||
optional. Python defaults d to None, but that doesn't make sense
|
||||
for mappings that can't have None as a value (for example, an
|
||||
IIBTree can have only integers as values).
|
||||
"""
|
||||
|
||||
def pop(key, d):
|
||||
"""D.pop(k[, d]) -> v, remove key and return the corresponding value.
|
||||
|
||||
If key is not found, d is returned if given, otherwise KeyError is
|
||||
raised.
|
||||
"""
|
||||
|
||||
|
||||
class IBTree(IDictionaryIsh):
|
||||
|
||||
def insert(key, value):
|
||||
"""Insert a key and value into the collection.
|
||||
|
||||
If the key was already in the collection, then there is no
|
||||
change and 0 is returned.
|
||||
|
||||
If the key was not already in the collection, then the item is
|
||||
added and 1 is returned.
|
||||
|
||||
This method is here to allow one to generate random keys and
|
||||
to insert and test whether the key was there in one operation.
|
||||
|
||||
A standard idiom for generating new keys will be::
|
||||
|
||||
key = generate_key()
|
||||
while not t.insert(key, value):
|
||||
key=generate_key()
|
||||
"""
|
||||
|
||||
|
||||
class IMerge(Interface):
|
||||
"""Object with methods for merging sets, buckets, and trees.
|
||||
|
||||
These methods are supplied in modules that define collection
|
||||
classes with particular key and value types. The operations apply
|
||||
only to collections from the same module. For example, the
|
||||
IIBTree.union can only be used with IIBTree.IIBTree,
|
||||
IIBTree.IIBucket, IIBTree.IISet, and IIBTree.IITreeSet.
|
||||
|
||||
The implementing module has a value type. The IOBTree and OOBTree
|
||||
modules have object value type. The IIBTree and OIBTree modules
|
||||
have integer value types. Other modules may be defined in the
|
||||
future that have other value types.
|
||||
|
||||
The individual types are classified into set (Set and TreeSet) and
|
||||
mapping (Bucket and BTree) types.
|
||||
"""
|
||||
|
||||
def difference(c1, c2):
|
||||
"""Return the keys or items in c1 for which there is no key in c2.
|
||||
|
||||
If c1 is None, then None is returned. If c2 is None, then c1
|
||||
is returned.
|
||||
|
||||
If neither c1 nor c2 is None, the output is a Set if c1 is a Set or
|
||||
TreeSet, and is a Bucket if c1 is a Bucket or BTree.
|
||||
"""
|
||||
|
||||
def union(c1, c2):
|
||||
"""Compute the Union of c1 and c2.
|
||||
|
||||
If c1 is None, then c2 is returned, otherwise, if c2 is None,
|
||||
then c1 is returned.
|
||||
|
||||
The output is a Set containing keys from the input
|
||||
collections.
|
||||
"""
|
||||
|
||||
def intersection(c1, c2):
|
||||
"""Compute the intersection of c1 and c2.
|
||||
|
||||
If c1 is None, then c2 is returned, otherwise, if c2 is None,
|
||||
then c1 is returned.
|
||||
|
||||
The output is a Set containing matching keys from the input
|
||||
collections.
|
||||
"""
|
||||
|
||||
|
||||
class IBTreeModule(Interface):
|
||||
"""These are available in all modules (IOBTree, OIBTree, OOBTree, IIBTree,
|
||||
IFBTree, LFBTree, LOBTree, OLBTree, and LLBTree).
|
||||
"""
|
||||
|
||||
BTree = Attribute(
|
||||
"""The IBTree for this module.
|
||||
|
||||
Also available as [prefix]BTree, as in IOBTree.""")
|
||||
|
||||
Bucket = Attribute(
|
||||
"""The leaf-node data buckets used by the BTree.
|
||||
|
||||
(IBucket is not currently defined in this file, but is essentially
|
||||
IDictionaryIsh, with the exception of __nonzero__, as of this
|
||||
writing.)
|
||||
|
||||
Also available as [prefix]Bucket, as in IOBucket.""")
|
||||
|
||||
TreeSet = Attribute(
|
||||
"""The ITreeSet for this module.
|
||||
|
||||
Also available as [prefix]TreeSet, as in IOTreeSet.""")
|
||||
|
||||
Set = Attribute(
|
||||
"""The ISet for this module: the leaf-node data buckets used by the
|
||||
TreeSet.
|
||||
|
||||
Also available as [prefix]BTree, as in IOSet.""")
|
||||
|
||||
|
||||
class IIMerge(IMerge):
|
||||
"""Merge collections with integer value type.
|
||||
|
||||
A primary intent is to support operations with no or integer
|
||||
values, which are used as "scores" to rate indiviual keys. That
|
||||
is, in this context, a BTree or Bucket is viewed as a set with
|
||||
scored keys, using integer scores.
|
||||
"""
|
||||
|
||||
def weightedUnion(c1, c2, weight1=1, weight2=1):
|
||||
"""Compute the weighted union of c1 and c2.
|
||||
|
||||
If c1 and c2 are None, the output is (0, None).
|
||||
|
||||
If c1 is None and c2 is not None, the output is (weight2, c2).
|
||||
|
||||
If c1 is not None and c2 is None, the output is (weight1, c1).
|
||||
|
||||
Else, and hereafter, c1 is not None and c2 is not None.
|
||||
|
||||
If c1 and c2 are both sets, the output is 1 and the (unweighted)
|
||||
union of the sets.
|
||||
|
||||
Else the output is 1 and a Bucket whose keys are the union of c1 and
|
||||
c2's keys, and whose values are::
|
||||
|
||||
v1*weight1 + v2*weight2
|
||||
|
||||
where:
|
||||
|
||||
v1 is 0 if the key is not in c1
|
||||
1 if the key is in c1 and c1 is a set
|
||||
c1[key] if the key is in c1 and c1 is a mapping
|
||||
|
||||
v2 is 0 if the key is not in c2
|
||||
1 if the key is in c2 and c2 is a set
|
||||
c2[key] if the key is in c2 and c2 is a mapping
|
||||
|
||||
Note that c1 and c2 must be collections.
|
||||
"""
|
||||
|
||||
def weightedIntersection(c1, c2, weight1=1, weight2=1):
|
||||
"""Compute the weighted intersection of c1 and c2.
|
||||
|
||||
If c1 and c2 are None, the output is (0, None).
|
||||
|
||||
If c1 is None and c2 is not None, the output is (weight2, c2).
|
||||
|
||||
If c1 is not None and c2 is None, the output is (weight1, c1).
|
||||
|
||||
Else, and hereafter, c1 is not None and c2 is not None.
|
||||
|
||||
If c1 and c2 are both sets, the output is the sum of the weights
|
||||
and the (unweighted) intersection of the sets.
|
||||
|
||||
Else the output is 1 and a Bucket whose keys are the intersection of
|
||||
c1 and c2's keys, and whose values are::
|
||||
|
||||
v1*weight1 + v2*weight2
|
||||
|
||||
where:
|
||||
|
||||
v1 is 1 if c1 is a set
|
||||
c1[key] if c1 is a mapping
|
||||
|
||||
v2 is 1 if c2 is a set
|
||||
c2[key] if c2 is a mapping
|
||||
|
||||
Note that c1 and c2 must be collections.
|
||||
"""
|
||||
|
||||
|
||||
class IMergeIntegerKey(IMerge):
|
||||
"""IMerge-able objects with integer keys.
|
||||
|
||||
Concretely, this means the types in IOBTree and IIBTree.
|
||||
"""
|
||||
|
||||
def multiunion(seq):
|
||||
"""Return union of (zero or more) integer sets, as an integer set.
|
||||
|
||||
seq is a sequence of objects each convertible to an integer set.
|
||||
These objects are convertible to an integer set:
|
||||
|
||||
+ An integer, which is added to the union.
|
||||
|
||||
+ A Set or TreeSet from the same module (for example, an
|
||||
IIBTree.TreeSet for IIBTree.multiunion()). The elements of the
|
||||
set are added to the union.
|
||||
|
||||
+ A Bucket or BTree from the same module (for example, an
|
||||
IOBTree.IOBTree for IOBTree.multiunion()). The keys of the
|
||||
mapping are added to the union.
|
||||
|
||||
The union is returned as a Set from the same module (for example,
|
||||
IIBTree.multiunion() returns an IIBTree.IISet).
|
||||
|
||||
The point to this method is that it can run much faster than
|
||||
doing a sequence of two-input union() calls. Under the covers,
|
||||
all the integers in all the inputs are sorted via a single
|
||||
linear-time radix sort, then duplicates are removed in a second
|
||||
linear-time pass.
|
||||
"""
|
||||
|
||||
class IBTreeFamily(Interface):
|
||||
"""the 64-bit or 32-bit family"""
|
||||
IO = Attribute('The IIntegerObjectBTreeModule for this family')
|
||||
OI = Attribute('The IObjectIntegerBTreeModule for this family')
|
||||
II = Attribute('The IIntegerIntegerBTreeModule for this family')
|
||||
IF = Attribute('The IIntegerFloatBTreeModule for this family')
|
||||
OO = Attribute('The IObjectObjectBTreeModule for this family')
|
||||
maxint = Attribute('The maximum integer storable in this family')
|
||||
minint = Attribute('The minimum integer storable in this family')
|
||||
|
||||
|
||||
class IIntegerObjectBTreeModule(IBTreeModule, IMerge):
|
||||
"""keys, or set values, are integers; values are objects.
|
||||
|
||||
describes IOBTree and LOBTree"""
|
||||
|
||||
family = Attribute('The IBTreeFamily of this module')
|
||||
|
||||
|
||||
class IObjectIntegerBTreeModule(IBTreeModule, IIMerge):
|
||||
"""keys, or set values, are objects; values are integers.
|
||||
|
||||
Object keys (and set values) must sort reliably (for instance, *not* on
|
||||
object id)! Homogenous key types recommended.
|
||||
|
||||
describes OIBTree and LOBTree"""
|
||||
|
||||
family = Attribute('The IBTreeFamily of this module')
|
||||
|
||||
|
||||
class IIntegerIntegerBTreeModule(IBTreeModule, IIMerge, IMergeIntegerKey):
|
||||
"""keys, or set values, are integers; values are also integers.
|
||||
|
||||
describes IIBTree and LLBTree"""
|
||||
|
||||
family = Attribute('The IBTreeFamily of this module')
|
||||
|
||||
|
||||
class IObjectObjectBTreeModule(IBTreeModule, IMerge):
|
||||
"""keys, or set values, are objects; values are also objects.
|
||||
|
||||
Object keys (and set values) must sort reliably (for instance, *not* on
|
||||
object id)! Homogenous key types recommended.
|
||||
|
||||
describes OOBTree"""
|
||||
|
||||
# Note that there's no ``family`` attribute; all families include
|
||||
# the OO flavor of BTrees.
|
||||
|
||||
|
||||
class IIntegerFloatBTreeModule(IBTreeModule, IMerge):
|
||||
"""keys, or set values, are integers; values are floats.
|
||||
|
||||
describes IFBTree and LFBTree"""
|
||||
|
||||
family = Attribute('The IBTreeFamily of this module')
|
||||
|
||||
|
||||
try:
|
||||
from ZODB.POSException import BTreesConflictError
|
||||
except ImportError:
|
||||
class BTreesConflictError(ValueError):
|
||||
@property
|
||||
def reason(self):
|
||||
return self.args[-1]
|
||||
|
||||
###############################################################
|
||||
# IMPORTANT NOTE
|
||||
#
|
||||
# Getting the length of a BTree, TreeSet, or output of keys,
|
||||
# values, or items of same is expensive. If you need to get the
|
||||
# length, you need to maintain this separately.
|
||||
#
|
||||
# Eventually, I need to express this through the interfaces.
|
||||
#
|
||||
################################################################
|
113
thesisenv/lib/python3.6/site-packages/BTrees/LFBTree.py
Normal file
113
thesisenv/lib/python3.6/site-packages/BTrees/LFBTree.py
Normal file
@ -0,0 +1,113 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001-2012 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
|
||||
'LFBucket', 'LFSet', 'LFBTree', 'LFTreeSet',
|
||||
'union', 'intersection', 'difference',
|
||||
'weightedUnion', 'weightedIntersection', 'multiunion',
|
||||
)
|
||||
|
||||
from zope.interface import moduleProvides
|
||||
|
||||
from .Interfaces import IIntegerFloatBTreeModule
|
||||
from ._base import Bucket
|
||||
from ._base import MERGE
|
||||
from ._base import MERGE_WEIGHT_numeric
|
||||
from ._base import MERGE_DEFAULT_float
|
||||
from ._base import Set
|
||||
from ._base import Tree as BTree
|
||||
from ._base import TreeSet
|
||||
from ._base import _TreeIterator
|
||||
from ._base import difference as _difference
|
||||
from ._base import intersection as _intersection
|
||||
from ._base import multiunion as _multiunion
|
||||
from ._base import set_operation as _set_operation
|
||||
from ._base import to_long as _to_key
|
||||
from ._base import to_float as _to_value
|
||||
from ._base import union as _union
|
||||
from ._base import weightedIntersection as _weightedIntersection
|
||||
from ._base import weightedUnion as _weightedUnion
|
||||
from ._base import _fix_pickle
|
||||
from ._compat import import_c_extension
|
||||
|
||||
_BUCKET_SIZE = 120
|
||||
_TREE_SIZE = 500
|
||||
using64bits = True
|
||||
|
||||
|
||||
class LFBucketPy(Bucket):
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class LFSetPy(Set):
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class LFBTreePy(BTree):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class LFTreeSetPy(TreeSet):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class LFTreeIteratorPy(_TreeIterator):
|
||||
pass
|
||||
|
||||
|
||||
# Can't declare forward refs, so fix up afterwards:
|
||||
|
||||
LFBucketPy._mapping_type = LFBucketPy._bucket_type = LFBucketPy
|
||||
LFBucketPy._set_type = LFSetPy
|
||||
|
||||
LFSetPy._mapping_type = LFBucketPy
|
||||
LFSetPy._set_type = LFSetPy._bucket_type = LFSetPy
|
||||
|
||||
LFBTreePy._mapping_type = LFBTreePy._bucket_type = LFBucketPy
|
||||
LFBTreePy._set_type = LFSetPy
|
||||
|
||||
LFTreeSetPy._mapping_type = LFBucketPy
|
||||
LFTreeSetPy._set_type = LFTreeSetPy._bucket_type = LFSetPy
|
||||
|
||||
|
||||
differencePy = _set_operation(_difference, LFSetPy)
|
||||
unionPy = _set_operation(_union, LFSetPy)
|
||||
intersectionPy = _set_operation(_intersection, LFSetPy)
|
||||
multiunionPy = _set_operation(_multiunion, LFSetPy)
|
||||
weightedUnionPy = _set_operation(_weightedUnion, LFSetPy)
|
||||
weightedIntersectionPy = _set_operation(_weightedIntersection, LFSetPy)
|
||||
|
||||
import_c_extension(globals())
|
||||
|
||||
_fix_pickle(globals(), __name__)
|
||||
|
||||
moduleProvides(IIntegerFloatBTreeModule)
|
113
thesisenv/lib/python3.6/site-packages/BTrees/LLBTree.py
Normal file
113
thesisenv/lib/python3.6/site-packages/BTrees/LLBTree.py
Normal file
@ -0,0 +1,113 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001-2012 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
|
||||
'LLBucket', 'LLSet', 'LLBTree', 'LLTreeSet',
|
||||
'union', 'intersection', 'difference',
|
||||
'weightedUnion', 'weightedIntersection', 'multiunion',
|
||||
)
|
||||
|
||||
from zope.interface import moduleProvides
|
||||
|
||||
from .Interfaces import IIntegerIntegerBTreeModule
|
||||
from ._base import Bucket
|
||||
from ._base import MERGE
|
||||
from ._base import MERGE_WEIGHT_numeric
|
||||
from ._base import MERGE_DEFAULT_int
|
||||
from ._base import Set
|
||||
from ._base import Tree as BTree
|
||||
from ._base import TreeSet
|
||||
from ._base import _TreeIterator
|
||||
from ._base import difference as _difference
|
||||
from ._base import intersection as _intersection
|
||||
from ._base import multiunion as _multiunion
|
||||
from ._base import set_operation as _set_operation
|
||||
from ._base import to_long as _to_key
|
||||
from ._base import to_long as _to_value
|
||||
from ._base import union as _union
|
||||
from ._base import weightedIntersection as _weightedIntersection
|
||||
from ._base import weightedUnion as _weightedUnion
|
||||
from ._base import _fix_pickle
|
||||
from ._compat import import_c_extension
|
||||
|
||||
_BUCKET_SIZE = 120
|
||||
_TREE_SIZE = 500
|
||||
using64bits = True
|
||||
|
||||
|
||||
class LLBucketPy(Bucket):
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class LLSetPy(Set):
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class LLBTreePy(BTree):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class LLTreeSetPy(TreeSet):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class LLTreeIteratorPy(_TreeIterator):
|
||||
pass
|
||||
|
||||
|
||||
# Can't declare forward refs, so fix up afterwards:
|
||||
|
||||
LLBucketPy._mapping_type = LLBucketPy._bucket_type = LLBucketPy
|
||||
LLBucketPy._set_type = LLSetPy
|
||||
|
||||
LLSetPy._mapping_type = LLBucketPy
|
||||
LLSetPy._set_type = LLSetPy._bucket_type = LLSetPy
|
||||
|
||||
LLBTreePy._mapping_type = LLBTreePy._bucket_type = LLBucketPy
|
||||
LLBTreePy._set_type = LLSetPy
|
||||
|
||||
LLTreeSetPy._mapping_type = LLBucketPy
|
||||
LLTreeSetPy._set_type = LLTreeSetPy._bucket_type = LLSetPy
|
||||
|
||||
|
||||
differencePy = _set_operation(_difference, LLSetPy)
|
||||
unionPy = _set_operation(_union, LLSetPy)
|
||||
intersectionPy = _set_operation(_intersection, LLSetPy)
|
||||
multiunionPy = _set_operation(_multiunion, LLSetPy)
|
||||
weightedUnionPy = _set_operation(_weightedUnion, LLSetPy)
|
||||
weightedIntersectionPy = _set_operation(_weightedIntersection, LLSetPy)
|
||||
|
||||
import_c_extension(globals())
|
||||
|
||||
_fix_pickle(globals(), __name__)
|
||||
|
||||
moduleProvides(IIntegerIntegerBTreeModule)
|
96
thesisenv/lib/python3.6/site-packages/BTrees/LOBTree.py
Normal file
96
thesisenv/lib/python3.6/site-packages/BTrees/LOBTree.py
Normal file
@ -0,0 +1,96 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001-2012 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
|
||||
'LOBucket', 'LOSet', 'LOBTree', 'LOTreeSet',
|
||||
'union', 'intersection', 'difference', 'multiunion',
|
||||
)
|
||||
|
||||
from zope.interface import moduleProvides
|
||||
|
||||
from .Interfaces import IIntegerObjectBTreeModule
|
||||
from ._base import Bucket
|
||||
from ._base import MERGE_WEIGHT_default
|
||||
from ._base import Set
|
||||
from ._base import Tree as BTree
|
||||
from ._base import TreeSet
|
||||
from ._base import _TreeIterator
|
||||
from ._base import difference as _difference
|
||||
from ._base import intersection as _intersection
|
||||
from ._base import multiunion as _multiunion
|
||||
from ._base import set_operation as _set_operation
|
||||
from ._base import to_long as _to_key
|
||||
from ._base import to_ob as _to_value
|
||||
from ._base import union as _union
|
||||
from ._base import _fix_pickle
|
||||
from ._compat import import_c_extension
|
||||
|
||||
_BUCKET_SIZE = 60
|
||||
_TREE_SIZE = 500
|
||||
using64bits = True
|
||||
|
||||
|
||||
class LOBucketPy(Bucket):
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_default
|
||||
|
||||
|
||||
class LOSetPy(Set):
|
||||
_to_key = _to_key
|
||||
|
||||
|
||||
class LOBTreePy(BTree):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_default
|
||||
|
||||
|
||||
class LOTreeSetPy(TreeSet):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
|
||||
|
||||
class LOTreeIteratorPy(_TreeIterator):
|
||||
pass
|
||||
|
||||
|
||||
# Can't declare forward refs, so fix up afterwards:
|
||||
|
||||
LOBucketPy._mapping_type = LOBucketPy._bucket_type = LOBucketPy
|
||||
LOBucketPy._set_type = LOSetPy
|
||||
|
||||
LOSetPy._mapping_type = LOBucketPy
|
||||
LOSetPy._set_type = LOSetPy._bucket_type = LOSetPy
|
||||
|
||||
LOBTreePy._mapping_type = LOBTreePy._bucket_type = LOBucketPy
|
||||
LOBTreePy._set_type = LOSetPy
|
||||
|
||||
LOTreeSetPy._mapping_type = LOBucketPy
|
||||
LOTreeSetPy._set_type = LOTreeSetPy._bucket_type = LOSetPy
|
||||
|
||||
|
||||
differencePy = _set_operation(_difference, LOSetPy)
|
||||
unionPy = _set_operation(_union, LOSetPy)
|
||||
intersectionPy = _set_operation(_intersection, LOSetPy)
|
||||
multiunionPy = _set_operation(_multiunion, LOSetPy)
|
||||
|
||||
import_c_extension(globals())
|
||||
|
||||
_fix_pickle(globals(), __name__)
|
||||
|
||||
moduleProvides(IIntegerObjectBTreeModule)
|
58
thesisenv/lib/python3.6/site-packages/BTrees/Length.py
Normal file
58
thesisenv/lib/python3.6/site-packages/BTrees/Length.py
Normal file
@ -0,0 +1,58 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001, 2002 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import persistent
|
||||
|
||||
class Length(persistent.Persistent):
|
||||
"""BTree lengths are often too expensive to compute.
|
||||
|
||||
Objects that use BTrees need to keep track of lengths themselves.
|
||||
This class provides an object for doing this.
|
||||
|
||||
As a bonus, the object support application-level conflict
|
||||
resolution.
|
||||
|
||||
It is tempting to to assign length objects to __len__ attributes
|
||||
to provide instance-specific __len__ methods. However, this no
|
||||
longer works as expected, because new-style classes cache
|
||||
class-defined slot methods (like __len__) in C type slots. Thus,
|
||||
instance-defined slot fillers are ignored.
|
||||
"""
|
||||
# class-level default required to keep copy.deepcopy happy -- see
|
||||
# https://bugs.launchpad.net/zodb/+bug/516653
|
||||
value = 0
|
||||
|
||||
def __init__(self, v=0):
|
||||
self.value = v
|
||||
|
||||
def __getstate__(self):
|
||||
return self.value
|
||||
|
||||
def __setstate__(self, v):
|
||||
self.value = v
|
||||
|
||||
def set(self, v):
|
||||
"Set the length value to v."
|
||||
self.value = v
|
||||
|
||||
def _p_resolveConflict(self, old, s1, s2):
|
||||
return s1 + s2 - old
|
||||
|
||||
def change(self, delta):
|
||||
"Add delta to the length value."
|
||||
self.value += delta
|
||||
|
||||
def __call__(self, *args):
|
||||
"Return the current length value."
|
||||
return self.value
|
349
thesisenv/lib/python3.6/site-packages/BTrees/MergeTemplate.c
Normal file
349
thesisenv/lib/python3.6/site-packages/BTrees/MergeTemplate.c
Normal file
@ -0,0 +1,349 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2001, 2002 Zope Foundation and Contributors.
|
||||
All Rights Reserved.
|
||||
|
||||
This software is subject to the provisions of the Zope Public License,
|
||||
Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#define MERGETEMPLATE_C "$Id$\n"
|
||||
|
||||
/****************************************************************************
|
||||
Set operations
|
||||
****************************************************************************/
|
||||
|
||||
static int
|
||||
merge_output(Bucket *r, SetIteration *i, int mapping)
|
||||
{
|
||||
if (r->len >= r->size && Bucket_grow(r, -1, !mapping) < 0)
|
||||
return -1;
|
||||
COPY_KEY(r->keys[r->len], i->key);
|
||||
INCREF_KEY(r->keys[r->len]);
|
||||
if (mapping) {
|
||||
COPY_VALUE(r->values[r->len], i->value);
|
||||
INCREF_VALUE(r->values[r->len]);
|
||||
}
|
||||
r->len++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The "reason" argument is a little integer giving "a reason" for the
|
||||
* error. In the Zope3 codebase, these are mapped to explanatory strings
|
||||
* via zodb/btrees/interfaces.py.
|
||||
*/
|
||||
static PyObject *
|
||||
merge_error(int p1, int p2, int p3, int reason)
|
||||
{
|
||||
PyObject *r;
|
||||
|
||||
UNLESS (r=Py_BuildValue("iiii", p1, p2, p3, reason)) r=Py_None;
|
||||
if (ConflictError == NULL) {
|
||||
ConflictError = PyExc_ValueError;
|
||||
Py_INCREF(ConflictError);
|
||||
}
|
||||
PyErr_SetObject(ConflictError, r);
|
||||
if (r != Py_None)
|
||||
{
|
||||
Py_DECREF(r);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* It's hard to explain "the rules" for bucket_merge, in large part because
|
||||
* any automatic conflict-resolution scheme is going to be incorrect for
|
||||
* some endcases of *some* app. The scheme here is pretty conservative,
|
||||
* and should be OK for most apps. It's easier to explain what the code
|
||||
* allows than what it forbids:
|
||||
*
|
||||
* Leaving things alone: it's OK if both s2 and s3 leave a piece of s1
|
||||
* alone (don't delete the key, and don't change the value).
|
||||
*
|
||||
* Key deletion: a transaction (s2 or s3) can delete a key (from s1), but
|
||||
* only if the other transaction (of s2 and s3) doesn't delete the same key.
|
||||
* However, it's not OK for s2 and s3 to, between them, end up deleting all
|
||||
* the keys. This is a higher-level constraint, due to that the caller of
|
||||
* bucket_merge() doesn't have enough info to unlink the resulting empty
|
||||
* bucket from its BTree correctly. It's also not OK if s2 or s3 are empty,
|
||||
* because the transaction that emptied the bucket unlinked the bucket from
|
||||
* the tree, and nothing we do here can get it linked back in again.
|
||||
*
|
||||
* Key insertion: s2 or s3 can add a new key, provided the other transaction
|
||||
* doesn't insert the same key. It's not OK even if they insert the same
|
||||
* <key, value> pair.
|
||||
*
|
||||
* Mapping value modification: s2 or s3 can modify the value associated
|
||||
* with a key in s1, provided the other transaction doesn't make a
|
||||
* modification of the same key to a different value. It's OK if s2 and s3
|
||||
* both give the same new value to the key while it's hard to be precise about
|
||||
* why, this doesn't seem consistent with that it's *not* OK for both to add
|
||||
* a new key mapping to the same value).
|
||||
*/
|
||||
static PyObject *
|
||||
bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3)
|
||||
{
|
||||
Bucket *r=0;
|
||||
PyObject *s;
|
||||
SetIteration i1 = {0,0,0}, i2 = {0,0,0}, i3 = {0,0,0};
|
||||
int cmp12, cmp13, cmp23, mapping, set;
|
||||
|
||||
/* If either "after" bucket is empty, punt. */
|
||||
if (s2->len == 0 || s3->len == 0)
|
||||
{
|
||||
merge_error(-1, -1, -1, 12);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (initSetIteration(&i1, OBJECT(s1), 1) < 0)
|
||||
goto err;
|
||||
if (initSetIteration(&i2, OBJECT(s2), 1) < 0)
|
||||
goto err;
|
||||
if (initSetIteration(&i3, OBJECT(s3), 1) < 0)
|
||||
goto err;
|
||||
|
||||
mapping = i1.usesValue | i2.usesValue | i3.usesValue;
|
||||
set = !mapping;
|
||||
|
||||
if (mapping)
|
||||
r = (Bucket *)PyObject_CallObject((PyObject *)&BucketType, NULL);
|
||||
else
|
||||
r = (Bucket *)PyObject_CallObject((PyObject *)&SetType, NULL);
|
||||
if (r == NULL)
|
||||
goto err;
|
||||
|
||||
if (i1.next(&i1) < 0)
|
||||
goto err;
|
||||
if (i2.next(&i2) < 0)
|
||||
goto err;
|
||||
if (i3.next(&i3) < 0)
|
||||
goto err;
|
||||
|
||||
/* Consult zodb/btrees/interfaces.py for the meaning of the last
|
||||
* argument passed to merge_error().
|
||||
*/
|
||||
/* TODO: This isn't passing on errors raised by value comparisons. */
|
||||
while (i1.position >= 0 && i2.position >= 0 && i3.position >= 0)
|
||||
{
|
||||
TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err;
|
||||
TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err;
|
||||
if (cmp12==0)
|
||||
{
|
||||
if (cmp13==0)
|
||||
{
|
||||
if (set || (TEST_VALUE(i1.value, i2.value) == 0))
|
||||
{ /* change in i3 value or all same */
|
||||
if (merge_output(r, &i3, mapping) < 0) goto err;
|
||||
}
|
||||
else if (set || (TEST_VALUE(i1.value, i3.value) == 0))
|
||||
{ /* change in i2 value */
|
||||
if (merge_output(r, &i2, mapping) < 0) goto err;
|
||||
}
|
||||
else
|
||||
{ /* conflicting value changes in i2 and i3 */
|
||||
merge_error(i1.position, i2.position, i3.position, 1);
|
||||
goto err;
|
||||
}
|
||||
if (i1.next(&i1) < 0) goto err;
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
if (i3.next(&i3) < 0) goto err;
|
||||
}
|
||||
else if (cmp13 > 0)
|
||||
{ /* insert i3 */
|
||||
if (merge_output(r, &i3, mapping) < 0) goto err;
|
||||
if (i3.next(&i3) < 0) goto err;
|
||||
}
|
||||
else if (set || (TEST_VALUE(i1.value, i2.value) == 0))
|
||||
{ /* deleted in i3 */
|
||||
if (i3.position == 1)
|
||||
{
|
||||
/* Deleted the first item. This will modify the
|
||||
parent node, so we don't know if merging will be
|
||||
safe
|
||||
*/
|
||||
merge_error(i1.position, i2.position, i3.position, 13);
|
||||
goto err;
|
||||
}
|
||||
if (i1.next(&i1) < 0) goto err;
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
}
|
||||
else
|
||||
{ /* conflicting del in i3 and change in i2 */
|
||||
merge_error(i1.position, i2.position, i3.position, 2);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else if (cmp13 == 0)
|
||||
{
|
||||
if (cmp12 > 0)
|
||||
{ /* insert i2 */
|
||||
if (merge_output(r, &i2, mapping) < 0) goto err;
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
}
|
||||
else if (set || (TEST_VALUE(i1.value, i3.value) == 0))
|
||||
{ /* deleted in i2 */
|
||||
if (i2.position == 1)
|
||||
{
|
||||
/* Deleted the first item. This will modify the
|
||||
parent node, so we don't know if merging will be
|
||||
safe
|
||||
*/
|
||||
merge_error(i1.position, i2.position, i3.position, 13);
|
||||
goto err;
|
||||
}
|
||||
if (i1.next(&i1) < 0) goto err;
|
||||
if (i3.next(&i3) < 0) goto err;
|
||||
}
|
||||
else
|
||||
{ /* conflicting del in i2 and change in i3 */
|
||||
merge_error(i1.position, i2.position, i3.position, 3);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* Both keys changed */
|
||||
TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err;
|
||||
if (cmp23==0)
|
||||
{ /* dueling inserts or deletes */
|
||||
merge_error(i1.position, i2.position, i3.position, 4);
|
||||
goto err;
|
||||
}
|
||||
if (cmp12 > 0)
|
||||
{ /* insert i2 */
|
||||
if (cmp23 > 0)
|
||||
{ /* insert i3 first */
|
||||
if (merge_output(r, &i3, mapping) < 0) goto err;
|
||||
if (i3.next(&i3) < 0) goto err;
|
||||
}
|
||||
else
|
||||
{ /* insert i2 first */
|
||||
if (merge_output(r, &i2, mapping) < 0) goto err;
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
}
|
||||
}
|
||||
else if (cmp13 > 0)
|
||||
{ /* Insert i3 */
|
||||
if (merge_output(r, &i3, mapping) < 0) goto err;
|
||||
if (i3.next(&i3) < 0) goto err;
|
||||
}
|
||||
else
|
||||
{ /* 1<2 and 1<3: both deleted 1.key */
|
||||
merge_error(i1.position, i2.position, i3.position, 5);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (i2.position >= 0 && i3.position >= 0)
|
||||
{ /* New inserts */
|
||||
TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err;
|
||||
if (cmp23==0)
|
||||
{ /* dueling inserts */
|
||||
merge_error(i1.position, i2.position, i3.position, 6);
|
||||
goto err;
|
||||
}
|
||||
if (cmp23 > 0)
|
||||
{ /* insert i3 */
|
||||
if (merge_output(r, &i3, mapping) < 0) goto err;
|
||||
if (i3.next(&i3) < 0) goto err;
|
||||
}
|
||||
else
|
||||
{ /* insert i2 */
|
||||
if (merge_output(r, &i2, mapping) < 0) goto err;
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
}
|
||||
}
|
||||
|
||||
while (i1.position >= 0 && i2.position >= 0)
|
||||
{ /* remainder of i1 deleted in i3 */
|
||||
TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err;
|
||||
if (cmp12 > 0)
|
||||
{ /* insert i2 */
|
||||
if (merge_output(r, &i2, mapping) < 0) goto err;
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
}
|
||||
else if (cmp12==0 && (set || (TEST_VALUE(i1.value, i2.value) == 0)))
|
||||
{ /* delete i3 */
|
||||
if (i1.next(&i1) < 0) goto err;
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
}
|
||||
else
|
||||
{ /* Dueling deletes or delete and change */
|
||||
merge_error(i1.position, i2.position, i3.position, 7);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
while (i1.position >= 0 && i3.position >= 0)
|
||||
{ /* remainder of i1 deleted in i2 */
|
||||
TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err;
|
||||
if (cmp13 > 0)
|
||||
{ /* insert i3 */
|
||||
if (merge_output(r, &i3, mapping) < 0) goto err;
|
||||
if (i3.next(&i3) < 0) goto err;
|
||||
}
|
||||
else if (cmp13==0 && (set || (TEST_VALUE(i1.value, i3.value) == 0)))
|
||||
{ /* delete i2 */
|
||||
if (i1.next(&i1) < 0) goto err;
|
||||
if (i3.next(&i3) < 0) goto err;
|
||||
}
|
||||
else
|
||||
{ /* Dueling deletes or delete and change */
|
||||
merge_error(i1.position, i2.position, i3.position, 8);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (i1.position >= 0)
|
||||
{ /* Dueling deletes */
|
||||
merge_error(i1.position, i2.position, i3.position, 9);
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (i2.position >= 0)
|
||||
{ /* Inserting i2 at end */
|
||||
if (merge_output(r, &i2, mapping) < 0) goto err;
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
}
|
||||
|
||||
while (i3.position >= 0)
|
||||
{ /* Inserting i3 at end */
|
||||
if (merge_output(r, &i3, mapping) < 0) goto err;
|
||||
if (i3.next(&i3) < 0) goto err;
|
||||
}
|
||||
|
||||
/* If the output bucket is empty, conflict resolution doesn't have
|
||||
* enough info to unlink it from its containing BTree correctly.
|
||||
*/
|
||||
if (r->len == 0)
|
||||
{
|
||||
merge_error(-1, -1, -1, 10);
|
||||
goto err;
|
||||
}
|
||||
|
||||
finiSetIteration(&i1);
|
||||
finiSetIteration(&i2);
|
||||
finiSetIteration(&i3);
|
||||
|
||||
if (s1->next)
|
||||
{
|
||||
Py_INCREF(s1->next);
|
||||
r->next = s1->next;
|
||||
}
|
||||
s = bucket_getstate(r);
|
||||
Py_DECREF(r);
|
||||
|
||||
return s;
|
||||
|
||||
err:
|
||||
finiSetIteration(&i1);
|
||||
finiSetIteration(&i2);
|
||||
finiSetIteration(&i3);
|
||||
Py_XDECREF(r);
|
||||
return NULL;
|
||||
}
|
110
thesisenv/lib/python3.6/site-packages/BTrees/OIBTree.py
Normal file
110
thesisenv/lib/python3.6/site-packages/BTrees/OIBTree.py
Normal file
@ -0,0 +1,110 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001-2012 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
|
||||
'OIBucket', 'OISet', 'OIBTree', 'OITreeSet',
|
||||
'union', 'intersection', 'difference',
|
||||
'weightedUnion', 'weightedIntersection',
|
||||
)
|
||||
|
||||
from zope.interface import moduleProvides
|
||||
|
||||
from .Interfaces import IObjectIntegerBTreeModule
|
||||
from ._base import Bucket
|
||||
from ._base import MERGE
|
||||
from ._base import MERGE_WEIGHT_numeric
|
||||
from ._base import MERGE_DEFAULT_float
|
||||
from ._base import Set
|
||||
from ._base import Tree as BTree
|
||||
from ._base import TreeSet
|
||||
from ._base import _TreeIterator
|
||||
from ._base import difference as _difference
|
||||
from ._base import intersection as _intersection
|
||||
from ._base import set_operation as _set_operation
|
||||
from ._base import to_ob as _to_key
|
||||
from ._base import to_int as _to_value
|
||||
from ._base import union as _union
|
||||
from ._base import weightedIntersection as _weightedIntersection
|
||||
from ._base import weightedUnion as _weightedUnion
|
||||
from ._base import _fix_pickle
|
||||
from ._compat import import_c_extension
|
||||
|
||||
_BUCKET_SIZE = 60
|
||||
_TREE_SIZE = 250
|
||||
using64bits = True
|
||||
|
||||
class OIBucketPy(Bucket):
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class OISetPy(Set):
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class OIBTreePy(BTree):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class OITreeSetPy(TreeSet):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_float
|
||||
|
||||
|
||||
class OITreeIteratorPy(_TreeIterator):
|
||||
pass
|
||||
|
||||
|
||||
# Can't declare forward refs, so fix up afterwards:
|
||||
|
||||
OIBucketPy._mapping_type = OIBucketPy._bucket_type = OIBucketPy
|
||||
OIBucketPy._set_type = OISetPy
|
||||
|
||||
OISetPy._mapping_type = OIBucketPy
|
||||
OISetPy._set_type = OISetPy._bucket_type = OISetPy
|
||||
|
||||
OIBTreePy._mapping_type = OIBTreePy._bucket_type = OIBucketPy
|
||||
OIBTreePy._set_type = OISetPy
|
||||
|
||||
OITreeSetPy._mapping_type = OIBucketPy
|
||||
OITreeSetPy._set_type = OITreeSetPy._bucket_type = OISetPy
|
||||
|
||||
|
||||
differencePy = _set_operation(_difference, OISetPy)
|
||||
unionPy = _set_operation(_union, OISetPy)
|
||||
intersectionPy = _set_operation(_intersection, OISetPy)
|
||||
weightedUnionPy = _set_operation(_weightedUnion, OISetPy)
|
||||
weightedIntersectionPy = _set_operation(_weightedIntersection, OISetPy)
|
||||
|
||||
import_c_extension(globals())
|
||||
|
||||
_fix_pickle(globals(), __name__)
|
||||
|
||||
moduleProvides(IObjectIntegerBTreeModule)
|
111
thesisenv/lib/python3.6/site-packages/BTrees/OLBTree.py
Normal file
111
thesisenv/lib/python3.6/site-packages/BTrees/OLBTree.py
Normal file
@ -0,0 +1,111 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001-2012 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
|
||||
'OLBucket', 'OLSet', 'OLBTree', 'OLTreeSet',
|
||||
'union', 'intersection', 'difference',
|
||||
'weightedUnion', 'weightedIntersection',
|
||||
)
|
||||
|
||||
from zope.interface import moduleProvides
|
||||
|
||||
from .Interfaces import IObjectIntegerBTreeModule
|
||||
from ._base import Bucket
|
||||
from ._base import MERGE
|
||||
from ._base import MERGE_WEIGHT_numeric
|
||||
from ._base import MERGE_DEFAULT_int
|
||||
from ._base import Set
|
||||
from ._base import Tree as BTree
|
||||
from ._base import TreeSet
|
||||
from ._base import _TreeIterator
|
||||
from ._base import difference as _difference
|
||||
from ._base import intersection as _intersection
|
||||
from ._base import set_operation as _set_operation
|
||||
from ._base import to_ob as _to_key
|
||||
from ._base import to_long as _to_value
|
||||
from ._base import union as _union
|
||||
from ._base import weightedIntersection as _weightedIntersection
|
||||
from ._base import weightedUnion as _weightedUnion
|
||||
from ._base import _fix_pickle
|
||||
from ._compat import import_c_extension
|
||||
|
||||
_BUCKET_SIZE = 60
|
||||
_TREE_SIZE = 250
|
||||
using64bits = True
|
||||
|
||||
|
||||
class OLBucketPy(Bucket):
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class OLSetPy(Set):
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class OLBTreePy(BTree):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class OLTreeSetPy(TreeSet):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
MERGE = MERGE
|
||||
MERGE_WEIGHT = MERGE_WEIGHT_numeric
|
||||
MERGE_DEFAULT = MERGE_DEFAULT_int
|
||||
|
||||
|
||||
class OLTreeIteratorPy(_TreeIterator):
|
||||
pass
|
||||
|
||||
|
||||
# Can't declare forward refs, so fix up afterwards:
|
||||
|
||||
OLBucketPy._mapping_type = OLBucketPy._bucket_type = OLBucketPy
|
||||
OLBucketPy._set_type = OLSetPy
|
||||
|
||||
OLSetPy._mapping_type = OLBucketPy
|
||||
OLSetPy._set_type = OLSetPy._bucket_type = OLSetPy
|
||||
|
||||
OLBTreePy._mapping_type = OLBTreePy._bucket_type = OLBucketPy
|
||||
OLBTreePy._set_type = OLSetPy
|
||||
|
||||
OLTreeSetPy._mapping_type = OLBucketPy
|
||||
OLTreeSetPy._set_type = OLTreeSetPy._bucket_type = OLSetPy
|
||||
|
||||
|
||||
differencePy = _set_operation(_difference, OLSetPy)
|
||||
unionPy = _set_operation(_union, OLSetPy)
|
||||
intersectionPy = _set_operation(_intersection, OLSetPy)
|
||||
weightedUnionPy = _set_operation(_weightedUnion, OLSetPy)
|
||||
weightedIntersectionPy = _set_operation(_weightedIntersection, OLSetPy)
|
||||
|
||||
import_c_extension(globals())
|
||||
|
||||
_fix_pickle(globals(), __name__)
|
||||
|
||||
moduleProvides(IObjectIntegerBTreeModule)
|
91
thesisenv/lib/python3.6/site-packages/BTrees/OOBTree.py
Normal file
91
thesisenv/lib/python3.6/site-packages/BTrees/OOBTree.py
Normal file
@ -0,0 +1,91 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001-2012 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
__all__ = ('Bucket', 'Set', 'BTree', 'TreeSet',
|
||||
'OOBucket', 'OOSet', 'OOBTree', 'OOTreeSet',
|
||||
'union', 'intersection','difference',
|
||||
)
|
||||
|
||||
from zope.interface import moduleProvides
|
||||
|
||||
from .Interfaces import IObjectObjectBTreeModule
|
||||
from ._base import Bucket
|
||||
from ._base import Set
|
||||
from ._base import Tree as BTree
|
||||
from ._base import TreeSet
|
||||
from ._base import _TreeIterator
|
||||
from ._base import difference as _difference
|
||||
from ._base import intersection as _intersection
|
||||
from ._base import set_operation as _set_operation
|
||||
from ._base import to_ob as _to_key
|
||||
_to_value = _to_key
|
||||
from ._base import union as _union
|
||||
from ._base import _fix_pickle
|
||||
from ._compat import import_c_extension
|
||||
|
||||
_BUCKET_SIZE = 30
|
||||
_TREE_SIZE = 250
|
||||
using64bits = False
|
||||
|
||||
|
||||
class OOBucketPy(Bucket):
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
|
||||
|
||||
class OOSetPy(Set):
|
||||
_to_key = _to_key
|
||||
|
||||
|
||||
class OOBTreePy(BTree):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
_to_value = _to_value
|
||||
|
||||
|
||||
class OOTreeSetPy(TreeSet):
|
||||
max_leaf_size = _BUCKET_SIZE
|
||||
max_internal_size = _TREE_SIZE
|
||||
_to_key = _to_key
|
||||
|
||||
|
||||
class OOTreeIteratorPy(_TreeIterator):
|
||||
pass
|
||||
|
||||
|
||||
# Can't declare forward refs, so fix up afterwards:
|
||||
|
||||
OOBucketPy._mapping_type = OOBucketPy._bucket_type = OOBucketPy
|
||||
OOBucketPy._set_type = OOSetPy
|
||||
|
||||
OOSetPy._mapping_type = OOBucketPy
|
||||
OOSetPy._set_type = OOSetPy._bucket_type = OOSetPy
|
||||
|
||||
OOBTreePy._mapping_type = OOBTreePy._bucket_type = OOBucketPy
|
||||
OOBTreePy._set_type = OOSetPy
|
||||
|
||||
OOTreeSetPy._mapping_type = OOBucketPy
|
||||
OOTreeSetPy._set_type = OOTreeSetPy._bucket_type = OOSetPy
|
||||
|
||||
|
||||
differencePy = _set_operation(_difference, OOSetPy)
|
||||
unionPy = _set_operation(_union, OOSetPy)
|
||||
intersectionPy = _set_operation(_intersection, OOSetPy)
|
||||
|
||||
import_c_extension(globals())
|
||||
|
||||
_fix_pickle(globals(), __name__)
|
||||
|
||||
moduleProvides(IObjectObjectBTreeModule)
|
557
thesisenv/lib/python3.6/site-packages/BTrees/SetOpTemplate.c
Normal file
557
thesisenv/lib/python3.6/site-packages/BTrees/SetOpTemplate.c
Normal file
@ -0,0 +1,557 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2001, 2002 Zope Foundation and Contributors.
|
||||
All Rights Reserved.
|
||||
|
||||
This software is subject to the provisions of the Zope Public License,
|
||||
Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
Set operations
|
||||
****************************************************************************/
|
||||
|
||||
#define SETOPTEMPLATE_C "$Id$\n"
|
||||
|
||||
#ifdef KEY_CHECK
|
||||
static int
|
||||
nextKeyAsSet(SetIteration *i)
|
||||
{
|
||||
if (i->position >= 0) {
|
||||
if (i->position) {
|
||||
DECREF_KEY(i->key);
|
||||
i->position = -1;
|
||||
}
|
||||
else
|
||||
i->position = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* initSetIteration
|
||||
*
|
||||
* Start the set iteration protocol. See the comments at struct SetIteration.
|
||||
*
|
||||
* Arguments
|
||||
* i The address of a SetIteration control struct.
|
||||
* s The address of the set, bucket, BTree, ..., to be iterated.
|
||||
* useValues Boolean; if true, and s has values (is a mapping), copy
|
||||
* them into i->value each time i->next() is called; else
|
||||
* ignore s's values even if s is a mapping.
|
||||
*
|
||||
* Return
|
||||
* 0 on success; -1 and an exception set if error.
|
||||
* i.usesValue is set to 1 (true) if s has values and useValues was
|
||||
* true; else usesValue is set to 0 (false).
|
||||
* i.set gets a new reference to s, or to some other object used to
|
||||
* iterate over s.
|
||||
* i.position is set to 0.
|
||||
* i.next is set to an appropriate iteration function.
|
||||
* i.key and i.value are left alone.
|
||||
*
|
||||
* Internal
|
||||
* i.position < 0 means iteration terminated.
|
||||
* i.position = 0 means iteration hasn't yet begun (next() hasn't
|
||||
* been called yet).
|
||||
* In all other cases, i.key, and possibly i.value, own references.
|
||||
* These must be cleaned up, either by next() routines, or by
|
||||
* finiSetIteration.
|
||||
* next() routines must ensure the above. They should return without
|
||||
* doing anything when i.position < 0.
|
||||
* It's the responsibility of {init, fini}setIteration to clean up
|
||||
* the reference in i.set, and to ensure that no stale references
|
||||
* live in i.key or i.value if iteration terminates abnormally.
|
||||
* A SetIteration struct has been cleaned up iff i.set is NULL.
|
||||
*/
|
||||
static int
|
||||
initSetIteration(SetIteration *i, PyObject *s, int useValues)
|
||||
{
|
||||
i->set = NULL;
|
||||
i->position = -1; /* set to 0 only on normal return */
|
||||
i->usesValue = 0; /* assume it's a set or that values aren't iterated */
|
||||
|
||||
if (PyObject_IsInstance(s, (PyObject *)&BucketType))
|
||||
{
|
||||
i->set = s;
|
||||
Py_INCREF(s);
|
||||
|
||||
if (useValues)
|
||||
{
|
||||
i->usesValue = 1;
|
||||
i->next = nextBucket;
|
||||
}
|
||||
else
|
||||
i->next = nextSet;
|
||||
}
|
||||
else if (PyObject_IsInstance(s, (PyObject *)&SetType))
|
||||
{
|
||||
i->set = s;
|
||||
Py_INCREF(s);
|
||||
i->next = nextSet;
|
||||
}
|
||||
else if (PyObject_IsInstance(s, (PyObject *)&BTreeType))
|
||||
{
|
||||
i->set = BTree_rangeSearch(BTREE(s), NULL, NULL, 'i');
|
||||
UNLESS(i->set) return -1;
|
||||
|
||||
if (useValues)
|
||||
{
|
||||
i->usesValue = 1;
|
||||
i->next = nextBTreeItems;
|
||||
}
|
||||
else
|
||||
i->next = nextTreeSetItems;
|
||||
}
|
||||
else if (PyObject_IsInstance(s, (PyObject *)&TreeSetType))
|
||||
{
|
||||
i->set = BTree_rangeSearch(BTREE(s), NULL, NULL, 'k');
|
||||
UNLESS(i->set) return -1;
|
||||
i->next = nextTreeSetItems;
|
||||
}
|
||||
#ifdef KEY_CHECK
|
||||
else if (KEY_CHECK(s))
|
||||
{
|
||||
int copied = 1;
|
||||
COPY_KEY_FROM_ARG(i->key, s, copied);
|
||||
UNLESS (copied) return -1;
|
||||
|
||||
INCREF_KEY(i->key);
|
||||
i->set = s;
|
||||
Py_INCREF(s);
|
||||
i->next = nextKeyAsSet;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
PyErr_SetString(PyExc_TypeError, "invalid argument");
|
||||
return -1;
|
||||
}
|
||||
|
||||
i->position = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef MERGE_WEIGHT
|
||||
#define MERGE_WEIGHT(O, w) (O)
|
||||
#endif
|
||||
|
||||
static int
|
||||
copyRemaining(Bucket *r, SetIteration *i, int merge,
|
||||
|
||||
/* See comment # 42 */
|
||||
#ifdef MERGE
|
||||
VALUE_TYPE w)
|
||||
#else
|
||||
int w)
|
||||
#endif
|
||||
{
|
||||
while (i->position >= 0)
|
||||
{
|
||||
if(r->len >= r->size && Bucket_grow(r, -1, ! merge) < 0) return -1;
|
||||
COPY_KEY(r->keys[r->len], i->key);
|
||||
INCREF_KEY(r->keys[r->len]);
|
||||
|
||||
if (merge)
|
||||
{
|
||||
COPY_VALUE(r->values[r->len], MERGE_WEIGHT(i->value, w));
|
||||
INCREF_VALUE(r->values[r->len]);
|
||||
}
|
||||
r->len++;
|
||||
if (i->next(i) < 0) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is the workhorse for all set merge operations: the weighted and
|
||||
* unweighted flavors of union and intersection, and set difference. The
|
||||
* algorithm is conceptually simple but the code is complicated due to all
|
||||
* the options.
|
||||
*
|
||||
* s1, s2
|
||||
* The input collections to be merged.
|
||||
*
|
||||
* usevalues1, usevalues2
|
||||
* Booleans. In the output, should values from s1 (or s2) be used? This
|
||||
* only makes sense when an operation intends to support mapping outputs;
|
||||
* these should both be false for operations that want pure set outputs.
|
||||
*
|
||||
* w1, w2
|
||||
* If usevalues1(2) are true, these are the weights to apply to the
|
||||
* input values.
|
||||
*
|
||||
* c1
|
||||
* Boolean. Should keys that appear in c1 but not c2 appear in the output?
|
||||
* c12
|
||||
* Boolean. Should keys that appear in both inputs appear in the output?
|
||||
* c2
|
||||
* Boolean. Should keys that appear in c2 but not c1 appear in the output?
|
||||
*
|
||||
* Returns NULL if error, else a Set or Bucket, depending on whether a set or
|
||||
* mapping was requested.
|
||||
*/
|
||||
static PyObject *
|
||||
set_operation(PyObject *s1, PyObject *s2,
|
||||
int usevalues1, int usevalues2,
|
||||
|
||||
/* Comment # 42
|
||||
|
||||
The following ifdef works around a template/type problem
|
||||
|
||||
Weights are passed as integers. In particular, the weight passed by
|
||||
difference is one. This works fine in the int value and float value
|
||||
cases but makes no sense in the object value case. In the object
|
||||
value case, we don't do merging, so we don't use the weights, so it
|
||||
doesn't matter what they are.
|
||||
*/
|
||||
#ifdef MERGE
|
||||
VALUE_TYPE w1, VALUE_TYPE w2,
|
||||
#else
|
||||
int w1, int w2,
|
||||
#endif
|
||||
int c1, int c12, int c2)
|
||||
|
||||
|
||||
{
|
||||
Bucket *r=0;
|
||||
SetIteration i1 = {0,0,0}, i2 = {0,0,0};
|
||||
int cmp, merge;
|
||||
|
||||
if (initSetIteration(&i1, s1, usevalues1) < 0) goto err;
|
||||
if (initSetIteration(&i2, s2, usevalues2) < 0) goto err;
|
||||
merge = i1.usesValue | i2.usesValue;
|
||||
|
||||
if (merge)
|
||||
{
|
||||
#ifndef MERGE
|
||||
if (c12 && i1.usesValue && i2.usesValue) goto invalid_set_operation;
|
||||
#endif
|
||||
if (! i1.usesValue&& i2.usesValue)
|
||||
{
|
||||
SetIteration t;
|
||||
int i;
|
||||
|
||||
/* See comment # 42 above */
|
||||
#ifdef MERGE
|
||||
VALUE_TYPE v;
|
||||
#else
|
||||
int v;
|
||||
#endif
|
||||
|
||||
t=i1; i1=i2; i2=t;
|
||||
i=c1; c1=c2; c2=i;
|
||||
v=w1; w1=w2; w2=v;
|
||||
}
|
||||
#ifdef MERGE_DEFAULT
|
||||
i1.value=MERGE_DEFAULT;
|
||||
i2.value=MERGE_DEFAULT;
|
||||
#else
|
||||
if (i1.usesValue)
|
||||
{
|
||||
if (! i2.usesValue && c2) goto invalid_set_operation;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c1 || c12) goto invalid_set_operation;
|
||||
}
|
||||
#endif
|
||||
|
||||
UNLESS(r=BUCKET(PyObject_CallObject(OBJECT(&BucketType), NULL)))
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNLESS(r=BUCKET(PyObject_CallObject(OBJECT(&SetType), NULL)))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (i1.next(&i1) < 0) goto err;
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
|
||||
while (i1.position >= 0 && i2.position >= 0)
|
||||
{
|
||||
TEST_KEY_SET_OR(cmp, i1.key, i2.key) goto err;
|
||||
if(cmp < 0)
|
||||
{
|
||||
if(c1)
|
||||
{
|
||||
if(r->len >= r->size && Bucket_grow(r, -1, ! merge) < 0) goto err;
|
||||
COPY_KEY(r->keys[r->len], i1.key);
|
||||
INCREF_KEY(r->keys[r->len]);
|
||||
if (merge)
|
||||
{
|
||||
COPY_VALUE(r->values[r->len], MERGE_WEIGHT(i1.value, w1));
|
||||
INCREF_VALUE(r->values[r->len]);
|
||||
}
|
||||
r->len++;
|
||||
}
|
||||
if (i1.next(&i1) < 0) goto err;
|
||||
}
|
||||
else if(cmp==0)
|
||||
{
|
||||
if(c12)
|
||||
{
|
||||
if(r->len >= r->size && Bucket_grow(r, -1, ! merge) < 0) goto err;
|
||||
COPY_KEY(r->keys[r->len], i1.key);
|
||||
INCREF_KEY(r->keys[r->len]);
|
||||
if (merge)
|
||||
{
|
||||
#ifdef MERGE
|
||||
r->values[r->len] = MERGE(i1.value, w1, i2.value, w2);
|
||||
#else
|
||||
COPY_VALUE(r->values[r->len], i1.value);
|
||||
INCREF_VALUE(r->values[r->len]);
|
||||
#endif
|
||||
}
|
||||
r->len++;
|
||||
}
|
||||
if (i1.next(&i1) < 0) goto err;
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(c2)
|
||||
{
|
||||
if(r->len >= r->size && Bucket_grow(r, -1, ! merge) < 0) goto err;
|
||||
COPY_KEY(r->keys[r->len], i2.key);
|
||||
INCREF_KEY(r->keys[r->len]);
|
||||
if (merge)
|
||||
{
|
||||
COPY_VALUE(r->values[r->len], MERGE_WEIGHT(i2.value, w2));
|
||||
INCREF_VALUE(r->values[r->len]);
|
||||
}
|
||||
r->len++;
|
||||
}
|
||||
if (i2.next(&i2) < 0) goto err;
|
||||
}
|
||||
}
|
||||
if(c1 && copyRemaining(r, &i1, merge, w1) < 0) goto err;
|
||||
if(c2 && copyRemaining(r, &i2, merge, w2) < 0) goto err;
|
||||
|
||||
|
||||
finiSetIteration(&i1);
|
||||
finiSetIteration(&i2);
|
||||
|
||||
return OBJECT(r);
|
||||
|
||||
#ifndef MERGE_DEFAULT
|
||||
invalid_set_operation:
|
||||
PyErr_SetString(PyExc_TypeError, "invalid set operation");
|
||||
#endif
|
||||
|
||||
err:
|
||||
finiSetIteration(&i1);
|
||||
finiSetIteration(&i2);
|
||||
Py_XDECREF(r);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
difference_m(PyObject *ignored, PyObject *args)
|
||||
{
|
||||
PyObject *o1, *o2;
|
||||
|
||||
UNLESS(PyArg_ParseTuple(args, "OO", &o1, &o2)) return NULL;
|
||||
|
||||
|
||||
if (o1 == Py_None || o2 == Py_None)
|
||||
{
|
||||
/* difference(None, X) -> None; difference(X, None) -> X */
|
||||
Py_INCREF(o1);
|
||||
return o1;
|
||||
}
|
||||
|
||||
return set_operation(o1, o2, 1, 0, /* preserve values from o1, ignore o2's */
|
||||
1, 0, /* o1's values multiplied by 1 */
|
||||
1, 0, 0); /* take only keys unique to o1 */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
union_m(PyObject *ignored, PyObject *args)
|
||||
{
|
||||
PyObject *o1, *o2;
|
||||
|
||||
UNLESS(PyArg_ParseTuple(args, "OO", &o1, &o2)) return NULL;
|
||||
|
||||
if (o1 == Py_None)
|
||||
{
|
||||
Py_INCREF(o2);
|
||||
return o2;
|
||||
}
|
||||
else if (o2 == Py_None)
|
||||
{
|
||||
Py_INCREF(o1);
|
||||
return o1;
|
||||
}
|
||||
|
||||
return set_operation(o1, o2, 0, 0, /* ignore values in both */
|
||||
1, 1, /* the weights are irrelevant */
|
||||
1, 1, 1); /* take all keys */
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
intersection_m(PyObject *ignored, PyObject *args)
|
||||
{
|
||||
PyObject *o1, *o2;
|
||||
|
||||
UNLESS(PyArg_ParseTuple(args, "OO", &o1, &o2)) return NULL;
|
||||
|
||||
if (o1 == Py_None)
|
||||
{
|
||||
Py_INCREF(o2);
|
||||
return o2;
|
||||
}
|
||||
else if (o2 == Py_None)
|
||||
{
|
||||
Py_INCREF(o1);
|
||||
return o1;
|
||||
}
|
||||
|
||||
return set_operation(o1, o2, 0, 0, /* ignore values in both */
|
||||
1, 1, /* the weights are irrelevant */
|
||||
0, 1, 0); /* take only keys common to both */
|
||||
}
|
||||
|
||||
#ifdef MERGE
|
||||
|
||||
static PyObject *
|
||||
wunion_m(PyObject *ignored, PyObject *args)
|
||||
{
|
||||
PyObject *o1, *o2;
|
||||
VALUE_TYPE w1 = 1, w2 = 1;
|
||||
|
||||
UNLESS(PyArg_ParseTuple(args, "OO|" VALUE_PARSE VALUE_PARSE,
|
||||
&o1, &o2, &w1, &w2)
|
||||
) return NULL;
|
||||
|
||||
if (o1 == Py_None)
|
||||
return Py_BuildValue(VALUE_PARSE "O", (o2 == Py_None ? 0 : w2), o2);
|
||||
else if (o2 == Py_None)
|
||||
return Py_BuildValue(VALUE_PARSE "O", w1, o1);
|
||||
|
||||
o1 = set_operation(o1, o2, 1, 1, w1, w2, 1, 1, 1);
|
||||
if (o1)
|
||||
ASSIGN(o1, Py_BuildValue(VALUE_PARSE "O", (VALUE_TYPE)1, o1));
|
||||
|
||||
return o1;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
wintersection_m(PyObject *ignored, PyObject *args)
|
||||
{
|
||||
PyObject *o1, *o2;
|
||||
VALUE_TYPE w1 = 1, w2 = 1;
|
||||
|
||||
UNLESS(PyArg_ParseTuple(args, "OO|" VALUE_PARSE VALUE_PARSE,
|
||||
&o1, &o2, &w1, &w2)
|
||||
) return NULL;
|
||||
|
||||
if (o1 == Py_None)
|
||||
return Py_BuildValue(VALUE_PARSE "O", (o2 == Py_None ? 0 : w2), o2);
|
||||
else if (o2 == Py_None)
|
||||
return Py_BuildValue(VALUE_PARSE "O", w1, o1);
|
||||
|
||||
o1 = set_operation(o1, o2, 1, 1, w1, w2, 0, 1, 0);
|
||||
if (o1)
|
||||
ASSIGN(o1, Py_BuildValue(VALUE_PARSE "O",
|
||||
((o1->ob_type == (PyTypeObject*)(&SetType)) ? w2+w1 : 1),
|
||||
o1));
|
||||
|
||||
return o1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MULTI_INT_UNION
|
||||
#include "sorters.c"
|
||||
|
||||
/* Input is a sequence of integer sets (or convertible to sets by the
|
||||
set iteration protocol). Output is the union of the sets. The point
|
||||
is to run much faster than doing pairs of unions.
|
||||
*/
|
||||
static PyObject *
|
||||
multiunion_m(PyObject *ignored, PyObject *args)
|
||||
{
|
||||
PyObject *seq; /* input sequence */
|
||||
int n; /* length of input sequence */
|
||||
PyObject *set = NULL; /* an element of the input sequence */
|
||||
Bucket *result; /* result set */
|
||||
SetIteration setiter = {0};
|
||||
int i;
|
||||
|
||||
UNLESS(PyArg_ParseTuple(args, "O", &seq))
|
||||
return NULL;
|
||||
|
||||
n = PyObject_Length(seq);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
|
||||
/* Construct an empty result set. */
|
||||
result = BUCKET(PyObject_CallObject(OBJECT(&SetType), NULL));
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
/* For each set in the input sequence, append its elements to the result
|
||||
set. At this point, we ignore the possibility of duplicates. */
|
||||
for (i = 0; i < n; ++i) {
|
||||
set = PySequence_GetItem(seq, i);
|
||||
if (set == NULL)
|
||||
goto Error;
|
||||
|
||||
/* If set is a bucket, do a straight resize + memcpy. */
|
||||
if (set->ob_type == (PyTypeObject*)&SetType ||
|
||||
set->ob_type == (PyTypeObject*)&BucketType)
|
||||
{
|
||||
Bucket *b = BUCKET(set);
|
||||
int status = 0;
|
||||
|
||||
UNLESS (PER_USE(b)) goto Error;
|
||||
if (b->len)
|
||||
status = bucket_append(result, b, 0, b->len, 0, i < n-1);
|
||||
PER_UNUSE(b);
|
||||
if (status < 0) goto Error;
|
||||
}
|
||||
else {
|
||||
/* No cheap way: iterate over set's elements one at a time. */
|
||||
if (initSetIteration(&setiter, set, 0) < 0) goto Error;
|
||||
if (setiter.next(&setiter) < 0) goto Error;
|
||||
while (setiter.position >= 0) {
|
||||
if (result->len >= result->size && Bucket_grow(result, -1, 1) < 0)
|
||||
goto Error;
|
||||
COPY_KEY(result->keys[result->len], setiter.key);
|
||||
++result->len;
|
||||
/* We know the key is an int, so no need to incref it. */
|
||||
if (setiter.next(&setiter) < 0) goto Error;
|
||||
}
|
||||
finiSetIteration(&setiter);
|
||||
}
|
||||
Py_DECREF(set);
|
||||
set = NULL;
|
||||
}
|
||||
|
||||
/* Combine, sort, remove duplicates, and reset the result's len.
|
||||
If the set shrinks (which happens if and only if there are
|
||||
duplicates), no point to realloc'ing the set smaller, as we
|
||||
expect the result set to be short-lived.
|
||||
*/
|
||||
if (result->len > 0) {
|
||||
size_t newlen; /* number of elements in final result set */
|
||||
newlen = sort_int_nodups(result->keys, (size_t)result->len);
|
||||
result->len = (int)newlen;
|
||||
}
|
||||
return (PyObject *)result;
|
||||
|
||||
Error:
|
||||
Py_DECREF(result);
|
||||
Py_XDECREF(set);
|
||||
finiSetIteration(&setiter);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
381
thesisenv/lib/python3.6/site-packages/BTrees/SetTemplate.c
Normal file
381
thesisenv/lib/python3.6/site-packages/BTrees/SetTemplate.c
Normal file
@ -0,0 +1,381 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2001, 2002 Zope Foundation and Contributors.
|
||||
All Rights Reserved.
|
||||
|
||||
This software is subject to the provisions of the Zope Public License,
|
||||
Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE
|
||||
|
||||
****************************************************************************/
|
||||
#include "_compat.h"
|
||||
|
||||
#define SETTEMPLATE_C "$Id$\n"
|
||||
|
||||
static PyObject *
|
||||
Set_insert(Bucket *self, PyObject *args)
|
||||
{
|
||||
PyObject *key;
|
||||
int i;
|
||||
|
||||
UNLESS (PyArg_ParseTuple(args, "O", &key))
|
||||
return NULL;
|
||||
if ( (i=_bucket_set(self, key, Py_None, 1, 1, 0)) < 0)
|
||||
return NULL;
|
||||
return INT_FROM_LONG(i);
|
||||
}
|
||||
|
||||
/* _Set_update and _TreeSet_update are identical except for the
|
||||
function they call to add the element to the set.
|
||||
*/
|
||||
|
||||
static int
|
||||
_Set_update(Bucket *self, PyObject *seq)
|
||||
{
|
||||
int n=0, ind=0;
|
||||
PyObject *iter, *v;
|
||||
|
||||
iter = PyObject_GetIter(seq);
|
||||
if (iter == NULL)
|
||||
return -1;
|
||||
|
||||
while (1) {
|
||||
v = PyIter_Next(iter);
|
||||
if (v == NULL) {
|
||||
if (PyErr_Occurred())
|
||||
goto err;
|
||||
else
|
||||
break;
|
||||
}
|
||||
ind = _bucket_set(self, v, Py_None, 1, 1, 0);
|
||||
Py_DECREF(v);
|
||||
if (ind < 0)
|
||||
goto err;
|
||||
else
|
||||
n += ind;
|
||||
}
|
||||
|
||||
err:
|
||||
Py_DECREF(iter);
|
||||
if (ind < 0)
|
||||
return -1;
|
||||
return n;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
Set_update(Bucket *self, PyObject *args)
|
||||
{
|
||||
PyObject *seq = NULL;
|
||||
int n = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|O:update", &seq))
|
||||
return NULL;
|
||||
|
||||
if (seq) {
|
||||
n = _Set_update(self, seq);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return INT_FROM_LONG(n);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
Set_remove(Bucket *self, PyObject *args)
|
||||
{
|
||||
PyObject *key;
|
||||
|
||||
UNLESS (PyArg_ParseTuple(args, "O", &key))
|
||||
return NULL;
|
||||
if (_bucket_set(self, key, NULL, 0, 1, 0) < 0)
|
||||
return NULL;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static int
|
||||
_set_setstate(Bucket *self, PyObject *args)
|
||||
{
|
||||
PyObject *k, *items;
|
||||
Bucket *next=0;
|
||||
int i, l, copied=1;
|
||||
KEY_TYPE *keys;
|
||||
|
||||
UNLESS (PyArg_ParseTuple(args, "O|O", &items, &next))
|
||||
return -1;
|
||||
|
||||
if (!PyTuple_Check(items)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"tuple required for first state element");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((l=PyTuple_Size(items)) < 0)
|
||||
return -1;
|
||||
|
||||
for (i=self->len; --i >= 0; )
|
||||
{
|
||||
DECREF_KEY(self->keys[i]);
|
||||
}
|
||||
self->len=0;
|
||||
|
||||
if (self->next)
|
||||
{
|
||||
Py_DECREF(self->next);
|
||||
self->next=0;
|
||||
}
|
||||
|
||||
if (l > self->size)
|
||||
{
|
||||
UNLESS (keys=BTree_Realloc(self->keys, sizeof(KEY_TYPE)*l))
|
||||
return -1;
|
||||
self->keys=keys;
|
||||
self->size=l;
|
||||
}
|
||||
|
||||
for (i=0; i<l; i++)
|
||||
{
|
||||
k=PyTuple_GET_ITEM(items, i);
|
||||
COPY_KEY_FROM_ARG(self->keys[i], k, copied);
|
||||
UNLESS (copied)
|
||||
return -1;
|
||||
INCREF_KEY(self->keys[i]);
|
||||
}
|
||||
|
||||
self->len=l;
|
||||
|
||||
if (next)
|
||||
{
|
||||
self->next=next;
|
||||
Py_INCREF(next);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
set_setstate(Bucket *self, PyObject *args)
|
||||
{
|
||||
int r;
|
||||
|
||||
UNLESS (PyArg_ParseTuple(args, "O", &args))
|
||||
return NULL;
|
||||
|
||||
PER_PREVENT_DEACTIVATION(self);
|
||||
r=_set_setstate(self, args);
|
||||
PER_UNUSE(self);
|
||||
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static struct PyMethodDef Set_methods[] = {
|
||||
{"__getstate__", (PyCFunction) bucket_getstate, METH_VARARGS,
|
||||
"__getstate__() -- Return the picklable state of the object"},
|
||||
|
||||
{"__setstate__", (PyCFunction) set_setstate, METH_VARARGS,
|
||||
"__setstate__() -- Set the state of the object"},
|
||||
|
||||
{"keys", (PyCFunction) bucket_keys, METH_VARARGS | METH_KEYWORDS,
|
||||
"keys() -- Return the keys"},
|
||||
|
||||
{"has_key", (PyCFunction) bucket_has_key, METH_O,
|
||||
"has_key(key) -- Test whether the bucket contains the given key"},
|
||||
|
||||
{"clear", (PyCFunction) bucket_clear, METH_VARARGS,
|
||||
"clear() -- Remove all of the items from the bucket"},
|
||||
|
||||
{"maxKey", (PyCFunction) Bucket_maxKey, METH_VARARGS,
|
||||
"maxKey([key]) -- Find the maximum key\n\n"
|
||||
"If an argument is given, find the maximum <= the argument"},
|
||||
|
||||
{"minKey", (PyCFunction) Bucket_minKey, METH_VARARGS,
|
||||
"minKey([key]) -- Find the minimum key\n\n"
|
||||
"If an argument is given, find the minimum >= the argument"},
|
||||
|
||||
#ifdef PERSISTENT
|
||||
{"_p_resolveConflict",
|
||||
(PyCFunction) bucket__p_resolveConflict, METH_VARARGS,
|
||||
"_p_resolveConflict() -- Reinitialize from a newly created copy"},
|
||||
|
||||
{"_p_deactivate",
|
||||
(PyCFunction) bucket__p_deactivate, METH_VARARGS | METH_KEYWORDS,
|
||||
"_p_deactivate() -- Reinitialize from a newly created copy"},
|
||||
#endif
|
||||
|
||||
{"add", (PyCFunction)Set_insert, METH_VARARGS,
|
||||
"add(id) -- Add a key to the set"},
|
||||
|
||||
{"insert", (PyCFunction)Set_insert, METH_VARARGS,
|
||||
"insert(id) -- Add a key to the set"},
|
||||
|
||||
{"update", (PyCFunction)Set_update, METH_VARARGS,
|
||||
"update(seq) -- Add the items from the given sequence to the set"},
|
||||
|
||||
{"remove", (PyCFunction)Set_remove, METH_VARARGS,
|
||||
"remove(id) -- Remove an id from the set"},
|
||||
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
static int
|
||||
Set_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *v = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|O:" MOD_NAME_PREFIX "Set", &v))
|
||||
return -1;
|
||||
|
||||
if (v)
|
||||
return _Set_update((Bucket *)self, v);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PyObject *
|
||||
set_repr(Bucket *self)
|
||||
{
|
||||
static PyObject *format;
|
||||
PyObject *r, *t;
|
||||
|
||||
if (!format)
|
||||
format = TEXT_FROM_STRING(MOD_NAME_PREFIX "Set(%s)");
|
||||
UNLESS (t = PyTuple_New(1))
|
||||
return NULL;
|
||||
UNLESS (r = bucket_keys(self, NULL, NULL))
|
||||
goto err;
|
||||
PyTuple_SET_ITEM(t, 0, r);
|
||||
r = t;
|
||||
ASSIGN(r, TEXT_FORMAT(format, r));
|
||||
return r;
|
||||
err:
|
||||
Py_DECREF(t);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Py_ssize_t
|
||||
set_length(Bucket *self)
|
||||
{
|
||||
int r;
|
||||
|
||||
PER_USE_OR_RETURN(self, -1);
|
||||
r = self->len;
|
||||
PER_UNUSE(self);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
set_item(Bucket *self, Py_ssize_t index)
|
||||
{
|
||||
PyObject *r=0;
|
||||
|
||||
PER_USE_OR_RETURN(self, NULL);
|
||||
if (index >= 0 && index < self->len)
|
||||
{
|
||||
COPY_KEY_TO_OBJECT(r, self->keys[index]);
|
||||
}
|
||||
else
|
||||
IndexError(index);
|
||||
|
||||
PER_UNUSE(self);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static PySequenceMethods set_as_sequence = {
|
||||
(lenfunc)set_length, /* sq_length */
|
||||
(binaryfunc)0, /* sq_concat */
|
||||
(ssizeargfunc)0, /* sq_repeat */
|
||||
(ssizeargfunc)set_item, /* sq_item */
|
||||
(ssizessizeargfunc)0, /* sq_slice */
|
||||
(ssizeobjargproc)0, /* sq_ass_item */
|
||||
(ssizessizeobjargproc)0, /* sq_ass_slice */
|
||||
(objobjproc)bucket_contains, /* sq_contains */
|
||||
0, /* sq_inplace_concat */
|
||||
0, /* sq_inplace_repeat */
|
||||
};
|
||||
|
||||
static PyTypeObject SetType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0) /* PyPersist_Type */
|
||||
MODULE_NAME MOD_NAME_PREFIX "Set", /* tp_name */
|
||||
sizeof(Bucket), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)bucket_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
(reprfunc)set_repr, /* tp_repr */
|
||||
0, /* tp_as_number */
|
||||
&set_as_sequence, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT |
|
||||
Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
0, /* tp_doc */
|
||||
(traverseproc)bucket_traverse, /* tp_traverse */
|
||||
(inquiry)bucket_tp_clear, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)Bucket_getiter, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
Set_methods, /* tp_methods */
|
||||
Bucket_members, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
Set_init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
0, /*PyType_GenericNew,*/ /* tp_new */
|
||||
};
|
||||
|
||||
static int
|
||||
nextSet(SetIteration *i)
|
||||
{
|
||||
|
||||
if (i->position >= 0)
|
||||
{
|
||||
UNLESS(PER_USE(BUCKET(i->set)))
|
||||
return -1;
|
||||
|
||||
if (i->position)
|
||||
{
|
||||
DECREF_KEY(i->key);
|
||||
}
|
||||
|
||||
if (i->position < BUCKET(i->set)->len)
|
||||
{
|
||||
COPY_KEY(i->key, BUCKET(i->set)->keys[i->position]);
|
||||
INCREF_KEY(i->key);
|
||||
i->position ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
i->position = -1;
|
||||
PER_ACCESSED(BUCKET(i->set));
|
||||
}
|
||||
|
||||
PER_ALLOW_DEACTIVATION(BUCKET(i->set));
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
254
thesisenv/lib/python3.6/site-packages/BTrees/TreeSetTemplate.c
Normal file
254
thesisenv/lib/python3.6/site-packages/BTrees/TreeSetTemplate.c
Normal file
@ -0,0 +1,254 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2001, 2002 Zope Foundation and Contributors.
|
||||
All Rights Reserved.
|
||||
|
||||
This software is subject to the provisions of the Zope Public License,
|
||||
Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE
|
||||
|
||||
****************************************************************************/
|
||||
#include "_compat.h"
|
||||
|
||||
#define TREESETTEMPLATE_C "$Id$\n"
|
||||
|
||||
static PyObject *
|
||||
TreeSet_insert(BTree *self, PyObject *args)
|
||||
{
|
||||
PyObject *key;
|
||||
int i;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "O:insert", &key))
|
||||
return NULL;
|
||||
i = _BTree_set(self, key, Py_None, 1, 1);
|
||||
if (i < 0)
|
||||
return NULL;
|
||||
return INT_FROM_LONG(i);
|
||||
}
|
||||
|
||||
/* _Set_update and _TreeSet_update are identical except for the
|
||||
function they call to add the element to the set.
|
||||
*/
|
||||
|
||||
static int
|
||||
_TreeSet_update(BTree *self, PyObject *seq)
|
||||
{
|
||||
int n=0, ind=0;
|
||||
PyObject *iter, *v;
|
||||
|
||||
iter = PyObject_GetIter(seq);
|
||||
if (iter == NULL)
|
||||
return -1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
v = PyIter_Next(iter);
|
||||
if (v == NULL)
|
||||
{
|
||||
if (PyErr_Occurred())
|
||||
goto err;
|
||||
else
|
||||
break;
|
||||
}
|
||||
ind = _BTree_set(self, v, Py_None, 1, 1);
|
||||
Py_DECREF(v);
|
||||
if (ind < 0)
|
||||
goto err;
|
||||
else
|
||||
n += ind;
|
||||
}
|
||||
|
||||
err:
|
||||
Py_DECREF(iter);
|
||||
if (ind < 0)
|
||||
return -1;
|
||||
return n;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
TreeSet_update(BTree *self, PyObject *args)
|
||||
{
|
||||
PyObject *seq = NULL;
|
||||
int n = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|O:update", &seq))
|
||||
return NULL;
|
||||
|
||||
if (seq)
|
||||
{
|
||||
n = _TreeSet_update(self, seq);
|
||||
if (n < 0)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return INT_FROM_LONG(n);
|
||||
}
|
||||
|
||||
|
||||
static PyObject *
|
||||
TreeSet_remove(BTree *self, PyObject *args)
|
||||
{
|
||||
PyObject *key;
|
||||
|
||||
UNLESS (PyArg_ParseTuple(args, "O", &key))
|
||||
return NULL;
|
||||
if (_BTree_set(self, key, NULL, 0, 1) < 0)
|
||||
return NULL;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
TreeSet_setstate(BTree *self, PyObject *args)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!PyArg_ParseTuple(args,"O",&args))
|
||||
return NULL;
|
||||
|
||||
PER_PREVENT_DEACTIVATION(self);
|
||||
r=_BTree_setstate(self, args, 1);
|
||||
PER_UNUSE(self);
|
||||
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static struct PyMethodDef TreeSet_methods[] =
|
||||
{
|
||||
{"__getstate__", (PyCFunction) BTree_getstate, METH_NOARGS,
|
||||
"__getstate__() -> state\n\n"
|
||||
"Return the picklable state of the TreeSet."},
|
||||
|
||||
{"__setstate__", (PyCFunction) TreeSet_setstate, METH_VARARGS,
|
||||
"__setstate__(state)\n\n"
|
||||
"Set the state of the TreeSet."},
|
||||
|
||||
{"has_key", (PyCFunction) BTree_has_key, METH_O,
|
||||
"has_key(key)\n\n"
|
||||
"Return true if the TreeSet contains the given key."},
|
||||
|
||||
{"keys", (PyCFunction) BTree_keys, METH_VARARGS | METH_KEYWORDS,
|
||||
"keys([min, max]) -> list of keys\n\n"
|
||||
"Returns the keys of the TreeSet. If min and max are supplied, only\n"
|
||||
"keys greater than min and less than max are returned."},
|
||||
|
||||
{"maxKey", (PyCFunction) BTree_maxKey, METH_VARARGS,
|
||||
"maxKey([max]) -> key\n\n"
|
||||
"Return the largest key in the BTree. If max is specified, return\n"
|
||||
"the largest key <= max."},
|
||||
|
||||
{"minKey", (PyCFunction) BTree_minKey, METH_VARARGS,
|
||||
"minKey([mi]) -> key\n\n"
|
||||
"Return the smallest key in the BTree. If min is specified, return\n"
|
||||
"the smallest key >= min."},
|
||||
|
||||
{"clear", (PyCFunction) BTree_clear, METH_NOARGS,
|
||||
"clear()\n\nRemove all of the items from the BTree."},
|
||||
|
||||
{"add", (PyCFunction)TreeSet_insert, METH_VARARGS,
|
||||
"add(id) -- Add an item to the set"},
|
||||
|
||||
{"insert", (PyCFunction)TreeSet_insert, METH_VARARGS,
|
||||
"insert(id) -- Add an item to the set"},
|
||||
|
||||
{"update", (PyCFunction)TreeSet_update, METH_VARARGS,
|
||||
"update(collection)\n\n Add the items from the given collection."},
|
||||
|
||||
{"remove", (PyCFunction)TreeSet_remove, METH_VARARGS,
|
||||
"remove(id) -- Remove a key from the set"},
|
||||
|
||||
{"_check", (PyCFunction) BTree_check, METH_NOARGS,
|
||||
"Perform sanity check on TreeSet, and raise exception if flawed."},
|
||||
|
||||
#ifdef PERSISTENT
|
||||
{"_p_resolveConflict",
|
||||
(PyCFunction) BTree__p_resolveConflict, METH_VARARGS,
|
||||
"_p_resolveConflict() -- Reinitialize from a newly created copy"},
|
||||
|
||||
{"_p_deactivate",
|
||||
(PyCFunction) BTree__p_deactivate, METH_VARARGS | METH_KEYWORDS,
|
||||
"_p_deactivate()\n\nReinitialize from a newly created copy."},
|
||||
#endif
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
static PyMappingMethods TreeSet_as_mapping = {
|
||||
(lenfunc)BTree_length, /*mp_length*/
|
||||
};
|
||||
|
||||
static PySequenceMethods TreeSet_as_sequence = {
|
||||
(lenfunc)0, /* sq_length */
|
||||
(binaryfunc)0, /* sq_concat */
|
||||
(ssizeargfunc)0, /* sq_repeat */
|
||||
(ssizeargfunc)0, /* sq_item */
|
||||
(ssizessizeargfunc)0, /* sq_slice */
|
||||
(ssizeobjargproc)0, /* sq_ass_item */
|
||||
(ssizessizeobjargproc)0, /* sq_ass_slice */
|
||||
(objobjproc)BTree_contains, /* sq_contains */
|
||||
0, /* sq_inplace_concat */
|
||||
0, /* sq_inplace_repeat */
|
||||
};
|
||||
|
||||
static int
|
||||
TreeSet_init(PyObject *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *v = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|O:" MOD_NAME_PREFIX "TreeSet", &v))
|
||||
return -1;
|
||||
|
||||
if (v)
|
||||
return _TreeSet_update((BTree *)self, v);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyTypeObject TreeSetType =
|
||||
{
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
MODULE_NAME MOD_NAME_PREFIX "TreeSet", /* tp_name */
|
||||
sizeof(BTree), /* tp_basicsize */
|
||||
0, /* tp_itemsize */
|
||||
(destructor)BTree_dealloc, /* tp_dealloc */
|
||||
0, /* tp_print */
|
||||
0, /* tp_getattr */
|
||||
0, /* tp_setattr */
|
||||
0, /* tp_compare */
|
||||
0, /* tp_repr */
|
||||
&BTree_as_number_for_nonzero, /* tp_as_number */
|
||||
&TreeSet_as_sequence, /* tp_as_sequence */
|
||||
&TreeSet_as_mapping, /* tp_as_mapping */
|
||||
0, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
0, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /* tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
Py_TPFLAGS_DEFAULT |
|
||||
Py_TPFLAGS_HAVE_GC |
|
||||
Py_TPFLAGS_BASETYPE, /* tp_flags */
|
||||
0, /* tp_doc */
|
||||
(traverseproc)BTree_traverse, /* tp_traverse */
|
||||
(inquiry)BTree_tp_clear, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
(getiterfunc)BTree_getiter, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
TreeSet_methods, /* tp_methods */
|
||||
BTree_members, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
0, /* tp_dict */
|
||||
0, /* tp_descr_get */
|
||||
0, /* tp_descr_set */
|
||||
0, /* tp_dictoffset */
|
||||
TreeSet_init, /* tp_init */
|
||||
0, /* tp_alloc */
|
||||
0, /*PyType_GenericNew,*/ /* tp_new */
|
||||
};
|
41
thesisenv/lib/python3.6/site-packages/BTrees/_IFBTree.c
Normal file
41
thesisenv/lib/python3.6/site-packages/BTrees/_IFBTree.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*############################################################################
|
||||
#
|
||||
# Copyright (c) 2004 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
############################################################################*/
|
||||
|
||||
#define MASTER_ID "$Id$\n"
|
||||
|
||||
/* IFBTree - int key, float value BTree
|
||||
|
||||
Implements a collection using int type keys
|
||||
and float type values
|
||||
*/
|
||||
|
||||
/* Setup template macros */
|
||||
|
||||
#define PERSISTENT
|
||||
|
||||
#define MOD_NAME_PREFIX "IF"
|
||||
|
||||
#define DEFAULT_MAX_BUCKET_SIZE 120
|
||||
#define DEFAULT_MAX_BTREE_SIZE 500
|
||||
|
||||
#include "_compat.h"
|
||||
#include "intkeymacros.h"
|
||||
#include "floatvaluemacros.h"
|
||||
|
||||
#ifdef PY3K
|
||||
#define INITMODULE PyInit__IFBTree
|
||||
#else
|
||||
#define INITMODULE init_IFBTree
|
||||
#endif
|
||||
#include "BTreeModuleTemplate.c"
|
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_IFBTree.cpython-36m-darwin.so
Executable file
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_IFBTree.cpython-36m-darwin.so
Executable file
Binary file not shown.
41
thesisenv/lib/python3.6/site-packages/BTrees/_IIBTree.c
Normal file
41
thesisenv/lib/python3.6/site-packages/BTrees/_IIBTree.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*############################################################################
|
||||
#
|
||||
# Copyright (c) 2004 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
############################################################################*/
|
||||
|
||||
#define MASTER_ID "$Id$\n"
|
||||
|
||||
/* IIBTree - int key, int value BTree
|
||||
|
||||
Implements a collection using int type keys
|
||||
and int type values
|
||||
*/
|
||||
|
||||
/* Setup template macros */
|
||||
|
||||
#define PERSISTENT
|
||||
|
||||
#define MOD_NAME_PREFIX "II"
|
||||
|
||||
#define DEFAULT_MAX_BUCKET_SIZE 120
|
||||
#define DEFAULT_MAX_BTREE_SIZE 500
|
||||
|
||||
#include "_compat.h"
|
||||
#include "intkeymacros.h"
|
||||
#include "intvaluemacros.h"
|
||||
|
||||
#ifdef PY3K
|
||||
#define INITMODULE PyInit__IIBTree
|
||||
#else
|
||||
#define INITMODULE init_IIBTree
|
||||
#endif
|
||||
#include "BTreeModuleTemplate.c"
|
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_IIBTree.cpython-36m-darwin.so
Executable file
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_IIBTree.cpython-36m-darwin.so
Executable file
Binary file not shown.
39
thesisenv/lib/python3.6/site-packages/BTrees/_IOBTree.c
Normal file
39
thesisenv/lib/python3.6/site-packages/BTrees/_IOBTree.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*############################################################################
|
||||
#
|
||||
# Copyright (c) 2004 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
############################################################################*/
|
||||
|
||||
#define MASTER_ID "$Id$\n"
|
||||
|
||||
/* IOBTree - int key, object value BTree
|
||||
|
||||
Implements a collection using int type keys
|
||||
and object type values
|
||||
*/
|
||||
|
||||
#define PERSISTENT
|
||||
|
||||
#define MOD_NAME_PREFIX "IO"
|
||||
|
||||
#define DEFAULT_MAX_BUCKET_SIZE 60
|
||||
#define DEFAULT_MAX_BTREE_SIZE 500
|
||||
|
||||
#include "_compat.h"
|
||||
#include "intkeymacros.h"
|
||||
#include "objectvaluemacros.h"
|
||||
|
||||
#ifdef PY3K
|
||||
#define INITMODULE PyInit__IOBTree
|
||||
#else
|
||||
#define INITMODULE init_IOBTree
|
||||
#endif
|
||||
#include "BTreeModuleTemplate.c"
|
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_IOBTree.cpython-36m-darwin.so
Executable file
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_IOBTree.cpython-36m-darwin.so
Executable file
Binary file not shown.
43
thesisenv/lib/python3.6/site-packages/BTrees/_LFBTree.c
Normal file
43
thesisenv/lib/python3.6/site-packages/BTrees/_LFBTree.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*############################################################################
|
||||
#
|
||||
# Copyright (c) 2004 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
############################################################################*/
|
||||
|
||||
#define MASTER_ID "$Id: _IFBTree.c 67074 2006-04-17 19:13:39Z fdrake $\n"
|
||||
|
||||
/* IFBTree - int key, float value BTree
|
||||
|
||||
Implements a collection using int type keys
|
||||
and float type values
|
||||
*/
|
||||
|
||||
/* Setup template macros */
|
||||
|
||||
#define PERSISTENT
|
||||
|
||||
#define MOD_NAME_PREFIX "LF"
|
||||
|
||||
#define DEFAULT_MAX_BUCKET_SIZE 120
|
||||
#define DEFAULT_MAX_BTREE_SIZE 500
|
||||
|
||||
#define ZODB_64BIT_INTS
|
||||
|
||||
#include "_compat.h"
|
||||
#include "intkeymacros.h"
|
||||
#include "floatvaluemacros.h"
|
||||
|
||||
#ifdef PY3K
|
||||
#define INITMODULE PyInit__LFBTree
|
||||
#else
|
||||
#define INITMODULE init_LFBTree
|
||||
#endif
|
||||
#include "BTreeModuleTemplate.c"
|
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_LFBTree.cpython-36m-darwin.so
Executable file
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_LFBTree.cpython-36m-darwin.so
Executable file
Binary file not shown.
43
thesisenv/lib/python3.6/site-packages/BTrees/_LLBTree.c
Normal file
43
thesisenv/lib/python3.6/site-packages/BTrees/_LLBTree.c
Normal file
@ -0,0 +1,43 @@
|
||||
/*############################################################################
|
||||
#
|
||||
# Copyright (c) 2004 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
############################################################################*/
|
||||
|
||||
#define MASTER_ID "$Id: _IIBTree.c 25186 2004-06-02 15:07:33Z jim $\n"
|
||||
|
||||
/* IIBTree - int key, int value BTree
|
||||
|
||||
Implements a collection using int type keys
|
||||
and int type values
|
||||
*/
|
||||
|
||||
/* Setup template macros */
|
||||
|
||||
#define PERSISTENT
|
||||
|
||||
#define MOD_NAME_PREFIX "LL"
|
||||
|
||||
#define DEFAULT_MAX_BUCKET_SIZE 120
|
||||
#define DEFAULT_MAX_BTREE_SIZE 500
|
||||
|
||||
#define ZODB_64BIT_INTS
|
||||
|
||||
#include "_compat.h"
|
||||
#include "intkeymacros.h"
|
||||
#include "intvaluemacros.h"
|
||||
|
||||
#ifdef PY3K
|
||||
#define INITMODULE PyInit__LLBTree
|
||||
#else
|
||||
#define INITMODULE init_LLBTree
|
||||
#endif
|
||||
#include "BTreeModuleTemplate.c"
|
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_LLBTree.cpython-36m-darwin.so
Executable file
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_LLBTree.cpython-36m-darwin.so
Executable file
Binary file not shown.
41
thesisenv/lib/python3.6/site-packages/BTrees/_LOBTree.c
Normal file
41
thesisenv/lib/python3.6/site-packages/BTrees/_LOBTree.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*############################################################################
|
||||
#
|
||||
# Copyright (c) 2004 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
############################################################################*/
|
||||
|
||||
#define MASTER_ID "$Id: _IOBTree.c 25186 2004-06-02 15:07:33Z jim $\n"
|
||||
|
||||
/* IOBTree - int key, object value BTree
|
||||
|
||||
Implements a collection using int type keys
|
||||
and object type values
|
||||
*/
|
||||
|
||||
#define PERSISTENT
|
||||
|
||||
#define MOD_NAME_PREFIX "LO"
|
||||
|
||||
#define DEFAULT_MAX_BUCKET_SIZE 60
|
||||
#define DEFAULT_MAX_BTREE_SIZE 500
|
||||
|
||||
#define ZODB_64BIT_INTS
|
||||
|
||||
#include "_compat.h"
|
||||
#include "intkeymacros.h"
|
||||
#include "objectvaluemacros.h"
|
||||
|
||||
#ifdef PY3K
|
||||
#define INITMODULE PyInit__LOBTree
|
||||
#else
|
||||
#define INITMODULE init_LOBTree
|
||||
#endif
|
||||
#include "BTreeModuleTemplate.c"
|
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_LOBTree.cpython-36m-darwin.so
Executable file
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_LOBTree.cpython-36m-darwin.so
Executable file
Binary file not shown.
39
thesisenv/lib/python3.6/site-packages/BTrees/_OIBTree.c
Normal file
39
thesisenv/lib/python3.6/site-packages/BTrees/_OIBTree.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*############################################################################
|
||||
#
|
||||
# Copyright (c) 2004 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
############################################################################*/
|
||||
|
||||
#define MASTER_ID "$Id$\n"
|
||||
|
||||
/* OIBTree - object key, int value BTree
|
||||
|
||||
Implements a collection using object type keys
|
||||
and int type values
|
||||
*/
|
||||
|
||||
#define PERSISTENT
|
||||
|
||||
#define MOD_NAME_PREFIX "OI"
|
||||
|
||||
#define DEFAULT_MAX_BUCKET_SIZE 60
|
||||
#define DEFAULT_MAX_BTREE_SIZE 250
|
||||
|
||||
#include "_compat.h"
|
||||
#include "objectkeymacros.h"
|
||||
#include "intvaluemacros.h"
|
||||
|
||||
#ifdef PY3K
|
||||
#define INITMODULE PyInit__OIBTree
|
||||
#else
|
||||
#define INITMODULE init_OIBTree
|
||||
#endif
|
||||
#include "BTreeModuleTemplate.c"
|
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_OIBTree.cpython-36m-darwin.so
Executable file
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_OIBTree.cpython-36m-darwin.so
Executable file
Binary file not shown.
41
thesisenv/lib/python3.6/site-packages/BTrees/_OLBTree.c
Normal file
41
thesisenv/lib/python3.6/site-packages/BTrees/_OLBTree.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*############################################################################
|
||||
#
|
||||
# Copyright (c) 2004 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
############################################################################*/
|
||||
|
||||
#define MASTER_ID "$Id: _OIBTree.c 25186 2004-06-02 15:07:33Z jim $\n"
|
||||
|
||||
/* OIBTree - object key, int value BTree
|
||||
|
||||
Implements a collection using object type keys
|
||||
and int type values
|
||||
*/
|
||||
|
||||
#define PERSISTENT
|
||||
|
||||
#define MOD_NAME_PREFIX "OL"
|
||||
|
||||
#define DEFAULT_MAX_BUCKET_SIZE 60
|
||||
#define DEFAULT_MAX_BTREE_SIZE 250
|
||||
|
||||
#define ZODB_64BIT_INTS
|
||||
|
||||
#include "_compat.h"
|
||||
#include "objectkeymacros.h"
|
||||
#include "intvaluemacros.h"
|
||||
|
||||
#ifdef PY3K
|
||||
#define INITMODULE PyInit__OLBTree
|
||||
#else
|
||||
#define INITMODULE init_OLBTree
|
||||
#endif
|
||||
#include "BTreeModuleTemplate.c"
|
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_OLBTree.cpython-36m-darwin.so
Executable file
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_OLBTree.cpython-36m-darwin.so
Executable file
Binary file not shown.
39
thesisenv/lib/python3.6/site-packages/BTrees/_OOBTree.c
Normal file
39
thesisenv/lib/python3.6/site-packages/BTrees/_OOBTree.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*############################################################################
|
||||
#
|
||||
# Copyright (c) 2004 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
############################################################################*/
|
||||
|
||||
#define MASTER_ID "$Id$\n"
|
||||
|
||||
/* OOBTree - object key, object value BTree
|
||||
|
||||
Implements a collection using object type keys
|
||||
and object type values
|
||||
*/
|
||||
|
||||
#define PERSISTENT
|
||||
|
||||
#define MOD_NAME_PREFIX "OO"
|
||||
|
||||
#define DEFAULT_MAX_BUCKET_SIZE 30
|
||||
#define DEFAULT_MAX_BTREE_SIZE 250
|
||||
|
||||
#include "_compat.h"
|
||||
#include "objectkeymacros.h"
|
||||
#include "objectvaluemacros.h"
|
||||
|
||||
#ifdef PY3K
|
||||
#define INITMODULE PyInit__OOBTree
|
||||
#else
|
||||
#define INITMODULE init_OOBTree
|
||||
#endif
|
||||
#include "BTreeModuleTemplate.c"
|
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_OOBTree.cpython-36m-darwin.so
Executable file
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_OOBTree.cpython-36m-darwin.so
Executable file
Binary file not shown.
69
thesisenv/lib/python3.6/site-packages/BTrees/__init__.py
Normal file
69
thesisenv/lib/python3.6/site-packages/BTrees/__init__.py
Normal file
@ -0,0 +1,69 @@
|
||||
#############################################################################
|
||||
#
|
||||
# Copyright (c) 2007 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
import zope.interface
|
||||
import BTrees.Interfaces
|
||||
|
||||
|
||||
@zope.interface.implementer(BTrees.Interfaces.IBTreeFamily)
|
||||
class _Family(object):
|
||||
|
||||
from BTrees import OOBTree as OO
|
||||
|
||||
class _Family32(_Family):
|
||||
from BTrees import OIBTree as OI
|
||||
from BTrees import IIBTree as II
|
||||
from BTrees import IOBTree as IO
|
||||
from BTrees import IFBTree as IF
|
||||
|
||||
maxint = int(2**31-1)
|
||||
minint = -maxint - 1
|
||||
|
||||
def __reduce__(self):
|
||||
return _family32, ()
|
||||
|
||||
class _Family64(_Family):
|
||||
from BTrees import OLBTree as OI
|
||||
from BTrees import LLBTree as II
|
||||
from BTrees import LOBTree as IO
|
||||
from BTrees import LFBTree as IF
|
||||
|
||||
maxint = 2**63-1
|
||||
minint = -maxint - 1
|
||||
|
||||
def __reduce__(self):
|
||||
return _family64, ()
|
||||
|
||||
def _family32():
|
||||
return family32
|
||||
_family32.__safe_for_unpickling__ = True
|
||||
|
||||
def _family64():
|
||||
return family64
|
||||
_family64.__safe_for_unpickling__ = True
|
||||
|
||||
|
||||
family32 = _Family32()
|
||||
family64 = _Family64()
|
||||
|
||||
|
||||
BTrees.family64.IO.family = family64
|
||||
BTrees.family64.OI.family = family64
|
||||
BTrees.family64.IF.family = family64
|
||||
BTrees.family64.II.family = family64
|
||||
|
||||
BTrees.family32.IO.family = family32
|
||||
BTrees.family32.OI.family = family32
|
||||
BTrees.family32.IF.family = family32
|
||||
BTrees.family32.II.family = family32
|
1595
thesisenv/lib/python3.6/site-packages/BTrees/_base.py
Normal file
1595
thesisenv/lib/python3.6/site-packages/BTrees/_base.py
Normal file
File diff suppressed because it is too large
Load Diff
55
thesisenv/lib/python3.6/site-packages/BTrees/_compat.h
Normal file
55
thesisenv/lib/python3.6/site-packages/BTrees/_compat.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* Straddle Python 2 / 3 */
|
||||
#ifndef BTREES__COMPAT_H
|
||||
#define BTREES__COMPAT_H
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
#ifdef INTERN
|
||||
#undef INTERN
|
||||
#endif
|
||||
|
||||
#ifdef INT_FROM_LONG
|
||||
#undef INT_FROM_LONG
|
||||
#endif
|
||||
|
||||
#ifdef INT_CHECK
|
||||
#undef INT_CHECK
|
||||
#endif
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
|
||||
#define PY3K
|
||||
|
||||
#define INTERN PyUnicode_InternFromString
|
||||
#define INT_FROM_LONG(x) PyLong_FromLong(x)
|
||||
#define INT_CHECK(x) PyLong_Check(x)
|
||||
#define INT_AS_LONG(x) PyLong_AS_LONG(x)
|
||||
#define TEXT_FROM_STRING PyUnicode_FromString
|
||||
#define TEXT_FORMAT PyUnicode_Format
|
||||
|
||||
/* Note that the second comparison is skipped if the first comparison returns:
|
||||
|
||||
1 -> There was no error and the answer is -1
|
||||
-1 -> There was an error, which the caller will detect with PyError_Occurred.
|
||||
*/
|
||||
#define COMPARE(lhs, rhs) \
|
||||
(lhs == Py_None ? (rhs == Py_None ? 0 : -1) : (rhs == Py_None ? 1 : \
|
||||
(PyObject_RichCompareBool((lhs), (rhs), Py_LT) != 0 ? -1 : \
|
||||
(PyObject_RichCompareBool((lhs), (rhs), Py_EQ) > 0 ? 0 : 1))))
|
||||
|
||||
#else
|
||||
|
||||
#define INTERN PyString_InternFromString
|
||||
#define INT_FROM_LONG(x) PyInt_FromLong(x)
|
||||
#define INT_CHECK(x) PyInt_Check(x)
|
||||
#define INT_AS_LONG(x) PyInt_AS_LONG(x)
|
||||
#define TEXT_FROM_STRING PyString_FromString
|
||||
#define TEXT_FORMAT PyString_Format
|
||||
|
||||
#define COMPARE(lhs, rhs) \
|
||||
(lhs == Py_None ? (rhs == Py_None ? 0 : -1) : (rhs == Py_None ? 1 : \
|
||||
PyObject_Compare((lhs), (rhs))))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* BTREES__COMPAT_H */
|
100
thesisenv/lib/python3.6/site-packages/BTrees/_compat.py
Normal file
100
thesisenv/lib/python3.6/site-packages/BTrees/_compat.py
Normal file
@ -0,0 +1,100 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2001-2012 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
import os
|
||||
import sys
|
||||
|
||||
PYPY = hasattr(sys, 'pypy_version_info')
|
||||
# We can and do build the C extensions on PyPy, but
|
||||
# as of Persistent 4.2.5 the persistent C extension is not
|
||||
# built on PyPy, so importing our C extension will fail anyway.
|
||||
PURE_PYTHON = os.environ.get('PURE_PYTHON', PYPY)
|
||||
|
||||
|
||||
if sys.version_info[0] < 3: #pragma NO COVER Python2
|
||||
|
||||
PY2 = True
|
||||
PY3 = False
|
||||
|
||||
int_types = int, long
|
||||
xrange = xrange
|
||||
def compare(x, y):
|
||||
if x is None:
|
||||
if y is None:
|
||||
return 0
|
||||
else:
|
||||
return -1
|
||||
elif y is None:
|
||||
return 1
|
||||
else:
|
||||
return cmp(x, y)
|
||||
|
||||
_bytes = str
|
||||
def _ascii(x):
|
||||
return bytes(x)
|
||||
|
||||
else: #pragma NO COVER Python3
|
||||
|
||||
PY2 = False
|
||||
PY3 = True
|
||||
|
||||
int_types = int,
|
||||
xrange = range
|
||||
|
||||
def compare(x, y):
|
||||
if x is None:
|
||||
if y is None:
|
||||
return 0
|
||||
else:
|
||||
return -1
|
||||
elif y is None:
|
||||
return 1
|
||||
else:
|
||||
return (x > y) - (y > x)
|
||||
|
||||
_bytes = bytes
|
||||
def _ascii(x):
|
||||
return bytes(x, 'ascii')
|
||||
|
||||
|
||||
def import_c_extension(mod_globals):
|
||||
import importlib
|
||||
c_module = None
|
||||
module_name = mod_globals['__name__']
|
||||
assert module_name.startswith('BTrees.')
|
||||
module_name = module_name.split('.')[1]
|
||||
if not PURE_PYTHON:
|
||||
try:
|
||||
c_module = importlib.import_module('BTrees._' + module_name)
|
||||
except ImportError:
|
||||
pass
|
||||
if c_module is not None:
|
||||
new_values = dict(c_module.__dict__)
|
||||
new_values.pop("__name__", None)
|
||||
new_values.pop('__file__', None)
|
||||
new_values.pop('__doc__', None)
|
||||
mod_globals.update(new_values)
|
||||
else:
|
||||
# No C extension, make the Py versions available without that
|
||||
# extension. The list comprehension both filters and prevents
|
||||
# concurrent modification errors.
|
||||
for py in [k for k in mod_globals if k.endswith('Py')]:
|
||||
mod_globals[py[:-2]] = mod_globals[py]
|
||||
|
||||
# Assign the global aliases
|
||||
prefix = module_name[:2]
|
||||
for name in ('Bucket', 'Set', 'BTree', 'TreeSet'):
|
||||
mod_globals[name] = mod_globals[prefix + name]
|
||||
|
||||
# Cleanup
|
||||
del mod_globals['import_c_extension']
|
164
thesisenv/lib/python3.6/site-packages/BTrees/_fsBTree.c
Normal file
164
thesisenv/lib/python3.6/site-packages/BTrees/_fsBTree.c
Normal file
@ -0,0 +1,164 @@
|
||||
/*############################################################################
|
||||
#
|
||||
# Copyright (c) 2004 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
############################################################################*/
|
||||
|
||||
#define MASTER_ID "$Id$\n"
|
||||
|
||||
/* fsBTree - FileStorage index BTree
|
||||
|
||||
This BTree implements a mapping from 2-character strings
|
||||
to six-character strings. This allows us to efficiently store
|
||||
a FileStorage index as a nested mapping of 6-character oid prefix
|
||||
to mapping of 2-character oid suffix to 6-character (byte) file
|
||||
positions.
|
||||
*/
|
||||
|
||||
typedef unsigned char char2[2];
|
||||
typedef unsigned char char6[6];
|
||||
|
||||
/* Setup template macros */
|
||||
|
||||
#define PERSISTENT
|
||||
|
||||
#define MOD_NAME_PREFIX "fs"
|
||||
|
||||
#define DEFAULT_MAX_BUCKET_SIZE 500
|
||||
#define DEFAULT_MAX_BTREE_SIZE 500
|
||||
|
||||
#include "_compat.h"
|
||||
/*#include "intkeymacros.h"*/
|
||||
|
||||
#define KEYMACROS_H "$Id$\n"
|
||||
#define KEY_TYPE char2
|
||||
#undef KEY_TYPE_IS_PYOBJECT
|
||||
#define KEY_CHECK(K) (PyBytes_Check(K) && PyBytes_GET_SIZE(K)==2)
|
||||
#define TEST_KEY_SET_OR(V, K, T) if ( ( (V) = ((*(K) < *(T) || (*(K) == *(T) && (K)[1] < (T)[1])) ? -1 : ((*(K) == *(T) && (K)[1] == (T)[1]) ? 0 : 1)) ), 0 )
|
||||
#define DECREF_KEY(KEY)
|
||||
#define INCREF_KEY(k)
|
||||
#define COPY_KEY(KEY, E) (*(KEY)=*(E), (KEY)[1]=(E)[1])
|
||||
#define COPY_KEY_TO_OBJECT(O, K) O=PyBytes_FromStringAndSize((const char*)K,2)
|
||||
#define COPY_KEY_FROM_ARG(TARGET, ARG, STATUS) \
|
||||
if (KEY_CHECK(ARG)) memcpy(TARGET, PyBytes_AS_STRING(ARG), 2); else { \
|
||||
PyErr_SetString(PyExc_TypeError, "expected two-character string key"); \
|
||||
(STATUS)=0; }
|
||||
|
||||
/*#include "intvaluemacros.h"*/
|
||||
#define VALUEMACROS_H "$Id$\n"
|
||||
#define VALUE_TYPE char6
|
||||
#undef VALUE_TYPE_IS_PYOBJECT
|
||||
#define TEST_VALUE(K, T) memcmp(K,T,6)
|
||||
#define DECREF_VALUE(k)
|
||||
#define INCREF_VALUE(k)
|
||||
#define COPY_VALUE(V, E) (memcpy(V, E, 6))
|
||||
#define COPY_VALUE_TO_OBJECT(O, K) O=PyBytes_FromStringAndSize((const char*)K,6)
|
||||
#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS) \
|
||||
if ((PyBytes_Check(ARG) && PyBytes_GET_SIZE(ARG)==6)) \
|
||||
memcpy(TARGET, PyBytes_AS_STRING(ARG), 6); else { \
|
||||
PyErr_SetString(PyExc_TypeError, "expected six-character string key"); \
|
||||
(STATUS)=0; }
|
||||
|
||||
#define NORMALIZE_VALUE(V, MIN)
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
static PyObject *bucket_toBytes(PyObject *self);
|
||||
|
||||
static PyObject *bucket_fromBytes(PyObject *self, PyObject *state);
|
||||
|
||||
#define EXTRA_BUCKET_METHODS \
|
||||
{"toBytes", (PyCFunction) bucket_toBytes, METH_NOARGS, \
|
||||
"toBytes() -- Return the state as a bytes array"}, \
|
||||
{"fromBytes", (PyCFunction) bucket_fromBytes, METH_O, \
|
||||
"fromSBytes(s) -- Set the state of the object from a bytes array"}, \
|
||||
{"toString", (PyCFunction) bucket_toBytes, METH_NOARGS, \
|
||||
"toString() -- Deprecated alias for 'toBytes'"}, \
|
||||
{"fromString", (PyCFunction) bucket_fromBytes, METH_O, \
|
||||
"fromString(s) -- Deprecated alias for 'fromBytes'"}, \
|
||||
|
||||
#ifdef PY3K
|
||||
#define INITMODULE PyInit__fsBTree
|
||||
#else
|
||||
#define INITMODULE init_fsBTree
|
||||
#endif
|
||||
#include "BTreeModuleTemplate.c"
|
||||
|
||||
static PyObject *
|
||||
bucket_toBytes(PyObject *oself)
|
||||
{
|
||||
Bucket *self = (Bucket *)oself;
|
||||
PyObject *items = NULL;
|
||||
int len;
|
||||
|
||||
PER_USE_OR_RETURN(self, NULL);
|
||||
|
||||
len = self->len;
|
||||
|
||||
items = PyBytes_FromStringAndSize(NULL, len*8);
|
||||
if (items == NULL)
|
||||
goto err;
|
||||
memcpy(PyBytes_AS_STRING(items), self->keys, len*2);
|
||||
memcpy(PyBytes_AS_STRING(items)+len*2, self->values, len*6);
|
||||
|
||||
PER_UNUSE(self);
|
||||
return items;
|
||||
|
||||
err:
|
||||
PER_UNUSE(self);
|
||||
Py_XDECREF(items);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
bucket_fromBytes(PyObject *oself, PyObject *state)
|
||||
{
|
||||
Bucket *self = (Bucket *)oself;
|
||||
int len;
|
||||
KEY_TYPE *keys;
|
||||
VALUE_TYPE *values;
|
||||
|
||||
len = PyBytes_Size(state);
|
||||
if (len < 0)
|
||||
return NULL;
|
||||
|
||||
if (len%8)
|
||||
{
|
||||
PyErr_SetString(PyExc_ValueError, "state string of wrong size");
|
||||
return NULL;
|
||||
}
|
||||
len /= 8;
|
||||
|
||||
if (self->next) {
|
||||
Py_DECREF(self->next);
|
||||
self->next = NULL;
|
||||
}
|
||||
|
||||
if (len > self->size) {
|
||||
keys = BTree_Realloc(self->keys, sizeof(KEY_TYPE)*len);
|
||||
if (keys == NULL)
|
||||
return NULL;
|
||||
values = BTree_Realloc(self->values, sizeof(VALUE_TYPE)*len);
|
||||
if (values == NULL)
|
||||
return NULL;
|
||||
self->keys = keys;
|
||||
self->values = values;
|
||||
self->size = len;
|
||||
}
|
||||
|
||||
memcpy(self->keys, PyBytes_AS_STRING(state), len*2);
|
||||
memcpy(self->values, PyBytes_AS_STRING(state)+len*2, len*6);
|
||||
|
||||
self->len = len;
|
||||
|
||||
Py_INCREF(self);
|
||||
return (PyObject *)self;
|
||||
}
|
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_fsBTree.cpython-36m-darwin.so
Executable file
BIN
thesisenv/lib/python3.6/site-packages/BTrees/_fsBTree.cpython-36m-darwin.so
Executable file
Binary file not shown.
428
thesisenv/lib/python3.6/site-packages/BTrees/check.py
Normal file
428
thesisenv/lib/python3.6/site-packages/BTrees/check.py
Normal file
@ -0,0 +1,428 @@
|
||||
##############################################################################
|
||||
#
|
||||
# Copyright (c) 2003 Zope Foundation and Contributors.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# This software is subject to the provisions of the Zope Public License,
|
||||
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
|
||||
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE
|
||||
#
|
||||
##############################################################################
|
||||
"""
|
||||
Utilities for working with BTrees (TreeSets, Buckets, and Sets) at a low
|
||||
level.
|
||||
|
||||
The primary function is check(btree), which performs value-based consistency
|
||||
checks of a kind btree._check() does not perform. See the function docstring
|
||||
for details.
|
||||
|
||||
display(btree) displays the internal structure of a BTree (TreeSet, etc) to
|
||||
stdout.
|
||||
|
||||
CAUTION: When a BTree node has only a single bucket child, it can be
|
||||
impossible to get at the bucket from Python code (__getstate__() may squash
|
||||
the bucket object out of existence, as a pickling storage optimization). In
|
||||
such a case, the code here synthesizes a temporary bucket with the same keys
|
||||
(and values, if the bucket is of a mapping type). This has no first-order
|
||||
consequences, but can mislead if you pay close attention to reported object
|
||||
addresses and/or object identity (the synthesized bucket has an address
|
||||
that doesn't exist in the actual BTree).
|
||||
"""
|
||||
|
||||
from BTrees.IFBTree import IFBTree, IFBucket, IFSet, IFTreeSet
|
||||
from BTrees.IFBTree import IFBTreePy, IFBucketPy, IFSetPy, IFTreeSetPy
|
||||
from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet
|
||||
from BTrees.IIBTree import IIBTreePy, IIBucketPy, IISetPy, IITreeSetPy
|
||||
from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
|
||||
from BTrees.IOBTree import IOBTreePy, IOBucketPy, IOSetPy, IOTreeSetPy
|
||||
from BTrees.LFBTree import LFBTree, LFBucket, LFSet, LFTreeSet
|
||||
from BTrees.LFBTree import LFBTreePy, LFBucketPy, LFSetPy, LFTreeSetPy
|
||||
from BTrees.LLBTree import LLBTree, LLBucket, LLSet, LLTreeSet
|
||||
from BTrees.LLBTree import LLBTreePy, LLBucketPy, LLSetPy, LLTreeSetPy
|
||||
from BTrees.LOBTree import LOBTree, LOBucket, LOSet, LOTreeSet
|
||||
from BTrees.LOBTree import LOBTreePy, LOBucketPy, LOSetPy, LOTreeSetPy
|
||||
from BTrees.OIBTree import OIBTree, OIBucket, OISet, OITreeSet
|
||||
from BTrees.OIBTree import OIBTreePy, OIBucketPy, OISetPy, OITreeSetPy
|
||||
from BTrees.OLBTree import OLBTree, OLBucket, OLSet, OLTreeSet
|
||||
from BTrees.OLBTree import OLBTreePy, OLBucketPy, OLSetPy, OLTreeSetPy
|
||||
from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet
|
||||
from BTrees.OOBTree import OOBTreePy, OOBucketPy, OOSetPy, OOTreeSetPy
|
||||
|
||||
from BTrees.utils import positive_id
|
||||
from BTrees.utils import oid_repr
|
||||
|
||||
TYPE_UNKNOWN, TYPE_BTREE, TYPE_BUCKET = range(3)
|
||||
|
||||
from ._compat import compare
|
||||
|
||||
_type2kind = {}
|
||||
for kv in ('OO',
|
||||
'II', 'IO', 'OI', 'IF',
|
||||
'LL', 'LO', 'OL', 'LF',
|
||||
):
|
||||
for name, kind in (
|
||||
('BTree', (TYPE_BTREE, True)),
|
||||
('Bucket', (TYPE_BUCKET, True)),
|
||||
('TreeSet', (TYPE_BTREE, False)),
|
||||
('Set', (TYPE_BUCKET, False)),
|
||||
):
|
||||
_type2kind[globals()[kv+name]] = kind
|
||||
py = kv + name + 'Py'
|
||||
_type2kind[globals()[py]] = kind
|
||||
|
||||
# Return pair
|
||||
#
|
||||
# TYPE_BTREE or TYPE_BUCKET, is_mapping
|
||||
|
||||
def classify(obj):
|
||||
return _type2kind[type(obj)]
|
||||
|
||||
|
||||
BTREE_EMPTY, BTREE_ONE, BTREE_NORMAL = range(3)
|
||||
|
||||
# If the BTree is empty, returns
|
||||
#
|
||||
# BTREE_EMPTY, [], []
|
||||
#
|
||||
# If the BTree has only one bucket, sometimes returns
|
||||
#
|
||||
# BTREE_ONE, bucket_state, None
|
||||
#
|
||||
# Else returns
|
||||
#
|
||||
# BTREE_NORMAL, list of keys, list of kids
|
||||
#
|
||||
# and the list of kids has one more entry than the list of keys.
|
||||
#
|
||||
# BTree.__getstate__() docs:
|
||||
#
|
||||
# For an empty BTree (self->len == 0), None.
|
||||
#
|
||||
# For a BTree with one child (self->len == 1), and that child is a bucket,
|
||||
# and that bucket has a NULL oid, a one-tuple containing a one-tuple
|
||||
# containing the bucket's state:
|
||||
#
|
||||
# (
|
||||
# (
|
||||
# child[0].__getstate__(),
|
||||
# ),
|
||||
# )
|
||||
#
|
||||
# Else a two-tuple. The first element is a tuple interleaving the BTree's
|
||||
# keys and direct children, of size 2*self->len - 1 (key[0] is unused and
|
||||
# is not saved). The second element is the firstbucket:
|
||||
#
|
||||
# (
|
||||
# (child[0], key[1], child[1], key[2], child[2], ...,
|
||||
# key[len-1], child[len-1]),
|
||||
# self->firstbucket
|
||||
# )
|
||||
|
||||
_btree2bucket = {}
|
||||
for kv in ('OO',
|
||||
'II', 'IO', 'OI', 'IF',
|
||||
'LL', 'LO', 'OL', 'LF',
|
||||
):
|
||||
_btree2bucket[globals()[kv+'BTree']] = globals()[kv+'Bucket']
|
||||
py = kv + 'BTreePy'
|
||||
_btree2bucket[globals()[py]] = globals()[kv+'BucketPy']
|
||||
_btree2bucket[globals()[kv+'TreeSet']] = globals()[kv+'Set']
|
||||
py = kv + 'TreeSetPy'
|
||||
_btree2bucket[globals()[kv+'TreeSetPy']] = globals()[kv+'SetPy']
|
||||
|
||||
|
||||
def crack_btree(t, is_mapping):
|
||||
state = t.__getstate__()
|
||||
if state is None:
|
||||
return BTREE_EMPTY, [], []
|
||||
|
||||
assert isinstance(state, tuple)
|
||||
if len(state) == 1:
|
||||
state = state[0]
|
||||
assert isinstance(state, tuple) and len(state) == 1
|
||||
state = state[0]
|
||||
return BTREE_ONE, state, None
|
||||
|
||||
assert len(state) == 2
|
||||
data, firstbucket = state
|
||||
n = len(data)
|
||||
assert n & 1
|
||||
kids = []
|
||||
keys = []
|
||||
i = 0
|
||||
for x in data:
|
||||
if i & 1:
|
||||
keys.append(x)
|
||||
else:
|
||||
kids.append(x)
|
||||
i += 1
|
||||
return BTREE_NORMAL, keys, kids
|
||||
|
||||
# Returns
|
||||
#
|
||||
# keys, values # for a mapping; len(keys) == len(values) in this case
|
||||
# or
|
||||
# keys, [] # for a set
|
||||
#
|
||||
# bucket.__getstate__() docs:
|
||||
#
|
||||
# For a set bucket (self->values is NULL), a one-tuple or two-tuple. The
|
||||
# first element is a tuple of keys, of length self->len. The second element
|
||||
# is the next bucket, present if and only if next is non-NULL:
|
||||
#
|
||||
# (
|
||||
# (keys[0], keys[1], ..., keys[len-1]),
|
||||
# <self->next iff non-NULL>
|
||||
# )
|
||||
#
|
||||
# For a mapping bucket (self->values is not NULL), a one-tuple or two-tuple.
|
||||
# The first element is a tuple interleaving keys and values, of length
|
||||
# 2 * self->len. The second element is the next bucket, present iff next is
|
||||
# non-NULL:
|
||||
#
|
||||
# (
|
||||
# (keys[0], values[0], keys[1], values[1], ...,
|
||||
# keys[len-1], values[len-1]),
|
||||
# <self->next iff non-NULL>
|
||||
# )
|
||||
|
||||
def crack_bucket(b, is_mapping):
|
||||
state = b.__getstate__()
|
||||
assert isinstance(state, tuple)
|
||||
assert 1 <= len(state) <= 2
|
||||
data = state[0]
|
||||
if not is_mapping:
|
||||
return data, []
|
||||
keys = []
|
||||
values = []
|
||||
n = len(data)
|
||||
assert n & 1 == 0
|
||||
i = 0
|
||||
for x in data:
|
||||
if i & 1:
|
||||
values.append(x)
|
||||
else:
|
||||
keys.append(x)
|
||||
i += 1
|
||||
return keys, values
|
||||
|
||||
def type_and_adr(obj):
|
||||
if hasattr(obj, '_p_oid'):
|
||||
oid = oid_repr(obj._p_oid)
|
||||
else:
|
||||
oid = 'None'
|
||||
return "%s (0x%x oid=%s)" % (type(obj).__name__, positive_id(obj), oid)
|
||||
|
||||
# Walker implements a depth-first search of a BTree (or TreeSet or Set or
|
||||
# Bucket). Subclasses must implement the visit_btree() and visit_bucket()
|
||||
# methods, and arrange to call the walk() method. walk() calls the
|
||||
# visit_XYZ() methods once for each node in the tree, in depth-first
|
||||
# left-to-right order.
|
||||
|
||||
class Walker:
|
||||
def __init__(self, obj):
|
||||
self.obj = obj
|
||||
|
||||
# obj is the BTree (BTree or TreeSet).
|
||||
# path is a list of indices, from the root. For example, if a BTree node
|
||||
# is child[5] of child[3] of the root BTree, [3, 5].
|
||||
# parent is the parent BTree object, or None if this is the root BTree.
|
||||
# is_mapping is True for a BTree and False for a TreeSet.
|
||||
# keys is a list of the BTree's internal keys.
|
||||
# kids is a list of the BTree's children.
|
||||
# If the BTree is an empty root node, keys == kids == [].
|
||||
# Else len(kids) == len(keys) + 1.
|
||||
# lo and hi are slice bounds on the values the elements of keys *should*
|
||||
# lie in (lo inclusive, hi exclusive). lo is None if there is no lower
|
||||
# bound known, and hi is None if no upper bound is known.
|
||||
|
||||
def visit_btree(self, obj, path, parent, is_mapping,
|
||||
keys, kids, lo, hi):
|
||||
raise NotImplementedError
|
||||
|
||||
# obj is the bucket (Bucket or Set).
|
||||
# path is a list of indices, from the root. For example, if a bucket
|
||||
# node is child[5] of child[3] of the root BTree, [3, 5].
|
||||
# parent is the parent BTree object.
|
||||
# is_mapping is True for a Bucket and False for a Set.
|
||||
# keys is a list of the bucket's keys.
|
||||
# values is a list of the bucket's values.
|
||||
# If is_mapping is false, values == []. Else len(keys) == len(values).
|
||||
# lo and hi are slice bounds on the values the elements of keys *should*
|
||||
# lie in (lo inclusive, hi exclusive). lo is None if there is no lower
|
||||
# bound known, and hi is None if no upper bound is known.
|
||||
|
||||
def visit_bucket(self, obj, path, parent, is_mapping,
|
||||
keys, values, lo, hi):
|
||||
raise NotImplementedError
|
||||
|
||||
def walk(self):
|
||||
obj = self.obj
|
||||
path = []
|
||||
stack = [(obj, path, None, None, None)]
|
||||
while stack:
|
||||
obj, path, parent, lo, hi = stack.pop()
|
||||
kind, is_mapping = classify(obj)
|
||||
if kind is TYPE_BTREE:
|
||||
bkind, keys, kids = crack_btree(obj, is_mapping)
|
||||
if bkind is BTREE_NORMAL:
|
||||
# push the kids, in reverse order (so they're popped off
|
||||
# the stack in forward order)
|
||||
n = len(kids)
|
||||
for i in range(len(kids)-1, -1, -1):
|
||||
newlo, newhi = lo, hi
|
||||
if i < n-1:
|
||||
newhi = keys[i]
|
||||
if i > 0:
|
||||
newlo = keys[i-1]
|
||||
stack.append((kids[i],
|
||||
path + [i],
|
||||
obj,
|
||||
newlo,
|
||||
newhi))
|
||||
|
||||
elif bkind is BTREE_EMPTY:
|
||||
pass
|
||||
else:
|
||||
assert bkind is BTREE_ONE
|
||||
# Yuck. There isn't a bucket object to pass on, as
|
||||
# the bucket state is embedded directly in the BTree
|
||||
# state. Synthesize a bucket.
|
||||
assert kids is None # and "keys" is really the bucket
|
||||
# state
|
||||
bucket = _btree2bucket[type(obj)]()
|
||||
bucket.__setstate__(keys)
|
||||
stack.append((bucket,
|
||||
path + [0],
|
||||
obj,
|
||||
lo,
|
||||
hi))
|
||||
keys = []
|
||||
kids = [bucket]
|
||||
|
||||
self.visit_btree(obj,
|
||||
path,
|
||||
parent,
|
||||
is_mapping,
|
||||
keys,
|
||||
kids,
|
||||
lo,
|
||||
hi)
|
||||
else:
|
||||
assert kind is TYPE_BUCKET
|
||||
keys, values = crack_bucket(obj, is_mapping)
|
||||
self.visit_bucket(obj,
|
||||
path,
|
||||
parent,
|
||||
is_mapping,
|
||||
keys,
|
||||
values,
|
||||
lo,
|
||||
hi)
|
||||
|
||||
|
||||
class Checker(Walker):
|
||||
def __init__(self, obj):
|
||||
Walker.__init__(self, obj)
|
||||
self.errors = []
|
||||
|
||||
def check(self):
|
||||
self.walk()
|
||||
if self.errors:
|
||||
s = "Errors found in %s:" % type_and_adr(self.obj)
|
||||
self.errors.insert(0, s)
|
||||
s = "\n".join(self.errors)
|
||||
raise AssertionError(s)
|
||||
|
||||
def visit_btree(self, obj, path, parent, is_mapping,
|
||||
keys, kids, lo, hi):
|
||||
self.check_sorted(obj, path, keys, lo, hi)
|
||||
|
||||
def visit_bucket(self, obj, path, parent, is_mapping,
|
||||
keys, values, lo, hi):
|
||||
self.check_sorted(obj, path, keys, lo, hi)
|
||||
|
||||
def check_sorted(self, obj, path, keys, lo, hi):
|
||||
i, n = 0, len(keys)
|
||||
for x in keys:
|
||||
# lo or hi are ommitted by supplying None. Thus the not
|
||||
# None checkes below.
|
||||
if lo is not None and not compare(lo, x) <= 0:
|
||||
s = "key %r < lower bound %r at index %d" % (x, lo, i)
|
||||
self.complain(s, obj, path)
|
||||
if hi is not None and not compare(x, hi) < 0:
|
||||
s = "key %r >= upper bound %r at index %d" % (x, hi, i)
|
||||
self.complain(s, obj, path)
|
||||
if i < n-1 and not compare(x, keys[i+1]) < 0:
|
||||
s = "key %r at index %d >= key %r at index %d" % (
|
||||
x, i, keys[i+1], i+1)
|
||||
self.complain(s, obj, path)
|
||||
i += 1
|
||||
|
||||
def complain(self, msg, obj, path):
|
||||
s = "%s, in %s, path from root %s" % (
|
||||
msg,
|
||||
type_and_adr(obj),
|
||||
".".join(map(str, path)))
|
||||
self.errors.append(s)
|
||||
|
||||
class Printer(Walker): #pragma NO COVER
|
||||
def __init__(self, obj):
|
||||
Walker.__init__(self, obj)
|
||||
|
||||
def display(self):
|
||||
self.walk()
|
||||
|
||||
def visit_btree(self, obj, path, parent, is_mapping,
|
||||
keys, kids, lo, hi):
|
||||
indent = " " * len(path)
|
||||
print("%s%s %s with %d children" % (
|
||||
indent,
|
||||
".".join(map(str, path)),
|
||||
type_and_adr(obj),
|
||||
len(kids)))
|
||||
indent += " "
|
||||
n = len(keys)
|
||||
for i in range(n):
|
||||
print("%skey %d: %r" % (indent, i, keys[i]))
|
||||
|
||||
def visit_bucket(self, obj, path, parent, is_mapping,
|
||||
keys, values, lo, hi):
|
||||
indent = " " * len(path)
|
||||
print("%s%s %s with %d keys" % (
|
||||
indent,
|
||||
".".join(map(str, path)),
|
||||
type_and_adr(obj),
|
||||
len(keys)))
|
||||
indent += " "
|
||||
n = len(keys)
|
||||
for i in range(n):
|
||||
print("%skey %d: %r" % (indent, i, keys[i]),)
|
||||
if is_mapping:
|
||||
print("value %r" % (values[i],))
|
||||
|
||||
def check(btree):
|
||||
"""Check internal value-based invariants in a BTree or TreeSet.
|
||||
|
||||
The btree._check() method checks internal C-level pointer consistency.
|
||||
The check() function here checks value-based invariants: whether the
|
||||
keys in leaf bucket and internal nodes are in strictly increasing order,
|
||||
and whether they all lie in their expected range. The latter is a subtle
|
||||
invariant that can't be checked locally -- it requires propagating
|
||||
range info down from the root of the tree, and modifying it at each
|
||||
level for each child.
|
||||
|
||||
Raises AssertionError if anything is wrong, with a string detail
|
||||
explaining the problems. The entire tree is checked before
|
||||
AssertionError is raised, and the string detail may be large (depending
|
||||
on how much went wrong).
|
||||
"""
|
||||
|
||||
Checker(btree).check()
|
||||
|
||||
def display(btree): #pragma NO COVER
|
||||
"Display the internal structure of a BTree, Bucket, TreeSet or Set."
|
||||
Printer(btree).display()
|
@ -0,0 +1,25 @@
|
||||
|
||||
#define VALUEMACROS_H "$Id$\n"
|
||||
|
||||
#define VALUE_TYPE float
|
||||
#undef VALUE_TYPE_IS_PYOBJECT
|
||||
#define TEST_VALUE(K, T) (((K) < (T)) ? -1 : (((K) > (T)) ? 1: 0))
|
||||
#define VALUE_SAME(VALUE, TARGET) ( (VALUE) == (TARGET) )
|
||||
#define DECLARE_VALUE(NAME) VALUE_TYPE NAME
|
||||
#define VALUE_PARSE "f"
|
||||
#define DECREF_VALUE(k)
|
||||
#define INCREF_VALUE(k)
|
||||
#define COPY_VALUE(V, E) (V=(E))
|
||||
#define COPY_VALUE_TO_OBJECT(O, K) O=PyFloat_FromDouble(K)
|
||||
#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS) \
|
||||
if (PyFloat_Check(ARG)) TARGET = (float)PyFloat_AsDouble(ARG); \
|
||||
else if (INT_CHECK(ARG)) TARGET = (float)INT_AS_LONG(ARG); \
|
||||
else { \
|
||||
PyErr_SetString(PyExc_TypeError, "expected float or int value"); \
|
||||
(STATUS)=0; (TARGET)=0; }
|
||||
|
||||
#define NORMALIZE_VALUE(V, MIN) ((MIN) > 0) ? ((V)/=(MIN)) : 0
|
||||
|
||||
#define MERGE_DEFAULT 1.0f
|
||||
#define MERGE(O1, w1, O2, w2) ((O1)*(w1)+(O2)*(w2))
|
||||
#define MERGE_WEIGHT(O, w) ((O)*(w))
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user