Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add PEP 489 support #209

Open
wants to merge 78 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
da5cd5e
chore: declutter: one decl per line, wrap long lines
tseaver Jun 2, 2024
d9d8a34
refactor: remove weird 'object_' static
tseaver Jun 2, 2024
3b45b38
refactor: homogenize string interning
tseaver Jun 2, 2024
d451191
refactor: explicitly declare the CAPI struct static
tseaver Jun 2, 2024
c0af71d
refactor: add flags for PEP 489 conditional implementation
tseaver Jun 2, 2024
328767b
refactor: store / use imported ConflictError in module state
tseaver Jun 2, 2024
73e60bd
refactor: add helper method for looking up the CAPI struct
tseaver Jun 3, 2024
076738b
refactor: move the global static CAPI pointer to module state
tseaver Jun 3, 2024
175627d
refactor: move the 'allowed names' static into module state
tseaver Jun 3, 2024
5bcbcdf
refactor: remove use of PER_GHOSTIFY macro
tseaver Jun 3, 2024
3206eef
refactor: remove use of PER_CHANGED macro
tseaver Jun 3, 2024
7cf369d
refactor: remove use of PER_READCURRENT macro
tseaver Jun 3, 2024
9e9dc06
refactor: remove use of local PER_UNUSE macro
tseaver Jun 3, 2024
a461d85
refactor: remove use of PER_ACCESSED macro
tseaver Jun 3, 2024
16f9d2c
refactor: convert PER_ALLOW_DEACTIVATION macro to inline static func
tseaver Jun 3, 2024
67770d3
refactor: convert PER_PREVENT_DEACTIVATION macro to inline static func
tseaver Jun 3, 2024
cd83510
refactor: convert PER_USE* macros to inline static func
tseaver Jun 3, 2024
53dc058
refactor: tidying
tseaver Jun 3, 2024
b6d3692
refactor: cleanup imports
tseaver Jun 3, 2024
07128b3
refactor: assign module state 'capi_struct' directly
tseaver Jun 3, 2024
f08c58b
refactor: condition static / multi-phase init on Python version
tseaver Jun 3, 2024
7142eb3
refactor: re-order to prep for multi-phase module init
tseaver Jun 3, 2024
bb37267
fix: copy-pasta in not-yet-active branch of '_get_module'
tseaver Jun 3, 2024
31d55f2
refactor: store type objects in state
tseaver Jun 3, 2024
2c55b0f
refactor: normalize static type definitions
tseaver Jun 3, 2024
e8ec9c6
refactor: sanify whitespace / brackets
tseaver Jun 3, 2024
27b77ae
refactor: add module state accessors for type objects
tseaver Jun 3, 2024
043fa95
refactor: use module state accessors for type objects
tseaver Jun 3, 2024
b1e6f1b
fix: init non-persistent types properly
tseaver Jun 4, 2024
2502190
fix: use normal 'Py_VISIT' macro in tree's 'traverse'
tseaver Jun 4, 2024
e2bebf0
fix: typo
tseaver Jun 4, 2024
4dfbf09
tests: remove 'test_suite' decoy
tseaver Jun 4, 2024
b5f5bbf
feat: add accessors for BTreeItems and BTreeIter types
tseaver Jun 4, 2024
eb57962
feat: expose '_get_module' helper
tseaver Jun 4, 2024
babc653
refactor: make 'newBTreeItems' function as a module 'method'
tseaver Jun 4, 2024
c9527d1
refactor: rename 'BTreeIter_new' -> 'newBTreeIter'
tseaver Jun 4, 2024
f28a420
refactor: normalize static type defs (iter/items)
tseaver Jun 4, 2024
c090165
refactor: further prep static type defs for addition of heap types
tseaver Jun 4, 2024
3d7d69a
feat: add equivalent heap-alloc type specs
tseaver Jun 4, 2024
880c573
refactor: note 'module' as first arg
tseaver Jun 4, 2024
933742c
fix: overlooked use of '&Set_type_def'
tseaver Jun 4, 2024
39321eb
fix: typo
tseaver Jun 4, 2024
dea5ff0
chore: removed unused forward
tseaver Jun 4, 2024
87da2c1
fix: pass ob w/ fully-initialized type
tseaver Jun 4, 2024
737956f
fix: set 'immutable' flag on extension types
tseaver Jun 4, 2024
3369741
refactor: standard Python patterns for '_traverse'/'_dealloc'
tseaver Jun 4, 2024
868465d
refactor: backpedal 'master' version
tseaver Jun 4, 2024
ae23b39
fix: make items/iter types GC aware when heap-allocated
tseaver Jun 4, 2024
4f4239e
fix: decref type in 'Bucket_dealloc'
tseaver Jun 4, 2024
10fcd21
feat: PEP489 for Python >= 3.12
tseaver Jun 4, 2024
8b89e70
refactor: call type's 'tp_alloc' directly
tseaver Jun 4, 2024
6de0312
refactor: pass type ptr to '_bucket__p_resolveConflict'
tseaver Jun 5, 2024
768e512
refactor: replace moar call-type-as-factory w/ 'tp->tp_alloc'
tseaver Jun 5, 2024
411b3af
refactor: use 'PyObject_CallMethodObjArgs' as Guido indented
tseaver Jun 5, 2024
61871ef
fix: improve decref safety
tseaver Jun 5, 2024
2a80897
fix: initialize set's object ptr members
tseaver Jun 5, 2024
902b32e
refactor: moar GC / dealloc cleanups
tseaver Jun 5, 2024
48f532b
fix: set explicit 'tp_alloc'/'tp_new' slots
tseaver Jun 5, 2024
f6f1357
fix: typo in 'basicsize' for heap-alloc Set
tseaver Jun 5, 2024
28249ce
fix: add 'sq_contains' slot for heap-alloc Bucket
tseaver Jun 5, 2024
2cfb0ea
fix: pass explicit 'module' to 'union'/'difference'/'intersection'
tseaver Jun 5, 2024
d68f547
fix: make 'initSetIteration'/'set_operation' quasi-methods
tseaver Jun 5, 2024
84a35d9
fix: fully-qualified name for BTreeItems types
tseaver Jun 5, 2024
7cbcc77
chore: tidy
tseaver Jun 5, 2024
7c77caf
chore: note to future self on GC
tseaver Jun 5, 2024
6196785
refactor: regularize '_dealloc'/'_traverse'
tseaver Jun 5, 2024
0ba1854
fix: explicit checks for NULL returns from '_get_module'
tseaver Jun 5, 2024
a65ad02
feat: extra '_get_conflict_error_from_module' helper
tseaver Jun 5, 2024
3038691
refactor: make 'bucket_merge'/'merge_error' quasi-methods
tseaver Jun 5, 2024
65b57a3
refactor: make 'get_bucket_state' a quasi-method
tseaver Jun 5, 2024
02d0964
refactor: use '_from_module' variant for all '_get_*_type' lookups
tseaver Jun 5, 2024
4fbe255
refactor: rename '_get_*_type_from_module'->'_get_*_type'
tseaver Jun 5, 2024
0e8b5f3
refactor: reduce verbosity of Persistent CAPI type
tseaver Jun 5, 2024
27f10b7
refactor: add '_get_per_capi' lookup
tseaver Jun 5, 2024
65138bb
refactor: rename 'capi_struct'->'per_capi' to reflect new typedef
tseaver Jun 5, 2024
6ba3f38
refactor: remove '_get_capi_struct'/'_get_capi_struct_from_module' ac…
tseaver Jun 5, 2024
9396f92
refactor: consol '_get_conflict_error' w/ '_from_module' variant
tseaver Jun 5, 2024
ba7c000
refactor: rename state attr / accessor for settable BTree attrs
tseaver Jun 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
375 changes: 257 additions & 118 deletions src/BTrees/BTreeItemsTemplate.c

