Kaydet (Commit) f2055ae4 authored tarafından Andrew M. Kuchling's avatar Andrew M. Kuchling

Remove Tools/modulator, a reference to it in the docs, and a screenshot of it.

(I asked the BDFL first, and he approved removing it.  The last actual bugfix
to Tools/modulator was in 2001; since then all changes have been search-and-replace:
string methods, whitespace fixes, etc.)
üst 1ce61360
......@@ -372,12 +372,7 @@ source distribution.
A more substantial example module is included in the Python source distribution
as :file:`Modules/xxmodule.c`. This file may be used as a template or simply
read as an example. The :program:`modulator.py` script included in the source
distribution or Windows install provides a simple graphical user interface for
declaring the functions and objects which a module should implement, and can
generate a template which can be filled in. The script lives in the
:file:`Tools/modulator/` directory; see the :file:`README` file there for more
information.
read as an example.
.. _compilation:
......
This diff was suppressed by a .gitattributes entry.
......@@ -25,9 +25,6 @@ i18n Tools for internationalization. pygettext.py
and msgfmt.py generates a binary message catalog
from a catalog in text format.
modulator Interactively generate boiler plate for an extension
module. Works easiest if you have Tk.
pynche A Tkinter-based color editor.
scripts A number of useful single-file programs, e.g. tabnanny.py
......
#
# Example input file for modulator if you don't have tk.
#
# You may also have to strip some imports out of modulator to make
# it work.
import genmodule
#
# Generate code for a simple object with a method called sample
o = genmodule.object()
o.name = 'simple object'
o.abbrev = 'simp'
o.methodlist = ['sample']
o.funclist = ['new']
#
# Generate code for an object that looks numberish
#
o2 = genmodule.object()
o2.name = 'number-like object'
o2.abbrev = 'nl'
o2.typelist = ['tp_as_number']
o2.funclist = ['new', 'tp_repr', 'tp_compare']
#
# Generate code for a method with a full complement of functions,
# some methods, accessible as sequence and allowing structmember.c type
# structure access as well.
#
o3 = genmodule.object()
o3.name = 'over-the-top object'
o3.abbrev = 'ot'
o3.methodlist = ['method1', 'method2']
o3.funclist = ['new', 'tp_dealloc', 'tp_print', 'tp_getattr', 'tp_setattr',
'tp_compare', 'tp_repr', 'tp_hash']
o3.typelist = ['tp_as_sequence', 'structure']
#
# Now generate code for a module that incorporates these object types.
# Also add the boilerplates for functions to create instances of each
# type.
#
m = genmodule.module()
m.name = 'sample'
m.abbrev = 'sample'
m.methodlist = ['newsimple', 'newnumberish', 'newott']
m.objects = [o, o2, o3]
fp = open('EXAMPLEmodule.c', 'w')
genmodule.write(fp, m)
fp.close()
This is release 1.2 of modulator, a generator of boilerplate code for
modules to be written in C.
Difference between 1.2 and 1.1: __doc__ templates are now generated
(thanks to Jim Fulton).
Difference between 1.1 and 1.0: the templates now use "new-style"
naming conventions. Many thanks to Chak Tan <tan@ee.rochester.edu> for
supplying them.
Usage when you have tk is *really* simple: start modulator, fill out
the forms specifying all the objects and methods, tell modulator
whether objects should also be accessible as sequences, etc and press
'generate code'. It will write a complete skeleton module for you.
Usage when you don't have tk is slightly more difficult. Look at
EXAMPLE.py for some details (to run, use "python EXAMPLE.py"). Don't
bother with EXAMPLE.py if you have Tkinter!!!
Oh yeah: you'll probably want to change Templates/copyright, or all
your code ends up as being copyrighted to CWI:-)
Let me know what you think,
Jack Jansen, jack@cwi.nl
# A ScrolledList widget feels like a list widget but also has a
# vertical scroll bar on its right. (Later, options may be added to
# add a horizontal bar as well, to make the bars disappear
# automatically when not needed, to move them to the other side of the
# window, etc.)
#
# Configuration options are passed to the List widget.
# A Frame widget is inserted between the master and the list, to hold
# the Scrollbar widget.
# Most methods calls are inherited from the List widget; Pack methods
# are redirected to the Frame widget however.
from Tkinter import *
from Tkinter import _cnfmerge
class ScrolledListbox(Listbox):
def __init__(self, master=None, cnf={}):
cnf = _cnfmerge(cnf)
fcnf = {}
vcnf = {'name': 'vbar',
Pack: {'side': 'right', 'fill': 'y'},}
for k in cnf.keys():
if type(k) == ClassType or k == 'name':
fcnf[k] = cnf[k]
del cnf[k]
self.frame = Frame(master, fcnf)
self.vbar = Scrollbar(self.frame, vcnf)
cnf[Pack] = {'side': 'left', 'fill': 'both', 'expand': 'yes'}
cnf['name'] = 'list'
Listbox.__init__(self, self.frame, cnf)
self['yscrollcommand'] = (self.vbar, 'set')
self.vbar['command'] = (self, 'yview')
# Copy Pack methods of self.frame -- hack!
for m in Pack.__dict__.keys():
if m[0] != '_' and m != 'config':
setattr(self, m, getattr(self.frame, m))
#include "Python.h"
static PyObject *ErrorObject;
/* ----------------------------------------------------- */
static char $abbrev$_$method$__doc__[] =
""
;
static PyObject *
$abbrev$_$method$(PyObject *self /* Not used */, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
/* List of methods defined in the module */
static struct PyMethodDef $abbrev$_methods[] = {
$methodlist$
{NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called init$name$) */
static char $name$_module_documentation[] =
""
;
void
init$name$()
{
PyObject *m, *d;
/* Create the module and add the functions */
m = Py_InitModule4("$name$", $abbrev$_methods,
$name$_module_documentation,
(PyObject*)NULL,PYTHON_API_VERSION);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
ErrorObject = PyString_FromString("$name$.error");
PyDict_SetItemString(d, "error", ErrorObject);
/* XXXX Add constants here */
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module $name$");
}
/* Declarations for objects of type $name$ */
typedef struct {
PyObject_HEAD
/* XXXX Add your own stuff here */
} $abbrev$object;
static PyTypeObject $Abbrev$type;
/* ---------------------------------------------------------------- */
static char $abbrev$_$method$__doc__[] =
""
;
static PyObject *
$abbrev$_$method$($abbrev$object *self, PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef $abbrev$_methods[] = {
$methodlist$
{NULL, NULL} /* sentinel */
};
/* ---------- */
static $abbrev$object *
new$abbrev$object()
{
$abbrev$object *self;
self = PyObject_NEW($abbrev$object, &$Abbrev$type);
if (self == NULL)
return NULL;
/* XXXX Add your own initializers here */
return self;
}
/* Code to access structure members by accessing attributes */
#include "structmember.h"
#define OFF(x) offsetof(XXXXobject, x)
static struct memberlist $abbrev$_memberlist[] = {
/* XXXX Add lines like { "foo", T_INT, OFF(foo), RO } */
{NULL} /* Sentinel */
};
static PyObject *
$abbrev$_getattr($abbrev$object *self, char *name)
{
PyObject *rv;
/* XXXX Add your own getattr code here */
rv = PyMember_Get((char *)/*XXXX*/0, $abbrev$_memberlist, name);
if (rv)
return rv;
PyErr_Clear();
return Py_FindMethod($abbrev$_methods, (PyObject *)self, name);
}
static int
$abbrev$_setattr($abbrev$object *self, char *name, PyObject *v)
{
/* XXXX Add your own setattr code here */
if ( v == NULL ) {
PyErr_SetString(PyExc_AttributeError, "Cannot delete attribute");
return -1;
}
return PyMember_Set((char *)/*XXXX*/0, $abbrev$_memberlist, name, v);
}
static char $Abbrev$type__doc__[] =
""
;
static PyTypeObject $Abbrev$type = {
PyObject_HEAD_INIT(&PyType_Type)
0, /*ob_size*/
"$name$", /*tp_name*/
sizeof($abbrev$object), /*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)$tp_dealloc$, /*tp_dealloc*/
(printfunc)$tp_print$, /*tp_print*/
(getattrfunc)$tp_getattr$, /*tp_getattr*/
(setattrfunc)$tp_setattr$, /*tp_setattr*/
(cmpfunc)$tp_compare$, /*tp_compare*/
(reprfunc)$tp_repr$, /*tp_repr*/
$tp_as_number$, /*tp_as_number*/
$tp_as_sequence$, /*tp_as_sequence*/
$tp_as_mapping$, /*tp_as_mapping*/
(hashfunc)$tp_hash$, /*tp_hash*/
(ternaryfunc)$tp_call$, /*tp_call*/
(reprfunc)$tp_str$, /*tp_str*/
/* Space for future expansion */
0L,0L,0L,0L,
$Abbrev$type__doc__ /* Documentation string */
};
/* End of code for $name$ objects */
/* -------------------------------------------------------- */
/* Code to access $name$ objects as mappings */
static int
$abbrev$_length($abbrev$object *self)
{
/* XXXX Return the size of the mapping */
}
static PyObject *
$abbrev$_subscript($abbrev$object *self, PyObject *key)
{
/* XXXX Return the item of self indexed by key */
}
static int
$abbrev$_ass_sub($abbrev$object *self, PyObject *v, PyObject *w)
{
/* XXXX Put w in self under key v */
return 0;
}
static PyMappingMethods $abbrev$_as_mapping = {
(inquiry)$abbrev$_length, /*mp_length*/
(binaryfunc)$abbrev$_subscript, /*mp_subscript*/
(objobjargproc)$abbrev$_ass_sub, /*mp_ass_subscript*/
};
/* -------------------------------------------------------- */
/* Code to access $name$ objects as numbers */
static PyObject *
$abbrev$_add($abbrev$object *v, $abbrev$object *w)
{
/* XXXX Add them */
}
static PyObject *
$abbrev$_sub($abbrev$object *v, $abbrev$object *w)
{
/* XXXX Subtract them */
}
static PyObject *
$abbrev$_mul($abbrev$object *v, $abbrev$object *w)
{
/* XXXX Multiply them */
}
static PyObject *
$abbrev$_div($abbrev$object *x, $abbrev$object *y)
{
/* XXXX Divide them */
}
static PyObject *
$abbrev$_mod($abbrev$object *x, $abbrev$object *y)
{
/* XXXX Modulo them */
}
static PyObject *
$abbrev$_divmod($abbrev$object *x, $abbrev$object *y)
{
/* XXXX Return 2-tuple with div and mod */
}
static PyObject *
$abbrev$_pow($abbrev$object *v, $abbrev$object *w, $abbrev$object *z)
{
/* XXXX */
}
static PyObject *
$abbrev$_neg($abbrev$object *v)
{
/* XXXX */
}
static PyObject *
$abbrev$_pos($abbrev$object *v)
{
/* XXXX */
}
static PyObject *
$abbrev$_abs($abbrev$object *v)
{
/* XXXX */
}
static int
$abbrev$_nonzero($abbrev$object *v)
{
/* XXXX Return 1 if non-zero */
}
static PyObject *
$abbrev$_invert($abbrev$object *v)
{
/* XXXX */
}
static PyObject *
$abbrev$_lshift($abbrev$object *v, $abbrev$object *w)
{
/* XXXX */
}
static PyObject *
$abbrev$_rshift($abbrev$object *v, $abbrev$object *w)
{
/* XXXX */
}
static PyObject *
$abbrev$_and($abbrev$object *v, $abbrev$object *w)
{
/* XXXX */
}
static PyObject *
$abbrev$_xor($abbrev$object *v, $abbrev$object *w)
{
/* XXXX */
}
static PyObject *
$abbrev$_or($abbrev$object *v, $abbrev$object *w)
{
/* XXXX */
}
static int
$abbrev$_coerce(PyObject **pv, PyObject **pw)
{
/* XXXX I haven't a clue... */
return 1;
}
static PyObject *
$abbrev$_int($abbrev$object *v)
{
/* XXXX */
}
static PyObject *
$abbrev$_long($abbrev$object *v)
{
/* XXXX */
}
static PyObject *
$abbrev$_float($abbrev$object *v)
{
/* XXXX */
}
static PyObject *
$abbrev$_oct($abbrev$object *v)
{
/* XXXX Return object as octal stringobject */
}
static PyObject *
$abbrev$_hex($abbrev$object *v)
{
/* XXXX Return object as hex stringobject */
}
static PyNumberMethods $abbrev$_as_number = {
(binaryfunc)$abbrev$_add, /*nb_add*/
(binaryfunc)$abbrev$_sub, /*nb_subtract*/
(binaryfunc)$abbrev$_mul, /*nb_multiply*/
(binaryfunc)$abbrev$_div, /*nb_divide*/
(binaryfunc)$abbrev$_mod, /*nb_remainder*/
(binaryfunc)$abbrev$_divmod, /*nb_divmod*/
(ternaryfunc)$abbrev$_pow, /*nb_power*/
(unaryfunc)$abbrev$_neg, /*nb_negative*/
(unaryfunc)$abbrev$_pos, /*nb_positive*/
(unaryfunc)$abbrev$_abs, /*nb_absolute*/
(inquiry)$abbrev$_nonzero, /*nb_nonzero*/
(unaryfunc)$abbrev$_invert, /*nb_invert*/
(binaryfunc)$abbrev$_lshift, /*nb_lshift*/
(binaryfunc)$abbrev$_rshift, /*nb_rshift*/
(binaryfunc)$abbrev$_and, /*nb_and*/
(binaryfunc)$abbrev$_xor, /*nb_xor*/
(binaryfunc)$abbrev$_or, /*nb_or*/
(coercion)$abbrev$_coerce, /*nb_coerce*/
(unaryfunc)$abbrev$_int, /*nb_int*/
(unaryfunc)$abbrev$_long, /*nb_long*/
(unaryfunc)$abbrev$_float, /*nb_float*/
(unaryfunc)$abbrev$_oct, /*nb_oct*/
(unaryfunc)$abbrev$_hex, /*nb_hex*/
};
/* ------------------------------------------------------- */
/* Code to handle accessing $name$ objects as sequence objects */
static int
$abbrev$_length($abbrev$object *self)
{
/* XXXX Return the size of the object */
}
static PyObject *
$abbrev$_concat($abbrev$object *self, PyObject *bb)
{
/* XXXX Return the concatenation of self and bb */
}
static PyObject *
$abbrev$_repeat($abbrev$object *self, int n)
{
/* XXXX Return a new object that is n times self */
}
static PyObject *
$abbrev$_item($abbrev$object *self, int i)
{
/* XXXX Return the i-th object of self */
}
static PyObject *
$abbrev$_slice($abbrev$object *self, int ilow, int ihigh)
{
/* XXXX Return the ilow..ihigh slice of self in a new object */
}
static int
$abbrev$_ass_item($abbrev$object *self, int i, PyObject *v)
{
/* XXXX Assign to the i-th element of self */
return 0;
}
static int
$abbrev$_ass_slice(PyListObject *self, int ilow, int ihigh, PyObject *v)
{
/* XXXX Replace ilow..ihigh slice of self with v */
return 0;
}
static PySequenceMethods $abbrev$_as_sequence = {
(inquiry)$abbrev$_length, /*sq_length*/
(binaryfunc)$abbrev$_concat, /*sq_concat*/
(intargfunc)$abbrev$_repeat, /*sq_repeat*/
(intargfunc)$abbrev$_item, /*sq_item*/
(intintargfunc)$abbrev$_slice, /*sq_slice*/
(intobjargproc)$abbrev$_ass_item, /*sq_ass_item*/
(intintobjargproc)$abbrev$_ass_slice, /*sq_ass_slice*/
};
/* -------------------------------------------------------------- */
static PyObject *
$abbrev$_call($abbrev$object *self, PyObject *args, PyObject *kwargs)
{
/* XXXX Return the result of calling self with argument args */
}
static int
$abbrev$_compare($abbrev$object *v, $abbrev$object *w)
{
/* XXXX Compare objects and return -1, 0 or 1 */
}
static void
$abbrev$_dealloc($abbrev$object *self)
{
/* XXXX Add your own cleanup code here */
PyMem_DEL(self);
}
static PyObject *
$abbrev$_getattr($abbrev$object *self, char *name)
{
/* XXXX Add your own getattr code here */
return Py_FindMethod($abbrev$_methods, (PyObject *)self, name);
}
static long
$abbrev$_hash($abbrev$object *self)
{
/* XXXX Return a hash of self (or -1) */
}
static int
$abbrev$_print($abbrev$object *self, FILE *fp, int flags)
{
/* XXXX Add code here to print self to fp */
return 0;
}
static PyObject *
$abbrev$_repr($abbrev$object *self)
{
PyObject *s;
/* XXXX Add code here to put self into s */
return s;
}
static int
$abbrev$_setattr($abbrev$object *self, char *name, PyObject *v)
{
/* Set attribute 'name' to value 'v'. v==NULL means delete */
/* XXXX Add your own setattr code here */
return -1;
}
static PyObject *
$abbrev$_str($abbrev$object *self)
{
PyObject *s;
/* XXXX Add code here to put self into s */
return s;
}
#! /usr/bin/env python
# A Python function that generates dialog boxes with a text message,
# optional bitmap, and any number of buttons.
# Cf. Ousterhout, Tcl and the Tk Toolkit, Figs. 27.2-3, pp. 269-270.
from Tkinter import *
mainWidget = None
def dialog(master, title, text, bitmap, default, *args):
# 1. Create the top-level window and divide it into top
# and bottom parts.
w = Toplevel(master, {'class': 'Dialog'})
w.title(title)
w.iconname('Dialog')
top = Frame(w, {'relief': 'raised', 'bd': 1,
Pack: {'side': 'top', 'fill': 'both'}})
bot = Frame(w, {'relief': 'raised', 'bd': 1,
Pack: {'side': 'bottom', 'fill': 'both'}})
# 2. Fill the top part with the bitmap and message.
msg = Message(top,
{'width': '3i',
'text': text,
'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
Pack: {'side': 'right', 'expand': 1,
'fill': 'both',
'padx': '3m', 'pady': '3m'}})
if bitmap:
bm = Label(top, {'bitmap': bitmap,
Pack: {'side': 'left',
'padx': '3m', 'pady': '3m'}})
# 3. Create a row of buttons at the bottom of the dialog.
buttons = []
i = 0
for but in args:
b = Button(bot, {'text': but,
'command': ('set', 'button', i)})
buttons.append(b)
if i == default:
bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
Pack: {'side': 'left', 'expand': 1,
'padx': '3m', 'pady': '2m'}})
b.lift()
b.pack ({'in': bd, 'side': 'left',
'padx': '2m', 'pady': '2m',
'ipadx': '2m', 'ipady': '1m'})
else:
b.pack ({'side': 'left', 'expand': 1,
'padx': '3m', 'pady': '3m',
'ipady': '2m', 'ipady': '1m'})
i = i+1
# 4. Set up a binding for <Return>, if there's a default,
# set a grab, and claim the focus too.
if default >= 0:
w.bind('<Return>',
lambda e, b=buttons[default], i=default:
(b.flash(),
b.setvar('button', i)))
oldFocus = w.tk.call('focus') # XXX
w.grab_set()
w.focus()
# 5. Wait for the user to respond, then restore the focus
# and return the index of the selected button.
w.waitvar('button')
w.destroy()
w.tk.call('focus', oldFocus) # XXX
return w.getint(w.getvar('button'))
def strdialog(master, title, text, bitmap, default, *args):
# 1. Create the top-level window and divide it into top
# and bottom parts.
w = Toplevel(master, {'class': 'Dialog'})
w.title(title)
w.iconname('Dialog')
top = Frame(w, {'relief': 'raised', 'bd': 1,
Pack: {'side': 'top', 'fill': 'both'}})
if args:
bot = Frame(w, {'relief': 'raised', 'bd': 1,
Pack: {'side': 'bottom', 'fill': 'both'}})
# 2. Fill the top part with the bitmap, message and input field.
if bitmap:
bm = Label(top, {'bitmap': bitmap,
Pack: {'side': 'left',
'padx': '3m', 'pady': '3m'}})
msg = Message(top,
{'width': '3i',
'text': text,
'font': '-Adobe-Times-Medium-R-Normal-*-180-*',
Pack: {'side': 'left',
'fill': 'both',
'padx': '3m', 'pady': '3m'}})
field = Entry(top,
{'relief':'sunken',
Pack:{'side':'left',
'fill':'x',
'expand':1,
'padx':'3m', 'pady':'3m'}})
# 3. Create a row of buttons at the bottom of the dialog.
buttons = []
i = 0
for but in args:
b = Button(bot, {'text': but,
'command': ('set', 'button', i)})
buttons.append(b)
if i == default:
bd = Frame(bot, {'relief': 'sunken', 'bd': 1,
Pack: {'side': 'left', 'expand': 1,
'padx': '3m', 'pady': '2m'}})
b.lift()
b.pack ({'in': bd, 'side': 'left',
'padx': '2m', 'pady': '2m',
'ipadx': '2m', 'ipady': '1m'})
else:
b.pack ({'side': 'left', 'expand': 1,
'padx': '3m', 'pady': '3m',
'ipady': '2m', 'ipady': '1m'})
i = i+1
# 4. Set up a binding for <Return>, if there's a default,
# set a grab, and claim the focus too.
if not args:
w.bind('<Return>', lambda arg, top=top: top.setvar('button', 0))
field.bind('<Return>', lambda arg, top=top: top.setvar('button', 0))
elif default >= 0:
w.bind('<Return>',
lambda e, b=buttons[default], i=default:
(b.flash(),
b.setvar('button', i)))
field.bind('<Return>',
lambda e, b=buttons[default], i=default:
(b.flash(),
b.setvar('button', i)))
oldFocus = w.tk.call('focus') # XXX
w.grab_set()
field.focus()
# 5. Wait for the user to respond, then restore the focus
# and return the index of the selected button.
w.waitvar('button')
v = field.get()
w.destroy()
w.tk.call('focus', oldFocus) # XXX
if args:
return v, w.getint(w.getvar('button'))
else:
return v
def message(str):
i = dialog(mainWidget, 'Message', str, '', 0, 'OK')
def askyn(str):
i = dialog(mainWidget, 'Question', str, '', 0, 'No', 'Yes')
return i
def askync(str):
i = dialog(mainWidget, 'Question', str, '', 0, 'Cancel', 'No', 'Yes')
return i-1
def askstr(str):
i = strdialog(mainWidget, 'Question', str, '', 0)
return i
def askfile(str): # XXXX For now...
i = strdialog(mainWidget, 'Question', str, '', 0)
return i
# The rest is the test program.
def _go():
i = dialog(mainWidget,
'Not Responding',
"The file server isn't responding right now; "
"I'll keep trying.",
'',
-1,
'OK')
print 'pressed button', i
i = dialog(mainWidget,
'File Modified',
'File "tcl.h" has been modified since '
'the last time it was saved. '
'Do you want to save it before exiting the application?',
'warning',
0,
'Save File',
'Discard Changes',
'Return To Editor')
print 'pressed button', i
print message('Test of message')
print askyn('Test of yes/no')
print askync('Test of yes/no/cancel')
print askstr('Type a string:')
print strdialog(mainWidget, 'Question', 'Another string:', '',
0, 'Save', 'Save as text')
def _test():
global mainWidget
mainWidget = Frame()
Pack.config(mainWidget)
start = Button(mainWidget,
{'text': 'Press Here To Start', 'command': _go})
start.pack()
endit = Button(mainWidget,
{'text': 'Exit',
'command': 'exit',
Pack: {'fill' : 'both'}})
mainWidget.mainloop()
if __name__ == '__main__':
_test()
#
# Genmodule - A python program to help you build (template) modules.
#
# Usage:
#
# o = genmodule.object()
# o.name = 'dwarve object'
# o.abbrev = 'dw'
# o.funclist = ['new', 'dealloc', 'getattr', 'setattr']
# o.methodlist = ['dig']
#
# m = genmodule.module()
# m.name = 'beings'
# m.abbrev = 'be'
# m.methodlist = ['newdwarve']
# m.objects = [o]
#
# genmodule.write(sys.stdout, m)
#
import sys
import os
import varsubst
error = 'genmodule.error'
#
# Names of functions in the object-description struct.
#
FUNCLIST = ['new', 'tp_dealloc', 'tp_print', 'tp_getattr', 'tp_setattr',
'tp_compare', 'tp_repr', 'tp_hash', 'tp_call', 'tp_str']
TYPELIST = ['tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'structure']
#
# writer is a base class for the object and module classes
# it contains code common to both.
#
class writer:
def __init__(self):
self._subst = None
def makesubst(self):
if not self._subst:
if not self.__dict__.has_key('abbrev'):
self.abbrev = self.name
self.Abbrev = self.abbrev[0].upper()+self.abbrev[1:]
subst = varsubst.Varsubst(self.__dict__)
subst.useindent(1)
self._subst = subst.subst
def addcode(self, name, fp):
ifp = self.opentemplate(name)
self.makesubst()
d = ifp.read()
d = self._subst(d)
fp.write(d)
def opentemplate(self, name):
for p in sys.path:
fn = os.path.join(p, name)
if os.path.exists(fn):
return open(fn, 'r')
fn = os.path.join(p, 'Templates')
fn = os.path.join(fn, name)
if os.path.exists(fn):
return open(fn, 'r')
raise error, 'Template '+name+' not found for '+self._type+' '+ \
self.name
class module(writer):
_type = 'module'
def writecode(self, fp):
self.addcode('copyright', fp)
self.addcode('module_head', fp)
for o in self.objects:
o.writehead(fp)
for o in self.objects:
o.writebody(fp)
new_ml = ''
for fn in self.methodlist:
self.method = fn
self.addcode('module_method', fp)
new_ml = new_ml + (
'{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
%(fn, self.abbrev, fn, self.abbrev, fn))
self.methodlist = new_ml
self.addcode('module_tail', fp)
class object(writer):
_type = 'object'
def __init__(self):
self.typelist = []
self.methodlist = []
self.funclist = ['new']
writer.__init__(self)
def writecode(self, fp):
self.addcode('copyright', fp)
self.writehead(fp)
self.writebody(fp)
def writehead(self, fp):
self.addcode('object_head', fp)
def writebody(self, fp):
new_ml = ''
for fn in self.methodlist:
self.method = fn
self.addcode('object_method', fp)
new_ml = new_ml + (
'{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
%(fn, self.abbrev, fn, self.abbrev, fn))
self.methodlist = new_ml
self.addcode('object_mlist', fp)
# Add getattr if we have methods
if self.methodlist and not 'tp_getattr' in self.funclist:
self.funclist.insert(0, 'tp_getattr')
for fn in FUNCLIST:
setattr(self, fn, '0')
#
# Special case for structure-access objects: put getattr in the
# list of functions but don't generate code for it directly,
# the code is obtained from the object_structure template.
# The same goes for setattr.
#
if 'structure' in self.typelist:
if 'tp_getattr' in self.funclist:
self.funclist.remove('tp_getattr')
if 'tp_setattr' in self.funclist:
self.funclist.remove('tp_setattr')
self.tp_getattr = self.abbrev + '_getattr'
self.tp_setattr = self.abbrev + '_setattr'
for fn in self.funclist:
self.addcode('object_'+fn, fp)
setattr(self, fn, '%s_%s'%(self.abbrev, fn[3:]))
for tn in TYPELIST:
setattr(self, tn, '0')
for tn in self.typelist:
self.addcode('object_'+tn, fp)
setattr(self, tn, '&%s_%s'%(self.abbrev, tn[3:]))
self.addcode('object_tail', fp)
def write(fp, obj):
obj.writecode(fp)
if __name__ == '__main__':
o = object()
o.name = 'dwarve object'
o.abbrev = 'dw'
o.funclist = ['new', 'tp_dealloc']
o.methodlist = ['dig']
m = module()
m.name = 'beings'
m.abbrev = 'be'
m.methodlist = ['newdwarve']
m.objects = [o]
write(sys.stdout, m)
This diff is collapsed.
#
# Variable substitution. Variables are $delimited$
#
import re
error = 'varsubst.error'
class Varsubst:
def __init__(self, dict):
self.dict = dict
self.prog = re.compile('\$([a-zA-Z0-9_]*)\$')
self.do_useindent = 0
def useindent(self, onoff):
self.do_useindent = onoff
def subst(self, s):
rv = ''
while 1:
m = self.prog.search(s)
if not m:
return rv + s
rv = rv + s[:m.start()]
s = s[m.end():]
if m.end() - m.start() == 2:
# Escaped dollar
rv = rv + '$'
s = s[2:]
continue
name = m.group(1)
if not self.dict.has_key(name):
raise error, 'No such variable: '+name
value = self.dict[name]
if self.do_useindent and '\n' in value:
value = self._modindent(value, rv)
rv = rv + value
def _modindent(self, value, old):
lastnl = old.rfind('\n', 0) + 1
lastnl = len(old) - lastnl
sub = '\n' + (' '*lastnl)
return re.sub('\n', sub, value)
def _test():
import sys
import os
sys.stderr.write('-- Copying stdin to stdout with environment map --\n')
c = Varsubst(os.environ)
c.useindent(1)
d = sys.stdin.read()
sys.stdout.write(c.subst(d))
sys.exit(1)
if __name__ == '__main__':
_test()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment