4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * This is a new part of Blender.
25 * Contributor(s): Willian P. Germano
27 * ***** END GPL LICENSE BLOCK *****
30 #include "Text.h" /*This must come first*/
32 #include "BKE_library.h"
34 #include "BKE_global.h"
36 #include "BIF_drawtext.h"
37 #include "BIF_screen.h"
39 #include "BKE_suggestions.h"
40 #include "BLI_blenlib.h"
41 #include "DNA_screen_types.h"
42 #include "DNA_space_types.h"
43 #include "MEM_guardedalloc.h"
44 #include "gen_utils.h"
45 #include "gen_library.h"
46 #include "../BPY_extern.h"
48 #define EXPP_TEXT_MODE_FOLLOW TXT_FOLLOW
50 /*****************************************************************************/
51 /* Python API function prototypes for the Text module. */
52 /*****************************************************************************/
53 static PyObject *M_Text_New( PyObject * self, PyObject * args);
54 static PyObject *M_Text_Get( PyObject * self, PyObject * args );
55 static PyObject *M_Text_Load( PyObject * self, PyObject * value );
56 static PyObject *M_Text_unlink( PyObject * self, PyObject * args );
58 /*****************************************************************************/
59 /* The following string definitions are used for documentation strings. */
60 /* In Python these will be written to the console when doing a */
61 /* Blender.Text.__doc__ */
62 /*****************************************************************************/
63 static char M_Text_doc[] = "The Blender Text module\n\n";
65 static char M_Text_New_doc[] = "() - return a new Text object";
67 static char M_Text_Get_doc[] = "(name) - return the Text with name 'name', \
68 returns None if not found.\n If 'name' is not specified, \
69 it returns a list of all Texts in the\ncurrent scene.";
71 static char M_Text_Load_doc[] =
72 "(filename) - return text from file filename as a Text Object, \
73 returns None if not found.\n";
75 static char M_Text_unlink_doc[] =
76 "(text) - remove Text object 'text' from Blender";
78 /*****************************************************************************/
79 /* Python method structure definition for Blender.Text module: */
80 /*****************************************************************************/
81 struct PyMethodDef M_Text_methods[] = {
82 {"New", M_Text_New, METH_VARARGS, M_Text_New_doc},
83 {"Get", M_Text_Get, METH_VARARGS, M_Text_Get_doc},
84 {"get", M_Text_Get, METH_VARARGS, M_Text_Get_doc},
85 {"Load", M_Text_Load, METH_O, M_Text_Load_doc},
86 {"unlink", M_Text_unlink, METH_VARARGS, M_Text_unlink_doc},
91 /*****************************************************************************/
92 /* Python BPy_Text methods declarations: */
93 /*****************************************************************************/
94 static PyObject *Text_getFilename( BPy_Text * self );
95 static PyObject *Text_getNLines( BPy_Text * self );
96 static PyObject *Text_clear( BPy_Text * self );
97 static PyObject *Text_reset( BPy_Text * self );
98 static PyObject *Text_readline( BPy_Text * self );
99 static PyObject *Text_write( BPy_Text * self, PyObject * value );
100 static PyObject *Text_insert( BPy_Text * self, PyObject * value );
101 static PyObject *Text_set( BPy_Text * self, PyObject * args );
102 static PyObject *Text_asLines( BPy_Text * self );
103 static PyObject *Text_getCursorPos( BPy_Text * self );
104 static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args );
105 static PyObject *Text_suggest( BPy_Text * self, PyObject * args );
106 static PyObject *Text_showDocs( BPy_Text * self, PyObject * args );
108 /*****************************************************************************/
109 /* Python BPy_Text methods table: */
110 /*****************************************************************************/
111 static PyMethodDef BPy_Text_methods[] = {
112 /* name, method, flags, doc */
113 {"getName", ( PyCFunction ) GenericLib_getName, METH_NOARGS,
114 "() - Return Text Object name"},
115 {"getFilename", ( PyCFunction ) Text_getFilename, METH_VARARGS,
116 "() - Return Text Object filename"},
117 {"getNLines", ( PyCFunction ) Text_getNLines, METH_VARARGS,
118 "() - Return number of lines in text buffer"},
119 {"setName", ( PyCFunction ) GenericLib_setName_with_method, METH_VARARGS,
120 "(str) - Change Text Object name"},
121 {"clear", ( PyCFunction ) Text_clear, METH_NOARGS,
122 "() - Clear Text buffer"},
123 {"reset", ( PyCFunction ) Text_reset, METH_NOARGS,
124 "() - Moves the IO pointer back to the start of the Text buffer for reading"},
125 {"readline", ( PyCFunction ) Text_readline, METH_NOARGS,
126 "() - Reads a line of text from the buffer and returns it incrementing the internal IO pointer."},
127 {"write", ( PyCFunction ) Text_write, METH_O,
128 "(line) - Append string 'str' to Text buffer"},
129 {"insert", ( PyCFunction ) Text_insert, METH_O,
130 "(line) - Insert string 'str' to Text buffer at cursor location"},
131 {"set", ( PyCFunction ) Text_set, METH_VARARGS,
132 "(name, val) - Set attribute 'name' to value 'val'"},
133 {"asLines", ( PyCFunction ) Text_asLines, METH_NOARGS,
134 "() - Return text buffer as a list of lines"},
135 {"getCursorPos", ( PyCFunction ) Text_getCursorPos, METH_NOARGS,
136 "() - Return cursor position as (row, col) tuple"},
137 {"setCursorPos", ( PyCFunction ) Text_setCursorPos, METH_VARARGS,
138 "(row, col) - Set the cursor position to (row, col)"},
139 {"suggest", ( PyCFunction ) Text_suggest, METH_VARARGS,
140 "(list, prefix='') - Presents a list of suggestions. List is of strings, or tuples. Tuples must be of the form (name, type) where type is one of 'm', 'v', 'f', 'k' for module, variable, function and keyword respectively or '?' for other types"},
141 {"showDocs", ( PyCFunction ) Text_showDocs, METH_VARARGS,
142 "(docs) - Documentation string"},
143 {NULL, NULL, 0, NULL}
146 /*****************************************************************************/
147 /* Python Text_Type callback function prototypes: */
148 /*****************************************************************************/
149 static int Text_compare( BPy_Text * a, BPy_Text * b );
150 static PyObject *Text_repr( BPy_Text * self );
152 /*****************************************************************************/
153 /* Function: M_Text_New */
154 /* Python equivalent: Blender.Text.New */
155 /*****************************************************************************/
156 static PyObject *M_Text_New( PyObject * self, PyObject * args)
160 Text *bl_text; /* blender text object */
161 PyObject *py_text; /* python wrapper */
163 if( !PyArg_ParseTuple( args, "|si", &name, &follow ) )
164 return EXPP_ReturnPyObjError( PyExc_AttributeError,
165 "expected string and int arguments (or nothing)" );
167 bl_text = add_empty_text( name );
170 /* do not set user count because Text is already linked */
172 /* create python wrapper obj */
173 py_text = Text_CreatePyObject( bl_text );
175 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
176 "couldn't create Text Object in Blender" );
178 return EXPP_ReturnPyObjError( PyExc_MemoryError,
179 "couldn't create Text Object wrapper" );
182 bl_text->flags |= EXPP_TEXT_MODE_FOLLOW;
187 /*****************************************************************************/
188 /* Function: M_Text_Get */
189 /* Python equivalent: Blender.Text.Get */
190 /* Description: Receives a string and returns the text object */
191 /* whose name matches the string. If no argument is */
192 /* passed in, a list of all text names in the current */
193 /* scene is returned. */
194 /*****************************************************************************/
195 static PyObject *M_Text_Get( PyObject * self, PyObject * args )
200 if( !PyArg_ParseTuple( args, "|s", &name ) )
201 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
202 "expected string argument (or nothing)" ) );
204 txt_iter = G.main->text.first;
206 if( name ) { /* (name) - Search text by name */
208 PyObject *wanted_txt = NULL;
210 while( ( txt_iter ) && ( wanted_txt == NULL ) ) {
212 if( strcmp( name, txt_iter->id.name + 2 ) == 0 ) {
213 wanted_txt = Text_CreatePyObject( txt_iter );
216 txt_iter = txt_iter->id.next;
219 if( wanted_txt == NULL ) { /* Requested text doesn't exist */
221 PyOS_snprintf( error_msg, sizeof( error_msg ),
222 "Text \"%s\" not found", name );
223 return ( EXPP_ReturnPyObjError
224 ( PyExc_NameError, error_msg ) );
230 else { /* () - return a list of all texts in the scene */
232 PyObject *txtlist, *pyobj;
234 txtlist = PyList_New( BLI_countlist( &( G.main->text ) ) );
236 if( txtlist == NULL )
237 return ( EXPP_ReturnPyObjError( PyExc_MemoryError,
238 "couldn't create PyList" ) );
241 pyobj = Text_CreatePyObject( txt_iter );
245 return ( EXPP_ReturnPyObjError
247 "couldn't create PyString" ) );
249 PyList_SET_ITEM( txtlist, index, pyobj );
251 txt_iter = txt_iter->id.next;
259 /*****************************************************************************/
260 /* Function: M_Text_Load */
261 /* Python equivalent: Blender.Text.Load */
262 /* Description: Receives a filename and returns the text object */
263 /* created from the corresponding file. */
264 /*****************************************************************************/
265 static PyObject *M_Text_Load( PyObject * self, PyObject * value )
267 char *fname = PyString_AsString(value);
268 char fpath[FILE_MAXDIR + FILE_MAXFILE];
269 Text *txt_ptr = NULL;
270 unsigned int maxlen = FILE_MAXDIR + FILE_MAXFILE;
273 return ( EXPP_ReturnPyObjError( PyExc_TypeError,
274 "expected string argument" ) );
276 if (strlen(fname) > (maxlen - 1))
277 return EXPP_ReturnPyObjError (PyExc_AttributeError,
278 "text filename too long");
279 else if (!BLI_exists(fname))
280 return EXPP_ReturnPyObjError (PyExc_AttributeError,
281 "text file not found");
283 BLI_strncpy(fpath, fname, maxlen);
285 txt_ptr = add_text( fpath );
287 return EXPP_ReturnPyObjError( PyExc_IOError,
288 "couldn't load text" );
290 return Text_CreatePyObject(txt_ptr);
293 /*****************************************************************************/
294 /* Function: M_Text_unlink */
295 /* Python equivalent: Blender.Text.unlink */
296 /* Description: Removes the given Text object from Blender */
297 /*****************************************************************************/
298 static PyObject *M_Text_unlink( PyObject * self, PyObject * args )
303 if( !PyArg_ParseTuple( args, "O!", &Text_Type, &textobj ) )
304 return EXPP_ReturnPyObjError( PyExc_TypeError,
305 "expected a Text object as argument" );
307 text = ( ( BPy_Text * ) textobj )->text;
310 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
311 "this text was already unlinked!" );
313 BPY_clear_bad_scriptlinks( text );
314 BPY_free_pyconstraint_links( text );
315 free_text_controllers( text );
318 free_libblock( &G.main->text, text );
320 ( ( BPy_Text * ) textobj )->text = NULL;
325 /*****************************************************************************/
326 /* Function: Text_Init */
327 /*****************************************************************************/
328 PyObject *Text_Init( void )
332 if( PyType_Ready( &Text_Type ) < 0 )
336 Py_InitModule3( "Blender.Text", M_Text_methods, M_Text_doc );
338 return ( submodule );
341 /*****************************************************************************/
342 /* Function: Text_CreatePyObject */
343 /*****************************************************************************/
344 PyObject *Text_CreatePyObject( Text * txt )
348 pytxt = ( BPy_Text * ) PyObject_NEW( BPy_Text, &Text_Type );
351 return EXPP_ReturnPyObjError( PyExc_MemoryError,
352 "couldn't create BPy_Text PyObject" );
358 return ( PyObject * ) pytxt;
361 /*****************************************************************************/
362 /* Python BPy_Text methods: */
363 /*****************************************************************************/
364 static PyObject *Text_getFilename( BPy_Text * self )
366 if( self->text->name )
367 return PyString_FromString( self->text->name );
372 static PyObject *Text_getNLines( BPy_Text * self )
373 { /* text->nlines isn't updated in Blender (?) */
377 line = self->text->lines.first;
379 while( line ) { /* so we have to count them ourselves */
384 self->text->nlines = nlines; /* and update Blender, too (should we?) */
386 return PyInt_FromLong( nlines );
389 static PyObject *Text_clear( BPy_Text * self)
394 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
395 "This object isn't linked to a Blender Text Object" );
397 oldstate = txt_get_undostate( );
398 txt_set_undostate( 1 );
399 txt_sel_all( self->text );
400 txt_cut_sel( self->text );
401 txt_set_undostate( oldstate );
406 static PyObject *Text_reset( BPy_Text * self )
414 static PyObject *Text_readline( BPy_Text * self )
421 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
422 "This object isn't linked to a Blender Text Object" );
424 for (i=0, line=self->text->lines.first; i<self->iol && line; i++, line=line->next);
427 PyErr_SetString( PyExc_StopIteration, "End of buffer reached" );
428 return PyString_FromString( "" );
431 if (self->ioc > line->len)
432 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
433 "Line length exceeded, text may have changed while reading" );
435 tmpstr = PyString_FromString( line->line + self->ioc );
437 PyString_ConcatAndDel( &tmpstr, PyString_FromString("\n") );
445 static PyObject *Text_write( BPy_Text * self, PyObject * value )
447 char *str = PyString_AsString(value);
451 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
452 "This object isn't linked to a Blender Text Object" );
455 return EXPP_ReturnPyObjError( PyExc_TypeError,
456 "expected string argument" );
458 oldstate = txt_get_undostate( );
459 txt_insert_buf( self->text, str );
460 txt_move_eof( self->text, 0 );
461 txt_set_undostate( oldstate );
466 static PyObject *Text_insert( BPy_Text * self, PyObject * value )
468 char *str = PyString_AsString(value);
472 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
473 "This object isn't linked to a Blender Text Object" );
476 return EXPP_ReturnPyObjError( PyExc_TypeError,
477 "expected string argument" );
479 oldstate = txt_get_undostate( );
480 txt_insert_buf( self->text, str );
481 txt_set_undostate( oldstate );
486 static PyObject *Text_set( BPy_Text * self, PyObject * args )
491 if( !PyArg_ParseTuple( args, "si", &attr, &ival ) )
492 return EXPP_ReturnPyObjError( PyExc_TypeError,
493 "expected a string and an int as arguments" );
495 if( strcmp( "follow_cursor", attr ) == 0 ) {
497 self->text->flags |= EXPP_TEXT_MODE_FOLLOW;
499 self->text->flags &= EXPP_TEXT_MODE_FOLLOW;
505 static PyObject *Text_asLines( BPy_Text * self )
508 PyObject *list, *tmpstr;
511 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
512 "This object isn't linked to a Blender Text Object" );
514 line = self->text->lines.first;
515 list = PyList_New( 0 );
518 return EXPP_ReturnPyObjError( PyExc_MemoryError,
519 "couldn't create PyList" );
522 tmpstr = PyString_FromString( line->line );
523 PyList_Append( list, tmpstr );
531 static PyObject *Text_getCursorPos( BPy_Text * self )
539 return EXPP_ReturnPyObjError( PyExc_RuntimeError,
540 "This object isn't linked to a Blender Text Object" );
542 for (row=0,linep=text->lines.first; linep!=text->curl; linep=linep->next)
546 return Py_BuildValue( "ii", row, col );
549 static PyObject *Text_setCursorPos( BPy_Text * self, PyObject * args )
556 return EXPP_ReturnPyObjError(PyExc_RuntimeError,
557 "This object isn't linked to a Blender Text Object");
559 if (!PyArg_ParseTuple(args, "ii", &row, &col))
560 return EXPP_ReturnPyObjError(PyExc_TypeError,
561 "expected two ints as arguments.");
563 if (col>self->text->curl->len) col=self->text->curl->len;
565 oldstate = txt_get_undostate();
566 txt_move_to(self->text, row, col, 0);
567 txt_set_undostate(oldstate);
569 if (curarea->spacetype == SPACE_TEXT && (st=curarea->spacedata.first))
575 static PyObject *Text_suggest( BPy_Text * self, PyObject * args )
577 PyObject *item = NULL, *tup1 = NULL, *tup2 = NULL;
578 PyObject *list = NULL, *resl = NULL;
580 char *prefix = NULL, *name, type;
584 return EXPP_ReturnPyObjError(PyExc_RuntimeError,
585 "This object isn't linked to a Blender Text Object");
587 /* Parse args for a list of strings/tuples */
588 if (!PyArg_ParseTuple(args, "O!|s", &PyList_Type, &list, &prefix))
589 return EXPP_ReturnPyObjError(PyExc_TypeError,
590 "expected list of strings or tuples followed by an optional string");
592 if (curarea->spacetype != SPACE_TEXT)
593 return EXPP_ReturnPyObjError(PyExc_RuntimeError,
594 "Active space type is not text");
596 st = curarea->spacedata.first;
597 if (!st || !st->text)
598 return EXPP_ReturnPyObjError(PyExc_RuntimeError,
599 "Active text area has no Text object");
601 suggest_clear_list();
602 suggest_set_active(st->text);
603 list_len = PyList_Size(list);
605 for (i = 0; i < list_len; i++) {
606 item = PyList_GetItem(list, i);
608 if (PyString_Check(item)) {
609 name = PyString_AsString(item);
611 } else if (PyTuple_Check(item) && PyTuple_GET_SIZE(item) == 2) {
612 tup1 = PyTuple_GetItem(item, 0);
613 tup2 = PyTuple_GetItem(item, 1);
614 if (PyString_Check(tup1) && PyString_Check(tup2)) {
615 name = PyString_AsString(tup1);
616 type = PyString_AsString(tup2)[0];
618 return EXPP_ReturnPyObjError(PyExc_AttributeError,
619 "list must contain tuples of two strings only: (name, type)" );
621 return EXPP_ReturnPyObjError(PyExc_AttributeError,
622 "list must contain only individual strings or tuples of size 2" );
624 if (!strlen(name) || (type!='m' && type!='v' && type!='f' && type!='k' && type!='?'))
625 return EXPP_ReturnPyObjError(PyExc_AttributeError,
626 "names must be non-empty and types in ['m', 'v', 'f', 'k', '?']" );
628 suggest_add(name, type);
632 suggest_prefix(prefix);
633 scrarea_queue_redraw(curarea);
638 static PyObject *Text_showDocs( BPy_Text * self, PyObject * args )
644 return EXPP_ReturnPyObjError(PyExc_RuntimeError,
645 "This object isn't linked to a Blender Text Object");
647 if (!PyArg_ParseTuple(args, "s", &docs))
648 return EXPP_ReturnPyObjError( PyExc_TypeError,
649 "expected a string as argument" );
651 if (curarea->spacetype != SPACE_TEXT)
652 return EXPP_ReturnPyObjError(PyExc_RuntimeError,
653 "Active space type is not text");
655 st = curarea->spacedata.first;
656 if (!st || !st->text)
657 return EXPP_ReturnPyObjError(PyExc_RuntimeError,
658 "Active text area has no Text object");
660 suggest_set_active(st->text);
661 suggest_documentation(docs);
662 scrarea_queue_redraw(curarea);
667 /*****************************************************************************/
668 /* Function: Text_compare */
669 /* Description: This is a callback function for the BPy_Text type. It */
670 /* compares two Text_Type objects. Only the "==" and "!=" */
671 /* comparisons are meaninful. Returns 0 for equality and -1 if */
672 /* they don't point to the same Blender Text struct. */
673 /* In Python it becomes 1 if they are equal, 0 otherwise. */
674 /*****************************************************************************/
675 static int Text_compare( BPy_Text * a, BPy_Text * b )
677 return ( a->text == b->text ) ? 0 : -1;
680 /*****************************************************************************/
681 /* Function: Text_repr */
682 /* Description: This is a callback function for the BPy_Text type. It */
683 /* builds a meaninful string to represent text objects. */
684 /*****************************************************************************/
685 static PyObject *Text_repr( BPy_Text * self )
688 return PyString_FromFormat( "[Text \"%s\"]",
689 self->text->id.name + 2 );
691 return PyString_FromString( "[Text <deleted>]" );
694 /*****************************************************************************/
695 /* Python attributes get/set functions: */
696 /*****************************************************************************/
697 static PyObject *Text_getMode(BPy_Text * self)
699 return PyInt_FromLong( self->text->flags );
702 /*****************************************************************************/
703 /* Python attributes get/set structure: */
704 /*****************************************************************************/
705 static PyGetSetDef BPy_Text_getseters[] = {
706 GENERIC_LIB_GETSETATTR,
707 {"filename", (getter)Text_getFilename, (setter)NULL,
708 "text filename", NULL},
709 {"mode", (getter)Text_getMode, (setter)NULL,
710 "text mode flag", NULL},
711 {"nlines", (getter)Text_getNLines, (setter)NULL,
712 "number of lines", NULL},
713 {NULL,NULL,NULL,NULL,NULL} /* Sentinel */
716 /*****************************************************************************/
717 /* Python Text_Type structure definition: */
718 /*****************************************************************************/
719 PyTypeObject Text_Type = {
720 PyObject_HEAD_INIT( NULL )
722 "Blender Text", /* tp_name */
723 sizeof( BPy_Text ), /* tp_basicsize */
726 NULL, /* tp_dealloc */
728 NULL, /* tp_getattr */
729 NULL, /* tp_setattr */
730 ( cmpfunc ) Text_compare, /* tp_compare */
731 ( reprfunc ) Text_repr, /* tp_repr */
733 /* Method suites for standard classes */
735 NULL, /* PyNumberMethods *tp_as_number; */
736 NULL, /* PySequenceMethods *tp_as_sequence; */
737 NULL, /* PyMappingMethods *tp_as_mapping; */
739 /* More standard operations (here for binary compatibility) */
741 ( hashfunc ) GenericLib_hash, /* hashfunc tp_hash; */
742 NULL, /* ternaryfunc tp_call; */
743 NULL, /* reprfunc tp_str; */
744 NULL, /* getattrofunc tp_getattro; */
745 NULL, /* setattrofunc tp_setattro; */
747 /* Functions to access object as input/output buffer */
748 NULL, /* PyBufferProcs *tp_as_buffer; */
750 /*** Flags to define presence of optional/expanded features ***/
751 Py_TPFLAGS_DEFAULT, /* long tp_flags; */
753 NULL, /* char *tp_doc; Documentation string */
754 /*** Assigned meaning in release 2.0 ***/
755 /* call function for all accessible objects */
756 NULL, /* traverseproc tp_traverse; */
758 /* delete references to contained objects */
759 NULL, /* inquiry tp_clear; */
761 /*** Assigned meaning in release 2.1 ***/
762 /*** rich comparisons ***/
763 NULL, /* richcmpfunc tp_richcompare; */
765 /*** weak reference enabler ***/
766 0, /* long tp_weaklistoffset; */
768 /*** Added in release 2.2 ***/
770 NULL, /* getiterfunc tp_iter; */
771 NULL, /* iternextfunc tp_iternext; */
773 /*** Attribute descriptor and subclassing stuff ***/
774 BPy_Text_methods, /* struct PyMethodDef *tp_methods; */
775 NULL, /* struct PyMemberDef *tp_members; */
776 BPy_Text_getseters, /* struct PyGetSetDef *tp_getset; */
777 NULL, /* struct _typeobject *tp_base; */
778 NULL, /* PyObject *tp_dict; */
779 NULL, /* descrgetfunc tp_descr_get; */
780 NULL, /* descrsetfunc tp_descr_set; */
781 0, /* long tp_dictoffset; */
782 NULL, /* initproc tp_init; */
783 NULL, /* allocfunc tp_alloc; */
784 NULL, /* newfunc tp_new; */
785 /* Low-level free-memory routine */
786 NULL, /* freefunc tp_free; */
787 /* For PyObject_IS_GC */
788 NULL, /* inquiry tp_is_gc; */
789 NULL, /* PyObject *tp_bases; */
790 /* method resolution order */
791 NULL, /* PyObject *tp_mro; */
792 NULL, /* PyObject *tp_cache; */
793 NULL, /* PyObject *tp_subclasses; */
794 NULL, /* PyObject *tp_weaklist; */