You can subscribe to this list here.
| 2003 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(19) |
Nov
(45) |
Dec
(80) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2004 |
Jan
(58) |
Feb
(127) |
Mar
(74) |
Apr
(34) |
May
(117) |
Jun
(14) |
Jul
(26) |
Aug
(13) |
Sep
(1) |
Oct
(38) |
Nov
(13) |
Dec
(5) |
| 2005 |
Jan
(108) |
Feb
(134) |
Mar
(54) |
Apr
(133) |
May
(16) |
Jun
(54) |
Jul
(128) |
Aug
(99) |
Sep
(157) |
Oct
(182) |
Nov
(236) |
Dec
(212) |
| 2006 |
Jan
(86) |
Feb
(76) |
Mar
(121) |
Apr
(27) |
May
(7) |
Jun
(1) |
Jul
(6) |
Aug
(28) |
Sep
(1) |
Oct
(27) |
Nov
(5) |
Dec
|
| 2007 |
Jan
(32) |
Feb
(22) |
Mar
(22) |
Apr
(11) |
May
(3) |
Jun
(12) |
Jul
(11) |
Aug
(9) |
Sep
(37) |
Oct
(4) |
Nov
(9) |
Dec
(51) |
| 2008 |
Jan
(7) |
Feb
(31) |
Mar
(46) |
Apr
(31) |
May
(5) |
Jun
(27) |
Jul
(12) |
Aug
(5) |
Sep
(13) |
Oct
(24) |
Nov
(112) |
Dec
(15) |
| 2009 |
Jan
(6) |
Feb
(103) |
Mar
(66) |
Apr
(9) |
May
(8) |
Jun
(1) |
Jul
(20) |
Aug
(9) |
Sep
(2) |
Oct
(81) |
Nov
(88) |
Dec
(30) |
| 2010 |
Jan
(65) |
Feb
(57) |
Mar
(22) |
Apr
(12) |
May
(4) |
Jun
(12) |
Jul
(43) |
Aug
(6) |
Sep
(6) |
Oct
(4) |
Nov
(6) |
Dec
(3) |
| 2011 |
Jan
(10) |
Feb
(27) |
Mar
(11) |
Apr
(9) |
May
(69) |
Jun
(73) |
Jul
(67) |
Aug
(116) |
Sep
(40) |
Oct
(11) |
Nov
(34) |
Dec
(19) |
| 2012 |
Jan
|
Feb
(4) |
Mar
(28) |
Apr
(18) |
May
(9) |
Jun
(7) |
Jul
(4) |
Aug
(155) |
Sep
(264) |
Oct
(172) |
Nov
(15) |
Dec
(40) |
| 2013 |
Jan
(1) |
Feb
(2) |
Mar
|
Apr
|
May
|
Jun
(20) |
Jul
(76) |
Aug
(67) |
Sep
(49) |
Oct
(27) |
Nov
(3) |
Dec
(3) |
| 2014 |
Jan
(7) |
Feb
(7) |
Mar
(16) |
Apr
|
May
(4) |
Jun
(1) |
Jul
(18) |
Aug
|
Sep
|
Oct
|
Nov
(1) |
Dec
|
| 2015 |
Jan
(6) |
Feb
(5) |
Mar
(3) |
Apr
(23) |
May
(5) |
Jun
|
Jul
(2) |
Aug
(4) |
Sep
|
Oct
|
Nov
(2) |
Dec
(4) |
| 2016 |
Jan
(2) |
Feb
(7) |
Mar
(2) |
Apr
(1) |
May
(14) |
Jun
(3) |
Jul
|
Aug
(3) |
Sep
|
Oct
|
Nov
(1) |
Dec
(3) |
| 2017 |
Jan
(6) |
Feb
|
Mar
(3) |
Apr
|
May
|
Jun
|
Jul
|
Aug
(12) |
Sep
(6) |
Oct
|
Nov
(3) |
Dec
|
| 2018 |
Jan
(4) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
(8) |
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2019 |
Jan
|
Feb
|
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
(3) |
Sep
(8) |
Oct
|
Nov
(2) |
Dec
(25) |
| 2020 |
Jan
|
Feb
(3) |
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
(3) |
Oct
(53) |
Nov
(33) |
Dec
|
| 2021 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(4) |
Dec
(5) |
| 2022 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(5) |
Jul
(93) |
Aug
(206) |
Sep
(39) |
Oct
(19) |
Nov
(11) |
Dec
|
| 2023 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(2) |
Jun
(150) |
Jul
(124) |
Aug
(14) |
Sep
(5) |
Oct
|
Nov
(1) |
Dec
|
| 2024 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(12) |
Jul
(62) |
Aug
|
Sep
(7) |
Oct
|
Nov
(7) |
Dec
|
| 2025 |
Jan
|
Feb
|
Mar
|
Apr
(14) |
May
(3) |
Jun
|
Jul
|
Aug
(76) |
Sep
(214) |
Oct
(6) |
Nov
|
Dec
|
|
From: <kin...@us...> - 2025-04-14 15:38:31
|
Revision: 7261
http://sourceforge.net/p/teem/code/7261
Author: kindlmann
Date: 2025-04-14 15:38:13 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
syncing with Teem sources
Modified Paths:
--------------
teem/trunk/python/cffi/cdef/cdef_limn.h
Modified: teem/trunk/python/cffi/cdef/cdef_limn.h
===================================================================
--- teem/trunk/python/cffi/cdef/cdef_limn.h 2025-04-14 14:58:31 UTC (rev 7260)
+++ teem/trunk/python/cffi/cdef/cdef_limn.h 2025-04-14 15:38:13 UTC (rev 7261)
@@ -845,7 +845,7 @@
extern limnCbfPath *limnCbfPathNew(unsigned segNum);
extern limnCbfPath *limnCbfPathNix(limnCbfPath *path);
extern void limnCbfPathJoin(limnCbfPath *dst, const limnCbfPath *src);
-extern limnCbfCtx *limnCbfCtxNew();
+extern limnCbfCtx *limnCbfCtxNew(void);
extern limnCbfCtx *limnCbfCtxNix(limnCbfCtx *fctx);
extern int limnCbfCtxPrep(limnCbfCtx *fctx, const limnCbfPoints *lpnt);
extern void limnCbfSegEval(double *xy, const limnCbfSeg *seg, double tt);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 14:58:53
|
Revision: 7260
http://sourceforge.net/p/teem/code/7260
Author: kindlmann
Date: 2025-04-14 14:58:31 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
resurrecting this on GLKs new laptop with latest greatest nm etc
Modified Paths:
--------------
teem/trunk/src/_util/scan-symbols.py
Modified: teem/trunk/src/_util/scan-symbols.py
===================================================================
--- teem/trunk/src/_util/scan-symbols.py 2025-04-14 14:55:36 UTC (rev 7259)
+++ teem/trunk/src/_util/scan-symbols.py 2025-04-14 14:58:31 UTC (rev 7260)
@@ -331,6 +331,7 @@
runthis('make clean', False)
runthis('make', False)
runthis('make install', False)
+ # HEY HEY this depends on "nm" being llvm-nm
nmOut = runthis(f'nm {archDir}/lib/lib{lib}.a', True).stdout.decode('UTF-8').splitlines()
nmOut.pop(0) # first line is empty (at least on Mac)
# symb accumulates a dict mapping from symbol name to little description:
@@ -339,7 +340,8 @@
symb = {}
currFile = None
for L in nmOut:
- if match := re.match(r'[^\()]+\(([^\)]+).o\):$', L):
+ # if match := re.match(r'[^\()]+\(([^\)]+).o\):$', L): # old nm
+ if match := re.match(r'^([^\)]+).o:$', L): # new llvm-nm
currFile = match.group(1) + '.c'
if verbose > 1:
print(f' ... {currFile}')
@@ -772,7 +774,7 @@
'1: do scan to flag issues in code, but no new annotations\n'
'2: add annotations where there are not, but dont overwrite '
'any existing wrong annotations or comments\n'
- '3: create all anntations (including over-writing comments '
+ '3: create all annotations (including over-writing comments '
'and wrong annotations)\n'
'In fact no original source files are over-written: the result '
'of annotating functions in foo.c is a new file foo-annote.c',
@@ -849,6 +851,7 @@
if verbose:
print(f'========== biff auto-scan ... ')
for bs in toBS:
+ # print(f' = = = = {bs=}')
bnote = biffScan(*bs)
if not bnote or 1 == args.biff:
# just passing through
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 14:55:54
|
Revision: 7259
http://sourceforge.net/p/teem/code/7259
Author: kindlmann
Date: 2025-04-14 14:55:36 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
better notes to GLK on how to run teem/src/_util/scan-symbols.py
Modified Paths:
--------------
teem/trunk/src/biff/README.txt
Modified: teem/trunk/src/biff/README.txt
===================================================================
--- teem/trunk/src/biff/README.txt 2025-04-14 14:54:06 UTC (rev 7258)
+++ teem/trunk/src/biff/README.txt 2025-04-14 14:55:36 UTC (rev 7259)
@@ -102,6 +102,8 @@
GLK has his teem source checkout in ~/teem.
From the ~/teem/src/_util directory:
+ unset TEEM_SRC
+ export TEEM_ARCH=darwin.64 # for example
python3 scan-symbols.py ~/teem -biff 3 gage
why -biff 3: because
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 14:54:23
|
Revision: 7258
http://sourceforge.net/p/teem/code/7258
Author: kindlmann
Date: 2025-04-14 14:54:06 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
now with biff annotations
Modified Paths:
--------------
teem/trunk/src/limn/splineFit.c
Modified: teem/trunk/src/limn/splineFit.c
===================================================================
--- teem/trunk/src/limn/splineFit.c 2025-04-14 14:53:15 UTC (rev 7257)
+++ teem/trunk/src/limn/splineFit.c 2025-04-14 14:54:06 UTC (rev 7258)
@@ -1435,7 +1435,7 @@
return 0;
}
-static int
+static int /* Biff: 1 */
vttvCalcOrCopy(double *vttv[4], int *givenP, const double vv0[2], const double tt1[2],
const double tt2[2], const double vv3[2], limnCbfCtx *fctx,
const limnCbfPoints *lpnt, uint loi, uint hii) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 14:53:33
|
Revision: 7257
http://sourceforge.net/p/teem/code/7257
Author: kindlmann
Date: 2025-04-14 14:53:15 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
now with biff annotations
Modified Paths:
--------------
teem/trunk/src/unrrdu/ninspect.c
Modified: teem/trunk/src/unrrdu/ninspect.c
===================================================================
--- teem/trunk/src/unrrdu/ninspect.c 2025-04-14 14:52:28 UTC (rev 7256)
+++ teem/trunk/src/unrrdu/ninspect.c 2025-04-14 14:53:15 UTC (rev 7257)
@@ -39,7 +39,7 @@
"name of what used to be a stand-alone Teem command-line utility, "
"peer to unu).");
-static int
+static int /* Biff: 1 */
fixproj(Nrrd *nproj[3], const Nrrd *nvol) {
static const char me[] = "fixproj";
airArray *mop;
@@ -157,7 +157,7 @@
return 0;
}
-static int
+static int /* Biff: 1 */
ninspect_proj(Nrrd *nout, const Nrrd *nin, int axis, int smart, float amount) {
static const char me[] = "ninspect_proj";
airArray *mop;
@@ -214,7 +214,7 @@
return 0;
}
-static int
+static int /* Biff: 1 */
doit(Nrrd *nout, const Nrrd *nin, int smart, float amount, unsigned int margin,
const unsigned char *back) {
static const char me[] = "doit";
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 14:52:46
|
Revision: 7256
http://sourceforge.net/p/teem/code/7256
Author: kindlmann
Date: 2025-04-14 14:52:28 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
oops forgot static qualifier on nfdsChar
Modified Paths:
--------------
teem/trunk/src/unrrdu/uncmt.c
Modified: teem/trunk/src/unrrdu/uncmt.c
===================================================================
--- teem/trunk/src/unrrdu/uncmt.c 2025-04-14 11:45:25 UTC (rev 7255)
+++ teem/trunk/src/unrrdu/uncmt.c 2025-04-14 14:52:28 UTC (rev 7256)
@@ -57,7 +57,7 @@
Monitors input characters ci, to prevent output of "float" or "double"
state is maintained by the floatCount and doubleCount variables
passed by reference */
-int
+static int
nfdsChar(unsigned int *floatCountP, unsigned int *doubleCountP, int ci) {
int co = ci; /* by default, output == input */
unsigned int fc = *floatCountP;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 11:45:43
|
Revision: 7255
http://sourceforge.net/p/teem/code/7255
Author: kindlmann
Date: 2025-04-14 11:45:25 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
WHOA optarr_incr was missing static declaration
Modified Paths:
--------------
teem/trunk/src/hest/methodsHest.c
Modified: teem/trunk/src/hest/methodsHest.c
===================================================================
--- teem/trunk/src/hest/methodsHest.c 2025-04-14 11:39:14 UTC (rev 7254)
+++ teem/trunk/src/hest/methodsHest.c 2025-04-14 11:45:25 UTC (rev 7255)
@@ -234,7 +234,7 @@
/* line airArrayLenIncr(1): increments logical length by 1,
and returns index of newly-available element */
-unsigned int
+static unsigned int
optarr_incr(hestOpt **optP) {
unsigned int olen, nlen;
olen = (*optP)->arrLen; /* == index of new element */
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 11:39:32
|
Revision: 7254
http://sourceforge.net/p/teem/code/7254
Author: kindlmann
Date: 2025-04-14 11:39:14 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
adding airJSFRand to list of Teem types
Modified Paths:
--------------
teem/trunk/src/_util/scan-symbols.py
Modified: teem/trunk/src/_util/scan-symbols.py
===================================================================
--- teem/trunk/src/_util/scan-symbols.py 2025-04-14 11:09:38 UTC (rev 7253)
+++ teem/trunk/src/_util/scan-symbols.py 2025-04-14 11:39:14 UTC (rev 7254)
@@ -98,6 +98,7 @@
'airThreadMutex',
'airThreadCond',
'airThreadBarrier',
+ 'airJSFRand',
'biffMsg',
'hestCB',
'hestParm',
@@ -323,8 +324,9 @@
# compile the "lib" library, run nm on it
# and build up a list of the actual, defined, symbols in it
def symbList(lib, firstClean):
+ runthis('pwd', False)
if verbose:
- print(f'========== recompiling, scanning definitions in {lib}.a ... ')
+ print(f'========== recompiling to then scan definitions in {lib}.a ... ')
if firstClean:
runthis('make clean', False)
runthis('make', False)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 11:09:56
|
Revision: 7253
http://sourceforge.net/p/teem/code/7253
Author: kindlmann
Date: 2025-04-14 11:09:38 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
now with 90 column lines
Modified Paths:
--------------
teem/trunk/src/biff/README.txt
Modified: teem/trunk/src/biff/README.txt
===================================================================
--- teem/trunk/src/biff/README.txt 2025-04-14 11:08:16 UTC (rev 7252)
+++ teem/trunk/src/biff/README.txt 2025-04-14 11:09:38 UTC (rev 7253)
@@ -1,27 +1,25 @@
All about /* Biff: */ annotations (new with Teem 1.13)
-teem/src/_util/scan-symbols.py -biff (the "biff auto-scan") will scrutinize
-Teem source code to look at how it uses biff. This analysis creates parsable
-annotations of function definitions to automate whether and how biffGet{Done}
-is called in response to an error (in, say, a Python wrapper), as follows.
+teem/src/_util/scan-symbols.py -biff (the "biff auto-scan") will scrutinize Teem source
+code to look at how it uses biff. This analysis creates parsable annotations of function
+definitions to automate whether and how biffGet{Done} is called in response to an error
+(in, say, a Python wrapper), as follows.
-Even though these annotations were motivated by the needs of Python wrapping
-(which is only wrapping things in the public API), GLK decided to also do these
-annotations for "private" functions (which are are available for linking in the
-library, but are declared in privateLib.h rather than lib.h), and even for
-static functions that do use biff. The idea is that this is potentially useful
-information for further analysis or for human coding, and its better to err on
-the side of more info, discretely packaged, when the quality/correctness of the
-info is high.
+Even though these annotations were motivated by the needs of Python wrapping (which is
+only wrapping things in the public API), GLK decided to also do these annotations for
+"private" functions (which are are available for linking in the library, but are declared
+in privateLib.h rather than lib.h), and even for static functions that do use biff. The
+idea is that this is potentially useful information for further analysis or for human
+coding, and its better to err on the side of more info, discretely packaged, when the
+quality/correctness of the info is high.
-NOTE that the Biff annotation on a function currently reflects a simplistic
-textual analysis of that function code, saying "it looks like this function
-uses biff in this way." This is not based on any proper parsing of the code
-AST, so calls to biff could be hidden behind a #define, and there is certainly
-no way to know (without execution) whether any other functions called from
-this function used biff. The formatting of the newly adopted clang-format
-is a big help. In any case this seems adequate for Teem's Python wrapping error
-handling.
+NOTE that the Biff annotation on a function currently reflects a simplistic textual
+analysis of that function code, saying "it looks like this function uses biff in this
+way." This is not based on any proper parsing of the code AST, so calls to biff could be
+hidden behind a #define, and there is certainly no way to know (without execution)
+whether any other functions called from this function used biff. The formatting of the
+newly adopted clang-format is a big help. In any case this seems adequate for Teem's
+Python wrapping error handling.
Here is an example annotation from teem/src/nrrd/subset.c
@@ -28,9 +26,9 @@
int /* Biff: 1 */
nrrdSlice(Nrrd *nout, const Nrrd *cnin, unsigned int saxi, size_t pos) {
-The annotations are a one-line comment, always on the line with the function
-return type, which is above the function name (this formatting is enforced by
-new use of clang-format).
+The annotations are a one-line comment, always on the line with the function return type,
+which is above the function name (this formatting is enforced by new use of
+clang-format).
** NOTE that in Teem code, the remainder of the line after the function return
** type (with the function name on the next line) is reserved for these kinds
** of annotations. Human-written comments about the return type/qualifers need
@@ -45,49 +43,42 @@
teem/src/_util/scan-symbols.py -biff *only* produces Biff? annotations.
--- Optional:
-"(private)" : this function is private (as described above). Otherwise, from
-the qualifiers on the return type of the function (the same line as this
-annotation), "static" will mean that the function is static, while not having
-"static" (and absent "(private)"), this is declared in lib.h and intended for
-external linkage. Such "private" functions probably aren't even in a python
-wrapper, but the fact of being private is nice to record once known, since you
-can't tell by looking at a function definition where it has been
-declared. Despite the tendency, there is no iron rule in Teem code that private
+"(private)" : this function is private (as described above). Otherwise, from the
+qualifiers on the return type of the function (the same line as this annotation),
+"static" will mean that the function is static, while not having "static" (and absent
+"(private)"), this is declared in lib.h and intended for external linkage. Such "private"
+functions probably aren't even in a python wrapper, but the fact of being private is nice
+to record once known, since you can't tell by looking at a function definition where it
+has been declared. Despite the tendency, there is no iron rule in Teem code that private
function names start with a single "_".
--- Required:
- "<val>" : The return value <val> indicates a biff-reported error, i.e., if
- the function returns <val> then someone needs to retrieve the biff
- error message. <val> must not contain '|', ':', or whitespace, and
- it cannot be "nope" nor "maybe". <val> is just a string (since it
- is in a comment), but hopfully it is parsable as the function return
- type (on this same line, before the comment containing this
- annotation). Simple integers are easy, but it could get trickier:
- example returns (currently used in Teem) include NULL, EOF,
- AIR_FALSE, AIR_NAN, UINT_MAX, Z_STREAM_ERROR, and
- nrrdField_unknown. The point is: be prepared to do some work if
- you're in the business of parsing and acting on Biff annotations.
-or "<v1>|<v2>" : A return value of either <v1> or <v2> indicates an error has
- been recorded in biff
-or "<v1>|<v2>|<v3>" : Error values are <v1> or <v2> or <v3>
- (and so on)
-or "maybe:<N>:<val>" : This function uses something like biffMaybeAddf(), which
- may or may not set a biff error message, depending on the value of
- one of the function parameters (always called "useBiff", as enforced
- by biff auto-scan). useBiff is the Nth function parameter, in the
- *1*-based numbering of the function parameters.
-or "nope" : This function does not use biff. The function may usefully
- communicate something about how things went wrong by a returning
- one of some possible error return values, but that isn't documented
- here because it doesn't involve biff. (Why "nope": it won't be
- confused for anything else, and GLK had just seen the excellent
- Jordan Peele movie of the same name)
+ "<val>" : The return value <val> indicates a biff-reported error, i.e., if the function
+ returns <val> then someone needs to retrieve the biff error message.
+ <val> must not contain '|', ':', or whitespace, and cannot be "nope" or "maybe"
+ <val> is just a string (since it is in a comment), but hopfully it is parsable
+ as the function return type (on this same line, before the comment containing
+ this annotation). Simple integers are easy, but it could get trickier: example
+ returns (currently used in Teem) include NULL, EOF, AIR_FALSE, AIR_NAN,
+ UINT_MAX, Z_STREAM_ERROR, and nrrdField_unknown. The point is: be prepared to
+ do some work if you're trying to parse and act on Biff annotations.
+or "<v1>|<v2>" : A return value of either <v1> or <v2> indicates an error has been
+ recorded in biff
+or "<v1>|<v2>|<v3>" : Error values are <v1> or <v2> or <v3> (and so on)
+or "maybe:<N>:<val>" : This function uses something like biffMaybeAddf(), which may or
+ may not set a biff error message, depending on the value of one of the
+ function parameters (always called "useBiff", as enforced by biff auto-scan).
+ useBiff is the Nth function parameter, in the *1*-based numbering of the
+ function parameters.
+or "nope" : This function does not use biff. The function may usefully communicate
+ something about how things went wrong by a returning one of some possible
+ error return values, but that isn't documented here because it doesn't
+ involve biff. (Why "nope": it won't be confused for anything else, and GLK had
+ just seen the excellent Jordan Peele movie of the same name)
--- Optional:
# <comments> : anything after a '#' is ignored by an annotation parser
-These annotiations are parsed and consumed by teem/python/cffi/
-
Other examples:
int /* Biff: (private) maybe:2:nrrdField_unknown */
@@ -101,7 +92,13 @@
grep 'Biff:' */*.c | cut -d: -f 2- | cut -d/ -f 2- | cut -d' ' -f 2- | cut -d\* -f 1 | sort | uniq
-Some notes on how GLK creates the annotations, for example for gage:
+For context: the Biff: annotations are created with the help of
+../_util/scan-symbols.py, which is re-run as needed when the API changes,
+and prior to releases. Then, the Biff: annotations are ready by
+../_util/gen_biffdata.py, which repackages the info and save it into
+../../python/cffi/biffdata/*.csv, one file per Teem library.
+
+Some further notes on how GLK creates the annotations, for example for gage:
GLK has his teem source checkout in ~/teem.
From the ~/teem/src/_util directory:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 11:08:34
|
Revision: 7252
http://sourceforge.net/p/teem/code/7252
Author: kindlmann
Date: 2025-04-14 11:08:16 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
tweaks3 as GLK revisits this and gets it working on new laptop
Modified Paths:
--------------
teem/trunk/python/cffi/README.md
Modified: teem/trunk/python/cffi/README.md
===================================================================
--- teem/trunk/python/cffi/README.md 2025-04-14 10:53:14 UTC (rev 7251)
+++ teem/trunk/python/cffi/README.md 2025-04-14 11:08:16 UTC (rev 7252)
@@ -22,8 +22,6 @@
- `exult.py` (distributed with Teem source) is CFFI **EX**tension module **U**tilities for **L**ibraries depending on **T**eem, which arose with the recognition that knowledge of Teem's organization and contents matter for two distinct but connected steps: compiling extension modules that depend on Teem (or are Teem), and wrapping those extension modules in Pythonic ways. `exult.py` defines a `Tffi` object is used to compile extension modules (via its `.cdef()`, `.set_source()`, and `.compile()` methods) and then generate a Python wrapper around the extension module (the `Tffi.wrap()` method). `exult.py` has become home for functionality that started in an earlier version of `teem.py` (such as knowledge of the inter-dependencies of Teem libraries)
- `lliibb.py` (distributed with Teem source) is the template for all the Python wrappers (around extension modules) that `exult.py` can generate, including `teem.py`. No python code will ever "`import lliibb`"; the text of this is transformed by `exult.py`'s `Tffi.wrap()` to generate things like `teem.py`. `lliibb.py` is the new home for functionality (such as the `Tenum` python wrapper for an airEnum) that started in an earlier version of `build_teem.py`. The biggest text transformation that `Tffi.wrap()` does is to inject a Python dictionary summarizing which C functions use `biff`, and how to interpret their return values as errors.
- `build_teem.py` (distributed with Teem source, run by user): Running `python3 build_teem.py -gch $TEEM_INSTALL` does a lot of fragile hacking on the headers in `$TEEM_INSTALL/include/teem` to produce restatement of Teem library APIs in `cdef/cdef_*.h`. Without the `-gch` option, `python3 build_teem.py $TEEM_INSTALL` will (with help from class `Tffi` in `exult.py`) produce `_teem.c` and compile it to make the `_teem.cpython....so` shared object (above). Whether `$TEEM_INSTALL` includes the "experimental" Teem libraries will determine the contents of `_teem.c`, which why it is not distributed with the Teem source.
-- `biffdata/*.csv`: these are a repackaging of the `/* Biff: */` annotations of the source code in `$TEEM_SRC/src/*/*.c`, which describe what different return values from a Teem C function indicates that the function has used `biff` to describe an error. The `biffdata/*.csv` files are read in by `exult.py`'s `Tffi.wrap()` to generate a Python dictionary `_BIFF_DICT` that `teem.py` (or other wrapper) uses to generate Exceptions upon errors.
+- `biffdata/*.csv`: these are a repackaging of the `/* Biff: */` annotations of the source code in `$TEEM_SRC/src/*/*.c`, which describe what different return values from a Teem C function indicates that the function has used `biff` to describe an error. The `biffdata/*.csv` files are read in by `exult.py`'s `Tffi.wrap()` to generate a Python dictionary `_BIFF_DICT` that `teem.py` (or other wrapper) uses to generate Exceptions upon errors. The `biffdata/*.csv` files are generated by `$TEEM_SRC/src/_util/gen_biffdata.py`, which scans all the `$TEEM_SRC/src/*/*.c` source code files for "`/* Biff: */`" annotations. The "`/* Biff: */`" annotations are created in turn by `$TEEM_SRC/src/_util/scan-symbols.py`, which is re-run as needed when the API changes, and prior to releases. The format of the annotations is defined in `$TEEM_SRC/biff/README.txt`.
-For the curious: `$TEEM_SRC/src/_util/gen_biffdata.py` generates the `biffdata/*.csv` files by scanning the `$TEEM_SRC/src/*/*.c` source code for "`/* Biff: */`" annotations. The "`/* Biff: */`" annotations are created by `$TEEM_SRC/src/_util/scan-symbols.py`, which is run as needed when the API changes, and prior to releases. The format of the annotations is defined in `$TEEM_SRC/biff/README.txt`.
-
Also: the motivation for centralizing (in `exult.py`) how Teem-related extension modules are compiled and wrapped comes from frustrations arising with trying to connect extensions modules that each had their own CFFI bridges to `libteem`, with error messages like `TypeError: initializer for ctype 'airEnum *' appears indeed to be 'airEnum *', but the types are different (check that you are not e.g. mixing up different ffi instances)`.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 10:53:31
|
Revision: 7251
http://sourceforge.net/p/teem/code/7251
Author: kindlmann
Date: 2025-04-14 10:53:14 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
tweaks2 as GLK revisits this and gets it working on new laptop
Modified Paths:
--------------
teem/trunk/python/cffi/README.md
Modified: teem/trunk/python/cffi/README.md
===================================================================
--- teem/trunk/python/cffi/README.md 2025-04-14 10:50:44 UTC (rev 7250)
+++ teem/trunk/python/cffi/README.md 2025-04-14 10:53:14 UTC (rev 7251)
@@ -19,7 +19,7 @@
- `teem.py` (distributed with Teem source): enables "import teem" from python3, and provides access to the entire Teem API, with some added benefits (mainly `biff` errors turning into Python exceptions). `teem.py` is generated by `build_teem.py` in its final "wrap" step. At runtime,`teem.py` relies on an `import _teem` which dynamically loads and links in:
- `_teem.cpython-`_platformspecifics_`.so` (created by user, because it is specific to the local OS and the local version of Python): This platform-specific shared library is the bridge between Python and the symbols in `$TEEM_INSTALL/lib/libteem`. Linking regular C code with `libteem` requires declarations from the .h headers in `$TEEM_INSTALL/include/teem`, but the work of describing the Teem API to CFFI, so as to mirror it all in Python, is done by:
- `cdef/cdef_air.h`, `cdef/cdef_biff.h`, `cdef/cdef_nrrd.h`, etc (distributed with Teem source): these are restatements of the API of each library in Teem in a form digestable to the meagre C header parser inside `cffi.FFI()`: basically removing all pre-processor logic and all `#define` macros, keeping only the `#define`s around integers (which can be parsed). Some subset of these are read by `Tffi.cdef()` in `exult.py` to tell CFFI what bridge code to generate when creating the extension module. Including these files in the Teem source (as opposed to requiring users to regenerate them) may not be wise, but they are there to be used as part of creating extension module for other non-Teem libraries.
-- `exult.py` (distributed with Teem source) is CFFI **EX**tension module **U**tilities for **L**ibraries depending on **T**eem, which arose with the recognition that knowledge of Teem's organization and contents matter for two things: compiling extension modules that depend on Teem (or are Teem), and wrapping those extension modules in Pythonic ways. `exult.py` defines a `Tffi` object is used to compile extension modules (via its `.cdef()`, `.set_source()`, and `.compile()` methods) and then generate a Python wrapper around the extension module (the `Tffi.wrap()` method). `exult.py` has become home for functionality that started in an earlier version of `teem.py` (such as knowledge of the inter-dependencies of Teem libraries)
+- `exult.py` (distributed with Teem source) is CFFI **EX**tension module **U**tilities for **L**ibraries depending on **T**eem, which arose with the recognition that knowledge of Teem's organization and contents matter for two distinct but connected steps: compiling extension modules that depend on Teem (or are Teem), and wrapping those extension modules in Pythonic ways. `exult.py` defines a `Tffi` object is used to compile extension modules (via its `.cdef()`, `.set_source()`, and `.compile()` methods) and then generate a Python wrapper around the extension module (the `Tffi.wrap()` method). `exult.py` has become home for functionality that started in an earlier version of `teem.py` (such as knowledge of the inter-dependencies of Teem libraries)
- `lliibb.py` (distributed with Teem source) is the template for all the Python wrappers (around extension modules) that `exult.py` can generate, including `teem.py`. No python code will ever "`import lliibb`"; the text of this is transformed by `exult.py`'s `Tffi.wrap()` to generate things like `teem.py`. `lliibb.py` is the new home for functionality (such as the `Tenum` python wrapper for an airEnum) that started in an earlier version of `build_teem.py`. The biggest text transformation that `Tffi.wrap()` does is to inject a Python dictionary summarizing which C functions use `biff`, and how to interpret their return values as errors.
- `build_teem.py` (distributed with Teem source, run by user): Running `python3 build_teem.py -gch $TEEM_INSTALL` does a lot of fragile hacking on the headers in `$TEEM_INSTALL/include/teem` to produce restatement of Teem library APIs in `cdef/cdef_*.h`. Without the `-gch` option, `python3 build_teem.py $TEEM_INSTALL` will (with help from class `Tffi` in `exult.py`) produce `_teem.c` and compile it to make the `_teem.cpython....so` shared object (above). Whether `$TEEM_INSTALL` includes the "experimental" Teem libraries will determine the contents of `_teem.c`, which why it is not distributed with the Teem source.
- `biffdata/*.csv`: these are a repackaging of the `/* Biff: */` annotations of the source code in `$TEEM_SRC/src/*/*.c`, which describe what different return values from a Teem C function indicates that the function has used `biff` to describe an error. The `biffdata/*.csv` files are read in by `exult.py`'s `Tffi.wrap()` to generate a Python dictionary `_BIFF_DICT` that `teem.py` (or other wrapper) uses to generate Exceptions upon errors.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-14 10:51:04
|
Revision: 7250
http://sourceforge.net/p/teem/code/7250
Author: kindlmann
Date: 2025-04-14 10:50:44 +0000 (Mon, 14 Apr 2025)
Log Message:
-----------
tweaks as GLK revisits this and gets it working on new laptop
Modified Paths:
--------------
teem/trunk/python/cffi/README.md
Modified: teem/trunk/python/cffi/README.md
===================================================================
--- teem/trunk/python/cffi/README.md 2025-04-06 16:10:35 UTC (rev 7249)
+++ teem/trunk/python/cffi/README.md 2025-04-14 10:50:44 UTC (rev 7250)
@@ -1,6 +1,6 @@
# CFFI-based Python wrappers for Teem
-The `teem.py` in this directory is a new (as of Teem v2 in 2024? 2025?) Python wrapper for all of Teem, built via CFFI. It does useful error handling, and has one or more helper/wrappers (including a Python object "foo" wrapping of "const airEnum \*const foo").
+The `teem.py` in this directory is a new (as of Teem v2 in 2024? 2025?) Python wrapper for all of Teem, built via CFFI. It does useful error handling (automatically turning `biff` errors into Python Exceptions), and has one or more pythonic helper/wrappers (including a Python object "foo" wrapping of "const airEnum \*const foo").
These notes by GLK are mostly to document for future GLK what's involved in creating teem.py, but also for anyone else who is in a position to improve how Python users can access and benefit from Teem.
@@ -9,14 +9,14 @@
- The previous Python wrapping method, using [ctypes](https://docs.python.org/3/library/ctypes.html) (in `../ctypes`) is stalled because the automated generation of ctypes description of the API depended on a patched version of [gccxml](https://gccxml.github.io/HTML/Index.html), which is no longer maintained. A new [llvm-based ctypeslib](https://github.com/trolldbois/ctypeslib) is the likely basis of any future ctypes Teem wrapper.
- The current approach uses [CFFI](https://cffi.readthedocs.io/), specifically the ["API, out-of-line" mode](https://cffi.readthedocs.io/en/latest/overview.html#other-cffi-modes), which includes a C compilation step to produce a platform-specific bridge between the Python run-time and symbols in the Teem library. This should be faster than ctypes, which CFFI would call "ABI, in-line"
- Teem is written in C as a collection of libraries (`air`, `biff`, `hest`, `nrrd`, etc), but compiling and installing with CMake produces a single `libteem` library to link with. CFFI can call into either a static or shared library, but additional dependencies (png, zlib) currently -- for the sake of this wrapping -- require a shared library: `libteem.so` or `libteem.dylib` for Linux or Mac, respectively. Windows should be possible but hasn't been tried.
-- Teem's `biff` library is for human-readable error message accumulation. Handling an error in a Teem function like `nrrdLoad()` sometimes involves subsequent calls like `biffGetDone()` to retrieve the error message. Work on this Python wrapper has led to a new systematic way of documenting which functions use biff, and what return values indicate an error. This information is now stored in `/* Biff: */` annotations at the start of function definitions in Teem's C source code.
+- Teem's `biff` library is for human-readable error message accumulation. Handling an error in a Teem function like `nrrdLoad()` sometimes involves subsequent calls like `biffGetDone()` to retrieve the error message. Work on this Python wrapper has led to a new systematic way of documenting which functions use biff, and what return values indicate an error. This information is now stored in `/* Biff: */` annotations at the start of function definitions in Teem's C source code. See `teem/src/biff/README.txt` for details on the syntax of these annotations.
- The following description will use:
- `$TEEM_INSTALL` to refer to whatever directory in which (as the result of a `make install`) CMake installed Teem, with a `lib` subdir containing `libteem{.so,.dylib}`, an `include` subdir containing all the Teem headers (`teem/air.h`, `teem/biff.h`, etc). There's also a `bin` subdir for executables but they aren't relevant for Python wrapping.
- - `$TEEM_SRC` to refer to whatever directory has the source checkout of Teem (from this file, `../..`), with a `src` subdir for all sources, and a `python` subdir for python wrappings, and `python/cffi` containing this file.
+ - `$TEEM_SRC` to refer to whatever directory has the source checkout of Teem (from this file, `../..`), with a `src` subdir for all sources, and a `python` subdir for python wrappings, and `python/cffi` containing this file. For example, `$TEEM_SRC/src/_util/gen_biffdata.py` is the utility that scans for and parses "Biff:" anntations in Teem's .c files (`$TEEM_SRC/src/*/*.c`) to generate `$TEEM_SRC/python/cffi/biffdata/*.csv`.
The various files in this directory (`$TEEM_SRC/python/cffi`), where they come from, and their role:
-- `teem.py` (distributed with Teem source): enables "import teem" from python3, and provides access to the entire Teem API, with some added benefits (mainly biff errors turning into Python exceptions). `teem.py` is generated by `build_teem.py` in its final "wrap" step. At runtime,`teem.py` relies on an `import _teem` which dynamically loads and links in:
+- `teem.py` (distributed with Teem source): enables "import teem" from python3, and provides access to the entire Teem API, with some added benefits (mainly `biff` errors turning into Python exceptions). `teem.py` is generated by `build_teem.py` in its final "wrap" step. At runtime,`teem.py` relies on an `import _teem` which dynamically loads and links in:
- `_teem.cpython-`_platformspecifics_`.so` (created by user, because it is specific to the local OS and the local version of Python): This platform-specific shared library is the bridge between Python and the symbols in `$TEEM_INSTALL/lib/libteem`. Linking regular C code with `libteem` requires declarations from the .h headers in `$TEEM_INSTALL/include/teem`, but the work of describing the Teem API to CFFI, so as to mirror it all in Python, is done by:
- `cdef/cdef_air.h`, `cdef/cdef_biff.h`, `cdef/cdef_nrrd.h`, etc (distributed with Teem source): these are restatements of the API of each library in Teem in a form digestable to the meagre C header parser inside `cffi.FFI()`: basically removing all pre-processor logic and all `#define` macros, keeping only the `#define`s around integers (which can be parsed). Some subset of these are read by `Tffi.cdef()` in `exult.py` to tell CFFI what bridge code to generate when creating the extension module. Including these files in the Teem source (as opposed to requiring users to regenerate them) may not be wise, but they are there to be used as part of creating extension module for other non-Teem libraries.
- `exult.py` (distributed with Teem source) is CFFI **EX**tension module **U**tilities for **L**ibraries depending on **T**eem, which arose with the recognition that knowledge of Teem's organization and contents matter for two things: compiling extension modules that depend on Teem (or are Teem), and wrapping those extension modules in Pythonic ways. `exult.py` defines a `Tffi` object is used to compile extension modules (via its `.cdef()`, `.set_source()`, and `.compile()` methods) and then generate a Python wrapper around the extension module (the `Tffi.wrap()` method). `exult.py` has become home for functionality that started in an earlier version of `teem.py` (such as knowledge of the inter-dependencies of Teem libraries)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2025-04-06 16:10:52
|
Revision: 7249
http://sourceforge.net/p/teem/code/7249
Author: kindlmann
Date: 2025-04-06 16:10:35 +0000 (Sun, 06 Apr 2025)
Log Message:
-----------
weird that this function prototype has been busted for so long
Modified Paths:
--------------
teem/trunk/src/limn/limn.h
Modified: teem/trunk/src/limn/limn.h
===================================================================
--- teem/trunk/src/limn/limn.h 2024-11-30 11:52:54 UTC (rev 7248)
+++ teem/trunk/src/limn/limn.h 2025-04-06 16:10:35 UTC (rev 7249)
@@ -931,7 +931,7 @@
LIMN_EXPORT limnCbfPath *limnCbfPathNew(unsigned segNum);
LIMN_EXPORT limnCbfPath *limnCbfPathNix(limnCbfPath *path);
LIMN_EXPORT void limnCbfPathJoin(limnCbfPath *dst, const limnCbfPath *src);
-LIMN_EXPORT limnCbfCtx *limnCbfCtxNew();
+LIMN_EXPORT limnCbfCtx *limnCbfCtxNew(void);
LIMN_EXPORT limnCbfCtx *limnCbfCtxNix(limnCbfCtx *fctx);
LIMN_EXPORT int limnCbfCtxPrep(limnCbfCtx *fctx, const limnCbfPoints *lpnt);
LIMN_EXPORT void limnCbfSegEval(double *xy, const limnCbfSeg *seg, double tt);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-11-30 11:52:56
|
Revision: 7248
http://sourceforge.net/p/teem/code/7248
Author: kindlmann
Date: 2024-11-30 11:52:54 +0000 (Sat, 30 Nov 2024)
Log Message:
-----------
fixing where NULL comes from
Modified Paths:
--------------
teem/trunk/python/cffi/lliibb.py
teem/trunk/python/cffi/teem.py
Modified: teem/trunk/python/cffi/lliibb.py
===================================================================
--- teem/trunk/python/cffi/lliibb.py 2024-11-28 16:42:21 UTC (rev 7247)
+++ teem/trunk/python/cffi/lliibb.py 2024-11-30 11:52:54 UTC (rev 7248)
@@ -189,7 +189,7 @@
def _equals_null(val): # likely used in _BIFF_DICT, below
"""Returns True iff given val equals NULL"""
- return val == NULL # NULL is set at very end of this file
+ return val == _lliibb.ffi.NULL
_BIFF_DICT = { # contents here are filled in by teem/python/cffi/exult.py Tffi.wrap()
Modified: teem/trunk/python/cffi/teem.py
===================================================================
--- teem/trunk/python/cffi/teem.py 2024-11-28 16:42:21 UTC (rev 7247)
+++ teem/trunk/python/cffi/teem.py 2024-11-30 11:52:54 UTC (rev 7248)
@@ -189,7 +189,7 @@
def _equals_null(val): # likely used in _BIFF_DICT, below
"""Returns True iff given val equals NULL"""
- return val == NULL # NULL is set at very end of this file
+ return val == _teem.ffi.NULL
_BIFF_DICT = { # contents here are filled in by teem/python/cffi/exult.py Tffi.wrap()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-11-28 16:42:24
|
Revision: 7247
http://sourceforge.net/p/teem/code/7247
Author: kindlmann
Date: 2024-11-28 16:42:21 +0000 (Thu, 28 Nov 2024)
Log Message:
-----------
re-ordering
Modified Paths:
--------------
teem/trunk/python/cffi/lliibb.py
teem/trunk/python/cffi/teem.py
Modified: teem/trunk/python/cffi/lliibb.py
===================================================================
--- teem/trunk/python/cffi/lliibb.py 2024-11-28 07:44:43 UTC (rev 7246)
+++ teem/trunk/python/cffi/lliibb.py 2024-11-28 16:42:21 UTC (rev 7247)
@@ -290,17 +290,26 @@
# _sym is name of an airEnum, wrap it as such
setattr(self, sym_name, Tenum(sym, sym_name))
elif (
- strsym.startswith("<cdata 'char *'") # a char* C string
- or strsym.startswith("<cdata 'struct ") # struct pointer
- # e.g. <cdata 'double(*[30])(double *)'> for _tenAnisoEval_d
- or strsym.startswith("<cdata 'double(*[")
- # e.g. <cdata 'float(*[30])(float *)'> for _tenAnisoEval_f
- or strsym.startswith("<cdata 'float(*[")
- # e.g. <cdata 'unsigned int(*[13])(void *, ...) for airParseStr
+ # Annoyingly, functions in _lliibb.lib can either look like
+ # <cdata 'int(*)(char *, ...)' 0x10af91330> or like
+ # <built-in method _lib_Foo of _cffi_backend.Lib object at 0x10b0cd210>
+ (strsym.startswith('<cdata') and '(*)(' in strsym) # some functions
+ or strsym.startswith('<built-in method') # other functions
+ # ridiculous list of wacky types of things in Teem
+ or strsym.startswith("<cdata 'void(*[")
+ or strsym.startswith("<cdata 'char *")
+ or strsym.startswith("<cdata 'char[")
+ or strsym.startswith("<cdata 'unsigned int *")
or strsym.startswith("<cdata 'unsigned int(*")
- # e.g. <cdata 'unsigned int[1000]' for airPrimeList
or strsym.startswith("<cdata 'unsigned int[")
- # e.g. some other stuff!
+ or strsym.startswith("<cdata 'int[")
+ or strsym.startswith("<cdata 'int(*[")
+ or strsym.startswith("<cdata 'float(*[")
+ or strsym.startswith("<cdata 'double[")
+ or strsym.startswith("<cdata 'double(*[")
+ or strsym.startswith("<cdata 'size_t[")
+ or strsym.startswith("<cdata 'size_t(*[")
+ or strsym.startswith("<cdata 'struct ")
or strsym.startswith("<cdata 'airFloat &'")
or strsym.startswith("<cdata 'hestCB &'")
or strsym.startswith("<cdata 'airRandMTState *'")
@@ -314,25 +323,9 @@
or strsym.startswith("<cdata 'coilMethod *")
or strsym.startswith("<cdata 'pushEnergy *")
or strsym.startswith("<cdata 'pullEnergy *")
- or strsym.startswith("<cdata 'void(*[")
- or strsym.startswith("<cdata 'int(*[")
- or strsym.startswith("<cdata 'size_t[")
- or strsym.startswith("<cdata 'size_t(*[")
- or strsym.startswith("<cdata 'int[")
- or strsym.startswith("<cdata 'char[")
- or strsym.startswith("<cdata 'double[")
- or strsym.startswith("<cdata 'char *")
- or strsym.startswith("<cdata 'unsigned int *")
- or (strsym.startswith('<cdata') and '(*)(' in strsym) # some functions
- or strsym.startswith('<built-in method') # other functions
):
# with C strings, it might be cute to instead export a real Python string, but
# then its value would NOT be useful as is for the underlying C library.
- # HEY perhaps future function wrappers will automatically handle C char*
- # <--> Python str conversions?
- # Annoyingly, functions in _lliibb.lib can either look like
- # <cdata 'int(*)(char *, ...)' 0x10af91330> or like
- # <built-in method _lib_Foo of _cffi_backend.Lib object at 0x10b0cd210>
setattr(self, sym_name, sym)
else:
# More special cases; see if sym is an integer constant: enum or #define
@@ -353,8 +346,9 @@
# sym_name is a NON-CONST scalar, do not export, instead alias it
self._alias[sym_name] = sym_name
# HEY in the python wrappers for GLK's SciVis, this aliasing is
- # non-trivial e.g. `foo.Verbose` aliases _foo.lib.fooVerbose`;
- # not sure about the utility of this here ...
+ # non-trivial e.g. `foo.Verbose` aliases _foo.lib.fooVerbose`.
+ # Here, `_alias` instead becomes a badly-named mechanism to indicate
+ # which exports might be mutable
else:
raise ValueError(
f'Libary item {sym_name} is something ({strsym}) unexpected; sorry'
Modified: teem/trunk/python/cffi/teem.py
===================================================================
--- teem/trunk/python/cffi/teem.py 2024-11-28 07:44:43 UTC (rev 7246)
+++ teem/trunk/python/cffi/teem.py 2024-11-28 16:42:21 UTC (rev 7247)
@@ -814,17 +814,26 @@
# _sym is name of an airEnum, wrap it as such
setattr(self, sym_name, Tenum(sym, sym_name))
elif (
- strsym.startswith("<cdata 'char *'") # a char* C string
- or strsym.startswith("<cdata 'struct ") # struct pointer
- # e.g. <cdata 'double(*[30])(double *)'> for _tenAnisoEval_d
- or strsym.startswith("<cdata 'double(*[")
- # e.g. <cdata 'float(*[30])(float *)'> for _tenAnisoEval_f
- or strsym.startswith("<cdata 'float(*[")
- # e.g. <cdata 'unsigned int(*[13])(void *, ...) for airParseStr
+ # Annoyingly, functions in _teem.lib can either look like
+ # <cdata 'int(*)(char *, ...)' 0x10af91330> or like
+ # <built-in method _lib_Foo of _cffi_backend.Lib object at 0x10b0cd210>
+ (strsym.startswith('<cdata') and '(*)(' in strsym) # some functions
+ or strsym.startswith('<built-in method') # other functions
+ # ridiculous list of wacky types of things in Teem
+ or strsym.startswith("<cdata 'void(*[")
+ or strsym.startswith("<cdata 'char *")
+ or strsym.startswith("<cdata 'char[")
+ or strsym.startswith("<cdata 'unsigned int *")
or strsym.startswith("<cdata 'unsigned int(*")
- # e.g. <cdata 'unsigned int[1000]' for airPrimeList
or strsym.startswith("<cdata 'unsigned int[")
- # e.g. some other stuff!
+ or strsym.startswith("<cdata 'int[")
+ or strsym.startswith("<cdata 'int(*[")
+ or strsym.startswith("<cdata 'float(*[")
+ or strsym.startswith("<cdata 'double[")
+ or strsym.startswith("<cdata 'double(*[")
+ or strsym.startswith("<cdata 'size_t[")
+ or strsym.startswith("<cdata 'size_t(*[")
+ or strsym.startswith("<cdata 'struct ")
or strsym.startswith("<cdata 'airFloat &'")
or strsym.startswith("<cdata 'hestCB &'")
or strsym.startswith("<cdata 'airRandMTState *'")
@@ -838,25 +847,9 @@
or strsym.startswith("<cdata 'coilMethod *")
or strsym.startswith("<cdata 'pushEnergy *")
or strsym.startswith("<cdata 'pullEnergy *")
- or strsym.startswith("<cdata 'void(*[")
- or strsym.startswith("<cdata 'int(*[")
- or strsym.startswith("<cdata 'size_t[")
- or strsym.startswith("<cdata 'size_t(*[")
- or strsym.startswith("<cdata 'int[")
- or strsym.startswith("<cdata 'char[")
- or strsym.startswith("<cdata 'double[")
- or strsym.startswith("<cdata 'char *")
- or strsym.startswith("<cdata 'unsigned int *")
- or (strsym.startswith('<cdata') and '(*)(' in strsym) # some functions
- or strsym.startswith('<built-in method') # other functions
):
# with C strings, it might be cute to instead export a real Python string, but
# then its value would NOT be useful as is for the underlying C library.
- # HEY perhaps future function wrappers will automatically handle C char*
- # <--> Python str conversions?
- # Annoyingly, functions in _teem.lib can either look like
- # <cdata 'int(*)(char *, ...)' 0x10af91330> or like
- # <built-in method _lib_Foo of _cffi_backend.Lib object at 0x10b0cd210>
setattr(self, sym_name, sym)
else:
# More special cases; see if sym is an integer constant: enum or #define
@@ -877,8 +870,9 @@
# sym_name is a NON-CONST scalar, do not export, instead alias it
self._alias[sym_name] = sym_name
# HEY in the python wrappers for GLK's SciVis, this aliasing is
- # non-trivial e.g. `foo.Verbose` aliases _foo.lib.fooVerbose`;
- # not sure about the utility of this here ...
+ # non-trivial e.g. `foo.Verbose` aliases _foo.lib.fooVerbose`.
+ # Here, `_alias` instead becomes a badly-named mechanism to indicate
+ # which exports might be mutable
else:
raise ValueError(
f'Libary item {sym_name} is something ({strsym}) unexpected; sorry'
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-11-28 07:44:44
|
Revision: 7246
http://sourceforge.net/p/teem/code/7246
Author: kindlmann
Date: 2024-11-28 07:44:43 +0000 (Thu, 28 Nov 2024)
Log Message:
-----------
adopting strategy that GLK used for his SciVis class code python wrappers, whereby an object instance becomes the module, and can thereby implement read-only module members
Modified Paths:
--------------
teem/trunk/python/cffi/lliibb.py
teem/trunk/python/cffi/teem.py
Modified: teem/trunk/python/cffi/lliibb.py
===================================================================
--- teem/trunk/python/cffi/lliibb.py 2024-11-28 06:18:02 UTC (rev 7245)
+++ teem/trunk/python/cffi/lliibb.py 2024-11-28 07:44:43 UTC (rev 7246)
@@ -31,7 +31,7 @@
"""
import math as _math # # likely used in _BIFF_DICT, below, for testing function return values
-
+import sys as _sys
import argparse as _argparse
# halt if python2; thanks to https://stackoverflow.com/a/65407535/1465384
@@ -233,35 +233,191 @@
return wrapper
-def export_lliibb():
+# NOTE: this is copy-pasta from GLK's SciVis class code, and the python wrappers there
+class _lliibb_Module:
+ """An object that exists just to "become" the imported module, an old hack[1,2]
+ that is still needed because even though there is now module-level __getattr__[3],
+ module-level __setattr__ has been sadly rejected[4,5]. Using __setattr__ here
+ solves two problems: (1) supporting true read-only variables, which avoids easy but
+ confusing mistakes (should NOT be able to over-write the C functions we need to use,
+ and accurately reflecting C names (of enums, functions) matters more than hewing to
+ the mere convention that ALL-CAPS Python variables are constants), and, (2) creating
+ useful aliases for global variables so that they are actually set in the underlying
+ C library instead of just modifying a Python-only variable.
+ [1] https://groups.google.com/g/comp.lang.python/c/2H53WSCXhoM
+ [2] https://mail.python.org/pipermail/python-ideas/2012-May/014969.html
+ [3] https://peps.python.org/pep-0562/
+ [4] https://discuss.python.org/t/extend-pep-562-with-setattr-for-modules/25506
+ [5] https://discuss.python.org/t/pep-726-module-setattr-and-delattr/32640
"""
- Exports things from _lliibb.lib, adding biff wrappers to functions where possible.
- """
- for sym_name in dir(_lliibb.lib):
- if 'free' == sym_name:
- # don't export C runtime's free(), though we use it above in the biff wrapper
- continue
- sym = getattr(_lliibb.lib, sym_name)
- # Create a python object in this module for the library symbol sym
- xprt = None
- # The exported symbol xprt will be ...
- if not sym_name in _BIFF_DICT:
- # ... either: not a function, or a function known to not use biff
- if str(sym).startswith("<cdata 'airEnum *' "):
+
+ # _done being False indicates to __setattr__ that __init__ is in progress
+ _done = False
+
+ def __init__(self):
+ """Set up all the extension module wrapping"""
+ # we init ourself with the globals() to best emulate being a module
+ for kk, vv in globals().items():
+ setattr(self, kk, vv)
+ # set various things that simplify using CFFI and this module
+ # for slight convenience, e.g. when calling nrrdLoad with NULL (default) NrrdIoState
+ self.NULL = _lliibb.ffi.NULL
+ # The value of this ffi, as opposed to "from cffi import FFI; ffi = FFI()" is that it knows
+ # about the various typedefs that were learned to build the CFFI wrapper, which may in turn
+ # be useful for setting up calls into liblliibb
+ self.ffi = _lliibb.ffi
+ # enable access to original un-wrapped things, straight from cffi
+ self.lib = _lliibb.lib
+ # for non-const things, self._alias maps from exported name to CFFI object
+ # in the underlying library
+ self._alias = {}
+ # go through everything in underlying C library, and process accordingly
+ for sym_name in dir(_lliibb.lib):
+ if 'free' == sym_name:
+ # don't export C runtime's free(), though we use it above in the biff wrapper
+ continue
+ # sym is the symbol with name sym_name
+ # (not __lib_.lib[sym_name] since '_cffi_backend.Lib' object is not subscriptable)
+ sym = getattr(_lliibb.lib, sym_name)
+ # string useful for distinguishing different kinds of CFFI objects
+ strsym = str(sym)
+ # The exported symbol xprt will be ...
+ if sym_name in _BIFF_DICT:
+ # ... or: a Python wrapper around a function known to use biff.
+ setattr(self, sym_name, _biffer(sym, sym_name, _BIFF_DICT[sym_name]))
+ # else either a function known to not use biff, or not a function,
+ elif strsym.startswith("<cdata 'airEnum *' "):
# _sym is name of an airEnum, wrap it as such
- xprt = Tenum(sym, sym_name)
+ setattr(self, sym_name, Tenum(sym, sym_name))
+ elif (
+ strsym.startswith("<cdata 'char *'") # a char* C string
+ or strsym.startswith("<cdata 'struct ") # struct pointer
+ # e.g. <cdata 'double(*[30])(double *)'> for _tenAnisoEval_d
+ or strsym.startswith("<cdata 'double(*[")
+ # e.g. <cdata 'float(*[30])(float *)'> for _tenAnisoEval_f
+ or strsym.startswith("<cdata 'float(*[")
+ # e.g. <cdata 'unsigned int(*[13])(void *, ...) for airParseStr
+ or strsym.startswith("<cdata 'unsigned int(*")
+ # e.g. <cdata 'unsigned int[1000]' for airPrimeList
+ or strsym.startswith("<cdata 'unsigned int[")
+ # e.g. some other stuff!
+ or strsym.startswith("<cdata 'airFloat &'")
+ or strsym.startswith("<cdata 'hestCB &'")
+ or strsym.startswith("<cdata 'airRandMTState *'")
+ or strsym.startswith("<cdata 'hestCB *'")
+ or strsym.startswith("<cdata 'unrrduCmd * *'")
+ or strsym.startswith("<cdata 'gageItemPack *'")
+ or strsym.startswith("<cdata 'NrrdFormat *")
+ or strsym.startswith("<cdata 'NrrdKernel *")
+ or strsym.startswith("<cdata 'coilKind &'")
+ or strsym.startswith("<cdata 'coilKind *")
+ or strsym.startswith("<cdata 'coilMethod *")
+ or strsym.startswith("<cdata 'pushEnergy *")
+ or strsym.startswith("<cdata 'pullEnergy *")
+ or strsym.startswith("<cdata 'void(*[")
+ or strsym.startswith("<cdata 'int(*[")
+ or strsym.startswith("<cdata 'size_t[")
+ or strsym.startswith("<cdata 'size_t(*[")
+ or strsym.startswith("<cdata 'int[")
+ or strsym.startswith("<cdata 'char[")
+ or strsym.startswith("<cdata 'double[")
+ or strsym.startswith("<cdata 'char *")
+ or strsym.startswith("<cdata 'unsigned int *")
+ or (strsym.startswith('<cdata') and '(*)(' in strsym) # some functions
+ or strsym.startswith('<built-in method') # other functions
+ ):
+ # with C strings, it might be cute to instead export a real Python string, but
+ # then its value would NOT be useful as is for the underlying C library.
+ # HEY perhaps future function wrappers will automatically handle C char*
+ # <--> Python str conversions?
+ # Annoyingly, functions in _lliibb.lib can either look like
+ # <cdata 'int(*)(char *, ...)' 0x10af91330> or like
+ # <built-in method _lib_Foo of _cffi_backend.Lib object at 0x10b0cd210>
+ setattr(self, sym_name, sym)
else:
- # straight copy of (reference to) sym
- xprt = sym
- else:
- # ... or: a Python wrapper around a function known to use biff.
- xprt = _biffer(sym, sym_name, _BIFF_DICT[sym_name])
- # can't do "if not xprt:" because, e.g. AIR_FALSE is 0 but needs to be exported
- if xprt is None:
- raise Exception(f"didn't handle symbol {sym_name}")
- globals()[sym_name] = xprt
+ # More special cases; see if sym is an integer constant: enum or #define
+ cval = None # value of symbol as integer const
+ try:
+ cval = _lliibb.ffi.integer_const(sym_name)
+ except _lliibb.ffi.error:
+ # sym_name wasn't actually an integer const; ignore the complaint.
+ pass
+ if cval is sym:
+ # so sym_name *is* an integer const, export that (integer) value
+ setattr(self, sym_name, sym)
+ elif (
+ isinstance(sym, int)
+ or isinstance(sym, float)
+ or isinstance(sym, bytes)
+ ):
+ # sym_name is a NON-CONST scalar, do not export, instead alias it
+ self._alias[sym_name] = sym_name
+ # HEY in the python wrappers for GLK's SciVis, this aliasing is
+ # non-trivial e.g. `foo.Verbose` aliases _foo.lib.fooVerbose`;
+ # not sure about the utility of this here ...
+ else:
+ raise ValueError(
+ f'Libary item {sym_name} is something ({strsym}) unexpected; sorry'
+ )
+ # done looping through symbols
+ # Fake out the name of this class to be name of wannabe module
+ self.__class__.__name__ = __name__
+ # Prevent further changes
+ self._done = True
+ def __setattr__(self, name, value):
+ """Allow new attributes during __init__, then be read-only except for aliased variables"""
+ if not self._done:
+ # self.__init__ is still in progress; pass through
+ self.__dict__[name] = value
+ return
+ # else __init__ is done; have turned mostly read-only
+ if name in self._alias:
+ # the aliases are the one thing we allow changing
+ setattr(self.lib, self._alias[name], value)
+ # and we're done
+ return
+ # else try to give informative exceptions to documenting being read-only
+ if not name in self.__dict__:
+ raise ValueError(
+ f'"{name}" not already in {self.__name__} wrapper module '
+ 'and cannot add new elements.'
+ )
+ raise ValueError(
+ f'Cannot change "{name}" in {self.__name__} wrapper module'
+ # not saying this because somethings like _lib_.NULL or .NAN
+ # are not actually in the underlying C library
+ # 'corresponding element of underlying C library is const.'
+ )
+ def __getattr__(self, name):
+ """Handle requests for attributes that don't really exist;
+ currently just the aliased variables"""
+ if name in self._alias:
+ return getattr(self.lib, self._alias[name])
+ # else not an alias
+ raise KeyError(f'"{name}" not in {self.__name__} wrapper module')
+
+ def __dir__(self):
+ """Directory of self, hacked to include the aliased variables"""
+ lst = list(self.__dict__.keys())
+ for name in self._alias:
+ lst.append(name)
+ return lst
+
+ # other utility functions that come in handy
+ def str(self, cstr):
+ """Utility function from C char* to Python string; nothing more than
+ str(cstr) = _lliibb.ffi.string(cstr).decode('utf8')"""
+ return _lliibb.ffi.string(cstr).decode('utf8')
+
+ def cs(self, pstr: str):
+ """Utility function from Python string to something compatible with C char*.
+ Has such a short name ("cs" could stand for "C string" or "char star") to be
+ shorter than its simple implementation: cs(pstr) = pstr.encode('utf8')"""
+ return pstr.encode('utf8')
+
+
if 'lliibb' == __name__: # being imported
try:
import _lliibb
@@ -271,13 +427,6 @@
print('*** _lliibb.cpython-platform.so.')
print('*** Is there a build_lliibb.py script you can run to recompile it?\n')
raise
- # The value of this ffi, as opposed to "from cffi import FFI; ffi = FFI()" is that it knows
- # about the various typedefs that were learned to build the CFFI wrapper, which may in turn
- # be useful for setting up calls into liblliibb
- ffi = _lliibb.ffi
- # enable access to original un-wrapped things, straight from cffi
- lib = _lliibb.lib
- # for slight convenience, e.g. when calling nrrdLoad with NULL (default) NrrdIoState
- NULL = _lliibb.ffi.NULL
- # now export/wrap everything
- export_lliibb()
+ # Finally, the object-instance-becomes-the-module fake-out workaround described in the
+ # __lib_Module docstring above and the links therein.
+ _sys.modules[__name__] = _lliibb_Module()
Modified: teem/trunk/python/cffi/teem.py
===================================================================
--- teem/trunk/python/cffi/teem.py 2024-11-28 06:18:02 UTC (rev 7245)
+++ teem/trunk/python/cffi/teem.py 2024-11-28 07:44:43 UTC (rev 7246)
@@ -31,7 +31,7 @@
"""
import math as _math # # likely used in _BIFF_DICT, below, for testing function return values
-
+import sys as _sys
import argparse as _argparse
# halt if python2; thanks to https://stackoverflow.com/a/65407535/1465384
@@ -757,35 +757,191 @@
return wrapper
-def export_teem():
+# NOTE: this is copy-pasta from GLK's SciVis class code, and the python wrappers there
+class _teem_Module:
+ """An object that exists just to "become" the imported module, an old hack[1,2]
+ that is still needed because even though there is now module-level __getattr__[3],
+ module-level __setattr__ has been sadly rejected[4,5]. Using __setattr__ here
+ solves two problems: (1) supporting true read-only variables, which avoids easy but
+ confusing mistakes (should NOT be able to over-write the C functions we need to use,
+ and accurately reflecting C names (of enums, functions) matters more than hewing to
+ the mere convention that ALL-CAPS Python variables are constants), and, (2) creating
+ useful aliases for global variables so that they are actually set in the underlying
+ C library instead of just modifying a Python-only variable.
+ [1] https://groups.google.com/g/comp.lang.python/c/2H53WSCXhoM
+ [2] https://mail.python.org/pipermail/python-ideas/2012-May/014969.html
+ [3] https://peps.python.org/pep-0562/
+ [4] https://discuss.python.org/t/extend-pep-562-with-setattr-for-modules/25506
+ [5] https://discuss.python.org/t/pep-726-module-setattr-and-delattr/32640
"""
- Exports things from _teem.lib, adding biff wrappers to functions where possible.
- """
- for sym_name in dir(_teem.lib):
- if 'free' == sym_name:
- # don't export C runtime's free(), though we use it above in the biff wrapper
- continue
- sym = getattr(_teem.lib, sym_name)
- # Create a python object in this module for the library symbol sym
- xprt = None
- # The exported symbol xprt will be ...
- if not sym_name in _BIFF_DICT:
- # ... either: not a function, or a function known to not use biff
- if str(sym).startswith("<cdata 'airEnum *' "):
+
+ # _done being False indicates to __setattr__ that __init__ is in progress
+ _done = False
+
+ def __init__(self):
+ """Set up all the extension module wrapping"""
+ # we init ourself with the globals() to best emulate being a module
+ for kk, vv in globals().items():
+ setattr(self, kk, vv)
+ # set various things that simplify using CFFI and this module
+ # for slight convenience, e.g. when calling nrrdLoad with NULL (default) NrrdIoState
+ self.NULL = _teem.ffi.NULL
+ # The value of this ffi, as opposed to "from cffi import FFI; ffi = FFI()" is that it knows
+ # about the various typedefs that were learned to build the CFFI wrapper, which may in turn
+ # be useful for setting up calls into libteem
+ self.ffi = _teem.ffi
+ # enable access to original un-wrapped things, straight from cffi
+ self.lib = _teem.lib
+ # for non-const things, self._alias maps from exported name to CFFI object
+ # in the underlying library
+ self._alias = {}
+ # go through everything in underlying C library, and process accordingly
+ for sym_name in dir(_teem.lib):
+ if 'free' == sym_name:
+ # don't export C runtime's free(), though we use it above in the biff wrapper
+ continue
+ # sym is the symbol with name sym_name
+ # (not __lib_.lib[sym_name] since '_cffi_backend.Lib' object is not subscriptable)
+ sym = getattr(_teem.lib, sym_name)
+ # string useful for distinguishing different kinds of CFFI objects
+ strsym = str(sym)
+ # The exported symbol xprt will be ...
+ if sym_name in _BIFF_DICT:
+ # ... or: a Python wrapper around a function known to use biff.
+ setattr(self, sym_name, _biffer(sym, sym_name, _BIFF_DICT[sym_name]))
+ # else either a function known to not use biff, or not a function,
+ elif strsym.startswith("<cdata 'airEnum *' "):
# _sym is name of an airEnum, wrap it as such
- xprt = Tenum(sym, sym_name)
+ setattr(self, sym_name, Tenum(sym, sym_name))
+ elif (
+ strsym.startswith("<cdata 'char *'") # a char* C string
+ or strsym.startswith("<cdata 'struct ") # struct pointer
+ # e.g. <cdata 'double(*[30])(double *)'> for _tenAnisoEval_d
+ or strsym.startswith("<cdata 'double(*[")
+ # e.g. <cdata 'float(*[30])(float *)'> for _tenAnisoEval_f
+ or strsym.startswith("<cdata 'float(*[")
+ # e.g. <cdata 'unsigned int(*[13])(void *, ...) for airParseStr
+ or strsym.startswith("<cdata 'unsigned int(*")
+ # e.g. <cdata 'unsigned int[1000]' for airPrimeList
+ or strsym.startswith("<cdata 'unsigned int[")
+ # e.g. some other stuff!
+ or strsym.startswith("<cdata 'airFloat &'")
+ or strsym.startswith("<cdata 'hestCB &'")
+ or strsym.startswith("<cdata 'airRandMTState *'")
+ or strsym.startswith("<cdata 'hestCB *'")
+ or strsym.startswith("<cdata 'unrrduCmd * *'")
+ or strsym.startswith("<cdata 'gageItemPack *'")
+ or strsym.startswith("<cdata 'NrrdFormat *")
+ or strsym.startswith("<cdata 'NrrdKernel *")
+ or strsym.startswith("<cdata 'coilKind &'")
+ or strsym.startswith("<cdata 'coilKind *")
+ or strsym.startswith("<cdata 'coilMethod *")
+ or strsym.startswith("<cdata 'pushEnergy *")
+ or strsym.startswith("<cdata 'pullEnergy *")
+ or strsym.startswith("<cdata 'void(*[")
+ or strsym.startswith("<cdata 'int(*[")
+ or strsym.startswith("<cdata 'size_t[")
+ or strsym.startswith("<cdata 'size_t(*[")
+ or strsym.startswith("<cdata 'int[")
+ or strsym.startswith("<cdata 'char[")
+ or strsym.startswith("<cdata 'double[")
+ or strsym.startswith("<cdata 'char *")
+ or strsym.startswith("<cdata 'unsigned int *")
+ or (strsym.startswith('<cdata') and '(*)(' in strsym) # some functions
+ or strsym.startswith('<built-in method') # other functions
+ ):
+ # with C strings, it might be cute to instead export a real Python string, but
+ # then its value would NOT be useful as is for the underlying C library.
+ # HEY perhaps future function wrappers will automatically handle C char*
+ # <--> Python str conversions?
+ # Annoyingly, functions in _teem.lib can either look like
+ # <cdata 'int(*)(char *, ...)' 0x10af91330> or like
+ # <built-in method _lib_Foo of _cffi_backend.Lib object at 0x10b0cd210>
+ setattr(self, sym_name, sym)
else:
- # straight copy of (reference to) sym
- xprt = sym
- else:
- # ... or: a Python wrapper around a function known to use biff.
- xprt = _biffer(sym, sym_name, _BIFF_DICT[sym_name])
- # can't do "if not xprt:" because, e.g. AIR_FALSE is 0 but needs to be exported
- if xprt is None:
- raise Exception(f"didn't handle symbol {sym_name}")
- globals()[sym_name] = xprt
+ # More special cases; see if sym is an integer constant: enum or #define
+ cval = None # value of symbol as integer const
+ try:
+ cval = _teem.ffi.integer_const(sym_name)
+ except _teem.ffi.error:
+ # sym_name wasn't actually an integer const; ignore the complaint.
+ pass
+ if cval is sym:
+ # so sym_name *is* an integer const, export that (integer) value
+ setattr(self, sym_name, sym)
+ elif (
+ isinstance(sym, int)
+ or isinstance(sym, float)
+ or isinstance(sym, bytes)
+ ):
+ # sym_name is a NON-CONST scalar, do not export, instead alias it
+ self._alias[sym_name] = sym_name
+ # HEY in the python wrappers for GLK's SciVis, this aliasing is
+ # non-trivial e.g. `foo.Verbose` aliases _foo.lib.fooVerbose`;
+ # not sure about the utility of this here ...
+ else:
+ raise ValueError(
+ f'Libary item {sym_name} is something ({strsym}) unexpected; sorry'
+ )
+ # done looping through symbols
+ # Fake out the name of this class to be name of wannabe module
+ self.__class__.__name__ = __name__
+ # Prevent further changes
+ self._done = True
+ def __setattr__(self, name, value):
+ """Allow new attributes during __init__, then be read-only except for aliased variables"""
+ if not self._done:
+ # self.__init__ is still in progress; pass through
+ self.__dict__[name] = value
+ return
+ # else __init__ is done; have turned mostly read-only
+ if name in self._alias:
+ # the aliases are the one thing we allow changing
+ setattr(self.lib, self._alias[name], value)
+ # and we're done
+ return
+ # else try to give informative exceptions to documenting being read-only
+ if not name in self.__dict__:
+ raise ValueError(
+ f'"{name}" not already in {self.__name__} wrapper module '
+ 'and cannot add new elements.'
+ )
+ raise ValueError(
+ f'Cannot change "{name}" in {self.__name__} wrapper module'
+ # not saying this because somethings like _lib_.NULL or .NAN
+ # are not actually in the underlying C library
+ # 'corresponding element of underlying C library is const.'
+ )
+ def __getattr__(self, name):
+ """Handle requests for attributes that don't really exist;
+ currently just the aliased variables"""
+ if name in self._alias:
+ return getattr(self.lib, self._alias[name])
+ # else not an alias
+ raise KeyError(f'"{name}" not in {self.__name__} wrapper module')
+
+ def __dir__(self):
+ """Directory of self, hacked to include the aliased variables"""
+ lst = list(self.__dict__.keys())
+ for name in self._alias:
+ lst.append(name)
+ return lst
+
+ # other utility functions that come in handy
+ def str(self, cstr):
+ """Utility function from C char* to Python string; nothing more than
+ str(cstr) = _teem.ffi.string(cstr).decode('utf8')"""
+ return _teem.ffi.string(cstr).decode('utf8')
+
+ def cs(self, pstr: str):
+ """Utility function from Python string to something compatible with C char*.
+ Has such a short name ("cs" could stand for "C string" or "char star") to be
+ shorter than its simple implementation: cs(pstr) = pstr.encode('utf8')"""
+ return pstr.encode('utf8')
+
+
if 'teem' == __name__: # being imported
try:
import _teem
@@ -795,13 +951,6 @@
print('*** _teem.cpython-platform.so.')
print('*** Is there a build_teem.py script you can run to recompile it?\n')
raise
- # The value of this ffi, as opposed to "from cffi import FFI; ffi = FFI()" is that it knows
- # about the various typedefs that were learned to build the CFFI wrapper, which may in turn
- # be useful for setting up calls into libteem
- ffi = _teem.ffi
- # enable access to original un-wrapped things, straight from cffi
- lib = _teem.lib
- # for slight convenience, e.g. when calling nrrdLoad with NULL (default) NrrdIoState
- NULL = _teem.ffi.NULL
- # now export/wrap everything
- export_teem()
+ # Finally, the object-instance-becomes-the-module fake-out workaround described in the
+ # __lib_Module docstring above and the links therein.
+ _sys.modules[__name__] = _teem_Module()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-11-28 06:18:03
|
Revision: 7245
http://sourceforge.net/p/teem/code/7245
Author: kindlmann
Date: 2024-11-28 06:18:02 +0000 (Thu, 28 Nov 2024)
Log Message:
-----------
synching Tenum with GLKs SciVis class python wrappers, adding TenumVal and TenumValParseAction from that
Modified Paths:
--------------
teem/trunk/python/cffi/teem.py
Modified: teem/trunk/python/cffi/teem.py
===================================================================
--- teem/trunk/python/cffi/teem.py 2024-11-28 06:13:22 UTC (rev 7244)
+++ teem/trunk/python/cffi/teem.py 2024-11-28 06:18:02 UTC (rev 7245)
@@ -32,6 +32,8 @@
import math as _math # # likely used in _BIFF_DICT, below, for testing function return values
+import argparse as _argparse
+
# halt if python2; thanks to https://stackoverflow.com/a/65407535/1465384
_x, *_y = 1, 2 # NOTE: A SyntaxError means you need Python3, not Python2
del _x, _y
@@ -52,7 +54,9 @@
def __init__(self, aenm, _name):
"""Constructor takes a Teem airEnum pointer (const airEnum *const)."""
if not str(aenm).startswith("<cdata 'airEnum *' "):
- raise TypeError(f'passed argument {aenm} does not seem to be an airEnum pointer')
+ raise TypeError(
+ f'passed argument {aenm} does not seem to be an airEnum pointer'
+ )
self.aenm = aenm
self.name = string(self.aenm.name)
self._name = _name # the variable name for the airEnum in libteem
@@ -69,6 +73,10 @@
"""Provides a way to iterate through the valid values of the enum"""
return iter(self.vals)
+ def vals(self):
+ """Provides list of valid values"""
+ return self._vals.copy()
+
def valid(self, ios) -> bool: # ios = int or string
"""Answers whether given int is a valid value of enum, or whether given string
is a valid string in enum, depending on incoming type.
@@ -80,15 +88,20 @@
# else
raise TypeError(f'Need an int or str argument (not {type(ios)})')
- def str(self, val: int, picky=False) -> str:
- """Converts from integer enum value val to string identifier
- (wraps airEnumStr())"""
+ def str(self, val: int, picky=False, excls=ValueError) -> str:
+ """Converts from integer enum value val to string identifier.
+ If picky, then failure to parse string generates an exception,
+ of class excls (defaults to ValueError) (wraps airEnumStr())"""
assert isinstance(val, int), f'Need an int argument (not {type(val)})'
if picky and not self.valid(val):
- raise ValueError(f'{val} not a valid {self._name} ("{self.name}") enum value')
+ raise excls(f'{val} not a valid {self._name} ("{self.name}") enum value')
# else
- return string(_teem.lib.airEnumStr(self.aenm, val))
+ return _teem.ffi.string(_teem.lib.airEnumStr(self.aenm, val)).decode('utf8')
+ def strs(self):
+ """Provides a list of strings for the valid values"""
+ return [self.str(v) for v in self.vals()]
+
def desc(self, val: int) -> str:
"""Converts from integer value val to description string
(wraps airEnumDesc())"""
@@ -101,7 +114,9 @@
assert isinstance(sss, str), f'Need an string argument (not {type(sss)})'
ret = _teem.lib.airEnumVal(self.aenm, sss.encode('ascii'))
if picky and ret == self.unknown():
- raise ValueError(f'"{sss}" not parsable as {self._name} ("{self.name}") enum value')
+ raise ValueError(
+ f'"{sss}" not parsable as {self._name} ("{self.name}") enum value'
+ )
# else
return ret
@@ -111,6 +126,62 @@
return _teem.lib.airEnumUnknown(self.aenm)
+class TenumVal:
+ """Represents one value in a Tenum, in a way that can be both an int and a string,
+ and that remembers which Tenum it is part of"""
+
+ def __init__(self, tenum, ios):
+ """Create enum value from Tenum and either int or string value"""
+ if not isinstance(tenum, Tenum):
+ raise ValueError(f'Given {tenum=} not actually a Tenum')
+ if not tenum.valid(ios):
+ raise ValueError(f'Given {ios=} not member of enum {tenum.name}')
+ self.tenum = tenum
+ self.val = ios if isinstance(ios, int) else tenum.val(ios)
+
+ def __str__(self):
+ """Return own value as string"""
+ return self.tenum.str(self.val)
+
+ def __int__(self):
+ """Return own value as int"""
+ return self.val
+
+ def __repr__(self):
+ """Full string representation of own value
+ (though currently nothing knows how to parse this)"""
+ return f'{self.tenum.str(self.val)}:({self.tenum.name} enum)'
+
+ def __eq__(self, other):
+ """Test equality between two things"""
+ if isinstance(other, TenumVal):
+ if self.tenum != other.tenum:
+ return False
+ # else other same kind of tenum
+ return self.val == other.val
+ # else other not a tenum
+ if not self.tenum.valid(other):
+ raise ValueError(f'Given {other=} not member of enum {self.tenum.name}')
+ oval = other if isinstance(other, int) else self.tenum.val(other)
+ return self.val == oval
+
+
+class TenumValParseAction(_argparse.Action):
+ """Custom argparse action for parsing a TenumVal from the command-line"""
+
+ def __init__(self, option_strings, dest, tenum, **kwargs):
+ super().__init__(option_strings, dest, **kwargs)
+ # Store the enum we want to parse
+ self.tenum = tenum
+
+ def __call__(self, _parser, namespace, string, _option_string=None):
+ # parse value from string
+ val = self.tenum.val(string, True, _argparse.ArgumentTypeError)
+ tval = TenumVal(self.tenum, val)
+ # Set the parsed result in the namespace
+ setattr(namespace, self.dest, tval)
+
+
def _equals_one(val): # likely used in _BIFF_DICT, below
"""Returns True iff given val equals 1"""
return val == 1
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-11-28 06:13:25
|
Revision: 7244
http://sourceforge.net/p/teem/code/7244
Author: kindlmann
Date: 2024-11-28 06:13:22 +0000 (Thu, 28 Nov 2024)
Log Message:
-----------
synching Tenum with GLKs SciVis class python wrappers, adding TenumVal and TenumValParseAction from that
Modified Paths:
--------------
teem/trunk/python/cffi/lliibb.py
Modified: teem/trunk/python/cffi/lliibb.py
===================================================================
--- teem/trunk/python/cffi/lliibb.py 2024-11-28 05:29:44 UTC (rev 7243)
+++ teem/trunk/python/cffi/lliibb.py 2024-11-28 06:13:22 UTC (rev 7244)
@@ -32,6 +32,8 @@
import math as _math # # likely used in _BIFF_DICT, below, for testing function return values
+import argparse as _argparse
+
# halt if python2; thanks to https://stackoverflow.com/a/65407535/1465384
_x, *_y = 1, 2 # NOTE: A SyntaxError means you need Python3, not Python2
del _x, _y
@@ -71,6 +73,10 @@
"""Provides a way to iterate through the valid values of the enum"""
return iter(self.vals)
+ def vals(self):
+ """Provides list of valid values"""
+ return self._vals.copy()
+
def valid(self, ios) -> bool: # ios = int or string
"""Answers whether given int is a valid value of enum, or whether given string
is a valid string in enum, depending on incoming type.
@@ -82,17 +88,20 @@
# else
raise TypeError(f'Need an int or str argument (not {type(ios)})')
- def str(self, val: int, picky=False) -> str:
- """Converts from integer enum value val to string identifier
- (wraps airEnumStr())"""
+ def str(self, val: int, picky=False, excls=ValueError) -> str:
+ """Converts from integer enum value val to string identifier.
+ If picky, then failure to parse string generates an exception,
+ of class excls (defaults to ValueError) (wraps airEnumStr())"""
assert isinstance(val, int), f'Need an int argument (not {type(val)})'
if picky and not self.valid(val):
- raise ValueError(
- f'{val} not a valid {self._name} ("{self.name}") enum value'
- )
+ raise excls(f'{val} not a valid {self._name} ("{self.name}") enum value')
# else
- return string(_lliibb.lib.airEnumStr(self.aenm, val))
+ return _lliibb.ffi.string(_lliibb.lib.airEnumStr(self.aenm, val)).decode('utf8')
+ def strs(self):
+ """Provides a list of strings for the valid values"""
+ return [self.str(v) for v in self.vals()]
+
def desc(self, val: int) -> str:
"""Converts from integer value val to description string
(wraps airEnumDesc())"""
@@ -117,6 +126,62 @@
return _lliibb.lib.airEnumUnknown(self.aenm)
+class TenumVal:
+ """Represents one value in a Tenum, in a way that can be both an int and a string,
+ and that remembers which Tenum it is part of"""
+
+ def __init__(self, tenum, ios):
+ """Create enum value from Tenum and either int or string value"""
+ if not isinstance(tenum, Tenum):
+ raise ValueError(f'Given {tenum=} not actually a Tenum')
+ if not tenum.valid(ios):
+ raise ValueError(f'Given {ios=} not member of enum {tenum.name}')
+ self.tenum = tenum
+ self.val = ios if isinstance(ios, int) else tenum.val(ios)
+
+ def __str__(self):
+ """Return own value as string"""
+ return self.tenum.str(self.val)
+
+ def __int__(self):
+ """Return own value as int"""
+ return self.val
+
+ def __repr__(self):
+ """Full string representation of own value
+ (though currently nothing knows how to parse this)"""
+ return f'{self.tenum.str(self.val)}:({self.tenum.name} enum)'
+
+ def __eq__(self, other):
+ """Test equality between two things"""
+ if isinstance(other, TenumVal):
+ if self.tenum != other.tenum:
+ return False
+ # else other same kind of tenum
+ return self.val == other.val
+ # else other not a tenum
+ if not self.tenum.valid(other):
+ raise ValueError(f'Given {other=} not member of enum {self.tenum.name}')
+ oval = other if isinstance(other, int) else self.tenum.val(other)
+ return self.val == oval
+
+
+class TenumValParseAction(_argparse.Action):
+ """Custom argparse action for parsing a TenumVal from the command-line"""
+
+ def __init__(self, option_strings, dest, tenum, **kwargs):
+ super().__init__(option_strings, dest, **kwargs)
+ # Store the enum we want to parse
+ self.tenum = tenum
+
+ def __call__(self, _parser, namespace, string, _option_string=None):
+ # parse value from string
+ val = self.tenum.val(string, True, _argparse.ArgumentTypeError)
+ tval = TenumVal(self.tenum, val)
+ # Set the parsed result in the namespace
+ setattr(namespace, self.dest, tval)
+
+
def _equals_one(val): # likely used in _BIFF_DICT, below
"""Returns True iff given val equals 1"""
return val == 1
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-11-28 05:29:46
|
Revision: 7243
http://sourceforge.net/p/teem/code/7243
Author: kindlmann
Date: 2024-11-28 05:29:44 +0000 (Thu, 28 Nov 2024)
Log Message:
-----------
just blue formatting (maybe shorter line length?)
Modified Paths:
--------------
teem/trunk/python/cffi/lliibb.py
Modified: teem/trunk/python/cffi/lliibb.py
===================================================================
--- teem/trunk/python/cffi/lliibb.py 2024-11-28 05:28:59 UTC (rev 7242)
+++ teem/trunk/python/cffi/lliibb.py 2024-11-28 05:29:44 UTC (rev 7243)
@@ -52,7 +52,9 @@
def __init__(self, aenm, _name):
"""Constructor takes a Teem airEnum pointer (const airEnum *const)."""
if not str(aenm).startswith("<cdata 'airEnum *' "):
- raise TypeError(f'passed argument {aenm} does not seem to be an airEnum pointer')
+ raise TypeError(
+ f'passed argument {aenm} does not seem to be an airEnum pointer'
+ )
self.aenm = aenm
self.name = string(self.aenm.name)
self._name = _name # the variable name for the airEnum in libteem
@@ -85,7 +87,9 @@
(wraps airEnumStr())"""
assert isinstance(val, int), f'Need an int argument (not {type(val)})'
if picky and not self.valid(val):
- raise ValueError(f'{val} not a valid {self._name} ("{self.name}") enum value')
+ raise ValueError(
+ f'{val} not a valid {self._name} ("{self.name}") enum value'
+ )
# else
return string(_lliibb.lib.airEnumStr(self.aenm, val))
@@ -101,7 +105,9 @@
assert isinstance(sss, str), f'Need an string argument (not {type(sss)})'
ret = _lliibb.lib.airEnumVal(self.aenm, sss.encode('ascii'))
if picky and ret == self.unknown():
- raise ValueError(f'"{sss}" not parsable as {self._name} ("{self.name}") enum value')
+ raise ValueError(
+ f'"{sss}" not parsable as {self._name} ("{self.name}") enum value'
+ )
# else
return ret
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-11-28 05:29:01
|
Revision: 7242
http://sourceforge.net/p/teem/code/7242
Author: kindlmann
Date: 2024-11-28 05:28:59 +0000 (Thu, 28 Nov 2024)
Log Message:
-----------
noted more realistic release year
Modified Paths:
--------------
teem/trunk/python/cffi/README.md
Modified: teem/trunk/python/cffi/README.md
===================================================================
--- teem/trunk/python/cffi/README.md 2024-09-19 21:28:42 UTC (rev 7241)
+++ teem/trunk/python/cffi/README.md 2024-11-28 05:28:59 UTC (rev 7242)
@@ -1,6 +1,6 @@
# CFFI-based Python wrappers for Teem
-The `teem.py` in this directory is a new (as of Teem v2 in 2024) Python wrapper for all of Teem, built via CFFI. It does useful error handling, and has one or more helper/wrappers (including a Python object "foo" wrapping of "const airEnum \*const foo").
+The `teem.py` in this directory is a new (as of Teem v2 in 2024? 2025?) Python wrapper for all of Teem, built via CFFI. It does useful error handling, and has one or more helper/wrappers (including a Python object "foo" wrapping of "const airEnum \*const foo").
These notes by GLK are mostly to document for future GLK what's involved in creating teem.py, but also for anyone else who is in a position to improve how Python users can access and benefit from Teem.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-09-19 21:28:44
|
Revision: 7241
http://sourceforge.net/p/teem/code/7241
Author: kindlmann
Date: 2024-09-19 21:28:42 +0000 (Thu, 19 Sep 2024)
Log Message:
-----------
syncing with source
Modified Paths:
--------------
teem/trunk/python/cffi/biffdata/nrrd.csv
teem/trunk/python/cffi/cdef/cdef_nrrd.h
teem/trunk/python/cffi/teem.py
Modified: teem/trunk/python/cffi/biffdata/nrrd.csv
===================================================================
--- teem/trunk/python/cffi/biffdata/nrrd.csv 2024-09-19 20:41:54 UTC (rev 7240)
+++ teem/trunk/python/cffi/biffdata/nrrd.csv 2024-09-19 21:28:42 UTC (rev 7241)
@@ -71,28 +71,28 @@
nrrdBoundarySpecParse,int,1,0,nrrd,nrrd/methodsNrrd.c:117
nrrdBoundarySpecSprint,int,1,0,nrrd,nrrd/methodsNrrd.c:176
nrrdBoundarySpecCompare,int,1,0,nrrd,nrrd/methodsNrrd.c:198
-nrrdBasicInfoCopy,int,1,0,nrrd,nrrd/methodsNrrd.c:538
-nrrdWrap_nva,int,1,0,nrrd,nrrd/methodsNrrd.c:814
-nrrdWrap_va,int,1,0,nrrd,nrrd/methodsNrrd.c:845
-nrrdCopy,int,1,0,nrrd,nrrd/methodsNrrd.c:936
-nrrdAlloc_nva,int,1,0,nrrd,nrrd/methodsNrrd.c:966
-nrrdAlloc_va,int,1,0,nrrd,nrrd/methodsNrrd.c:1015
-nrrdMaybeAlloc_nva,int,1,0,nrrd,nrrd/methodsNrrd.c:1136
-nrrdMaybeAlloc_va,int,1,0,nrrd,nrrd/methodsNrrd.c:1153
-nrrdCompare,int,1,0,nrrd,nrrd/methodsNrrd.c:1194
-nrrdPPM,int,1,0,nrrd,nrrd/methodsNrrd.c:1380
-nrrdPGM,int,1,0,nrrd,nrrd/methodsNrrd.c:1400
+nrrdBasicInfoCopy,int,1,0,nrrd,nrrd/methodsNrrd.c:541
+nrrdWrap_nva,int,1,0,nrrd,nrrd/methodsNrrd.c:817
+nrrdWrap_va,int,1,0,nrrd,nrrd/methodsNrrd.c:848
+nrrdCopy,int,1,0,nrrd,nrrd/methodsNrrd.c:939
+nrrdAlloc_nva,int,1,0,nrrd,nrrd/methodsNrrd.c:969
+nrrdAlloc_va,int,1,0,nrrd,nrrd/methodsNrrd.c:1018
+nrrdMaybeAlloc_nva,int,1,0,nrrd,nrrd/methodsNrrd.c:1139
+nrrdMaybeAlloc_va,int,1,0,nrrd,nrrd/methodsNrrd.c:1156
+nrrdCompare,int,1,0,nrrd,nrrd/methodsNrrd.c:1197
+nrrdPPM,int,1,0,nrrd,nrrd/methodsNrrd.c:1383
+nrrdPGM,int,1,0,nrrd,nrrd/methodsNrrd.c:1403
nrrdSpaceVectorParse,int,1,4,nrrd,nrrd/parseNrrd.c:521
_nrrdDataFNCheck,int,1,3,nrrd,nrrd/parseNrrd.c:1198
nrrdRangePercentileSet,int,1,0,nrrd,nrrd/range.c:109
nrrdRangePercentileFromStringSet,int,1,0,nrrd,nrrd/range.c:211
-nrrdOneLine,int,1,0,nrrd,nrrd/read.c:72
-nrrdLineSkip,int,1,0,nrrd,nrrd/read.c:236
-nrrdByteSkip,int,1,0,nrrd,nrrd/read.c:332
-nrrdRead,int,1,0,nrrd,nrrd/read.c:496
-nrrdStringRead,int,1,0,nrrd,nrrd/read.c:516
-nrrdLoad,int,1|2,0,nrrd,nrrd/read.c:612
-nrrdLoadMulti,int,1,0,nrrd,nrrd/read.c:666
+nrrdOneLine,int,1,0,nrrd,nrrd/read.c:76
+nrrdLineSkip,int,1,0,nrrd,nrrd/read.c:240
+nrrdByteSkip,int,1,0,nrrd,nrrd/read.c:336
+nrrdRead,int,1,0,nrrd,nrrd/read.c:500
+nrrdStringRead,int,1,0,nrrd,nrrd/read.c:520
+nrrdLoad,int,1|2,0,nrrd,nrrd/read.c:616
+nrrdLoadMulti,int,1,0,nrrd,nrrd/read.c:683
nrrdInvertPerm,int,1,0,nrrd,nrrd/reorder.c:34
nrrdAxesInsert,int,1,0,nrrd,nrrd/reorder.c:86
nrrdAxesPermute,int,1,0,nrrd,nrrd/reorder.c:152
@@ -147,10 +147,10 @@
nrrdPad_nva,int,1,0,nrrd,nrrd/superset.c:487
nrrdSimplePad_va,int,1,0,nrrd,nrrd/superset.c:515
nrrdSimplePad_nva,int,1,0,nrrd,nrrd/superset.c:553
-nrrdIoStateSet,int,1,0,nrrd,nrrd/write.c:31
-nrrdIoStateEncodingSet,int,1,0,nrrd,nrrd/write.c:104
-nrrdIoStateFormatSet,int,1,0,nrrd,nrrd/write.c:124
-nrrdWrite,int,1,0,nrrd,nrrd/write.c:944
-nrrdStringWrite,int,1,0,nrrd,nrrd/write.c:960
-nrrdSave,int,1,0,nrrd,nrrd/write.c:981
-nrrdSaveMulti,int,1,0,nrrd,nrrd/write.c:1034
+nrrdIoStateSet,int,1,0,nrrd,nrrd/write.c:30
+nrrdIoStateEncodingSet,int,1,0,nrrd,nrrd/write.c:103
+nrrdIoStateFormatSet,int,1,0,nrrd,nrrd/write.c:123
+nrrdWrite,int,1,0,nrrd,nrrd/write.c:943
+nrrdStringWrite,int,1,0,nrrd,nrrd/write.c:959
+nrrdSave,int,1,0,nrrd,nrrd/write.c:980
+nrrdSaveMulti,int,1,0,nrrd,nrrd/write.c:1046
Modified: teem/trunk/python/cffi/cdef/cdef_nrrd.h
===================================================================
--- teem/trunk/python/cffi/cdef/cdef_nrrd.h 2024-09-19 20:41:54 UTC (rev 7240)
+++ teem/trunk/python/cffi/cdef/cdef_nrrd.h 2024-09-19 21:28:42 UTC (rev 7241)
@@ -1151,15 +1151,29 @@
nrrd format. Probably used in conjunction with
skipData. (currently for "unu data")
ON WRITE: no semantics */
- zlibLevel, /* zlib compression level (0-9, -1 for
- default[6], 0 for no compression). */
- zlibStrategy, /* zlib compression strategy, can be one
- of the nrrdZlibStrategy enums, default is
- nrrdZlibStrategyDefault. */
- bzip2BlockSize, /* block size used for compression,
- roughly equivalent to better but slower
- (1-9, -1 for default[9]). */
/* ---- BEGIN non-NrrdIO */
+ declineStdioOnTTY, /* ON READ and ON WRITE: If nrrdLoad is about to read from
+ filename "-" (via nrrdRead), or nrrdSave is about to write to
+ "-" (via nrrdWrite), regardless of file format (which isn't
+ known on read, though may be known on write): if this is
+ non-zero, decline to nrrdRead from stdin or nrrdWrite to stdout
+ IF stdin/stdout seems to be a terminal (as per isatty()). On
+ read, this avoids cryptic stalls as something tries to read
+ from the terminal (where a human is unlikely to be typing the
+ file contents), and on write, this avoids clobbering the
+ terminal with screens of non-printing characters. Using
+ filename "-=" is a sneaky way to name stdin/stdout while
+ over-riding this declination and force that IO to happen. */
+ /* ---- END non-NrrdIO */
+ zlibLevel, /* zlib compression level (0-9, -1 for
+ default[6], 0 for no compression). */
+ zlibStrategy, /* zlib compression strategy, can be one
+ of the nrrdZlibStrategy enums, default is
+ nrrdZlibStrategyDefault. */
+ bzip2BlockSize, /* block size used for compression,
+ roughly equivalent to better but slower
+ (1-9, -1 for default[9]). */
+ /* ---- BEGIN non-NrrdIO */
/* seems odd to have contents of NrrdIoState differ between full Teem
and NrrdIO, but these fields can't be meaningfully set or read if
the nrrdFormatPNGsRGBIntent is not available */
@@ -1412,6 +1426,7 @@
extern double nrrdDefaultResamplePadValue;
extern int nrrdDefaultResampleNonExistent;
extern double nrrdDefaultKernelParm0;
+extern int nrrdDefaultDeclineStdioOnTTY;
/* ---- END non-NrrdIO */
extern int nrrdDefaultCenter;
extern double nrrdDefaultSpacing;
Modified: teem/trunk/python/cffi/teem.py
===================================================================
--- teem/trunk/python/cffi/teem.py 2024-09-19 20:41:54 UTC (rev 7240)
+++ teem/trunk/python/cffi/teem.py 2024-09-19 21:28:42 UTC (rev 7241)
@@ -194,28 +194,28 @@
'nrrdBoundarySpecParse': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:117'),
'nrrdBoundarySpecSprint': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:176'),
'nrrdBoundarySpecCompare': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:198'),
- 'nrrdBasicInfoCopy': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:538'),
- 'nrrdWrap_nva': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:814'),
- 'nrrdWrap_va': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:845'),
- 'nrrdCopy': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:936'),
- 'nrrdAlloc_nva': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:966'),
- 'nrrdAlloc_va': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1015'),
- 'nrrdMaybeAlloc_nva': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1136'),
- 'nrrdMaybeAlloc_va': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1153'),
- 'nrrdCompare': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1194'),
- 'nrrdPPM': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1380'),
- 'nrrdPGM': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1400'),
+ 'nrrdBasicInfoCopy': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:541'),
+ 'nrrdWrap_nva': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:817'),
+ 'nrrdWrap_va': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:848'),
+ 'nrrdCopy': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:939'),
+ 'nrrdAlloc_nva': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:969'),
+ 'nrrdAlloc_va': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1018'),
+ 'nrrdMaybeAlloc_nva': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1139'),
+ 'nrrdMaybeAlloc_va': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1156'),
+ 'nrrdCompare': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1197'),
+ 'nrrdPPM': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1383'),
+ 'nrrdPGM': (_equals_one, 0, b'nrrd', 'nrrd/methodsNrrd.c:1403'),
'nrrdSpaceVectorParse': (_equals_one, 4, b'nrrd', 'nrrd/parseNrrd.c:521'),
'_nrrdDataFNCheck': (_equals_one, 3, b'nrrd', 'nrrd/parseNrrd.c:1198'),
'nrrdRangePercentileSet': (_equals_one, 0, b'nrrd', 'nrrd/range.c:109'),
'nrrdRangePercentileFromStringSet': (_equals_one, 0, b'nrrd', 'nrrd/range.c:211'),
- 'nrrdOneLine': (_equals_one, 0, b'nrrd', 'nrrd/read.c:72'),
- 'nrrdLineSkip': (_equals_one, 0, b'nrrd', 'nrrd/read.c:236'),
- 'nrrdByteSkip': (_equals_one, 0, b'nrrd', 'nrrd/read.c:332'),
- 'nrrdRead': (_equals_one, 0, b'nrrd', 'nrrd/read.c:496'),
- 'nrrdStringRead': (_equals_one, 0, b'nrrd', 'nrrd/read.c:516'),
- 'nrrdLoad': ((lambda rv: 1 == rv or 2 == rv), 0, b'nrrd', 'nrrd/read.c:612'),
- 'nrrdLoadMulti': (_equals_one, 0, b'nrrd', 'nrrd/read.c:666'),
+ 'nrrdOneLine': (_equals_one, 0, b'nrrd', 'nrrd/read.c:76'),
+ 'nrrdLineSkip': (_equals_one, 0, b'nrrd', 'nrrd/read.c:240'),
+ 'nrrdByteSkip': (_equals_one, 0, b'nrrd', 'nrrd/read.c:336'),
+ 'nrrdRead': (_equals_one, 0, b'nrrd', 'nrrd/read.c:500'),
+ 'nrrdStringRead': (_equals_one, 0, b'nrrd', 'nrrd/read.c:520'),
+ 'nrrdLoad': ((lambda rv: 1 == rv or 2 == rv), 0, b'nrrd', 'nrrd/read.c:616'),
+ 'nrrdLoadMulti': (_equals_one, 0, b'nrrd', 'nrrd/read.c:683'),
'nrrdInvertPerm': (_equals_one, 0, b'nrrd', 'nrrd/reorder.c:34'),
'nrrdAxesInsert': (_equals_one, 0, b'nrrd', 'nrrd/reorder.c:86'),
'nrrdAxesPermute': (_equals_one, 0, b'nrrd', 'nrrd/reorder.c:152'),
@@ -270,13 +270,13 @@
'nrrdPad_nva': (_equals_one, 0, b'nrrd', 'nrrd/superset.c:487'),
'nrrdSimplePad_va': (_equals_one, 0, b'nrrd', 'nrrd/superset.c:515'),
'nrrdSimplePad_nva': (_equals_one, 0, b'nrrd', 'nrrd/superset.c:553'),
- 'nrrdIoStateSet': (_equals_one, 0, b'nrrd', 'nrrd/write.c:31'),
- 'nrrdIoStateEncodingSet': (_equals_one, 0, b'nrrd', 'nrrd/write.c:104'),
- 'nrrdIoStateFormatSet': (_equals_one, 0, b'nrrd', 'nrrd/write.c:124'),
- 'nrrdWrite': (_equals_one, 0, b'nrrd', 'nrrd/write.c:944'),
- 'nrrdStringWrite': (_equals_one, 0, b'nrrd', 'nrrd/write.c:960'),
- 'nrrdSave': (_equals_one, 0, b'nrrd', 'nrrd/write.c:981'),
- 'nrrdSaveMulti': (_equals_one, 0, b'nrrd', 'nrrd/write.c:1034'),
+ 'nrrdIoStateSet': (_equals_one, 0, b'nrrd', 'nrrd/write.c:30'),
+ 'nrrdIoStateEncodingSet': (_equals_one, 0, b'nrrd', 'nrrd/write.c:103'),
+ 'nrrdIoStateFormatSet': (_equals_one, 0, b'nrrd', 'nrrd/write.c:123'),
+ 'nrrdWrite': (_equals_one, 0, b'nrrd', 'nrrd/write.c:943'),
+ 'nrrdStringWrite': (_equals_one, 0, b'nrrd', 'nrrd/write.c:959'),
+ 'nrrdSave': (_equals_one, 0, b'nrrd', 'nrrd/write.c:980'),
+ 'nrrdSaveMulti': (_equals_one, 0, b'nrrd', 'nrrd/write.c:1046'),
'ell_Nm_check': (_equals_one, 0, b'ell', 'ell/genmat.c:25'),
'ell_Nm_tran': (_equals_one, 0, b'ell', 'ell/genmat.c:59'),
'ell_Nm_mul': (_equals_one, 0, b'ell', 'ell/genmat.c:104'),
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-09-19 20:41:56
|
Revision: 7240
http://sourceforge.net/p/teem/code/7240
Author: kindlmann
Date: 2024-09-19 20:41:54 +0000 (Thu, 19 Sep 2024)
Log Message:
-----------
API NEW: new field NrrdIoState->declineStdioOnTTY, which instructs nrrdLoad/nrrdSave to decline reading/writing to stdin/stdout if the given filename is - AND stdin/stdout is a terminal (as per isatty). Can be over-ridden by using filename -=. This is long-wanted functionality that was only half-addressed, on the command-line input side, via nrrdHestNrrdNoTTY
Modified Paths:
--------------
teem/trunk/src/nrrd/defaultsNrrd.c
teem/trunk/src/nrrd/methodsNrrd.c
teem/trunk/src/nrrd/nrrd.h
teem/trunk/src/nrrd/read.c
teem/trunk/src/nrrd/write.c
Modified: teem/trunk/src/nrrd/defaultsNrrd.c
===================================================================
--- teem/trunk/src/nrrd/defaultsNrrd.c 2024-09-19 20:36:33 UTC (rev 7239)
+++ teem/trunk/src/nrrd/defaultsNrrd.c 2024-09-19 20:41:54 UTC (rev 7240)
@@ -51,6 +51,8 @@
double nrrdDefaultResamplePadValue = 0.0;
int nrrdDefaultResampleNonExistent = nrrdResampleNonExistentNoop;
double nrrdDefaultKernelParm0 = 1.0;
+/* creating and by-default enabling this functionality is a change for Teem2 */
+int nrrdDefaultDeclineStdioOnTTY = AIR_TRUE;
/* ---- END non-NrrdIO */
int nrrdDefaultCenter = nrrdCenterCell;
double nrrdDefaultSpacing = 1.0;
Modified: teem/trunk/src/nrrd/methodsNrrd.c
===================================================================
--- teem/trunk/src/nrrd/methodsNrrd.c 2024-09-19 20:36:33 UTC (rev 7239)
+++ teem/trunk/src/nrrd/methodsNrrd.c 2024-09-19 20:41:54 UTC (rev 7240)
@@ -278,6 +278,9 @@
nio->skipData = AIR_FALSE;
nio->skipFormatURL = AIR_FALSE;
nio->keepNrrdDataFileOpen = AIR_FALSE;
+ /* ---- BEGIN non-NrrdIO */
+ nio->declineStdioOnTTY = nrrdDefaultDeclineStdioOnTTY;
+ /* ---- END non-NrrdIO */
nio->zlibLevel = -1;
nio->zlibStrategy = nrrdZlibStrategyDefault;
nio->bzip2BlockSize = -1;
Modified: teem/trunk/src/nrrd/nrrd.h
===================================================================
--- teem/trunk/src/nrrd/nrrd.h 2024-09-19 20:36:33 UTC (rev 7239)
+++ teem/trunk/src/nrrd/nrrd.h 2024-09-19 20:41:54 UTC (rev 7240)
@@ -427,15 +427,29 @@
nrrd format. Probably used in conjunction with
skipData. (currently for "unu data")
ON WRITE: no semantics */
- zlibLevel, /* zlib compression level (0-9, -1 for
- default[6], 0 for no compression). */
- zlibStrategy, /* zlib compression strategy, can be one
- of the nrrdZlibStrategy enums, default is
- nrrdZlibStrategyDefault. */
- bzip2BlockSize, /* block size used for compression,
- roughly equivalent to better but slower
- (1-9, -1 for default[9]). */
/* ---- BEGIN non-NrrdIO */
+ declineStdioOnTTY, /* ON READ and ON WRITE: If nrrdLoad is about to read from
+ filename "-" (via nrrdRead), or nrrdSave is about to write to
+ "-" (via nrrdWrite), regardless of file format (which isn't
+ known on read, though may be known on write): if this is
+ non-zero, decline to nrrdRead from stdin or nrrdWrite to stdout
+ IF stdin/stdout seems to be a terminal (as per isatty()). On
+ read, this avoids cryptic stalls as something tries to read
+ from the terminal (where a human is unlikely to be typing the
+ file contents), and on write, this avoids clobbering the
+ terminal with screens of non-printing characters. Using
+ filename "-=" is a sneaky way to name stdin/stdout while
+ over-riding this declination and force that IO to happen. */
+ /* ---- END non-NrrdIO */
+ zlibLevel, /* zlib compression level (0-9, -1 for
+ default[6], 0 for no compression). */
+ zlibStrategy, /* zlib compression strategy, can be one
+ of the nrrdZlibStrategy enums, default is
+ nrrdZlibStrategyDefault. */
+ bzip2BlockSize, /* block size used for compression,
+ roughly equivalent to better but slower
+ (1-9, -1 for default[9]). */
+ /* ---- BEGIN non-NrrdIO */
/* seems odd to have contents of NrrdIoState differ between full Teem
and NrrdIO, but these fields can't be meaningfully set or read if
the nrrdFormatPNGsRGBIntent is not available */
@@ -707,6 +721,7 @@
NRRD_EXPORT double nrrdDefaultResamplePadValue;
NRRD_EXPORT int nrrdDefaultResampleNonExistent;
NRRD_EXPORT double nrrdDefaultKernelParm0;
+NRRD_EXPORT int nrrdDefaultDeclineStdioOnTTY;
/* ---- END non-NrrdIO */
NRRD_EXPORT int nrrdDefaultCenter;
NRRD_EXPORT double nrrdDefaultSpacing;
Modified: teem/trunk/src/nrrd/read.c
===================================================================
--- teem/trunk/src/nrrd/read.c 2024-09-19 20:36:33 UTC (rev 7239)
+++ teem/trunk/src/nrrd/read.c 2024-09-19 20:41:54 UTC (rev 7240)
@@ -26,6 +26,10 @@
# include <bzlib.h>
#endif
+/* ---- BEGIN non-NrrdIO */
+#include <unistd.h> /* for isatty() and STDIN_FILENO */
+/* ---- END non-NrrdIO */
+
/* (not apparently used) const char *const _nrrdRelativePathFlag = "./"; */
const char *const _nrrdFieldSep = " \t";
static const char *const _nrrdLineSep = "\r\n";
@@ -639,6 +643,19 @@
airMopError(mop);
return 2;
}
+ /* ---- BEGIN non-NrrdIO */
+ if (nio->declineStdioOnTTY /* if we're cautious about reading from stdin */
+ && stdin == file /* and we're reading from stdin */
+ && strcmp("-=", filename) /* and filename is NOT -= (which over-rides caution) */
+ && isatty(STDIN_FILENO) /* and stdin is a tty */) {
+ biffAddf(NRRD,
+ "%s: declining to try reading Nrrd from terminal (tty) stdin "
+ "(implied by filename \"%s\"; over-ride with \"-=\")",
+ me, filename);
+ airMopError(mop);
+ return 1;
+ }
+ /* ---- END non-NrrdIO */
airMopAdd(mop, file, (airMopper)airFclose, airMopOnError);
/* non-error exiting is handled below */
Modified: teem/trunk/src/nrrd/write.c
===================================================================
--- teem/trunk/src/nrrd/write.c 2024-09-19 20:36:33 UTC (rev 7239)
+++ teem/trunk/src/nrrd/write.c 2024-09-19 20:41:54 UTC (rev 7240)
@@ -22,10 +22,9 @@
#include "nrrd.h"
#include "privateNrrd.h"
-/*
- #include <sys/types.h>
- #include <unistd.h>
-*/
+/* ---- BEGIN non-NrrdIO */
+#include <unistd.h> /* for isatty() and STDIN_FILENO */
+/* ---- END non-NrrdIO */
int /* Biff: 1 */
nrrdIoStateSet(NrrdIoState *nio, int parm, int value) {
@@ -1018,6 +1017,19 @@
airMopError(mop);
return 1;
}
+ /* ---- BEGIN non-NrrdIO */
+ if (nio->declineStdioOnTTY /* if we're cautious about writing to stdout */
+ && stdout == file /* and we're writing to stdout */
+ && strcmp("-=", filename) /* and filename is NOT -= (which over-rides caution) */
+ && isatty(STDOUT_FILENO) /* and stdout is a tty */) {
+ biffAddf(NRRD,
+ "%s: declining to try writing file to terminal (tty) stdout "
+ "(implied by filename \"%s\"; over-ride with \"-=\")",
+ me, filename);
+ airMopError(mop);
+ return 1;
+ }
+ /* ---- END non-NrrdIO */
airMopAdd(mop, file, (airMopper)airFclose, airMopAlways);
if (nrrdWrite(file, nrrd, nio)) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-09-19 20:36:34
|
Revision: 7239
http://sourceforge.net/p/teem/code/7239
Author: kindlmann
Date: 2024-09-19 20:36:33 +0000 (Thu, 19 Sep 2024)
Log Message:
-----------
now clang-format'ed
Modified Paths:
--------------
teem/trunk/src/nrrd/test/io.c
Modified: teem/trunk/src/nrrd/test/io.c
===================================================================
--- teem/trunk/src/nrrd/test/io.c 2024-09-19 20:03:20 UTC (rev 7238)
+++ teem/trunk/src/nrrd/test/io.c 2024-09-19 20:36:33 UTC (rev 7239)
@@ -19,7 +19,6 @@
Fifth Floor, Boston, MA 02110-1301 USA
*/
-
#include "../nrrd.h"
void
@@ -45,9 +44,8 @@
io = nrrdIoStateNew();
nrrdStateVerboseIO = 10;
- if (nrrdLoad(nrrd=nrrdNew(), argv[1], NULL)) {
- fprintf(stderr, "%s: trouble loading \"%s\":\n%s",
- me, argv[1], err = biffGet(NRRD));
+ if (nrrdLoad(nrrd = nrrdNew(), argv[1], NULL)) {
+ fprintf(stderr, "%s: trouble loading \"%s\":\n%s", me, argv[1], err = biffGet(NRRD));
free(err);
exit(1);
}
@@ -55,13 +53,13 @@
domNum = nrrdDomainAxesGet(nrrd, domAxi);
rngNum = nrrdRangeAxesGet(nrrd, rngAxi);
fprintf(stderr, "%s domain axes (%u):", me, domNum);
- for (axi=0; axi<domNum; axi++) {
+ for (axi = 0; axi < domNum; axi++) {
fprintf(stderr, " %u(%s)", domAxi[axi],
airEnumStr(nrrdKind, nrrd->axis[domAxi[axi]].kind));
}
fprintf(stderr, "\n");
fprintf(stderr, "%s range naxes (%u):", me, rngNum);
- for (axi=0; axi<rngNum; axi++) {
+ for (axi = 0; axi < rngNum; axi++) {
fprintf(stderr, " %u(%s)", rngAxi[axi],
airEnumStr(nrrdKind, nrrd->axis[rngAxi[axi]].kind));
}
@@ -81,59 +79,46 @@
val[2][0] = 5.11;
val[2][1] = 6.11;
val[2][2] = 7.11;
- fprintf(stderr, "%s: val[0,1,2] = %lu %lu %lu\n", me,
- (unsigned long)(val[0]),
- (unsigned long)(val[1]),
- (unsigned long)(val[2]));
+ fprintf(stderr, "%s: val[0,1,2] = %lu %lu %lu\n", me, (unsigned long)(val[0]),
+ (unsigned long)(val[1]), (unsigned long)(val[2]));
nrrdAxisInfoSet_va(nrrd, nrrdAxisInfoSpaceDirection, val[0], val[1], val[2]);
fprintf(stderr, "2 --------------------------------------\n");
nrrdAxisInfoGet_nva(nrrd, nrrdAxisInfoSpaceDirection, val);
- fprintf(stderr, "%s: val[0] = %g %g %g\n", me,
- val[0][0], val[0][1], val[0][2]);
- fprintf(stderr, "%s: val[1] = %g %g %g\n", me,
- val[1][0], val[1][1], val[1][2]);
- fprintf(stderr, "%s: val[2] = %g %g %g\n", me,
- val[2][0], val[2][1], val[2][2]);
+ fprintf(stderr, "%s: val[0] = %g %g %g\n", me, val[0][0], val[0][1], val[0][2]);
+ fprintf(stderr, "%s: val[1] = %g %g %g\n", me, val[1][0], val[1][1], val[1][2]);
+ fprintf(stderr, "%s: val[2] = %g %g %g\n", me, val[2][0], val[2][1], val[2][2]);
fprintf(stderr, "3 --------------------------------------\n");
nrrdAxisInfoGet_va(nrrd, nrrdAxisInfoSpaceDirection, val[0], val[1], val[2]);
fprintf(stderr, "4 --------------------------------------\n");
- fprintf(stderr, "%s: val[0] = %g %g %g\n", me,
- val[0][0], val[0][1], val[0][2]);
- fprintf(stderr, "%s: val[1] = %g %g %g\n", me,
- val[1][0], val[1][1], val[1][2]);
- fprintf(stderr, "%s: val[2] = %g %g %g\n", me,
- val[2][0], val[2][1], val[2][2]);
+ fprintf(stderr, "%s: val[0] = %g %g %g\n", me, val[0][0], val[0][1], val[0][2]);
+ fprintf(stderr, "%s: val[1] = %g %g %g\n", me, val[1][0], val[1][1], val[1][2]);
+ fprintf(stderr, "%s: val[2] = %g %g %g\n", me, val[2][0], val[2][1], val[2][2]);
fprintf(stderr, "5 --------------------------------------\n");
if (nrrdSave("out.nrrd", nrrd, io)) {
- fprintf(stderr, "%s: trouble saving \"%s\":\n%s",
- me, argv[1], err = biffGet(NRRD));
+ fprintf(stderr, "%s: trouble saving \"%s\":\n%s", me, argv[1], err = biffGet(NRRD));
free(err);
exit(1);
}
nrrdIoStateInit(io);
if (nrrdSave(argv[2], nrrd, io)) {
- fprintf(stderr, "%s: trouble saving \"%s\":\n%s",
- me, argv[1], err = biffGet(NRRD));
+ fprintf(stderr, "%s: trouble saving \"%s\":\n%s", me, argv[1], err = biffGet(NRRD));
free(err);
exit(1);
}
nrrdIoStateInit(io);
if (nrrdSave(argv[2], nrrd, io)) {
- fprintf(stderr, "%s: trouble saving \"%s\":\n%s",
- me, argv[1], err = biffGet(NRRD));
+ fprintf(stderr, "%s: trouble saving \"%s\":\n%s", me, argv[1], err = biffGet(NRRD));
free(err);
exit(1);
}
nrrdIoStateInit(io);
if (nrrdSave(argv[2], nrrd, io)) {
- fprintf(stderr, "%s: trouble saving \"%s\":\n%s",
- me, argv[1], err = biffGet(NRRD));
+ fprintf(stderr, "%s: trouble saving \"%s\":\n%s", me, argv[1], err = biffGet(NRRD));
free(err);
exit(1);
}
-
nrrdIoStateNix(io);
nrrdNuke(nrrd);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-09-19 20:03:21
|
Revision: 7238
http://sourceforge.net/p/teem/code/7238
Author: kindlmann
Date: 2024-09-19 20:03:20 +0000 (Thu, 19 Sep 2024)
Log Message:
-----------
added ability to recognize -= as the same stdin/stdout that - is recognized as
Modified Paths:
--------------
teem/trunk/src/air/miscAir.c
Modified: teem/trunk/src/air/miscAir.c
===================================================================
--- teem/trunk/src/air/miscAir.c 2024-09-06 08:11:53 UTC (rev 7237)
+++ teem/trunk/src/air/miscAir.c 2024-09-19 20:03:20 UTC (rev 7238)
@@ -104,10 +104,14 @@
/*
******** airFopen()
**
-** encapsulates that idea that "-" is either standard in or stardard
-** out, and does McRosopht stuff required to make piping work
+** encapsulates that idea that "-" OR "-=" is either standard in or standard
+** out, and does McRosopht stuff required to make piping work. Handling "-="
+** is a convenience for implementing NrrdIoState->declineStdioOnTTY, with
+** the semantics (not handled here) that "-=" means "read/write from stdin/
+** stdout, even when it IS a terminal". But this is currently only supported
+** in full Teem, not the minimal NrrdIO library.
**
-** Does not error checking. If fopen fails, then C' errno and strerror are
+** Does no error checking. If fopen fails, then C' errno and strerror are
** left untouched for the caller to access.
*/
FILE *
@@ -114,7 +118,11 @@
airFopen(const char *name, FILE *std, const char *mode) {
FILE *ret;
- if (!strcmp(name, "-")) {
+ if (!strcmp(name, "-")
+ /* ---- BEGIN non-NrrdIO */
+ || !strcmp(name, "-=")
+ /* ---- END non-NrrdIO */
+ ) {
ret = std;
#ifdef _WIN32
if (strchr(mode, 'b')) {
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <kin...@us...> - 2024-09-06 08:11:55
|
Revision: 7237
http://sourceforge.net/p/teem/code/7237
Author: kindlmann
Date: 2024-09-06 08:11:53 +0000 (Fri, 06 Sep 2024)
Log Message:
-----------
source sync
Modified Paths:
--------------
teem/trunk/python/cffi/teem.py
Modified: teem/trunk/python/cffi/teem.py
===================================================================
--- teem/trunk/python/cffi/teem.py 2024-09-06 08:00:29 UTC (rev 7236)
+++ teem/trunk/python/cffi/teem.py 2024-09-06 08:11:53 UTC (rev 7237)
@@ -293,6 +293,14 @@
'mossSamplerSample': (_equals_one, 0, b'moss', 'moss/sampler.c:195'),
'mossLinearTransform': (_equals_one, 0, b'moss', 'moss/xform.c:140'),
'mossFourPointTransform': (_equals_one, 0, b'moss', 'moss/xform.c:219'),
+ 'alanUpdate': (_equals_one, 0, b'alan', 'alan/coreAlan.c:60'),
+ 'alanInit': (_equals_one, 0, b'alan', 'alan/coreAlan.c:99'),
+ 'alanRun': (_equals_one, 0, b'alan', 'alan/coreAlan.c:453'),
+ 'alanDimensionSet': (_equals_one, 0, b'alan', 'alan/methodsAlan.c:104'),
+ 'alan2DSizeSet': (_equals_one, 0, b'alan', 'alan/methodsAlan.c:119'),
+ 'alan3DSizeSet': (_equals_one, 0, b'alan', 'alan/methodsAlan.c:139'),
+ 'alanTensorSet': (_equals_one, 0, b'alan', 'alan/methodsAlan.c:161'),
+ 'alanParmSet': (_equals_one, 0, b'alan', 'alan/methodsAlan.c:208'),
'gageContextCopy': (_equals_null, 0, b'gage', 'gage/ctx.c:88'),
'gageKernelSet': (_equals_one, 0, b'gage', 'gage/ctx.c:199'),
'gagePerVolumeAttach': (_equals_one, 0, b'gage', 'gage/ctx.c:398'),
@@ -339,6 +347,31 @@
'gageOptimSigErrorPlotSliding': (_equals_one, 0, b'gage', 'gage/optimsig.c:1253'),
'dyeConvert': (_equals_one, 0, b'dye', 'dye/convertDye.c:351'),
'dyeColorParse': (_equals_one, 0, b'dye', 'dye/methodsDye.c:185'),
+ 'baneClipNew': (_equals_null, 0, b'bane', 'bane/clip.c:102'),
+ 'baneClipAnswer': (_equals_one, 0, b'bane', 'bane/clip.c:152'),
+ 'baneClipCopy': (_equals_null, 0, b'bane', 'bane/clip.c:167'),
+ 'baneFindInclusion': (_equals_one, 0, b'bane', 'bane/hvol.c:87'),
+ 'baneMakeHVol': (_equals_one, 0, b'bane', 'bane/hvol.c:248'),
+ 'baneGKMSHVol': (_equals_null, 0, b'bane', 'bane/hvol.c:447'),
+ 'baneIncNew': (_equals_null, 0, b'bane', 'bane/inc.c:251'),
+ 'baneIncAnswer': (_equals_one, 0, b'bane', 'bane/inc.c:360'),
+ 'baneIncCopy': (_equals_null, 0, b'bane', 'bane/inc.c:375'),
+ 'baneMeasrNew': (_equals_null, 0, b'bane', 'bane/measr.c:33'),
+ 'baneMeasrCopy': (_equals_null, 0, b'bane', 'bane/measr.c:149'),
+ 'baneRangeNew': (_equals_null, 0, b'bane', 'bane/rangeBane.c:89'),
+ 'baneRangeCopy': (_equals_null, 0, b'bane', 'bane/rangeBane.c:130'),
+ 'baneRangeAnswer': (_equals_one, 0, b'bane', 'bane/rangeBane.c:144'),
+ 'baneRawScatterplots': (_equals_one, 0, b'bane', 'bane/scat.c:26'),
+ 'baneOpacInfo': (_equals_one, 0, b'bane', 'bane/trnsf.c:29'),
+ 'bane1DOpacInfoFrom2D': (_equals_one, 0, b'bane', 'bane/trnsf.c:144'),
+ 'baneSigmaCalc': (_equals_one, 0, b'bane', 'bane/trnsf.c:222'),
+ 'banePosCalc': (_equals_one, 0, b'bane', 'bane/trnsf.c:253'),
+ 'baneOpacCalc': (_equals_one, 0, b'bane', 'bane/trnsf.c:403'),
+ 'baneInputCheck': (_equals_one, 0, b'bane', 'bane/valid.c:26'),
+ 'baneHVolCheck': (_equals_one, 0, b'bane', 'bane/valid.c:64'),
+ 'baneInfoCheck': (_equals_one, 0, b'bane', 'bane/valid.c:106'),
+ 'banePosCheck': (_equals_one, 0, b'bane', 'bane/valid.c:144'),
+ 'baneBcptsCheck': (_equals_one, 0, b'bane', 'bane/valid.c:179'),
'limnCameraUpdate': (_equals_one, 0, b'limn', 'limn/cam.c:33'),
'limnCameraAspectSet': (_equals_one, 0, b'limn', 'limn/cam.c:130'),
'limnCameraPathMake': (_equals_one, 0, b'limn', 'limn/cam.c:189'),
@@ -582,6 +615,21 @@
'pullTraceMultiPlotAdd': (_equals_one, 0, b'pull', 'pull/trace.c:704'),
'pullTraceMultiWrite': (_equals_one, 0, b'pull', 'pull/trace.c:1014'),
'pullTraceMultiRead': (_equals_one, 0, b'pull', 'pull/trace.c:1119'),
+ 'coilStart': (_equals_one, 0, b'coil', 'coil/coreCoil.c:287'),
+ 'coilIterate': (_equals_one, 0, b'coil', 'coil/coreCoil.c:362'),
+ 'coilFinish': (_equals_one, 0, b'coil', 'coil/coreCoil.c:407'),
+ 'coilVolumeCheck': (_equals_one, 0, b'coil', 'coil/methodsCoil.c:25'),
+ 'coilContextAllSet': (_equals_one, 0, b'coil', 'coil/methodsCoil.c:69'),
+ 'coilOutputGet': (_equals_one, 0, b'coil', 'coil/methodsCoil.c:200'),
+ 'pushOutputGet': (_equals_one, 0, b'push', 'push/action.c:71'),
+ 'pushBinProcess': (_equals_one, 0, b'push', 'push/action.c:161'),
+ 'pushBinPointAdd': (_equals_one, 0, b'push', 'push/binning.c:180'),
+ 'pushRebin': (_equals_one, 0, b'push', 'push/binning.c:197'),
+ 'pushStart': (_equals_one, 0, b'push', 'push/corePush.c:183'),
+ 'pushIterate': (_equals_one, 0, b'push', 'push/corePush.c:233'),
+ 'pushRun': (_equals_one, 0, b'push', 'push/corePush.c:306'),
+ 'pushFinish': (_equals_one, 0, b'push', 'push/corePush.c:396'),
+ 'pushEnergySpecParse': (_equals_one, 0, b'push', 'push/forces.c:304'),
'miteSample': (_math.isnan, 0, b'mite', 'mite/ray.c:151'),
'miteRenderBegin': (_equals_one, 0, b'mite', 'mite/renderMite.c:63'),
'miteShadeSpecParse': (_equals_one, 0, b'mite', 'mite/shade.c:69'),
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|