zope.hookable 6.0__cp39-cp39-win_amd64.whl → 8.0__cp39-cp39-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of zope.hookable might be problematic. Click here for more details.

@@ -1,264 +1,285 @@
1
- /*############################################################################
2
- #
3
- # Copyright (c) 2003 Zope Foundation and Contributors.
4
- # All Rights Reserved.
5
- #
6
- # This software is subject to the provisions of the Zope Public License,
7
- # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
- # FOR A PARTICULAR PURPOSE.
12
- #
13
- ############################################################################*/
14
-
15
- /* _zope_hookable.c
16
-
17
- Provide an efficient implementation for hookable objects
18
-
19
- */
20
-
21
- #include "Python.h"
22
- #include "structmember.h"
23
-
24
- typedef struct {
25
- PyObject_HEAD
26
- PyObject *old;
27
- PyObject *implementation;
28
- } hookable;
29
-
30
- static int
31
- hookable_init(hookable *self, PyObject *args, PyObject *kwds)
32
- {
33
- static char *kwlist[] = {"implementation", NULL};
34
- PyObject *implementation;
35
-
36
- if (! PyArg_ParseTupleAndKeywords(args, kwds, "O:hookable", kwlist,
37
- &implementation))
38
- return -1;
39
-
40
- Py_INCREF(implementation);
41
- Py_INCREF(implementation);
42
- Py_XDECREF(self->old);
43
- self->old = implementation;
44
- Py_XDECREF(self->implementation);
45
- self->implementation = implementation;
46
-
47
- return 0;
48
- }
49
-
50
- static int
51
- hookable_traverse(hookable *self, visitproc visit, void *arg)
52
- {
53
- if (self->implementation != NULL && visit(self->implementation, arg) < 0)
54
- return -1;
55
- if (self->old != NULL
56
- && self->old != self->implementation
57
- && visit(self->old, arg) < 0
58
- )
59
- return -1;
60
-
61
- return 0;
62
- }
63
-
64
- static int
65
- hookable_clear(hookable *self)
66
- {
67
- Py_XDECREF(self->old);
68
- self->old = NULL;
69
- Py_XDECREF(self->implementation);
70
- self->implementation = NULL;
71
- return 0;
72
- }
73
-
74
-
75
- static void
76
- hookable_dealloc(hookable *self)
77
- {
78
- PyObject_GC_UnTrack((PyObject *)self);
79
- Py_XDECREF(self->old);
80
- Py_XDECREF(self->implementation);
81
- Py_TYPE(self)->tp_free((PyObject*)self);
82
- }
83
-
84
- static PyObject *
85
- hookable_sethook(hookable *self, PyObject *implementation)
86
- {
87
- PyObject *old;
88
-
89
- old = self->implementation;
90
- Py_INCREF(implementation);
91
- self->implementation = implementation;
92
-
93
- if (old == NULL)
94
- {
95
- Py_INCREF(Py_None);
96
- return Py_None;
97
- }
98
-
99
- return old;
100
- }
101
-
102
- static PyObject *
103
- hookable_reset(hookable *self)
104
- {
105
- Py_XINCREF(self->old);
106
- Py_XDECREF(self->implementation);
107
- self->implementation = self->old;
108
- Py_INCREF(Py_None);
109
- return Py_None;
110
- }
111
-
112
- static struct PyMethodDef hookable_methods[] = {
113
- {"sethook", (PyCFunction)hookable_sethook, METH_O,
114
- "Set the hook implementation for the hookable object"},
115
- {"reset", (PyCFunction)hookable_reset, METH_NOARGS,
116
- "Reset the hook to the original value"},
117
- {NULL, NULL} /* sentinel */
118
- };
119
-
120
-
121
- static PyObject *
122
- hookable_call(hookable *self, PyObject *args, PyObject *kw)
123
- {
124
- if (self->implementation != NULL)
125
- return PyObject_Call(self->implementation, args, kw);
126
- PyErr_SetString(PyExc_TypeError, "Hookable has no implementation");
127
- return NULL;
128
- }
129
-
130
-
131
- static PyObject *
132
- hookable_getattro(hookable *self, PyObject *name)
133
- {
134
- PyObject *result = NULL;
135
- const char *name_as_string;
136
- int maybe_special_name;
137
-
138
- name_as_string = PyUnicode_AsUTF8(name);
139
-
140
- if (name_as_string == NULL) {
141
- return NULL;
142
- }
143
-
144
- maybe_special_name = name_as_string[0] == '_' && name_as_string[1] == '_';
145
-
146
- if (maybe_special_name) {
147
- /* pass through __doc__ to the original implementation */
148
- if (strcmp("__doc__", name_as_string) == 0) {
149
- return PyObject_GetAttr(self->old, name);
150
- }
151
- /* synthesize __base__ and __dict__ if the original fails */
152
- if (strcmp("__bases__", name_as_string) == 0) {
153
- result = PyObject_GetAttr(self->old, name);
154
- if (result == NULL) {
155
- PyErr_Clear();
156
- result = PyTuple_New(0);
157
- }
158
- return result;
159
- }
160
- if (strcmp("__dict__", name_as_string) == 0) {
161
- result = PyObject_GetAttr(self->old, name);
162
- if (result == NULL) {
163
- PyErr_Clear();
164
- result = PyDict_New();
165
- }
166
- return result;
167
- }
168
- }
169
-
170
- return PyObject_GenericGetAttr((PyObject*)self, name);
171
- }
172
-
173
- static PyMemberDef hookable_members[] = {
174
- { "original", T_OBJECT_EX, offsetof(hookable, old), READONLY },
175
- { "implementation", T_OBJECT_EX, offsetof(hookable, implementation), READONLY },
176
- {NULL} /* Sentinel */
177
- };
178
-
179
-
180
- static char Hookabletype__doc__[] =
181
- "Callable objects that support being overridden"
182
- ;
183
-
184
- static PyTypeObject hookabletype = {
185
- PyVarObject_HEAD_INIT(NULL, 0)
186
- /* tp_name */ "zope.hookable."
187
- "hookable",
188
- /* tp_basicsize */ sizeof(hookable),
189
- /* tp_itemsize */ 0,
190
- /* tp_dealloc */ (destructor)&hookable_dealloc,
191
- /* tp_print */ (printfunc)0,
192
- /* tp_getattr */ (getattrfunc)0,
193
- /* tp_setattr */ (setattrfunc)0,
194
- /* tp_compare */ 0,
195
- /* tp_repr */ (reprfunc)0,
196
- /* tp_as_number */ 0,
197
- /* tp_as_sequence */ 0,
198
- /* tp_as_mapping */ 0,
199
- /* tp_hash */ (hashfunc)0,
200
- /* tp_call */ (ternaryfunc)hookable_call,
201
- /* tp_str */ (reprfunc)0,
202
- /* tp_getattro */ (getattrofunc)hookable_getattro,
203
- /* tp_setattro */ (setattrofunc)0,
204
- /* tp_as_buffer */ 0,
205
- /* tp_flags */ Py_TPFLAGS_DEFAULT
206
- | Py_TPFLAGS_BASETYPE
207
- | Py_TPFLAGS_HAVE_GC,
208
- /* tp_doc */ Hookabletype__doc__,
209
- /* tp_traverse */ (traverseproc)hookable_traverse,
210
- /* tp_clear */ (inquiry)hookable_clear,
211
- /* tp_richcompare */ (richcmpfunc)0,
212
- /* tp_weaklistoffset */ (long)0,
213
- /* tp_iter */ (getiterfunc)0,
214
- /* tp_iternext */ (iternextfunc)0,
215
- /* tp_methods */ hookable_methods,
216
- /* tp_members */ hookable_members,
217
- /* tp_getset */ 0,
218
- /* tp_base */ 0,
219
- /* tp_dict */ 0, /* internal use */
220
- /* tp_descr_get */ (descrgetfunc)0,
221
- /* tp_descr_set */ (descrsetfunc)0,
222
- /* tp_dictoffset */ 0,
223
- /* tp_init */ (initproc)hookable_init,
224
- /* tp_alloc */ (allocfunc)0,
225
- /* tp_new */ (newfunc)0 /*PyType_GenericNew*/,
226
- /* tp_free */ 0/*PyObject_GC_Del*/,
227
- };
228
-
229
-
230
- #define MOD_ERROR_VAL NULL
231
- #define MOD_SUCCESS_VAL(val) val
232
- #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
233
- #define MOD_DEF(ob, name, doc, methods) \
234
- static struct PyModuleDef moduledef = { \
235
- PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \
236
- ob = PyModule_Create(&moduledef);
237
-
238
- static struct PyMethodDef module_methods[] = {
239
- {NULL, NULL}
240
- };
241
-
242
- MOD_INIT(_zope_hookable)
243
- {
244
- PyObject *m;
245
-
246
- MOD_DEF(m, "_zope_hookable",
247
- "Provide an efficient implementation for hookable objects",
248
- module_methods)
249
-
250
- if (m == NULL)
251
- return MOD_ERROR_VAL;
252
-
253
- hookabletype.tp_new = PyType_GenericNew;
254
- hookabletype.tp_free = PyObject_GC_Del;
255
-
256
- if (PyType_Ready(&hookabletype) < 0)
257
- return MOD_ERROR_VAL;
258
-
259
- if (PyModule_AddObject(m, "hookable", (PyObject *)&hookabletype) < 0)
260
- return MOD_ERROR_VAL;
261
-
262
- return MOD_SUCCESS_VAL(m);
263
-
264
- }
1
+ /*############################################################################
2
+ #
3
+ # Copyright (c) 2003 Zope Foundation and Contributors.
4
+ # All Rights Reserved.
5
+ #
6
+ # This software is subject to the provisions of the Zope Public License,
7
+ # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8
+ # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
+ # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
+ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
+ # FOR A PARTICULAR PURPOSE.
12
+ #
13
+ ############################################################################*/
14
+
15
+ static char module__doc__[] = (
16
+ "Provide an efficient implementation for hookable objects"
17
+ );
18
+
19
+ #include "Python.h"
20
+ #include "structmember.h"
21
+
22
+ typedef struct
23
+ {
24
+ PyObject_HEAD
25
+ PyObject* original;
26
+ PyObject* implementation;
27
+ } hookable;
28
+
29
+ static int
30
+ hookable_init(hookable* self, PyObject* args, PyObject* kwds)
31
+ {
32
+ static char* kwlist[] = { "implementation", NULL };
33
+ PyObject* implementation;
34
+
35
+ if (!PyArg_ParseTupleAndKeywords(
36
+ args, kwds, "O:hookable", kwlist, &implementation))
37
+ return -1;
38
+
39
+ /* Both 'self->original' and 'self->implementation' are originally
40
+ * set to the passed-in 'implementation', hence the need for
41
+ * two increfs.
42
+ */
43
+ Py_INCREF(implementation);
44
+ Py_XDECREF(self->original);
45
+ self->original = implementation;
46
+
47
+ Py_INCREF(implementation);
48
+ Py_XDECREF(self->implementation);
49
+ self->implementation = implementation;
50
+
51
+ return 0;
52
+ }
53
+
54
+ static int
55
+ hookable_traverse(hookable* self, visitproc visit, void* arg)
56
+ {
57
+ #if PY_VERSION_HEX >= 0x03090000
58
+ Py_VISIT(Py_TYPE(self));
59
+ #endif
60
+ Py_VISIT(self->implementation);
61
+ Py_VISIT(self->original);
62
+ return 0;
63
+ }
64
+
65
+ static int
66
+ hookable_clear(hookable* self)
67
+ {
68
+ Py_XDECREF(self->original);
69
+ self->original = NULL;
70
+
71
+ Py_XDECREF(self->implementation);
72
+ self->implementation = NULL;
73
+
74
+ return 0;
75
+ }
76
+
77
+ static void
78
+ hookable_dealloc(hookable* self)
79
+ {
80
+ PyObject_GC_UnTrack((PyObject*)self);
81
+ PyTypeObject* tp = Py_TYPE(self);
82
+
83
+ Py_XDECREF(self->original);
84
+ Py_XDECREF(self->implementation);
85
+
86
+ tp->tp_free((PyObject*)self);
87
+
88
+ /* heap types must decref their type when dealloc'ed */
89
+ Py_DECREF(tp);
90
+ }
91
+
92
+ static PyObject*
93
+ hookable_call(hookable* self, PyObject* args, PyObject* kw)
94
+ {
95
+ if (self->implementation != NULL)
96
+ return PyObject_Call(self->implementation, args, kw);
97
+
98
+ PyErr_SetString(PyExc_TypeError, "Hookable has no implementation");
99
+ return NULL;
100
+ }
101
+
102
+ static PyObject*
103
+ hookable_getattro(hookable* self, PyObject* name)
104
+ {
105
+ PyObject* result = NULL;
106
+ const char* name_as_string;
107
+ int maybe_special_name;
108
+
109
+ name_as_string = PyUnicode_AsUTF8(name);
110
+ if (name_as_string == NULL) { return NULL; }
111
+
112
+ maybe_special_name = name_as_string[0] == '_' && name_as_string[1] == '_';
113
+
114
+ if (maybe_special_name) {
115
+ /* pass through __doc__ to the original implementation */
116
+ if (strcmp("__doc__", name_as_string) == 0) {
117
+ return PyObject_GetAttr(self->original, name);
118
+ }
119
+ /* synthesize __bases__ and __dict__ if the original fails */
120
+ if (strcmp("__bases__", name_as_string) == 0) {
121
+ result = PyObject_GetAttr(self->original, name);
122
+ if (result == NULL) {
123
+ PyErr_Clear();
124
+ result = PyTuple_New(0);
125
+ }
126
+ return result;
127
+ }
128
+ if (strcmp("__dict__", name_as_string) == 0) {
129
+ result = PyObject_GetAttr(self->original, name);
130
+ if (result == NULL) {
131
+ PyErr_Clear();
132
+ result = PyDict_New();
133
+ }
134
+ return result;
135
+ }
136
+ }
137
+
138
+ return PyObject_GenericGetAttr((PyObject*)self, name);
139
+ }
140
+
141
+ static char hookable_sethook__doc__[] = (
142
+ "Set the hook implementation for the hookable object\n\n"
143
+ "Return the previous hook implementation, or None."
144
+ );
145
+
146
+ static PyObject*
147
+ hookable_sethook(hookable* self, PyObject* implementation)
148
+ {
149
+ PyObject* current;
150
+
151
+ current = self->implementation;
152
+ Py_INCREF(implementation);
153
+ self->implementation = implementation;
154
+
155
+ if (current == NULL) {
156
+ Py_INCREF(Py_None);
157
+ return Py_None;
158
+ }
159
+
160
+ return current;
161
+ }
162
+
163
+ static char hookable_reset__doc__[] = (
164
+ "Reset the hook to the original value"
165
+ );
166
+
167
+ static PyObject*
168
+ hookable_reset(hookable* self)
169
+ {
170
+ Py_XINCREF(self->original);
171
+ Py_XDECREF(self->implementation);
172
+
173
+ self->implementation = self->original;
174
+
175
+ Py_INCREF(Py_None);
176
+ return Py_None;
177
+ }
178
+
179
+ static struct PyMethodDef hookable_methods[] = {
180
+ { "sethook",
181
+ (PyCFunction)hookable_sethook, METH_O, hookable_sethook__doc__ },
182
+ { "reset",
183
+ (PyCFunction)hookable_reset, METH_NOARGS, hookable_reset__doc__},
184
+ { NULL, NULL } /* sentinel */
185
+ };
186
+
187
+ static PyMemberDef hookable_members[] = {
188
+ { "original",
189
+ T_OBJECT_EX, offsetof(hookable, original), READONLY },
190
+ { "implementation",
191
+ T_OBJECT_EX, offsetof(hookable, implementation), READONLY },
192
+ { NULL } /* Sentinel */
193
+ };
194
+
195
+ static char hookable__name__[] = "zope.hookable.hookable";
196
+ static char hookable__doc__[] =
197
+ "Callable objects that support being overridden";
198
+
199
+
200
+ /*
201
+ * Heap type: hookable
202
+ */
203
+ static PyType_Slot hookable_type_slots[] = {
204
+ {Py_tp_doc, hookable__doc__},
205
+ {Py_tp_init, hookable_init},
206
+ {Py_tp_call, hookable_call},
207
+ {Py_tp_getattro, hookable_getattro},
208
+ {Py_tp_traverse, hookable_traverse},
209
+ {Py_tp_clear, hookable_clear},
210
+ {Py_tp_dealloc, hookable_dealloc},
211
+ {Py_tp_members, hookable_members},
212
+ {Py_tp_methods, hookable_methods},
213
+ {0, NULL}
214
+ };
215
+
216
+ static PyType_Spec hookable_type_spec = {
217
+ .name = hookable__name__,
218
+ .basicsize = sizeof(hookable),
219
+ .flags = Py_TPFLAGS_DEFAULT |
220
+ Py_TPFLAGS_BASETYPE |
221
+ #if PY_VERSION_HEX >= 0x030c0000
222
+ Py_TPFLAGS_MANAGED_WEAKREF |
223
+ #endif
224
+ Py_TPFLAGS_HAVE_GC,
225
+ .slots = hookable_type_slots
226
+ };
227
+
228
+ /*
229
+ * Module initialization
230
+ */
231
+
232
+ static struct PyMethodDef hookable_module_methods[] = {
233
+ { NULL, NULL } /* sentinel */
234
+ };
235
+
236
+
237
+ /* Handler for the 'execute' phase of multi-phase initialization
238
+ *
239
+ * See: https://docs.python.org/3/c-api/module.html#multi-phase-initialization
240
+ * and: https://peps.python.org/pep-0489/#module-execution-phase
241
+ */
242
+ static int
243
+ hookable_module_exec(PyObject* module)
244
+ {
245
+ PyObject* hookable_type;
246
+
247
+ hookable_type = PyType_FromSpec(&hookable_type_spec);
248
+ if (hookable_type == NULL) { return -1; }
249
+
250
+ if (PyModule_AddObject(module, "hookable", hookable_type) < 0)
251
+ return -1;
252
+
253
+ return 0;
254
+ }
255
+
256
+
257
+ /* Slot definitions for multi-phase initialization
258
+ *
259
+ * See: https://docs.python.org/3/c-api/module.html#multi-phase-initialization
260
+ * and: https://peps.python.org/pep-0489
261
+ */
262
+ static PyModuleDef_Slot hookable_module_slots[] = {
263
+ {Py_mod_exec, hookable_module_exec},
264
+ {0, NULL}
265
+ };
266
+
267
+ static struct PyModuleDef hookable_module_def = {
268
+ PyModuleDef_HEAD_INIT,
269
+ .m_name = "_zope_hookable",
270
+ .m_doc = module__doc__,
271
+ .m_methods = hookable_module_methods,
272
+ .m_slots = hookable_module_slots
273
+ };
274
+
275
+ static PyObject*
276
+ init(void)
277
+ {
278
+ return PyModuleDef_Init(&hookable_module_def);
279
+ }
280
+
281
+ PyMODINIT_FUNC
282
+ PyInit__zope_hookable(void)
283
+ {
284
+ return init();
285
+ }
@@ -1 +1 @@
1
- # This line required to prevent an empty file.
1
+ # This line required to prevent an empty file.
@@ -1,29 +1,29 @@
1
- ##############################################################################
2
- #
3
- # Copyright (c) 2022 Zope Foundation and Contributors.
4
- # All Rights Reserved.
5
- #
6
- # This software is subject to the provisions of the Zope Public License,
7
- # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8
- # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
- # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
- # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
- # FOR A PARTICULAR PURPOSE
12
- #
13
- ##############################################################################
14
- import struct
15
- import unittest
16
-
17
- import zope.hookable # noqa: try to load a C module for side effects
18
-
19
-
20
- class TestFloatingPoint(unittest.TestCase):
21
-
22
- def test_no_fast_math_optimization(self):
23
- # Building with -Ofast enables -ffast-math, which sets certain FPU
24
- # flags that can cause breakage elsewhere. A library such as BTrees
25
- # has no business changing global FPU flags for the entire process.
26
- zero_bits = struct.unpack("!Q", struct.pack("!d", 0.0))[0]
27
- next_up = zero_bits + 1
28
- smallest_subnormal = struct.unpack("!d", struct.pack("!Q", next_up))[0]
29
- self.assertNotEqual(smallest_subnormal, 0.0)
1
+ ##############################################################################
2
+ #
3
+ # Copyright (c) 2022 Zope Foundation and Contributors.
4
+ # All Rights Reserved.
5
+ #
6
+ # This software is subject to the provisions of the Zope Public License,
7
+ # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8
+ # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
+ # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
+ # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
+ # FOR A PARTICULAR PURPOSE
12
+ #
13
+ ##############################################################################
14
+ import struct
15
+ import unittest
16
+
17
+ import zope.hookable # noqa: try to load a C module for side effects
18
+
19
+
20
+ class TestFloatingPoint(unittest.TestCase):
21
+
22
+ def test_no_fast_math_optimization(self):
23
+ # Building with -Ofast enables -ffast-math, which sets certain FPU
24
+ # flags that can cause breakage elsewhere. A library such as BTrees
25
+ # has no business changing global FPU flags for the entire process.
26
+ zero_bits = struct.unpack("!Q", struct.pack("!d", 0.0))[0]
27
+ next_up = zero_bits + 1
28
+ smallest_subnormal = struct.unpack("!d", struct.pack("!Q", next_up))[0]
29
+ self.assertNotEqual(smallest_subnormal, 0.0)