/Tools/modulator/genmodule.py

http://unladen-swallow.googlecode.com/ · Python · 160 lines · 110 code · 17 blank · 33 comment · 19 complexity · 0a8fe024b8ba829cfeb97fbc9f3ffbf6 MD5 · raw file

  1. #
  2. # Genmodule - A python program to help you build (template) modules.
  3. #
  4. # Usage:
  5. #
  6. # o = genmodule.object()
  7. # o.name = 'dwarve object'
  8. # o.abbrev = 'dw'
  9. # o.funclist = ['new', 'dealloc', 'getattr', 'setattr']
  10. # o.methodlist = ['dig']
  11. #
  12. # m = genmodule.module()
  13. # m.name = 'beings'
  14. # m.abbrev = 'be'
  15. # m.methodlist = ['newdwarve']
  16. # m.objects = [o]
  17. #
  18. # genmodule.write(sys.stdout, m)
  19. #
  20. import sys
  21. import os
  22. import varsubst
  23. error = 'genmodule.error'
  24. #
  25. # Names of functions in the object-description struct.
  26. #
  27. FUNCLIST = ['new', 'tp_dealloc', 'tp_print', 'tp_getattr', 'tp_setattr',
  28. 'tp_compare', 'tp_repr', 'tp_hash', 'tp_call', 'tp_str']
  29. TYPELIST = ['tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'structure']
  30. #
  31. # writer is a base class for the object and module classes
  32. # it contains code common to both.
  33. #
  34. class writer:
  35. def __init__(self):
  36. self._subst = None
  37. def makesubst(self):
  38. if not self._subst:
  39. if not self.__dict__.has_key('abbrev'):
  40. self.abbrev = self.name
  41. self.Abbrev = self.abbrev[0].upper()+self.abbrev[1:]
  42. subst = varsubst.Varsubst(self.__dict__)
  43. subst.useindent(1)
  44. self._subst = subst.subst
  45. def addcode(self, name, fp):
  46. ifp = self.opentemplate(name)
  47. self.makesubst()
  48. d = ifp.read()
  49. d = self._subst(d)
  50. fp.write(d)
  51. def opentemplate(self, name):
  52. for p in sys.path:
  53. fn = os.path.join(p, name)
  54. if os.path.exists(fn):
  55. return open(fn, 'r')
  56. fn = os.path.join(p, 'Templates')
  57. fn = os.path.join(fn, name)
  58. if os.path.exists(fn):
  59. return open(fn, 'r')
  60. raise error, 'Template '+name+' not found for '+self._type+' '+ \
  61. self.name
  62. class module(writer):
  63. _type = 'module'
  64. def writecode(self, fp):
  65. self.addcode('copyright', fp)
  66. self.addcode('module_head', fp)
  67. for o in self.objects:
  68. o.writehead(fp)
  69. for o in self.objects:
  70. o.writebody(fp)
  71. new_ml = ''
  72. for fn in self.methodlist:
  73. self.method = fn
  74. self.addcode('module_method', fp)
  75. new_ml = new_ml + (
  76. '{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
  77. %(fn, self.abbrev, fn, self.abbrev, fn))
  78. self.methodlist = new_ml
  79. self.addcode('module_tail', fp)
  80. class object(writer):
  81. _type = 'object'
  82. def __init__(self):
  83. self.typelist = []
  84. self.methodlist = []
  85. self.funclist = ['new']
  86. writer.__init__(self)
  87. def writecode(self, fp):
  88. self.addcode('copyright', fp)
  89. self.writehead(fp)
  90. self.writebody(fp)
  91. def writehead(self, fp):
  92. self.addcode('object_head', fp)
  93. def writebody(self, fp):
  94. new_ml = ''
  95. for fn in self.methodlist:
  96. self.method = fn
  97. self.addcode('object_method', fp)
  98. new_ml = new_ml + (
  99. '{"%s",\t(PyCFunction)%s_%s,\tMETH_VARARGS,\t%s_%s__doc__},\n'
  100. %(fn, self.abbrev, fn, self.abbrev, fn))
  101. self.methodlist = new_ml
  102. self.addcode('object_mlist', fp)
  103. # Add getattr if we have methods
  104. if self.methodlist and not 'tp_getattr' in self.funclist:
  105. self.funclist.insert(0, 'tp_getattr')
  106. for fn in FUNCLIST:
  107. setattr(self, fn, '0')
  108. #
  109. # Special case for structure-access objects: put getattr in the
  110. # list of functions but don't generate code for it directly,
  111. # the code is obtained from the object_structure template.
  112. # The same goes for setattr.
  113. #
  114. if 'structure' in self.typelist:
  115. if 'tp_getattr' in self.funclist:
  116. self.funclist.remove('tp_getattr')
  117. if 'tp_setattr' in self.funclist:
  118. self.funclist.remove('tp_setattr')
  119. self.tp_getattr = self.abbrev + '_getattr'
  120. self.tp_setattr = self.abbrev + '_setattr'
  121. for fn in self.funclist:
  122. self.addcode('object_'+fn, fp)
  123. setattr(self, fn, '%s_%s'%(self.abbrev, fn[3:]))
  124. for tn in TYPELIST:
  125. setattr(self, tn, '0')
  126. for tn in self.typelist:
  127. self.addcode('object_'+tn, fp)
  128. setattr(self, tn, '&%s_%s'%(self.abbrev, tn[3:]))
  129. self.addcode('object_tail', fp)
  130. def write(fp, obj):
  131. obj.writecode(fp)
  132. if __name__ == '__main__':
  133. o = object()
  134. o.name = 'dwarve object'
  135. o.abbrev = 'dw'
  136. o.funclist = ['new', 'tp_dealloc']
  137. o.methodlist = ['dig']
  138. m = module()
  139. m.name = 'beings'
  140. m.abbrev = 'be'
  141. m.methodlist = ['newdwarve']
  142. m.objects = [o]
  143. write(sys.stdout, m)