Large diffs are not rendered by default.

892 changes: 708 additions & 184 deletions src/BTrees/BTreeModuleTemplate.c

Large diffs are not rendered by default.

854 changes: 533 additions & 321 deletions src/BTrees/BTreeTemplate.c

Large diffs are not rendered by default.

591 changes: 361 additions & 230 deletions src/BTrees/BucketTemplate.c

Large diffs are not rendered by default.

489 changes: 244 additions & 245 deletions src/BTrees/MergeTemplate.c

Large diffs are not rendered by default.

760 changes: 388 additions & 372 deletions src/BTrees/SetOpTemplate.c

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/BTrees/SetOpTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
#include "Python.h"

static PyObject *
union_m(PyObject *ignored, PyObject *args);
union_m(PyObject *module, PyObject *args);

static PyObject *
intersection_m(PyObject *ignored, PyObject *args);
intersection_m(PyObject *module, PyObject *args);

static PyObject *
difference_m(PyObject *ignored, PyObject *args);
difference_m(PyObject *module, PyObject *args);

# endif
207 changes: 109 additions & 98 deletions src/BTrees/SetTemplate.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,7 @@ _set_setstate(Bucket *self, PyObject *args)
}
self->len=0;

if (self->next)
{
Py_DECREF(self->next);
self->next=0;
}
Py_CLEAR(self->next);

