~divmod-dev/divmod.org/trunk

« back to all changes in this revision

Viewing changes to Nevow/nevow/flat/ten.py

  • Committer: Jean-Paul Calderone
  • Date: 2014-06-29 20:33:04 UTC
  • mfrom: (2749.1.1 remove-epsilon-1325289)
  • Revision ID: exarkun@twistedmatrix.com-20140629203304-gdkmbwl1suei4m97
mergeĀ lp:~exarkun/divmod.org/remove-epsilon-1325289

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (c) 2004 Divmod.
2
 
# See LICENSE for details.
3
 
 
4
 
from __future__ import generators
5
 
 
6
 
import types
7
 
import warnings
8
 
from zope.interface import declarations, interface
9
 
 
10
 
import twisted.python.components as tpc
11
 
 
12
 
from nevow import inevow
13
 
from nevow import tags
14
 
from nevow import util
15
 
from nevow.inevow import ISerializable
16
 
 
17
 
"""
18
 
# NOTE:
19
 
# If you're about to import something from this module then you probably want
20
 
# to get it from nevow.flat instead. The idea is that flat's __init__.py may
21
 
# get smarter about the version of serialize/flatten/etc that is used,
22
 
# depending on what else is available. For instance, non-Twisted versions of
23
 
# these function may be imported into nevow.flat if Twisted is not installed.
24
 
"""
25
 
 
26
 
def registerFlattener(flattener, forType):
27
 
    """Register a function, 'flattener', which will be invoked when an object of type 'forType'
28
 
    is encountered in the stan dom. This function should return or yield strings, or objects
29
 
    for which there is also a flattener registered.
30
 
    
31
 
    flattener should take (original, ctx) where original is the object to flatten.
32
 
    """
33
 
    if type(flattener) is str or type(forType) is str:
34
 
        assert type(flattener) is str and type(forType) is str, "Must pass both strings or no strings to registerFlattener"
35
 
        flattener = util._namedAnyWithBuiltinTranslation(flattener)
36
 
        forType = util._namedAnyWithBuiltinTranslation(forType)
37
 
 
38
 
    if not isinstance(forType, interface.InterfaceClass):
39
 
        forType = declarations.implementedBy(forType)
40
 
        
41
 
    tpc.globalRegistry.register([forType], ISerializable, 'nevow.flat', flattener)
42
 
 
43
 
def getFlattener(original):
44
 
    """Get a flattener function with signature (ctx, original) for the object original.
45
 
    """
46
 
    return tpc.globalRegistry.lookup1(declarations.providedBy(original), ISerializable, 'nevow.flat')
47
 
 
48
 
def getSerializer(obj):
49
 
    warnings.warn('getSerializer is deprecated; It has been renamed getFlattener.', stacklevel=2)
50
 
    return getFlattener(obj)
51
 
 
52
 
 
53
 
def partialflatten(context, obj):
54
 
    """Run a flattener on the object 'obj' in the context 'context'.
55
 
    
56
 
    The return results from this function will not necessarily be a string, but will probably
57
 
    need further processing.
58
 
    """
59
 
    flattener = getFlattener(obj)
60
 
    if flattener is not None:
61
 
        return flattener(obj, context)
62
 
 
63
 
    raise NotImplementedError(
64
 
        'There is no flattener function registered for object %r of type %s.' %
65
 
        (obj, type(obj)))
66
 
 
67
 
 
68
 
def serialize(obj, context):
69
 
    #warnings.warn('serialize is deprecated; it has been renamed partialflatten.', stacklevel=2)
70
 
    return partialflatten(context, obj)
71
 
 
72
 
 
73
 
def iterflatten(stan, ctx, writer, shouldYieldItem=None):
74
 
    """This is the main meat of the nevow renderer. End-user programmers should
75
 
    instead use either flatten or precompile.
76
 
    """
77
 
    # 'rest' is a list of generators.
78
 
    # initialize as one-element list of a one-element generator of 
79
 
    rest = [ iter([partialflatten(ctx, stan)]) ]
80
 
    straccum = []
81
 
    while rest:
82
 
        gen = rest.pop()
83
 
        for item in gen:
84
 
            if isinstance(item, str):
85
 
                straccum.append(item)
86
 
            elif isinstance(item, unicode):
87
 
                straccum.append(item.encode('utf8'))
88
 
            elif isinstance(item, (list, types.GeneratorType)):
89
 
                # stop iterating this generator and put it back on the stack
90
 
                # and start iterating the new item instead.
91
 
                rest.append(gen)
92
 
                rest.append(iter(item))
93
 
                break
94
 
            else:
95
 
                if straccum:
96
 
                    writer(tags.raw(''.join(straccum)))
97
 
                    del straccum[:]
98
 
                if shouldYieldItem is not None and shouldYieldItem(item):
99
 
                    replacement = []
100
 
                    yield item, replacement.append
101
 
                    rest.append(gen)
102
 
                    rest.append(iter([replacement]))
103
 
                    break
104
 
                else:
105
 
                    if ctx.precompile:
106
 
                        ## We're precompiling and this is an item which can't be calculated until render time
107
 
                        ## add it to the list in 'precompile'
108
 
                        writer(item)
109
 
                    else:
110
 
                        rest.append(gen)
111
 
                        rest.append(iter([partialflatten(ctx, item)]))
112
 
                        break
113
 
 
114
 
    if straccum:
115
 
        writer(tags.raw(''.join(straccum)))
116
 
 
117
 
 
118
 
def flatten(stan, ctx=None):
119
 
    """Given the stan and the optional context, return a string containing the
120
 
    representation of the tree in the given context.
121
 
    """
122
 
    if ctx is None:
123
 
        from nevow.context import RequestContext, PageContext
124
 
        from nevow.testutil import FakeRequest
125
 
        ctx = PageContext(tag=None, parent=RequestContext(tag=FakeRequest()))
126
 
        ctx.remember(None, inevow.IData)
127
 
    result = []
128
 
    list(iterflatten(stan, ctx, result.append))
129
 
    return tags.raw(''.join(result))
130
 
 
131
 
 
132
 
def precompile(stan, ctx=None):
133
 
    """Given the stan and the optional context, return a list of strings and
134
 
    Context instances, optimizing as much static content as possible into contiguous
135
 
    string runs.
136
 
 
137
 
    The Context instances will have Tag instances whose .children have also been
138
 
    precompiled.
139
 
    """
140
 
    from nevow.context import WovenContext
141
 
    newctx = WovenContext(precompile=True)
142
 
    if ctx is not None:
143
 
        macroFactory = inevow.IMacroFactory(ctx, None)
144
 
        if macroFactory is not None:
145
 
            newctx.remember(macroFactory, inevow.IMacroFactory)
146
 
    doc = []
147
 
    list(iterflatten(stan, newctx, doc.append))
148
 
    return doc
149