示例#1
0
 def get_items(node,
               branches_expr=args['branches_expr'],
               md=md):
     md._push(InstanceDict(node, md))
     items = branches_expr(md)
     md._pop()
     return items
    def test_getitem_2(self):
        # It does not break the acquisition chain of stored objects.

        from DocumentTemplate._DocumentTemplate import InstanceDict

        main = Item('main')
        main.sub = Item('sub')
        side = Item('side')
        side.here = Item('here')

        path = side.here.__of__(main)
        i_dict = InstanceDict(path, {}, getattr)
        self.assertEqual(main.sub, i_dict['sub'])
    def test_getitem(self):
        # The acquisition chain of the object a got method is bound to
        # does not contain the InstanceDict instance itself.

        # This is a test for the fix of the regression described in
        # https://github.com/zopefoundation/Zope/issues/292

        from DocumentTemplate._DocumentTemplate import InstanceDict

        inst = Item('a').__of__(Item('b'))
        i_dict = InstanceDict(inst, {}, getattr)

        for element in Acquisition.aq_chain(i_dict['method1'].__self__):
            self.assertNotIsInstance(element, InstanceDict)
示例#4
0
    def test_instancedict(self):
        context = ['context']
        here = ['here']
        request = {'request': 1}
        names = {'context': context, 'here': here, 'request': request}
        td = RestrictedTemplateDict()
        td.this = context
        td._push(request)
        td._push(InstanceDict(td.this, td))
        td._push(names)

        def func(td):
            return td.this

        result = func(td)
        self.assertTrue(result is context)
示例#5
0
def call_with_ns(f, ns, arg=1):
    td = Rtd()
    # prefer 'context' to 'here';  fall back to 'None'
    this = ns.get('context', ns.get('here'))
    td.this = this
    request = ns.get('request', {})
    if hasattr(request, 'taintWrapper'):
        request = request.taintWrapper()
    td._push(request)
    td._push(InstanceDict(td.this, td))
    td._push(ns)
    try:
        if arg == 2:
            return f(None, td)
        else:
            return f(td)
    finally:
        td._pop(3)
示例#6
0
    def test_taintwrapper(self):
        class Request(dict):
            def taintWrapper(self):
                return {'tainted': 'found'}

        context = ['context']
        here = ['here']
        request = Request().taintWrapper()
        names = {'context': context, 'here': here, 'request': request}
        td = RestrictedTemplateDict()
        td.this = context
        td._push(request)
        td._push(InstanceDict(td.this, td))
        td._push(names)

        def func(td):
            return td['tainted']

        found = func(td)
        self.assertEqual(found, 'found')
示例#7
0
    def _exec(self, bound_data, args, kw):
        # Cook if we haven't already
        self._cook_check()

        # If this object has no encoding set, we use the old default
        encoding = getattr(self, 'encoding', OLD_DEFAULT_ENCODING)

        # Get our caller's namespace, and set up our own.
        cns = bound_data['caller_namespace']
        ns = self._Bindings_ns_class()
        push = ns._push
        ns.guarded_getattr = None
        ns.guarded_getitem = None

        req = None
        kw_bind = kw
        if cns:
            # Someone called us.
            push(cns)
            ns.level = cns.level + 1
            ns.this = getattr(cns, 'this', None)
            # Get their bindings.  Copy the request reference
            # forward, and include older keyword arguments in the
            # current 'keyword_args' binding.
            try:
                last_bound = ns[('current bindings',)]
                last_req = last_bound.get('REQUEST', None)
                if last_req:
                    bound_data['REQUEST'] = last_req
                old_kw = last_bound['keyword_args']
                if old_kw:
                    kw_bind = old_kw.copy()
                    kw_bind.update(kw)
            except Exception:
                pass
        else:
            # We're first, so get the REQUEST.
            try:
                req = aq_acquire(self, 'REQUEST')
                if hasattr(req, 'taintWrapper'):
                    req = req.taintWrapper()
            except Exception:
                pass
            bound_data['REQUEST'] = req
            ns.this = bound_data['context']
        # Bind 'keyword_args' to the complete set of keyword arguments.
        bound_data['keyword_args'] = kw_bind

        # Push globals, initialized variables, REQUEST (if any),
        # and keyword arguments onto the namespace stack

        for nsitem in (self.globals, self._vars, req, kw):
            if nsitem:
                push(nsitem)

        # Push the 'container' (default), 'context', or nothing.
        bind_to = self._Bindings_client
        if bind_to in ('container', 'client'):
            push(InstanceDict(bound_data[bind_to], ns))

        # Push the name bindings, and a reference to grab later.
        push(bound_data)
        push({('current bindings',): bound_data})

        security = getSecurityManager()
        security.addContext(self)
        try:
            value = self.ZDocumentTemplate_beforeRender(ns, _marker)
            if value is _marker:
                try:
                    result = render_blocks(self._v_blocks, ns,
                                           encoding=encoding)
                except DTReturn as v:
                    result = v.v

                self.ZDocumentTemplate_afterRender(ns, result)
                return result
            else:
                return value
        finally:
            security.removeContext(self)
            # Clear the namespace, breaking circular references.
            while len(ns):
                ns._pop()