if (l > self->size)
{
Expand Down Expand Up @@ -276,14 +272,17 @@ _set_setstate(Bucket *self, PyObject *args)
static PyObject *
set_setstate(Bucket *self, PyObject *args)
{
PyObject* obj_self = (PyObject*)self;
PerCAPI* per_capi = _get_per_capi(obj_self);
int r;

UNLESS (PyArg_ParseTuple(args, "O", &args))
return NULL;

PER_PREVENT_DEACTIVATION(self);
r=_set_setstate(self, args);
PER_UNUSE(self);
per_prevent_deactivation((cPersistentObject*)self);
r = _set_setstate(self, args);
per_allow_deactivation((cPersistentObject*)self);
per_capi->accessed((cPersistentObject*)self);

if (r < 0)
return NULL;
Expand Down Expand Up @@ -353,13 +352,18 @@ static struct PyMethodDef Set_methods[] = {
static int
Set_init(PyObject *self, PyObject *args, PyObject *kwds)
{
Bucket* b_self = BUCKET(self);
PyObject *v = NULL;

b_self->next = 0;
b_self->keys = 0;
b_self->values = 0;

if (!PyArg_ParseTuple(args, "|O:" MOD_NAME_PREFIX "Set", &v))
return -1;

if (v)
return _Set_update((Bucket *)self, v);
return _Set_update(b_self, v);
else
return 0;
}
Expand Down Expand Up @@ -390,29 +394,38 @@ set_repr(Bucket *self)
static Py_ssize_t
set_length(Bucket *self)
{
PyObject* obj_self = (PyObject*)self;
PerCAPI* per_capi = _get_per_capi(obj_self);
int r;

PER_USE_OR_RETURN(self, -1);
if (!per_use((cPersistentObject*)self, per_capi))
return -1;
r = self->len;
PER_UNUSE(self);
per_allow_deactivation((cPersistentObject*)self);
per_capi->accessed((cPersistentObject*)self);

return r;
}

static PyObject *
set_item(Bucket *self, Py_ssize_t index)
{
PyObject *r=0;
PyObject* obj_self = (PyObject*)self;
PerCAPI* per_capi = _get_per_capi(obj_self);

PER_USE_OR_RETURN(self, NULL);
PyObject *r = 0;

if (!per_use((cPersistentObject*)self, per_capi))
return NULL;
if (index >= 0 && index < self->len)
{
COPY_KEY_TO_OBJECT(r, self->keys[index]);
}
else
IndexError(index);

PER_UNUSE(self);
per_allow_deactivation((cPersistentObject*)self);
per_capi->accessed((cPersistentObject*)self);

return r;
}
Expand Down Expand Up @@ -656,101 +669,99 @@ set_iand(Bucket* self, PyObject* other)
return result;
}

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 char Set__name__[] = MODULE_NAME MOD_NAME_PREFIX "Set";
static char Set__doc__[] = "Result set mapped as a single bucket";

#if USE_STATIC_TYPES

static PyNumberMethods Set_as_number = {
.nb_subtract = bucket_sub,
.nb_and = bucket_and,
.nb_xor = (binaryfunc)Generic_set_xor,
.nb_or = bucket_or,
.nb_inplace_subtract = (binaryfunc)set_isub,
.nb_inplace_and = (binaryfunc)set_iand,
.nb_inplace_xor = (binaryfunc)set_ixor,
.nb_inplace_or = (binaryfunc)set_ior,
};

static PyNumberMethods set_as_number = {
(binaryfunc)0, /* nb_add */
bucket_sub, /* nb_subtract */
(binaryfunc)0, /* nb_multiply */
(binaryfunc)0, /* nb_remainder */
(binaryfunc)0, /* nb_divmod */
(ternaryfunc)0, /* nb_power */
(unaryfunc)0, /* nb_negative */
(unaryfunc)0, /* nb_positive */
(unaryfunc)0, /* nb_absolute */
(inquiry)0, /* nb_bool */
(unaryfunc)0, /* nb_invert */
(binaryfunc)0, /* nb_lshift */
(binaryfunc)0, /* nb_rshift */
bucket_and, /* nb_and */
(binaryfunc)Generic_set_xor, /* nb_xor */
bucket_or, /* nb_or */
0, /*nb_int*/
0, /*nb_reserved*/
0, /*nb_float*/
0, /*nb_inplace_add*/
(binaryfunc)set_isub, /*nb_inplace_subtract*/
0, /*nb_inplace_multiply*/
0, /*nb_inplace_remainder*/
0, /*nb_inplace_power*/
0, /*nb_inplace_lshift*/
0, /*nb_inplace_rshift*/
(binaryfunc)set_iand, /*nb_inplace_and*/
(binaryfunc)set_ixor, /*nb_inplace_xor*/
(binaryfunc)set_ior, /*nb_inplace_or*/
static PySequenceMethods Set_as_sequence = {
.sq_length = (lenfunc)set_length,
.sq_item = (ssizeargfunc)set_item,
.sq_contains = (objobjproc)bucket_contains,
};

static PyTypeObject SetType = {
static PyTypeObject Set_type_def = {
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 */
&set_as_number, /* 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 */
.tp_name = Set__name__,
.tp_doc = Set__doc__,
.tp_basicsize = sizeof(Bucket),
.tp_flags = Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE,
.tp_alloc = _pytype_generic_alloc,
.tp_new = _pytype_generic_new,
.tp_init = Set_init,
.tp_repr = (reprfunc)set_repr,
.tp_iter = (getiterfunc)Bucket_getiter,
.tp_traverse = (traverseproc)bucket_traverse,
.tp_clear = (inquiry)bucket_tp_clear,
.tp_dealloc = (destructor)bucket_dealloc,
.tp_methods = Set_methods,
.tp_members = Bucket_members,
.tp_as_number = &Set_as_number,
.tp_as_sequence = &Set_as_sequence,
};

#else

static PyType_Slot Set_type_slots[] = {
{Py_tp_doc, Set__doc__},
{Py_tp_alloc, _pytype_generic_alloc},
{Py_tp_new, _pytype_generic_new},
{Py_tp_init, Set_init},
{Py_tp_repr, (reprfunc)set_repr},
{Py_tp_iter, (getiterfunc)Bucket_getiter},
{Py_tp_traverse, (traverseproc)bucket_traverse},
{Py_tp_clear, (inquiry)bucket_tp_clear},
{Py_tp_dealloc, (destructor)bucket_dealloc},
{Py_tp_methods, Set_methods},
{Py_tp_members, Bucket_members},
{Py_nb_subtract, bucket_sub},
{Py_nb_and, bucket_and},
{Py_nb_xor, (binaryfunc)Generic_set_xor},
{Py_nb_or, bucket_or},
{Py_nb_inplace_subtract, (binaryfunc)set_isub},
{Py_nb_inplace_and, (binaryfunc)set_iand},
{Py_nb_inplace_xor, (binaryfunc)set_ixor},
{Py_nb_inplace_or, (binaryfunc)set_ior},
{Py_sq_length, (lenfunc)set_length},
{Py_sq_item, (ssizeargfunc)set_item},
{Py_sq_contains, (objobjproc)bucket_contains},
{0, NULL}
};

static PyType_Spec Set_type_spec = {
.name = Set__name__,
.basicsize = sizeof(Bucket),
.flags = Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE |
Py_TPFLAGS_BASETYPE,
.slots = Set_type_slots
};

#endif

static int
nextSet(SetIteration *i)
{
PyObject* obj_self = i->set;
PerCAPI* per_capi = _get_per_capi(obj_self);

if (i->position >= 0)
{
UNLESS(PER_USE(BUCKET(i->set)))
UNLESS(per_use((cPersistentObject*)BUCKET(i->set), per_capi))
return -1;

if (i->position)
Expand All @@ -767,10 +778,10 @@ nextSet(SetIteration *i)
else
{
i->position = -1;
PER_ACCESSED(BUCKET(i->set));
per_capi->accessed((cPersistentObject*)BUCKET(i->set));
}

PER_ALLOW_DEACTIVATION(BUCKET(i->set));
per_allow_deactivation((cPersistentObject*)BUCKET(i->set));
}


Expand Down
Loading
Loading