[h5py] 186/455: New setup script

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:31 UTC 2015


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to annotated tag 1.3.0
in repository h5py.

commit befc00a01d6b547fc44ae2077dde5cf63f6a7311
Author: andrewcollette <andrew.collette at gmail.com>
Date:   Fri Jan 16 06:59:29 2009 +0000

    New setup script
---
 MANIFEST.in                    |   3 +
 h5py/h5l.pxd                   |   6 +-
 h5py/h5l.pyx                   | 260 +-----------------------
 h5py/{h5l.pyx => h5l_body.pyx} |   0
 h5py/h5o.pxd                   |   2 +
 h5py/h5o.pyx                   | 348 +------------------------------
 h5py/{h5o.pyx => h5o_body.pyx} |   0
 setup.py                       | 452 ++++++++++++++---------------------------
 8 files changed, 166 insertions(+), 905 deletions(-)

diff --git a/MANIFEST.in b/MANIFEST.in
index afb4695..dee39c3 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,5 +2,8 @@ include MANIFEST.in
 include LICENSE.txt
 include INSTALL.txt
 include README.txt
+include setup.py
+recursive-include api16 *
+recursive-include api18 *
 recursive-include h5py *.py *.pyx *.pxd *.pxi *.h *.c *.hdf5
 recursive-include licenses *
diff --git a/h5py/h5l.pxd b/h5py/h5l.pxd
index e4f4195..b5b2d4a 100644
--- a/h5py/h5l.pxd
+++ b/h5py/h5l.pxd
@@ -12,8 +12,10 @@
 
 include "defs.pxd"
 
-cdef class LinkProxy:
+IF H5PY_18API:
 
-    cdef hid_t id
+    cdef class LinkProxy:
+
+        cdef hid_t id
 
 
diff --git a/h5py/h5l.pyx b/h5py/h5l.pyx
index 0d629d7..a8c2080 100644
--- a/h5py/h5l.pyx
+++ b/h5py/h5l.pyx
@@ -1,262 +1,6 @@
-#+
-# 
-# This file is part of h5py, a low-level Python interface to the HDF5 library.
-# 
-# Copyright (C) 2008 Andrew Collette
-# http://h5py.alfven.org
-# License: BSD  (See LICENSE.txt for full license)
-# 
-# $Date$
-# 
-#-
-__doc__ = \
-"""
-    API for the "H5L" family of link-related operations
-"""
 
 include "config.pxi"
 
