Back to index

enigmail  1.4.3
Classes | Public Member Functions | Public Attributes
Preprocessor.Preprocessor Class Reference

List of all members.

Classes

class  Error

Public Member Functions

def __init__
def setLineEndings
def setMarker
def clone
def write
def handleCommandLine
def getCommandLineParser
def handleLine
def do_define
def do_undef
def ensure_not_else
def do_if
def do_ifdef
def do_ifndef
def do_else
def do_elif
def do_elifdef
def do_elifndef
def do_endif
def do_expand
def do_literal
def do_filter
def do_unfilter
def filter_emptyLines
def filter_slashslash
def filter_spaces
def filter_substitution
def filter_attemptSubstitution
def do_include
def do_includesubst
def do_error

Public Attributes

 context
 disableLevel
 ifStates
 checkLineNumbers
 writtenLines
 filters
 cmds
 out
 LE
 varsubst
 marker
 instruction
 comment

Detailed Description

Class for preprocessing text files.

Definition at line 61 of file Preprocessor.py.


Constructor & Destructor Documentation

Definition at line 71 of file Preprocessor.py.

00071 
00072   def __init__(self):
00073     self.context = Expression.Context()
00074     for k,v in {'FILE': '',
00075                 'LINE': 0,
00076                 'DIRECTORY': os.path.abspath('.')}.iteritems():
00077       self.context[k] = v
00078     self.disableLevel = 0
00079     # ifStates can be
00080     #  0: hadTrue
00081     #  1: wantsTrue
00082     #  2: #else found
00083     self.ifStates = []
00084     self.checkLineNumbers = False
00085     self.writtenLines = 0
00086     self.filters = []
00087     self.cmds = {}
00088     for cmd, level in {'define': 0,
00089                        'undef': 0,
00090                        'if': sys.maxint,
00091                        'ifdef': sys.maxint,
00092                        'ifndef': sys.maxint,
00093                        'else': 1,
00094                        'elif': 1,
00095                        'elifdef': 1,
00096                        'elifndef': 1,
00097                        'endif': sys.maxint,
00098                        'expand': 0,
00099                        'literal': 0,
00100                        'filter': 0,
00101                        'unfilter': 0,
00102                        'include': 0,
00103                        'includesubst': 0,
00104                        'error': 0}.iteritems():
00105       self.cmds[cmd] = (level, getattr(self, 'do_' + cmd))
00106     self.out = sys.stdout
00107     self.setMarker('#')
00108     self.LE = '\n'
00109     self.varsubst = re.compile('@(?P<VAR>\w+)@', re.U)
  

Member Function Documentation

Create a clone of the current processor, including line ending
settings, marker, variable definitions, output stream.

Definition at line 125 of file Preprocessor.py.

00125 
00126   def clone(self):
00127     """
00128     Create a clone of the current processor, including line ending
00129     settings, marker, variable definitions, output stream.
00130     """
00131     rv = Preprocessor()
00132     rv.context.update(self.context)
00133     rv.setMarker(self.marker)
00134     rv.LE = self.LE
00135     rv.out = self.out
00136     return rv
  
def Preprocessor.Preprocessor.do_define (   self,
  args 
)

Definition at line 239 of file Preprocessor.py.

00239 
00240   def do_define(self, args):
00241     m = re.match('(?P<name>\w+)(?:\s(?P<value>.*))?', args, re.U)
00242     if not m:
00243       raise Preprocessor.Error(self, 'SYNTAX_DEF', args)
00244     val = 1
00245     if m.group('value'):
00246       val = m.group('value')
00247       try:
00248         val = int(val)
00249       except:
00250         pass
    self.context[m.group('name')] = val
def Preprocessor.Preprocessor.do_elif (   self,
  args 
)

Definition at line 322 of file Preprocessor.py.

00322 
00323   def do_elif(self, args):
00324     if self.disableLevel == 1:
00325       if self.ifStates[-1] == 1:
00326         self.do_if(args, replace=True)
00327     else:
      self.do_else(None, self.ifStates[-1])

Here is the call graph for this function:

def Preprocessor.Preprocessor.do_elifdef (   self,
  args 
)

Definition at line 328 of file Preprocessor.py.

00328 
00329   def do_elifdef(self, args):
00330     if self.disableLevel == 1:
00331       if self.ifStates[-1] == 1:
00332         self.do_ifdef(args, replace=True)
00333     else:
      self.do_else(None, self.ifStates[-1])

