[yoda-svn] r556 - in trunk: . include/YODA include/YODA/Utils pyext pyext/yoda pyext/yoda/include

blackhole at projects.hepforge.org blackhole at projects.hepforge.org
Sat Feb 2 13:19:11 GMT 2013


Author: davemallows
Date: Sat Feb  2 13:19:10 2013
New Revision: 556

Log:
Adding support for Python >= 2.4 and fixing warnings present in GCC 4.1.

Modified:
   trunk/ChangeLog
   trunk/configure.ac
   trunk/include/YODA/Bin2D.h
   trunk/include/YODA/Utils/BinSearcher.h
   trunk/pyext/template.py
   trunk/pyext/yoda/core.pyx
   trunk/pyext/yoda/declarations.pxd
   trunk/pyext/yoda/include/Dbn3D.pyx
   trunk/pyext/yoda/include/Histo2D.pyx
   trunk/pyext/yoda/include/Point2D.pyx
   trunk/pyext/yoda/include/Point3D.pyx
   trunk/pyext/yoda/include/Scatter2D.pyx
   trunk/pyext/yoda/util.pyx

Modified: trunk/ChangeLog
==============================================================================
--- trunk/ChangeLog	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/ChangeLog	Sat Feb  2 13:19:10 2013	(r556)
@@ -1,3 +1,9 @@
+2013-02-02  David Mallows  <dave.mallows at gmail.com>
+
+	* Adding support for Python >= 2.4 (was Python >= 2.6)
+
+	* Fixing miscellaneous warnings on GCC 4.1
+
 2013-01-30  Andy Buckley  <andy.buckley at cern.ch>
 
 	* Adding a points() method to the Python Scatter2D wrapper.

Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/configure.ac	Sat Feb  2 13:19:10 2013	(r556)
@@ -32,6 +32,7 @@
 AC_LIBTOOL_DLOPEN
 AC_PROG_LIBTOOL
 
+
 ## Work out library suffix for the build
 LIB_SUFFIX=\\\"$shrext_cmds\\\"
 AC_SUBST([LIB_SUFFIX])
@@ -48,7 +49,7 @@
 ## Basic Python checks
 if test x$enable_pyext == xyes; then
   AZ_PYTHON_PATH
-  AZ_PYTHON_VERSION_ENSURE([2.6])
+  AZ_PYTHON_VERSION_ENSURE([2.4])
   PYTHON_VERSION=`$PYTHON -c "import sys; print '.'.join(map(str, sys.version_info@<:@:2@:>@));"`
   AC_SUBST(PYTHON_VERSION)
   RIVET_PYTHONPATH=`$PYTHON -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(prefix='$prefix', plat_specific=True);"`

Modified: trunk/include/YODA/Bin2D.h
==============================================================================
--- trunk/include/YODA/Bin2D.h	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/include/YODA/Bin2D.h	Sat Feb  2 13:19:10 2013	(r556)
@@ -268,7 +268,7 @@
     }
 
     /// The effective number of entries
-    unsigned long effNumEntries() const {
+    double effNumEntries() const {
       return _dbn.effNumEntries();
     }
 
@@ -421,8 +421,8 @@
         return yedges();
     }
 