-from h5 cimport init_hdf5, SmartStruct
-from h5p cimport PropID, pdefault
-from h5g cimport GroupID
-from utils cimport emalloc, efree
-from python_exc cimport PyErr_SetString
-
-init_hdf5()
-
-# Runtime imports
-from _sync import sync, nosync
-
-# === Public constants ========================================================
-
-TYPE_HARD = H5L_TYPE_HARD         
-TYPE_SOFT = H5L_TYPE_SOFT      
-TYPE_EXTERNAL = H5L_TYPE_EXTERNAL     
-
-cdef class LinkInfo(SmartStruct):
-
-    cdef H5L_info_t infostruct
-
-    property type:
-        """ Integer type code for link (h5l.TYPE_*) """
-        def __get__(self):
-            return <int>self.infostruct.type
-    property corder_valid:
-        """ Indicates if the creation order is valid """
-        def __get__(self):
-            return <bint>self.infostruct.corder_valid
-    property corder:
-        """ Creation order """
-        def __get__(self):
-            return self.infostruct.corder
-    property cset:
-        """ Integer type code for character set (h5t.CSET_*) """
-        def __get__(self):
-            return self.infostruct.cset
-    property u:
-        """ Either the address of a hard link or the size of a soft/UD link """
-        def __get__(self):
-            if self.infostruct.type == H5L_TYPE_HARD:
-                return self.infostruct.u.address
-            else:
-                return self.infostruct.u.val_size
-
-cdef class _LinkVisitor:
-
-    """ Helper class for iteration callback """
-
-    cdef object func
-    cdef object retval
-    cdef LinkInfo info
-
-    def __init__(self, func):
-        self.func = func
-        self.retval = None
-        self.info = LinkInfo()
-
-cdef herr_t cb_link_iterate(hid_t grp, char* name, H5L_info_t *istruct, void* data) except 2:
-    # Standard iteration callback for iterate/visit routines
-
-    cdef _LinkVisitor it = <_LinkVisitor?>data
-    it.info.infostruct = istruct[0]
-    it.retval = it.func(name, it.info)
-    if (it.retval is None) or (not it.retval):
-        return 0
-    return 1
-
-cdef herr_t cb_link_simple(hid_t grp, char* name, H5L_info_t *istruct, void* data) except 2:
-    # Simplified iteration callback which only provides the name
-
-    cdef _LinkVisitor it = <_LinkVisitor?>data
-    it.retval = it.func(name)
-    if (it.retval is None) or (not it.retval):
-        return 0
-    return 1
-
-
-cdef class LinkProxy:
-
-    """
-        Proxy class which provides access to the HDF5 "H5L" API.
-
-        These come attached to GroupID objects as "obj.links".  Since every
-        H5L function operates on at least one group, the methods provided
-        operate on their parent group identifier.  For example::
-
-            >>> g = h5g.open(fid, '/')
-            >>> g.links.exists("MyGroup")
-            True
-            >>> g.links.exists("FooBar")
-            False
-
-        * Hashable: No
-        * Equality: Undefined
-    """
-
-    def __init__(self, hid_t id_):
-
-        # The identifier in question is the hid_t for the parent GroupID.
-        # We "borrow" this reference.
-        self.id = id_
-
-    def __richcmp__(self, object other, int how):
-        return NotImplemented
-
-    def __hash__(self):
-        raise TypeError("Link proxies are unhashable; use the parent group instead.")
-
-    @sync
-    def create_hard(self, char* new_name, GroupID cur_loc not None,
-        char* cur_name, PropID lcpl=None, PropID lapl=None):
-        """ (STRING new_name, GroupID cur_loc, STRING cur_name,
-        PropID lcpl=None, PropID lapl=None)
-
-        Create a new hard link in this group pointing to an existing link
-        in another group.
-        """
-        H5Lcreate_hard(cur_loc.id, cur_name, self.id, new_name,
-            pdefault(lcpl), pdefault(lapl))
-
-    @sync
-    def create_soft(self, char* new_name, char* target,
-        PropID lcpl=None, PropID lapl=None):
-        """(STRING new_name, STRING target, PropID lcpl=None, PropID lapl=None)
-
-        Create a new soft link in this group, with the given string value.
-        The link target does not need to exist.
-        """
-        H5Lcreate_soft(target, self.id, new_name,
-            pdefault(lcpl), pdefault(lapl))
-
-    @sync
-    def create_external(self, char* link_name, char* file_name, char* obj_name,
-        PropID lcpl=None, PropID lapl=None):
-        """(STRING link_name, STRING file_name, STRING obj_name,
-        PropLCID lcpl=None, PropLAID lapl=None)
-
-        Create a new external link, pointing to an object in another file.
-        """
-        H5Lcreate_external(file_name, obj_name, self.id, link_name,
-            pdefault(lcpl), pdefault(lapl))
-
-    @sync
-    def get_val(self, char* name, PropID lapl=None):
-        """(STRING name, PropLAID lapl=None) => STRING or TUPLE(file, obj)
-
-        Get the string value of a soft link, or a 2-tuple representing
-        the contents of an external link.
-        """
-        cdef hid_t plist = pdefault(lapl)
-        cdef H5L_info_t info
-        cdef size_t buf_size
-        cdef char* buf = NULL
-        cdef char* ext_file_name = NULL
-        cdef char* ext_obj_name = NULL
-        cdef unsigned int wtf = 0
-
-        H5Lget_info(self.id, name, &info, plist)
-        if info.type != H5L_TYPE_SOFT and info.type != H5L_TYPE_EXTERNAL:
-            raise TypeError("Link must be either a soft or external link")
-
-        buf_size = info.u.val_size
-        buf = <char*>emalloc(buf_size)
-        try:
-            H5Lget_val(self.id, name, buf, buf_size, plist)
-            if info.type == H5L_TYPE_SOFT:
-                py_retval = buf
-            else:
-                H5Lunpack_elink_val(buf, buf_size, &wtf, &ext_file_name, &ext_obj_name)
-                py_retval = (str(ext_file_name), str(ext_obj_name))
-        finally:
-            efree(buf)
-        
-        return py_retval
-
-    @sync
-    def exists(self, char* name):
-        """ (STRING name) => BOOL
-
-            Check if a link of the specified name exists in this group.
-        """
-        return <bint>(H5Lexists(self.id, name, H5P_DEFAULT))
-
-    @sync
-    def get_info(self, char* name, int index=-1, *, PropID lapl=None):
-        """(STRING name=, INT index=, **kwds) => LinkInfo instance
-
-        Get information about a link, either by name or its index.
-
-        Keywords:
-        """
-        cdef LinkInfo info = LinkInfo()
-        H5Lget_info(self.id, name, &info.infostruct, pdefault(lapl))
-        return info
-
-    @sync
-    def visit(self, object func, *,
-              int idx_type=H5_INDEX_NAME, int order=H5_ITER_NATIVE,
-              char* obj_name='.', PropID lapl=None, bint info=0):
-        """(CALLABLE func, **kwds) => <Return value from func>
-
-        Iterate a function or callable object over all groups below this
-        one.  Your callable should conform to the signature::
-
-            func(STRING name) => Result
-
-        or if the keyword argument "info" is True::
-
-            func(STRING name, LinkInfo info) => Result
-
-        Returning None or a logical False continues iteration; returning
-        anything else aborts iteration and returns that value.
-
-        BOOL info (False)
-            Provide a LinkInfo instance to callback
-
-        STRING obj_name (".")
-            Visit this subgroup instead
-
-        PropLAID lapl (None)
-            Link access property list for "obj_name"
-
-        INT idx_type (h5.INDEX_NAME)
-
-        INT order (h5.ITER_NATIVE)
-        """
-        cdef _LinkVisitor it = _LinkVisitor(func)
-        cdef H5L_iterate_t cfunc
-
-        if info:
-            cfunc = cb_link_iterate
-        else:
-            cfunc = cb_link_simple
-
-        H5Lvisit_by_name(self.id, obj_name, <H5_index_t>idx_type,
-            <H5_iter_order_t>order, cfunc, <void*>it, pdefault(lapl))
-
-        return it.retval
-
-
-
-
+IF H5PY_18API:
+    include "h5l_body.pyx"
 
diff --git a/h5py/h5l.pyx b/h5py/h5l_body.pyx
similarity index 100%
copy from h5py/h5l.pyx
copy to h5py/h5l_body.pyx
diff --git a/h5py/h5o.pxd b/h5py/h5o.pxd
index 2116324..2eda7a5 100644
--- a/h5py/h5o.pxd
+++ b/h5py/h5o.pxd
@@ -12,3 +12,5 @@
 
 include "defs.pxd"
 
