/usr/share/pyshared/h5py/api_gen.py is in python-h5py 2.0.1-1build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | import re
import warnings
class BadLineError(Exception):
pass
class UnknownCodeError(Exception):
pass
# The following files are used to talk to the HDF5 api:
#
# (1) hdf5.pxd: HDF5 function signatures (autogenerated)
# (2) hdf5_types.pxd: HDF5 type definitions (static)
# (3) defs.pxd: HDF5 function proxy defs (autogenerated)
# (4) defs.pyx: HDF5 function proxies (autogenerated)
function_pattern = r'((?P<api>([0-9]\.[0-9]))[ ]+)?(?P<code>(unsigned[ ]+)?[a-zA-Z_]+[a-zA-Z0-9_]*\**)[ ]+(?P<fname>[a-zA-Z_]+[a-zA-Z0-9_]*)[ ]*\((?P<sig>[a-zA-Z0-9_,* ]*)\)'
sig_pattern = r'(unsigned[ ]+)?(?:[a-zA-Z_]+[a-zA-Z0-9_]*\**)[ ]+[ *]*(?P<param>[a-zA-Z_]+[a-zA-Z0-9_]*)'
fp = re.compile(function_pattern)
sp = re.compile(sig_pattern)
raw_preamble = """\
include "config.pxi"
from api_types_hdf5 cimport *
from api_types_ext cimport *
"""
def_preamble = """\
include "config.pxi"
from api_types_hdf5 cimport *
from api_types_ext cimport *
"""
imp_preamble = """\
include "config.pxi"
from api_types_ext cimport *
from api_types_hdf5 cimport *
cimport _hdf5
from _errors cimport set_exception
"""
class FunctionCruncher2(object):
def __init__(self, stub=False):
self.stub = stub
def run(self):
# Function definitions file
self.functions = open('api_functions.txt','r')
# Create output files
self.raw_defs = open('_hdf5.pxd','w')
self.cython_def = open('defs.pxd','w')
self.cython_imp = open('defs.pyx','w')
self.raw_defs.write(raw_preamble)
self.cython_def.write(def_preamble)
self.cython_imp.write(imp_preamble)
self.raw_defs.write('cdef extern from "hdf5.h":\n')
for line in self.functions:
line = line.strip()
if not line or line[0] == '#':
continue
try:
self.handle_line(line)
except BadLineError:
warnings.warn("Skipped <<%s>>" % line)
self.functions.close()
self.cython_imp.close()
self.cython_def.close()
self.raw_defs.close()
def handle_line(self, line):
""" Parse a function definition line and output the correct code
to each of the output files. """
m = fp.match(line)
if m is None:
raise BadLineError("Signature for line <<%s>> did not match regexp" % line)
function_parts = m.groupdict()
self.raw_defs.write(' '+self.make_raw_sig(function_parts))
self.cython_def.write(self.make_cython_sig(function_parts))
self.cython_imp.write(self.make_cython_imp(function_parts))
def version_wrap(self, function_parts, string):
""" Perform indentation, etc. appropriate for version switching """
api = function_parts['api']
if api == '1.8':
out = "IF H5PY_18API:\n"
out += "\n".join(' '+x for x in string.split('\n'))+'\n'
return out
return string
def make_raw_sig(self, function_parts):
""" Build a "cdef extern"-style definition for an HDF5 function """
code = "%(code)s %(fname)s(%(sig)s)\n" % function_parts
return self.version_wrap(function_parts, code)
def make_cython_sig(self, function_parts):
""" Build Cython signature for wrapper function """
code = "cdef %(code)s %(fname)s(%(sig)s) except *\n" % function_parts
return self.version_wrap(function_parts, code)
def make_cython_imp(self, function_parts, stub=False):
""" Build a Cython wrapper implementation. If stub is True, do
nothing but call the function and return its value """
args = sp.findall(function_parts['sig'])
if args is None:
raise BadLineError("Can't understand function signature <<%s>>" % function_parts['sig'])
args = ", ".join(x[1] for x in args)
# Figure out what conditional to use for the error testing
code = function_parts['code']
if '*' in code or code in ('H5T_conv_t',):
condition = "==NULL"
retval = "NULL"
elif code in ('int', 'herr_t', 'htri_t', 'hid_t','hssize_t','ssize_t') \
or re.match(r'H5[A-Z]+_[a-zA-Z_]+_t',code):
condition = "<0"
retval = "-1"
elif code in ('unsigned int','haddr_t','hsize_t','size_t'):
condition = "==0"
retval = 0
else:
raise UnknownCodeError("Return code <<%s>> unknown" % self.code)
parts = function_parts.copy()
parts.update({'condition': condition, 'retval': retval, 'args': args})
# Have to use except * because Cython can't handle special types here
imp = """\
cdef %(code)s %(fname)s(%(sig)s) except *:
cdef %(code)s r
r = _hdf5.%(fname)s(%(args)s)
if r%(condition)s:
if set_exception():
return <%(code)s>%(retval)s;
return r
"""
stub_imp = """\
cdef %(code)s %(fname)s(%(sig)s) except *:
return hdf5.%(fname)s(%(args)s)
"""
return self.version_wrap(function_parts, (stub_imp if self.stub else imp) % parts)
if __name__ == '__main__':
import sys
stub = True if 'stub' in sys.argv else False
fc = FunctionCruncher2(stub)
fc.run()
|