Here is the call graph for this function:

def Preprocessor.Preprocessor.do_elifndef (   self,
  args 
)

Definition at line 334 of file Preprocessor.py.

00334 
00335   def do_elifndef(self, args):
00336     if self.disableLevel == 1:
00337       if self.ifStates[-1] == 1:
00338         self.do_ifndef(args, replace=True)
00339     else:
      self.do_else(None, self.ifStates[-1])

Here is the call graph for this function:

def Preprocessor.Preprocessor.do_else (   self,
  args,
  ifState = 2 
)

Definition at line 314 of file Preprocessor.py.

00314 
00315   def do_else(self, args, ifState = 2):
00316     self.ensure_not_else()
00317     hadTrue = self.ifStates[-1] == 0
00318     self.ifStates[-1] = ifState # in-else
00319     if hadTrue:
00320       self.disableLevel = 1
00321       return
    self.disableLevel = 0

Here is the call graph for this function:

Here is the caller graph for this function:

def Preprocessor.Preprocessor.do_endif (   self,
  args 
)

Definition at line 340 of file Preprocessor.py.

00340 
00341   def do_endif(self, args):
00342     if self.disableLevel > 0:
00343       self.disableLevel -= 1
00344     if self.disableLevel == 0:
      self.ifStates.pop()
def Preprocessor.Preprocessor.do_error (   self,
  args 
)

Definition at line 457 of file Preprocessor.py.

00457 
00458   def do_error(self, args):
00459     raise Preprocessor.Error(self, 'Error: ', str(args))

def Preprocessor.Preprocessor.do_expand (   self,
  args 
)

Definition at line 346 of file Preprocessor.py.

00346 
00347   def do_expand(self, args):
00348     lst = re.split('__(\w+)__', args, re.U)
00349     do_replace = False
00350     def vsubst(v):
00351       if v in self.context:
00352         return str(self.context[v])
00353       return ''
00354     for i in range(1, len(lst), 2):
00355       lst[i] = vsubst(lst[i])
00356     lst.append('\n') # add back the newline
    self.write(reduce(lambda x, y: x+y, lst, ''))

Here is the call graph for this function:

def Preprocessor.Preprocessor.do_filter (   self,
  args 
)

Definition at line 359 of file Preprocessor.py.

00359 
00360   def do_filter(self, args):
00361     filters = [f for f in args.split(' ') if hasattr(self, 'filter_' + f)]
00362     if len(filters) == 0:
00363       return
00364     current = dict(self.filters)
00365     for f in filters:
00366       current[f] = getattr(self, 'filter_' + f)
00367     filterNames = current.keys()
00368     filterNames.sort()
00369     self.filters = [(fn, current[fn]) for fn in filterNames]
    return

Here is the caller graph for this function:

def Preprocessor.Preprocessor.do_if (   self,
  args,
  replace = False 
)

Definition at line 261 of file Preprocessor.py.

00261 
00262   def do_if(self, args, replace=False):
00263     if self.disableLevel and not replace:
00264       self.disableLevel += 1
00265       return
00266     val = None
00267     try:
00268       e = Expression.Expression(args)
00269       val = e.evaluate(self.context)
00270     except Exception:
00271       # XXX do real error reporting
00272       raise Preprocessor.Error(self, 'SYNTAX_ERR', args)
00273     if type(val) == str:
00274       # we're looking for a number value, strings are false
00275       val = False
00276     if not val:
00277       self.disableLevel = 1
00278     if replace:
00279       if val:
00280         self.disableLevel = 0
00281       self.ifStates[-1] = self.disableLevel
00282     else:
00283       self.ifStates.append(self.disableLevel)
    pass

Here is the caller graph for this function:

def Preprocessor.Preprocessor.do_ifdef (   self,
  args,
  replace = False 
)

Definition at line 284 of file Preprocessor.py.

00284 
00285   def do_ifdef(self, args, replace=False):
00286     if self.disableLevel and not replace:
00287       self.disableLevel += 1
00288       return
00289     if re.match('\W', args, re.U):
00290       raise Preprocessor.Error(self, 'INVALID_VAR', args)
00291     if args not in self.context:
00292       self.disableLevel = 1
00293     if replace:
00294       if args in self.context:
00295         self.disableLevel = 0
00296       self.ifStates[-1] = self.disableLevel
00297     else:
00298       self.ifStates.append(self.disableLevel)
    pass

