PythonEmbedded.py :  » Web-Frameworks » Python-Publishing-Accessories » PPA-0.2.7 » PPA » Template » Engines » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Python Publishing Accessories 
Python Publishing Accessories » PPA 0.2.7 » PPA » Template » Engines » PythonEmbedded.py
# $Id: PythonEmbedded.py,v 1.8 2005/05/03 09:42:06 corva Exp $

import string, re

single_re = r"'[^\n'\\]*(?:\\.[^\n'\\]*)*'"
double_re = r'"[^\n"\\]*(?:\\.[^\n"\\]*)*"'
triple_single_re = r"'''[^'\\]*(?:(?:\\.|'(?!''))[^'\\]*)*'''"
triple_double_re = r'"""[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""'
string_re = r'(%s|%s|%s|%s)' % (triple_single_re, triple_double_re,
                                single_re, double_re)

expr_match = re.compile(r'(?:[^\'"%%\n]|%%(?!>)|\\.|%s)+' % string_re,
                        re.S).match
suite_match = re.compile(r'(?:[^\'"%%]|%%(?!>)|\\.|%s)*' % string_re,
                         re.S).match
suite_check_start = re.compile(r'\s*\n').match
suite_check_end = re.compile(r'\n\s*$').search


class Error(Exception):
    def __init__(self, message='', filename='?', line=None):
        self.message = message
        self.filename = filename
        self.line = line
    def __str__(self):
        res = '%s in "%s"' % (self.message, self.filename)
        if self.line:
            res = '%s, line %d' % (res, self.line)
        return res

class ParseError(Error): pass
class CompileError(Error): pass


class Parser:
    
    def __init__(self, s, filename='?'):
        self.string = s
        self.filename = filename
        self.length = len(self.string)
    
    def process(self):
        self.cur_pos = 0
        self.parts = []
        self.append = self.parts.append
        state = 'html'
        while state!='EOF':
            state = getattr(self, 'process_'+state)()
        return self.parts
    
    def report_error(self, message, pos=None):
        if pos is None:
            pos = self.cur_pos
        line = self.string.count('\n', 0, pos) + 1
        raise ParseError(message, self.filename, line)
    
    def process_html(self):
        pos = self.string.find('<%', self.cur_pos)
        if pos<0:
            text = self.string[self.cur_pos:]
            if text:
                self.append(('html', text))
            return 'EOF'
        text = self.string[self.cur_pos:pos]
        if text:
            self.append(('html', text))
        if self.string[pos+2:pos+3]=='=':
            self.cur_pos = pos+3
            return 'expr'
        else:
            self.cur_pos = pos+2
            return 'suite'

    def process_expr(self):
        m = expr_match(self.string, self.cur_pos)
        if not m:
            self.report_error('Empty expression')
        pos = m.end()
        text = self.string[self.cur_pos:pos].strip()
        if not text:
            self.report_error('Empty expression')
        self.append(('expr', text))
        if self.length==pos:
            self.report_error('Unexpected EOF in embedded expression', pos)
        if self.string[pos:pos+2]!='%>':
            self.report_error('Embedded expression should end with "%>"', pos)
        self.cur_pos = pos+2
        return 'html'

    def process_suite(self):
        m = suite_match(self.string, self.cur_pos)
        assert m
        pos = m.end()
        suite = self.string[self.cur_pos:pos]
        if not suite_check_start(suite):
            self.report_error(
                'Embedded suite must start from new line after "...<%"',
                self.cur_pos)
        if not suite_check_end(suite):
            self.report_error(
                'Embedded suite must end with separate line containing "%>..."',
                pos)
        self.append(('suite', suite))
        if self.length==pos:
            self.report_error('Unexpected EOF in embedded suite', pos)
        assert self.string[pos:pos+2]=='%>', [self.string[pos:]]
        self.cur_pos = pos+2
        return 'html'
    

def compile_unicode(source, filename, method):
    '''Compile Python source represented as unicode object. All string
    litterals containing non-ASCII character will be unicode objects.'''
    import parser
    from token import ISNONTERMINAL,STRING
    source = source.encode('utf-8')  # parser complains about unicode source
    if method=='exec':
        ast = parser.suite(source)
    elif method=='eval':
        ast = parser.expr(source)
    else:
        raise ValueError('Unsupported compilation method: %r' % (method,))
    ast_seq = ast.tolist(True)
    # non-recursive method to walk through tree
    stack = [iter([ast_seq]).next]
    while stack:
        try:
            node = stack[-1]()
        except StopIteration:
            stack.pop()
            continue
        if ISNONTERMINAL(node[0]):
            stack.append(iter(node[1:]).next)
        elif node[0]==STRING:
            s = eval(node[1])
            try:
                s.decode('ascii')
            except UnicodeDecodeError:
                s = s.decode('utf-8')
            node[1] = repr(s)
    return parser.sequence2ast(ast_seq).compile(filename)


class Compiler:

    def __init__(self, source, filename):
        self.source = source
        self.filename = filename
        
    def process(self):
        parser = Parser(self.source, self.filename)
        self.content = content = []
        self.write = write = self.content.append
        for state, s in parser.process():
            getattr(self, 'process_'+state)(s)
        content.append('\n')
        source = ''.join(content)
        if isinstance(source, unicode):
            _compile = compile_unicode
        else:
            _compile = compile
        try:
            return _compile(source, self.filename, 'exec')
        except SyntaxError, exc:
            raise CompileError(exc.msg, self.filename, exc.lineno)

    def process_html(self, s):
        self.write('__PythonEmbedded_write__("""%s""");' % \
                   s.replace('"', '\\"'))

    def process_expr(self, s):
        self.write('__PythonEmbedded_write__(%s);' % s)

    def process_suite(self, s):
        self.write(s)


class Writer:
    """Wraps fp.write fuction, most file objects accept only string values
    for write"""
    
    def __init__(self, fp):
        self.write = fp.write
    def __call__(self, object):
        self.write('%s' % (object,))


class Engine:

    type = 'pyem'
        
    def compileString(self, source, template_name, get_template):
        c = Compiler(source, '.'.join((template_name, self.type)))
        return c.process()
    
    def compileFile(self, fp, template_name, get_template):
        return self.compileString(fp.read(), template_name, get_template)

    def interpret(self, program, fp, globals, locals, get_template):
        if fp is None:
            import sys
            fp = sys.stdout
        globals['__PythonEmbedded_write__'] = Writer(fp)
        exec program in globals, locals

    def dump(self, program):
        from marshal import dumps
        return dumps(program)

    def load(self, s):
        from marshal import loads
        return loads(s)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.