[h5py] 120/455: Begin giant move to Cython
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Thu Jul 2 18:19:24 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 2a57e26ebf15f1dda9e0d01104fc2ca1a5b5448c
Author: andrewcollette <andrew.collette at gmail.com>
Date: Sun Sep 21 09:25:05 2008 +0000
Begin giant move to Cython
---
h5py/_extras.py | 74 +++++++
h5py/defs_c.pxd | 38 ----
h5py/extras.py | 26 ---
h5py/h5.pxd | 19 +-
h5py/h5.pyx | 29 +--
h5py/h5a.pyx | 2 +
h5py/h5d.pyx | 50 ++---
h5py/h5f.pyx | 8 +-
h5py/h5fd.pyx | 20 +-
h5py/h5g.pxd | 31 ++-
h5py/h5g.pyx | 482 ++++++++++++++++++++++++--------------------
h5py/h5p.pyx | 2 +-
h5py/h5s.pxd | 5 +-
h5py/h5s.pyx | 49 ++++-
h5py/h5t.pxd | 7 +-
h5py/h5t.pyx | 52 ++++-
h5py/std_code.pxi | 33 +++
h5py/std_defs.pxi | 57 +++++-
h5py/tests/test_h5g.py | 3 +-
h5py/tests/test_threads.py | 4 +-
setup.py | 28 +--
setup.py => setup_cython.py | 367 ++++++++++++++++-----------------
22 files changed, 809 insertions(+), 577 deletions(-)
diff --git a/h5py/_extras.py b/h5py/_extras.py
new file mode 100644
index 0000000..c80abd1
--- /dev/null
+++ b/h5py/_extras.py
@@ -0,0 +1,74 @@
+#+
+#
+# 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$
+#
+#-
+from __future__ import with_statement
+
+import logging
+from h5py import config
+
+# Decorator utility for low-level thread safety
+from functools import update_wrapper
+
+def uw_apply(wrap, func):
+ # Cython methods don't have a "module" attribute for some reason
+ if hasattr(func, '__module__'):
+ update_wrapper(wrap, func)
+ else:
+ update_wrapper(wrap, func, assigned=('__name__','__doc__'))
+
+def h5sync(logger=None):
+
+ if logger is None:
+ def sync_simple(func):
+
+ def wrap(*args, **kwds):
+ with config.lock:
+ return func(*args, **kwds)
+
+ uw_apply(wrap, func)
+ return wrap
+
+ return sync_simple
+
+ else:
+
+ def sync_debug(func):
+
+ def wrap(*args, **kwds):
+ logger.debug("$ Threadsafe function entry: %s" % func.__name__)
+ with config.lock:
+ logger.debug("> Acquired lock on %s" % func.__name__)
+ retval = func(*args, **kwds)
+ logger.debug("< Released lock on %s" % func.__name__)
+ return retval
+
+ uw_apply(wrap, func)
+ return wrap
+
+ return sync_debug
+
+def h5sync_dummy(logger):
+
+ def log_only(func):
+
+ def wrap(*args, **kwds):
+ logger.debug("$ Function entry: %s" % func.__name__)
+ return func(*args, **kwds)
+
+ uw_apply(wrap, func)
+ return wrap
+
+ return log_only
+
+
+
+
+
diff --git a/h5py/defs_c.pxd b/h5py/defs_c.pxd
deleted file mode 100644
index 6ae13c2..0000000
--- a/h5py/defs_c.pxd
+++ /dev/null
@@ -1,38 +0,0 @@
-#+
-#
-# 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$
-#
-#-
-
-# This file is based on code from the PyTables project. The complete PyTables
-# license is available at licenses/pytables.txt, in the distribution root
-# directory.
-
-# Standard C functions.
-
-cdef extern from "stdlib.h":
- ctypedef long size_t
- void *malloc(size_t size)
- void free(void *ptr)
-
-cdef extern from "string.h":
- char *strchr(char *s, int c)
- char *strcpy(char *dest, char *src)
- char *strncpy(char *dest, char *src, size_t n)
- int strcmp(char *s1, char *s2)
- char *strdup(char *s)
- void *memcpy(void *dest, void *src, size_t n)
-
-cdef extern from "time.h":
- ctypedef int time_t
-
-cdef extern from "unistd.h":
- ctypedef long ssize_t
-
-
diff --git a/h5py/extras.py b/h5py/extras.py
deleted file mode 100644
index 5135358..0000000
--- a/h5py/extras.py
+++ /dev/null
@@ -1,26 +0,0 @@
-#+
-#
-# 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$
-#
-#-
-from __future__ import with_statement
-
-from h5py import config
-
-# Decorator utility for low-level thread safety
-from functools import update_wrapper
-def h5sync(func):
-
- def wrap(*args, **kwds):
- with config.lock:
- return func(*args, **kwds)
-
- update_wrapper(wrap, func)
- return wrap
-
diff --git a/h5py/h5.pxd b/h5py/h5.pxd
index aa1a3c7..d2717fe 100644
--- a/h5py/h5.pxd
+++ b/h5py/h5.pxd
@@ -14,22 +14,10 @@
# license is available at licenses/pytables.txt, in the distribution root
# directory.
-include "conditions.pxi"
-from defs_c cimport size_t, ssize_t, malloc, free
+include "std_defs.pxi"
-# Common structs and types from HDF5
cdef extern from "hdf5.h":
- ctypedef int hid_t # In H5Ipublic.h
- ctypedef int hbool_t
- ctypedef int herr_t
- ctypedef int htri_t
- # hsize_t should be unsigned, but Windows platform does not support
- # such an unsigned long long type.
- ctypedef long long hsize_t
- ctypedef signed long long hssize_t
- ctypedef signed long long haddr_t # I suppose this must be signed as well...
-
ctypedef struct hvl_t:
size_t len # Length of VL data (in base type units)
void *p # Pointer to VL data
@@ -255,7 +243,10 @@ cdef class H5PYConfig:
cdef object _complex_names # ('r','i')
cdef object _lock # Primary HDF5 Interface Lock (PHIL)
- cdef readonly object compile_opts
+ cdef readonly object API_16
+ cdef readonly object API_18
+ cdef readonly object DEBUG
+ cdef readonly object THREADS
cdef class ObjectID:
""" Base wrapper class for HDF5 object identifiers """
diff --git a/h5py/h5.pyx b/h5py/h5.pyx
index 6d1604c..4ed3f29 100644
--- a/h5py/h5.pyx
+++ b/h5py/h5.pyx
@@ -30,7 +30,7 @@
All exception classes and error handling functions are also in this module.
"""
-include "conditions.pxi"
+include "config.pxi"
from python cimport PyErr_SetObject
import atexit
@@ -40,9 +40,10 @@ from weakref import WeakKeyDictionary
# Logging is only enabled when compiled with H5PY_DEBUG nonzero
IF H5PY_DEBUG:
import logging
- logger = logging.getLogger('h5py')
+ logger = logging.getLogger('h5py') # Set up the root logger
logger.setLevel(H5PY_DEBUG)
logger.addHandler(logging.StreamHandler())
+ log_ident = logging.getLogger('h5py.identifiers')
def get_libversion():
""" () => TUPLE (major, minor, release)
@@ -79,9 +80,12 @@ cdef class H5PYConfig:
"""
def __init__(self):
+ global logger
self._complex_names = ('r','i')
- self.compile_opts = {'IO_NONBLOCK': H5PY_NONBLOCK,
- 'DEBUG': H5PY_DEBUG}
+ self.API_16 = H5PY_16API
+ self.API_18 = H5PY_18API
+ self.DEBUG = H5PY_DEBUG
+ self.THREADS = H5PY_THREADS
self._lock = threading.RLock()
property lock:
@@ -123,7 +127,7 @@ cdef object standard_richcmp(object self, object other, int how):
if how == 2 or how == 3:
- if not typecheck(self, ObjectID) and typecheck(other, ObjectID):
+ if not isinstance(self, ObjectID) and isinstance(other, ObjectID):
return NotImplemented
eq = (hash(self) == hash(other))
@@ -170,12 +174,12 @@ cdef class ObjectID:
self._locked = 0
self.id = id_
IF H5PY_DEBUG:
- logger.debug("+ %s" % str(self))
+ log_ident.debug("+ %s" % str(self))
def __dealloc__(self):
""" Automatically decrefs the ID, if it's valid. """
IF H5PY_DEBUG:
- logger.debug("- %s" % str(self))
+ log_ident.debug("- %s" % str(self))
if (not self._locked) and self._valid:
H5Idec_ref(self.id)
@@ -187,12 +191,12 @@ cdef class ObjectID:
"""
cdef ObjectID copy
copy = type(self)(self.id)
- assert typecheck(copy, ObjectID), "ObjectID copy encountered invalid type"
+ assert isinstance(copy, ObjectID), "ObjectID copy encountered invalid type"
if self._valid and not self._locked:
H5Iinc_ref(self.id)
copy._locked = self._locked
IF H5PY_DEBUG:
- logger.debug("c %s" % str(self))
+ log_ident.debug("c %s" % str(self))
return copy
def __richcmp__(self, object other, int how):
@@ -608,14 +612,11 @@ import_hdf5()
hdf5_version_tuple = get_libversion()
hdf5_version = "%d.%d.%d" % hdf5_version_tuple
-api_version_tuple = (H5PY_API_MAJ, H5PY_API_MIN)
+api_version_tuple = (int(H5PY_API/10), H5PY_API%10)
api_version = "%d.%d" % api_version_tuple
version = H5PY_VERSION
-version_tuple = [] # no list comprehensions in Pyrex
-for _x in version.split('.'):
- version_tuple.append(int(_x))
-version_tuple = tuple(version_tuple)
+version_tuple = tuple([int(x) for x in version.split('.')])
_config = H5PYConfig()
diff --git a/h5py/h5a.pyx b/h5py/h5a.pyx
index be2d5e6..77a3d6c 100644
--- a/h5py/h5a.pyx
+++ b/h5py/h5a.pyx
@@ -18,6 +18,8 @@
py_exists(ObjectID, STRING) Test if a named attribute exists
"""
+include "std_code.pxi"
+
# Pyrex compile-time imports
from h5p cimport H5P_DEFAULT
from h5t cimport TypeID, typewrap
diff --git a/h5py/h5d.pyx b/h5py/h5d.pyx
index 9e89354..7c874d3 100644
--- a/h5py/h5d.pyx
+++ b/h5py/h5d.pyx
@@ -13,7 +13,7 @@
"""
Provides access to the low-level HDF5 "H5D" dataset interface.
"""
-include "conditions.pxi"
+include "std_code.pxi"
# Pyrex compile-time imports
from h5 cimport standard_richcmp
@@ -156,6 +156,7 @@ cdef class DatasetID(ObjectID):
"""
H5Dclose(self.id)
+ @sync
def read(self, SpaceID mspace not None, SpaceID fspace not None,
ndarray arr_obj not None, PropDXID dxpl=None):
""" (SpaceID mspace, SpaceID fspace, NDARRAY arr_obj,
@@ -177,8 +178,8 @@ cdef class DatasetID(ObjectID):
The actual read is non-blocking; the array object is temporarily
marked read-only, but attempting to mutate it in another thread
- is a bad idea. Also, this DatasetID object acquires its own lock
- (obj.pylock) until the operation completes.
+ is a bad idea. All HDF5 API calls are locked until the read
+ completes.
"""
cdef TypeID mtype
cdef hid_t self_id, mtype_id, mspace_id, fspace_id, plist_id
@@ -195,20 +196,14 @@ cdef class DatasetID(ObjectID):
plist_id = pdefault(dxpl)
data = PyArray_DATA(arr_obj)
- IF H5PY_NONBLOCK:
- lock = config.lock
- lock.acquire()
- oldflags = arr_obj.flags
- arr_obj.flags = oldflags & (~NPY_WRITEABLE) # Wish-it-was-a-mutex approach
- try:
- with nogil:
- H5PY_H5Dread(self_id, mtype_id, mspace_id, fspace_id, plist_id, data)
- finally:
- arr_obj.flags = oldflags
- lock.release()
- ELSE:
- H5PY_H5Dread(self_id, mtype_id, mspace_id, fspace_id, plist_id, data)
+ arr_obj.flags &= (~NPY_WRITEABLE) # Wish-it-was-a-mutex approach
+ try:
+ with nogil:
+ H5PY_H5Dread(self_id, mtype_id, mspace_id, fspace_id, plist_id, data)
+ finally:
+ arr_obj.flags |= NPY_WRITEABLE
+ @sync
def write(self, SpaceID mspace not None, SpaceID fspace not None,
ndarray arr_obj not None, PropDXID dxpl=None):
""" (SpaceID mspace, SpaceID fspace, NDARRAY arr_obj,
@@ -223,8 +218,8 @@ cdef class DatasetID(ObjectID):
The actual write is non-blocking; the array object is temporarily
marked read-only, but attempting to mutate it in another thread
- is a bad idea. Also, this DatasetID object acquires its own lock
- (obj.pylock) until the operation completes.
+ is a bad idea. All HDF5 API calls are locked until the write
+ completes.
"""
cdef TypeID mtype
cdef hid_t self_id, mtype_id, mspace_id, fspace_id, plist_id
@@ -241,19 +236,12 @@ cdef class DatasetID(ObjectID):
plist_id = pdefault(dxpl)
data = PyArray_DATA(arr_obj)
- IF H5PY_NONBLOCK:
- lock = config.lock
- lock.acquire()
- oldflags = arr_obj.flags
- arr_obj.flags = oldflags & (~NPY_WRITEABLE) # Wish-it-was-a-mutex approach
- try:
- with nogil:
- H5PY_H5Dwrite(self_id, mtype_id, mspace_id, fspace_id, plist_id, data)
- finally:
- arr_obj.flags = oldflags
- lock.release()
- ELSE:
- H5PY_H5Dwrite(self_id, mtype_id, mspace_id, fspace_id, plist_id, data)
+ arr_obj.flags &= (~NPY_WRITEABLE) # Wish-it-was-a-mutex approach
+ try:
+ with nogil:
+ H5PY_H5Dwrite(self_id, mtype_id, mspace_id, fspace_id, plist_id, data)
+ finally:
+ arr_obj.flags |= NPY_WRITEABLE
def extend(self, object shape):
""" (TUPLE shape)
diff --git a/h5py/h5f.pyx b/h5py/h5f.pyx
index 96ef323..602cac7 100644
--- a/h5py/h5f.pyx
+++ b/h5py/h5f.pyx
@@ -146,9 +146,9 @@ def get_obj_count(object where=OBJ_ALL, int types=H5F_OBJ_ALL):
identifier.
"""
cdef hid_t where_id
- if typecheck(where, FileID):
+ if isinstance(where, FileID):
where_id = where.id
- elif typecheck(where, int) or typecheck(where, long):
+ elif isinstance(where, int) or isinstance(where, long):
where_id = where
else:
raise TypeError("Location must be a FileID or OBJ_ALL.")
@@ -201,9 +201,9 @@ def get_obj_ids(object where=OBJ_ALL, int types=H5F_OBJ_ALL):
obj_list = NULL
py_obj_list = []
- if typecheck(where, FileID):
+ if isinstance(where, FileID):
where_id = where.id
- elif typecheck(where, int) or typecheck(where, long):
+ elif isinstance(where, int) or isinstance(where, long):
where_id = where
else:
raise TypeError("Location must be a FileID or OBJ_ALL.")
diff --git a/h5py/h5fd.pyx b/h5py/h5fd.pyx
index fe234e9..d1fe854 100644
--- a/h5py/h5fd.pyx
+++ b/h5py/h5fd.pyx
@@ -41,29 +41,29 @@ LOG_LOC_WRITE = H5FD_LOG_LOC_WRITE # 0x0002
LOG_LOC_SEEK = H5FD_LOG_LOC_SEEK # 0x0004
LOG_LOC_IO = H5FD_LOG_LOC_IO # (H5FD_LOG_LOC_READ|H5FD_LOG_LOC_WRITE|H5FD_LOG_LOC_SEEK)
-# /* Flags for tracking number of times each byte is read/written */
+# Flags for tracking number of times each byte is read/written
LOG_FILE_READ = H5FD_LOG_FILE_READ # 0x0008
LOG_FILE_WRITE= H5FD_LOG_FILE_WRITE # 0x0010
LOG_FILE_IO = H5FD_LOG_FILE_IO # (H5FD_LOG_FILE_READ|H5FD_LOG_FILE_WRITE)
-# /* Flag for tracking "flavor" (type) of information stored at each byte */
+# Flag for tracking "flavor" (type) of information stored at each byte
LOG_FLAVOR = H5FD_LOG_FLAVOR # 0x0020
-# /* Flags for tracking total number of reads/writes/seeks */
+# Flags for tracking total number of reads/writes/seeks
LOG_NUM_READ = H5FD_LOG_NUM_READ # 0x0040
LOG_NUM_WRITE = H5FD_LOG_NUM_WRITE # 0x0080
LOG_NUM_SEEK = H5FD_LOG_NUM_SEEK # 0x0100
LOG_NUM_IO = H5FD_LOG_NUM_IO # (H5FD_LOG_NUM_READ|H5FD_LOG_NUM_WRITE|H5FD_LOG_NUM_SEEK)
-# /* Flags for tracking time spent in open/read/write/seek/close */
-LOG_TIME_OPEN = H5FD_LOG_TIME_OPEN # 0x0200 # /* Not implemented yet */
-LOG_TIME_READ = H5FD_LOG_TIME_READ # 0x0400 # /* Not implemented yet */
-LOG_TIME_WRITE= H5FD_LOG_TIME_WRITE # 0x0800 # /* Partially implemented (need to track total time) */
-LOG_TIME_SEEK = H5FD_LOG_TIME_SEEK # 0x1000 # /* Partially implemented (need to track total time & track time for seeks during reading) */
-LOG_TIME_CLOSE= H5FD_LOG_TIME_CLOSE # 0x2000 # /* Fully implemented */
+# Flags for tracking time spent in open/read/write/seek/close
+LOG_TIME_OPEN = H5FD_LOG_TIME_OPEN # 0x0200 # Not implemented yet
+LOG_TIME_READ = H5FD_LOG_TIME_READ # 0x0400 # Not implemented yet
+LOG_TIME_WRITE= H5FD_LOG_TIME_WRITE # 0x0800 # Partially implemented (need to track total time)
+LOG_TIME_SEEK = H5FD_LOG_TIME_SEEK # 0x1000 # Partially implemented (need to track total time & track time for seeks during reading)
+LOG_TIME_CLOSE= H5FD_LOG_TIME_CLOSE # 0x2000 # Fully implemented
LOG_TIME_IO = H5FD_LOG_TIME_IO # (H5FD_LOG_TIME_OPEN|H5FD_LOG_TIME_READ|H5FD_LOG_TIME_WRITE|H5FD_LOG_TIME_SEEK|H5FD_LOG_TIME_CLOSE)
-# /* Flag for tracking allocation of space in file */
+# Flag for tracking allocation of space in file
LOG_ALLOC = H5FD_LOG_ALLOC # 0x4000
LOG_ALL = H5FD_LOG_ALL # (H5FD_LOG_ALLOC|H5FD_LOG_TIME_IO|H5FD_LOG_NUM_IO|H5FD_LOG_FLAVOR|H5FD_LOG_FILE_IO|H5FD_LOG_LOC_IO)
diff --git a/h5py/h5g.pxd b/h5py/h5g.pxd
index dc2c758..bb5dd72 100644
--- a/h5py/h5g.pxd
+++ b/h5py/h5g.pxd
@@ -14,7 +14,6 @@
# license is available at licenses/pytables.txt, in the distribution root
# directory.
-include "conditions.pxi"
include "std_defs.pxi"
from h5 cimport class ObjectID
@@ -51,13 +50,10 @@ cdef extern from "hdf5.h":
hid_t H5Gcreate(hid_t loc_id, char *name, size_t size_hint ) except *
hid_t H5Gopen(hid_t loc_id, char *name ) except *
herr_t H5Gclose(hid_t group_id) except *
-# herr_t H5Glink (hid_t file_id, H5G_link_t link_type,
-# char *current_name, char *new_name) except *
herr_t H5Glink2( hid_t curr_loc_id, char *current_name,
H5G_link_t link_type, hid_t new_loc_id, char *new_name ) except *
herr_t H5Gunlink (hid_t file_id, char *name) except *
-# herr_t H5Gmove(hid_t loc_id, char *src, char *dst) except *
herr_t H5Gmove2(hid_t src_loc_id, char *src_name,
hid_t dst_loc_id, char *dst_name ) except *
herr_t H5Gget_num_objs(hid_t loc_id, hsize_t* num_obj) except *
@@ -72,7 +68,34 @@ cdef extern from "hdf5.h":
herr_t H5Gset_comment(hid_t loc_id, char *name, char *comment ) except *
int H5Gget_comment(hid_t loc_id, char *name, size_t bufsize, char *comment ) except *
+ # --- New 1.8.X functions ---------------------------------------------------
+
IF H5PY_18API:
+ ctypedef enum H5G_storage_type_t:
+ H5G_STORAGE_TYPE_UNKNOWN = -1,
+ H5G_STORAGE_TYPE_SYMBOL_TABLE,
+ H5G_STORAGE_TYPE_COMPACT,
+ H5G_STORAGE_TYPE_DENSE
+
+ ctypedef struct H5G_info_t:
+ H5G_storage_type_t storage_type
+ hsize_t nlinks
+ long int max_corder # FIXME: not really long int
+
hid_t H5Gcreate_anon( hid_t loc_id, hid_t gcpl_id, hid_t gapl_id ) except *
+ hid_t H5Gcreate2(hid_t loc_id, char *name, hid_t lcpl_id, hid_t gcpl_id, hid_t gapl_id) except *
+ hid_t H5Gopen2( hid_t loc_id, char * name, hid_t gapl_id ) except *
+ herr_t H5Gget_info( hid_t group_id, H5G_info_t *group_info ) except *
+ herr_t H5Gget_info_by_name( hid_t loc_id, char *group_name, H5G_info_t *group_info, hid_t lapl_id ) except *
+
+
+
+
+
+
+
+
+
+
diff --git a/h5py/h5g.pyx b/h5py/h5g.pyx
index 5d05b35..1ad2bbf 100644
--- a/h5py/h5g.pyx
+++ b/h5py/h5g.pyx
@@ -13,12 +13,12 @@
"""
Low-level HDF5 "H5G" group interface.
"""
-include "conditions.pxi"
+include "std_code.pxi"
# Pyrex compile-time imports
from utils cimport emalloc, efree
from h5 cimport standard_richcmp
-from h5p cimport H5P_DEFAULT
+from h5p cimport H5P_DEFAULT, PropID, pdefault
IF H5PY_18API:
from h5l cimport LinkProxy
@@ -118,21 +118,43 @@ cdef class GroupIter:
# === Basic group management ==================================================
-def open(ObjectID loc not None, char* name):
- """ (ObjectID loc, STRING name) => GroupID
+# COMPAT: 1.8 update
+IF H5PY_18API:
+ def open(ObjectID loc not None, char* name, PropID gapl=None):
+ """ (ObjectID loc, STRING name, PropGAID gapl=None)
- Open an existing HDF5 group, attached to some other group.
- """
- return GroupID(H5Gopen(loc.id, name))
+ Open an existing HDF5 group, attached to some other group.
+ """
+ return GroupID(H5Gopen2(loc.id, name, pdefault(gapl)))
+ELSE:
+ def open(ObjectID loc not None, char* name):
+ """ (ObjectID loc, STRING name) => GroupID
+
+ Open an existing HDF5 group, attached to some other group.
+ """
+ return GroupID(H5Gopen(loc.id, name))
-def create(ObjectID loc not None, char* name, int size_hint=-1):
- """ (ObjectID loc, STRING name, INT size_hint=-1) => GroupID
+# COMPAT: 1.8 update
+IF H5PY_18API:
+ def create(ObjectID loc not None, char* name, PropID lcpl=None,
+ PropID gcpl=None, PropID gapl=None):
+ """ (ObjectID loc, STRING name, PropLCID lcpl=None, PropGCID gcpl=None,
+ PropGAID gapl=None) => GroupID
- Create a new group, under a given parent group. If given, size_hint
- is an estimate of the space to reserve (in bytes) for group member
- names.
- """
- return GroupID(H5Gcreate(loc.id, name, size_hint))
+ Create a new group, under a given parent group.
+ """
+ return GroupID(H5Gcreate2(loc.id, name, pdefault(lcpl),
+ pdefault(gcpl),
+ pdefault(gapl)))
+ELSE:
+ def create(ObjectID loc not None, char* name, int size_hint=-1):
+ """ (ObjectID loc, STRING name, INT size_hint=-1) => GroupID
+
+ Create a new group, under a given parent group. If given, size_hint
+ is an estimate of the space to reserve (in bytes) for group member
+ names.
+ """
+ return GroupID(H5Gcreate(loc.id, name, size_hint))
cdef herr_t iter_cb_helper(hid_t gid, char *name, object int_tpl) except -1:
# Callback function for H5Giterate
@@ -152,60 +174,64 @@ cdef herr_t iter_cb_helper(hid_t gid, char *name, object int_tpl) except -1:
return 0
-def iterate(GroupID loc not None, char* name, object func, object data=None,
- int startidx=0):
- """ (GroupID loc, STRING name, FUNCTION func, OBJECT data=None,
- UINT startidx=0) => INT last_index_processed
-
- Iterate an arbitrary Python function over a group. Note that the
- group is specified by a parent and a name; if you have a group
- identifier and want to iterate over it; pass in "." for the name.
- You can also start at an arbitrary member by specifying its
- (zero-based) index.
-
- Your function:
- 1. Should accept three arguments: the GroupID of the group, the
- (STRING) name of the member, and an arbitary Python object you
- provide as data. Any return value is ignored.
- 2. Raise StopIteration to bail out before all members are processed.
- 3. Raising anything else immediately aborts iteration, and the
- exception is propagated.
- """
- cdef int i
- cdef list err_list
- err_list = []
+# COMPAT: 1.8 deprecation
+IF H5PY_16API:
+ def iterate(GroupID loc not None, char* name, object func, object data=None,
+ int startidx=0):
+ """ (GroupID loc, STRING name, FUNCTION func, OBJECT data=None,
+ UINT startidx=0) => INT last_index_processed
+
+ Iterate an arbitrary Python function over a group. Note that the
+ group is specified by a parent and a name; if you have a group
+ identifier and want to iterate over it; pass in "." for the name.
+ You can also start at an arbitrary member by specifying its
+ (zero-based) index.
+
+ Your function:
+ 1. Should accept three arguments: the GroupID of the group, the
+ (STRING) name of the member, and an arbitary Python object you
+ provide as data. Any return value is ignored.
+ 2. Raise StopIteration to bail out before all members are processed.
+ 3. Raising anything else immediately aborts iteration, and the
+ exception is propagated.
+ """
+ cdef int i
+ cdef list err_list
+ err_list = []
- if startidx < 0:
- raise ValueError("Starting index must be non-negative.")
- i = startidx
+ if startidx < 0:
+ raise ValueError("Starting index must be non-negative.")
+ i = startidx
- int_tpl = (loc, func, data, err_list)
+ int_tpl = (loc, func, data, err_list)
- H5Giterate(loc.id, name, &i, <H5G_iterate_t>iter_cb_helper, int_tpl)
+ H5Giterate(loc.id, name, &i, <H5G_iterate_t>iter_cb_helper, int_tpl)
- if len(err_list) > 0:
- raise err_list[0]
+ if len(err_list) > 0:
+ raise err_list[0]
-def get_objinfo(ObjectID obj not None, object name='.', int follow_link=1):
- """ (ObjectID obj, STRING name='.', BOOL follow_link=True) => GroupStat object
+# COMPAT: 1.8 deprecation
+IF H5PY_16API:
+ def get_objinfo(ObjectID obj not None, object name='.', int follow_link=1):
+ """ (ObjectID obj, STRING name='.', BOOL follow_link=True) => GroupStat object
- Obtain information about a named object. If "name" is provided,
- "obj" is taken to be a GroupID object containing the target.
- The return value is a GroupStat object; see that class's docstring
- for a description of its attributes.
+ Obtain information about a named object. If "name" is provided,
+ "obj" is taken to be a GroupID object containing the target.
+ The return value is a GroupStat object; see that class's docstring
+ for a description of its attributes.
- If follow_link is True (default) and the object is a symbolic link,
- the information returned describes its target. Otherwise the
- information describes the link itself.
- """
- cdef GroupStat statobj
- statobj = GroupStat()
- cdef char* _name
- _name = name
+ If follow_link is True (default) and the object is a symbolic link,
+ the information returned describes its target. Otherwise the
+ information describes the link itself.
+ """
+ cdef GroupStat statobj
+ statobj = GroupStat()
+ cdef char* _name
+ _name = name
- H5Gget_objinfo(obj.id, _name, follow_link, &statobj.infostruct)
+ H5Gget_objinfo(obj.id, _name, follow_link, &statobj.infostruct)
- return statobj
+ return statobj
# === Group member management =================================================
@@ -238,159 +264,178 @@ cdef class GroupID(ObjectID):
when their Python wrappers are freed.
"""
H5Gclose(self.id)
-
- def link(self, char* current_name, char* new_name,
- int link_type=H5G_LINK_HARD, GroupID remote=None):
- """ (STRING current_name, STRING new_name, INT link_type=LINK_HARD,
- GroupID remote=None)
-
- Create a new hard or soft link. current_name identifies
- the link target (object the link will point to). The new link is
- identified by new_name and (optionally) another group "remote".
-
- Link types are:
- LINK_HARD: Hard link to existing object (default)
- LINK_SOFT: Symbolic link; link target need not exist.
- """
- cdef hid_t remote_id
- if remote is None:
- remote_id = self.id
- else:
- remote_id = remote.id
-
- H5Glink2(self.id, current_name, <H5G_link_t>link_type, remote_id, new_name)
-
- def unlink(self, char* name):
- """ (STRING name)
-
- Remove a link to an object from this group.
- """
- H5Gunlink(self.id, name)
-
- def move(self, char* current_name, char* new_name, GroupID remote=None):
- """ (STRING current_name, STRING new_name, GroupID remote=None)
-
- Relink an object. current_name identifies the object.
- new_name and (optionally) another group "remote" determine
- where it should be moved.
- """
- cdef hid_t remote_id
- if remote is None:
- remote_id = self.id
- else:
- remote_id = remote.id
-
- H5Gmove2(self.id, current_name, remote_id, new_name)
-
- def get_num_objs(self):
- """ () => INT number_of_objects
-
- Get the number of objects directly attached to a given group.
- """
- cdef hsize_t size
- H5Gget_num_objs(self.id, &size)
- return size
-
- def get_objname_by_idx(self, hsize_t idx):
- """ (INT idx) => STRING object_name
-
- Get the name of a group member given its zero-based index.
-
- Due to a limitation of the HDF5 library, the generic exception
- H5Error (errno 1) is raised if the idx parameter is out-of-range.
- """
- cdef int size
- cdef char* buf
- buf = NULL
-
- # This function does not properly raise an exception
- size = H5Gget_objname_by_idx(self.id, idx, NULL, 0)
- if size < 0:
- raise H5Error((1,"Invalid argument"))
-
- buf = <char*>emalloc(sizeof(char)*(size+1))
- try:
- H5Gget_objname_by_idx(self.id, idx, buf, size+1)
- pystring = buf
- return pystring
- finally:
- efree(buf)
-
- def get_objtype_by_idx(self, hsize_t idx):
- """ (INT idx) => INT object_type_code
-
- Get the type of an object attached to a group, given its zero-based
- index. Possible return values are:
- - LINK
- - GROUP
- - DATASET
- - DATATYPE
-
- Due to a limitation of the HDF5 library, the generic exception
- H5Error (errno 1) is raised if the idx parameter is out-of-range.
- """
- # This function does not properly raise an exception
- cdef herr_t retval
- retval = H5Gget_objtype_by_idx(self.id, idx)
- if retval < 0:
- raise H5Error((1,"Invalid argument."))
- return retval
-
-
- def get_linkval(self, char* name):
- """ (STRING name) => STRING link_value
-
- Retrieve the value (target name) of a symbolic link.
- Limited to 2048 characters on Windows.
- """
- cdef char* value
- cdef H5G_stat_t statbuf
- value = NULL
-
- H5Gget_objinfo(self.id, name, 0, &statbuf)
-
- if statbuf.type != H5G_LINK:
- raise ValueError('"%s" is not a symbolic link.' % name)
-
- IF UNAME_SYSNAME == "Windows":
- linklen = 2049 # Windows statbuf.linklen seems broken
- ELSE:
- linklen = statbuf.linklen+1
- value = <char*>emalloc(sizeof(char)*linklen)
- try:
- H5Gget_linkval(self.id, name, linklen, value)
- value[linklen-1] = c'\0' # in case HDF5 doesn't null terminate on Windows
- pyvalue = value
- return pyvalue
- finally:
- efree(value)
-
- def set_comment(self, char* name, char* comment):
- """ (STRING name, STRING comment)
-
- Set the comment on a group member.
- """
- H5Gset_comment(self.id, name, comment)
-
- def get_comment(self, char* name):
- """ (STRING name) => STRING comment
-
- Retrieve the comment for a group member.
- """
- cdef int cmnt_len
- cdef char* cmnt
- cmnt = NULL
-
- cmnt_len = H5Gget_comment(self.id, name, 0, NULL)
- assert cmnt_len >= 0
-
- cmnt = <char*>emalloc(sizeof(char)*(cmnt_len+1))
- try:
- H5Gget_comment(self.id, name, cmnt_len+1, cmnt)
- py_cmnt = cmnt
- return py_cmnt
- finally:
- efree(cmnt)
+ IF H5PY_18API:
+ H5Gclose(self.id) # extra ref in the LinkProxy
+
+ # COMPAT: 1.8 deprecation
+ IF H5PY_16API:
+ def link(self, char* current_name, char* new_name,
+ int link_type=H5G_LINK_HARD, GroupID remote=None):
+ """ (STRING current_name, STRING new_name, INT link_type=LINK_HARD,
+ GroupID remote=None)
+
+ Create a new hard or soft link. current_name identifies
+ the link target (object the link will point to). The new link is
+ identified by new_name and (optionally) another group "remote".
+
+ Link types are:
+ LINK_HARD: Hard link to existing object (default)
+ LINK_SOFT: Symbolic link; link target need not exist.
+ """
+ cdef hid_t remote_id
+ if remote is None:
+ remote_id = self.id
+ else:
+ remote_id = remote.id
+
+ H5Glink2(self.id, current_name, <H5G_link_t>link_type, remote_id, new_name)
+
+ # COMPAT: 1.8 deprecation
+ IF H5PY_16API:
+ def unlink(self, char* name):
+ """ (STRING name)
+
+ Remove a link to an object from this group.
+ """
+ H5Gunlink(self.id, name)
+
+ # COMPAT: 1.8 deprecation
+ IF H5PY_16API:
+ def move(self, char* current_name, char* new_name, GroupID remote=None):
+ """ (STRING current_name, STRING new_name, GroupID remote=None)
+
+ Relink an object. current_name identifies the object.
+ new_name and (optionally) another group "remote" determine
+ where it should be moved.
+ """
+ cdef hid_t remote_id
+ if remote is None:
+ remote_id = self.id
+ else:
+ remote_id = remote.id
+
+ H5Gmove2(self.id, current_name, remote_id, new_name)
+
+ # COMPAT: 1.8 deprecation
+ IF H5PY_16API:
+ def get_num_objs(self):
+ """ () => INT number_of_objects
+
+ Get the number of objects directly attached to a given group.
+ """
+ cdef hsize_t size
+ H5Gget_num_objs(self.id, &size)
+ return size
+
+ # COMPAT: 1.8 deprecation
+ IF H5PY_16API:
+ def get_objname_by_idx(self, hsize_t idx):
+ """ (INT idx) => STRING object_name
+
+ Get the name of a group member given its zero-based index.
+
+ Due to a limitation of the HDF5 library, the generic exception
+ H5Error (errno 1) is raised if the idx parameter is out-of-range.
+ """
+ cdef int size
+ cdef char* buf
+ buf = NULL
+
+ # This function does not properly raise an exception
+ size = H5Gget_objname_by_idx(self.id, idx, NULL, 0)
+ if size < 0:
+ raise H5Error((1,"Invalid argument"))
+
+ buf = <char*>emalloc(sizeof(char)*(size+1))
+ try:
+ H5Gget_objname_by_idx(self.id, idx, buf, size+1)
+ pystring = buf
+ return pystring
+ finally:
+ efree(buf)
+
+ # COMPAT: 1.8 deprecation
+ IF H5PY_16API:
+ def get_objtype_by_idx(self, hsize_t idx):
+ """ (INT idx) => INT object_type_code
+
+ Get the type of an object attached to a group, given its zero-based
+ index. Possible return values are:
+ - LINK
+ - GROUP
+ - DATASET
+ - DATATYPE
+
+ Due to a limitation of the HDF5 library, the generic exception
+ H5Error (errno 1) is raised if the idx parameter is out-of-range.
+ """
+ # This function does not properly raise an exception
+ cdef herr_t retval
+ retval = H5Gget_objtype_by_idx(self.id, idx)
+ if retval < 0:
+ raise H5Error((1,"Invalid argument."))
+ return retval
+
+ # COMPAT: 1.8 deprecation
+ IF H5PY_16API:
+ def get_linkval(self, char* name):
+ """ (STRING name) => STRING link_value
+
+ Retrieve the value (target name) of a symbolic link.
+ Limited to 2048 characters on Windows.
+ """
+ cdef char* value
+ cdef H5G_stat_t statbuf
+ value = NULL
+
+ H5Gget_objinfo(self.id, name, 0, &statbuf)
+
+ if statbuf.type != H5G_LINK:
+ raise ValueError('"%s" is not a symbolic link.' % name)
+
+ IF UNAME_SYSNAME == "Windows":
+ linklen = 2049 # Windows statbuf.linklen seems broken
+ ELSE:
+ linklen = statbuf.linklen+1
+ value = <char*>emalloc(sizeof(char)*linklen)
+ try:
+ H5Gget_linkval(self.id, name, linklen, value)
+ value[linklen-1] = c'\0' # in case HDF5 doesn't null terminate on Windows
+ pyvalue = value
+ return pyvalue
+ finally:
+ efree(value)
+
+ # COMPAT: 1.8 deprecation
+ IF H5PY_16API:
+ def set_comment(self, char* name, char* comment):
+ """ (STRING name, STRING comment)
+
+ Set the comment on a group member.
+ """
+ H5Gset_comment(self.id, name, comment)
+
+ # COMPAT: 1.8 deprecation
+ IF H5PY_16API:
+ def get_comment(self, char* name):
+ """ (STRING name) => STRING comment
+
+ Retrieve the comment for a group member.
+ """
+ cdef int cmnt_len
+ cdef char* cmnt
+ cmnt = NULL
+
+ cmnt_len = H5Gget_comment(self.id, name, 0, NULL)
+ assert cmnt_len >= 0
+
+ cmnt = <char*>emalloc(sizeof(char)*(cmnt_len+1))
+ try:
+ H5Gget_comment(self.id, name, cmnt_len+1, cmnt)
+ py_cmnt = cmnt
+ return py_cmnt
+ finally:
+ efree(cmnt)
# === Special methods =====================================================
@@ -400,7 +445,7 @@ cdef class GroupID(ObjectID):
Determine if a group member of the given name is present
"""
try:
- info = get_objinfo(self,name)
+ H5Gget_objinfo(self.id, name, 1, NULL)
return True
except H5Error:
return False
@@ -411,14 +456,19 @@ cdef class GroupID(ObjectID):
def __len__(self):
""" Number of group members """
- return self.get_num_objs()
+ cdef hsize_t size
+ H5Gget_num_objs(self.id, &size)
+ return size
def __richcmp__(self, object other, int how):
return standard_richcmp(self, other, how)
def __hash__(self):
if self._hash is None:
- info = get_objinfo(self)
- self._hash = hash( (info.fileno, info.objno) )
+ IF H5PY_16API:
+ info = get_objinfo(self)
+ self._hash = hash( (info.fileno, info.objno) )
+ ELSE:
+ self._hash = self.id
return self._hash
diff --git a/h5py/h5p.pyx b/h5py/h5p.pyx
index 489ee72..3cfc98e 100644
--- a/h5py/h5p.pyx
+++ b/h5py/h5p.pyx
@@ -625,7 +625,7 @@ cdef class PropFAID(PropInstanceID):
"""
cdef hid_t plist_id
plist_id = pdefault(memb_fapl)
- H5Pset_fapl(self.id, memb_size, plist_id)
+ H5Pset_fapl_family(self.id, memb_size, plist_id)
def get_fapl_family(self):
""" () => TUPLE info
diff --git a/h5py/h5s.pxd b/h5py/h5s.pxd
index d4f4bab..0c2864d 100644
--- a/h5py/h5s.pxd
+++ b/h5py/h5s.pxd
@@ -18,6 +18,7 @@
# license is available in the file licenses/hdf5.txt in the distribution
# root directory.
+include "config.pxi"
include "std_defs.pxi"
from h5 cimport class ObjectID
from numpy cimport ndarray
@@ -102,7 +103,9 @@ cdef extern from "hdf5.h":
hsize_t start[], hsize_t _stride[],
hsize_t count[], hsize_t _block[]) except *
-
+ IF H5PY_18API:
+ herr_t H5Sencode(hid_t obj_id, void *buf, size_t *nalloc)
+ hid_t H5Sdecode(void *buf)
diff --git a/h5py/h5s.pyx b/h5py/h5s.pyx
index f440f9e..600af26 100644
--- a/h5py/h5s.pyx
+++ b/h5py/h5s.pyx
@@ -13,10 +13,12 @@
"""
Low-level interface to the "H5S" family of data-space functions.
"""
+include "std_code.pxi"
# Pyrex compile-time imports
from utils cimport require_tuple, require_list, convert_dims, convert_tuple, \
emalloc, efree, pybool, create_numpy_hsize, create_hsize_array
+from python cimport PyString_FromStringAndSize
# Runtime imports
import h5
@@ -67,6 +69,7 @@ def create(int class_code):
"""
return SpaceID(H5Screate(<H5S_class_t>class_code))
+ at sync
def create_simple(object dims_tpl, object max_dims_tpl=None):
""" (TUPLE dims_tpl, TUPLE max_dims_tpl) => INT new_space_id
@@ -101,6 +104,17 @@ def create_simple(object dims_tpl, object max_dims_tpl=None):
efree(dims)
efree(max_dims)
+IF H5PY_18API:
+ def decode(buf):
+ """ (STRING buf) => SpaceID
+
+ Unserialize a dataspace. Bear in mind you can also use the native
+ Python pickling machinery to do this.
+ """
+ cdef char* buf_
+ buf_ = buf
+ return SpaceID(H5Sdecode(buf_))
+
# === H5S class API ===========================================================
cdef class SpaceID(ObjectID):
@@ -134,6 +148,39 @@ cdef class SpaceID(ObjectID):
"""
return SpaceID(H5Scopy(self.id))
+ IF H5PY_18API:
+ def encode(self):
+ """ () => STRING
+
+ Serialize a dataspace, including its selection. Bear in mind you
+ can also use the native Python pickling machinery to do this.
+ """
+ cdef void* buf
+ cdef size_t nalloc
+ buf = NULL
+ nalloc = 0
+
+ H5Sencode(self.id, NULL, &nalloc)
+ buf = emalloc(nalloc)
+ try:
+ H5Sencode(self.id, buf, &nalloc)
+ pystr = PyString_FromStringAndSize(<char*>buf, nalloc)
+ finally:
+ efree(buf)
+
+ return pystr
+
+ IF H5PY_18API:
+ # Enable pickling
+
+ def __reduce__(self):
+ return (type(self), (-1,), self.encode())
+
+ def __setstate__(self, state):
+ cdef char* buf
+ buf = state
+ self.id = H5Sdecode(buf)
+
# === Simple dataspaces ===================================================
def is_simple(self):
@@ -158,7 +205,7 @@ cdef class SpaceID(ObjectID):
try:
if not H5Sis_simple(self.id):
- raise ValueError("%d is not a simple dataspace" % space_id)
+ raise ValueError("%d is not a simple dataspace" % self.id)
rank = H5Sget_simple_extent_ndims(self.id)
diff --git a/h5py/h5t.pxd b/h5py/h5t.pxd
index dfeab53..b63aee4 100644
--- a/h5py/h5t.pxd
+++ b/h5py/h5t.pxd
@@ -14,6 +14,7 @@
# license is available at licenses/pytables.txt, in the distribution root
# directory.
+include "config.pxi"
include "std_defs.pxi"
from h5 cimport class ObjectID
@@ -302,9 +303,9 @@ cdef extern from "hdf5.h":
herr_t H5Tset_tag(hid_t type_id, char* tag) except *
char* H5Tget_tag(hid_t type_id) except? NULL
-
-
-
+ IF H5PY_18API:
+ hid_t H5Tdecode(unsigned char *buf) except *
+ herr_t H5Tencode(hid_t obj_id, unsigned char *buf, size_t *nalloc) except *
diff --git a/h5py/h5t.pyx b/h5py/h5t.pyx
index 06a2f3e..9ba53fa 100644
--- a/h5py/h5t.pyx
+++ b/h5py/h5t.pyx
@@ -53,14 +53,16 @@
VLEN types can be manipulated, but reading and writing data in VLEN
format is not supported. This applies to VLEN strings as well.
+
+ 5. Datatypes can be pickled if HDF5 1.8.X is available.
"""
-include "conditions.pxi"
+include "config.pxi"
# Pyrex compile-time imports
-from defs_c cimport free
from h5 cimport err_c, pause_errors, resume_errors
from numpy cimport dtype, ndarray
+from python cimport PyString_FromStringAndSize
from utils cimport emalloc, efree, pybool, \
create_ieee_complex64, create_ieee_complex128, \
@@ -299,6 +301,17 @@ def vlen_create(TypeID base not None):
"""
return typewrap(H5Tvlen_create(base.id))
+IF H5PY_18API:
+ def decode(buf):
+ """ (STRING buf) => TypeID
+
+ Unserialize an HDF5 type. Bear in mind that you can also use the
+ Python pickle/unpickle machinery to do this.
+ """
+ cdef char* buf_
+ buf_ = buf
+ return typewrap(H5Tdecode(<unsigned char*>buf_))
+
# === Base type class =========================================================
cdef class TypeID(ObjectID):
@@ -310,7 +323,6 @@ cdef class TypeID(ObjectID):
def __copy__(self):
cdef TypeID cpy
cpy = ObjectID.__copy__(self)
- assert typecheck(cpy, TypeID), "TypeID copy encounted invalid type"
return cpy
property dtype:
@@ -413,6 +425,40 @@ cdef class TypeID(ObjectID):
if not self._locked:
H5Tclose(self.id)
+ IF H5PY_18API:
+ def encode(self):
+ """ () => STRING
+
+ Serialize an HDF5 type. Bear in mind you can also use the
+ native Python pickle/unpickle machinery to do this. The
+ returned string may contain binary values, including NULLs.
+ """
+ cdef size_t nalloc
+ cdef char* buf
+ buf = NULL
+ nalloc = 0
+
+ H5Tencode(self.id, NULL, &nalloc)
+ buf = <char*>emalloc(sizeof(char)*nalloc)
+ try:
+ H5Tencode(self.id, <unsigned char*>buf, &nalloc)
+ pystr = PyString_FromStringAndSize(buf, nalloc)
+ finally:
+ efree(buf)
+
+ return pystr
+
+ IF H5PY_18API:
+ # Enable pickling
+
+ def __reduce__(self):
+ return (type(self), (-1,), self.encode())
+
+ def __setstate__(self, state):
+ cdef char* buf
+ buf = state
+ self.id = H5Tdecode(<unsigned char*>buf)
+
# === Top-level classes (inherit directly from TypeID) ========================
cdef class TypeArrayID(TypeID):
diff --git a/h5py/std_code.pxi b/h5py/std_code.pxi
new file mode 100644
index 0000000..9f794e9
--- /dev/null
+++ b/h5py/std_code.pxi
@@ -0,0 +1,33 @@
+#+
+#
+# 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$
+#
+#-
+
+# Common, stateless code safe for inclusion in each .pyx file. Also brings
+# in config.pxi.
+
+include "config.pxi"
+
+# Set up synchronization decorator for threads
+IF H5PY_THREADS:
+ from _extras import h5sync
+ IF H5PY_DEBUG:
+ import logging
+ sync = h5sync(logging.getLogger('h5py.functions'))
+ ELSE:
+ sync = h5sync()
+ELSE:
+ IF H5PY_DEBUG:
+ import logging
+ from _extras import h5sync_dummy
+ sync = h5sync_dummy(logging.getLogger('h5py.functions'))
+ ELSE:
+ cdef inline object sync(object func):
+ return func
diff --git a/h5py/std_defs.pxi b/h5py/std_defs.pxi
index ac4dc91..7805324 100644
--- a/h5py/std_defs.pxi
+++ b/h5py/std_defs.pxi
@@ -10,15 +10,32 @@
#
#-
-# "Boilerplate" includes which are so common I don't want to repeat them
-# in every file. These include all basic HDF5 and C typedefs.
-# This file is designed to be included in *.pxd files; only definitions
-# are allowed.
+# "Boilerplate" definitions which are used in every .pxd file. Also includes
+# the dynamically-generated config.pxi interface file. A companion file
+# "std_code.pxi" goes in every .pyx file.
-from h5 cimport hid_t, hbool_t, herr_t, htri_t, hsize_t, \
- hssize_t, haddr_t, hvl_t
+include "config.pxi"
-from defs_c cimport size_t, time_t, ssize_t
+# === Standard C functions and definitions ===
+
+cdef extern from "stdlib.h":
+ ctypedef long size_t
+ void *malloc(size_t size)
+ void free(void *ptr)
+
+cdef extern from "string.h":
+ char *strchr(char *s, int c)
+ char *strcpy(char *dest, char *src)
+ char *strncpy(char *dest, char *src, size_t n)
+ int strcmp(char *s1, char *s2)
+ char *strdup(char *s)
+ void *memcpy(void *dest, void *src, size_t n)
+
+cdef extern from "time.h":
+ ctypedef int time_t
+
+cdef extern from "unistd.h":
+ ctypedef long ssize_t
cdef extern from "stdint.h":
ctypedef signed char int8_t
@@ -29,3 +46,29 @@ cdef extern from "stdint.h":
ctypedef unsigned long int uint32_t
ctypedef signed long long int int64_t
ctypedef signed long long int uint64_t
+
+# === HDF5 types ===
+
+cdef extern from "hdf5.h":
+
+ ctypedef int hid_t # In H5Ipublic.h
+ ctypedef int hbool_t
+ ctypedef int herr_t
+ ctypedef int htri_t
+ # hsize_t should be unsigned, but Windows platform does not support
+ # such an unsigned long long type.
+ ctypedef long long hsize_t
+ ctypedef signed long long hssize_t
+ ctypedef signed long long haddr_t # I suppose this must be signed as well...
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/h5py/tests/test_h5g.py b/h5py/tests/test_h5g.py
index 2ca4ad6..77ceea5 100644
--- a/h5py/tests/test_h5g.py
+++ b/h5py/tests/test_h5g.py
@@ -39,8 +39,9 @@ class TestH5G(TestBase):
for name in TEST_GROUPS:
grp = h5g.open(self.obj, name)
self.assert_(self.is_grp(grp))
+ pr = str(grp)
grp._close()
- self.assert_(not self.is_grp(grp))
+ self.assert_(not self.is_grp(grp), pr+"::"+str(grp))
self.assertRaises(H5Error, h5g.open, self.obj, 'Some other group')
diff --git a/h5py/tests/test_threads.py b/h5py/tests/test_threads.py
index 14f5eb1..593cb77 100644
--- a/h5py/tests/test_threads.py
+++ b/h5py/tests/test_threads.py
@@ -178,7 +178,7 @@ class TestThreads(unittest.TestCase):
if write_time < DELAY:
raise Exception("Write was too fast to test blocking (%f sec; need %f)" % (write_time, DELAY))
- if h5py.config.compile_opts['IO_NONBLOCK']:
+ if h5py.config.THREADS:
self.assert_(thread_b.time < thread_a.timestop, "%f !< %f" % (thread_b.time, thread_a.timestop))
else:
self.assert_(thread_b.time > thread_a.timestop, "%f !> %f" % (thread_b.time, thread_a.timestop))
@@ -199,7 +199,7 @@ class TestThreads(unittest.TestCase):
time.sleep(2)
writethread.join()
- if h5py.config.compile_opts['IO_NONBLOCK']:
+ if h5py.config.THREADS:
# With non-blocking I/O, the library will double-check that the
# global lock isn't held, to prevent more than one thread from
# calling into the HDF5 API.
diff --git a/setup.py b/setup.py
index cc2e7c6..2847481 100644
--- a/setup.py
+++ b/setup.py
@@ -71,8 +71,8 @@ opts.PYREX_ONLY = False # Flag: Run Pyrex, but don't perform build
opts.PYREX_FORCE = False # Flag: Disable Pyrex timestamp checking
opts.PYREX_FORCE_OFF = False # Flag: Don't run Pyrex, no matter what
-opts.API_MAJ = 1 # API interface version (not library version)
-opts.API_MIN = 6
+opts.API_16 = True # Include 1.6.X-specific functions
+opts.API_18 = False # Include new 1.8.X functions
opts.DEBUG_LEVEL = 0 # Logging-module number, 0 to turn off
opts.HDF5_DIR = None # Custom HDF5 directory, or None
opts.IO_NONBLOCK = False # Experimental non-blocking I/O
@@ -95,15 +95,13 @@ for arg in sys.argv[:]:
elif arg.find('--api=') == 0:
opts.ENABLE_PYREX=True
api = arg[6:]
- if api == '16':
- opts.API_MAJ = 1
- opts.API_MIN = 6
- elif api == '18':
- opts.API_MAJ = 1
- opts.API_MIN = 8
- warn('1.8.X API is still under development')
- else:
- fatal('Unrecognized API version "%s" (only "16", "18" currently allowed)' % api)
+ api = api.split(',')
+ if not all(x in ("16","18") for x in api):
+ fatal('Illegal option to --api (legal values are "16" and "18")')
+ if not ("16" in api or "18" in api):
+ fatal("At least one of 1.6 or 1.8 compatibility must be specified.")
+ opts.API_16 = "16" in api
+ opts.API_18 = "18" in api
sys.argv.remove(arg)
elif arg.find('--debug=') == 0:
opts.ENABLE_PYREX=True
@@ -123,6 +121,9 @@ for arg in sys.argv[:]:
opts.IO_NONBLOCK = True
sys.argv.remove(arg)
+opts.API_MAJ = 1
+opts.API_MIN = 8 if opts.API_18 else 6
+
if 'sdist' in sys.argv:
if os.path.exists('MANIFEST'):
warn("Cleaning up stale MANIFEST file")
@@ -218,8 +219,8 @@ DEF H5PY_API_MAJ = %(API_MAJ)d
DEF H5PY_API_MIN = %(API_MIN)d
DEF H5PY_DEBUG = %(DEBUG_LEVEL)d
-DEF H5PY_16API = H5PY_API_MIN == 6
-DEF H5PY_18API = H5PY_API_MIN == 8
+DEF H5PY_16API = %(API_16)d
+DEF H5PY_18API = %(API_18)d
DEF H5PY_NONBLOCK = %(IO_NONBLOCK)d
""" \
@@ -235,6 +236,7 @@ DEF H5PY_NONBLOCK = %(IO_NONBLOCK)d
# is useless. So only replace it if it's out of date.
if cond_present != cond:
print "Replacing conditions file..."
+ print cond
cond_file = open(cond_path,'w')
cond_file.write(cond)
cond_file.close()
diff --git a/setup.py b/setup_cython.py
similarity index 54%
copy from setup.py
copy to setup_cython.py
index cc2e7c6..52b93f9 100644
--- a/setup.py
+++ b/setup_cython.py
@@ -15,7 +15,7 @@
"""
Setup script for the h5py package.
- All commands take the usual distutils options, like --home, etc. Pyrex is
+ All commands take the usual distutils options, like --home, etc. Cython is
not required for installation, but will be invoked if the .c files are
missing, one of the --pyrex options is used, or if a non-default API
version or debug level is requested.
@@ -32,24 +32,65 @@
See INSTALL.txt or the h5py manual for additional build options.
"""
-# === Global constants ========================================================
-
-NAME = 'h5py'
-VERSION = '0.3.1'
-
-MIN_PYREX = '0.9.8.4' # for compile_multiple
-MIN_NUMPY = '1.0.3'
-
-# === Initial imports and utilities ===========================================
+import os
+import sys
+import shutil
+import os.path as op
from distutils.cmd import Command
from distutils.errors import DistutilsError, DistutilsExecError
from distutils.core import setup
from distutils.extension import Extension
-import os
-import sys
-import shutil
-import os.path as op
+
+class CmdOptions(object):
+
+ """ Manages package and compiler options. """
+
+ def __init__(self):
+
+ # Basic package options
+ self.NAME = 'h5py'
+ self.VERSION = '0.3.1'
+ self.MIN_NUMPY = '1.0.3'
+ self.MIN_CYTHON = '0.9.8.1'
+ self.KNOWN_API = (16,18) # Legal API levels (1.8.X or 1.6.X)
+ self.SRC_PATH = 'h5py' # Name of directory with .pyx files
+ self.CMD_CLASS = {} # Custom command classes for setup()
+
+ # Compilation flags
+ self.CYTHON = False # Run Cython. Default is OFF for distribution.
+ self.API = (16,) # API levels to include. Default is 1.6.X only.
+ self.DEBUG = 0 # Compile-time debug level. Default is OFF.
+ self.HDF5 = None # Custom HDF5 directory.
+
+ # Feature flags
+ self.THREADS = False # Thread-aware (safety & non-blocking IO)
+
+ def get_pxi(self):
+ """ Return a string with compile-time defines. """
+
+ pxi_str = \
+"""# This file is automatically generated. Do not edit.
+
+DEF H5PY_VERSION = "%(VERSION)s"
+
+DEF H5PY_API = %(API_MAX)d # Highest API level (i.e. 18 or 16)
+DEF H5PY_16API = %(API_16)d # 1.6.X API available
+DEF H5PY_18API = %(API_18)d # 1.8.X API available
+
+DEF H5PY_DEBUG = %(DEBUG)d # Logging-level number, or 0 to disable
+
+DEF H5PY_THREADS = %(THREADS)d # Enable thread-safety and non-blocking reads
+
+"""
+ opts = dict(self.__dict__)
+ opts.update({ "API_MAX": max(self.API),
+ "API_16": 16 in self.API,
+ "API_18": 18 in self.API})
+ return pxi_str % opts
+
+
+opts = CmdOptions() # Global to hold compilation options
def fatal(instring, code=1):
print >> sys.stderr, "Fatal: "+instring
@@ -58,133 +99,151 @@ def fatal(instring, code=1):
def warn(instring):
print >> sys.stderr, "Warning: "+instring
-# === Parse command line arguments ============================================
+# === Required imports ========================================================
-class CmdOptions(object):
- pass
-opts = CmdOptions()
-
-opts.AUTO_HDR = "# This file is automatically generated. Do not edit."
-opts.VERSION = VERSION
-opts.ENABLE_PYREX = False # Flag: Pyrex must be run
-opts.PYREX_ONLY = False # Flag: Run Pyrex, but don't perform build
-opts.PYREX_FORCE = False # Flag: Disable Pyrex timestamp checking
-opts.PYREX_FORCE_OFF = False # Flag: Don't run Pyrex, no matter what
-
-opts.API_MAJ = 1 # API interface version (not library version)
-opts.API_MIN = 6
-opts.DEBUG_LEVEL = 0 # Logging-module number, 0 to turn off
-opts.HDF5_DIR = None # Custom HDF5 directory, or None
-opts.IO_NONBLOCK = False # Experimental non-blocking I/O
+# Check Python version (2.5 or greater required)
+if not (sys.version_info[0:2] >= (2,5)):
+ fatal("At least Python 2.5 is required to install h5py")
+
+# Check for Numpy (required)
+try:
+ import numpy
+ if numpy.version.version < opts.MIN_NUMPY:
+ fatal("Numpy version %s is out of date (>= %s needed)" % (numpy.version.version, opts.MIN_NUMPY))
+
+except ImportError:
+ fatal("Numpy not installed (version >= %s required)" % opts.MIN_NUMPY)
+
+# === Parse command line arguments ============================================
for arg in sys.argv[:]:
- if arg == '--pyrex':
- opts.ENABLE_PYREX = True
- sys.argv.remove(arg)
- elif arg == '--pyrex-only':
- opts.ENABLE_PYREX = True
- opts.PYREX_ONLY = True
- sys.argv.remove(arg)
- elif arg == '--pyrex-force':
- opts.ENABLE_PYREX=True
- opts.PYREX_FORCE = True
- sys.argv.remove(arg)
- elif arg == '--no-pyrex':
- opts.PYREX_FORCE_OFF = True
+
+ if arg == '--cython':
+ opts.CYTHON = True
sys.argv.remove(arg)
+
elif arg.find('--api=') == 0:
- opts.ENABLE_PYREX=True
- api = arg[6:]
- if api == '16':
- opts.API_MAJ = 1
- opts.API_MIN = 6
- elif api == '18':
- opts.API_MAJ = 1
- opts.API_MIN = 8
- warn('1.8.X API is still under development')
- else:
- fatal('Unrecognized API version "%s" (only "16", "18" currently allowed)' % api)
+ try:
+ api = arg[6:]
+ api = tuple(int(x) for x in api.split(',') if len(x) > 0)
+ if len(api) == 0 or not all(x in opts.KNOWN_API for x in api):
+ raise Exception
+ except Exception:
+ fatal('Illegal option to --api= (legal values are %s)' % ','.join(str(x) for x in opts.KNOWN_API))
+ opts.API = api
+ opts.CYTHON = True
sys.argv.remove(arg)
+
elif arg.find('--debug=') == 0:
- opts.ENABLE_PYREX=True
try:
- opts.DEBUG_LEVEL = int(arg[8:])
+ opts.DEBUG = int(arg[8:])
except:
fatal('Debuglevel not understood (wants --debug=<n>)')
+ opts.CYTHON = True
sys.argv.remove(arg)
+
elif arg.find('--hdf5=') == 0:
splitarg = arg.split('=',1)
if len(splitarg) != 2:
fatal("HDF5 directory not understood (wants --hdf5=/path/to/hdf5)")
- opts.HDF5_DIR = op.abspath(splitarg[1])
+ path = op.abspath(splitarg[1])
+ if not op.exists(path):
+ fatal("HDF5 path is illegal: %s" % path)
+ opts.HDF5 = path
+ opts.CYTHON = True
sys.argv.remove(arg)
- elif arg.find('--io-nonblock') == 0:
- opts.ENABLE_PYREX=True
- opts.IO_NONBLOCK = True
+
+ elif arg.find('--threads') == 0:
+ opts.THREADS = True
+ opts.CYTHON = True
sys.argv.remove(arg)
+# Check if the config.pxi file needs to be updated for the given
+# command-line options.
+pxi_path = op.join(opts.SRC_PATH, 'config.pxi')
+pxi = opts.get_pxi()
+if not op.exists(pxi_path):
+ try:
+ f = open(pxi_path, 'w')
+ f.write(pxi)
+ f.close()
+ except IOError:
+ fatal('Failed write to "%s"' % pxi_path)
+ opts.CYTHON = True
+ if not "--force" in sys.argv: sys.argv.append("--force") # Cython ignores .pxi change
+else:
+ try:
+ f = open(pxi_path, 'r+')
+ except IOError:
+ fatal("Can't read file %s" % pxi_path)
+ if f.read() != pxi:
+ f.close()
+ f = open(pxi_path, 'w')
+ f.write(pxi)
+ opts.CYTHON = True
+ if not "--force" in sys.argv: sys.argv.append("--force") # Cython ignores .pxi change
+ f.close()
+
if 'sdist' in sys.argv:
if os.path.exists('MANIFEST'):
warn("Cleaning up stale MANIFEST file")
os.remove('MANIFEST')
shutil.copyfile(reduce(op.join, ('docs', 'source', 'build.rst')), 'INSTALL.txt')
-
-# === Required imports ========================================================
-
-# Check Python version (2.5 or greater required)
-if not (sys.version_info[0] == 2 and sys.version_info[1] >= 5):
- fatal("At least Python 2.5 is required to install h5py")
-
-# Check for Numpy (required)
-try:
- import numpy
- if numpy.version.version < MIN_NUMPY:
- fatal("Numpy version %s is out of date (>= %s needed)" % (numpy.version.version, MIN_NUMPY))
-
-except ImportError:
- fatal("Numpy not installed (version >= %s required)" % MIN_NUMPY)
-# === Platform configuration & Pyrex check ====================================
+# === Platform configuration & Cython check ====================================
-# Pyrex modules (without extension)
+# Cython modules (without extension)
modules = ['h5' , 'h5f', 'h5g', 'h5s', 'h5t', 'h5d',
- 'h5a', 'h5p', 'h5z', 'h5i', 'h5r', 'h5fd', 'utils']
+ 'h5a', 'h5p', 'h5z', 'h5i', 'h5r', 'h5fd', 'utils']
-if (opts.API_MAJ, opts.API_MIN) >= (1,8):
+# Only enable H5O and H5L interface if we're building against 1.8.X
+if 18 in opts.API:
modules += ['h5o','h5l']
-# C source files required for Pyrex code (with extension)
+# C source files required for Cython code (with extension)
extra_src = ['utils_low.c']
-# Where these live, relative to setup.py
-src_path = 'h5py'
+
+if opts.CYTHON:
+ try:
+ from Cython.Compiler.Main import Version
+ from Cython.Distutils import build_ext
+ except ImportError:
+ fatal("Cython recompilation required, but Cython not installed.")
+
+ if Version.version < opts.MIN_CYTHON:
+ fatal("Old Cython version detected; at least %s required" % opts.MIN_CYTHON)
+
+ # This is what enables Cython. Explicit calls to compile() don't work yet,
+ # which is really annoying and breaks a lot of the options behavior.
+ opts.CMD_CLASS.update({'build_ext': build_ext})
+
# Platform-dependent arguments to setup() or Extension()
if os.name == 'nt':
-
- if opts.HDF5_DIR is None:
+ if opts.HDF5 is None:
fatal("On Windows, HDF5 directory must be specified.")
libraries = ['hdf5dll']
- include_dirs = [numpy.get_include(), op.join(opts.HDF5_DIR, 'include')]
- library_dirs = [op.join(opts.HDF5_DIR, 'dll2')] # Must contain only "hdf5dll.dll.a"
+ include_dirs = [numpy.get_include(), op.join(opts.HDF5, 'include')]
+ library_dirs = [op.join(opts.HDF5, 'dll2')] # Must contain only "hdf5dll.dll.a"
runtime_dirs = []
extra_compile_args = ['-DH5_USE_16_API', '-D_HDF5USEDLL_', '-DH5_SIZEOF_SSIZE_T=4']
extra_link_args = []
package_data = {'h5py': ['*.pyx', '*.dll',
- 'Microsoft.VC90.CRT/*.manifest',
- 'Microsoft.VC90.CRT/*.dll'],
- 'h5py.tests': ['data/*.hdf5']}
+ 'Microsoft.VC90.CRT/*.manifest',
+ 'Microsoft.VC90.CRT/*.dll'],
+ 'h5py.tests': ['data/*.hdf5']}
-else:
+else: # Assume Unix-like
libraries = ['hdf5']
- if opts.HDF5_DIR is None:
+ if opts.HDF5 is None:
include_dirs = [numpy.get_include(), '/usr/include', '/usr/local/include']
library_dirs = ['/usr/lib/', '/usr/local/lib']
else:
- include_dirs = [numpy.get_include(), op.join(opts.HDF5_DIR, 'include')]
- library_dirs = [op.join(opts.HDF5_DIR, 'lib')]
+ include_dirs = [numpy.get_include(), op.join(opts.HDF5, 'include')]
+ library_dirs = [op.join(opts.HDF5, 'lib')]
runtime_dirs = library_dirs
extra_compile_args = ['-DH5_USE_16_API', '-Wno-unused', '-Wno-uninitialized']
extra_link_args = []
@@ -192,92 +251,29 @@ else:
package_data = {'h5py': ['*.pyx'],
'h5py.tests': ['data/*.hdf5']}
-# If for some reason the .c files are missing, Pyrex is required.
-cfiles = [op.join(src_path, x+'.c') for x in modules]
-
-if not all( [op.exists(x) for x in cfiles]):
- opts.ENABLE_PYREX = True
-
-if opts.ENABLE_PYREX and not opts.PYREX_FORCE_OFF:
- print "Running Pyrex..."
-
- try:
- from Pyrex.Compiler.Main import Version
-
- if Version.version >= MIN_PYREX:
- from Pyrex.Compiler.Main import compile_multiple, CompilationOptions
-
- # Check if the conditions.pxi file is up-to-date
- cond_path = op.join(src_path, 'conditions.pxi')
- cond = \
-"""
-%(AUTO_HDR)s
+# Explicit list of source files for each module.
+mod_paths = [op.join(opts.SRC_PATH, x) for x in modules]
+extra_paths = [op.join(opts.SRC_PATH, x) for x in extra_src]
+if opts.CYTHON:
+ module_sources = [[x+'.pyx']+extra_paths for x in mod_paths]
+else:
+ module_sources = [[x+'.c']+extra_paths for x in mod_paths]
-DEF H5PY_VERSION = "%(VERSION)s"
-DEF H5PY_API_MAJ = %(API_MAJ)d
-DEF H5PY_API_MIN = %(API_MIN)d
-DEF H5PY_DEBUG = %(DEBUG_LEVEL)d
-
-DEF H5PY_16API = H5PY_API_MIN == 6
-DEF H5PY_18API = H5PY_API_MIN == 8
-
-DEF H5PY_NONBLOCK = %(IO_NONBLOCK)d
-""" \
- % opts.__dict__
- try:
- cond_file = open(cond_path,'r')
- cond_present = cond_file.read()
- cond_file.close()
- except IOError:
- cond_present = ""
-
- # If we regenerate the file every time, Pyrex's timestamp checking
- # is useless. So only replace it if it's out of date.
- if cond_present != cond:
- print "Replacing conditions file..."
- cond_file = open(cond_path,'w')
- cond_file.write(cond)
- cond_file.close()
-
- pyxopts = CompilationOptions(verbose=True, timestamps=(not opts.PYREX_FORCE))
- results = compile_multiple( [op.join(src_path,x+'.pyx') for x in modules], pyxopts)
-
- if results.num_errors != 0:
- fatal("%d Pyrex compilation errors encountered; aborting." % results.num_errors)
- if opts.PYREX_ONLY:
- exit(0)
- else:
- fatal("Old Pyrex version %s detected (min %s)" % (Version.version, MIN_PYREX))
+extensions = [ Extension(opts.NAME+'.'+module,
+ sources,
+ include_dirs = include_dirs,
+ libraries = libraries,
+ library_dirs = library_dirs,
+ runtime_library_dirs = runtime_dirs,
+ extra_compile_args = extra_compile_args,
+ extra_link_args = extra_link_args)
+ for module, sources in zip(modules, module_sources) ]
- except ImportError:
- fatal("Pyrex recompilation required, but Pyrex not installed.")
-else:
- pass
- #print "Skipping Pyrex..."
-
-# One extension is built for each module
-extensions = []
-for module in modules:
- mod_sources = [op.join(src_path, module) +'.c']
- mod_sources += [op.join(src_path, x) for x in extra_src]
-
- extensions.append(
- Extension(
- NAME+'.'+module,
- mod_sources,
- include_dirs = include_dirs,
- libraries = libraries,
- library_dirs = library_dirs,
- runtime_library_dirs = runtime_dirs,
- extra_compile_args = extra_compile_args,
- extra_link_args = extra_link_args
- )
- )
# === Custom extensions for distutils =========================================
class test(Command):
- description = "Build %s and run unit tests" % NAME
+ description = "Build and run unit tests"
user_options = [('sections=','s','Comma separated list of tests ("-" prefix to NOT run)')]
def initialize_options(self):
@@ -302,7 +298,7 @@ class dev(Command):
description = "Developer commands (--doc, --clean, --readme=<file>)"
user_options = [('doc','d','Rebuild documentation'),
- ('clean', 'c', 'Remove built files and Pyrex temp files.')]
+ ('clean', 'c', 'Remove built files and Cython temp files.')]
boolean_options = ['doc']
def initialize_options(self):
@@ -320,8 +316,8 @@ class dev(Command):
shutil.rmtree(x)
except OSError:
pass
- fnames = [ op.join(src_path, x+'.dep') for x in modules ] + \
- [ op.join(src_path, x+'.c') for x in modules ] + \
+ fnames = [ op.join(opts.SRC_PATH, x+'.dep') for x in modules ] + \
+ [ op.join(opts.SRC_PATH, x+'.c') for x in modules ] + \
[ 'MANIFEST']
for name in fnames:
@@ -354,14 +350,9 @@ class dev(Command):
# New commands for setup (e.g. "python setup.py test")
if os.name == 'nt':
- CMD_CLASS = {'test': test}
+ opts.CMD_CLASS.update({'test': test})
else:
- CMD_CLASS = {'dev': dev, 'test': test}
-
-#print "Configuration"
-#print '-'*40
-#for key in sorted(opts.__dict__):
-# print "%-20s %s" % (key, opts.__dict__[key])
+ opts.CMD_CLASS.update({'dev': dev, 'test': test})
cls_txt = \
@@ -395,8 +386,8 @@ reading and writing data from Python.
"""
setup(
- name = NAME,
- version = VERSION,
+ name = opts.NAME,
+ version = opts.VERSION,
description = short_desc,
long_description = long_desc,
classifiers = [x for x in cls_txt.split("\n") if x],
@@ -408,8 +399,8 @@ setup(
packages = ['h5py','h5py.tests'],
package_data = package_data,
ext_modules = extensions,
- requires = ['numpy (>=1.0.3)'],
- cmdclass = CMD_CLASS
+ requires = ['numpy (>=%s)' % opts.MIN_NUMPY],
+ cmdclass = opts.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