-    double _edge_perp(int i) const {
-      double output;
+    double _edge_perp(size_t i) const {
+      double output = 0.0;
 
       switch (i) {
         case 0: output = xMax(); break;

Modified: trunk/include/YODA/Utils/BinSearcher.h
==============================================================================
--- trunk/include/YODA/Utils/BinSearcher.h	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/include/YODA/Utils/BinSearcher.h	Sat Feb  2 13:19:10 2013	(r556)
@@ -174,7 +174,7 @@
           }
 
         size_t estimate(const double x) const {
-          double y = (*_est)(x);
+          size_t y = (size_t)(*_est)(x);
           size_t yi = 0 ? (y < 0) : y;
           return (yi > _max) ? _max : yi;
         }

Modified: trunk/pyext/template.py
==============================================================================
--- trunk/pyext/template.py	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/pyext/template.py	Sat Feb  2 13:19:10 2013	(r556)
@@ -1,5 +1,15 @@
 from string import Template
-from itertools import product, izip
+from itertools import izip
+
+def product(*args, **kwds):
+    # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy
+    # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111
+    pools = map(tuple, args) * kwds.get('repeat', 1)
+    result = [[]]
+    for pool in pools:
+        result = [x+[y] for x in result for y in pool]
+    for prod in result:
+        yield tuple(prod)
 
 # A total mess. Uses python's string.Template to substitute values in various
 # templated C++ wrappers, as Cython has no support for templates (and fused
@@ -37,8 +47,9 @@
                            product(*kwargs.itervalues())]
 
     full_filename = os.path.join(INCLUDE_DIR, filename + '.pyx')
-    with open(path(full_filename)) as f:
-        template = Template(f.read())
+    f = open(path(full_filename))
+    template = Template(f.read())
+    f.close()
 
     plain_name = filename
     for i in individuals[0]:
@@ -54,14 +65,16 @@
             newname = newname.replace(i, j)
 
         out_filename = os.path.join(GENERATED_DIR, newname + '.pyx')
-        with open(path(out_filename), 'w') as f:
-            f.write(GENERATED_HEADER.substitute(filename=filename))
-            f.write(template.substitute(**a))
+        f = open(path(out_filename), 'w')
+        f.write(GENERATED_HEADER.substitute(filename=filename))
+        f.write(template.substitute(**a))
+        f.close()
         includes.append(out_filename)
         
         inc_filename = os.path.join(INCLUDE_DIR, plain_name + '.pxi')
 
-        with open(path(inc_filename), 'w') as f:
-            f.write(GENERATED_HEADER.substitute(filename=filename))
-            f.write("\n".join('include "%s"' % i for i in includes))
+        f = open(path(inc_filename), 'w')
+        f.write(GENERATED_HEADER.substitute(filename=filename))
+        f.write("\n".join('include "%s"' % i for i in includes))
+        f.close()
 

Modified: trunk/pyext/yoda/core.pyx
==============================================================================
--- trunk/pyext/yoda/core.pyx	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/pyext/yoda/core.pyx	Sat Feb  2 13:19:10 2013	(r556)
@@ -6,7 +6,7 @@
 from libcpp.vector cimport vector
 from libcpp.pair cimport pair
 from libcpp.map cimport map
-import ctypes
+#import ctypes # Not done here any more, instead done on transformX/Y.
 
 # Pure python imports
 from itertools import repeat, imap

Modified: trunk/pyext/yoda/declarations.pxd
==============================================================================
--- trunk/pyext/yoda/declarations.pxd	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/pyext/yoda/declarations.pxd	Sat Feb  2 13:19:10 2013	(r556)
@@ -35,7 +35,7 @@
 
         # Raw distribution running sums
         unsigned long numEntries() except+ err
-        unsigned long effNumEntries() except+ err
+        double effNumEntries() except+ err
         double sumW() except+ err
         double sumW2() except+ err
         double sumWX() except+ err
@@ -73,7 +73,7 @@
         
         # Raw distribution running sums
         unsigned long numEntries() except+ err
-        unsigned long effNumEntries() except+ err
+        double effNumEntries() except+ err
         double sumW() except+ err
         double sumW2() except+ err
         double sumWX() except+ err
@@ -129,7 +129,7 @@
         
         # Raw distribution running sums
         unsigned long numEntries()
-        unsigned long effNumEntries()
+        double effNumEntries()
         double sumW()
         double sumW2()
 
@@ -280,7 +280,7 @@
 
         # raw statistics
         unsigned long numEntries() except+ err
-        unsigned long effNumEntries() except+ err
+        double effNumEntries() except+ err
         double sumW() except+ err
         double sumW2() except+ err
         double sumWX() except+ err
@@ -335,7 +335,7 @@
 
         # raw statistics
         unsigned long numEntries() except+ err
-        unsigned long effNumEntries() except+ err
+        double effNumEntries() except+ err
         double sumW() except+ err
         double sumW2() except+ err
         double sumWX() except+ err

Modified: trunk/pyext/yoda/include/Dbn3D.pyx
==============================================================================
--- trunk/pyext/yoda/include/Dbn3D.pyx	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/pyext/yoda/include/Dbn3D.pyx	Sat Feb  2 13:19:10 2013	(r556)
@@ -1,6 +1,3 @@
-from collections import namedtuple
-from itertools import izip, repeat
-
 cdef class Dbn3D(util.Base):
     """
     A 2D distribution 'counter', used and exposed by 2D histograms and

Modified: trunk/pyext/yoda/include/Histo2D.pyx
==============================================================================
--- trunk/pyext/yoda/include/Histo2D.pyx	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/pyext/yoda/include/Histo2D.pyx	Sat Feb  2 13:19:10 2013	(r556)
@@ -38,9 +38,16 @@
     def fill(self, double x, double y, weight=1.0):
         self._Histo2D().fill(x, y, weight)
 
+    # Todo: amalgomate this with fill to take arbitrary iterators?
     def fill_many(self, xs, ys, weight=1.0):
-        for x, y in izip(xs, ys):
-            self._Histo2D().fill(x, y, weight)
+        cdef double x, y
+        try:
+            while True:
+                x = next(xs)
+                y = next(ys)
+                self._Histo2D().fill(x, y, weight)
+        except StopIteration:
+            pass
 
     def copy(self, char *path=""):
         return util.new_owned_cls(Histo2D,

Modified: trunk/pyext/yoda/include/Point2D.pyx
==============================================================================
--- trunk/pyext/yoda/include/Point2D.pyx	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/pyext/yoda/include/Point2D.pyx	Sat Feb  2 13:19:10 2013	(r556)
@@ -1,6 +1,3 @@
-from collections import namedtuple
-from libcpp cimport bool
-
 cdef inline pair[double, double] read_symmetric(object val) except *:
     try:
         a, b = val

Modified: trunk/pyext/yoda/include/Point3D.pyx
==============================================================================
--- trunk/pyext/yoda/include/Point3D.pyx	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/pyext/yoda/include/Point3D.pyx	Sat Feb  2 13:19:10 2013	(r556)
@@ -1,6 +1,3 @@
-from collections import namedtuple
-from libcpp cimport bool
-
 # TODO: make more consistent with Point2D
 
 cdef class Point3D(util.Base):

Modified: trunk/pyext/yoda/include/Scatter2D.pyx
==============================================================================
--- trunk/pyext/yoda/include/Scatter2D.pyx	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/pyext/yoda/include/Scatter2D.pyx	Sat Feb  2 13:19:10 2013	(r556)
@@ -1,6 +1,5 @@
 #TODO: Tidy up + docstrings etc.
 
-cdef object transform_functor = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)
 
 cdef class Scatter2D(AnalysisObject):
     """
@@ -11,11 +10,6 @@
     cdef inline c.Scatter2D *_Scatter2D(self) except NULL:
         return <c.Scatter2D*> self.ptr()
 
-    # There is a pythonic constructor here, and it looks a little like...
-    # __init__(self, *args, **kwargs)
-    # ([edge], path="", title="")
-    # ([bins], **kwargs)
-
     def __init__(self, *args, **kwargs):
         util.try_loop([self.__init_2, self.__init_3], *args, **kwargs)
 
@@ -74,20 +68,30 @@
 
 
     def transformX(self, f):
+        # Import ctypes here (rather than at module import) so that Python 2.4
+        # users don't need ctypes to use the rest of the library.
+        import ctypes
+
         try:
-            callback = transform_functor(f)
+            callback = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)(f)
         except:
-            raise RuntimeError("Callback be of type (double) -> double")
+            raise RuntimeError("Callback is not of type (double) -> double")
+
 
         fptr = (<c.dbl_dbl_fptr*><size_t>ctypes.addressof(callback))[0]
 
         c.Scatter2D_transformX(deref(self._Scatter2D()), fptr)
 
     def transformY(self, f):
+        # Import ctypes here (rather than at module import) so that Python 2.4
+        # users don't need ctypes to use the rest of the library.
+        import ctypes
+
         try:
-            callback = transform_functor(f)
+            callback = ctypes.CFUNCTYPE(ctypes.c_double, ctypes.c_double)(f)
         except:
-            raise RuntimeError("Callback be of type (double) -> double")
+            raise RuntimeError("Callback is not of type (double) -> double")
+
 
         fptr = (<c.dbl_dbl_fptr*><size_t>ctypes.addressof(callback))[0]
 

Modified: trunk/pyext/yoda/util.pyx
==============================================================================
--- trunk/pyext/yoda/util.pyx	Wed Jan 30 15:50:44 2013	(r555)
+++ trunk/pyext/yoda/util.pyx	Sat Feb  2 13:19:10 2013	(r556)
@@ -1,4 +1,5 @@
-from collections import namedtuple
+#from collections import namedtuple
+from operator import itemgetter
 
 cdef class Base:
     pass
@@ -13,7 +14,183 @@
 
     raise TypeError(_msg)
 
-Edges = namedtuple('Edges', ('low', 'high'))
-Errors = namedtuple('Errors', ('minus', 'plus'))
-XY = namedtuple('XY', ('x', 'y'))
-XYZ = namedtuple('XYZ', ('x', 'y', 'z'))
+class Edges(tuple):
+    'Edges(low, high)' 
+
+    __slots__ = () 
+
+    _fields = ('low', 'high') 
+
+    def __new__(_cls, low, high):
+        'Create new instance of Edges(low, high)'
+        return tuple.__new__(_cls, (low, high)) 
+
+    @classmethod
+    def _make(cls, iterable, new=tuple.__new__, len=len):
+        'Make a new Edges object from a sequence or iterable'
+        result = new(cls, iterable)
+        if len(result) != 2:
+            raise TypeError('Expected 2 arguments, got %d' % len(result))
+        return result 
+
+    def __repr__(self):
+        'Return a nicely formatted representation string'
+        return 'Edges(low=%r, high=%r)' % self 
+
+    def _asdict(self):
+        'Return a new dict which maps field names to their values'
+        return dict(zip(self._fields, self)) 
+
+    __dict__ = property(_asdict) 
+
+    def _replace(_self, **kwds):
+        'Return a new Edges object replacing specified fields with new values'
+        result = _self._make(map(kwds.pop, ('low', 'high'), _self))
+        if kwds:
+            raise ValueError('Got unexpected field names: %r' % kwds.keys())
+        return result 
+
+    def __getnewargs__(self):
+        'Return self as a plain tuple.  Used by copy and pickle.'
+        return tuple(self) 
+
+    low = property(itemgetter(0), doc='Alias for field number 0')
+    high = property(itemgetter(1), doc='Alias for field number 1')
+
+
+class Errors(tuple):
+    'Errors(minus, plus)' 
+
+    __slots__ = () 
+
+    _fields = ('minus', 'plus') 
+
+    def __new__(_cls, minus, plus):
+        'Create new instance of Errors(minus, plus)'
+        return tuple.__new__(_cls, (minus, plus)) 
+
+    @classmethod
+    def _make(cls, iterable, new=tuple.__new__, len=len):
+        'Make a new Errors object from a sequence or iterable'
+        result = new(cls, iterable)
+        if len(result) != 2:
+            raise TypeError('Expected 2 arguments, got %d' % len(result))
+        return result 
+
+    def __repr__(self):
+        'Return a nicely formatted representation string'
+        return 'Errors(minus=%r, plus=%r)' % self 
+
+    def _asdict(self):
+        'Return a new dict which maps field names to their values'
+        return dict(zip(self._fields, self)) 
+
+    __dict__ = property(_asdict) 
+
+    def _replace(_self, **kwds):
+        'Return a new Errors object replacing specified fields with new values'
+        result = _self._make(map(kwds.pop, ('minus', 'plus'), _self))
+        if kwds:
+            raise ValueError('Got unexpected field names: %r' % kwds.keys())
+        return result 
+
+    def __getnewargs__(self):
+        'Return self as a plain tuple.  Used by copy and pickle.'
+        return tuple(self) 
+
+    minus = property(itemgetter(0), doc='Alias for field number 0')
+    plus = property(itemgetter(1), doc='Alias for field number 1')
+
+
+#Edges = namedtuple('Edges', ('low', 'high'))
+#Errors = namedtuple('Errors', ('minus', 'plus'))
+#XY = namedtuple('XY', ('x', 'y'))
+class XY(tuple):
+    'XY(x, y)' 
+
+    __slots__ = () 
+
+    _fields = ('x', 'y') 
+
+    def __new__(_cls, x, y):
+        'Create new instance of XY(x, y)'
+        return tuple.__new__(_cls, (x, y)) 
+
+    @classmethod
+    def _make(cls, iterable, new=tuple.__new__, len=len):
+        'Make a new XY object from a sequence or iterable'
+        result = new(cls, iterable)
+        if len(result) != 2:
+            raise TypeError('Expected 2 arguments, got %d' % len(result))
+        return result 
+
+    def __repr__(self):
+        'Return a nicely formatted representation string'
+        return 'XY(x=%r, y=%r)' % self 
+
+    def _asdict(self):
+        'Return a new dict which maps field names to their values'
+        return dict(zip(self._fields, self)) 
+
+    __dict__ = property(_asdict) 
+
+    def _replace(_self, **kwds):
+        'Return a new XY object replacing specified fields with new values'
+        result = _self._make(map(kwds.pop, ('x', 'y'), _self))
+        if kwds:
+            raise ValueError('Got unexpected field names: %r' % kwds.keys())
+        return result 
+
+    def __getnewargs__(self):
+        'Return self as a plain tuple.  Used by copy and pickle.'
+        return tuple(self) 
+
+    x = property(itemgetter(0), doc='Alias for field number 0')
+    y = property(itemgetter(1), doc='Alias for field number 1')
+
+#XYZ = namedtuple('XYZ', ('x', 'y', 'z'))
+
+class XYZ(tuple):
+    'XYZ(x, y, z)' 
+
+    __slots__ = () 
+
+    _fields = ('x', 'y', 'z') 
+
+    def __new__(_cls, x, y, z):
+        'Create new instance of XYZ(x, y, z)'
+        return tuple.__new__(_cls, (x, y, z)) 
+
+    @classmethod
+    def _make(cls, iterable, new=tuple.__new__, len=len):
+        'Make a new XYZ object from a sequence or iterable'
+        result = new(cls, iterable)
+        if len(result) != 3:
+            raise TypeError('Expected 3 arguments, got %d' % len(result))
+        return result 
+
+    def __repr__(self):
+        'Return a nicely formatted representation string'
+        return 'XYZ(x=%r, y=%r, z=%r)' % self 
+
+    def _asdict(self):
+        'Return a new dict which maps field names to their values'
+        return dict(zip(self._fields, self)) 
+
+    __dict__ = property(_asdict) 
+
+    def _replace(_self, **kwds):
+        'Return a new XYZ object replacing specified fields with new values'
+        result = _self._make(map(kwds.pop, ('x', 'y', 'z'), _self))
+        if kwds:
+            raise ValueError('Got unexpected field names: %r' % kwds.keys())
+        return result 
+
+    def __getnewargs__(self):
+        'Return self as a plain tuple.  Used by copy and pickle.'
+        return tuple(self) 
+
+    x = property(itemgetter(0), doc='Alias for field number 0')
+    y = property(itemgetter(1), doc='Alias for field number 1')
+    z = property(itemgetter(2), doc='Alias for field number 2')
+


More information about the yoda-svn mailing list