+IF H5PY_18API:
+    pass
diff --git a/h5py/h5o.pyx b/h5py/h5o.pyx
index 75e2fee..ea42f78 100644
--- a/h5py/h5o.pyx
+++ b/h5py/h5o.pyx
@@ -1,349 +1,5 @@
-#+
-# 
-# This file is part of h5py, a low-level Python interface to the HDF5 library.
-# 
-# Copyright (C) 2008 Andrew Collette
-# http://h5py.alfven.org
-# License: BSD  (See LICENSE.txt for full license)
-# 
-# $Date$
-# 
-#-
 
 include "config.pxi"
 
-# Module for the new "H5O" functions introduced in HDF5 1.8.0.  Not even
-# built with API compatibility level below 1.8.
-
-# Pyrex compile-time imports
-from h5 cimport init_hdf5, ObjectID, SmartStruct
-from h5g cimport GroupID
-from h5i cimport wrap_identifier
-from h5p cimport PropID, pdefault
-from utils cimport emalloc, efree
-
-# Initialization
-init_hdf5()
-
-# Runtime imports
-from _sync import sync, nosync
-
-# === Public constants ========================================================
-    
-TYPE_GROUP = H5O_TYPE_GROUP    
-TYPE_DATASET = H5O_TYPE_DATASET   
-TYPE_NAMED_DATATYPE = H5O_TYPE_NAMED_DATATYPE
-
-COPY_SHALLOW_HIERARCHY_FLAG = H5O_COPY_SHALLOW_HIERARCHY_FLAG
-COPY_EXPAND_SOFT_LINK_FLAG  = H5O_COPY_EXPAND_SOFT_LINK_FLAG
-COPY_EXPAND_EXT_LINK_FLAG   = H5O_COPY_EXPAND_EXT_LINK_FLAG
-COPY_EXPAND_REFERENCE_FLAG  = H5O_COPY_EXPAND_REFERENCE_FLAG
-COPY_WITHOUT_ATTR_FLAG      = H5O_COPY_WITHOUT_ATTR_FLAG
-COPY_PRESERVE_NULL_FLAG     = H5O_COPY_PRESERVE_NULL_FLAG
-
-# === Giant H5O_info_t structure ==============================================
-
-cdef class _ObjInfoBase(SmartStruct):
-
-    cdef H5O_info_t *istr
-
-cdef class _OHdrMesg(_ObjInfoBase):
-
-    property present:
-        def __get__(self):
-            return self.istr[0].hdr.mesg.present
-    property shared:
-        def __get__(self):
-            return self.istr[0].hdr.mesg.shared
-
-    def _hash(self):
-        return hash((self.present, self.shared))
-
-cdef class _OHdrSpace(_ObjInfoBase):
-
-    property total:
-        def __get__(self):
-            return self.istr[0].hdr.space.total
-    property meta:
-        def __get__(self):
-            return self.istr[0].hdr.space.meta
-    property mesg:
-        def __get__(self):
-            return self.istr[0].hdr.space.mesg
-    property free:
-        def __get__(self):
-            return self.istr[0].hdr.space.free
-
-    def _hash(self):
-        return hash((self.total, self.meta, self.mesg, self.free))
-
-cdef class _OHdr(_ObjInfoBase):
-
-    cdef public _OHdrSpace space
-    cdef public _OHdrMesg mesg
-
-    property version:
-        def __get__(self):
-            return self.istr[0].hdr.version
-    property nmesgs:
-        def __get__(self):
-            return self.istr[0].hdr.nmesgs
-
-    def __init__(self):
-        self.space = _OHdrSpace()
-        self.mesg = _OHdrMesg()
-
-    def _hash(self):
-        return hash((self.version, self.nmesgs, self.space, self.mesg))
-
-cdef class _ObjInfo(_ObjInfoBase):
-
-    property fileno:
-        def __get__(self):
-            return self.istr[0].fileno
-    property addr:
-        def __get__(self):
-            return self.istr[0].addr
-    property type:
-        def __get__(self):
-            return <int>self.istr[0].type
-    property rc:
-        def __get__(self):
-            return self.istr[0].rc
-
-    def _hash(self):
-        return hash((self.fileno, self.addr, self.type, self.rc))
-
-cdef class ObjInfo(_ObjInfo):
-
-    """
-        Represents the H5O_info_t structure
-    """
-
-    cdef H5O_info_t infostruct
-    cdef public _OHdr hdr
-
-    def __init__(self):
-        self.hdr = _OHdr()
-
-        self.istr = &self.infostruct
-        self.hdr.istr = &self.infostruct
-        self.hdr.space.istr = &self.infostruct
-        self.hdr.mesg.istr = &self.infostruct
-
-    def __copy__(self):
-        cdef ObjInfo newcopy
-        newcopy = ObjInfo()
-        newcopy.infostruct = self.infostruct
-        return newcopy
-
- at sync
-def get_info(ObjectID loc not None, char* name=NULL, int index=-1, *,
-        char* obj_name='.', int index_type=H5_INDEX_NAME, int order=H5_ITER_NATIVE,
-        PropID lapl=None):
-    """(ObjectID loc, STRING name=, INT index=, **kwds) => ObjInfo
-
-    Get information describing an object in an HDF5 file.  Provide the object
-    itself, or the containing group and exactly one of "name" or "index".
-
-    STRING obj_name (".")
-        When "index" is specified, look in this subgroup instead.
-        Otherwise ignored.
-
-    PropID lapl (None)
-        Link access property list
-
-    INT index_type (h5.INDEX_NAME)
-
-    INT order (h5.ITER_NATIVE)
-    """
-    cdef ObjInfo info
-    info = ObjInfo()
-
-    if name != NULL and index >= 0:
-        raise TypeError("At most one of name or index may be specified")
-    elif name != NULL and index < 0:
-        H5Oget_info_by_name(loc.id, name, &info.infostruct, pdefault(lapl)) 
-    elif name == NULL and index >= 0:
-        H5Oget_info_by_idx(loc.id, obj_name, <H5_index_t>index_type,
-            <H5_iter_order_t>order, index, &info.infostruct, pdefault(lapl))
-    else: 
-        H5Oget_info(loc.id, &info.infostruct)
-
-    return info
-
-# === General object operations ===============================================
-
- at sync
-def open(ObjectID loc not None, char* name, PropID lapl=None):
-    """(ObjectID loc, STRING name, PropID lapl=None) => ObjectID
-
-    Open a group, dataset, or named datatype attached to an existing group.
-    """
-    return wrap_identifier(H5Oopen(loc.id, name, pdefault(lapl)))
-
- at sync
-def link(ObjectID obj not None, GroupID loc not None, char* name,
-    PropID lcpl=None, PropID lapl=None):
-    """(ObjectID obj, GroupID loc, STRING name, PropID lcpl=None,
-    PropID lapl=None)
-
-    Create a new hard link to an object.  Useful for objects created with
-    h5g.create_anon() or h5d.create_anon().
-    """
-    H5Olink(obj.id, loc.id, name, pdefault(lcpl), pdefault(lapl))
-
- at sync
-def copy(GroupID src_loc not None, char* src_name, GroupID dst_loc not None,
-    char* dst_name, PropID copypl=None, PropID lcpl=None):
-    """(GroupID src_loc, STRING src_name, GroupID dst_loc, STRING dst_name,
-    PropID copypl=None, PropID lcpl=None)
-    
-    Copy a group, dataset or named datatype from one location to another.  The
-    source and destination need not be in the same file.
-
-    The default behavior is a recursive copy of the object and all objects
-    below it.  This behavior is modified via the "copypl" property list.
-    """
-    H5Ocopy(src_loc.id, src_name, dst_loc.id, dst_name, pdefault(copypl),
-        pdefault(lcpl))
-
- at sync
-def set_comment(ObjectID loc not None, char* comment, *, char* obj_name=".",
-    PropID lapl=None):
-    """(ObjectID loc, STRING comment, **kwds)
-
-    Set the comment for any-file resident object.  Keywords:
-
-    STRING obj_name (".")
-        Set comment on this group member instead
-
-    PropID lapl (None)
-        Link access property list
-    """
-    H5Oset_comment_by_name(loc.id, obj_name, comment, pdefault(lapl))
-
-
- at sync
-def get_comment(ObjectID loc not None, char* comment, *, char* obj_name=".",
-    PropID lapl=None):
-    """(ObjectID loc, STRING comment, **kwds)
-
-    Get the comment for any-file resident object.  Keywords:
-
-    STRING obj_name (".")
-        Set comment on this group member instead
-
-    PropID lapl (None)
-        Link access property list
-    """
-    cdef ssize_t size
-    cdef char* buf
-
-    size = H5Oget_comment_by_name(loc.id, obj_name, NULL, 0, pdefault(lapl))
-    buf = <char*>emalloc(size+1)
-    try:
-        H5Oget_comment_by_name(loc.id, obj_name, buf, size+1, pdefault(lapl))
-        pstring = buf
-    finally:
-        efree(buf)
-
-    return pstring
-
-# === Visit routines ==========================================================
-
-cdef class _ObjectVisitor:
-
-    cdef object func
-    cdef object retval
-    cdef ObjInfo objinfo
-
-    def __init__(self, func):
-        self.func = func
-        self.retval = None
-        self.objinfo = ObjInfo()
-
-cdef herr_t cb_obj_iterate(hid_t obj, char* name, H5O_info_t *info, void* data) except 2:
-
-    cdef _ObjectVisitor visit
-
-    # HDF5 doesn't respect callback return for ".", so skip it
-    if strcmp(name, ".") == 0:
-        return 0
-
-    visit = <_ObjectVisitor>data
-    visit.objinfo.infostruct = info[0]
-    visit.retval = visit.func(name, visit.objinfo)
-
-    if visit.retval is not None:
-        return 1
-    return 0
-
-cdef herr_t cb_obj_simple(hid_t obj, char* name, H5O_info_t *info, void* data) except 2:
-
-    cdef _ObjectVisitor visit
-
-    # HDF5 doesn't respect callback return for ".", so skip it
-    if strcmp(name, ".") == 0:
-        return 0
-
-    visit = <_ObjectVisitor>data
-    visit.retval = visit.func(name)
-
-    if visit.retval is not None:
-        return 1
-    return 0
-
- at sync
-def visit(ObjectID loc not None, object func, *,
-          int idx_type=H5_INDEX_NAME, int order=H5_ITER_NATIVE,
-          char* obj_name=".", PropID lapl=None, bint info=0):
-    """(ObjectID loc, CALLABLE func, **kwds) => <Return value from func>
-
-    Iterate a function or callable object over all objects below the
-    specified one.  Your callable should conform to the signature::
-
-        func(STRING name) => Result
-
-    or if the keyword argument "info" is True::
-    
-        func(STRING name, ObjInfo info) => Result
-
-    Returning None continues iteration; returning anything else aborts
-    iteration and returns that value.  Keywords:
-
-    BOOL info (False)
-        Callback is func(STRING, Objinfo)
-
-    STRING obj_name (".")
-        Visit a subgroup of "loc" instead
-
-    PropLAID lapl (None)
-        Control how "obj_name" is interpreted
-
-    INT idx_type (h5.INDEX_NAME)
-        What indexing strategy to use
-
-    INT order (h5.ITER_NATIVE)
-        Order in which iteration occurs
-    """
-    cdef _ObjectVisitor visit = _ObjectVisitor(func)
-    cdef H5O_iterate_t cfunc
-
-    if info:
-        cfunc = cb_obj_iterate
-    else:
-        cfunc = cb_obj_simple
-
-    H5Ovisit_by_name(loc.id, obj_name, <H5_index_t>idx_type,
-        <H5_iter_order_t>order, cfunc, <void*>visit, pdefault(lapl))
-
-    return visit.retval
-
-
-
-
-
-
-
-
+IF H5PY_18API:
+    include "h5o_body.pyx"
diff --git a/h5py/h5o.pyx b/h5py/h5o_body.pyx
similarity index 100%
copy from h5py/h5o.pyx
copy to h5py/h5o_body.pyx
diff --git a/setup.py b/setup.py
index 47cb7df..eaa90d0 100644
--- a/setup.py
+++ b/setup.py
@@ -12,55 +12,39 @@
 # 
 #-
 
-from __future__ import with_statement
-
 """
     Setup script for the h5py package.  
 
-    All commands take the usual distutils options, like --home, etc.  Cython is
-    not required for installation, but will be invoked if one of the --cython
-    options is used, or if non-default options are specified for the build.
+    * Quick install:
+
+      python setup.py build [--api=<16|18>] [--hdf5=/path/to/hdf5]
+      [sudo] python setup.py install
+
+    * Full rebuild (i.e. if checked out from trunk):
 
-    To build:
-    python setup.py build [--help for additional options]
+      python setup.py cython build [--api=<16|18>] [--hdf5=/path/to/hdf5]
+      [sudo] python setup.py install
 
-    To install:
-    sudo python setup.py install
+    New commands:
 
-    To run the test suite locally (won't install anything):
-    python setup.py test
+    * cython [--api16] [--api18] [--diag]
 """
 
 import os
 import sys
 import shutil
 import commands
-import pickle
 import os.path as op
 
-from distutils.errors import DistutilsError
-from distutils.core import setup
-from distutils.extension import Extension
-from distutils.command.build import build 
-from distutils.command.clean import clean
-from distutils.command.sdist import sdist
-from distutils.cmd import Command
-
 # Basic package options
 NAME = 'h5py'               # Software title
 VERSION = '1.1.0'
 MIN_NUMPY = '1.0.3'
 MIN_CYTHON = '0.9.8.1.1'
 SRC_PATH = 'h5py'           # Name of directory with .pyx files
