tested django-newsletter
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996-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
|
||||
|
||||
****************************************************************************/
|
||||
#include "ExtensionClass/ExtensionClass.h"
|
||||
#include "ExtensionClass/_compat.h"
|
||||
|
||||
#define UNLESS(E) if(!(E))
|
||||
#define OBJECT(O) ((PyObject*)(O))
|
||||
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
PyObject *callable;
|
||||
int level;
|
||||
} CA;
|
||||
|
||||
static PyObject *
|
||||
CA__init__(CA *self, PyObject *args)
|
||||
{
|
||||
PyObject *callable;
|
||||
int level=0;
|
||||
|
||||
UNLESS(PyArg_ParseTuple(args,"O|i",&callable, &level)) return NULL;
|
||||
|
||||
if (level > 0)
|
||||
{
|
||||
callable=PyObject_CallFunction(OBJECT(Py_TYPE(self)), "Oi",
|
||||
callable, level-1);
|
||||
UNLESS (callable) return NULL;
|
||||
self->level=level;
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_INCREF(callable);
|
||||
self->level=0;
|
||||
}
|
||||
|
||||
self->callable=callable;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static void
|
||||
CA_dealloc(CA *self)
|
||||
{
|
||||
Py_DECREF(self->callable);
|
||||
Py_DECREF(Py_TYPE(self));
|
||||
Py_TYPE(self)->tp_free(OBJECT(self));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
CA_of(CA *self, PyObject *args)
|
||||
{
|
||||
if (self->level > 0)
|
||||
{
|
||||
Py_INCREF(self->callable);
|
||||
return self->callable;
|
||||
}
|
||||
|
||||
if (NATIVE_CHECK(self->callable))
|
||||
{
|
||||
/* Special case string as simple alias. */
|
||||
PyObject *o;
|
||||
|
||||
UNLESS (PyArg_ParseTuple(args,"O", &o)) return NULL;
|
||||
return PyObject_GetAttr(o, self->callable);
|
||||
}
|
||||
|
||||
return PyObject_CallObject(self->callable, args);
|
||||
}
|
||||
|
||||
static struct PyMethodDef CA_methods[] = {
|
||||
{"__init__",(PyCFunction)CA__init__, METH_VARARGS, ""},
|
||||
{"__of__", (PyCFunction)CA_of, METH_VARARGS, ""},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
static PyExtensionClass ComputedAttributeType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"ComputedAttribute", sizeof(CA),
|
||||
0,
|
||||
(destructor)CA_dealloc,
|
||||
0,0,0,0,0, 0,0,0, 0,0,0,0,0, 0,0,
|
||||
"ComputedAttribute(callable) -- Create a computed attribute",
|
||||
METHOD_CHAIN(CA_methods),
|
||||
(void*)(EXTENSIONCLASS_BINDABLE_FLAG)
|
||||
};
|
||||
|
||||
static struct PyMethodDef methods[] = {
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
#ifdef PY3K
|
||||
static struct PyModuleDef moduledef =
|
||||
{
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_ComputedAttribute", /* m_name */
|
||||
"Provide ComputedAttribute\n\n", /* m_doc */
|
||||
-1, /* m_size */
|
||||
methods, /* m_methods */
|
||||
NULL, /* m_reload */
|
||||
NULL, /* m_traverse */
|
||||
NULL, /* m_clear */
|
||||
NULL, /* m_free */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
static PyObject*
|
||||
module_init(void)
|
||||
{
|
||||
PyObject *m, *d;
|
||||
|
||||
UNLESS(ExtensionClassImported) return NULL;
|
||||
|
||||
#ifdef PY3K
|
||||
m = PyModule_Create(&moduledef);
|
||||
#else
|
||||
m = Py_InitModule3(
|
||||
"_ComputedAttribute",
|
||||
methods,
|
||||
"Provide Computed Attributes\n\n");
|
||||
#endif
|
||||
|
||||
if (m == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
d = PyModule_GetDict(m);
|
||||
if (d == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyExtensionClass_Export(d, "ComputedAttribute", ComputedAttributeType);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
#ifdef PY3K
|
||||
PyMODINIT_FUNC PyInit__ComputedAttribute(void)
|
||||
{
|
||||
return module_init();
|
||||
}
|
||||
#else
|
||||
PyMODINIT_FUNC init_ComputedAttribute(void)
|
||||
{
|
||||
module_init();
|
||||
}
|
||||
#endif
|
||||
Executable
BIN
Binary file not shown.
@@ -0,0 +1,22 @@
|
||||
from ExtensionClass import Base
|
||||
from ExtensionClass import C_EXTENSION
|
||||
|
||||
|
||||
class ComputedAttribute(Base):
|
||||
"""ComputedAttribute(callable) -- Create a computed attribute"""
|
||||
|
||||
def __init__(self, func, level=0):
|
||||
if level > 0:
|
||||
func = ComputedAttribute(func, level - 1)
|
||||
self.callable = func
|
||||
self.level = level
|
||||
|
||||
def __of__(self, inst):
|
||||
func = self.__dict__['callable']
|
||||
if self.level:
|
||||
return func
|
||||
return func(inst)
|
||||
|
||||
|
||||
if C_EXTENSION: # pragma no cover
|
||||
from ._ComputedAttribute import * # NOQA
|
||||
@@ -0,0 +1,108 @@
|
||||
##############################################################################
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
##############################################################################
|
||||
"""Computed Attributes
|
||||
|
||||
Computed attributes work much like properties:
|
||||
|
||||
>>> import math
|
||||
>>> from ComputedAttribute import ComputedAttribute
|
||||
>>> from ExtensionClass import Base
|
||||
>>> class Point(Base):
|
||||
... def __init__(self, x, y):
|
||||
... self.x, self.y = x, y
|
||||
... length = ComputedAttribute(lambda self: math.sqrt(self.x**2+self.y**2))
|
||||
|
||||
>>> p = Point(3, 4)
|
||||
>>> "%.1f" % p.length
|
||||
'5.0'
|
||||
|
||||
Except that you can also use computed attributes with instances:
|
||||
|
||||
>>> p.angle = ComputedAttribute(lambda self: math.atan(self.y*1.0/self.x))
|
||||
>>> "%.2f" % p.angle
|
||||
'0.93'
|
||||
"""
|
||||
|
||||
from doctest import DocTestSuite
|
||||
import unittest
|
||||
|
||||
from ComputedAttribute import ComputedAttribute
|
||||
from ExtensionClass import Base
|
||||
|
||||
|
||||
def test_wrapper_support():
|
||||
"""Wrapper support
|
||||
|
||||
To support acquisition wrappers, computed attributes have a level.
|
||||
The computation is only done when the level is zero. Retrieving a
|
||||
computed attribute with a level > 0 returns a computed attribute
|
||||
with a decremented level.
|
||||
|
||||
>>> from ExtensionClass import Base
|
||||
>>> class X(Base):
|
||||
... pass
|
||||
|
||||
>>> x = X()
|
||||
>>> x.n = 1
|
||||
|
||||
>>> from ComputedAttribute import ComputedAttribute
|
||||
>>> x.n2 = ComputedAttribute(lambda self: self.n*2)
|
||||
>>> x.n2
|
||||
2
|
||||
>>> x.n2.__class__.__name__
|
||||
'int'
|
||||
|
||||
>>> x.n2 = ComputedAttribute(lambda self: self.n*2, 2)
|
||||
>>> x.n2.__class__.__name__
|
||||
'ComputedAttribute'
|
||||
>>> x.n2 = x.n2
|
||||
>>> x.n2.__class__.__name__
|
||||
'ComputedAttribute'
|
||||
>>> x.n2 = x.n2
|
||||
>>> x.n2.__class__.__name__
|
||||
'int'
|
||||
"""
|
||||
|
||||
|
||||
class TestComputedAttribute(unittest.TestCase):
|
||||
def _construct_class(self, level):
|
||||
class X(Base):
|
||||
def _get_a(self):
|
||||
return 1
|
||||
|
||||
a = ComputedAttribute(_get_a, level)
|
||||
|
||||
return X
|
||||
|
||||
def test_computed_attribute_on_class_level0(self):
|
||||
x = self._construct_class(0)()
|
||||
self.assertEqual(x.a, 1)
|
||||
|
||||
def test_computed_attribute_on_class_level1(self):
|
||||
x = self._construct_class(1)()
|
||||
self.assertIsInstance(x.a, ComputedAttribute)
|
||||
|
||||
def test_compilation(self):
|
||||
from ExtensionClass import _IS_PYPY
|
||||
try:
|
||||
from ComputedAttribute import _ComputedAttribute
|
||||
except ImportError: # pragma: no cover
|
||||
self.assertTrue(_IS_PYPY)
|
||||
else:
|
||||
self.assertTrue(hasattr(_ComputedAttribute, 'ComputedAttribute'))
|
||||
|
||||
def test_suite():
|
||||
suite = unittest.defaultTestLoader.loadTestsFromName(__name__)
|
||||
suite.addTest(DocTestSuite())
|
||||
return suite
|
||||
Reference in New Issue
Block a user