Here is the caller graph for this function:

def Preprocessor.Preprocessor.do_ifndef (   self,
  args,
  replace = False 
)

Definition at line 299 of file Preprocessor.py.

00299 
00300   def do_ifndef(self, args, replace=False):
00301     if self.disableLevel and not replace:
00302       self.disableLevel += 1
00303       return
00304     if re.match('\W', args, re.U):
00305       raise Preprocessor.Error(self, 'INVALID_VAR', args)
00306     if args in self.context:
00307       self.disableLevel = 1
00308     if replace:
00309       if args not in self.context:
00310         self.disableLevel = 0
00311       self.ifStates[-1] = self.disableLevel
00312     else:
00313       self.ifStates.append(self.disableLevel)
    pass

Here is the caller graph for this function:

def Preprocessor.Preprocessor.do_include (   self,
  args 
)
Preprocess a given file.
args can either be a file name, or a file-like object.
Files should be opened, and will be closed after processing.

Definition at line 413 of file Preprocessor.py.

00413 
00414   def do_include(self, args):
00415     """
00416     Preprocess a given file.
00417     args can either be a file name, or a file-like object.
00418     Files should be opened, and will be closed after processing.
00419     """
00420     isName = type(args) == str or type(args) == unicode
00421     oldWrittenLines = self.writtenLines
00422     oldCheckLineNumbers = self.checkLineNumbers
00423     self.checkLineNumbers = False
00424     if isName:
00425       try:
00426         args = str(args)
00427         if not os.path.isabs(args):
00428           args = os.path.join(self.context['DIRECTORY'], args)
00429         args = open(args, 'rU')
00430       except:
00431         raise Preprocessor.Error(self, 'FILE_NOT_FOUND', str(args))
00432     self.checkLineNumbers = bool(re.search('\.(js|java)(?:\.in)?$', args.name))
00433     oldFile = self.context['FILE']
00434     oldLine = self.context['LINE']
00435     oldDir = self.context['DIRECTORY']
00436     if args.isatty():
00437       # we're stdin, use '-' and '' for file and dir
00438       self.context['FILE'] = '-'
00439       self.context['DIRECTORY'] = ''
00440     else:
00441       abspath = os.path.abspath(args.name)
00442       self.context['FILE'] = abspath
00443       self.context['DIRECTORY'] = os.path.dirname(abspath)
00444     self.context['LINE'] = 0
00445     self.writtenLines = 0
00446     for l in args:
00447       self.context['LINE'] += 1
00448       self.handleLine(l)
00449     args.close()
00450     self.context['FILE'] = oldFile
00451     self.checkLineNumbers = oldCheckLineNumbers
00452     self.writtenLines = oldWrittenLines
00453     self.context['LINE'] = oldLine
    self.context['DIRECTORY'] = oldDir

Here is the call graph for this function:

Here is the caller graph for this function:

def Preprocessor.Preprocessor.do_includesubst (   self,
  args 
)

Definition at line 454 of file Preprocessor.py.

00454 
00455   def do_includesubst(self, args):
00456     args = self.filter_substitution(args)
    self.do_include(args)

Here is the call graph for this function:

def Preprocessor.Preprocessor.do_literal (   self,
  args 
)

Definition at line 357 of file Preprocessor.py.

00357 
00358   def do_literal(self, args):
    self.write(args + self.LE)

Here is the call graph for this function:

def Preprocessor.Preprocessor.do_undef (   self,
  args 
)

Definition at line 251 of file Preprocessor.py.

00251 
00252   def do_undef(self, args):
00253     m = re.match('(?P<name>\w+)$', args, re.U)
00254     if not m:
00255       raise Preprocessor.Error(self, 'SYNTAX_DEF', args)
00256     if args in self.context:
      del self.context[args]
def Preprocessor.Preprocessor.do_unfilter (   self,
  args 
)

Definition at line 370 of file Preprocessor.py.

00370 
00371   def do_unfilter(self, args):
00372     filters = args.split(' ')
00373     current = dict(self.filters)
00374     for f in filters:
00375       if f in current:
00376         del current[f]
00377     filterNames = current.keys()
00378     filterNames.sort()
00379     self.filters = [(fn, current[fn]) for fn in filterNames]
    return

Definition at line 258 of file Preprocessor.py.