-HAVE_CYTHON = False         # Flag (updated below in "Import Checks")
-CMD_CLASS = {}              # Custom command classes for setup()
-PICKLE_FILE = 'buildconf.pickle'
-
-# The list of modules depends on max API version
-MODULES = {16:  ['h5', 'h5f', 'h5g', 'h5s', 'h5t', 'h5d', 'h5a', 'h5p', 'h5z',
-                 'h5i', 'h5r', 'h5fd', 'utils'],
-           18:  ['h5', 'h5f', 'h5g', 'h5s', 'h5t', 'h5d', 'h5a', 'h5p', 'h5z',
-                 'h5i', 'h5r', 'h5fd', 'utils', 'h5o', 'h5l']}
+
+MODULES = ['h5', 'h5f', 'h5g', 'h5s', 'h5t', 'h5d', 'h5a', 'h5p', 'h5z',
+                 'h5i', 'h5r', 'h5fd', 'utils', 'h5o', 'h5l']
 EXTRA_SRC = {'h5': ["lzf_filter.c", "lzf/lzf_c.c", "lzf/lzf_d.c"]}
 
 def version_check(vers, required):
@@ -78,10 +62,17 @@ def fatal(instring, code=1):
 def warn(instring):
     print >> sys.stderr, "Warning: "+instring
 
+def debug(instring):
+    if DEBUG:
+        print " DEBUG: "+instring
 
-# === Import Checks ===========================================================
+def localpath(*args):
+    return op.abspath(reduce(op.join, (op.dirname(__file__),)+args))
+
+# --- Imports ---
 
 # Evil test options for setup.py
+DEBUG = False
 for arg in sys.argv[:]:
     if arg.find('--disable-numpy') == 0:
         sys.argv.remove(arg)
@@ -89,6 +80,9 @@ for arg in sys.argv[:]:
     if arg.find('--disable-cython') == 0:
         sys.argv.remove(arg)
         sys.modules['Cython'] = None
+    if arg.find('--setup-debug') == 0:
+        sys.argv.remove(arg)
+        DEBUG = True
 
 # Check Python version (2.5 or greater required)
 if not (sys.version_info[0:2] >= (2,5)):
@@ -103,25 +97,33 @@ except ImportError:
     fatal("Numpy not installed (version >= %s required)" % MIN_NUMPY)
 
 try:
-    from Cython.Compiler.Main import Version, compile, compile_multiple, CompilationOptions
-    if version_check(Version.version, MIN_CYTHON):
-        HAVE_CYTHON = True
-    else:
-        HAVE_CYTHON = False
-        warn("Old Cython %s version ignored; at least %s required" % (Version.version, MIN_CYTHON))
+    from setuptools import setup
+    HAVE_SETUPTOOLS = True
+    debug("Using setuptools")
 except ImportError:
-    HAVE_CYTHON = False
-    warn("Cython (http://cython.org) is not available; only default build possible")
+    from distutils.core import setup
+    HAVE_SETUPTOOLS = False
+    warn("Setuptools unavailable")
+
+from distutils.errors import DistutilsError
+from distutils.extension import Extension
+from distutils.command.build import build 
+from distutils.command.build_ext import build_ext
+from distutils.cmd import Command
 
-# === Platform-dependent compiler config ======================================
 
+# --- Compiler and library config ---
+
+HDF5 = None
+for arg in sys.argv[:]:
+    if arg.find('--hdf5=') == 0:
+        HDF5 = arg.partition('=')[2]
+        sys.argv.remove(arg)
 
 class ExtensionCreator(object):
 
     """ Figures out what include/library dirs are appropriate, and
-        serves as a factory for Extension instances.  This is in a
-        class as opposed to module code since the HDF5 location
-        isn't known until runtime.
+        serves as a factory for Extension instances.
 
         Note this is a purely C-oriented process; it doesn't know or
         care about Cython.
@@ -169,120 +171,50 @@ class ExtensionCreator(object):
                             extra_compile_args = self.extra_compile_args,
                             extra_link_args = self.extra_link_args)
 
+creator = ExtensionCreator(HDF5)
+EXTENSIONS = [creator.create_extension(x) for x in MODULES]
+
 
 # === Custom extensions for distutils =========================================
 
-class cybuild(build):
+class cython(Command):
 
-    """ Cython-aware builder.
-    """
+    """ Cython pre-builder """
 
-    user_options = build.user_options + \
-                    [('hdf5=', '5', 'Custom location for HDF5'),
-                     ('api=', 'a', 'Set API levels (--api=16 or --api=18)'),
-                     ('cython','y','Run Cython'),
-                     ('cython-only','Y', 'Run Cython and stop'),
-                     ('diag', 'd','Enable library debug logging')]
+    user_options = [('diag', 'd', 'Enable library debug logging'),
+                    ('api16', '6', 'Build version 1.6'),
+                    ('api18', '8', 'Build version 1.8')]
 
-    boolean_options = build.boolean_options + ['cython', 'cython-only', 'diag']
+    boolean_options = ['diag']
 
     def initialize_options(self):
-        build.initialize_options(self)
-
-        # Build options
-        self.hdf5 = None
-        self.api = None
-
-        # Cython (config) options
-        self.cython = False
-        self.cython_only = False
-        self.diag = False
-
+        self.diag = None
+        self.api16 = None
+        self.api18 = None
 
     def finalize_options(self):
+        if not (self.api16 or self.api18):
+            self.api16 = self.api18 = True
 
-        build.finalize_options(self)
-
-        if self.hdf5 is not None:
-            self.hdf5 = op.abspath(self.hdf5)
-            if not op.exists(self.hdf5):
-                fatal('Specified HDF5 directory "%s" does not exist' % self.hdf5)
-
-        if self.api is not None:
-            try:
-                self.api = int(self.api)
-                if self.api not in (16,18):
-                    raise Exception
-            except Exception:
-                fatal('Illegal option %s to --api= (legal values are 16,18)' % self.api)
+    def checkdir(self, path):
+        if not op.isdir(path):
+            os.mkdir(path)
 
     def run(self):
+        
+        try:
+            from Cython.Compiler.Main import Version, compile, compile_multiple, CompilationOptions
+            if not version_check(Version.version, MIN_CYTHON):
+                fatal("Old Cython %s version detected; at least %s required" % (Version.version, MIN_CYTHON))
+        except ImportError:
+            fatal("Cython (http://cython.org) is not available; only default build possible")
 
-        # Hack to prevent "install" command from running Cython
-        if not 'build' in sys.argv:
-            build.run(self)
-            return
-
-        if self.api is None:
-            self.api = self.get_hdf5_version()  # either 16 or 18
-
-        modules = MODULES[self.api]
-        creator = ExtensionCreator(self.hdf5)
-        extensions = [creator.create_extension(x, EXTRA_SRC.get(x, None)) for x in modules]
-
-        self.distribution.ext_modules = extensions
-
-        # Cython must be run if any of the following are true:
-        # 1. Some of the .c files don't exist
-        # 2. The current config options don't match the last used options
-        # 3. Either option --cython or --cython-only is provided
-
-        src_missing = not all(op.exists(op.join(SRC_PATH, x+'.c')) for x in modules)
-        pxi = self.generate_pxi()
-        stale_pxi = pxi != self.read_pxi()
-
-        if any((src_missing, stale_pxi, self.cython, self.cython_only)):
-            if not HAVE_CYTHON:
-                fatal("Cython recompilation required, but Cython is unavailable or out of date")
-            if stale_pxi:
-                self.write_pxi(pxi)  # Do this AFTER the Cython check
-            self.compile_cython(sorted(modules), stale_pxi)
-            if self.cython_only:
-                exit(0)
-
-        # Hand over control to distutils
-        build.run(self)
-
-        # For commands test and doc, which need to know about this build
-        with open(PICKLE_FILE,'w') as f:
-            pickle.dump((modules, extensions, op.abspath(self.build_lib)), f)
-
-    def get_hdf5_version(self):
-        """ Try to determine the installed HDF5 version.
-
-            Returns either 16 or 18.  Defaults to 16 (and prints a warning)
-            if the installed version can't be identified.
-        """
-        if self.hdf5 is not None:
-            cmd = reduce(op.join, (self.hdf5, 'bin', 'h5cc'))+" -showconfig"
-        else:
-            cmd = "h5cc -showconfig"
-        output = commands.getoutput(cmd)
-        l = output.find("HDF5 Version")
-
-        if l > 0:
-            if output[l:l+30].find('1.8') > 0:
-                return 18
-            elif output[l:l+30].find('1.6') > 0:
-                return 16
-
-        warn("Can't determine HDF5 version, assuming 1.6 (use --api= to override)")
-        return 16
+        def cythonize(api, diag):
 
-    def generate_pxi(self):
-        """ Generate a Cython .pxi file reflecting the current options. """
+            outpath = localpath('api%d' % api)
+            self.checkdir(outpath)
 
-        pxi_str = \
+            pxi_str = \
 """# This file is automatically generated.  Do not edit.
 
 DEF H5PY_VERSION = "%(VERSION)s"