示例#8
0
def tpRenderTABLE(
    self,
    id,
    root_url,
    url,
    state,
    substate,
    diff,
    data,
    colspan,
    section,
    md,
    treeData,
    level=0,
    args=None,
    try_call_attr=try_call_attr,
    encoding=None,
):
    """Render a tree as a table"""
    encoding = encoding or 'latin-1'
    exp = 0

    if level >= 0:
        urlattr = args['url']
        if urlattr and hasattr(self, urlattr):
            tpUrl = try_call_attr(self, urlattr)
            url = (url and ('%s/%s' % (url, tpUrl))) or tpUrl
            root_url = root_url or tpUrl

    ptreeData = add_with_prefix(treeData, 'tree', args.get('prefix'))
    ptreeData['tree-item-url'] = url
    ptreeData['tree-level'] = level
    ptreeData['tree-item-expanded'] = 0

    output = data.append

    items = None
    if 'assume_children' in args and \
       args['assume_children'] and \
       substate is not state:
        # We should not compute children unless we have to.
        # See if we've been asked to expand our children.
        for i in range(len(substate)):
            sub = substate[i]
            if sub[0] == id:
                exp = i + 1
                break
        if not exp:
            items = 1

    get = md.guarded_getattr
    if get is None:
        get = getattr

    if items is None:
        if 'branches' in args and hasattr(self, args['branches']):
            items = get(self, args['branches'])
            items = items()
        elif 'branches_expr' in args:
            items = args['branches_expr'](md)

        if not items and 'leaves' in args:
            items = 1

    if items and items != 1:

        getitem = getattr(md, 'guarded_getitem', None)
        if getitem is not None:
            unauth = []
            for index in range(len(items)):
                try:
                    getitem(items, index)
                except ValidationError:
                    unauth.append(index)
            if unauth:
                if 'skip_unauthorized' in args and args['skip_unauthorized']:
                    items = list(items)
                    unauth.reverse()
                    for index in unauth:
                        del items[index]
                else:
                    raise ValidationError(unauth)

        if 'sort' in args:
            # Faster/less mem in-place sort
            if isinstance(items, tuple):
                items = list(items)
            sort = args['sort']
            size = range(len(items))
            for i in size:
                v = items[i]
                k = getattr(v, sort)
                try:
                    k = k()
                except Exception:
                    pass
                items[i] = (k, v)
            items.sort()
            for i in size:
                items[i] = items[i][1]

        if 'reverse' in args:
            items = list(items)  # Copy the list
            items.reverse()

    if isinstance(id, six.binary_type):
        diff.append(id.decode(encoding))
    else:
        diff.append(id)

    _td_colspan = '<td colspan="%s" style="white-space: nowrap"></td>'
    _td_single = '<td width="16" style="white-space: nowrap"></td>'

    sub = None
    if substate is state:
        output('<table cellspacing="0">\n')
        sub = substate[0]
        exp = items
    else:
        # Add prefix
        output('<tr>\n')

        # Add +/- icon
        if items:
            if level:
                if level > 3:
                    output(_td_colspan % (level - 1))
                elif level > 1:
                    output(_td_single * (level - 1))
                output(_td_single)
                output('\n')
            output('<td width="16" valign="top" style="white-space: nowrap">')
            for i in range(len(substate)):
                sub = substate[i]
                if sub[0] == id:
                    exp = i + 1
                    break

            s = encode_str(compress(json.dumps(diff)))  # bytes in ASCII enc.

            # For rendering the encoded state string in a URL under Python 3,
            # we must lose the "b" prefix by decoding
            if six.PY3:
                s = s.decode('ASCII')

            # Propagate extra args through tree.
            if 'urlparam' in args:
                param = args['urlparam']
                param = "%s&" % param
            else:
                param = ""

            if exp:
                ptreeData['tree-item-expanded'] = 1
                icon = ('<i title="Collapse..."'
                        ' class="fas fa-caret-down text-muted"></i>')
                output('<a name="%s" href="%s?%stree-c=%s#%s">%s</a>' %
                       (id, root_url, param, s, id, icon))
            else:
                icon = ('<i title="Expand..."'
                        ' class="fas fa-caret-right text-muted"></i>')
                output('<a name="%s" href="%s?%stree-e=%s#%s">%s</a>' %
                       (id, root_url, param, s, id, icon))
            output('</td>\n')

        else:
            if level > 2:
                output(_td_colspan % level)
            elif level > 0:
                output(_td_single * level)
            output(_td_single)
            output('\n')

        # add item text
        dataspan = colspan - level
        nowrap = (args.get('nowrap') and ' style="white-space: nowrap"') or ''
        output('<td%s%s valign="top" align="left">' %
               ((dataspan > 1 and (' colspan="%s"' % dataspan) or ''), nowrap))
        output(render_blocks(section, md, encoding=encoding))
        output('</td>\n</tr>\n')

    if exp:
        level = level + 1
        dataspan = colspan - level
        if level > 2:
            h = _td_colspan % level
        elif level > 0:
            h = _td_single * level
        else:
            h = ''

        if 'header' in args:
            doc = args['header']
            if doc in md:
                doc = md.getitem(doc, 0)
            else:
                doc = None
            if doc is not None:
                ds = (dataspan > 1 and (' colspan="%s"' % dataspan)) or ''
                output(
                    doc(
                        None,
                        md,
                        standard_html_header=(
                            '<tr>%s'
                            '<td width="16" style="white-space: nowrap"></td>'
                            '<td%s valign="top">' % (h, ds)),
                        standard_html_footer='</td></tr>',
                    ))

        if items == 1:
            # leaves
            if 'leaves' in args:
                doc = args['leaves']
                if doc in md:
                    doc = md.getitem(doc, 0)
                else:
                    doc = None
                if doc is not None:
                    ds = (dataspan > 1 and ' colspan="%s"' % dataspan) or ''
                    treeData['-tree-substate-'] = sub
                    ptreeData['tree-level'] = level
                    md._push(treeData)
                    try:
                        output(
                            doc(
                                None,
                                md,
                                standard_html_header=
                                ('<tr>%s<td '
                                 'width="16" style="white-space: nowrap"></td>'
                                 '<td%s valign="top">' % (h, ds)),
                                standard_html_footer='</td></tr>',
                            ))
                    finally:
                        md._pop(1)
        elif 'expand' in args:
            doc = args['expand']
            if doc in md:
                doc = md.getitem(doc, 0)
            else:
                doc = None
            if doc is not None:
                ds = (dataspan > 1 and ' colspan="%s"' % dataspan) or ''
                treeData['-tree-substate-'] = sub
                ptreeData['tree-level'] = level
                md._push(treeData)
                try:
                    output(
                        doc(
                            None,
                            md,
                            standard_html_header=(
                                '<tr>%s<td '
                                'width="16" style="white-space: nowrap"></td>'
                                '<td%s valign="top">' % (h, ds)),
                            standard_html_footer='</td></tr>',
                        ))
                finally:
                    md._pop(1)
        else:
            __traceback_info__ = sub, args, state, substate
            ids = {}
            for item in items:
                id = extract_id(item, args['id'])
                if len(sub) == 1:
                    sub.append([])
                substate = sub[1]
                ids[id] = 1
                md._push(InstanceDict(item, md))
                try:
                    data = tpRenderTABLE(item, id, root_url, url, state,
                                         substate, diff, data, colspan,
                                         section, md, treeData, level, args)
                finally:
                    md._pop()
                if not sub[1]:
                    del sub[1]

            ids = ids.__contains__
            for i in range(len(substate) - 1, -1):
                if not ids(substate[i][0]):
                    del substate[i]

        if 'footer' in args:
            doc = args['footer']
            if doc in md:
                doc = md.getitem(doc, 0)
            else:
                doc = None
            if doc is not None:
                ds = (dataspan > 1 and ' colspan="%s"' % dataspan) or ''
                output(
                    doc(
                        None,
                        md,
                        standard_html_header=(
                            '<tr>%s<td '
                            'width="16" style="white-space: nowrap"></td>'
                            '<td%s valign="top">' % (h, ds)),
                        standard_html_footer='</td></tr>',
                    ))

    del diff[-1]
    if not diff:
        output('</table>\n')

    return data
示例#9
0
def tpRender(self,
             md,
             section,
             args,
             try_call_attr=try_call_attr,
             encoding=None):
    """Render data organized as a tree.

    We keep track of open nodes using a cookie.  The cookie stored the
    tree state. State should be a tree represented like:

      []  # all closed
      ['eagle'], # eagle is open
      ['eagle'], ['jeep', [1983, 1985]]  # eagle, jeep, 1983 jeep and 1985 jeep

    where the items are object ids. The state will be pickled to a
    compressed and base64ed string that gets unencoded, uncompressed,
    and unpickled on the other side.

    Note that ids used in state need not be connected to urls, since
    state manipulation is internal to rendering logic.

    Note that to make unpickling safe, we use the MiniPickle module,
    that only creates safe objects
    """

    data = []

    id = extract_id(self, args['id'])

    try:
        # see if we are being run as a sub-document
        root = md['tree-root-url']
        url = md['tree-item-url']
        state = md['tree-state']
        diff = md['tree-diff']
        substate = md['-tree-substate-']
        colspan = md['tree-colspan']
        level = md['tree-level']

    except KeyError:
        # OK, we are a top-level invocation
        level = -1

        if 'collapse_all' in md:
            state = [id, []],
        elif 'expand_all' in md:
            if 'branches' in args:

                def get_items(node, branches=args['branches'], md=md):
                    get = md.guarded_getattr
                    if get is None:
                        get = getattr
                    items = get(node, branches)
                    return items()
            elif 'branches_expr' in args:

                def get_items(node,
                              branches_expr=args['branches_expr'],
                              md=md):
                    md._push(InstanceDict(node, md))
                    items = branches_expr(md)
                    md._pop()
                    return items

            state = [id, tpValuesIds(self, get_items, args)],
        else:
            if 'tree-s' in md:
                state = md['tree-s']
                state = decode_seq(state)
                try:
                    if state[0][0] != id:
                        state = [id, []],
                except IndexError:
                    state = [id, []],
            else:
                state = [id, []],

            if 'tree-e' in md:
                diff = decode_seq(md['tree-e'])
                apply_diff(state, diff, 1)

            if 'tree-c' in md:
                diff = decode_seq(md['tree-c'])
                apply_diff(state, diff, 0)

        colspan = tpStateLevel(state)
        substate = state
        diff = []

        url = ''
        root = md['URL']
        right_end = root.rfind('/')
        if right_end >= 0:
            root = root[right_end + 1:]

    treeData = {
        'tree-root-url': root,
        'tree-colspan': colspan,
        'tree-state': state
    }

    prefix = args.get('prefix')
    if prefix:
        for k, v in treeData.items():
            treeData[prefix + k[4:].replace('-', '_')] = v

    md._push(InstanceDict(self, md))
    md._push(treeData)

    try:
        tpRenderTABLE(self,
                      id,
                      root,
                      url,
                      state,
                      substate,
                      diff,
                      data,
                      colspan,
                      section,
                      md,
                      treeData,
                      level,
                      args,
                      encoding=encoding)
    finally:
        md._pop(2)

    if state is substate and not ('single' in args and args['single']):
        state = state or ([id], )
        state = encode_seq(state)
        md['RESPONSE'].setCookie('tree-s', state)

    return ''.join(data)