00258 
00259   def ensure_not_else(self):
00260     if len(self.ifStates) == 0 or self.ifStates[-1] == 2:
      sys.stderr.write('WARNING: bad nesting of #else\n')

Here is the caller graph for this function:

Definition at line 410 of file Preprocessor.py.

00410 
00411   def filter_attemptSubstitution(self, aLine):
    return self.filter_substitution(aLine, fatal=False)

Here is the call graph for this function:

def Preprocessor.Preprocessor.filter_emptyLines (   self,
  aLine 
)

Definition at line 384 of file Preprocessor.py.

00384 
00385   def filter_emptyLines(self, aLine):
00386     if aLine == '\n':
00387       return ''
    return aLine
def Preprocessor.Preprocessor.filter_slashslash (   self,
  aLine 
)

Definition at line 390 of file Preprocessor.py.

00390 
00391   def filter_slashslash(self, aLine):
00392     [aLine, rest] = aLine.split('//', 1)
00393     if rest:
00394       aLine += '\n'
    return aLine
def Preprocessor.Preprocessor.filter_spaces (   self,
  aLine 
)

Definition at line 397 of file Preprocessor.py.

00397 
00398   def filter_spaces(self, aLine):
    return re.sub(' +', ' ', aLine).strip(' ')
def Preprocessor.Preprocessor.filter_substitution (   self,
  aLine,
  fatal = True 
)

Definition at line 401 of file Preprocessor.py.

00401 
00402   def filter_substitution(self, aLine, fatal=True):
00403     def repl(matchobj):
00404       varname = matchobj.group('VAR')
00405       if varname in self.context:
00406         return str(self.context[varname])
00407       if fatal:
00408         raise Preprocessor.Error(self, 'UNDEFINED_VAR', varname)
00409       return ''
    return self.varsubst.sub(repl, aLine)

Here is the caller graph for this function:

def Preprocessor.Preprocessor.getCommandLineParser (   self,
  unescapeDefines = False 
)

Definition at line 171 of file Preprocessor.py.

00171 
00172   def getCommandLineParser(self, unescapeDefines = False):
00173     escapedValue = re.compile('".*"$')
00174     numberValue = re.compile('\d+$')
00175     def handleE(option, opt, value, parser):
00176       for k,v in os.environ.iteritems():
00177         self.context[k] = v
00178     def handleD(option, opt, value, parser):
00179       vals = value.split('=', 1)
00180       if len(vals) == 1:
00181         vals.append(1)
00182       elif unescapeDefines and escapedValue.match(vals[1]):
00183         # strip escaped string values
00184         vals[1] = vals[1][1:-1]
00185       elif numberValue.match(vals[1]):
00186         vals[1] = int(vals[1])
00187       self.context[vals[0]] = vals[1]
00188     def handleU(option, opt, value, parser):
00189       del self.context[value]
00190     def handleF(option, opt, value, parser):
00191       self.do_filter(value)
00192     def handleLE(option, opt, value, parser):
00193       self.setLineEndings(value)
00194     def handleMarker(option, opt, value, parser):
00195       self.setMarker(value)
00196     p = OptionParser()
00197     p.add_option('-I', action='append', type="string", default = [],
00198                  metavar="FILENAME", help='Include file')
00199     p.add_option('-E', action='callback', callback=handleE,
00200                  help='Import the environment into the defined variables')
00201     p.add_option('-D', action='callback', callback=handleD, type="string",
00202                  metavar="VAR[=VAL]", help='Define a variable')
00203     p.add_option('-U', action='callback', callback=handleU, type="string",
00204                  metavar="VAR", help='Undefine a variable')
00205     p.add_option('-F', action='callback', callback=handleF, type="string",
00206                  metavar="FILTER", help='Enable the specified filter')
00207     p.add_option('--line-endings', action='callback', callback=handleLE,
00208                  type="string", metavar="[cr|lr|crlf]",
00209                  help='Use the specified line endings [Default: OS dependent]')
00210     p.add_option('--marker', action='callback', callback=handleMarker,
00211                  type="string",
00212                  help='Use the specified marker instead of #')
00213     return p

Here is the call graph for this function:

Here is the caller graph for this function:

def Preprocessor.Preprocessor.handleCommandLine (   self,
  args,
  defaultToStdin = False 
)
Parse a commandline into this parser.
Uses OptionParser internally, no args mean sys.argv[1:].

