root/cdat/trunk/cdat/Modules/Cdunifmodule.c

Revision 845, 55.3 kB (checked in by drach, 9 years ago)

- separated PCMDI extensions and modules from the Python

distribution tree

- added NGI extensions to CDMS: LDAP, caching, progress gui

Line 
1 /*
2  * Objects representing cdunif files and variables.
3  *
4  * Adapted from code Written by Konrad Hinsen
5  * (last revision: 1998-3-14)
6  *
7  * Note: Compile with -DPCMDI_NUMERICS if the PCMDI
8  * Numerics module is used.
9  */
10
11
12 #include "Python.h"
13 #include "Numeric/arrayobject.h"
14 #include "netcdf.h"
15
16 #define _CDUNIF_MODULE
17 #include "Cdunifmodule.h"
18
19
20 staticforward int Cdunif_file_init();
21 staticforward PyCdunifVariableObject *Cdunif_variable_new();
22 staticforward PyObject *PyCdunifVariableObject_subscript();
23 staticforward PyObject *PyCdunifVariableObject_slice();
24 staticforward int PyCdunifVariableObject_ass_subscript();
25 staticforward int PyCdunifVariableObject_ass_slice();
26
27 /* Error object and error messages for netcdf-specific errors */
28
29 static PyObject *CdunifError;
30
31 static char *netcdf_errors[] = {
32   "No Error",
33   "Not a netcdf id",
34   "Too many netcdfs open",
35   "netcdf file exists && NC_NOCLOBBER",
36   "Invalid Argument",
37   "Write to read only",
38   "Operation not allowed in data mode",
39   "Operation not allowed in define mode",
40   "Coordinates out of Domain",
41   "MAX_NC_DIMS exceeded",
42   "String match to name in use",
43   "Attribute not found",
44   "MAX_NC_ATTRS exceeded",
45   "Not a netcdf data type",
46   "Invalid dimension id",
47   "NC_UNLIMITED in the wrong index",
48   "MAX_NC_VARS exceeded",
49   "Variable not found",
50   "Action prohibited on NC_GLOBAL varid",
51   "Not a netcdf file",
52   "In Fortran, string too short",
53   "MAX_NC_NAME exceeded",
54   "NC_UNLIMITED size already in use", /* 22 */
55   "", "", "", "", "", "", "", "", "",
56   "XDR error" /* 32 */
57 };
58
59 /* Set error string */
60 static void
61 Cdunif_seterror()
62 {
63   if (ncerr != 0) {
64     char *error = "Unknown error";
65     if (ncerr > 0 && ncerr <= 32)
66       error = netcdf_errors[ncerr];
67     PyErr_SetString(CdunifError, error);
68   }
69 }
70
71                                              /* cdunif/netCDF wrappers */
72
73 static void cdmapdatatype_cu(CuType cutype,nc_type *datatype){
74         switch (cutype){
75         case CuByte:
76                 *datatype = NC_BYTE;
77                 break;
78         case CuChar:
79                 *datatype = NC_CHAR;
80                 break;
81         case CuShort:
82                 *datatype = NC_SHORT;
83                 break;
84         case CuInt:
85         case CuLong:
86                 *datatype = NC_LONG;
87                 break;
88         case CuFloat:
89                 *datatype = NC_FLOAT;
90                 break;
91         case CuDouble:
92                 *datatype = NC_DOUBLE;
93                 break;
94         default:
95                 *datatype = 0;
96                 break;
97         }
98         return;
99 }
100
101 static int cdattget(PyCdunifFileObject *file, int varid, const char* name, void* value){
102         if (file->filetype==CuNetcdf)
103                 return ncattget(file->id,varid,name,value);
104         else
105                 return cuattget(file->id,varid,name,value);
106 }
107 static int cdattinq(PyCdunifFileObject *file, int varid, const char* name, nc_type* datatype, int* len){
108         CuType cutype;
109         int err;
110
111         if (file->filetype==CuNetcdf)
112                 return ncattinq(file->id,varid,name,datatype,len);
113         else{
114                 err = cuattinq(file->id,varid,name,&cutype,len);
115                 if (datatype != NULL)
116                         cdmapdatatype_cu(cutype,datatype);
117                 return err;
118         }
119 }
120 static int cdattname(PyCdunifFileObject *file, int varid, int attnum, char* name){
121         if (file->filetype==CuNetcdf)
122                 return ncattname(file->id,varid,attnum,name);
123         else
124                 return cuattname(file->id,varid,attnum,name);
125 }
126 static int cdclose(PyCdunifFileObject *file){
127         if (file->filetype==CuNetcdf)
128                 return ncclose(file->id);
129         else
130                 return cuclose(file->id);
131 }
132 static int cddimget(PyCdunifFileObject *file, int dimid, void *values){
133         if (file->filetype==CuNetcdf){
134                 char dimname[MAX_NC_NAME+1];
135                 float *fp;
136                 int cdfid;
137                 int dimids[MAX_VAR_DIMS];
138                 int dimvarid;
139                 long dlenbytes;
140                 int found;
141                 int ndims;
142                 int saveopts;
143                 int i;
144                 long length;
145                 long start;
146                 char varname[MAX_NC_NAME+1];
147                 nc_type nctype;
148                 int natts;
149                
150                 cdfid = file->id;
151                 if(ncdiminq(cdfid, dimid, dimname, &length)==-1){
152                         return -1;
153                 }
154                
155                                              /* Inquire a variable with */
156                                              /* - the same name as dimname, */
157                                              /* - a single dimension, and */
158                                              /* - a (single) dimension id which equals dimid */
159                 saveopts = ncopts;
160                 ncopts = 0;
161                 if((dimvarid = ncvarid(cdfid, dimname)) != -1){
162                         ncopts = saveopts;
163                         if(ncvarinq(cdfid, dimvarid, varname, &nctype, &ndims, dimids, &natts)==-1){
164                                 return -1;
165                         }
166                         found = (ndims == 1 && dimids[0]==dimid);
167                 }
168                 else
169                         found = 0;
170                 ncopts = saveopts;
171                
172                                              /* If the dimension variable was found, read it */
173                 if(found){
174                         dlenbytes = length * nctypelen(nctype);
175                                              /* Read the dimension */
176                         start = 0;
177                         if(values && ncvarget(cdfid, dimvarid, &start, &length, values)==-1)
178                                 return -1;
179                 }
180                 else{
181                                              /* Otherwise assign the default dimension */
182                         if(values){
183                                 for(i=0, fp=(float*)values; i<length; i++){
184                                         *fp++ = (float)i;
185                                 }
186                         }
187                 }
188                 return CU_SUCCESS;
189                
190         }
191         else
192                 return cudimget(file->id,dimid,values);
193 }
194 static int cddimid(PyCdunifFileObject *file, const char* name){
195         if (file->filetype==CuNetcdf)
196                 return ncdimid(file->id,name);
197         else
198                 return cudimid(file->id,CU_GLOBAL,name);
199 }
200 /* Inquire a dimension. varname is the name of the parent variable, if the dimension is local, else has value "" */
201 static int cddiminq(PyCdunifFileObject *file, int dimid, char* dimname, char *dimunits, nc_type *nctype, CuDimType *dimtype, char *varname, long* length){
202         int err;
203         CuType cutype;
204         int varid;
205         char dname[MAX_NC_NAME+1];
206         int cdfid;
207         int dimvarid;                        /* netCDF ID of variable associated with this dimension (if any) */
208         int found;                           /* True iff a dimension variable was found. */
209         int ndims;
210         int dimids[MAX_VAR_DIMS];
211         int saveopts;
212         long len;
213         nc_type ncunitstype;
214         int natts;
215         char vname[MAX_NC_NAME+1];
216         int attlen;
217        
218         if (file->filetype==CuNetcdf) {
219                 cdfid = file->id;
220                 if(ncdiminq(cdfid, dimid, dname, &len)==-1){
221                         return -1;
222                 }
223                 if(dimname) strncpy(dimname,dname,CU_MAX_NAME);
224                 if(length) *length = len;
225                
226                                              /* netCDF dimensions are always global */
227                 if(dimtype) *dimtype = CuGlobalDim;
228                 if(varname) strcpy(varname,"");
229                
230                                              /* Inquire a variable with */
231                                              /* - the same name as dimname, */
232                                              /* - a single dimension, and */
233                                              /* - a dimension name which equals the variable name. */
234                 saveopts = ncopts;
235                 ncopts = 0;
236                 if((dimvarid = ncvarid(cdfid, dname)) != -1){
237                         ncopts = saveopts;
238                         if(ncvarinq(cdfid, dimvarid, vname, nctype, &ndims, dimids, &natts)==-1){
239                                 return -1;
240                         }
241                         found = (ndims == 1 && dimids[0]==dimid);
242                 }
243                 else
244                         found = 0;
245                 ncopts = saveopts;
246                
247                                              /* If dimension variable was found, */
248                                              /* inquire the units attribute (if any) */
249                 if(found){
250                         saveopts = ncopts;
251                         ncopts = 0;
252                         if(ncattinq(cdfid, dimvarid, "units", &ncunitstype, &attlen) != -1 &&
253                            ncunitstype == NC_CHAR){
254                                 ncopts = saveopts;
255                                 if(dimunits && ncattget(cdfid, dimvarid, "units",dimunits)==-1)
256                                         return -1;
257                         }
258                                              /* Dimension variable was found, but no character units string */
259                         else{
260                                 if(dimunits) strcpy(dimunits,"");
261                         }
262                         ncopts = saveopts;
263                 }
264                 else{
265                                              /* The dimension variable was not found: */
266                                              /* return default units and datatype */
267                         if(dimunits) strcpy(dimunits,"");
268                         if(nctype) *nctype = NC_FLOAT;
269                 }
270                
271                 return CU_SUCCESS;
272         }
273         else {
274                 err = 0;
275                 if(cudiminq(file->id,dimid,dimname,dimunits,&cutype,dimtype,&varid,length)==-1)
276                         return -1;
277                 if (nctype)
278                         cdmapdatatype_cu(cutype,nctype);
279                 if (varname){
280                         if (varid==CU_GLOBAL)
281                                 strcpy(varname,"");
282                         else
283                                 err = cuvarinq(file->id,varid,varname,NULL,NULL,NULL,NULL);
284                 }
285                 return err;
286         }
287 }
288 static int cdendef(PyCdunifFileObject *file){
289         if (file->filetype==CuNetcdf)
290                 return ncendef(file->id);
291         else
292                 return 0;
293 }
294 static int cdgeterr(PyCdunifFileObject *file){
295         if (file->filetype==CuNetcdf)
296                 return ncerr;
297         else
298                 return cugeterr();
299 }
300 static int cdinquire(PyCdunifFileObject *file, int* ngdims, int* nvars, int* natts, int* recdim){
301         if (file->filetype==CuNetcdf)
302                 return ncinquire(file->id,ngdims,nvars,natts,recdim);
303         else
304                 return cuinquire(file->id,ngdims,nvars,natts,recdim);
305 }
306 static int cdopen(const char* controlpath, int mode, CuFileType *filetype){
307                                              /* Check the filetype */
308         *filetype=CuGetFileType(controlpath);
309         if (*filetype==CuNetcdf)
310                 return ncopen(controlpath,mode);
311         else{
312                 if (mode==NC_WRITE){
313                         ncerr = 5;           /* Write to read-only file */
314                         Cdunif_seterror();
315                         return -1;
316                 }
317                 return cuopenread(controlpath,NULL);
318         }
319 }
320 static int cdredef(PyCdunifFileObject *file){
321         if (file->filetype==CuNetcdf)
322                 return ncredef(file->id);
323         else
324                 return 0;
325 }
326 static int cdsync(PyCdunifFileObject *file){
327         if (file->filetype==CuNetcdf)
328                 return ncsync(file->id);
329         else
330                 return 0;
331 }
332 static int cdvarget(PyCdunifFileObject *file, int varid, const long start[], const long count[], void* value){
333         if (file->filetype==CuNetcdf)
334                 return ncvarget(file->id,varid,start,count,value);
335         else
336                 return cuvarget(file->id,varid,start,count,value);
337 }
338                                              /* Use for rank 0 variables only. */
339 static int cdvarget1(PyCdunifFileObject *file, int varid, const long mindex[], void *value){
340         long one;
341         if (file->filetype==CuNetcdf)
342                 return ncvarget1(file->id, varid, mindex, value);
343         else{
344                 one = 1;
345                 return cuvarget(file->id,varid,mindex,&one,value);
346         }
347 }
348 static int cdvargets(PyCdunifFileObject *file, int varid, const long start[], const long count[], const long stride[], void *values){
349         if (file->filetype==CuNetcdf)
350                 return ncvargetg(file->id,varid,start,count,stride,NULL,values);
351         else
352                 return cuvargets(file->id,varid,NULL,start,count,stride,0,values);
353 }
354 static int cdvarinq(PyCdunifFileObject *file, int varid, char* name, nc_type* datatype, int* ndims, int dimids[], int* natts){
355         CuType cutype;
356         int err;
357        
358         if (file->filetype==CuNetcdf)
359                 return ncvarinq(file->id,varid,name,datatype,ndims,dimids,natts);
360         else{
361                 err = cuvarinq(file->id,varid,name,&cutype,ndims,dimids,natts);
362                 if (datatype != NULL)
363                         cdmapdatatype_cu(cutype,datatype);
364                 return err;
365         }
366 }
367
368 /*
369  * Python equivalents to netCDF data types
370  *
371  * Attention: the following specification may not be fully portable.
372  * The comments indicate the correct netCDF specification. The assignment
373  * of Python types assumes that 'short' is 16-bit and 'int' is 32-bit.
374  */
375
376 int PyCdunif_data_types[] = {-1,  /* not used */
377                     PyArray_SBYTE,  /* signed 8-bit int */
378                     PyArray_CHAR,   /* 8-bit character */
379                     PyArray_SHORT,  /* 16-bit signed int */
380                     PyArray_INT,    /* 32-bit signed int */
381                     PyArray_FLOAT,  /* 32-bit IEEE float */
382                     PyArray_DOUBLE  /* 64-bit IEEE float */
383 };
384
385 static char *dimension_types[] = {"error", "global", "local"};
386
387 /* Utility functions */
388
389 static void
390 define_mode(file, define_flag)
391      PyCdunifFileObject *file;
392      int define_flag;
393 {
394   if (file->define != define_flag) {
395     if (file->define)
396       cdendef(file);
397     else
398       cdredef(file);
399     file->define = define_flag;
400   }
401 }
402
403 static char
404 typecode(type)
405      int type;
406 {
407   char t;
408   switch(type) {
409   case PyArray_CHAR:
410     t = 'c';
411     break;
412   case PyArray_UBYTE:
413     t = 'b';
414     break;
415   case PyArray_SBYTE:
416     t = '1';
417     break;
418   case PyArray_SHORT:
419     t = 's';
420     break;
421   case PyArray_INT:
422     t = 'i';
423     break;
424   case PyArray_LONG:
425     t = 'l';
426     break;
427   case PyArray_FLOAT:
428     t = 'f';
429     break;
430   case PyArray_DOUBLE:
431     t = 'd';
432     break;
433   default: t = ' ';
434   }
435   return t;
436 }
437
438 static int
439 netcdf_type_from_code(code)
440      char code;
441 {
442   int type;
443   switch(code) {
444   case 'c':
445     type = NC_CHAR;
446     break;
447   case 'b':
448   case '1':
449     type = NC_BYTE;
450     break;
451   case 's':
452     type = NC_SHORT;
453     break;
454   case 'i':
455   case 'l':
456     type = NC_LONG;
457     break;
458   case 'f':
459     type = NC_FLOAT;
460     break;
461   case 'd':
462     type = NC_DOUBLE;
463     break;
464   default:
465     type = 0;
466   }
467   return type;
468 }
469
470
471 static void
472 collect_attributes(file, varid, attributes, nattrs)
473      PyCdunifFileObject *file;
474      int varid;
475      PyObject *attributes;
476      int nattrs;
477 {
478   char name[MAX_NC_NAME];
479   nc_type type;
480   int length;
481   int py_type;
482   int i;
483   int fileid;
484
485   fileid = file->id;
486   for (i = 0; i < nattrs; i++) {
487     cdattname(file, varid, i, name);
488     cdattinq(file, varid, name, &type, &length);
489     py_type = PyCdunif_data_types[type];
490     if (py_type == PyArray_CHAR) {
491       char *s = (char *)malloc((length+1)*sizeof(char));
492       if (s != NULL) {
493         PyObject *string;
494         cdattget(file, varid, name, s);
495         s[length] = '\0';
496         string = PyString_FromString(s);
497         if (string != NULL) {
498           PyDict_SetItemString(attributes, name, string);
499           Py_DECREF(string);
500         }
501       }
502     }
503     else {
504       PyObject *array = PyArray_FromDims(1, &length, py_type);
505       if (array != NULL) {
506         cdattget(file, varid, name, ((PyArrayObject *)array)->data);
507         array = PyArray_Return((PyArrayObject *)array);
508         if (array != NULL) {
509 #ifdef PCMDI_NUMERICS
510           generate_pcmdi_dims(&array,"AttributeArray");
511 #endif         
512           PyDict_SetItemString(attributes, name, array);
513           Py_DECREF(array);
514         }
515       }
516     }
517   }
518 }
519
520 static int
521 set_attribute(fileid, varid, attributes, name, value)
522      int fileid;
523      int varid;
524      PyObject *attributes;
525      char *name;
526      PyObject *value;
527 {
528   if (PyString_Check(value)) {
529     if (ncattput(fileid, varid, name, NC_CHAR, PyString_Size(value)+1,
530                  PyString_AsString(value)) == -1) {
531       Cdunif_seterror();
532       return -1;
533     }
534     PyDict_SetItemString(attributes, name, value);
535     return 0;
536   }
537   else {
538     PyArrayObject *array =
539      (PyArrayObject *)PyArray_ContiguousFromObject(value, PyArray_NOTYPE, 0, 1);
540     if (array != NULL) {
541       int len = (array->nd == 0) ? 1 : array->dimensions[0];
542       int type = netcdf_type_from_code(array->descr->type);
543       if (ncattput(fileid, varid, name, type, len, array->data) == -1) {
544         Cdunif_seterror();
545         return -1;
546       }
547       PyDict_SetItemString(attributes, name, (PyObject *)array);
548       return 0;
549     }
550     else
551       return -1;
552   }
553 }
554
555 static int
556 check_if_open(file, mode)
557      PyCdunifFileObject *file;
558      int mode;
559 {
560   /* mode: -1 read, 1 write, 0 other */
561   if (file->open) {
562     if (mode != 1 || file->write) {
563       return 1;
564     }
565     else {
566       PyErr_SetString(CdunifError, "write access to read-only file");
567       return 0;
568     }
569   }
570   else {
571     PyErr_SetString(CdunifError, "file has been closed");
572     return 0;
573   }
574 }
575
576 /*
577  * CdunifFile object
578  * (type declaration in Cdunifmodule.h)
579  */
580
581 /* Destroy file object */
582
583 static void
584 PyCdunifFileObject_dealloc(self)
585      PyCdunifFileObject *self;
586 {
587   if (self->open)
588     PyCdunifFile_Close(self);
589   Py_XDECREF(self->dimensions);
590   Py_XDECREF(self->variables);
591   Py_XDECREF(self->attributes);
592   Py_XDECREF(self->name);
593   Py_XDECREF(self->mode);
594   Py_XDECREF(self->diminfo);
595   PyMem_DEL(self);
596 }
597
598 /* Create file object */
599
600 PyCdunifFileObject *
601 PyCdunifFile_Open(filename, mode)
602      char *filename;
603      char *mode;
604 {
605   PyCdunifFileObject *self = PyObject_NEW(PyCdunifFileObject,
606                                           &PyCdunifFile_Type);
607   int rw;
608   CuFileType filetype;
609
610   if (self == NULL)
611     return NULL;
612   self->dimensions = NULL;
613   self->variables = NULL;
614   self->attributes = NULL;
615   self->name = NULL;
616   self->mode = NULL;
617   self->diminfo = NULL;
618   if (strlen(mode) > 2 || (strlen(mode) == 2 && mode[1] != '+')) {
619     PyErr_SetString(PyExc_IOError, "illegal mode specification");
620     PyCdunifFileObject_dealloc(self);
621     return NULL;
622   }
623   rw = (strlen(mode) == 2);
624   self->open = 0;
625   if (mode[0] == 'w') {
626     self->id = nccreate(filename, NC_CLOBBER);
627     self->define = 1;
628     self->write = 1;
629     self->filetype = CuNetcdf;
630     if (self->id != -1) {
631       self->open = 1;
632       Cdunif_file_init(self);
633     }
634   }
635   else if (mode[0] == 'a') {
636     self->id = cdopen(filename, NC_WRITE, &self->filetype);
637     self->define = 0;
638     if (self->id == -1 && ncerr == NC_SYSERR) {
639       self->id = nccreate(filename, NC_NOCLOBBER);
640       self->filetype = CuNetcdf;
641       self->define = 1;
642     }
643     self->write = 1;
644     if (self->id != -1) {
645       self->open = 1;
646       Cdunif_file_init(self);
647     }
648   }
649   else if (mode[0] == 'r') {
650     self->id = cdopen(filename, rw ? NC_WRITE : NC_NOWRITE, &self->filetype);
651     self->define = 0;
652     self->write = rw;
653     if (self->id != -1) {
654       self->open = 1;
655       Cdunif_file_init(self);
656     }
657   }
658   else {
659     PyCdunifFileObject_dealloc(self);
660     return NULL;
661   }
662   if (self->id == -1) {
663     Cdunif_seterror();
664     PyCdunifFileObject_dealloc(self);
665     return NULL;
666   }
667   self->name = PyString_FromString(filename);
668   self->mode = PyString_FromString(mode);
669   return self;
670 }
671
672 /* Create variables from file */
673
674 static int
675 Cdunif_file_init(self)
676      PyCdunifFileObject *self;
677 {
678   int ndims, nvars, ngattrs, recdim;
679   int i;
680   char tcode;
681   PyObject *tuple;
682   CuDimType dimtype;
683   nc_type nctype;
684
685   self->dimensions = PyDict_New();
686   self->variables = PyDict_New();
687   self->attributes = PyDict_New();
688   self->diminfo = PyDict_New();
689   cdinquire(self, &ndims, &nvars, &ngattrs, &recdim);
690   self->recdim = recdim;
691   for (i = 0; i < ndims; i++) {
692     char name[MAX_NC_NAME];
693     char pseudoname[2*CU_MAX_NAME+1];
694     char dimunits[CU_MAX_NAME+1];
695     char vname[CU_MAX_NAME+1];
696     long size;
697     PyObject *size_ob;
698     cddiminq(self, i, name, dimunits, &nctype, &dimtype, vname, &size);
699     tcode = typecode(PyCdunif_data_types[nctype]);
700     tuple = Py_BuildValue("(scsssi)",dimunits,tcode,name,vname,dimension_types[dimtype],i);
701     if (dimtype==CuGlobalDim){
702             PyDict_SetItemString(self->diminfo, name, tuple);
703             if (i == recdim) {
704                     PyDict_SetItemString(self->dimensions, name, Py_None);
705             }
706             else {
707                     size_ob = PyInt_FromLong(size);
708                     PyDict_SetItemString(self->dimensions, name, size_ob);
709                     Py_DECREF(size_ob);
710             }
711     }
712     else {
713             sprintf(pseudoname,"%s_%s",name,vname);
714             PyDict_SetItemString(self->diminfo, pseudoname, tuple);
715             if (i == recdim) {
716                     PyDict_SetItemString(self->dimensions, pseudoname, Py_None);
717             }
718             else {
719                     size_ob = PyInt_FromLong(size);
720                     PyDict_SetItemString(self->dimensions, pseudoname, size_ob);
721                     Py_DECREF(size_ob);
722             }
723     }
724     Py_DECREF(tuple);
725   }
726   for (i = 0; i < nvars; i++) {
727     char name[MAX_NC_NAME];
728     nc_type datatype;
729     int ndimensions, nattrs;
730     int *dimids;
731     PyCdunifVariableObject *variable;
732     cdvarinq(self, i, name, &datatype, &ndimensions, NULL, &nattrs);
733     if (ndimensions > 0) {
734       dimids = (int *)malloc(ndimensions*sizeof(int));
735       if (dimids == NULL) {
736         PyErr_NoMemory();
737         return 0;
738       }
739       cdvarinq(self, i, NULL, NULL, NULL, dimids, NULL);
740     }
741     else
742       dimids = NULL;
743     variable = Cdunif_variable_new(self, name, i, PyCdunif_data_types[datatype],
744                                    ndimensions, dimids, nattrs);
745     PyDict_SetItemString(self->variables, name, (PyObject *)variable);
746     Py_DECREF(variable);
747   }
748   collect_attributes(self, NC_GLOBAL, self->attributes, ngattrs);
749 }
750
751 /* Create dimension */
752
753 int
754 PyCdunifFile_CreateDimension(file, name, size)
755      PyCdunifFileObject *file;
756      char *name;
757      long size;
758 {
759   PyObject *size_ob;
760   int id;
761   if (check_if_open(file, 1)) {
762     if (size == 0 && file->recdim != -1) {
763       PyErr_SetString(CdunifError, "there is already an unlimited dimension");
764       return -1;
765     }
766     define_mode(file, 1);
767     id = ncdimdef(file->id, name, (size == 0) ? NC_UNLIMITED : size);
768     if (id == -1) {
769       Cdunif_seterror();
770       return -1;
771     }
772     else {
773       if (size == 0) {
774         PyDict_SetItemString(file->dimensions, name, Py_None);
775         file->recdim = id;
776       }
777       else {
778         size_ob = PyInt_FromLong(size);
779         PyDict_SetItemString(file->dimensions, name, size_ob);
780         Py_DECREF(size_ob);
781       }
782       return 0;
783     }
784   }
785   else
786     return -1;
787 }
788
789 static PyObject *
790 PyCdunifFileObject_new_dimension(self, args)
791      PyCdunifFileObject *self;
792      PyObject *args;
793 {
794   char *name;
795   PyObject *size_ob;
796   long size;
797   if (!PyArg_ParseTuple(args, "sO", &name, &size_ob))
798     return NULL;
799   if (size_ob == Py_None)
800     size = 0;
801   else if (PyInt_Check(size_ob))
802     size = PyInt_AsLong(size_ob);
803   else {
804     PyErr_SetString(PyExc_TypeError, "size must be None or integer");
805     return NULL;
806   }
807   if (PyCdunifFile_CreateDimension(self, name, size) == 0) {
808     Py_INCREF(Py_None);
809     return Py_None;
810   }
811   else
812     return NULL;
813 }
814
815 /* Create variable */
816
817 PyCdunifVariableObject *
818 PyCdunifFile_CreateVariable(file, name, typecode, dimension_names, ndim)
819      PyCdunifFileObject *file;
820      char *name;
821      int typecode;
822      char **dimension_names;
823      int ndim;
824 {
825   int *dimids;
826   PyCdunifVariableObject *variable;
827   int ntype;
828   int i;
829   if (check_if_open(file, 1)) {
830     define_mode(file, 1);
831     if (ndim == 0)
832       dimids = NULL;
833     else {
834       dimids = (int *)malloc(ndim*sizeof(int));
835       if (dimids == NULL)
836         return (PyCdunifVariableObject *)PyErr_NoMemory();
837     }
838     for (i = 0; i < ndim; i++) {
839       dimids[i] = cddimid(file, dimension_names[i]);
840       if (dimids[i] == -1) {
841         Cdunif_seterror();
842         free(dimids);
843         return NULL;
844       }
845       if (dimids[i] == file->recdim && i > 0) {
846         PyErr_SetString(CdunifError, "unlimited dimension must be first");
847         free(dimids);
848         return NULL;
849       }
850     }
851     ntype = netcdf_type_from_code(typecode);
852     i = ncvardef(file->id, name, ntype, ndim, dimids);
853     if (i == -1) {
854       Cdunif_seterror();
855       if (dimids != NULL)
856         free(dimids);
857       return NULL;
858     }
859     variable = Cdunif_variable_new(file, name, i, PyCdunif_data_types[ntype],
860                                    ndim, dimids, 0);
861     PyDict_SetItemString(file->variables, name, (PyObject *)variable);
862     return variable;
863   }
864   else
865     return NULL;
866 }
867
868 static PyObject *
869 PyCdunifFileObject_new_variable(self, args)
870      PyCdunifFileObject *self;
871      PyObject *args;
872 {
873   PyCdunifVariableObject *var;
874   char **dimension_names;
875   PyObject *item, *dim;
876   char *name;
877   int ndim;
878   char type;
879   int i;
880   if (!PyArg_ParseTuple(args, "scO!", &name, &type, &PyTuple_Type, &dim))
881     return NULL;
882   ndim = PyTuple_Size(dim);
883   if (ndim == 0)
884     dimension_names = NULL;
885   else {
886     dimension_names = (char **)malloc(ndim*sizeof(char *));
887     if (dimension_names == NULL) {
888       PyErr_SetString(PyExc_MemoryError, "out of memory");
889       return NULL;
890     }
891   }
892   for (i = 0; i < ndim; i++) {
893     item = PyTuple_GetItem(dim, i);
894     if (PyString_Check(item))
895       dimension_names[i] = PyString_AsString(item);
896     else {
897       PyErr_SetString(PyExc_TypeError, "dimension name must be a string");
898       free(dimension_names);
899       return NULL;
900     }
901   }
902   var = PyCdunifFile_CreateVariable(self, name, type, dimension_names, ndim);
903   free(dimension_names);
904   return (PyObject *)var;
905 }
906
907 /* Return a variable object referring to an existing variable */
908
909 PyCdunifVariableObject *
910 PyCdunifFile_GetVariable(file, name)
911      PyCdunifFileObject *file;
912      char *name;
913 {
914   return (PyCdunifVariableObject *)PyDict_GetItemString(file->variables, name);
915 }
916
917 /* Synchronize output */
918
919 int
920 PyCdunifFile_Sync(file)
921      PyCdunifFileObject *file;
922 {
923   if (check_if_open(file, 0)) {
924     define_mode(file, 0);
925     if (cdsync(file) == -1) {
926       Cdunif_seterror();
927       return -1;
928     }
929     else
930       return 0;
931   }
932   else
933     return -1;
934 }
935
936 static PyObject *
937 PyCdunifFileObject_sync(self, args)
938      PyCdunifFileObject *self;
939      PyObject *args;
940 {
941   if (!PyArg_ParseTuple(args, ""))
942     return NULL;
943   if (PyCdunifFile_Sync(self) == 0) {
944     Py_INCREF(Py_None);
945     return Py_None;
946   }
947   else
948     return NULL;
949 }
950
951 /* Close file */
952
953 int
954 PyCdunifFile_Close(file)
955      PyCdunifFileObject *file;
956 {
957   if (check_if_open(file, 0)) {
958     if (cdclose(file) == -1) {
959       Cdunif_seterror();
960       return -1;
961     }
962     else
963       return 0;
964   }
965   else
966     return -1;
967 }
968
969 static PyObject *
970 PyCdunifFileObject_close(self, args)
971      PyCdunifFileObject *self;
972      PyObject *args;
973 {
974   char *history = NULL;
975   if (!PyArg_ParseTuple(args, "|s", &history))
976     return NULL;
977   if (history != NULL)
978     PyCdunifFile_AddHistoryLine(self, history);
979   if (PyCdunifFile_Close(self) == 0) {
980     Py_INCREF(Py_None);
981     return Py_None;
982   }
983   else
984     return NULL;
985 }
986
987 static PyObject *
988 PyCdunifFileObject_read_dimension(PyCdunifFileObject *self, PyObject *args){
989         char *name;
990         PyArrayObject *array;
991         PyObject *tuple, *dimidObj;
992         int dimid;
993         long length;
994         int dimlen;
995         nc_type nctype;
996        
997         if (!PyArg_ParseTuple(args, "s", &name))
998                 return NULL;
999
1000                                              /* Check that the file is open */
1001         if(!check_if_open(self, -1)){
1002                 PyErr_SetString(PyExc_TypeError, "File not open");
1003                 return NULL;
1004         }
1005                                              /* Get the dimension ID */
1006
1007         tuple = PyDict_GetItemString(self->diminfo,name);
1008         if (tuple==NULL || !PyTuple_Check(tuple)){
1009                 PyErr_SetString(PyExc_TypeError, "Dimension not found");
1010                 return NULL;
1011         }
1012         dimidObj = PyTuple_GetItem(tuple,5);
1013         if (!PyInt_Check(dimidObj)){
1014                 PyErr_SetString(PyExc_TypeError, "Bad dimension ID");
1015                 return NULL;
1016         }
1017         dimid = (int)PyInt_AsLong(dimidObj);
1018
1019                                              /* Get the dimension length and type*/
1020         if (cddiminq(self, dimid, NULL, NULL, &nctype, NULL, NULL, &length)==-1){
1021                 PyErr_SetString(PyExc_TypeError, "Dimension not found in file");
1022                 return NULL;
1023         }
1024
1025                                              /* Get the array */
1026         dimlen = length;
1027         array = (PyArrayObject *)PyArray_FromDims(1,&dimlen,PyCdunif_data_types[nctype]);
1028         if (array != NULL){
1029                 if (cddimget(self, dimid, array->data)==-1){
1030                         ncerr = cdgeterr(self);
1031                         Cdunif_seterror();
1032                         Py_DECREF(array);
1033                         array=NULL;
1034                 }
1035                                              /* This is ugly, concatenate fails otherwise */
1036 #ifdef PCMDI_NUMERICS
1037                 generate_pcmdi_dims(&array,"DimensionArray");
1038 #endif         
1039                 return (PyObject *)array;
1040         }
1041         else {
1042                 return PyErr_NoMemory();
1043         }
1044 }
1045
1046 /* Method table */
1047
1048 static PyMethodDef PyCdunifFileObject_methods[] = {
1049   {"close", (PyCFunction)PyCdunifFileObject_close, 1},
1050   {"createDimension", (PyCFunction)PyCdunifFileObject_new_dimension, 1},
1051   {"createVariable", (PyCFunction)PyCdunifFileObject_new_variable, 1},
1052   {"readDimension",(PyCFunction)PyCdunifFileObject_read_dimension, 1},
1053   {"sync", (PyCFunction)PyCdunifFileObject_sync, 1},
1054   {NULL, NULL}          /* sentinel */
1055 };
1056
1057 /* Attribute access */
1058
1059 PyObject *
1060 PyCdunifFile_GetAttribute(self, name)
1061      PyCdunifFileObject *self;
1062      char *name;
1063 {
1064   PyObject *value;
1065   if (check_if_open(self, -1)) {
1066     if (strcmp(name, "dimensions") == 0) {
1067       Py_INCREF(self->dimensions);
1068       return self->dimensions;
1069     }
1070     if (strcmp(name, "variables") == 0) {
1071       Py_INCREF(self->variables);
1072       return self->variables;
1073     }
1074     if (strcmp(name, "__dict__") == 0) {
1075       Py_INCREF(self->attributes);
1076       return self->attributes;
1077     }
1078     if (strcmp(name, "dimensioninfo") == 0) {
1079       Py_INCREF(self->diminfo);
1080       return self->diminfo;
1081     }
1082     value = PyDict_GetItemString(self->attributes, name);
1083     if (value != NULL) {
1084       Py_INCREF(value);
1085       return value;
1086     }
1087     else {
1088       PyErr_Clear();
1089       return Py_FindMethod(PyCdunifFileObject_methods, (PyObject *)self, name);
1090     }
1091   }
1092   else
1093     return NULL;
1094 }
1095
1096 int
1097 PyCdunifFile_SetAttribute(self, name, value)
1098      PyCdunifFileObject *self;
1099      char *name;
1100      PyObject *value;
1101 {
1102   if (check_if_open(self, 1)) {
1103     if (strcmp(name, "dimensions") == 0 ||
1104         strcmp(name, "variables") == 0 ||
1105         strcmp(name, "dimensioninfo") == 0 ||
1106         strcmp(name, "__dict__") == 0) {
1107       PyErr_SetString(PyExc_TypeError, "object has read-only attributes");
1108       return -1;
1109     }
1110     define_mode(self, 1);
1111     return set_attribute(self->id, NC_GLOBAL, self->attributes, name, value);
1112   }
1113   else
1114     return -1;
1115 }
1116
1117 int
1118 PyCdunifFile_SetAttributeString(self, name, value)
1119      PyCdunifFileObject *self;
1120      char *name;
1121      char *value;
1122 {
1123   PyObject *string = PyString_FromString(value);
1124   if (string != NULL)
1125     return PyCdunifFile_SetAttribute(self, name, string);
1126   else
1127     return -1;
1128 }
1129
1130 int
1131 PyCdunifFile_AddHistoryLine(self, text)
1132      PyCdunifFileObject *self;
1133      char *text;
1134 {
1135   static char *history = "history";
1136   int alloc, old, new, new_alloc;
1137   PyStringObject *new_string;
1138   PyObject *h = PyCdunifFile_GetAttribute(self, history);
1139   if (h == NULL) {
1140     PyErr_Clear();
1141     alloc = 0;
1142     old = 0;
1143     new = strlen(text);
1144   }
1145   else {
1146     alloc = PyString_Size(h);
1147     old = strlen(PyString_AsString(h));
1148     new = old + strlen(text) + 1;
1149   }
1150   new_alloc = (new <= alloc) ? alloc : new + 500;
1151   new_string = (PyStringObject *)PyString_FromStringAndSize(NULL, new_alloc);
1152   if (new_string) {
1153     char *s = new_string->ob_sval;
1154     int len, ret;
1155     memset(s, 0, new_alloc+1);
1156     if (h == NULL)
1157       len = -1;
1158     else {
1159       strcpy(s, PyString_AsString(h));
1160       len = strlen(s);
1161       s[len] = '\n';
1162     }
1163     strcpy(s+len+1, text);
1164     ret = PyCdunifFile_SetAttribute(self, history, (PyObject *)new_string);
1165     Py_XDECREF(h);
1166     Py_DECREF(new_string);
1167     return ret;
1168   }
1169   else
1170     return -1;
1171 }
1172
1173 /* Printed representation */
1174 static PyObject *
1175 PyCdunifFileObject_repr(file)
1176      PyCdunifFileObject *file;
1177 {
1178   char buf[300];
1179   sprintf(buf, "<%s Cdunif file '%.256s', mode '%.10s' at %lx>",
1180           file->open ? "open" : "closed",
1181           PyString_AsString(file->name),
1182           PyString_AsString(file->mode),
1183           (long)file);
1184   return PyString_FromString(buf);
1185 }
1186
1187 /* Type definition */
1188
1189 statichere PyTypeObject PyCdunifFile_Type = {
1190   PyObject_HEAD_INIT(NULL)
1191   0,            /*ob_size*/
1192   "CdunifFile", /*tp_name*/
1193   sizeof(PyCdunifFileObject),   /*tp_basicsize*/
1194   0,            /*tp_itemsize*/
1195   /* methods */
1196   (destructor)PyCdunifFileObject_dealloc, /*tp_dealloc*/
1197   0,                    /*tp_print*/
1198   (getattrfunc)PyCdunifFile_GetAttribute, /*tp_getattr*/
1199   (setattrfunc)PyCdunifFile_SetAttribute, /*tp_setattr*/
1200   0,                    /*tp_compare*/
1201   (reprfunc)PyCdunifFileObject_repr,   /*tp_repr*/
1202   0,                    /*tp_as_number*/
1203   0,                    /*tp_as_sequence*/
1204   0,                    /*tp_as_mapping*/
1205   0,                    /*tp_hash*/
1206 };
1207
1208 /*
1209  * CdunifVariable object
1210  * (type declaration in Cdunifmodule.h)
1211  */
1212
1213 /* Destroy variable object */
1214
1215 static void
1216 PyCdunifVariableObject_dealloc(self)
1217      PyCdunifVariableObject *self;
1218 {
1219   if (self->dimids != NULL)
1220     free(self->dimids);
1221   if (self->name != NULL)
1222     free(self->name);
1223   Py_XDECREF(self->file);
1224   PyMem_DEL(self);
1225 }
1226
1227 /* Create variable object */
1228
1229 statichere PyCdunifVariableObject *
1230 Cdunif_variable_new(file, name, id, type, ndims, dimids, nattrs)
1231      PyCdunifFileObject *file;
1232      char *name;
1233      int id;
1234      int type;
1235      int ndims;
1236      int *dimids;
1237      int nattrs;
1238 {
1239   PyCdunifVariableObject *self;
1240   int recdim;
1241   int i;
1242   if (check_if_open(file, -1)) {
1243     self = PyObject_NEW(PyCdunifVariableObject, &PyCdunifVariable_Type);
1244     if (self == NULL)
1245       return NULL;
1246     self->file = file;
1247     Py_INCREF(file);
1248     self->id = id;
1249     self->type = type;
1250     self->nd = ndims;
1251     self->dimids = dimids;
1252     self->unlimited = 0;
1253     cdinquire(file, NULL, NULL, NULL, &recdim);
1254     self->dimensions = (long *)malloc(ndims*sizeof(long));
1255     if (self->dimensions != NULL) {
1256       for (i = 0; i < ndims; i++) {
1257               cddiminq(file, dimids[i], NULL, NULL, NULL, NULL, NULL, &self->dimensions[i]);
1258       }
1259       if (ndims > 0 && self->dimids[0] == self->file->recdim)
1260         self->unlimited = 1;
1261     }
1262     self->name = (char *)malloc(strlen(name)+1);
1263     if (self->name != NULL)
1264       strcpy(self->name, name);
1265     self->attributes = PyDict_New();
1266     collect_attributes(file, self->id, self->attributes, nattrs);
1267     return self;
1268   }
1269   else
1270     return NULL;
1271 }
1272
1273 /* Return value */
1274
1275 PyObject *
1276 PyCdunifVariableObject_value(PyCdunifVariableObject *self, PyObject *args)
1277 {
1278   PyCdunifIndex *indices;
1279   if (!PyArg_ParseTuple(args, ""))
1280     return NULL;
1281   if (self->nd == 0)
1282     indices = NULL;
1283   else
1284     indices = PyCdunifVariable_Indices(self);
1285   return PyArray_Return(PyCdunifVariable_ReadAsArray(self, indices));
1286 }
1287
1288 /* Assign value */
1289
1290 PyObject *
1291 PyCdunifVariableObject_assign(PyCdunifVariableObject *self, PyObject *args)
1292 {
1293   PyObject *value;
1294   PyCdunifIndex *indices;
1295   if (!PyArg_ParseTuple(args, "O", &value))
1296     return NULL;
1297   if (self->nd == 0)
1298     indices = NULL;
1299   else
1300     indices = PyCdunifVariable_Indices(self);
1301   PyCdunifVariable_WriteArray(self, indices, value);
1302   Py_INCREF(Py_None);
1303   return Py_None;
1304 }
1305
1306 /* Return typecode */
1307
1308 PyObject *
1309 PyCdunifVariableObject_typecode(PyCdunifVariableObject *self, PyObject *args) {
1310   char t;
1311   if (!PyArg_ParseTuple(args, ""))
1312     return NULL;
1313   t = typecode(self->type);
1314   return PyString_FromStringAndSize(&t, 1);
1315 }
1316
1317 /* Get an item: wrapper for subscript */
1318 PyObject *
1319 PyCdunifVariableObject_getitem(PyCdunifVariableObject *self, PyObject *args) {
1320         return PyCdunifVariableObject_subscript(self,args);
1321 }
1322
1323 /* Get an item: wrapper for assign subscript */
1324 PyObject *
1325 PyCdunifVariableObject_setitem(PyCdunifVariableObject *self, PyObject *args) {
1326         PyObject *index;
1327         PyObject *value;
1328        
1329         if (!PyArg_ParseTuple(args, "OO", &index, &value))
1330                 return NULL;
1331         if (PyCdunifVariableObject_ass_subscript(self,index,value) != -1){
1332                 Py_INCREF(Py_None);
1333                 return Py_None;
1334         }
1335         else
1336                 return NULL;
1337 }
1338
1339 /* Get a slice */
1340 PyObject *
1341 PyCdunifVariableObject_getslice(PyCdunifVariableObject *self, PyObject *args) {
1342   int low, high;
1343
1344   if (!PyArg_ParseTuple(args, "ii", &low, &high))
1345           return NULL;
1346   return PyCdunifVariableObject_slice(self,low,high);
1347 }
1348
1349 /* Set a slice */
1350 PyObject *
1351 PyCdunifVariableObject_setslice(PyCdunifVariableObject *self, PyObject *args) {
1352   int low, high;
1353   PyObject *value;
1354
1355   if (!PyArg_ParseTuple(args, "iiO", &low, &high, &value))
1356           return NULL;
1357   if (PyCdunifVariableObject_ass_slice(self,low,high,value) != -1){
1358           Py_INCREF(Py_None);
1359           return Py_None;
1360   }
1361   else
1362           return NULL;
1363 }
1364
1365 /* Method table */
1366
1367 static PyMethodDef PyCdunifVariableObject_methods[] = {
1368   {"assignValue", (PyCFunction)PyCdunifVariableObject_assign, 1},
1369   {"getValue", (PyCFunction)PyCdunifVariableObject_value, 1},
1370   {"typecode", (PyCFunction)PyCdunifVariableObject_typecode, 1},
1371   {"getitem", (PyCFunction)PyCdunifVariableObject_getitem, 1},
1372   {"getslice", (PyCFunction)PyCdunifVariableObject_getslice, 1},
1373   {"setitem", (PyCFunction)PyCdunifVariableObject_setitem, 1},
1374   {"setslice", (PyCFunction)PyCdunifVariableObject_setslice, 1},
1375   {NULL, NULL}          /* sentinel */
1376 };
1377
1378 /* Attribute access */
1379
1380 int
1381 PyCdunifVariable_GetRank(var)
1382      PyCdunifVariableObject *var;
1383 {
1384   return var->nd;
1385 }
1386
1387 long *
1388 PyCdunifVariable_GetShape(var)
1389      PyCdunifVariableObject *var;
1390 {
1391   int i;
1392   if (check_if_open(var->file, -1)) {
1393     for (i = 0; i < var->nd; i++)
1394             cddiminq(var->file, var->dimids[i], NULL, NULL, NULL, NULL, NULL, &var->dimensions[i]);
1395     return var->dimensions;
1396   }
1397   else
1398     return NULL;
1399 }
1400
1401 PyObject *
1402 PyCdunifVariable_GetAttribute(self, name)
1403      PyCdunifVariableObject *self;
1404      char *name;
1405 {
1406   PyObject *value;
1407   if (strcmp(name, "shape") == 0) {
1408     PyObject *tuple;
1409     int i;
1410     if (check_if_open(self->file, -1)) {
1411       PyCdunifVariable_GetShape(self);
1412       tuple = PyTuple_New(self->nd);
1413       for (i = 0; i < self->nd; i++)
1414         PyTuple_SetItem(tuple, i, PyInt_FromLong(self->dimensions[i]));
1415       return tuple;
1416     }
1417     else
1418       return NULL;
1419   }
1420   if (strcmp(name, "dimensions") == 0) {
1421     PyObject *tuple;
1422     int i;
1423     if (check_if_open(self->file, -1)) {
1424       tuple = PyTuple_New(self->nd);
1425       for (i = 0; i < self->nd; i++) {
1426               CuDimType dimtype;
1427               char name[MAX_NC_NAME];
1428               char pseudoname[2*CU_MAX_NAME+1];
1429               char vname[CU_MAX_NAME+1];
1430               cddiminq(self->file, self->dimids[i], name, NULL, NULL, &dimtype, vname, NULL);
1431
1432               if (dimtype==CuGlobalDim){
1433                       PyTuple_SetItem(tuple, i, PyString_FromString(name));
1434               }
1435               else {
1436                       sprintf(pseudoname,"%s_%s",name,vname);
1437                       PyTuple_SetItem(tuple, i, PyString_FromString(pseudoname));
1438               }
1439       }
1440       return tuple;
1441     }
1442     else
1443       return NULL;
1444   }
1445   if (strcmp(name, "__dict__") == 0) {
1446     Py_INCREF(self->attributes);
1447     return self->attributes;
1448   }
1449   value = PyDict_GetItemString(self->attributes, name);
1450   if (value != NULL) {
1451     Py_INCREF(value);
1452     return value;
1453   }
1454   else {
1455     PyErr_Clear();
1456     return Py_FindMethod(PyCdunifVariableObject_methods, (PyObject *)self, name);
1457   }
1458 }
1459
1460 int
1461 PyCdunifVariable_SetAttribute(self, name, value)
1462      PyCdunifVariableObject *self;
1463      char *name;
1464      PyObject *value;
1465 {
1466   if (check_if_open(self->file, 1)) {
1467     if (strcmp(name, "shape") == 0 ||
1468         strcmp(name, "dimensions") == 0 ||
1469         strcmp(name, "__dict__") == 0) {
1470       PyErr_SetString(PyExc_TypeError, "object has read-only attributes");
1471       return -1;
1472     }
1473     define_mode(self->file, 1);
1474     return set_attribute(self->file->id, self->id, self->attributes,
1475                          name, value);
1476   }
1477   else
1478     return -1;
1479 }
1480
1481 int
1482 PyCdunifVariable_SetAttributeString(self, name, value)
1483      PyCdunifVariableObject *self;
1484      char *name;
1485      char *value;
1486 {
1487   PyObject *string = PyString_FromString(value);
1488   if (string != NULL)
1489     return PyCdunifVariable_SetAttribute(self, name, string);
1490   else
1491     return -1;
1492 }
1493
1494 /* Subscripting */
1495
1496 static int
1497 PyCdunifVariableObject_length(self)
1498      PyCdunifVariableObject *self;
1499 {
1500   if (self->nd > 0)
1501     return self->dimensions[0];
1502   else
1503     return 0;
1504 }
1505
1506 PyCdunifIndex *
1507 PyCdunifVariable_Indices(var)
1508      PyCdunifVariableObject *var;
1509 {
1510   PyCdunifIndex *indices =
1511     (PyCdunifIndex *)malloc(var->nd*sizeof(PyCdunifIndex));
1512   int i;
1513   if (indices != NULL)
1514     for (i = 0; i < var->nd; i++) {
1515       indices[i].start = 0;
1516       indices[i].stop = var->dimensions[i];
1517       indices[i].stride = 1;
1518       indices[i].item = 0;
1519     }
1520   else
1521     PyErr_SetString(PyExc_MemoryError, "out of memory");
1522   return indices;
1523 }
1524
1525 PyArrayObject *
1526 PyCdunifVariable_ReadAsArray(self, indices)
1527      PyCdunifVariableObject *self;
1528      PyCdunifIndex *indices;
1529 {
1530   int *dims;
1531   PyArrayObject *array;
1532   int i, d;
1533   int nitems;
1534   int error = 0;
1535   d = 0;
1536   nitems = 1;
1537   if (!check_if_open(self->file, -1)) {
1538     free(indices);
1539     return NULL;
1540   }
1541   define_mode(self->file, 0);
1542   if (self->nd == 0)
1543     dims = NULL;
1544   else {
1545     dims = (int *)malloc(self->nd*sizeof(int));
1546     if (dims == NULL) {
1547       free(indices);
1548       return (PyArrayObject *)PyErr_NoMemory();
1549     }
1550   }
1551   for (i = 0; i < self->nd; i++) {
1552     error = error || (indices[i].stride <= 0);
1553     if (indices[i].start < 0)
1554       indices[i].start += self->dimensions[i];
1555     if (indices[i].start < 0)
1556       indices[i].start = 0;
1557     if (indices[i].start > self->dimensions[i])
1558       indices[i].start = self->dimensions[i];
1559     if (indices[i].item != 0)
1560       indices[i].stop = indices[i].start + 1;
1561     else {
1562       if (indices[i].stop < 0)
1563         indices[i].stop += self->dimensions[i];
1564       if (indices[i].stop < 0)
1565         indices[i].stop = 0;
1566       if (indices[i].stop > self->dimensions[i])
1567         indices[i].stop = self->dimensions[i];
1568       dims[d] = (indices[i].stop-indices[i].start-1)/indices[i].stride+1;
1569       if (dims[d] < 0)
1570         dims[d] = 0;
1571       nitems *= dims[d];
1572       d++;
1573     }
1574   }
1575   if (error) {
1576     PyErr_SetString(PyExc_IndexError, "illegal index");
1577     if (dims != NULL)
1578       free(dims);
1579     if (indices != NULL)
1580       free(indices);
1581     return NULL;
1582   }
1583   array = (PyArrayObject *)PyArray_FromDims(d, dims, self->type);
1584   if (array != NULL && nitems > 0) {
1585     if (self->nd == 0) {
1586       long zero = 0;
1587       if (cdvarget1(self->file, self->id, &zero, array->data) == -1) {
1588         Cdunif_seterror();
1589         Py_DECREF(array);
1590         array = NULL;
1591       }
1592     }
1593     else {
1594       long *start;
1595       long *count;
1596       long *stride;
1597       start = (long *)malloc(self->nd*sizeof(long));
1598       count = (long *)malloc(self->nd*sizeof(long));
1599       stride = (long *)malloc(self->nd*sizeof(long));
1600       if (start != NULL && count != NULL && stride != NULL) {
1601         for (i = 0; i < self->nd; i++) {
1602           start[i] = indices[i].start;
1603           stride[i] = indices[i].stride;
1604           count[i] = (indices[i].stop-indices[i].start-1)/indices[i].stride+1;
1605         }
1606         if (cdvargets(self->file, self->id, start, count, stride, array->data) == -1) {
1607           Cdunif_seterror();
1608           Py_DECREF(array);
1609           array = NULL;
1610         }
1611 #ifdef PCMDI_NUMERICS
1612         generate_pcmdi_dims(&array,"DataArray");
1613 #endif
1614       }
1615       if (start != NULL)
1616         free(start);
1617       if (count != NULL)
1618         free(count);
1619       if (stride != NULL)
1620         free(stride);
1621     }
1622   }
1623   free(dims);
1624   free(indices);
1625   return array;
1626 }
1627
1628 PyStringObject *
1629 PyCdunifVariable_ReadAsString(self)
1630      PyCdunifVariableObject *self;
1631 {
1632   if (self->type != PyArray_CHAR || self->nd != 1) {
1633     PyErr_SetString(CdunifError, "not a string variable");
1634     return NULL;
1635   }
1636   if (check_if_open(self->file, -1)) {
1637     long zero = 0;
1638     char *temp;
1639     PyObject *string;
1640     define_mode(self->file, 0);
1641     temp = (char *)malloc((self->dimensions[0]+1)*sizeof(char));
1642     if (temp == NULL)
1643       return (PyStringObject *)PyErr_NoMemory();
1644     if (cdvarget(self->file, self->id, &zero,
1645                  self->dimensions, temp) == -1) {
1646       Cdunif_seterror();
1647       string = NULL;
1648     }
1649     else {
1650       temp[self->dimensions[0]] = '\0';
1651       string = PyString_FromString(temp);
1652     }
1653     free(temp);
1654     return (PyStringObject *)string;
1655   }
1656   else
1657     return NULL;
1658 }
1659
1660 int
1661 PyCdunifVariable_WriteArray(self, indices, value)
1662      PyCdunifVariableObject *self;
1663      PyCdunifIndex *indices;
1664      PyObject *value;
1665 {
1666   int *dims;
1667   PyArrayObject *array;
1668   int i, j, d;
1669   int nitems;
1670   int error = 0;
1671   int ret = 0;
1672   d = 0;
1673   nitems = 1;
1674   if (!check_if_open(self->file, 1)) {
1675     free(indices);
1676     return -1;
1677   }
1678   if (self->nd == 0)
1679     dims = NULL;
1680   else {
1681     dims = (int *)malloc(self->nd*sizeof(int));
1682     if (dims == NULL) {
1683       free(indices);
1684       PyErr_SetString(PyExc_MemoryError, "out of memory");
1685       return -1;
1686     }
1687   }
1688   define_mode(self->file, 0);
1689   for (i = 0; i < self->nd; i++) {
1690     error = error || (indices[i].stride <= 0);
1691     if (indices[i].start < 0)
1692       indices[i].start += self->dimensions[i];
1693     if (indices[i].start < 0)
1694       indices[i].start = 0;
1695     if (indices[i].stop < 0)
1696       indices[i].stop += self->dimensions[i];
1697     if (indices[i].stop < 0)
1698       indices[i].stop = 0;
1699     if (i > 0 || !self->unlimited) {
1700       if (indices[i].start > self->dimensions[i])
1701         indices[i].start = self->dimensions[i];
1702       if (indices[i].stop > self->dimensions[i])
1703         indices[i].stop = self->dimensions[i];
1704     }
1705     if (indices[i].item == 0) {
1706       dims[d] = (indices[i].stop-indices[i].start-1)/indices[i].stride+1;
1707       if (dims[d] < 0)
1708         dims[d] = 0;
1709       nitems *= dims[d];
1710       d++;
1711     }
1712     else
1713       indices[i].stop = indices[i].start + 1;
1714   }
1715   if (error) {
1716     PyErr_SetString(PyExc_IndexError, "illegal index");
1717     free(dims);
1718     free(indices);
1719     return -1;
1720   }
1721   array = (PyArrayObject *)PyArray_ContiguousFromObject(value, self->type,
1722                                                         0, d);
1723   if (array != NULL) {
1724     if (self->nd == 0) {
1725       long zero = 0;
1726       if (ncvarput1(self->file->id, self->id, &zero, array->data) == -1) {
1727         Cdunif_seterror();
1728         ret = -1;
1729       }
1730     }
1731     else {
1732       long *start;
1733       long *count, *count1;
1734       long *stride;
1735       long *current;
1736       char *loop;
1737       long repeat = 1;
1738       int elim, lastloop;
1739       start = (long *)malloc(self->nd*sizeof(long));
1740       count = (long *)malloc(self->nd*sizeof(long));
1741       count1 = (long *)malloc(self->nd*sizeof(long));
1742       stride = (long *)malloc(self->nd*sizeof(long));
1743       current = (long *)malloc(self->nd*sizeof(long));
1744       loop = (char *)malloc(self->nd*sizeof(char));
1745       if (start != NULL && count != NULL && count1 != NULL
1746           && stride != NULL && current != NULL && loop != NULL) {
1747         elim = 0;
1748         for (i = 0; i < self->nd; i++) {
1749           start[i] = indices[i].start;
1750           stride[i] = indices[i].stride;
1751           count[i] = (indices[i].stop-indices[i].start-1)/indices[i].stride+1;
1752           count1[i] = count[i];
1753           current[i] = 0;
1754           loop[i] = 0;
1755           if (indices[i].item)
1756             elim++;
1757         }
1758         for (i = array->nd-1, j = self->nd-1; i >= 0 && j >= 0; i--, j--) {
1759           while (j >= 0 && indices[j].item)
1760             j--;
1761           if (j < 0) {
1762             ret = -1;
1763             break;
1764           }
1765           if (array->dimensions[i] != count[j])
1766             ret = -1;
1767         }
1768         if (i == -1) {
1769           lastloop = -1;
1770           while (j >= 0) {
1771             loop[j] = !indices[j].item;
1772             if (loop[j]) {
1773               if (lastloop < 0)
1774                 lastloop = j;
1775               repeat *= count[j];
1776               count1[j] = 1;
1777             }
1778             j--;
1779           }
1780         }
1781         else
1782           ret = -1;
1783         if (ret == -1)
1784           PyErr_SetString(PyExc_ValueError, "shapes are not aligned");
1785         while (repeat-- && ret == 0) {
1786           if (ncvarputg(self->file->id, self->id, start, count1, stride, NULL,
1787                         array->data) == -1) {
1788             Cdunif_seterror();
1789             ret = -1;
1790           }
1791           if (lastloop >= 0) {
1792             for (i = lastloop; i >= 0; i--) {
1793               while (!loop[i] && i >= 0)
1794                 i--;
1795               if (i >= 0) {
1796                 start[i] += stride[i];
1797                 if (++current[i] != count[i])
1798                   break;
1799                 start[i] -= count[i]*stride[i];
1800                 current[i] = 0;
1801               }
1802             }
1803           }
1804         }
1805         if (self->unlimited)
1806           cddiminq(self->file, self->dimids[0], NULL, NULL, NULL, NULL, NULL, &self->dimensions[0]);
1807       }
1808       Py_DECREF(array);
1809       if (start != NULL)
1810         free(start);
1811       if (count != NULL)
1812         free(count);
1813       if (count1 != NULL)
1814         free(count1);
1815       if (stride != NULL)
1816         free(stride);
1817       if (current != NULL)
1818         free(current);
1819     }
1820     free(dims);
1821     free(indices);
1822     return ret;
1823   }
1824   else
1825     return -1;
1826 }
1827
1828 int
1829 PyCdunifVariable_WriteString(self, value)
1830      PyCdunifVariableObject *self;
1831      PyStringObject *value;
1832 {
1833   long zero = 0;
1834   long len;
1835   if (self->type != PyArray_CHAR || self->nd != 1) {
1836     PyErr_SetString(CdunifError, "not a string variable");
1837     return -1;
1838   }
1839   len = PyString_Size((PyObject *)value);
1840   if (len > self->dimensions[0]) {
1841     PyErr_SetString(PyExc_ValueError, "string too long");
1842     return -1;
1843   }
1844   if (self->dimensions[0] > len)
1845     len++;
1846   if (check_if_open(self->file, 1)) {
1847     define_mode(self->file, 0);
1848     if (ncvarput(self->file->id, self->id, &zero, &len,
1849                  PyString_AsString((PyObject *)value)) == -1) {
1850       Cdunif_seterror();
1851       return -1;
1852     }
1853     return 0;
1854   }
1855   else
1856     return -1;
1857 }
1858
1859 static PyObject *
1860 PyCdunifVariableObject_item(self, i)
1861      PyCdunifVariableObject *self;
1862      int i;
1863 {
1864   PyCdunifIndex *indices;
1865   if (self->nd == 0) {
1866     PyErr_SetString(PyExc_TypeError, "Not a sequence");
1867     return NULL;
1868   }
1869   indices = PyCdunifVariable_Indices(self);
1870   if (indices != NULL) {
1871     indices[0].start = i;
1872     indices[0].stop = i+1;
1873     indices[0].item = 1;
1874     return PyArray_Return(PyCdunifVariable_ReadAsArray(self, indices));
1875   }
1876   return NULL;
1877 }
1878
1879 static PyObject *
1880 PyCdunifVariableObject_slice(self, low, high)
1881      PyCdunifVariableObject *self;
1882      int low;
1883      int high;
1884 {
1885   PyCdunifIndex *indices;
1886   if (self->nd == 0) {
1887     PyErr_SetString(PyExc_TypeError, "Not a sequence");
1888     return NULL;
1889   }
1890   indices = PyCdunifVariable_Indices(self);
1891   if (indices != NULL) {
1892     indices[0].start = low;
1893     indices[0].stop = high;
1894     return PyArray_Return(PyCdunifVariable_ReadAsArray(self, indices));
1895   }
1896   return NULL;
1897 }
1898
1899 static PyObject *
1900 PyCdunifVariableObject_subscript(self, index)
1901      PyCdunifVariableObject *self;
1902      PyObject *index;
1903 {
1904   PyCdunifIndex *indices;
1905   if (PyInt_Check(index)) {
1906     int i = PyInt_AsLong(index);
1907     return PyCdunifVariableObject_item(self, i);
1908   }
1909   if (self->nd == 0) {
1910     PyErr_SetString(PyExc_TypeError, "Not a sequence");
1911     return NULL;
1912   }
1913   indices = PyCdunifVariable_Indices(self);
1914   if (indices != NULL) {
1915     if (PySlice_Check(index)) {
1916       PySlice_GetIndices((PySliceObject *)index, self->dimensions[0],
1917                          &indices->start, &indices->stop, &indices->stride);
1918       return PyArray_Return(PyCdunifVariable_ReadAsArray(self, indices));
1919     }
1920     if (PyTuple_Check(index)) {
1921       int ni = PyTuple_Size(index);
1922       if (ni <= self->nd) {
1923         int i, d;
1924         d = 0;
1925         for (i = 0; i < ni; i++) {
1926           PyObject *subscript = PyTuple_GetItem(index, i);
1927           if (PyInt_Check(subscript)) {
1928             int n = PyInt_AsLong(subscript);
1929             indices[d].start = n;
1930             indices[d].stop = n+1;
1931             indices[d].item = 1;
1932             d++;
1933           }
1934           else if (PySlice_Check(subscript)) {
1935             PySlice_GetIndices((PySliceObject *)subscript, self->dimensions[d],
1936                                &indices[d].start, &indices[d].stop,
1937                                &indices[d].stride);
1938             d++;
1939           }
1940           else if (subscript == Py_Ellipsis) {
1941             d = self->nd - ni + i + 1;
1942           }
1943           else {
1944             PyErr_SetString(PyExc_TypeError, "illegal subscript type");
1945             free(indices);
1946             return NULL;
1947           }
1948         }
1949         return PyArray_Return(PyCdunifVariable_ReadAsArray(self, indices));
1950       }
1951       else {
1952         PyErr_SetString(PyExc_IndexError, "too many subscripts");
1953         free(indices);
1954         return NULL;
1955       }
1956     }
1957     PyErr_SetString(PyExc_TypeError, "illegal subscript type");
1958     free(indices);
1959   }
1960   return NULL;
1961 }
1962
1963 static int
1964 PyCdunifVariableObject_ass_item(self, i, value)
1965      PyCdunifVariableObject *self;
1966      int i;
1967      PyObject *value;
1968 {
1969   PyCdunifIndex *indices;
1970   if (value == NULL) {
1971     PyErr_SetString(PyExc_ValueError, "Can't delete elements.");
1972     return -1;
1973   }
1974   if (self->nd == 0) {
1975     PyErr_SetString(PyExc_TypeError, "Not a sequence");
1976     return -1;
1977   }
1978   indices = PyCdunifVariable_Indices(self);
1979   if (indices != NULL) {
1980     indices[0].start = i;
1981     indices[0].stop = i+1;
1982     indices[0].item = 1;
1983     return PyCdunifVariable_WriteArray(self, indices, value);
1984   }
1985   return -1;
1986 }
1987
1988 static int
1989 PyCdunifVariableObject_ass_slice(self, low, high, value)
1990      PyCdunifVariableObject *self;
1991      int low;
1992      int high;
1993      PyObject *value;
1994 {
1995   PyCdunifIndex *indices;
1996   if (value == NULL) {
1997     PyErr_SetString(PyExc_ValueError, "Can't delete elements.");
1998     return -1;
1999   }
2000   if (self->nd == 0) {
2001     PyErr_SetString(PyExc_TypeError, "Not a sequence");
2002     return -1;
2003   }
2004   indices = PyCdunifVariable_Indices(self);
2005   if (indices != NULL) {
2006     indices[0].start = low;
2007     indices[0].stop = high;
2008     return PyCdunifVariable_WriteArray(self, indices, value);
2009   }
2010   return -1;
2011 }
2012
2013 static int
2014 PyCdunifVariableObject_ass_subscript(self, index, value)
2015      PyCdunifVariableObject *self;
2016      PyObject *index;
2017      PyObject *value;
2018 {
2019   PyCdunifIndex *indices;
2020   if (PyInt_Check(index)) {
2021     int i = PyInt_AsLong(index);
2022     return PyCdunifVariableObject_ass_item(self, i, value);
2023   }
2024   if (value == NULL) {
2025     PyErr_SetString(PyExc_ValueError, "Can't delete elements.");
2026     return -1;
2027   }
2028   if (self->nd == 0) {
2029     PyErr_SetString(PyExc_TypeError, "Not a sequence");
2030     return -1;
2031   }
2032   indices = PyCdunifVariable_Indices(self);
2033   if (indices != NULL) {
2034     if (PySlice_Check(index)) {
2035       PySlice_GetIndices((PySliceObject *)index, self->dimensions[0],
2036                          &indices->start, &indices->stop, &indices->stride);
2037       return PyCdunifVariable_WriteArray(self, indices, value);
2038     }
2039     if (PyTuple_Check(index)) {
2040       int ni = PyTuple_Size(index);
2041       if (ni <= self->nd) {
2042         int i, d;
2043         d = 0;
2044         for (i = 0; i < ni; i++) {
2045           PyObject *subscript = PyTuple_GetItem(index, i);
2046           if (PyInt_Check(subscript)) {
2047             int n = PyInt_AsLong(subscript);
2048             indices[d].start = n;
2049             indices[d].stop = n+1;
2050             indices[d].item = 1;
2051             d++;
2052           }
2053           else if (PySlice_Check(subscript)) {
2054             PySlice_GetIndices((PySliceObject *)subscript, self->dimensions[d],
2055                                &indices[d].start, &indices[d].stop,
2056                                &indices[d].stride);
2057             d++;
2058           }
2059           else if (subscript == Py_Ellipsis) {
2060             d = self->nd - ni + i + 1;
2061           }
2062           else {
2063             PyErr_SetString(PyExc_TypeError, "illegal subscript type");
2064             free(indices);
2065             return -1;
2066           }
2067         }
2068         return PyCdunifVariable_WriteArray(self, indices, value);
2069       }
2070       else {
2071         PyErr_SetString(PyExc_IndexError, "too many subscripts");
2072         free(indices);
2073         return -1;
2074       }
2075     }
2076     PyErr_SetString(PyExc_TypeError, "illegal subscript type");
2077     free(indices);
2078   }
2079   return -1;
2080 }
2081
2082 /* Type definition */
2083
2084 static PyObject *
2085 PyCdunifVariableObject_error1(self, other)
2086      PyCdunifVariableObject *self;
2087      PyCdunifVariableObject *other;
2088 {
2089   PyErr_SetString(PyExc_TypeError, "can't add Cdunif variables");
2090   return NULL;
2091 }
2092
2093 static PyObject *
2094 PyCdunifVariableObject_error2(self, n)
2095      PyCdunifVariableObject *self;
2096      int n;
2097 {
2098   PyErr_SetString(PyExc_TypeError, "can't multiply Cdunif variables");
2099   return NULL;
2100 }
2101
2102
2103 static PySequenceMethods PyCdunifVariableObject_as_sequence = {
2104   (inquiry)PyCdunifVariableObject_length,               /*sq_length*/
2105   (binaryfunc)PyCdunifVariableObject_error1,       /*nb_add*/
2106   (intargfunc)PyCdunifVariableObject_error2,       /*nb_multiply*/
2107   (intargfunc)PyCdunifVariableObject_item,              /*sq_item*/
2108   (intintargfunc)PyCdunifVariableObject_slice,  /*sq_slice*/
2109   (intobjargproc)PyCdunifVariableObject_ass_item,       /*sq_ass_item*/
2110   (intintobjargproc)PyCdunifVariableObject_ass_slice,   /*sq_ass_slice*/
2111 };
2112
2113 static PyMappingMethods PyCdunifVariableObject_as_mapping = {
2114   (inquiry)PyCdunifVariableObject_length,               /*mp_length*/
2115   (binaryfunc)PyCdunifVariableObject_subscript,       /*mp_subscript*/
2116   (objobjargproc)PyCdunifVariableObject_ass_subscript,   /*mp_ass_subscript*/
2117 };
2118
2119 statichere PyTypeObject PyCdunifVariable_Type = {
2120   PyObject_HEAD_INIT(NULL)
2121   0,                 /*ob_size*/
2122   "CdunifVariable"/*tp_name*/
2123   sizeof(PyCdunifVariableObject),            /*tp_basicsize*/
2124   0,                 /*tp_itemsize*/
2125   /* methods */
2126   (destructor)PyCdunifVariableObject_dealloc, /*tp_dealloc*/
2127   0,                    /*tp_print*/
2128   (getattrfunc)PyCdunifVariable_GetAttribute, /*tp_getattr*/
2129   (setattrfunc)PyCdunifVariable_SetAttribute, /*tp_setattr*/
2130   0,                    /*tp_compare*/
2131   0,                    /*tp_repr*/
2132   0,                    /*tp_as_number*/
2133   &PyCdunifVariableObject_as_sequence,  /*tp_as_sequence*/
2134   &PyCdunifVariableObject_as_mapping,   /*tp_as_mapping*/
2135   0,                    /*tp_hash*/
2136 };
2137
2138
2139 /* Creator for CdunifFile objects */
2140
2141 static PyObject *
2142 CdunifFile(self, args)
2143      PyObject *self; /* Not used */
2144      PyObject *args;
2145 {
2146   char *filename;
2147   char *mode = NULL;
2148   char *history = NULL;
2149   PyCdunifFileObject *file;
2150
2151   if (!PyArg_ParseTuple(args, "s|ss:CdunifFile", &filename, &mode, &history))
2152     return NULL;
2153   if (mode == NULL)
2154     mode = "r";
2155   file = PyCdunifFile_Open(filename, mode);
2156   if (file == NULL) {
2157     Cdunif_seterror();
2158     return NULL;
2159   }
2160   if (history != NULL)
2161     PyCdunifFile_AddHistoryLine(file, history);
2162   return (PyObject *)file;
2163 }
2164
2165 /* Table of functions defined in the module */
2166
2167 static PyMethodDef Cdunif_methods[] = {
2168   {"CdunifFile",        CdunifFile, 1},
2169   {NULL,                NULL}           /* sentinel */
2170 };
2171
2172 /* Module initialization */
2173
2174 void
2175 initCdunif()
2176 {
2177   PyObject *m, *d;
2178   static void *PyCdunif_API[PyCdunif_API_pointers];
2179
2180   /* Initialize netcdf and cdunif variables */
2181   ncopts = 0;
2182   cuseterropts(CU_VERBOSE);
2183
2184   /* Initialize type object headers */
2185   PyCdunifFile_Type.ob_type = &PyType_Type;
2186   PyCdunifVariable_Type.ob_type = &PyType_Type;
2187
2188   /* Create the module and add the functions */
2189   m = Py_InitModule("Cdunif", Cdunif_methods);
2190
2191   /* Import the array module */
2192 #ifdef import_array
2193   import_array();
2194 #endif
2195
2196   /* Add error object the module */
2197   d = PyModule_GetDict(m);
2198   CdunifError = PyString_FromString("CdunifError");
2199   PyDict_SetItemString(d, "CdunifError", CdunifError);
2200
2201   /* Initialize C API pointer array and store in module */
2202   PyCdunif_API[PyCdunifFile_Type_NUM] = (void *)&PyCdunifFile_Type;
2203   PyCdunif_API[PyCdunifVariable_Type_NUM] = (void *)&PyCdunifVariable_Type;
2204   PyCdunif_API[PyCdunifFile_Open_NUM] = (void *)&PyCdunifFile_Open;
2205   PyCdunif_API[PyCdunifFile_Close_NUM] = (void *)&PyCdunifFile_Close;
2206   PyCdunif_API[PyCdunifFile_Sync_NUM] = (void *)&PyCdunifFile_Sync;
2207   PyCdunif_API[PyCdunifFile_CreateDimension_NUM] =
2208     (void *)&PyCdunifFile_CreateDimension;
2209   PyCdunif_API[PyCdunifFile_CreateVariable_NUM] =
2210     (void *)&PyCdunifFile_CreateVariable;
2211   PyCdunif_API[PyCdunifFile_GetVariable_NUM] =
2212     (void *)&PyCdunifFile_GetVariable;
2213   PyCdunif_API[PyCdunifVariable_GetRank_NUM] =
2214     (void *)&PyCdunifVariable_GetRank;
2215   PyCdunif_API[PyCdunifVariable_GetShape_NUM] =
2216     (void *)&PyCdunifVariable_GetShape;
2217   PyCdunif_API[PyCdunifVariable_Indices_NUM] =
2218     (void *)&PyCdunifVariable_Indices;
2219   PyCdunif_API[PyCdunifVariable_ReadAsArray_NUM] =
2220     (void *)&PyCdunifVariable_ReadAsArray;
2221   PyCdunif_API[PyCdunifVariable_ReadAsString_NUM] =
2222     (void *)&PyCdunifVariable_ReadAsString;
2223   PyCdunif_API[PyCdunifVariable_WriteArray_NUM] =
2224     (void *)&PyCdunifVariable_WriteArray;
2225   PyCdunif_API[PyCdunifVariable_WriteString_NUM] =
2226     (void *)&PyCdunifVariable_WriteString;
2227   PyCdunif_API[PyCdunifFile_GetAttribute_NUM] =
2228     (void *)&PyCdunifFile_GetAttribute;
2229   PyCdunif_API[PyCdunifFile_SetAttribute_NUM] =
2230     (void *)&PyCdunifFile_SetAttribute;
2231   PyCdunif_API[PyCdunifFile_SetAttributeString_NUM] =
2232     (void *)&PyCdunifFile_SetAttributeString;
2233   PyCdunif_API[PyCdunifVariable_GetAttribute_NUM] =
2234     (void *)&PyCdunifVariable_GetAttribute;
2235   PyCdunif_API[PyCdunifVariable_SetAttribute_NUM] =
2236     (void *)&PyCdunifVariable_SetAttribute;
2237   PyCdunif_API[PyCdunifVariable_SetAttributeString_NUM] =
2238     (void *)&PyCdunifVariable_SetAttributeString;
2239   PyCdunif_API[PyCdunifFile_AddHistoryLine_NUM] =
2240     (void *)&PyCdunifFile_AddHistoryLine;
2241   PyDict_SetItemString(d, "_C_API",
2242                        PyCObject_FromVoidPtr((void *)PyCdunif_API, NULL));
2243
2244   /* Check for errors */
2245   if (PyErr_Occurred())
2246     Py_FatalError("can't initialize module Cdunif");
2247 }
Note: See TracBrowser for help on using the browser.