[Zope-Checkins] CVS: Zope/lib/python/ComputedAttribute - _ComputedAttribute.c:1.1.4.1 __init__.py:1.1.4.1 setup.py:1.1.4.1 tests.py:1.1.4.1

Jim Fulton cvs-admin at zope.org
Tue Nov 25 15:17:28 EST 2003


Update of /cvs-repository/Zope/lib/python/ComputedAttribute
In directory cvs.zope.org:/tmp/cvs-serv24052/lib/python/ComputedAttribute

Added Files:
      Tag: Zope-2_8-devel-branch
	_ComputedAttribute.c __init__.py setup.py tests.py 
Log Message:
merged everything but ZODB and ZEO from zodb33-devel-branch


=== Added File Zope/lib/python/ComputedAttribute/_ComputedAttribute.c ===
/*****************************************************************************

  Copyright (c) 1996-2003 Zope Corporation and Contributors.
  All Rights Reserved.

  This software is subject to the provisions of the Zope Public License,
  Version 2.0 (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.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(self->ob_type), "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(self->ob_type);
  PyMem_DEL(self);
}

static PyObject *
CA_of(CA *self, PyObject *args)
{
  if (self->level > 0) 
    {
      Py_INCREF(self->callable);
      return self->callable;
    }

  if (PyString_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 = {
  PyObject_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), 
  EXTENSIONCLASS_BINDABLE_FLAG
};

static struct PyMethodDef methods[] = {
  {NULL,		NULL}
};

void
init_ComputedAttribute(void)
{
  PyObject *m, *d;

  UNLESS(ExtensionClassImported) return;
  
  /* Create the module and add the functions */
  m = Py_InitModule4("_ComputedAttribute", methods,
	   "Provide Computed Attributes\n\n"
	   "$Id: _ComputedAttribute.c,v 1.1.4.1 2003/11/25 20:17:27 jim Exp $\n",
		     OBJECT(NULL),PYTHON_API_VERSION);

  d = PyModule_GetDict(m);
  PyExtensionClass_Export(d,"ComputedAttribute",ComputedAttributeType);
}


=== Added File Zope/lib/python/ComputedAttribute/__init__.py ===
from _ComputedAttribute import *


=== Added File Zope/lib/python/ComputedAttribute/setup.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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 distutils.core import setup, Extension
setup(name="_ComputedAttribute", version="2.0",
      ext_modules=[
         Extension("_ComputedAttribute", ["_ComputedAttribute.c"],
                   include_dirs = ['.', '../ExtensionClass'],
                   depends = ['../ExtensionClass/ExtensionClass.h']),
         ])



=== Added File Zope/lib/python/ComputedAttribute/tests.py ===
##############################################################################
#
# Copyright (c) 2003 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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
>>> 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'

$Id: tests.py,v 1.1.4.1 2003/11/25 20:17:27 jim Exp $
"""

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.

    >>> class X(Base):
    ...     pass

    >>> x = X()
    >>> x.n = 1
    >>> 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'
    
    """

import unittest
from doctest import DocTestSuite
from ExtensionClass import Base
from ComputedAttribute import ComputedAttribute

def test_suite():
    return unittest.TestSuite((DocTestSuite(),))

if __name__ == '__main__': unittest.main()




More information about the Zope-Checkins mailing list