[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