コード例 #1
0
ファイル: engine.py プロジェクト: sshyran/Zope
    def __call__(self, context, macros, tal=True, **options):
        if tal is False:
            return self.template.body

        # Swap out repeat dictionary for Chameleon implementation
        # and store wrapped dictionary in new variable -- this is
        # in turn used by the secure Python expression
        # implementation whenever a 'repeat' symbol is found
        kwargs = context.vars
        kwargs['wrapped_repeat'] = kwargs['repeat']
        kwargs['repeat'] = RepeatDict(context.repeat_vars)

        return self.template.render(**kwargs)
コード例 #2
0
def main():  # pylint:disable=too-many-locals,too-many-statements
    arg_parser = argparse.ArgumentParser(
        description="Render a single file with JSON data")
    arg_parser.add_argument('input', help="The input template")
    arg_parser.add_argument('output',
                            help="The output filename, or - for standard out.")
    arg_parser.add_argument(
        '--data',
        dest='data',
        help=
        "The path to a filename to read to get the data for template options.\n"
        "JSON, YAML or CSV can be used. If JSON or YAML, the options will be whatever was"
        " specified in the file, typically a dictionary or array."
        "If CSV, the first row should be a header row naming the fields, and the options"
        " will be a list of dictionaries with those keys")
    arg_parser.add_argument(
        '--repeat-on',
        dest='repeat_on',
        help="If given, a traversal path that specifies something that can be "
        "iterated; the template will be applied repeatedly to the elements.")
    arg_parser.add_argument(
        '--repeat-on-sequence-name',
        dest='repeat_on_sequence_name',
        help="If given along with --repeat-on, this name will be bound in"
        "the options dictionary as the sequence that --repeat-on is iterating")
    arg_parser.add_argument(
        '--repeat-on-name',
        dest='repeat_on_name',
        help=
        "The name of the element being iterated. REQUIRED if --repeat-on is given"
    )
    arg_parser.add_argument(
        '--repeat-as-iterable',
        dest='repeat_iter',
        action='store_true',
        default=False,
        help=
        "If given, wrap each item from --repeat-on as a one-element list. This makes "
        "it easy to convert templates to create multiple files and share the basic iteration code."
    )
    arg_parser.add_argument(
        '--repeat-filename-specific-path',
        dest='repeat_filename',
        help=
        "If given, a TAL path evaluated for each item being repeated. If found and true, "
        "used as a part of the filename, subject to mangling.")
    arg_parser.add_argument('--json', dest='data')
    arg_parser.add_argument('--encoding',
                            dest='encoding',
                            help="The encoding of the output file.")
    arg_parser.add_argument(
        '--repeat-exclude-field',
        dest='repeat_exclude_field',
        help=
        "If given, a field looked for in order to exclude the given element from "
        "the rendering process.")

    args = arg_parser.parse_args()

    # Must configure traversing;
    # other stuff might be convenient but slows down startup,
    # so add as use-cases arise
    # _configure( set_up_packages=('nti.appserver', 'nti.app.pyramid_zope') )
    _configure(set_up_packages=('z3c.ptcompat', ))
    # Turn zope.security back off, pointless in this context
    z3c.pt.pagetemplate.sys_modules = sys.modules

    class Lookup(object):
        auto_reload = False
        debug = True
        translate = ztranslate

    class View(object):
        context = None
        request = None

    renderer = ZPTTemplateRenderer(os.path.abspath(args.input), Lookup())
    system = {}
    system['view'] = View()
    system['request'] = None
    options = {}
    if args.data:
        # Mac Excel likes to save CSV files with Mac line endings (\r)
        # which is weird and breaks the parser unless universal newlines
        # is in effect.
        openers = {
            '.csv': ('rU', lambda x: list(csv.DictReader(x))),
            '.yaml': ('rb', yaml.load),
            '.json': ('rb', simplejson.load)
        }
        mode, func = openers[os.path.splitext(args.data)[1]]
        with open(args.data, mode) as data:
            options = func(data)

    encoding = args.encoding or 'utf-8'

    def _write(result, output):
        # The result of PT rendering is a unicode string.
        # If it contained actual non-ascii characters,
        # we need to pick an encoding on the way out.
        # Because we are in HTML/XML the safest thing to
        # do for an encoding that doesn't handle a given value
        # is to use an entity escape (however our default of utf8
        # should handle everything)
        with codecs.open(output,
                         'wb',
                         encoding=encoding,
                         errors='xmlcharrefreplace') as f:
            f.write(result)

    # It is useful to have the render time available to the templates
    # There doesn't seem to be a way to do this entirely in the templates
    # so we help out here.
    options['nti_render_time'] = datetime.datetime.now()

    if args.repeat_on:
        output_base, output_ext = os.path.splitext(args.output)

        repeat_on = tapi.traverse(options, args.repeat_on)
        if args.repeat_on_sequence_name:
            repeat_on = list(repeat_on)  # so multiple iterations work
            options[args.repeat_on_sequence_name] = repeat_on

        if args.repeat_exclude_field:
            # Filter out the elements we do not want and add the dict back in.
            exclude_field = args.repeat_exclude_field
            repeat_on = [x for x in repeat_on if exclude_field not in x]
            options[args.repeat_on_sequence_name] = repeat_on

        # Establish a repeat dict for the pages. This will be visible
        # as options/repeat, leaving the builtin repeat as specified.
        # (If our template class overrode _pt_get_context, we could
        # promote this to the top-level (builtin) scope (chameleon will
        # accept that, z3c.pt is the one that prevents it by wrapping
        # ALL keyword args in the options dict)).
        # When you specify the repeat_on_name, the RepeatItem will then be
        # available at 'options/repeat/$repeat_on_name', giving you access
        # to such things as 'index'.
        # NOTE: For that to work, we have to iterate across the returned
        # iterator, because the RepeatItem that's in the dict must stay in
        # sync, and it does this by peeking into the iterator itself.
        global_repeat = options['repeat'] = RepeatDict({})

        # register the repeat item...
        global_repeat(args.repeat_on_name, repeat_on)
        # ...get it...
        global_repeat_item = global_repeat[args.repeat_on_name]
        # ...now iterate on it
        global_repitition_iterator = iter(global_repeat_item)

        for repitition_value in global_repitition_iterator:
            i = global_repeat_item.index  # auto-advanced
            raw_val = repitition_value

            if args.repeat_iter:  # wrap if required
                repitition_value = [repitition_value]

            options_for_this_repitition = options.copy()
            options_for_this_repitition[args.repeat_on_name] = repitition_value

            result = renderer(options_for_this_repitition, system)

            # We avoiding rendering this for some reason; next.
            if not result or result.isspace():
                continue

            output_specific = None
            if args.repeat_filename:
                try:
                    output_specific = tapi.traverse(raw_val,
                                                    args.repeat_filename)
                    output_specific = output_specific.strip()
                    output_specific = output_specific.lower().replace(' ', '_')
                    output_specific = output_specific.replace(os.path.sep, '_')
                    if not output_specific:
                        raise ValueError()
                except (KeyError, TypeError, ValueError):
                    output_specific = None
            if output_specific is None:
                output_specific = str(i)

            output = output_base + os.path.extsep + output_specific + output_ext
            _write(result, output)
    else:
        result = renderer(options, system)
        _write(result, args.output)

    sys.exit(0)