zope.hookable 6.0__cp312-cp312-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.

@@ -0,0 +1,75 @@
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
+ """Hookable object support
15
+ """
16
+ import os
17
+ import platform
18
+
19
+
20
+ _PYPY = platform.python_implementation() in ('PyPy', 'Jython')
21
+ _PURE_PYTHON = os.environ.get('PURE_PYTHON', _PYPY)
22
+
23
+
24
+ class _py_hookable:
25
+ __slots__ = ('_original', '_implementation')
26
+
27
+ def __init__(self, *args, **kw):
28
+ if not args and 'implementation' in kw:
29
+ args = (kw.pop('implementation'),)
30
+ if kw:
31
+ raise TypeError('Unknown keyword arguments')
32
+ if len(args) != 1:
33
+ raise TypeError('Exactly one argument required')
34
+ self._original = self._implementation = args[0]
35
+
36
+ @property
37
+ def original(self):
38
+ return self._original
39
+
40
+ @property
41
+ def implementation(self):
42
+ return self._implementation
43
+
44
+ @property
45
+ def __doc__(self):
46
+ return self._original.__doc__
47
+
48
+ @property
49
+ def __dict__(self):
50
+ return getattr(self._original, '__dict__', {})
51
+
52
+ @property
53
+ def __bases__(self):
54
+ return getattr(self._original, '__bases__', ())
55
+
56
+ def sethook(self, new_callable):
57
+ old, self._implementation = self._implementation, new_callable
58
+ return old
59
+
60
+ def reset(self):
61
+ self._implementation = self._original
62
+
63
+ def __call__(self, *args, **kw):
64
+ return self._implementation(*args, **kw)
65
+
66
+
67
+ try:
68
+ from zope.hookable._zope_hookable import hookable as _c_hookable
69
+ except ImportError: # pragma: no cover
70
+ _c_hookable = None
71
+
72
+ if _PURE_PYTHON or _c_hookable is None:
73
+ hookable = _py_hookable
74
+ else: # pragma: no cover
75
+ hookable = _c_hookable
@@ -0,0 +1,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
+ /* _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
+ }
@@ -0,0 +1 @@
1
+ # This line required to prevent an empty file.
@@ -0,0 +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)
@@ -0,0 +1,198 @@
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
+ """Test the hookable support Extension
15
+ """
16
+ import unittest
17
+
18
+
19
+ def return_foo():
20
+ return 'FOO'
21
+
22
+
23
+ def return_bar():
24
+ return 'BAR'
25
+
26
+
27
+ def not_called():
28
+ raise AssertionError("This should not be called")
29
+
30
+
31
+ class PyHookableMixin:
32
+
33
+ def _callFUT(self, *args, **kw):
34
+ from zope.hookable import _py_hookable
35
+ return _py_hookable(*args, **kw)
36
+
37
+
38
+ class HookableMixin:
39
+
40
+ def _callFUT(self, *args, **kw):
41
+ from zope.hookable import _py_hookable
42
+ from zope.hookable import hookable
43
+ if hookable is _py_hookable:
44
+ raise unittest.SkipTest("Hookable and PyHookable are the same")
45
+ return hookable(*args, **kw) # pragma: no cover
46
+
47
+
48
+ class PyHookableTests(PyHookableMixin,
49
+ unittest.TestCase):
50
+
51
+ def test_pure_python(self):
52
+ from zope.hookable import _PURE_PYTHON
53
+ from zope.hookable import _c_hookable
54
+ from zope.hookable import _py_hookable
55
+ from zope.hookable import hookable
56
+ self.assertIs(hookable, _py_hookable if _PURE_PYTHON else _c_hookable)
57
+
58
+ def test_before_hook(self):
59
+ hooked = self._callFUT(return_foo)
60
+ self.assertIs(hooked.original, return_foo)
61
+ self.assertIs(hooked.implementation, return_foo)
62
+ self.assertEqual(hooked(), 'FOO')
63
+
64
+ def test_after_hook(self):
65
+ hooked = self._callFUT(not_called)
66
+ old = hooked.sethook(return_bar)
67
+ self.assertIs(old, not_called)
68
+ self.assertIs(hooked.original, not_called)
69
+ self.assertIs(hooked.implementation, return_bar)
70
+ self.assertEqual(hooked(), 'BAR')
71
+
72
+ def test_after_hook_and_reset(self):
73
+ hooked = self._callFUT(return_foo)
74
+ old = hooked.sethook(not_called)
75
+ hooked.reset()
76
+ self.assertIs(old, return_foo)
77
+ self.assertIs(hooked.original, return_foo)
78
+ self.assertIs(hooked.implementation, return_foo)
79
+ self.assertEqual(hooked(), 'FOO')
80
+
81
+ def test_original_cannot_be_deleted(self):
82
+ hooked = self._callFUT(not_called)
83
+ with self.assertRaises((TypeError, AttributeError)):
84
+ del hooked.original
85
+
86
+ def test_implementation_cannot_be_deleted(self):
87
+ hooked = self._callFUT(not_called)
88
+ with self.assertRaises((TypeError, AttributeError)):
89
+ del hooked.implementation
90
+
91
+ def test_no_args(self):
92
+ with self.assertRaises(TypeError):
93
+ self._callFUT()
94
+
95
+ def test_too_many_args(self):
96
+ with self.assertRaises(TypeError):
97
+ self._callFUT(not_called, not_called)
98
+
99
+ def test_w_implementation_kwarg(self):
100
+ hooked = self._callFUT(implementation=return_foo)
101
+ self.assertIs(hooked.original, return_foo)
102
+ self.assertIs(hooked.implementation, return_foo)
103
+ self.assertEqual(hooked(), 'FOO')
104
+
105
+ def test_w_unknown_kwarg(self):
106
+ with self.assertRaises(TypeError):
107
+ self._callFUT(nonesuch=42)
108
+
109
+ def test_class(self):
110
+ class C:
111
+ pass
112
+
113
+ hooked = self._callFUT(C)
114
+ self.assertIsInstance(hooked(), C)
115
+
116
+ hooked.sethook(return_bar)
117
+ self.assertEqual(hooked(), 'BAR')
118
+
119
+
120
+ class TestIssue6Py(PyHookableMixin,
121
+ unittest.TestCase):
122
+ # Make sphinx docs for hooked objects work.
123
+ # https://github.com/zopefoundation/zope.hookable/issues/6
124
+ # We need to proxy __doc__ to the original,
125
+ # and synthesize an empty __bases__ and a __dict__ attribute
126
+ # if they're not present.
127
+
128
+ def _check_preserves_doc(self, docs):
129
+ self.assertEqual("I have some docs", docs.__doc__)
130
+
131
+ hooked = self._callFUT(docs)
132
+ self.assertEqual(hooked.__doc__, docs.__doc__)
133
+
134
+ def test_preserves_doc_function(self):
135
+ def docs():
136
+ """I have some docs"""
137
+ self._check_preserves_doc(docs)
138
+
139
+ def test_preserves_doc_class(self):
140
+ class Docs:
141
+ """I have some docs"""
142
+
143
+ self._check_preserves_doc(Docs)
144
+
145
+ def test_empty_bases_function(self):
146
+ hooked = self._callFUT(return_foo)
147
+ self.assertEqual((), hooked.__bases__)
148
+
149
+ def test_empty_dict_function(self):
150
+ hooked = self._callFUT(return_foo)
151
+ self.assertEqual({}, hooked.__dict__)
152
+
153
+ def test_bases_class(self):
154
+ class C:
155
+ pass
156
+ self.assertEqual(C.__bases__, (object,))
157
+ hooked = self._callFUT(C)
158
+ self.assertEqual(hooked.__bases__, (object,))
159
+
160
+ def test_dict_class(self):
161
+ class C:
162
+ pass
163
+
164
+ hooked = self._callFUT(C)
165
+ self.assertEqual(hooked.__dict__, C.__dict__)
166
+
167
+ def test_non_string_attr_name(self):
168
+ # Specifically for the C implementation, which has to deal with this
169
+ hooked = self._callFUT(return_foo)
170
+ with self.assertRaises(TypeError):
171
+ getattr(hooked, 42)
172
+
173
+ with self.assertRaises(TypeError):
174
+ hooked.__getattribute__(42)
175
+
176
+ def test_unicode_attribute_name(self):
177
+ # Specifically for the C implementation, which has to deal with this
178
+ hooked = self._callFUT(return_foo)
179
+ result = hooked.__getattribute__('__bases__')
180
+ self.assertEqual(result, ())
181
+
182
+ def test_short_name(self):
183
+ # Specifically for the C implementation, which has to deal with this
184
+ hooked = self._callFUT(return_foo)
185
+ with self.assertRaises(AttributeError):
186
+ hooked.__getattribute__('')
187
+
188
+
189
+ class HookableTests(HookableMixin, PyHookableTests):
190
+ pass
191
+
192
+
193
+ class TestIssue6(HookableMixin, TestIssue6Py):
194
+ pass
195
+
196
+
197
+ def test_suite():
198
+ return unittest.defaultTestLoader.loadTestsFromName(__name__)
@@ -0,0 +1 @@
1
+ import sys, types, os;has_mfs = sys.version_info > (3, 5);p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('zope',));importlib = has_mfs and __import__('importlib.util');has_mfs and __import__('importlib.machinery');m = has_mfs and sys.modules.setdefault('zope', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('zope', [os.path.dirname(p)])));m = m or sys.modules.setdefault('zope', types.ModuleType('zope'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)
@@ -0,0 +1,44 @@
1
+ Zope Public License (ZPL) Version 2.1
2
+
3
+ A copyright notice accompanies this license document that identifies the
4
+ copyright holders.
5
+
6
+ This license has been certified as open source. It has also been designated as
7
+ GPL compatible by the Free Software Foundation (FSF).
8
+
9
+ Redistribution and use in source and binary forms, with or without
10
+ modification, are permitted provided that the following conditions are met:
11
+
12
+ 1. Redistributions in source code must retain the accompanying copyright
13
+ notice, this list of conditions, and the following disclaimer.
14
+
15
+ 2. Redistributions in binary form must reproduce the accompanying copyright
16
+ notice, this list of conditions, and the following disclaimer in the
17
+ documentation and/or other materials provided with the distribution.
18
+
19
+ 3. Names of the copyright holders must not be used to endorse or promote
20
+ products derived from this software without prior written permission from the
21
+ copyright holders.
22
+
23
+ 4. The right to distribute this software or to use it for any purpose does not
24
+ give you the right to use Servicemarks (sm) or Trademarks (tm) of the
25
+ copyright
26
+ holders. Use of them is covered by separate agreement with the copyright
27
+ holders.
28
+
29
+ 5. If any files are modified, you must cause the modified files to carry
30
+ prominent notices stating that you changed the files and the date of any
31
+ change.
32
+
33
+ Disclaimer
34
+
35
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED
36
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
38
+ EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
39
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
40
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
42
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
44
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,210 @@
1
+ Metadata-Version: 2.1
2
+ Name: zope.hookable
3
+ Version: 6.0
4
+ Summary: Zope hookable
5
+ Home-page: http://github.com/zopefoundation/zope.hookable
6
+ Author: Zope Foundation and Contributors
7
+ Author-email: zope-dev@zope.org
8
+ License: ZPL 2.1
9
+ Keywords: function hook replacement loose coupled
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Zope Public License
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Programming Language :: Python
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.7
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: Implementation :: CPython
23
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
24
+ Classifier: Framework :: Zope :: 3
25
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
26
+ Requires-Python: >=3.7
27
+ License-File: LICENSE.txt
28
+ Requires-Dist: setuptools
29
+ Provides-Extra: docs
30
+ Requires-Dist: Sphinx ; extra == 'docs'
31
+ Requires-Dist: sphinx-rtd-theme ; extra == 'docs'
32
+ Provides-Extra: test
33
+ Requires-Dist: zope.testing ; extra == 'test'
34
+ Requires-Dist: zope.testrunner ; extra == 'test'
35
+ Provides-Extra: testing
36
+ Requires-Dist: zope.testing ; extra == 'testing'
37
+ Requires-Dist: zope.testrunner ; extra == 'testing'
38
+ Requires-Dist: coverage ; extra == 'testing'
39
+
40
+ ===============
41
+ zope.hookable
42
+ ===============
43
+
44
+ .. image:: https://img.shields.io/pypi/v/zope.hookable.svg
45
+ :target: https://pypi.python.org/pypi/zope.hookable/
46
+ :alt: Latest release
47
+
48
+ .. image:: https://img.shields.io/pypi/pyversions/zope.hookable.svg
49
+ :target: https://pypi.org/project/zope.hookable/
50
+ :alt: Supported Python versions
51
+
52
+ .. image:: https://github.com/zopefoundation/zope.hookable/actions/workflows/tests.yml/badge.svg
53
+ :target: https://github.com/zopefoundation/zope.hookable/actions/workflows/tests.yml
54
+
55
+ .. image:: https://readthedocs.org/projects/zopehookable/badge/?version=latest
56
+ :target: https://zopehookable.readthedocs.io/en/latest/
57
+ :alt: Documentation Status
58
+
59
+ .. image:: https://coveralls.io/repos/github/zopefoundation/zope.hookable/badge.svg?branch=master
60
+ :target: https://coveralls.io/github/zopefoundation/zope.hookable?branch=master
61
+
62
+
63
+ This package supports the efficient creation of "hookable" objects, which
64
+ are callable objects that are meant to be optionally replaced.
65
+
66
+ The idea is that you create a function that does some default thing and make it
67
+ hookable. Later, someone can modify what it does by calling its sethook method
68
+ and changing its implementation. All users of the function, including those
69
+ that imported it, will see the change.
70
+
71
+ Documentation is hosted at https://zopehookable.readthedocs.io
72
+
73
+
74
+ =========
75
+ Changes
76
+ =========
77
+
78
+ 6.0 (2023-10-05)
79
+ ================
80
+
81
+ - Drop support for Python 2.7, 3.5, 3.6.
82
+
83
+ - Add support for Python 3.12.
84
+
85
+
86
+ 5.4 (2022-11-17)
87
+ ================
88
+
89
+ - Add support for building arm64 wheels on macOS.
90
+
91
+
92
+ 5.3 (2022-11-03)
93
+ ================
94
+
95
+ - Add support for the final release of Python 3.11.
96
+
97
+
98
+ 5.2 (2022-09-13)
99
+ ================
100
+
101
+ - Add support for Python 3.10 and 3.11 (as of 3.11.0rc1).
102
+
103
+ - Disable unsafe math optimizations in C code. See `pull request 25
104
+ <https://github.com/zopefoundation/zope.hookable/pull/25>`_.
105
+
106
+
107
+ 5.1.0 (2021-07-20)
108
+ ==================
109
+
110
+ - Add support for Python 3.9.
111
+
112
+ - Create Linux aarch64 wheels.
113
+
114
+
115
+ 5.0.1 (2020-03-10)
116
+ ==================
117
+
118
+ - Stop using the setuptools ``Feature`` class, allowing this
119
+ project to be built from source with newer versions of setuptools
120
+ that remove that functionality.
121
+
122
+
123
+ 5.0.0 (2019-11-12)
124
+ ==================
125
+
126
+ - Add support for Python 3.7 and 3.8.
127
+
128
+ - Drop support for Python 3.4.
129
+
130
+
131
+ 4.2.0 (2017-11-07)
132
+ ==================
133
+
134
+ - Expose the ``__doc__`` (and, where applicable, ``__bases__`` and
135
+ ``__dict__``) of the hooked object. This lets Sphinx document them.
136
+ See `issue 6 <https://github.com/zopefoundation/zope.hookable/issues/6>`_.
137
+
138
+ - Respect ``PURE_PYTHON`` at runtime. At build time, always try to
139
+ build the C extensions on supported platforms, but allow it to fail.
140
+ See `issue 7
141
+ <https://github.com/zopefoundation/zope.hookable/issues/7>`_.
142
+
143
+
144
+ 4.1.0 (2017-07-26)
145
+ ==================
146
+
147
+ - Drop support for Python 2.6, 3.2 and 3.3.
148
+
149
+ - Add support for Python 3.5 and 3.6.
150
+
151
+ 4.0.4 (2014-03-19)
152
+ ==================
153
+
154
+ - Add support for Python 3.4.
155
+
156
+ 4.0.3 (2014-03-17)
157
+ ==================
158
+
159
+ - Update ``boostrap.py`` to version 2.2.
160
+
161
+ - Fix extension compilation on Py3k.
162
+
163
+ 4.0.2 (2012-12-31)
164
+ ==================
165
+
166
+ - Flesh out PyPI Trove classifiers.
167
+
168
+ 4.0.1 (2012-11-21)
169
+ ==================
170
+
171
+ - Add support for Python 3.3.
172
+
173
+ - Avoid building the C extension explicitly (use the "feature" indirection
174
+ instead). https://bugs.launchpad.net/zope.hookable/+bug/1025470
175
+
176
+ 4.0.0 (2012-06-04)
177
+ ==================
178
+
179
+ - Add support for PyPy.
180
+
181
+ - Add support for continuous integration using ``tox`` and ``jenkins``.
182
+
183
+ - Add a pure-Python reference implementation.
184
+
185
+ - Move doctests to Sphinx documentation.
186
+
187
+ - Bring unit test coverage to 100%.
188
+
189
+ - Add 'setup.py docs' alias (installs ``Sphinx`` and dependencies).
190
+
191
+ - Add 'setup.py dev' alias (runs ``setup.py develop`` plus installs
192
+ ``nose`` and ``coverage``).
193
+
194
+ - Drop support for Python 2.4 / 2.5.
195
+
196
+ - Remove of 'zope.testing.doctestunit' in favor of stdlib's 'doctest.
197
+
198
+ - Add Python 3 support.
199
+
200
+ 3.4.1 (2009-04-05)
201
+ ==================
202
+
203
+ - Update for compatibility with Python 2.6 traceback formats.
204
+
205
+ - Use Jython-compatible ``bootstrap.py``.
206
+
207
+ 3.4.0 (2007-07-20)
208
+ ==================
209
+
210
+ - Initial release as a separate project.
@@ -0,0 +1,13 @@
1
+ zope.hookable-6.0-py3.12-nspkg.pth,sha256=v_t1oIorEnrHsL8_S45xOGNzLyFVAQCg1XkrPrk0VV8,530
2
+ zope/hookable/__init__.py,sha256=pb0kMg3D0-cDl4VLrYtYpaV499J8DpITbW01Wxc3_SA,2190
3
+ zope/hookable/_zope_hookable.c,sha256=3N5DrcP1lhrczu0yDqUshuuZ8GoCkWpf67lYzvkS8ao,7431
4
+ zope/hookable/_zope_hookable.cp312-win_amd64.pyd,sha256=PX1qFbREfBhSKn1J2Jk1MYr-52dGMIqcV3gAHSIZgBs,13824
5
+ zope/hookable/tests/__init__.py,sha256=Z9EJNKBQorYcdV6oaIRTRgF41SMRZEEoLltZCKyVPI8,47
6
+ zope/hookable/tests/test_compile_flags.py,sha256=91siNUs2kotDUYpVV1vAZ_opWhZ50X4_DYkIiNMh6h0,1289
7
+ zope/hookable/tests/test_hookable.py,sha256=Y7G2Z9CeZ4JBxaQSXi2AUvIN3ELP49T3_M9vBS2oQAk,6205
8
+ zope.hookable-6.0.dist-info/LICENSE.txt,sha256=PmcdsR32h1FswdtbPWXkqjg-rKPCDOo_r1Og9zNdCjw,2070
9
+ zope.hookable-6.0.dist-info/METADATA,sha256=xr9vKUXHxn6H02gmzIem7QXg0W137AyhoG93IToZ6Tc,6035
10
+ zope.hookable-6.0.dist-info/WHEEL,sha256=aDrgWfEd5Ac7WJzHsr90rcMGiH4MHbAXoCWpyP5CEBc,102
11
+ zope.hookable-6.0.dist-info/namespace_packages.txt,sha256=QpUHvpO4wIuZDeEgKY8qZCtD-tAukB0fn_f6utzlb98,5
12
+ zope.hookable-6.0.dist-info/top_level.txt,sha256=QpUHvpO4wIuZDeEgKY8qZCtD-tAukB0fn_f6utzlb98,5
13
+ zope.hookable-6.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.41.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp312-cp312-win_amd64
5
+
@@ -0,0 +1 @@
1
+ zope