[h5py] 124/455: Fix hashing, more thread decorators
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 b522c9ad2bba2ac2823f9e2515ac44fe47464400
Author: andrewcollette <andrew.collette at gmail.com>
Date: Mon Sep 22 06:43:06 2008 +0000
Fix hashing, more thread decorators
---
h5py/h5.pxd | 18 +++++----
h5py/h5.pyx | 118 +++++++++++++++++++++++++++++++++++++-----------------
h5py/h5d.pyx | 11 -----
h5py/h5f.pyx | 12 ------
h5py/h5g.pyx | 30 +++++++++-----
h5py/h5p.pyx | 12 ++++++
h5py/std_code.pxi | 4 +-
setup.py | 2 +-
8 files changed, 126 insertions(+), 81 deletions(-)
diff --git a/h5py/h5.pxd b/h5py/h5.pxd
index 51a2792..1697524 100644
--- a/h5py/h5.pxd
+++ b/h5py/h5.pxd
@@ -18,11 +18,6 @@ include "std_defs.pxi"
# === Custom C extensions =====================================================
-cdef int _enable_exceptions() except -1
-cdef int _disable_exceptions() except -1
-
-cdef object standard_richcmp(object self, object other, int how)
-
cdef class PHIL:
cdef object lock
@@ -36,8 +31,7 @@ cpdef PHIL get_phil()
cdef class H5PYConfig:
- # Global
- cdef object _complex_names # ('r','i')
+ cdef object _complex_names
cdef readonly object API_16
cdef readonly object API_18
cdef readonly object DEBUG
@@ -51,6 +45,9 @@ cdef class ObjectID:
cdef object _hash # Used by subclasses to cache a hash value,
# which may be expensive to compute.
+cdef object standard_richcmp(object self, object other, int how)
+cdef object obj_hash(ObjectID obj)
+
# === HDF5 API ================================================================
cdef extern from "hdf5.h":
@@ -64,7 +61,14 @@ cdef extern from "hdf5.h":
herr_t H5open() except *
herr_t H5close() except *
+ # For object hashing
+
+ ctypedef struct H5G_stat_t:
+ unsigned long fileno[2]
+ unsigned long objno[2]
+ herr_t H5Gget_objinfo(hid_t loc_id, char* name, int follow_link, H5G_stat_t *statbuf) except *
+
# --- Reflection ------------------------------------------------------------
ctypedef enum H5I_type_t:
H5I_BADID = -1
diff --git a/h5py/h5.pyx b/h5py/h5.pyx
index f529cdd..046baa4 100644
--- a/h5py/h5.pyx
+++ b/h5py/h5.pyx
@@ -48,24 +48,64 @@ IF H5PY_DEBUG:
log_threads = logging.getLogger('h5py.threads')
+def loglevel(lev):
+ """ (INT lev)
+
+ Shortcut to set the logging level on all library streams.
+ Does nothing if not built in debug mode.
+ """
+ IF H5PY_DEBUG:
+ for x in ('h5py.identifiers', 'h5py.functions', 'h5py.threads'):
+ l = logging.getLogger(x)
+ l.setLevel(lev)
+ ELSE:
+ pass
+
# --- C extensions and classes ------------------------------------------------
cdef object standard_richcmp(object self, object other, int how):
- # This needs to be shared because of weird CPython quirks involving
- # subclasses and the __hash__ method.
+ # HDF5 object identity is determined by comparing hash values. In the
+ # absence of a logical comparision method (for example, TypeId.equal()),
+ # this hash-based identity is used for comparison.
+
+ # Subject to:
+ # 1. Both must be of the same type
+ # 2. Both must be hashable
+ # 3. Only == and != comparisons are supported
+ #
+ # Otherwise NotImplemented is returned, for Python's fallback mechanics.
- if how == 2 or how == 3:
-
- if not isinstance(self, ObjectID) and isinstance(other, ObjectID):
- return NotImplemented
+ if how != 2 and how != 3:
+ return NotImplemented
+ if not type(self) == type(other) and isinstance(self, ObjectID):
+ return NotImplemented # Can't compare across types
+
+ try:
eq = (hash(self) == hash(other))
+ except TypeError:
+ return NotImplemented # Can't compare unhashable instances
- if how == 2:
- return eq
- return not eq
+ if how == 2:
+ return eq
+ return not eq
- return NotImplemented
+cdef object obj_hash(ObjectID obj):
+ # Try to compute the hash of the given file-resident object, raising
+ # TypeError if it can't be done.
+
+ # This is a counterpart to standard_richcmp.
+
+ cdef H5G_stat_t stat
+
+ phil.acquire()
+ try:
+ H5Gget_objinfo(obj.id, '.', 0, &stat)
+ return hash((stat.fileno[0], stat.fileno[1], stat.objno[0], stat.objno[1]))
+ except:
+ raise TypeError("Objects of class %s cannot be hashed" % obj.__class__.__name__)
+ finally:
+ phil.release()
cdef class H5PYConfig:
@@ -190,38 +230,45 @@ cdef class ObjectID:
across copies.
"""
cdef ObjectID copy
- copy = type(self)(self.id)
- 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:
- log_ident.debug("c %s" % str(self))
- return copy
+ phil.acquire()
+ try:
+ copy = type(self)(self.id)
+ if self._valid and not self._locked:
+ H5Iinc_ref(self.id)
+ copy._locked = self._locked
+ IF H5PY_DEBUG:
+ log_ident.debug("c %s" % str(self))
+ return copy
+ finally:
+ phil.release()
def __richcmp__(self, object other, int how):
""" Supports only == and != """
return standard_richcmp(self, other, how)
def __hash__(self):
- """ Hash method defaults to the identifer, as this cannot change over
- the life of the object.
+ """ By default HDF5 objects are hashed based on their file and object
+ numbers. Objects which are not file-resident cannot be hashed.
"""
- return self.id
+ if self._hash is None:
+ self._hash = obj_hash(self)
+ return self._hash
-
def __str__(self):
- ref = str(H5Iget_ref(self.id)) if self._valid else "X"
- lck = "L" if self._locked else "U"
-
- return "%s [%s] (%s) %d" % (self.__class__.__name__, ref, lck, self.id)
+ phil.acquire()
+ try:
+ ref = str(H5Iget_ref(self.id)) if self._valid else "X"
+ lck = "L" if self._locked else "U"
+ return "%s [%s] (%s) %d" % (self.__class__.__name__, ref, lck, self.id)
+ finally:
+ phil.release()
def __repr__(self):
return self.__str__()
# === HDF5 "H5" API ===========================================================
-
+ at sync
def get_libversion():
""" () => TUPLE (major, minor, release)
@@ -236,13 +283,13 @@ def get_libversion():
return (major, minor, release)
-
+ at sync
def _close():
""" Internal function; do not call unless you want to lose all your data.
"""
H5close()
-
+ at sync
def _open():
""" Internal function; do not call unless you want to lose all your data.
"""
@@ -253,9 +300,6 @@ def _open():
class H5Error(Exception):
""" Base class for internal HDF5 library exceptions.
- Subclass of EnvironmentError; errno is computed from the HDF5 major
- and minor error numbers:
- 1000*(major number) + minor number
"""
pass
@@ -444,7 +488,7 @@ cdef class ErrorStackElement:
cdef readonly unsigned int line
cdef readonly object desc
-
+ @sync
def __str__(self):
return '%2d:%2d "%s" at %s (%s: %s)' % (self.maj_num, self.min_num,
self.desc, self.func_name, H5Eget_major(<H5E_major_t>self.maj_num),
@@ -467,7 +511,7 @@ cdef herr_t walk_cb(int n, H5E_error_t *err_desc, void* stack_in):
return 0
-
+ at sync
def error_stack():
""" () => LIST error_stack
@@ -478,7 +522,7 @@ def error_stack():
H5Ewalk(H5E_WALK_DOWNWARD, walk_cb, <void*>stack)
return stack
-
+ at nosync
def error_string():
""" () => STRING error_stack
@@ -511,7 +555,7 @@ def error_string():
return msg
-
+ at sync
def clear():
""" ()
@@ -565,7 +609,7 @@ cdef int _disable_exceptions() except -1:
# === Library init ============================================================
-
+ at sync
def _exithack():
""" Internal function; do not call unless you want to lose all your data.
"""
diff --git a/h5py/h5d.pyx b/h5py/h5d.pyx
index 3d0ef86..7db815a 100644
--- a/h5py/h5d.pyx
+++ b/h5py/h5d.pyx
@@ -16,7 +16,6 @@
include "std_code.pxi"
# Pyrex compile-time imports
-from h5 cimport standard_richcmp
from h5s cimport H5S_ALL, H5S_UNLIMITED, H5S_SCALAR, H5S_SIMPLE, \
H5Sget_simple_extent_type, H5Sclose, H5Sselect_all, \
H5Sget_simple_extent_ndims, H5Sget_select_npoints
@@ -30,8 +29,6 @@ from h5 cimport HADDR_UNDEF
# Runtime imports
import h5
import h5t
-import h5s
-import h5g
import_array()
@@ -338,13 +335,5 @@ cdef class DatasetID(ObjectID):
"""
return H5Dget_storage_size(self.id)
- def __richcmp__(self, object other, int how):
- return standard_richcmp(self, other, how)
-
- def __hash__(self):
- if self._hash is None:
- info = h5g.get_objinfo(self)
- self._hash = hash( (info.fileno, info.objno) )
- return self._hash
diff --git a/h5py/h5f.pyx b/h5py/h5f.pyx
index 2ccf169..d132e34 100644
--- a/h5py/h5f.pyx
+++ b/h5py/h5f.pyx
@@ -16,7 +16,6 @@
include "std_code.pxi"
# Pyrex compile-time imports
-from h5 cimport standard_richcmp
from h5p cimport propwrap, pdefault, PropFAID, PropFCID, H5P_DEFAULT
from h5t cimport typewrap
from h5a cimport AttrID
@@ -28,7 +27,6 @@ from utils cimport emalloc, efree, pybool
# Runtime imports
import h5
-import h5g
# === Public constants and data structures ====================================
@@ -307,16 +305,6 @@ cdef class FileID(ObjectID):
only tracks free space until the file is closed.
"""
return H5Fget_freespace(self.id)
-
- def __richcmp__(self, object other, int how):
- return standard_richcmp(self, other, how)
-
- def __hash__(self):
- # Obtain the file number from the root group metadata
- if self._hash is None:
- info = h5g.get_objinfo(self)
- self._hash = hash(info.fileno)
- return self._hash
diff --git a/h5py/h5g.pyx b/h5py/h5g.pyx
index 1ad2bbf..50a8bbb 100644
--- a/h5py/h5g.pyx
+++ b/h5py/h5g.pyx
@@ -120,6 +120,7 @@ cdef class GroupIter:
# COMPAT: 1.8 update
IF H5PY_18API:
+ @sync
def open(ObjectID loc not None, char* name, PropID gapl=None):
""" (ObjectID loc, STRING name, PropGAID gapl=None)
@@ -127,6 +128,7 @@ IF H5PY_18API:
"""
return GroupID(H5Gopen2(loc.id, name, pdefault(gapl)))
ELSE:
+ @sync
def open(ObjectID loc not None, char* name):
""" (ObjectID loc, STRING name) => GroupID
@@ -136,6 +138,7 @@ ELSE:
# COMPAT: 1.8 update
IF H5PY_18API:
+ @sync
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,
@@ -147,6 +150,7 @@ IF H5PY_18API:
pdefault(gcpl),
pdefault(gapl)))
ELSE:
+ @sync
def create(ObjectID loc not None, char* name, int size_hint=-1):
""" (ObjectID loc, STRING name, INT size_hint=-1) => GroupID
@@ -176,6 +180,7 @@ cdef herr_t iter_cb_helper(hid_t gid, char *name, object int_tpl) except -1:
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
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,
@@ -212,6 +217,7 @@ IF H5PY_16API:
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
def get_objinfo(ObjectID obj not None, object name='.', int follow_link=1):
""" (ObjectID obj, STRING name='.', BOOL follow_link=True) => GroupStat object
@@ -256,6 +262,7 @@ cdef class GroupID(ObjectID):
def __init__(self, hid_t id_):
self.links = LinkProxy(id_)
+ @sync
def _close(self):
""" ()
@@ -269,6 +276,7 @@ cdef class GroupID(ObjectID):
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
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,
@@ -292,6 +300,7 @@ cdef class GroupID(ObjectID):
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
def unlink(self, char* name):
""" (STRING name)
@@ -301,6 +310,7 @@ cdef class GroupID(ObjectID):
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
def move(self, char* current_name, char* new_name, GroupID remote=None):
""" (STRING current_name, STRING new_name, GroupID remote=None)
@@ -318,6 +328,7 @@ cdef class GroupID(ObjectID):
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
def get_num_objs(self):
""" () => INT number_of_objects
@@ -329,6 +340,7 @@ cdef class GroupID(ObjectID):
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
def get_objname_by_idx(self, hsize_t idx):
""" (INT idx) => STRING object_name
@@ -356,6 +368,7 @@ cdef class GroupID(ObjectID):
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
def get_objtype_by_idx(self, hsize_t idx):
""" (INT idx) => INT object_type_code
@@ -378,6 +391,7 @@ cdef class GroupID(ObjectID):
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
def get_linkval(self, char* name):
""" (STRING name) => STRING link_value
@@ -408,6 +422,7 @@ cdef class GroupID(ObjectID):
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
def set_comment(self, char* name, char* comment):
""" (STRING name, STRING comment)
@@ -417,6 +432,7 @@ cdef class GroupID(ObjectID):
# COMPAT: 1.8 deprecation
IF H5PY_16API:
+ @sync
def get_comment(self, char* name):
""" (STRING name) => STRING comment
@@ -439,6 +455,7 @@ cdef class GroupID(ObjectID):
# === Special methods =====================================================
+ @sync
def __contains__(self, char* name):
""" (STRING name)
@@ -450,25 +467,16 @@ cdef class GroupID(ObjectID):
except H5Error:
return False
+ @nosync
def __iter__(self):
""" Return an iterator over the names of group members. """
return GroupIter(self)
+ @sync
def __len__(self):
""" Number of group members """
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:
- 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 3cfc98e..b02d229 100644
--- a/h5py/h5p.pyx
+++ b/h5py/h5p.pyx
@@ -17,6 +17,7 @@
# Pyrex compile-time imports
+from h5 cimport standard_richcmp
from utils cimport require_tuple, convert_dims, convert_tuple, \
emalloc, efree, pybool, require_list, \
check_numpy_write, check_numpy_read
@@ -32,6 +33,17 @@ import_array()
# === C API ===================================================================
+cdef class PropClassID(PropID):
+
+ def __richcmp__(self, object other, int how):
+ return standard_richcmp(self, other, how)
+
+ def __hash__(self):
+ """ Since classes are library-created and immutable, they are uniquely
+ identified by their HDF5 identifiers.
+ """
+ return hash(self.id)
+
cdef hid_t pdefault(PropID pid):
if pid is None:
diff --git a/h5py/std_code.pxi b/h5py/std_code.pxi
index 8d80420..ff7d280 100644
--- a/h5py/std_code.pxi
+++ b/h5py/std_code.pxi
@@ -17,8 +17,8 @@ include "config.pxi"
# Defines the following decorators:
#
-# sync: Acquire PHIL for this function, and log function entry and lock
-# acquisition in debug mode
+# sync: Acquire PHIL for this function, and log function entry in
+# debug mode.
# nosync: Don't acquire PHIL, but log function entry in debug mode.
#
diff --git a/setup.py b/setup.py
index b3fbce1..96c37b3 100644
--- a/setup.py
+++ b/setup.py
@@ -47,7 +47,7 @@ from distutils.command.sdist import sdist
# Basic package options
NAME = 'h5py'
-VERSION = '0.3.1'
+VERSION = '0.4.0'
MIN_NUMPY = '1.0.3'
MIN_CYTHON = '0.9.8.1'
KNOWN_API = (16,18) # Legal API levels (1.8.X or 1.6.X)
--
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