@@ -293,202 +225,124 @@ DEF H5PY_18API = %(API_18)d    # 1.8.X API available
 
 DEF H5PY_DEBUG = %(DEBUG)d    # Logging-level number, or 0 to disable
 """
-        return pxi_str % {"VERSION": VERSION, "API_MAX": self.api,
-                    "API_16": True, "API_18": self.api == 18,
-                    "DEBUG": 10 if self.diag else 0}
-
-    def read_pxi(self):
-        """ Returns the current config.pxi file, or an empty string. """
-
-        pxi_path = op.join(SRC_PATH, 'config.pxi')
-        if not op.exists(pxi_path):
-            return ""
-
-        try:
-            f = open(pxi_path, 'r')
-            return f.read()
-        except (IOError, OSError):
-            fatal("Can't read file %s" % pxi_path)
-        else:
-            f.close()
-    
-    def write_pxi(self, pxi):
-        """ Unconditionally overwrite the config.pxi file """
+            pxi_str %= {"VERSION": VERSION, "API_MAX": api,
+                        "API_16": True, "API_18": api == 18,
+                        "DEBUG": 10 if diag else 0}
 
-        pxi_path = op.join(SRC_PATH, 'config.pxi')
-        try:
-            f = open(pxi_path, 'w')
-            f.write(pxi)
+            f = open(op.join(outpath, 'config.pxi'),'w')
+            f.write(pxi_str)
             f.close()
-        except IOError:
-            fatal('Failed write to "%s"' % pxi_path)
 
-    def compile_cython(self, modules, recompile_all=False):
-        """ Regenerate the C source files for the build process.
-        """
+            print "Running Cython (%s)..." % Version.version
+            print "  API level: %d" % api
+            print "  Diagnostic mode: %s" % ('yes' if diag else 'no')
 
-        print "Running Cython (%s)..." % Version.version
-        print "  API level: %d" % self.api
-        print "  Diagnostic mode: %s" % ('yes' if self.diag else 'no')
-        print "  HDF5: %s" % ('default' if self.hdf5 is None else self.hdf5)
-
-        # Build each extension
-        # This should be a single call to compile_multiple, but it's
-        # broken in Cython 0.9.8.1.1
-        if 1:
-            cyopts = CompilationOptions(verbose=False)
-            for module in modules:
-                pyx_path = op.join(SRC_PATH,module+'.pyx')
-                c_path = op.join(SRC_PATH,module+'.c')
+            for module in MODULES:
+                pyx_path = localpath(SRC_PATH, module+'.pyx')
+                c_path = localpath(outpath, module+'.c')
                 if not op.exists(c_path) or \
-                   os.stat(pyx_path).st_mtime > os.stat(c_path).st_mtime or \
-                   recompile_all or\
-                   self.force:
+                os.stat(pyx_path).st_mtime > os.stat(c_path).st_mtime:
                     print "Cythoning %s" % pyx_path
-                    result = compile(pyx_path, cyopts)
+                    result = compile(pyx_path, verbose=False,
+                                     include_path=[outpath], output_file=c_path)
                     if result.num_errors != 0:
                         fatal("Cython error; aborting.")
-        else:
-            cyopts = CompilationOptions(verbose=True, timestamps=True)
-            modpaths = [op.join(SRC_PATH, x+'.pyx') for x in modules]
-            result = compile_multiple(modpaths, cyopts)
-            if result.num_errors != 0:
-                fatal("%d Cython errors; aborting" % result.num_errors)
-
-class test(Command):
-
-    """ Run unit tests """
-
-    description = "Run unit tests in-place"
-    user_options = [('sections=','s','Comma separated list of tests ("-" prefix to NOT run)'),
-                    ('detail=', 'd', 'Level of output detail (0-3, default 1)')]
-
-    def initialize_options(self):
-        self.sections = None
-        self.output = False
-        self.detail = 1
-
-    def finalize_options(self):
-        self.detail = int(self.detail)
-
-    def run(self):
-
-        try:
-            with open(PICKLE_FILE, 'r') as f:
-                modules, extensions, build_path = pickle.load(f)
-        except (IOError, OSError):
-            fatal("Project must be built before tests can be run")
-
-        oldpath = sys.path
-        try:
-            sys.path = [op.abspath(build_path)] + oldpath
-            import h5py.tests
-            if not h5py.tests.runtests(None if self.sections is None else tuple(self.sections.split(',')), self.detail):
-                raise DistutilsError("Unit tests failed.")
-        finally:
-            sys.path = oldpath
+        # end "def cythonize(...)"
 
-class doc(Command):
+        if self.api16:
+            cythonize(16, self.diag)
+        if self.api18:
+            cythonize(18, self.diag)
 
-    """ Regenerate documentation.  Unix only, requires epydoc/sphinx. """
+class hbuild(build):
 
-    description = "Rebuild documentation"
+    user_options = build.user_options + \
+                    [('hdf5=', '5', 'Custom location for HDF5'),
+                     ('api=', 'a', 'Set API levels (--api=16 or --api=18)')]
 
-    user_options = [('rebuild', 'r', "Rebuild from scratch")]
-    boolean_options = ['rebuild']
+    boolean_options = build.boolean_options 
 
     def initialize_options(self):
-        self.rebuild = False
+        build.initialize_options(self)
+
+        self.api = None
 
     def finalize_options(self):
-        pass
+        build.finalize_options(self)
 
-    def run(self):
+        if self.api is not None:
+            try:
+                self.api = int(self.api)
+                if self.api not in (16,18):
+                    raise Exception
+            except Exception:
+                fatal('Illegal option %s to --api= (legal values are 16,18)' % self.api)
 
-        try:
-            with open(PICKLE_FILE, 'r') as f:
-                modules, extensions, pth = pickle.load(f)
-        except (IOError, OSError):
-            fatal("Project must be built before docs can be compiled")
+    def run(self):
+        build.run(self)
 
-        pth = op.abspath(pth)
+    def get_api_version(self, hdf5=None):
+        """ Get the active HDF5 version, from the command line or by
+            trying to run showconfig.
+        """
+        if self.api is not None:
+            return self.api
 
-        print "Loading from %s" % pth
+        if hdf5 is not None:
+            cmd = reduce(op.join, (hdf5, 'bin', 'h5cc'))+" -showconfig"
+        else:
+            cmd = "h5cc -showconfig"
+        output = commands.getoutput(cmd)
+        l = output.find("HDF5 Version")
 
-        if self.rebuild and op.exists('docs/build'):
-            shutil.rmtree('docs/build')
+        if l > 0:
+            if output[l:l+30].find('1.8') > 0:
+                debug("Autodetected HDF5 1.8")
+                return 18
+            elif output[l:l+30].find('1.6') > 0:
+                debug("Autodetected HDF5 1.6")
+                return 16
 
-        cmd = "export H5PY_PATH=%s; cd docs; make html" % pth
+        debug("Autodetect FAILED")
+        warn("Can't determine HDF5 version, assuming 1.6 (use --api= to override)")
+        return 16
 
-        retval = os.system(cmd)
-        if retval != 0:
-            fatal("Can't build documentation")
+class hbuild_ext(build_ext):
 
-        if op.exists('docs/html'):
-            shutil.rmtree('docs/html')
+    def run(self):
+        buildobj = self.distribution.get_command_obj('build')
 
-        shutil.copytree('docs/build/html', 'docs/html')
+        api = buildobj.get_api_version(HDF5)
 
+        c_path = localpath('api%d' % api)
+        
+        if not all(op.exists(op.join(c_path, x+'.c')) for x in MODULES):
+            fatal("Cython rebuild required ('python setup.py cython')")
+        
+        for x in MODULES:
+            src = op.join(c_path, x+'.c')
+            dst = localpath(SRC_PATH)
+            debug("Copying %s -> %s" % (src, dst))
+            shutil.copy(src, dst)
 
-class cyclean(Command):
+        build_ext.run(self)
 
-    """ Clean up Cython-generated files and build cache"""
+class test_stub(Command):
 
     user_options = []
-
+    boolean_options = []
     def initialize_options(self):
         pass
-
     def finalize_options(self):
         pass
 
     def run(self):
-        
-        allmodules = set()
-        for x in MODULES.values():
-            allmodules.update(x)
-
-        dirs = ['build']
-
-        for x in dirs:
-            try:
-                shutil.rmtree(x)
-            except OSError:
-                pass
-
-        fnames = [ op.join(SRC_PATH, x+'.dep') for x in allmodules ] + \
-                 [ op.join(SRC_PATH, x+'.c') for x in allmodules ] + \
-                 [ op.join(SRC_PATH, 'config.pxi'), PICKLE_FILE]
-
-        for name in fnames:
-            try:
-                os.remove(name)
-            except OSError:
-                pass
-
+        fatal("Testing only available with setuptools")
 
-class new_sdist(sdist):
-
-    """ Version of sdist that doesn't cache the MANIFEST file """
-
-    def run(self):
-        if os.path.exists('MANIFEST'):
-            os.remove('MANIFEST')
-
-        ipath = reduce(op.join, ('docs', 'source', 'build.rst'))
-        if op.exists(ipath):
-            shutil.copyfile(ipath, 'INSTALL.txt')
-
-        sdist.run(self)
-
-# New commands for setup (e.g. "python setup.py test")
-if os.name == 'nt':
-    CMD_CLASS.update({'build': cybuild, 'test': test, 'sdist': new_sdist,
-                       'clean': cyclean})
-else:
-    CMD_CLASS.update({'build': cybuild, 'test': test, 'sdist': new_sdist,
-                      'doc': doc, 'clean': cyclean, })
+CMD_CLASS = {'build': hbuild, 'cython': cython, 'build_ext': hbuild_ext}
 
+if not HAVE_SETUPTOOLS:
+    CMD_CLASS.update({'test': test_stub})
 
 cls_txt = \
 """
@@ -544,7 +398,7 @@ setup(
   url = 'http://h5py.alfven.org',
   packages = ['h5py','h5py.tests'],
   package_data = package_data,
-  ext_modules = [],
+  ext_modules = EXTENSIONS,
   requires = ['numpy (>=%s)' % MIN_NUMPY],
   cmdclass = CMD_CLASS
 )

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/h5py.git



More information about the debian-science-commits mailing list