From a8d965d11c8e3046f9ffbb95e9556e33c4bc7447 Mon Sep 17 00:00:00 2001 From: berteh Date: Wed, 3 Sep 2014 14:52:21 +0200 Subject: [PATCH 1/4] added 'multiple' option to command line render --- pystache/commands/render.py | 32 ++++++++++++++++++----- pystache/tests/examples/multiple.json | 5 ++++ pystache/tests/examples/multiple.mustache | 3 +++ 3 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 pystache/tests/examples/multiple.json create mode 100644 pystache/tests/examples/multiple.mustache diff --git a/pystache/commands/render.py b/pystache/commands/render.py index 1a9c309d..9b2123d1 100644 --- a/pystache/commands/render.py +++ b/pystache/commands/render.py @@ -40,7 +40,7 @@ USAGE = """\ -%prog [-h] template context +%prog [options] template context Render a mustache template with the given context. @@ -57,11 +57,21 @@ def parse_args(sys_argv, usage): args = sys_argv[1:] parser = OptionParser(usage=usage) + parser.add_option("-m", "--multiple", dest="multiple", + help="render the template for each context children, writing output to FIELD file (with no warning if file already exists)", metavar="FIELD") options, args = parser.parse_args(args) - template, context = args + try: + template, context = args + except ValueError as e: + print('ERROR: %s\n' % e) + parser.print_help() + exit(1) + except UnboundLocalError as e: + print('ERROR: %s' % e) + exit(1) - return template, context + return template, context, options.multiple # TODO: verify whether the setup() method's entry_points argument @@ -70,7 +80,7 @@ def parse_args(sys_argv, usage): # http://packages.python.org/distribute/setuptools.html#automatic-script-creation # def main(sys_argv=sys.argv): - template, context = parse_args(sys_argv, USAGE) + template, context, multiple = parse_args(sys_argv, USAGE) if template.endswith('.mustache'): template = template[:-9] @@ -87,9 +97,17 @@ def main(sys_argv=sys.argv): except IOError: context = json.loads(context) - rendered = renderer.render(template, context) - print rendered - + if (multiple): + print ("multiple render on field %s" % multiple) + for c in context: + f_name = str(c[multiple]) + with open(f_name, "w") as f: # mode "wx" could be used to prevent overwriting, + pass IOError, adding "--force" option to override. + rendered = renderer.render(template, c) + f.write(rendered) + print ("%s done") % f_name + else: + rendered = renderer.render(template, context) + print rendered if __name__=='__main__': main() diff --git a/pystache/tests/examples/multiple.json b/pystache/tests/examples/multiple.json new file mode 100644 index 00000000..e1710602 --- /dev/null +++ b/pystache/tests/examples/multiple.json @@ -0,0 +1,5 @@ +[ + { "NO": 1, "TITLE": "Hello, World" }, + { "NO": 2, "TITLE": "Apple, Orange, and Banana" }, + { "NO": 3, "TITLE": "Thank you!" } +] \ No newline at end of file diff --git a/pystache/tests/examples/multiple.mustache b/pystache/tests/examples/multiple.mustache new file mode 100644 index 00000000..fe147ff9 --- /dev/null +++ b/pystache/tests/examples/multiple.mustache @@ -0,0 +1,3 @@ +{{#.}} +
{{NO}}: {{TITLE}}
+{{/.}} \ No newline at end of file From 76df37abe0658e93473358277b4ecc404271e52c Mon Sep 17 00:00:00 2001 From: berteh Date: Wed, 3 Sep 2014 15:13:45 +0200 Subject: [PATCH 2/4] use 'multiple' command line argument as key or filename --- pystache/commands/render.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pystache/commands/render.py b/pystache/commands/render.py index 9b2123d1..4cbfe59d 100644 --- a/pystache/commands/render.py +++ b/pystache/commands/render.py @@ -99,8 +99,11 @@ def main(sys_argv=sys.argv): if (multiple): print ("multiple render on field %s" % multiple) - for c in context: - f_name = str(c[multiple]) + for i,c in enumerate(context): + if c[multiple]: + f_name = str(c[multiple]) + else: + f_name = "%s%03d" (multiple, i) with open(f_name, "w") as f: # mode "wx" could be used to prevent overwriting, + pass IOError, adding "--force" option to override. rendered = renderer.render(template, c) f.write(rendered) From 3e13698092f6822b1c1b98437c540b28d9362c1a Mon Sep 17 00:00:00 2001 From: berteh Date: Wed, 3 Sep 2014 15:29:14 +0200 Subject: [PATCH 3/4] preserve extension of 'multiple' option filename on command line --- pystache/commands/render.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pystache/commands/render.py b/pystache/commands/render.py index 4cbfe59d..397387b8 100644 --- a/pystache/commands/render.py +++ b/pystache/commands/render.py @@ -27,7 +27,7 @@ # The optparse module is deprecated in Python 2.7 in favor of argparse. # However, argparse is not available in Python 2.6 and earlier. from optparse import OptionParser -import sys +import sys, os # We use absolute imports here to allow use of this script from its # location in source control (e.g. for development purposes). @@ -58,7 +58,10 @@ def parse_args(sys_argv, usage): parser = OptionParser(usage=usage) parser.add_option("-m", "--multiple", dest="multiple", - help="render the template for each context children, writing output to FIELD file (with no warning if file already exists)", metavar="FIELD") + help="""render the template for each context children, +writing output to KEY file (with no warning if file already exists). +If KEY is not a key of context children, then it is used as file output name, +and suffixed with a 3 digit incremental counter.""", metavar="KEY") options, args = parser.parse_args(args) try: @@ -99,11 +102,12 @@ def main(sys_argv=sys.argv): if (multiple): print ("multiple render on field %s" % multiple) + fileName, fileExt = os.path.splitext(multiple) for i,c in enumerate(context): - if c[multiple]: + if multiple in c: f_name = str(c[multiple]) - else: - f_name = "%s%03d" (multiple, i) + else: + f_name = "%s-%03d%s" % (fileName, i, fileExt) with open(f_name, "w") as f: # mode "wx" could be used to prevent overwriting, + pass IOError, adding "--force" option to override. rendered = renderer.render(template, c) f.write(rendered) From eb702c2a6197199fd06a6862d7d522d594a2b139 Mon Sep 17 00:00:00 2001 From: berteh Date: Wed, 3 Sep 2014 17:06:36 +0200 Subject: [PATCH 4/4] added support for CSV context from command-line --- pystache/commands/render.py | 28 +++++++++++++++++++++------- pystache/tests/examples/csv.test | 1 + pystache/tests/examples/multiple.csv | 4 ++++ 3 files changed, 26 insertions(+), 7 deletions(-) create mode 120000 pystache/tests/examples/csv.test create mode 100644 pystache/tests/examples/multiple.csv diff --git a/pystache/commands/render.py b/pystache/commands/render.py index 397387b8..f0eca076 100644 --- a/pystache/commands/render.py +++ b/pystache/commands/render.py @@ -28,6 +28,7 @@ # However, argparse is not available in Python 2.6 and earlier. from optparse import OptionParser import sys, os +import csv # We use absolute imports here to allow use of this script from its # location in source control (e.g. for development purposes). @@ -46,7 +47,7 @@ positional arguments: template A filename or template string. - context A filename or JSON string.""" + context A JSON string, or a JSON or CSV filename.""" def parse_args(sys_argv, usage): @@ -57,6 +58,9 @@ def parse_args(sys_argv, usage): args = sys_argv[1:] parser = OptionParser(usage=usage) + parser.add_option("-f", "--format", dest="format", + help="format of the context string of filename (choose from: 'json', 'csv'). Default is JSON, unless context is a filename with .csv extension.", + choices=("json","csv")) parser.add_option("-m", "--multiple", dest="multiple", help="""render the template for each context children, writing output to KEY file (with no warning if file already exists). @@ -74,7 +78,7 @@ def parse_args(sys_argv, usage): print('ERROR: %s' % e) exit(1) - return template, context, options.multiple + return template, context, options.format, options.multiple # TODO: verify whether the setup() method's entry_points argument @@ -83,7 +87,7 @@ def parse_args(sys_argv, usage): # http://packages.python.org/distribute/setuptools.html#automatic-script-creation # def main(sys_argv=sys.argv): - template, context, multiple = parse_args(sys_argv, USAGE) + template, context, c_format, multiple = parse_args(sys_argv, USAGE) if template.endswith('.mustache'): template = template[:-9] @@ -95,10 +99,20 @@ def main(sys_argv=sys.argv): except TemplateNotFoundError: pass - try: - context = json.load(open(context)) - except IOError: - context = json.loads(context) + if context.endswith(".csv") or (c_format and (c_format == "csv")): + try: + context = csv.DictReader(open(context, 'rb'))#, delimiter=',', quotechar='"') + except IOError: + print('ERROR: Could not parse context as CSV file. Check usage for input format options') + exit(-1) + else: + try: + context = json.load(open(context)) + except IOError: + context = json.loads(context) + except ValueError: #likely a not well-formed JSON string, or user forgot -f csv. + print('ERROR: Could not parse context as JSON file or text, check usage for input format options') + exit(1) if (multiple): print ("multiple render on field %s" % multiple) diff --git a/pystache/tests/examples/csv.test b/pystache/tests/examples/csv.test new file mode 120000 index 00000000..0d3c7d87 --- /dev/null +++ b/pystache/tests/examples/csv.test @@ -0,0 +1 @@ +multiple.csv \ No newline at end of file diff --git a/pystache/tests/examples/multiple.csv b/pystache/tests/examples/multiple.csv new file mode 100644 index 00000000..9cd3d004 --- /dev/null +++ b/pystache/tests/examples/multiple.csv @@ -0,0 +1,4 @@ +NO,TITLE +1,"Hello, World" +2,"Apple, Orange, and Banana" +3,"Thank you!" \ No newline at end of file