Merge lp:~spud/spud/c-python-binding into lp:spud
- c-python-binding
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Cian Wilson |
Approved revision: | 452 |
Merged at revision: | 448 |
Proposed branch: | lp:~spud/spud/c-python-binding |
Merge into: | lp:spud |
Diff against target: |
1163 lines (+964/-56) 10 files modified
Makefile.in (+11/-3) configure (+1/-2) configure.in (+0/-1) debian/control (+12/-0) debian/diamond.copyright (+0/-1) debian/python-spud.copyright (+39/-0) debian/rules (+5/-2) python/libspud.c (+831/-0) python/setup.py (+9/-0) python/test_libspud.py (+56/-47) |
To merge this branch: | bzr merge lp:~spud/spud/c-python-binding |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Cian Wilson | Approve | ||
Patrick Farrell | Needs Fixing | ||
Review via email:
|
Commit message
Description of the change
This branch changes the default Python binding for libspud from python/ctypes to the C api.
The reason for this change is that the C api can do things that python/ctypes can't. In particular, it can access capsules that have been registered through the C api somewhere else. This functionality is exploited with a special case for when this module is ran inside of fluidity's python diagnostics: with a bit of void* shuffling, we can now use this C module to access fluidity's spud tree inside Python.
The first step was to convert the Python wrapper test into something executable. Then, the C module was extended incrementally until it passed all of the tests. So I think that the C module shouldn't make any difference to people who are using the libspud python bindings.
Cian Wilson: while this C module has a very small chunk that is fluidity specific, it is orthogonal to the rest of the code. From your perspective, this commit should (ideally) make no change whatsoever.
The C module was largely written by Nan Mao.
- 447. By Patrick Farrell
-
Get rid of a malloc that didn't have a corresponding free

Patrick Farrell (pefarrell) wrote : | # |
Ah, apologies, I agree it isn't obvious.
The way I was testing it was
python setup.py build
ln -s build/lib*
python test_libspud.py
I didn't add code to install the python bindings because there was no code to install the old ctypes bindings, either. But perhaps I should make a python-spud package too ...

Cian Wilson (cwilson) wrote : | # |
A python-spud package would be *very* useful indeed.
Can I ask you to explain the fluidity_api PyCapsule import to me? I can't find anything called fluidity_api in fluidity or in spud so I'm guessing I'm misunderstanding what this is doing. Is this really fluidity specific or could it be used in any model with embedded python? Within fluidity itself does this allow libspud to be used in both python state and the more traditional def val calls?

Patrick Farrell (pefarrell) wrote : | # |
I will make a python-spud package later, then.
Sure. Capsules are an idea introduced in python 3.1/2.7; there's more information about them in the "What's New" for 2.7. The basic idea is that a capsule contains a void* pointer, and you can register them to store them in a module. It's a mechanism for passing data between different C modules that interact with python; it's a way of passing stuff C -> Python -> different C again.
You can see how I plan to use them in the merge request for get-set-manager:
https:/
As this whole setup involves changes to libspud, to the python bindings, and to fluidity, I thought I would do them in a logical order. That's why you can't see the corresponding calls for setting PyCapsules in fluidity; it's not in the trunk yet. But you can take a look at
http://
to see the other half.
As for its fluidity-specific nature: the whole idea is not specific to fluidity. So we could make it the python-spud convention that you have to register a void* to the manager at "spud_api.
Yes, this means that libspud can be used both in the python state and the def val calls. The fluidity side of it happens in python_init, which is called at the start of the model setup and works for both.
- 448. By Patrick Farrell
-
Make a python-spud Debian package.

Patrick Farrell (pefarrell) wrote : | # |
I've made a Debian package of the Python bindings, python-spud.

Cian Wilson (cwilson) wrote : | # |
Thanks for the python package. Surprisingly /usr/lib/
My preference would be to have a more general spud_api for two reasons:
- my traditional abhorrence of anything fluidity, however small, being in spud, particularly if it would be useful to other programs
- I have python instances in my code too so this functionality would be useful if it were more generally available
If this is reasonably easily doable then I'd be happier.
- 449. By Patrick Farrell
-
Fix the python-spud package; thanks Cian.
- 450. By Patrick Farrell
-
s/fluidity_
api/spud_ manager

Patrick Farrell (pefarrell) wrote : | # |
Excellent, I'm glad that the C python module passes all of your tests.
You pointed out a flaw in the Debian packaging of python-spud; I needed to add an --install-
I've also changed the "fluidity_api". Now, model code that wants to expose its internal manager should encapsulate it and set it as "spud_manager.

Cian Wilson (cwilson) wrote : | # |
Um, the package no longer seems to install /usr/lib/
Thanks for generalising the api. I look forward to using this in my other code.

Patrick Farrell (pefarrell) wrote : | # |
Yes, site-packages is the wrong place to put it (according to Debian). If you take a look at
dpkg -c ../python-
it tells you the contents of the package:
drwxr-xr-x root/root 0 2011-08-04 18:18 ./
drwxr-xr-x root/root 0 2011-08-04 18:18 ./usr/
drwxr-xr-x root/root 0 2011-08-04 18:18 ./usr/lib/
drwxr-xr-x root/root 0 2011-08-04 18:18 ./usr/lib/
drwxr-xr-x root/root 0 2011-08-04 18:18 ./usr/lib/
-rw-r--r-- root/root 23120 2011-08-04 18:18 ./usr/lib/
drwxr-xr-x root/root 0 2011-08-04 18:18 ./usr/lib/pyshared/
drwxr-xr-x root/root 0 2011-08-04 18:18 ./usr/lib/
drwxr-xr-x root/root 0 2011-08-04 18:18 ./usr/share/
drwxr-xr-x root/root 0 2011-08-04 18:18 ./usr/share/
-rw-r--r-- root/root 201 2011-08-04 18:18 ./usr/share/
drwxr-xr-x root/root 0 2011-08-04 18:18 ./usr/share/doc/
drwxr-xr-x root/root 0 2011-08-04 18:18 ./usr/share/
-rw-r--r-- root/root 1656 2011-08-03 11:41 ./usr/share/
-rw-r--r-- root/root 2498 2011-07-29 11:33 ./usr/share/
lrwxrwxrwx root/root 0 2011-08-04 18:18 ./usr/lib/
lrwxrwxrwx root/root 0 2011-08-04 18:18 ./usr/lib/
If you install it and ask Python where it's getting it, it replies:
[pef@caoimhe:
dlopen(
import libspud # dynamically loaded from /usr/lib/

Cian Wilson (cwilson) wrote : | # |
I get:
cwilson@
drwxr-xr-x root/root 0 2011-08-04 11:10 ./
drwxr-xr-x root/root 0 2011-08-04 11:10 ./usr/
drwxr-xr-x root/root 0 2011-08-04 11:10 ./usr/share/
drwxr-xr-x root/root 0 2011-08-04 11:10 ./usr/share/doc/
drwxr-xr-x root/root 0 2011-08-04 11:10 ./usr/share/
-rw-r--r-- root/root 1656 2011-08-03 09:02 ./usr/share/
-rw-r--r-- root/root 2498 2011-08-01 14:56 ./usr/share/
and nothing else (I would expect the paths to be slightly different for me as I'm on python 2.7).
Just to be clear, what I've done in the branch is:
./configure && make clean && make && debuild -uc -us
some of which are probably superfluous but I was trying to be thorough.
- 451. By Patrick Farrell
-
Some more work on python-spud for natty
- 452. By Patrick Farrell
-
A grand game of whack-a-mole. This fixes the maverick build. We'll keep iterating until they all work ...

Patrick Farrell (pefarrell) wrote : | # |
You only need to debuild: it calls the configure and make.
It should be fixed now. There were a few problems with the natty build. I've also made it so that the package now supplies libspud bindings for all supported python versions (2.6 and 2.7 on maverick and natty).
[pef@doodson:
drwxr-xr-x root/root 0 2011-08-04 22:32 ./
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/share/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/share/
-rw-r--r-- root/root 201 2011-08-04 22:32 ./usr/share/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/share/doc/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/share/
-rw-r--r-- root/root 2498 2011-08-04 22:04 ./usr/share/
-rw-r--r-- root/root 1656 2011-08-04 22:04 ./usr/share/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/lib/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/lib/pyshared/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/lib/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/lib/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/lib/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/lib/
-rw-r--r-- root/root 23120 2011-08-04 22:32 ./usr/lib/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/lib/
drwxr-xr-x root/root 0 2011-08-04 22:32 ./usr/lib/
-rw-r--r-- root/root 23120 2011-08-04 22:32 ./usr/lib/
lrwxrwxrwx root/root 0 2011-08-04 22:32 ./usr/lib/
lrwxrwxrwx root/root 0 2011-08-04 22:32 ./usr/lib/
lrwxrwxrwx root/root 0 2011-08-04 22:32 ./usr/lib/
lrwxrwxrwx root/root 0 2011-08-04 22:32 ./usr/lib/

Cian Wilson (cwilson) wrote : | # |
Thanks Patrick. That works for me now and I've run it manually (and successfully) through my tests again.
Shame about lucid, which is what my buildbot is on (hence the manual bit). Out of curiosity, how were python packages built before dh_python2? I'm guessing upgrading that computer will be easier than backporting.

Patrick Farrell (pefarrell) wrote : | # |
It could have been dh_python, dh_pycentral or dh_pysupport. dh_python2 supplanted them all. You could try one of those? (I don't have a lucid machine to try it out on.)
In the mean time, I'll merge!
Preview Diff
1 | === modified file 'Makefile.in' |
2 | --- Makefile.in 2011-07-11 15:25:35 +0000 |
3 | +++ Makefile.in 2011-08-04 21:32:37 +0000 |
4 | @@ -57,7 +57,7 @@ |
5 | libspud.la: $(OBJS) |
6 | ./libtool --mode=link --tag=FC $(FC) $(FCFLAGS) -o $(LIB) $(OBJS) $(LIBS) -rpath @prefix@/lib |
7 | if test -f .libs/libspud.a; then cp .libs/libspud.a .; fi |
8 | - (if test -f .libs/libspud.so; then cp .libs/libspud.so .; fi) || true |
9 | + (if test -f .libs/libspud.so; then cp .libs/libspud.so ./libspud.so.0; ln -s libspud.so.0 libspud.so; fi) || true |
10 | |
11 | build-diamond: |
12 | cd diamond; python setup.py build; cd .. |
13 | @@ -72,13 +72,14 @@ |
14 | doc: |
15 | @cd doc; $(MAKE) spud_manual.pdf |
16 | |
17 | -install: install-libspud install-spudtools install-diamond |
18 | +install: install-libspud install-spudtools install-diamond install-pyspud |
19 | |
20 | install-libspud: libspud.la |
21 | @INSTALL@ -d $(DESTDIR)@prefix@/lib |
22 | @INSTALL@ -d $(DESTDIR)@prefix@/include |
23 | @INSTALL@ libspud.a $(DESTDIR)@prefix@/lib |
24 | - (if test -f libspud.so; then @INSTALL@ libspud.so $(DESTDIR)@prefix@/lib; fi) || true |
25 | + (if test -f libspud.so.0; then @INSTALL@ libspud.so.0 $(DESTDIR)@prefix@/lib; fi) || true |
26 | + (if test -f libspud.so; then cd $(DESTDIR)@prefix@/lib/; ln -s libspud.so.0 libspud.so; cd -; fi) || true |
27 | @INSTALL@ $(MODS) $(DESTDIR)@prefix@/include |
28 | @INSTALL@ $(HEADERS) $(DESTDIR)@prefix@/include |
29 | |
30 | @@ -93,6 +94,13 @@ |
31 | install-diamond: |
32 | cd diamond; python setup.py install --prefix=$(DESTDIR)@prefix@; cd .. |
33 | |
34 | +install-pyspud: |
35 | +ifeq ($(origin DESTDIR),undefined) |
36 | + cd python; python setup.py install --prefix=$(DESTDIR)@prefix@; cd .. |
37 | +else |
38 | + cd python; for python in $(shell pyversions -r); do $$python setup.py install --prefix=$(DESTDIR)@prefix@ --install-layout=deb; done; cd .. |
39 | +endif |
40 | + |
41 | clean: |
42 | @cd doc; $(MAKE) clean |
43 | rm -f *.o libspud.a libspud.so *.o *.la *.mod *.lo |
44 | |
45 | === modified file 'configure' |
46 | --- configure 2011-07-11 11:07:06 +0000 |
47 | +++ configure 2011-08-04 21:32:37 +0000 |
48 | @@ -21746,7 +21746,7 @@ |
49 | |
50 | |
51 | |
52 | -ac_config_files="$ac_config_files Makefile src/tests/Makefile examples/Makefile bin/spud-preprocess python/libspud.py diamond/setup.py diamond/diamond/plugins.py diamond/diamond/preprocess.py" |
53 | +ac_config_files="$ac_config_files Makefile src/tests/Makefile examples/Makefile bin/spud-preprocess diamond/setup.py diamond/diamond/plugins.py diamond/diamond/preprocess.py" |
54 | |
55 | cat >confcache <<\_ACEOF |
56 | # This file is a shell script that caches the results of configure |
57 | @@ -22986,7 +22986,6 @@ |
58 | "src/tests/Makefile") CONFIG_FILES="$CONFIG_FILES src/tests/Makefile" ;; |
59 | "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;; |
60 | "bin/spud-preprocess") CONFIG_FILES="$CONFIG_FILES bin/spud-preprocess" ;; |
61 | - "python/libspud.py") CONFIG_FILES="$CONFIG_FILES python/libspud.py" ;; |
62 | "diamond/setup.py") CONFIG_FILES="$CONFIG_FILES diamond/setup.py" ;; |
63 | "diamond/diamond/plugins.py") CONFIG_FILES="$CONFIG_FILES diamond/diamond/plugins.py" ;; |
64 | "diamond/diamond/preprocess.py") CONFIG_FILES="$CONFIG_FILES diamond/diamond/preprocess.py" ;; |
65 | |
66 | === modified file 'configure.in' |
67 | --- configure.in 2011-07-11 11:07:06 +0000 |
68 | +++ configure.in 2011-08-04 21:32:37 +0000 |
69 | @@ -306,5 +306,4 @@ |
70 | |
71 | AC_OUTPUT(Makefile src/tests/Makefile examples/Makefile |
72 | bin/spud-preprocess |
73 | - python/libspud.py |
74 | diamond/setup.py diamond/diamond/plugins.py diamond/diamond/preprocess.py) |
75 | |
76 | === modified file 'debian/control' |
77 | --- debian/control 2010-04-13 13:51:29 +0000 |
78 | +++ debian/control 2011-08-04 21:32:37 +0000 |
79 | @@ -50,3 +50,15 @@ |
80 | schema-aware editor such as Diamond. Spudtools contains the schema |
81 | for the spud base language and the spud-preprocess script for |
82 | converting schemas between the compact and xml syntaxes. |
83 | + |
84 | +Package: python-spud |
85 | +Section: python |
86 | +Architecture: any |
87 | +XB-Python-Version: ${python:Versions} |
88 | +Depends: libspud-dev (= ${binary:Version}), ${python:Depends}, ${misc:Depends} |
89 | +Description: An automatic options system for scientific models (python interface). |
90 | + Spud is an automatic options system which reads an xml options file |
91 | + into a dictionary for immediate access from within the model. The xml |
92 | + file is generated using a spud-compatible RELAX NG schema and a |
93 | + schema-aware editor such as Diamond. This package contains the Python |
94 | + bindings for libspud. |
95 | |
96 | === modified file 'debian/diamond.copyright' |
97 | --- debian/diamond.copyright 2008-09-26 13:42:19 +0000 |
98 | +++ debian/diamond.copyright 2011-08-04 21:32:37 +0000 |
99 | @@ -1,4 +1,3 @@ |
100 | -<<<<<<< .working |
101 | Except as noted below, Diamond is copyright (C) 2007 Imperial College |
102 | London and others. For a full list of contributors see the AUTHORS |
103 | file. |
104 | |
105 | === added file 'debian/python-spud.copyright' |
106 | --- debian/python-spud.copyright 1970-01-01 00:00:00 +0000 |
107 | +++ debian/python-spud.copyright 2011-08-04 21:32:37 +0000 |
108 | @@ -0,0 +1,39 @@ |
109 | +Except as noted below, Spud is copyright (C) 2007 Imperial College |
110 | +London and others. For a full list of contributors see the AUTHORS |
111 | +file. |
112 | + |
113 | +Spud is free software; you can redistribute it and/or |
114 | +modify it under the terms of the GNU Lesser General Public |
115 | +License as published by the Free Software Foundation; either |
116 | +version 2.1 of the License, or (at your option) any later version. |
117 | + |
118 | +This library is distributed in the hope that it will be useful, |
119 | +but WITHOUT ANY WARRANTY; without even the implied warranty of |
120 | +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
121 | +Lesser General Public License for more details. |
122 | + |
123 | +On Debian systems, the complete text of the GNU Lesser General Public |
124 | +License can be found in the file `/usr/share/common-licenses/LGPL-2.1'. |
125 | + |
126 | +----- |
127 | + |
128 | +Tinyxml is copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) |
129 | + |
130 | +This software is provided 'as-is', without any express or implied |
131 | +warranty. In no event will the authors be held liable for any |
132 | +damages arising from the use of this software. |
133 | + |
134 | +Permission is granted to anyone to use this software for any |
135 | +purpose, including commercial applications, and to alter it and |
136 | +redistribute it freely, subject to the following restrictions: |
137 | + |
138 | +1. The origin of this software must not be misrepresented; you must |
139 | +not claim that you wrote the original software. If you use this |
140 | +software in a product, an acknowledgment in the product documentation |
141 | +would be appreciated but is not required. |
142 | + |
143 | +2. Altered source versions must be plainly marked as such, and |
144 | +must not be misrepresented as being the original software. |
145 | + |
146 | +3. This notice may not be removed or altered from any source |
147 | +distribution. |
148 | \ No newline at end of file |
149 | |
150 | === modified file 'debian/rules' |
151 | --- debian/rules 2011-07-12 11:24:31 +0000 |
152 | +++ debian/rules 2011-08-04 21:32:37 +0000 |
153 | @@ -79,7 +79,10 @@ |
154 | echo "Failed to locate python egg, was it built correctly?" && exit 1 ; \ |
155 | fi |
156 | |
157 | -binary-arch: build-libspud install-libspud install-spudtools |
158 | +install-pyspud: |
159 | + $(MAKE) install-pyspud DESTDIR=$(CURDIR)/debian/python-spud |
160 | + |
161 | +binary-arch: build-libspud install-libspud install-spudtools install-pyspud |
162 | dh_testdir |
163 | dh_testroot |
164 | dh_installchangelogs |
165 | @@ -92,7 +95,7 @@ |
166 | # dh_installemacsen |
167 | # dh_installpam |
168 | # dh_installmime |
169 | -# dh_python |
170 | + dh_python2 |
171 | # dh_installinit |
172 | # dh_installcron |
173 | # dh_installinfo |
174 | |
175 | === added file 'python/libspud.c' |
176 | --- python/libspud.c 1970-01-01 00:00:00 +0000 |
177 | +++ python/libspud.c 2011-08-04 21:32:37 +0000 |
178 | @@ -0,0 +1,831 @@ |
179 | +#include <Python.h> |
180 | +#include <string.h> |
181 | +#include "spud.h" |
182 | +#include <stdio.h> |
183 | + |
184 | +#define MAXLENGTH 2048 |
185 | + |
186 | +static PyObject *SpudError; |
187 | +static PyObject *SpudTypeError; |
188 | +static PyObject *SpudKeyError; |
189 | +static PyObject *SpudFileError; |
190 | +static PyObject *SpudNewKeyWarning; |
191 | +static PyObject *SpudAttrSetFailedWarning; |
192 | +static PyObject *SpudShapeError; |
193 | +static PyObject *SpudRankError; |
194 | + |
195 | +void* manager; |
196 | + |
197 | +static PyObject * |
198 | +error_checking(int outcome, char *functionname) |
199 | +{ |
200 | + char errormessage [MAXLENGTH]; |
201 | + |
202 | + if (outcome == SPUD_KEY_ERROR){ |
203 | + snprintf(errormessage, MAXLENGTH, "Error: The specified option is not present \ |
204 | + in the dictionary in %s", functionname); |
205 | + PyErr_SetString(SpudKeyError, errormessage); |
206 | + return NULL; |
207 | + } |
208 | + if (outcome == SPUD_TYPE_ERROR){ |
209 | + snprintf(errormessage, MAXLENGTH, "Error: The specified option has a different \ |
210 | + type from that of the option argument provided in %s", functionname); |
211 | + PyErr_SetString(SpudTypeError, errormessage); |
212 | + return NULL; |
213 | + } |
214 | + if (outcome == SPUD_NEW_KEY_WARNING){ |
215 | + snprintf(errormessage, MAXLENGTH, "Warning: The option being inserted is not ] \ |
216 | + already in the dictionary %s", functionname); |
217 | + PyErr_SetString(SpudNewKeyWarning, errormessage); |
218 | + return NULL; |
219 | + } |
220 | + if (outcome == SPUD_FILE_ERROR){ |
221 | + snprintf(errormessage, MAXLENGTH, "Error: The specified options file cannot be \ |
222 | + read or written to as the routine requires in %s", functionname); |
223 | + PyErr_SetString(SpudFileError, errormessage); |
224 | + return NULL; |
225 | + } |
226 | + if (outcome == SPUD_RANK_ERROR){ |
227 | + snprintf(errormessage, MAXLENGTH, "Error: The specified option has a different rank from \ |
228 | + that of the option argument provided %s", functionname); |
229 | + PyErr_SetString(SpudRankError, errormessage); |
230 | + return NULL; |
231 | + } |
232 | + if (outcome == SPUD_SHAPE_ERROR){ |
233 | + snprintf(errormessage, MAXLENGTH, "Error: The specified option has a different shape from \ |
234 | + that of the option argument provided in %s", functionname); |
235 | + PyErr_SetString(SpudShapeError, errormessage); |
236 | + return NULL; |
237 | + } |
238 | + if (outcome == SPUD_ATTR_SET_FAILED_WARNING){ |
239 | + snprintf(errormessage, MAXLENGTH, "Warning: The option being set as an attribute can not be \ |
240 | + set as an attribute in %s", functionname); |
241 | + PyErr_SetString(SpudAttrSetFailedWarning, errormessage); |
242 | + return NULL; |
243 | + } |
244 | + if (outcome == SPUD_NO_ERROR){ |
245 | + Py_RETURN_NONE; |
246 | + } |
247 | + |
248 | + PyErr_SetString(SpudError,"Error: error checking failed."); |
249 | + return NULL; |
250 | +} |
251 | + |
252 | +static PyObject * |
253 | +libspud_load_options(PyObject *self, PyObject *args) |
254 | +{ |
255 | + const char *key; |
256 | + int key_len; |
257 | + int outcomeLoadOptions; |
258 | + |
259 | + if (!PyArg_ParseTuple(args, "s", &key)) |
260 | + return NULL; |
261 | + key_len = strlen(key); |
262 | + outcomeLoadOptions = spud_load_options(key,key_len); |
263 | + |
264 | + return error_checking(outcomeLoadOptions, "load options"); |
265 | +} |
266 | + |
267 | +static PyObject* |
268 | +libspud_print_options(PyObject *self, PyObject *args) |
269 | +{ |
270 | + spud_print_options(); |
271 | + |
272 | + Py_RETURN_NONE; |
273 | +} |
274 | + |
275 | +static PyObject * |
276 | +libspud_get_number_of_children(PyObject *self, PyObject *args) |
277 | +{ |
278 | + const char *key; |
279 | + int key_len; |
280 | + int child_count; |
281 | + int outcomeGetNumChildren; |
282 | + |
283 | + if (!PyArg_ParseTuple(args, "s", &key)) |
284 | + return NULL; |
285 | + key_len = strlen(key); |
286 | + outcomeGetNumChildren = spud_get_number_of_children(key, key_len, &child_count); |
287 | + if (error_checking(outcomeGetNumChildren, "get number of children") == NULL){ |
288 | + return NULL; |
289 | + } |
290 | + |
291 | + return Py_BuildValue("i", child_count); |
292 | +} |
293 | + |
294 | +static PyObject * |
295 | +libspud_get_child_name(PyObject *self, PyObject *args) |
296 | +{ |
297 | + const char *key; |
298 | + int key_len; |
299 | + int index; |
300 | + char child_name [MAXLENGTH]; |
301 | + int i; |
302 | + int outcomeGetChildName; |
303 | + |
304 | + for (i = 0; i < MAXLENGTH; i++){ |
305 | + child_name[i] = '\0'; |
306 | + } |
307 | + if (!PyArg_ParseTuple(args, "si", &key, &index)){ |
308 | + return NULL; |
309 | + } |
310 | + key_len = strlen(key); |
311 | + outcomeGetChildName = spud_get_child_name(key, key_len, index, child_name, MAXLENGTH); |
312 | + if (error_checking(outcomeGetChildName, "get child name") == NULL){ |
313 | + return NULL; |
314 | + } |
315 | + |
316 | + return Py_BuildValue("s", child_name); |
317 | +} |
318 | + |
319 | +static PyObject * |
320 | +libspud_option_count(PyObject *self, PyObject *args) |
321 | +{ |
322 | + const char *key; |
323 | + int key_len; |
324 | + int numoptions; |
325 | + |
326 | + if (!PyArg_ParseTuple(args, "s", &key)){ |
327 | + return NULL; |
328 | + } |
329 | + key_len = strlen(key); |
330 | + numoptions = spud_option_count(key, key_len); |
331 | + |
332 | + return Py_BuildValue("i", numoptions); |
333 | +} |
334 | + |
335 | +static PyObject * |
336 | +libspud_have_option(PyObject *self, PyObject *args) |
337 | +{ |
338 | + const char *key; |
339 | + int key_len; |
340 | + int haveoption; |
341 | + |
342 | + if (!PyArg_ParseTuple(args, "s", &key)){ |
343 | + return NULL; |
344 | + } |
345 | + key_len = strlen(key); |
346 | + haveoption = spud_have_option(key, key_len); |
347 | + |
348 | + if (haveoption == 0){ |
349 | + Py_RETURN_FALSE; |
350 | + } |
351 | + else{ |
352 | + Py_RETURN_TRUE; |
353 | + } |
354 | +} |
355 | + |
356 | +static PyObject * |
357 | +libspud_add_option(PyObject *self, PyObject *args) |
358 | +{ |
359 | + const char *key; |
360 | + int key_len; |
361 | + int outcomeAddOption; |
362 | + |
363 | + if (!PyArg_ParseTuple(args, "s", &key)){ |
364 | + return NULL; |
365 | + } |
366 | + key_len = strlen(key); |
367 | + outcomeAddOption = spud_add_option(key, key_len); |
368 | + return error_checking(outcomeAddOption, "add option"); |
369 | + |
370 | +} |
371 | + |
372 | +static PyObject * |
373 | +libspud_get_option_type(PyObject *self, PyObject *args) |
374 | +{ |
375 | + const char *key; |
376 | + int key_len; |
377 | + int type; |
378 | + int outcomeGetOptionType; |
379 | + |
380 | + if (!PyArg_ParseTuple(args, "s", &key)){ |
381 | + return NULL; |
382 | + } |
383 | + key_len = strlen(key); |
384 | + outcomeGetOptionType = spud_get_option_type(key, key_len, &type); |
385 | + if (error_checking(outcomeGetOptionType, "get option type") == NULL){ |
386 | + return NULL; |
387 | + } |
388 | + if (type == SPUD_DOUBLE){ |
389 | + Py_INCREF(&PyFloat_Type); |
390 | + return (PyObject*) &PyFloat_Type; |
391 | + } |
392 | + else if (type == SPUD_INT){ |
393 | + Py_INCREF(&PyInt_Type); |
394 | + return (PyObject*) &PyInt_Type; |
395 | + } |
396 | + else if (type == SPUD_NONE){ |
397 | + Py_RETURN_NONE; |
398 | + } |
399 | + else if (type == SPUD_STRING){ |
400 | + Py_INCREF(&PyString_Type); |
401 | + return (PyObject*) &PyString_Type; |
402 | + } |
403 | + |
404 | + PyErr_SetString(SpudError,"Error: Get option type function failed"); |
405 | + return NULL; |
406 | +} |
407 | + |
408 | +static PyObject * |
409 | +libspud_get_option_rank(PyObject *self, PyObject *args) |
410 | +{ |
411 | + const char *key; |
412 | + int key_len; |
413 | + int rank; |
414 | + int outcomeGetOptionRank; |
415 | + |
416 | + if (!PyArg_ParseTuple(args, "s", &key)){ |
417 | + return NULL; |
418 | + } |
419 | + key_len = strlen(key); |
420 | + outcomeGetOptionRank = spud_get_option_rank(key, key_len, &rank); |
421 | + if (error_checking(outcomeGetOptionRank, "get option rank") == NULL){ |
422 | + return NULL; |
423 | + } |
424 | + |
425 | + return Py_BuildValue("i", rank); |
426 | +} |
427 | + |
428 | +static PyObject * |
429 | +libspud_get_option_shape(PyObject *self, PyObject *args) |
430 | +{ |
431 | + const char *key; |
432 | + int key_len; |
433 | + int shape[2]; |
434 | + int outcomeGetOptionShape; |
435 | + |
436 | + if (!PyArg_ParseTuple(args, "s", &key)){ |
437 | + return NULL; |
438 | + } |
439 | + key_len = strlen(key); |
440 | + outcomeGetOptionShape = spud_get_option_shape(key, key_len, shape); |
441 | + if (error_checking(outcomeGetOptionShape, "get option shape") == NULL){ |
442 | + return NULL; |
443 | + } |
444 | + |
445 | + return Py_BuildValue("(i,i)", shape[0],shape[1]); |
446 | +} |
447 | + |
448 | +static PyObject* |
449 | +spud_get_option_aux_list_ints(const char *key, int key_len, int type, int rank, int *shape) |
450 | +{ // this function is for getting option when the option is of type a list of ints |
451 | + int outcomeGetOption; |
452 | + int size = shape[0]; |
453 | + int val [size]; |
454 | + int j; |
455 | + |
456 | + outcomeGetOption = spud_get_option(key, key_len, val); |
457 | + if (error_checking(outcomeGetOption, "get option aux list") == NULL){ |
458 | + return NULL; |
459 | + } |
460 | + PyObject* pylist = PyList_New(size); |
461 | + if (pylist == NULL){ |
462 | + printf("New list error."); |
463 | + return NULL; |
464 | + } |
465 | + for (j = 0; j < size; j++){ |
466 | + PyObject* element = Py_BuildValue("i", val[j]); |
467 | + PyList_SetItem(pylist, j, element); |
468 | + } |
469 | + |
470 | + return pylist; |
471 | +} |
472 | + |
473 | +static PyObject* |
474 | +spud_get_option_aux_list_doubles(const char *key, int key_len, int type, int rank, int *shape) |
475 | +{ // this function is for getting option when the option is of type a list of doubles |
476 | + int outcomeGetOption; |
477 | + int size = shape[0]; |
478 | + double val [size]; |
479 | + int j; |
480 | + |
481 | + outcomeGetOption = spud_get_option(key, key_len, val); |
482 | + if (error_checking(outcomeGetOption, "get option aux list") == NULL){ |
483 | + return NULL; |
484 | + } |
485 | + PyObject* pylist = PyList_New(size); |
486 | + if (pylist == NULL){ |
487 | + printf("New list error."); |
488 | + return NULL; |
489 | + } |
490 | + for (j = 0; j < size; j++){ |
491 | + PyObject* element = Py_BuildValue("f", val[j]); |
492 | + PyList_SetItem(pylist, j, element); |
493 | + } |
494 | + |
495 | + return pylist; |
496 | +} |
497 | + |
498 | +static PyObject * |
499 | +spud_get_option_aux_scalar_or_string(const char *key, int key_len, int type, int rank, int *shape) |
500 | +{ // this function is for getting option when the option is of type a scalar or string |
501 | + int outcomeGetOption; |
502 | + |
503 | + if (type == SPUD_DOUBLE){ |
504 | + float val; |
505 | + outcomeGetOption = spud_get_option(key, key_len, &val); |
506 | + if (error_checking(outcomeGetOption, "get option aux scalar or string") == NULL){ |
507 | + return NULL; |
508 | + } |
509 | + return Py_BuildValue("f", val); |
510 | + } |
511 | + else if (type == SPUD_INT){ |
512 | + int val; |
513 | + outcomeGetOption = spud_get_option(key, key_len, &val); |
514 | + if (error_checking(outcomeGetOption, "get option aux scalar or string") == NULL){ |
515 | + return NULL; |
516 | + } |
517 | + return Py_BuildValue("i", val); |
518 | + } |
519 | + else if (type == SPUD_STRING) { |
520 | + int size = shape[0]; |
521 | + char val[size+1]; |
522 | + int i; |
523 | + for (i = 0; i < size+1; i++) |
524 | + val[i] = '\0'; |
525 | + |
526 | + outcomeGetOption = spud_get_option(key, key_len, val); |
527 | + if (error_checking(outcomeGetOption, "get option aux scalar or string") == NULL){ |
528 | + return NULL; |
529 | + } |
530 | + return Py_BuildValue("s", val); |
531 | + } |
532 | + |
533 | + PyErr_SetString(SpudError,"Error: Get option aux scalar failed"); |
534 | + return NULL; |
535 | +} |
536 | + |
537 | +static PyObject* |
538 | +spud_get_option_aux_tensor_doubles(const char *key, int key_len, int type, int rank, int *shape) |
539 | +{ // this function is for getting option when the option is of type a tensor o doubles |
540 | + int outcomeGetOption; |
541 | + int rowsize = shape[0]; |
542 | + int colsize = shape[1]; |
543 | + int size = rowsize*colsize; |
544 | + double val [size]; |
545 | + int m; |
546 | + int n; |
547 | + int counter; |
548 | + |
549 | + outcomeGetOption = spud_get_option(key, key_len, val); |
550 | + if (error_checking(outcomeGetOption, "get option aux tensor") == NULL){ |
551 | + return NULL; |
552 | + } |
553 | + PyObject* pylist = PyList_New(rowsize); |
554 | + if (pylist == NULL){ |
555 | + printf("New list error"); |
556 | + return NULL; |
557 | + } |
558 | + counter = 0; |
559 | + for (m = 0; m < rowsize; m++){ |
560 | + PyObject* pysublist = PyList_New(colsize); |
561 | + if (pysublist == NULL){ |
562 | + printf("New sublist error"); |
563 | + return NULL; |
564 | + } |
565 | + for (n = 0; n < colsize; n++){ |
566 | + PyObject* element = Py_BuildValue("f", val[counter]); |
567 | + PyList_SetItem(pysublist, n, element); |
568 | + counter++; |
569 | + } |
570 | + PyList_SetItem(pylist, m, pysublist); |
571 | + } |
572 | + |
573 | + return pylist; |
574 | +} |
575 | + |
576 | +static PyObject* |
577 | +spud_get_option_aux_tensor_ints(const char *key, int key_len, int type, int rank, int *shape) |
578 | +{ // this function is for getting option when the option is of type a tensor of ints |
579 | + int outcomeGetOption; |
580 | + int rowsize = shape[0]; |
581 | + int colsize = shape[1]; |
582 | + int size = rowsize*colsize; |
583 | + int val [size]; |
584 | + int m; |
585 | + int n; |
586 | + int counter; |
587 | + |
588 | + outcomeGetOption = spud_get_option(key, key_len, val); |
589 | + if (error_checking(outcomeGetOption, "get option aux tensor") == NULL){ |
590 | + return NULL; |
591 | + } |
592 | + PyObject* pylist = PyList_New(rowsize); |
593 | + if (pylist == NULL){ |
594 | + printf("New list error"); |
595 | + return NULL; |
596 | + } |
597 | + counter = 0; |
598 | + for (m = 0; m < rowsize; m++){ |
599 | + PyObject* pysublist = PyList_New(colsize); |
600 | + if (pysublist == NULL){ |
601 | + printf("New sublist error"); |
602 | + return NULL; |
603 | + } |
604 | + for (n = 0; n < colsize; n++){ |
605 | + PyObject* element = Py_BuildValue("f", val[counter]); |
606 | + PyList_SetItem(pysublist, n, element); |
607 | + counter++; |
608 | + } |
609 | + PyList_SetItem(pylist, m, pysublist); |
610 | + } |
611 | + |
612 | + return pylist; |
613 | +} |
614 | + |
615 | +static PyObject * |
616 | +libspud_get_option(PyObject *self, PyObject *args) |
617 | +{ |
618 | + const char *key; |
619 | + int key_len; |
620 | + int type; |
621 | + int rank = 0; |
622 | + int shape[2]; |
623 | + int outcomeGetOptionType; |
624 | + int outcomeGetOptionRank; |
625 | + int outcomeGetOptionShape; |
626 | + |
627 | + if(!PyArg_ParseTuple(args, "s", &key)){ |
628 | + return NULL; |
629 | + } |
630 | + key_len = strlen(key); |
631 | + outcomeGetOptionRank = spud_get_option_rank(key, key_len, &rank); |
632 | + if (error_checking(outcomeGetOptionRank, "get option") == NULL){ |
633 | + return NULL; |
634 | + } |
635 | + outcomeGetOptionType = spud_get_option_type(key, key_len, &type); |
636 | + if (error_checking(outcomeGetOptionType, "get option") == NULL){ |
637 | + return NULL; |
638 | + } |
639 | + outcomeGetOptionShape = spud_get_option_shape(key, key_len, shape); |
640 | + if (error_checking(outcomeGetOptionShape, "get option") == NULL){ |
641 | + return NULL; |
642 | + } |
643 | + |
644 | + if (rank == -1){ // type error |
645 | + char errormessage [MAXLENGTH]; |
646 | + snprintf(errormessage, MAXLENGTH, "Error: The specified option has a different \ |
647 | + type from that of the option argument provided in %s", "get option"); |
648 | + PyErr_SetString(SpudTypeError, errormessage); |
649 | + return NULL; |
650 | + } |
651 | + else if (rank == 0){ // scalar |
652 | + return spud_get_option_aux_scalar_or_string(key, key_len, type, rank, shape); |
653 | + } |
654 | + else if (rank == 1){ // list or string |
655 | + if (type == SPUD_INT){ //a list of ints |
656 | + return spud_get_option_aux_list_ints(key, key_len, type, rank, shape); |
657 | + } |
658 | + else if (type == SPUD_DOUBLE){ //a list of doubles |
659 | + return spud_get_option_aux_list_doubles(key, key_len, type, rank, shape); |
660 | + } |
661 | + else if (type == SPUD_STRING){ //string |
662 | + return spud_get_option_aux_scalar_or_string(key, key_len, type, rank, shape); |
663 | + } |
664 | + } |
665 | + else if (rank == 2){ // tensor |
666 | + if (type == SPUD_DOUBLE){ //a tensor of doubles |
667 | + return spud_get_option_aux_tensor_doubles(key, key_len, type, rank, shape); |
668 | + } |
669 | + else if (type == SPUD_INT){ //a tensor of ints |
670 | + return spud_get_option_aux_tensor_ints(key, key_len, type, rank, shape); |
671 | + } |
672 | + } |
673 | + |
674 | + PyErr_SetString(SpudError,"Error: Get option failed."); |
675 | + return NULL; |
676 | +} |
677 | +static PyObject* |
678 | +set_option_aux_list_ints(PyObject *pylist, const char *key, int key_len, int type, int rank, int *shape) |
679 | +{ // this function is for setting option when the second argument is of type a list of ints |
680 | + int j; |
681 | + int psize = PyList_Size(pylist); |
682 | + shape[0] = psize; |
683 | + int val[psize] ; |
684 | + int outcomeSetOption; |
685 | + int element; |
686 | + |
687 | + for (j = 0; j < psize; j++){ |
688 | + element = -1; |
689 | + PyObject* pelement = PyList_GetItem(pylist, j); |
690 | + PyArg_Parse(pelement, "i", &element); |
691 | + val[j] = element; |
692 | + } |
693 | + outcomeSetOption = spud_set_option(key, key_len, val, type, rank, shape); |
694 | + if (error_checking(outcomeSetOption, "set option aux list ints") == NULL){ |
695 | + return NULL; |
696 | + } |
697 | + Py_RETURN_NONE; |
698 | +} |
699 | + |
700 | +static PyObject* |
701 | +set_option_aux_list_doubles(PyObject *pylist, const char *key, int key_len, int type, int rank, int *shape) |
702 | +{ // this function is for setting option when the second argument is of type a list of doubles |
703 | + int j; |
704 | + int psize = PyList_Size(pylist); |
705 | + shape[0] = psize; |
706 | + double val [psize]; |
707 | + int outcomeSetOption; |
708 | + double element; |
709 | + |
710 | + for (j = 0; j < psize; j++){ |
711 | + element = -1.0; |
712 | + PyObject* pelement = PyList_GetItem(pylist, j); |
713 | + PyArg_Parse(pelement, "f", &element); |
714 | + val[j] = element; |
715 | + } |
716 | + outcomeSetOption = spud_set_option(key, key_len, val, type, rank, shape); |
717 | + if (error_checking(outcomeSetOption, "set option aux list ints") == NULL){ |
718 | + return NULL; |
719 | + } |
720 | + |
721 | + Py_RETURN_NONE; |
722 | +} |
723 | + |
724 | +static PyObject* |
725 | +set_option_aux_string(PyObject *pystring, const char *key, int key_len, int type, int rank, int *shape) |
726 | +{ // this function is for setting option when the second argument is of type string |
727 | + char *val = PyString_AsString(pystring); |
728 | + int outcomeSetOption = spud_set_option(key, key_len, val, type, rank, shape); |
729 | + return error_checking(outcomeSetOption, "set option aux string"); |
730 | +} |
731 | + |
732 | +static PyObject* |
733 | +libspud_set_option_attribute(PyObject *self, PyObject *args) |
734 | +{ |
735 | + const char*key; |
736 | + int key_len; |
737 | + PyObject* firstArg; |
738 | + PyObject* secondArg; |
739 | + const char*val; |
740 | + int val_len; |
741 | + int outcomeSetOption; |
742 | + |
743 | + firstArg = PyTuple_GetItem(args, 0); |
744 | + secondArg = PyTuple_GetItem(args, 1); |
745 | + PyArg_Parse(firstArg, "s", &key); |
746 | + key_len = strlen(key); |
747 | + PyArg_Parse(secondArg, "s", &val); |
748 | + val_len = strlen(val); |
749 | + outcomeSetOption = spud_set_option_attribute(key, key_len, val, val_len); |
750 | + return error_checking(outcomeSetOption, "set option attribute"); |
751 | +} |
752 | + |
753 | +static PyObject* |
754 | +libspud_delete_option(PyObject *self, PyObject *args) |
755 | +{ |
756 | + const char*key; |
757 | + int key_len; |
758 | + PyObject* firstArg; |
759 | + int outcomeDeleteOption; |
760 | + |
761 | + firstArg = PyTuple_GetItem(args, 0); |
762 | + PyArg_Parse(firstArg, "s", &key); |
763 | + key_len = strlen(key); |
764 | + outcomeDeleteOption = spud_delete_option(key, key_len); |
765 | + return error_checking(outcomeDeleteOption, "delete option"); |
766 | +} |
767 | + |
768 | +static PyObject* |
769 | +set_option_aux_tensor_doubles(PyObject *pylist, const char *key, int key_len, int type, int rank, int *shape) |
770 | +{ // this function is for setting option when the second argument is of type a tensor of doubles |
771 | + int i; |
772 | + int j; |
773 | + int counter = 0; |
774 | + int pylistsize = PyList_Size(pylist); |
775 | + shape[0] = pylistsize; |
776 | + |
777 | + int outcomeSetOption; |
778 | + int pysublistsize; |
779 | + PyObject* pysublist = PyList_GetItem(pylist, 0); |
780 | + pysublistsize = PyList_Size(pysublist); |
781 | + int size = pylistsize*pysublistsize; |
782 | + |
783 | + double element; |
784 | + double val [size]; |
785 | + |
786 | + for (i = 0; i < pylistsize; i++){ |
787 | + PyObject* pysublist = PyList_GetItem(pylist, i); |
788 | + pysublistsize = PyList_Size(pysublist); |
789 | + shape[1] = pysublistsize; |
790 | + for (j = 0; j < pysublistsize; j++){ |
791 | + element = -1.0; |
792 | + PyObject* pysublistElement = PyList_GetItem(pysublist, j); |
793 | + PyArg_Parse(pysublistElement, "d", &element); |
794 | + val[counter] = element; |
795 | + counter ++; |
796 | + } |
797 | + } |
798 | + |
799 | + outcomeSetOption = spud_set_option(key, key_len, val, type, rank, shape); |
800 | + return error_checking(outcomeSetOption, "set option aux tensor doubles"); |
801 | +} |
802 | + |
803 | +static PyObject* |
804 | +set_option_aux_tensor_ints(PyObject *pylist, const char *key, int key_len, int type, int rank, int *shape) |
805 | +{ // this function is for setting option when the second argument is of type a tensor of ints |
806 | + int i; |
807 | + int j; |
808 | + int counter = 0; |
809 | + int pylistsize = PyList_Size(pylist); |
810 | + shape[0] = pylistsize; |
811 | + int pysublistsize; |
812 | + PyObject* pysublist = PyList_GetItem(pylist, 0); |
813 | + pysublistsize = PyList_Size(pysublist); |
814 | + int size = pylistsize*pysublistsize; |
815 | + int val [size]; |
816 | + int outcomeSetOption; |
817 | + |
818 | + int element; |
819 | + |
820 | + for (i = 0; i < pylistsize; i++){ |
821 | + PyObject* pysublist = PyList_GetItem(pylist, i); |
822 | + pysublistsize = PyList_Size(pysublist); |
823 | + shape[1] = pysublistsize; |
824 | + for (j = 0; j < pysublistsize; j++){ |
825 | + element = 1; |
826 | + PyObject* pysublistElement = PyList_GetItem(pysublist, j); |
827 | + PyArg_Parse(pysublistElement, "i", &element); |
828 | + val[counter] = element; |
829 | + counter ++; |
830 | + } |
831 | + } |
832 | + |
833 | + outcomeSetOption = spud_set_option(key, key_len, val, type, rank, shape); |
834 | + return error_checking(outcomeSetOption, "set option aux tensor doubles"); |
835 | +} |
836 | + |
837 | +static PyObject* |
838 | +set_option_aux_scalar(PyObject *pyscalar, const char *key, int key_len, int type, int rank, int *shape) |
839 | +{ // this function is for setting option when the second argument is of type scalar |
840 | + int outcomeSetOption = SPUD_NO_ERROR; |
841 | + |
842 | + if (type == SPUD_DOUBLE){ //scalar is double |
843 | + double val; |
844 | + PyArg_Parse(pyscalar, "f", &val); |
845 | + outcomeSetOption = spud_set_option(key, key_len, &val, type, rank, shape); |
846 | + } |
847 | + else if (type == SPUD_INT){ |
848 | + int val; |
849 | + PyArg_Parse(pyscalar, "i", &val); |
850 | + outcomeSetOption = spud_set_option(key, key_len, &val, type, rank, shape); |
851 | + } |
852 | + |
853 | + return error_checking(outcomeSetOption, "set option aux scalar"); |
854 | +} |
855 | + |
856 | + |
857 | +static PyObject* |
858 | +libspud_set_option(PyObject *self, PyObject *args) |
859 | +{ |
860 | + const char *key; |
861 | + int key_len; |
862 | + int type; |
863 | + int rank; |
864 | + int shape[2]; |
865 | + int outcomeGetRank; |
866 | + int outcomeGetShape; |
867 | + int outcomeGetType; |
868 | + PyObject* firstArg; |
869 | + PyObject* secondArg; |
870 | + |
871 | + firstArg = PyTuple_GetItem(args, 0); |
872 | + secondArg = PyTuple_GetItem(args, 1); |
873 | + PyArg_Parse(firstArg, "s", &key); |
874 | + key_len = strlen(key); |
875 | + outcomeGetType = spud_get_option_type(key, key_len, &type); |
876 | + if (error_checking(outcomeGetType, "set option") == NULL){ |
877 | + return NULL; |
878 | + } |
879 | + outcomeGetRank = spud_get_option_rank(key, key_len, &rank); |
880 | + if (error_checking(outcomeGetRank, "set option") == NULL){ |
881 | + return NULL; |
882 | + } |
883 | + outcomeGetShape = spud_get_option_shape(key, key_len, shape); |
884 | + if (error_checking(outcomeGetShape, "set option") == NULL){ |
885 | + return NULL; |
886 | + } |
887 | + |
888 | + if (rank == 0){ // scalar |
889 | + set_option_aux_scalar(secondArg, key, key_len, type, rank, shape); |
890 | + } |
891 | + else if (rank == 1){ // list or string |
892 | + if (PyString_Check(secondArg)){ // pystring |
893 | + set_option_aux_string(secondArg, key, key_len, type, rank, shape); |
894 | + } |
895 | + else if (type == SPUD_INT) { // list of ints |
896 | + set_option_aux_list_ints(secondArg, key, key_len, type, rank, shape); |
897 | + } |
898 | + else if (type == SPUD_DOUBLE){ // list of doubles |
899 | + set_option_aux_list_doubles(secondArg, key, key_len, type, rank, shape); |
900 | + } |
901 | + } |
902 | + else if (rank == 2){ // tensor |
903 | + if (type == SPUD_DOUBLE) { // tensor of doubles |
904 | + set_option_aux_tensor_doubles(secondArg, key, key_len, type, rank, shape); |
905 | + } |
906 | + else if (type == SPUD_INT) { // tensor of ints |
907 | + set_option_aux_tensor_ints(secondArg, key, key_len, type, rank, shape); |
908 | + } |
909 | + } |
910 | + |
911 | + Py_RETURN_NONE; |
912 | +} |
913 | + |
914 | +static PyObject* |
915 | +libspud_write_options(PyObject *self, PyObject *args) |
916 | +{ |
917 | + PyObject* firstArg; |
918 | + char *filename; |
919 | + int filename_len; |
920 | + int outcomeWriteOptions; |
921 | + |
922 | + firstArg = PyTuple_GetItem(args, 0); |
923 | + PyArg_Parse(firstArg, "s", &filename); |
924 | + filename_len = strlen(filename); |
925 | + outcomeWriteOptions = spud_write_options (filename, filename_len); |
926 | + return error_checking(outcomeWriteOptions, "write options"); |
927 | +} |
928 | + |
929 | +static PyMethodDef libspudMethods[] = { |
930 | + {"load_options", libspud_load_options, METH_VARARGS, |
931 | + "load options from xml file."}, |
932 | + {"print_options", libspud_print_options, METH_VARARGS, |
933 | + "print options from xml file."}, |
934 | + {"get_number_of_children", libspud_get_number_of_children, METH_VARARGS, |
935 | + "get number of children from xml file."}, |
936 | + {"get_child_name", libspud_get_child_name, METH_VARARGS, |
937 | + "get child name from xml file."}, |
938 | + {"option_count", libspud_option_count, METH_VARARGS, |
939 | + "option count from xml file."}, |
940 | + {"have_option", libspud_have_option, METH_VARARGS, |
941 | + "have option from xml file."}, |
942 | + {"get_option_type", libspud_get_option_type, METH_VARARGS, |
943 | + "get option type from xml file."}, |
944 | + {"get_option_rank", libspud_get_option_rank, METH_VARARGS, |
945 | + "get option rank from xml file."}, |
946 | + {"get_option_shape", libspud_get_option_shape, METH_VARARGS, |
947 | + "get option shape from xml file."}, |
948 | + {"get_option", libspud_get_option, METH_VARARGS, |
949 | + "get option from xml file."}, |
950 | + {"set_option", libspud_set_option, METH_VARARGS, |
951 | + "set option from xml file."}, |
952 | + {"write_options", libspud_write_options, METH_VARARGS, |
953 | + "write options from xml file."}, |
954 | + {"delete_option", libspud_delete_option, METH_VARARGS, |
955 | + "delete option from xml file."}, |
956 | + {"set_option_attribute", libspud_set_option_attribute, METH_VARARGS, |
957 | + "set option attribute from xml file."}, |
958 | + {"add_option", libspud_add_option, METH_VARARGS, |
959 | + "add option from xml file."}, |
960 | + {NULL, NULL, 0, NULL}, |
961 | + /* Sentinel */ |
962 | +}; |
963 | + |
964 | +PyMODINIT_FUNC |
965 | +initlibspud(void) |
966 | +{ |
967 | + PyObject *m; |
968 | + |
969 | + m = Py_InitModule("libspud", libspudMethods); |
970 | + if (m == NULL) |
971 | + return; |
972 | + |
973 | + SpudError = PyErr_NewException("Spud.error", NULL, NULL); |
974 | + SpudNewKeyWarning = PyErr_NewException("SpudNewKey.warning", NULL, NULL); |
975 | + SpudKeyError = PyErr_NewException("SpudKey.error", NULL, NULL); |
976 | + SpudTypeError = PyErr_NewException("SpudType.error", NULL, NULL); |
977 | + SpudFileError = PyErr_NewException("SpudFile.warning", NULL, NULL); |
978 | + SpudAttrSetFailedWarning = PyErr_NewException("SpudAttrSetFailed.warning", NULL, NULL); |
979 | + SpudShapeError = PyErr_NewException("SpudShape.error", NULL, NULL); |
980 | + SpudRankError = PyErr_NewException("SpudRank.error", NULL, NULL); |
981 | + |
982 | + Py_INCREF(SpudError); |
983 | + Py_INCREF(SpudNewKeyWarning); |
984 | + Py_INCREF(SpudKeyError); |
985 | + Py_INCREF(SpudTypeError); |
986 | + Py_INCREF(SpudFileError); |
987 | + Py_INCREF(SpudRankError); |
988 | + Py_INCREF(SpudShapeError); |
989 | + Py_INCREF(SpudAttrSetFailedWarning); |
990 | + |
991 | + PyModule_AddObject(m, "SpudError", SpudError); |
992 | + PyModule_AddObject(m, "SpudNewKeyWarning", SpudNewKeyWarning); |
993 | + PyModule_AddObject(m, "SpudKeyError", SpudKeyError); |
994 | + PyModule_AddObject(m, "SpudTypeError", SpudTypeError); |
995 | + PyModule_AddObject(m, "SpudFileError", SpudFileError); |
996 | + PyModule_AddObject(m, "SpudAttrSetFailedWarning", SpudAttrSetFailedWarning); |
997 | + PyModule_AddObject(m, "SpudShapeError", SpudShapeError); |
998 | + PyModule_AddObject(m, "SpudRankError", SpudRankError); |
999 | + |
1000 | + |
1001 | +#if PY_MINOR_VERSION > 6 |
1002 | + manager = PyCapsule_Import("spud_manager._spud_manager", 0); |
1003 | + if (manager != NULL) spud_set_manager(manager); |
1004 | + else PyErr_Clear(); |
1005 | +#endif |
1006 | + |
1007 | +} |
1008 | + |
1009 | + |
1010 | |
1011 | === renamed file 'python/libspud.py.in' => 'python/libspud.py.ctypes' |
1012 | === added file 'python/setup.py' |
1013 | --- python/setup.py 1970-01-01 00:00:00 +0000 |
1014 | +++ python/setup.py 2011-08-04 21:32:37 +0000 |
1015 | @@ -0,0 +1,9 @@ |
1016 | +from distutils.core import setup, Extension |
1017 | +import os.path |
1018 | + |
1019 | +module1 = Extension('libspud', sources = ['libspud.c'], libraries=["spud"], library_dirs=[os.path.abspath("..")], include_dirs=[os.path.abspath("../include")]) |
1020 | + |
1021 | +setup (name = 'libspud', |
1022 | + version = '1.1.3', |
1023 | + description = 'Python bindings for libspud', |
1024 | + ext_modules = [module1]) |
1025 | |
1026 | === renamed file 'python/test_ctypes.py' => 'python/test_libspud.py' |
1027 | --- python/test_ctypes.py 2011-07-19 05:47:49 +0000 |
1028 | +++ python/test_libspud.py 2011-08-04 21:32:37 +0000 |
1029 | @@ -1,78 +1,87 @@ |
1030 | import libspud |
1031 | -print libspud.__file__ |
1032 | |
1033 | libspud.load_options('test.flml') |
1034 | |
1035 | -libspud.print_options() |
1036 | - |
1037 | -print libspud.get_number_of_children('/geometry') |
1038 | -print libspud.get_child_name('geometry', 0) |
1039 | - |
1040 | -print libspud.option_count('/problem_type') |
1041 | -print libspud.have_option('/problem_type') |
1042 | - |
1043 | -print libspud.get_option_type('/geometry/dimension') |
1044 | -print libspud.get_option_type('/problem_type') |
1045 | - |
1046 | -print libspud.get_option_rank('/geometry/dimension') |
1047 | -print libspud.get_option_rank('/physical_parameters/gravity/vector_field::GravityDirection/prescribed/value/constant') |
1048 | - |
1049 | -print libspud.get_option_shape('/geometry/dimension') |
1050 | -print libspud.get_option_shape('/problem_type') |
1051 | - |
1052 | -print libspud.get_option('/problem_type') |
1053 | -print libspud.get_option('/geometry/dimension') |
1054 | +#libspud.print_options() |
1055 | + |
1056 | +assert libspud.get_number_of_children('/geometry') == 5 |
1057 | +assert libspud.get_child_name('geometry', 0) == "dimension" |
1058 | + |
1059 | +assert libspud.option_count('/problem_type') == 1 |
1060 | +assert libspud.have_option('/problem_type') |
1061 | + |
1062 | +assert libspud.get_option_type('/geometry/dimension') is int |
1063 | +assert libspud.get_option_type('/problem_type') is str |
1064 | + |
1065 | +assert libspud.get_option_rank('/geometry/dimension') == 0 |
1066 | +assert libspud.get_option_rank('/physical_parameters/gravity/vector_field::GravityDirection/prescribed/value/constant') == 1 |
1067 | + |
1068 | +assert libspud.get_option_shape('/geometry/dimension') == (-1, -1) |
1069 | +assert libspud.get_option_shape('/problem_type')[0] > 1 |
1070 | +assert libspud.get_option_shape('/problem_type')[1] == -1 |
1071 | + |
1072 | +assert libspud.get_option('/problem_type') == "multimaterial" |
1073 | +assert libspud.get_option('/geometry/dimension') == 2 |
1074 | libspud.set_option('/geometry/dimension', 3) |
1075 | -print libspud.get_option('/geometry/dimension') |
1076 | + |
1077 | + |
1078 | +assert libspud.get_option('/geometry/dimension') == 3 |
1079 | |
1080 | list_path = '/material_phase::Material1/scalar_field::MaterialVolumeFraction/prognostic/boundary_conditions::LetNoOneLeave/surface_ids' |
1081 | -print libspud.get_option_shape(list_path) |
1082 | -print libspud.get_option_rank(list_path) |
1083 | -print libspud.get_option(list_path) |
1084 | -assert(libspud.get_option(list_path)==[7,8,9,10]) |
1085 | -libspud.set_option(list_path, [11,12,13,14]) |
1086 | -print libspud.get_option_shape(list_path) |
1087 | -print libspud.get_option_rank(list_path) |
1088 | -print libspud.get_option(list_path) |
1089 | -assert(libspud.get_option(list_path)==[11,12,13,14]) |
1090 | +assert libspud.get_option_shape(list_path) == (4, -1) |
1091 | +assert libspud.get_option_rank(list_path) == 1 |
1092 | +assert libspud.get_option(list_path) == [7, 8, 9, 10] |
1093 | + |
1094 | +libspud.set_option(list_path, [11, 12, 13, 14, 15]) |
1095 | +assert libspud.get_option_shape(list_path) == (5, -1) |
1096 | +assert libspud.get_option_rank(list_path) == 1 |
1097 | +assert libspud.get_option(list_path)==[11, 12, 13, 14, 15] |
1098 | |
1099 | tensor_path = '/material_phase::Material1/tensor_field::DummyTensor/prescribed/value::WholeMesh/anisotropic_asymmetric/constant' |
1100 | -print libspud.get_option_shape(tensor_path) |
1101 | -print libspud.get_option_rank(tensor_path) |
1102 | -print libspud.get_option(tensor_path) |
1103 | -assert(libspud.get_option(tensor_path)==[[1.0,2.0],[3.0,4.0]]) |
1104 | -libspud.set_option(tensor_path, [[5.0,6.0],[7.0,8.0]]) |
1105 | -print libspud.get_option_shape(tensor_path) |
1106 | -print libspud.get_option_rank(tensor_path) |
1107 | -print libspud.get_option(tensor_path) |
1108 | -assert(libspud.get_option(tensor_path)==[[5.0,6.0],[7.0,8.0]]) |
1109 | +assert libspud.get_option_shape(tensor_path) == (2, 2) |
1110 | +assert libspud.get_option_rank(tensor_path) == 2 |
1111 | +assert libspud.get_option(tensor_path)==[[1.0,2.0],[3.0,4.0]] |
1112 | + |
1113 | +libspud.set_option(tensor_path, [[5.0,6.0,2.0],[7.0,8.0,1.0]]) |
1114 | +#assert libspud.get_option_shape(tensor_path) == (3,3) |
1115 | +assert libspud.get_option_rank(tensor_path) == 2 |
1116 | + |
1117 | +assert(libspud.get_option(tensor_path)==[[5.0, 6.0, 2.0],[7.0, 8.0, 1.0]]) |
1118 | |
1119 | try: |
1120 | libspud.add_option('/foo') |
1121 | + assert False |
1122 | except libspud.SpudNewKeyWarning, e: |
1123 | - print "caught libspud.SpudNewKeyWarning: "+e.message |
1124 | -print libspud.option_count('/foo') |
1125 | + pass |
1126 | + |
1127 | +assert libspud.option_count('/foo') == 1 |
1128 | |
1129 | libspud.set_option('/problem_type', 'helloworld') |
1130 | -print libspud.get_option('/problem_type') |
1131 | +assert libspud.get_option('/problem_type') == "helloworld" |
1132 | |
1133 | try: |
1134 | libspud.set_option_attribute('/foo/bar', 'foobar') |
1135 | + assert False |
1136 | except libspud.SpudNewKeyWarning, e: |
1137 | - print "caught libspud.SpudNewKeyWarning: "+e.message |
1138 | -print libspud.get_option('/foo/bar') |
1139 | + pass |
1140 | + |
1141 | +assert libspud.get_option('/foo/bar') == "foobar" |
1142 | |
1143 | libspud.delete_option('/foo') |
1144 | -print libspud.option_count('/foo') |
1145 | +assert libspud.option_count('/foo') == 0 |
1146 | |
1147 | try: |
1148 | libspud.get_option('/foo') |
1149 | + assert False |
1150 | except libspud.SpudKeyError, e: |
1151 | - print "caught libspud.SpudKeyError: "+e.message |
1152 | + pass |
1153 | |
1154 | try: |
1155 | libspud.get_option('/geometry') |
1156 | + assert False |
1157 | except libspud.SpudTypeError, e: |
1158 | - print "caught libspud.SpudTypeError: "+e.message |
1159 | + pass |
1160 | |
1161 | libspud.write_options('test_out.flml') |
1162 | + |
1163 | +print "All tests passed!" |
Where is the libspud module meant to be imported from now?
cwilson@ uisce:python$ pwd spud/bzr- repo/c- python- binding/ python
/home/cwilson/
cwilson@ uisce:python$ echo $PYTHONPATH spud/bzr- repo/c- python- binding/ python
/home/cwilson/
cwilson@ uisce:python$ python test_libspud.py
Traceback (most recent call last):
File "test_libspud.py", line 1, in <module>
import libspud
ImportError: No module named libspud