Definition at line 156 of file Preprocessor.py.

00156 
00157   def handleCommandLine(self, args, defaultToStdin = False):
00158     """
00159     Parse a commandline into this parser.
00160     Uses OptionParser internally, no args mean sys.argv[1:].
00161     """
00162     p = self.getCommandLineParser()
00163     (options, args) = p.parse_args(args=args)
00164     includes = options.I
00165     if defaultToStdin and len(args) == 0:
00166       args = [sys.stdin]
00167     includes.extend(args)
00168     for f in includes:
00169       self.do_include(f)
00170     pass

Here is the call graph for this function:

def Preprocessor.Preprocessor.handleLine (   self,
  aLine 
)
Handle a single line of input (internal).

Definition at line 214 of file Preprocessor.py.

00214 
00215   def handleLine(self, aLine):
00216     """
00217     Handle a single line of input (internal).
00218     """
00219     m = self.instruction.match(aLine)
00220     if m:
00221       args = None
00222       cmd = m.group('cmd')
00223       try:
00224         args = m.group('args')
00225       except IndexError:
00226         pass
00227       if cmd not in self.cmds:
00228         raise Preprocessor.Error(self, 'INVALID_CMD', aLine)
00229       level, cmd = self.cmds[cmd]
00230       if (level >= self.disableLevel):
00231         cmd(args)
00232     elif self.disableLevel == 0 and not self.comment.match(aLine):
00233       self.write(aLine)
00234     pass

Here is the call graph for this function:

Here is the caller graph for this function:

def Preprocessor.Preprocessor.setLineEndings (   self,
  aLE 
)
Set the line endings to be used for output.

Definition at line 110 of file Preprocessor.py.

00110 
00111   def setLineEndings(self, aLE):
00112     """
00113     Set the line endings to be used for output.
00114     """
00115     self.LE = {'cr': '\x0D', 'lf': '\x0A', 'crlf': '\x0D\x0A'}[aLE]
  

Here is the caller graph for this function:

def Preprocessor.Preprocessor.setMarker (   self,
  aMarker 
)
Set the marker to be used for processing directives.
Used for handling CSS files, with pp.setMarker('%'), for example.

Definition at line 116 of file Preprocessor.py.

00116 
00117   def setMarker(self, aMarker):
00118     """
00119     Set the marker to be used for processing directives.
00120     Used for handling CSS files, with pp.setMarker('%'), for example.
00121     """
00122     self.marker = aMarker
00123     self.instruction = re.compile('%s(?P<cmd>[a-z]+)(?:\s(?P<args>.*))?$'%aMarker, re.U)
00124     self.comment = re.compile(aMarker, re.U)
  

Here is the caller graph for this function:

def Preprocessor.Preprocessor.write (   self,
  aLine 
)
Internal method for handling output.

Definition at line 137 of file Preprocessor.py.

00137 
00138   def write(self, aLine):
00139     """
00140     Internal method for handling output.
00141     """
00142     if self.checkLineNumbers:
00143       self.writtenLines += 1
00144       ln = self.context['LINE']
00145       if self.writtenLines != ln:
00146         self.out.write('//@line %(line)d "%(file)s"%(le)s'%{'line': ln,
00147                                                             'file': self.context['FILE'],
00148                                                             'le': self.LE})
00149         self.writtenLines = ln
00150     for f in self.filters:
00151       aLine = f[1](aLine)
00152     # ensure our line ending. Only need to handle \n, as we're reading
00153     # with universal line ending support, at least for files.
00154     aLine = re.sub('\n', self.LE, aLine)
00155     self.out.write(aLine)
  

Here is the caller graph for this function:


Member Data Documentation

Definition at line 83 of file Preprocessor.py.

Definition at line 86 of file Preprocessor.py.

Definition at line 123 of file Preprocessor.py.

Definition at line 72 of file Preprocessor.py.

Definition at line 77 of file Preprocessor.py.

Definition at line 85 of file Preprocessor.py.

Definition at line 82 of file Preprocessor.py.

Definition at line 122 of file Preprocessor.py.

Definition at line 107 of file Preprocessor.py.

Definition at line 121 of file Preprocessor.py.

Definition at line 105 of file Preprocessor.py.

Definition at line 108 of file Preprocessor.py.

Definition at line 84 of file Preprocessor.py.


The documentation for this class was generated from the following file: