PK 4@xHԬ( ( c2c.template-1.2.0-nspkg.pthimport sys, types, os;p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('c2c',));ie = os.path.exists(os.path.join(p,'__init__.py'));m = not ie and sys.modules.setdefault('c2c', types.ModuleType('c2c'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)
PK {^Gߏ8R= R= c2c/template.py# -*- coding: utf-8 -*-
# Copyright (c) 2011-2014, Camptocamp SA
# All rights reserved.
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# 1. Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# The views and conclusions contained in the software and documentation are those
# of the authors and should not be interpreted as representing official policies,
# either expressed or implied, of the FreeBSD Project.
import os
import sys
import traceback
import json
import yaml
from yaml.parser import ParserError
from argparse import ArgumentParser
from string import Formatter
from subprocess import CalledProcessError
try:
from subprocess import check_output
except ImportError: # pragma: nocover
from subprocess import Popen, PIPE
def check_output(cmd, cwd=None, stdin=None, stderr=None, shell=False): # noqa
"""Backwards compatible check_output"""
p = Popen(cmd, cwd=cwd, stdin=stdin, stderr=stderr, shell=shell, stdout=PIPE)
out, err = p.communicate()
return out
def main():
parser = ArgumentParser(
description='Used to run a template'
)
parser.add_argument(
'--engine', '-e', choices=['jinja', 'mako', 'template'], default='jinja',
help='the used template engine'
)
parser.add_argument(
'--vars', '-c', default='vars.yaml',
help="the YAML file defining the variables"
)
parser.add_argument(
'--section', action='store_true',
help="use the section (template specific)"
)
parser.add_argument(
'--files', nargs='*',
help="the files to interpret"
)
parser.add_argument(
'--get-vars', nargs='*', default=[],
help="the vars to get, can be MY_VAR=my_var"
)
parser.add_argument(
'--get-config', nargs='*',
help="generate a configuration file"
)
files_builder_help = \
"generate some files from a source file (first ARG), " \
"to files (second ARG, with format we can access to the value attribute), " \
"and get the value on iter on the variable referenced by the third argument"
parser.add_argument(
'--files-builder', nargs=3,
metavar='ARG', help=files_builder_help
)
options = parser.parse_args()
used_vars = read_vars(options.vars)
formatter = Formatter()
formatted = []
def format_walker(current_vars, path=None):
if isinstance(current_vars, basestring):
if path not in formatted:
attrs = formatter.parse(current_vars)
for _, attr, _, _ in attrs:
if attr is not None and attr not in formatted:
return current_vars, 1
formatted.append(path)
return current_vars.format(**used_vars), 0
return current_vars, 0
elif isinstance(current_vars, list):
formatteds = [
format_walker(var, "%s[%i]" % (path, index))
for index, var in enumerate(current_vars)
]
return [v for v, s in formatteds], sum([s for v, s in formatteds])
elif isinstance(current_vars, dict):
skip = 0
for key in current_vars.keys():
if path is None:
current_path = key
else:
current_path = "%s[%s]" % (path, key)
current_formatted = format_walker(current_vars[key], current_path)
current_vars[key] = current_formatted[0]
skip += current_formatted[1]
return current_vars, skip
else:
formatted.append(path)
return current_vars, 0
old_skip = 0
skip = -1
while old_skip != skip and skip != 0:
old_skip = skip
used_vars, skip = format_walker(used_vars)
for get_var in options.get_vars:
corresp = get_var.split('=')
if len(corresp) == 1:
corresp = (get_var.upper(), get_var)
if len(corresp) != 2: # pragma: nocover
print("ERROR the get variable '%s' has more than one '='." % (
get_var
))
exit(1)
print("%s=%r" % (corresp[0], used_vars[corresp[1]]))
if options.get_config is not None:
new_vars = {}
for v in options.get_config[1:]:
var_path = v.split('.')
value = used_vars
for key in var_path:
if key in value:
value = value[key]
else:
print("ERROR the variable '%s' don't exists." % v)
exit(1)
new_vars[v] = value
with open(options.get_config[0], 'wb') as file_open:
file_open.write(yaml.dump(new_vars))
if options.files_builder is not None:
var_path = options.files_builder[2].split('.')
values = used_vars
for key in var_path:
values = values[key]
if not isinstance(values, list): # pragma: nocover
print("ERROR the variable '%s': '%r' should be an array." % (
options.files_builder[2], values
))
for value in values:
file_vars = {}
file_vars.update(used_vars)
file_vars.update(value)
template = options.files_builder[0]
destination = options.files_builder[1].format(**value)
_proceed([[template, destination]], file_vars, options)
if options.files is not None:
files = [(f, '.'.join(f.split('.')[:-1])) for f in options.files]
_proceed(files, used_vars, options)
def get_path(value, path):
split_path = path.split(".")
parent = None
for element in split_path:
parent = value
value = parent[element]
return (parent, split_path[-1]), value
def set_path(item, value):
parent, element = item
parent[element] = value
def _proceed(files, used_vars, options):
if options.engine == 'jinja':
from bottle import jinja2_template as engine
bottle_template(files, used_vars, engine)
elif options.engine == 'mako':
from bottle import mako_template as engine
bottle_template(files, used_vars, engine)
elif options.engine == 'template':
for template, destination in files:
c2c_template = C2cTemplate(
template,
template,
used_vars
)
c2c_template.section = options.section
processed = unicode(c2c_template.substitute(), "utf8")
save(template, destination, processed)
try:
from z3c.recipe.filetemplate import Template
class C2cTemplate(Template): # pragma: nocover
def _get(self, section, option, start):
if self.section and section is not None:
return self.recipe[section][option]
else:
return self.recipe[option]
except ImportError:
class C2cTemplate:
def __init__(self, *args):
raise Exception("The egg 'z3c.recipe.filetemplate' is missing.")
def bottle_template(files, used_vars, engine):
for template, destination in files:
processed = engine(
template, **used_vars
)
save(template, destination, processed)
def save(template, destination, processed):
with open(destination, 'wb') as file_open:
file_open.write(processed.encode("utf-8"))
os.chmod(destination, os.stat(template).st_mode)
def read_vars(vars_file):
with open(vars_file, 'r') as file_open:
used = yaml.load(file_open.read())
current_vars = {}
if 'extends' in used:
current_vars = read_vars(used['extends'])
new_vars = used['vars']
if 'interpreted' in used:
interpreters = []
globs = {'__builtins__': __builtins__, 'os': os, 'sys': sys}
for key, interpreter in used['interpreted'].items():
if isinstance(interpreter, dict):
interpreter["name"] = key
if 'priority' not in interpreter:
interpreter["priority"] = 0 if key in ['json', 'yaml'] else 100
else:
interpreter = {
"name": key,
"vars": interpreter,
"priority": 0 if key in ['json', 'yaml'] else 100
}
interpreters.append(interpreter)
interpreters.sort(key=lambda v: -v["priority"])
for interpreter in interpreters:
for var_name in interpreter["vars"]:
try:
item, expression = get_path(new_vars, var_name)
except KeyError: # pragma: nocover
print("ERROR: Expression for key not found: %s" % var_name)
exit(1)
if "cmd" in interpreter:
cmd = interpreter["cmd"][:] # [:] to clone
cmd.append(expression)
try:
evaluated = check_output(cmd)
except OSError as e: # pragma: nocover
print("ERROR when running the expression '%r': %s" % (
expression, e
))
exit(1)
except CalledProcessError as e: # pragma: nocover
error = "ERROR when running the expression '%r': %s" % (
expression, e
)
print(error)
if interpreter.get("ignore_error", False):
evaluated = error
else:
exit(1)
elif interpreter["name"] == "python":
try:
evaluated = eval(expression, globs)
except: # pragma: nocover
error = "ERROR when evaluating %r expression %r as Python:\n%s" % (
var_name, expression, traceback.format_exc()
)
print(error)
if interpreter.get("ignore_error", False):
evaluated = error
else:
exit(1)
elif interpreter["name"] == 'bash':
try:
evaluated = check_output(expression, shell=True)
except OSError as e: # pragma: nocover
print("ERROR when running the expression '%r': %s" % (
expression, e
))
exit(1)
except CalledProcessError as e: # pragma: nocover
error = "ERROR when running the expression '%r': %s" % (
expression, e
)
print(error)
if interpreter.get("ignore_error", False):
evaluated = error
else:
exit(1)
elif interpreter["name"] == 'environment': # pragma: nocover
if expression is None:
evaluated = os.environ
else:
try:
evaluated = os.environ[expression]
except KeyError:
error = \
"ERROR when getting %r in environment variables, " \
"possible values are: %r" % (
expression, os.environ.keys()
)
print(error)
if interpreter.get("ignore_error", False):
evaluated = error
else:
exit(1)
elif interpreter["name"] == 'json':
try:
evaluated = json.loads(expression)
except ValueError as e: # pragma: nocover
error = "ERROR when evaluating %r expression %r as JSON: %s" % (
key, expression, e
)
print(error)
if interpreter.get("ignore_error", False):
evaluated = error
else:
exit(1)
elif interpreter["name"] == 'yaml':
try:
evaluated = yaml.load(expression)
except ParserError as e: # pragma: nocover
error = "ERROR when evaluating %r expression %r as YAML: %s" % (
key, expression, e
)
print(error)
if interpreter.get("ignore_error", False):
evaluated = error
else:
exit(1)
else: # pragma: nocover
print("Unknown interpreter name '{}'.".format(interpreter["name"]))
exit(1)
set_path(item, evaluated)
update_paths = []
for update_path in used.get("update_paths", []):
split_path = update_path.split(".")
for i in range(len(split_path)):
update_paths.append(".".join(split_path[:i + 1]))
update_vars(current_vars, new_vars, set(update_paths))
return current_vars
def update_vars(current_vars, new_vars, update_paths, path=None):
for key, value in new_vars.items():
if "." in key: # pragma: nocover
print("WARNING: the key '%s' has a dot" % key)
key_path = key if path is None else "%s.%s" % (path, key)
if key_path in update_paths:
if isinstance(value, dict) and isinstance(current_vars.get(key), dict):
update_vars(current_vars.get(key), value, update_paths, key_path)
elif isinstance(value, list) and isinstance(current_vars.get(key), list):
current_vars.get(key).extend(value)
else: # pragma: nocover
print("ERROR: Unable to update the path '%s', types '%r', '%r'." % (
key_path, type(value), type(current_vars.get(key))
))
else:
current_vars[key] = value
PK 4@xHJ#
#
, c2c.template-1.2.0.dist-info/DESCRIPTION.rstc2c.template
============
Supported template Jinja, Mako, Template.
Tools that collect some vars and get them to a template engine.
Supported template: `Jinja `_,
`Mako `_ and
`Template `_.
Use ``c2c-template --help`` to get the command line help.
Vars file
=========
The vars collector gets the vars from YAML files like this one:
.. code:: yaml
extends: inherit.yaml
vars:
string_var: a string
int_var: 42
interpreted_var: __import__('datetime').date.today()
combined_var: 'Today: {interpreted_var:%Y-%m-%d}'
facter_json: /usr/bin/facter --json
facter_yaml: /usr/bin/facter --yaml
pi: console.log(Math.PI.toPrecision(3))
obj:
v1: 1
v2: '2'
v3: [1, 2, 3]
interpreted:
python:
- interpreted_var
bash:
- facter_json
- facter_yaml
json:
- facter_json
yaml:
- facter_yaml
node:
vars: ["pi"]
cmd: ["node", "-e"]
update_path:
- obj
The ``inherit.yaml`` is an other file with the same syntax that will provide
initial vars.
The ``vars`` section is where we define the vars values, the YAML files
support typing, than ``42`` will be an integer.
The ``interpreted`` configuration to interpret some vars,
``python``, ``bash``, ``environ``, ``json``, ``yaml`` are predefined
interpreter, ``node`` is a custom interpreter.
The ``update_path`` is a list of '.'-separated paths that will be updated (for dicts)
or appended (for lists), instead of overwritten. The sub path will be implicitly added.
We can reuse predefined variables and format them (see ``combined_var``),
See: `str.format() `_.
Example of usage
================
Interpret variable in a template
--------------------------------
.. code:: bash
c2c-template --vars vars.yaml --engine jinja --files template.jinja
The result will be stored in a file named ``template``.
Get the vars
------------
It can be useful to get the variable outside.
.. code:: bash
`c2c-template --vars vars.yaml --get-vars INT_VAR=int_var string_var`
That will set the bash variable ``INT_VAR`` to 42, and ``STRING_VAR`` to 'a string'.
Get a configuration file
------------------------
.. code:: bash
c2c-template --vars vars.yaml --get-config config.yaml string-var int-var combined-var
Will create a file named ``config.yaml`` this:
.. code:: yaml
string-var: a string
int-var: 42
combined-var: Today: 2014-12-12
Build a set of file based on a template
---------------------------------------
Create the following vars file (``vars.yaml``):
.. code:: yaml
vars:
var1: common
iter:
- name: one
var2: first
- name: two
var2: second
And the following template (``template.jinja``):
.. code::
var1: {{ var1 }}
var2: {{ var2 }}
And run the following command:
.. code:: bash
c2c-template --vars vars.yaml --files-builder template.jinja {name}.txt iter
This will create two files:
the ``one.txt`` file, with::
var1: common
var2: first
The ``two.txt`` file, with::
var1: common
var2: second
PK 3@xH،4 4 - c2c.template-1.2.0.dist-info/entry_points.txt[console_scripts]
c2c-template = c2c.template:main
PK 4@xHϮ` ` * c2c.template-1.2.0.dist-info/metadata.json{"classifiers": ["Programming Language :: Python", "Environment :: Console", "Framework :: Bottle", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Topic :: Utilities", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4"], "extensions": {"python.commands": {"wrap_console": {"c2c-template": "c2c.template:main"}}, "python.details": {"contacts": [{"email": "info@camptocamp.com", "name": "camptocamp", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://www.camptocamp.com/geospatial-solutions"}}, "python.exports": {"console_scripts": {"c2c-template": "c2c.template:main"}}}, "extras": [], "generator": "bdist_wheel (0.26.0)", "keywords": ["template"], "metadata_version": "2.0", "name": "c2c.template", "run_requires": [{"requires": ["Jinja2", "Mako", "PyYAML", "bottle"]}], "summary": "Vars collector and template runner.", "version": "1.2.0"}PK 3@xHug= 3 c2c.template-1.2.0.dist-info/namespace_packages.txtc2c
PK 3@xHug= * c2c.template-1.2.0.dist-info/top_level.txtc2c
PK 4@xH''\ \ " c2c.template-1.2.0.dist-info/WHEELWheel-Version: 1.0
Generator: bdist_wheel (0.26.0)
Root-Is-Purelib: true
Tag: py2-none-any
PK 4@xHD%ۙ % c2c.template-1.2.0.dist-info/METADATAMetadata-Version: 2.0
Name: c2c.template
Version: 1.2.0
Summary: Vars collector and template runner.
Home-page: http://www.camptocamp.com/geospatial-solutions
Author: camptocamp
Author-email: info@camptocamp.com
License: UNKNOWN
Keywords: template
Platform: UNKNOWN
Classifier: Programming Language :: Python
Classifier: Environment :: Console
Classifier: Framework :: Bottle
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Utilities
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Requires-Dist: Jinja2
Requires-Dist: Mako
Requires-Dist: PyYAML
Requires-Dist: bottle
c2c.template
============
Supported template Jinja, Mako, Template.
Tools that collect some vars and get them to a template engine.
Supported template: `Jinja `_,
`Mako `_ and
`Template `_.
Use ``c2c-template --help`` to get the command line help.
Vars file
=========
The vars collector gets the vars from YAML files like this one:
.. code:: yaml
extends: inherit.yaml
vars:
string_var: a string
int_var: 42
interpreted_var: __import__('datetime').date.today()
combined_var: 'Today: {interpreted_var:%Y-%m-%d}'
facter_json: /usr/bin/facter --json
facter_yaml: /usr/bin/facter --yaml
pi: console.log(Math.PI.toPrecision(3))
obj:
v1: 1
v2: '2'
v3: [1, 2, 3]
interpreted:
python:
- interpreted_var
bash:
- facter_json
- facter_yaml
json:
- facter_json
yaml:
- facter_yaml
node:
vars: ["pi"]
cmd: ["node", "-e"]
update_path:
- obj
The ``inherit.yaml`` is an other file with the same syntax that will provide
initial vars.
The ``vars`` section is where we define the vars values, the YAML files
support typing, than ``42`` will be an integer.
The ``interpreted`` configuration to interpret some vars,
``python``, ``bash``, ``environ``, ``json``, ``yaml`` are predefined
interpreter, ``node`` is a custom interpreter.
The ``update_path`` is a list of '.'-separated paths that will be updated (for dicts)
or appended (for lists), instead of overwritten. The sub path will be implicitly added.
We can reuse predefined variables and format them (see ``combined_var``),
See: `str.format() `_.
Example of usage
================
Interpret variable in a template
--------------------------------
.. code:: bash
c2c-template --vars vars.yaml --engine jinja --files template.jinja
The result will be stored in a file named ``template``.
Get the vars
------------
It can be useful to get the variable outside.
.. code:: bash
`c2c-template --vars vars.yaml --get-vars INT_VAR=int_var string_var`
That will set the bash variable ``INT_VAR`` to 42, and ``STRING_VAR`` to 'a string'.
Get a configuration file
------------------------
.. code:: bash
c2c-template --vars vars.yaml --get-config config.yaml string-var int-var combined-var
Will create a file named ``config.yaml`` this:
.. code:: yaml
string-var: a string
int-var: 42
combined-var: Today: 2014-12-12
Build a set of file based on a template
---------------------------------------
Create the following vars file (``vars.yaml``):
.. code:: yaml
vars:
var1: common
iter:
- name: one
var2: first
- name: two
var2: second
And the following template (``template.jinja``):
.. code::
var1: {{ var1 }}
var2: {{ var2 }}
And run the following command:
.. code:: bash
c2c-template --vars vars.yaml --files-builder template.jinja {name}.txt iter
This will create two files:
the ``one.txt`` file, with::
var1: common
var2: first
The ``two.txt`` file, with::
var1: common
var2: second
PK 4@xHhny y # c2c.template-1.2.0.dist-info/RECORDc2c.template-1.2.0-nspkg.pth,sha256=hmGwcSup_BxULuyoaQob_j6EKXEslxN6jkCkxOjQc0c,296
c2c/template.py,sha256=YqBN-YYpNnVTxa4-QWuK2DGfJ2sjlxagwC0XI3GzU38,15698
c2c.template-1.2.0.dist-info/DESCRIPTION.rst,sha256=i-n9QPES_WEcWZXAkjrvFSg3p_Qk2lfq1IZXC3jqhQk,3363
c2c.template-1.2.0.dist-info/METADATA,sha256=UjNiGmvLhv7cv1qiiY5I6oiXWrzwfSceweEtZLYgr3Q,4249
c2c.template-1.2.0.dist-info/RECORD,,
c2c.template-1.2.0.dist-info/WHEEL,sha256=JTb7YztR8fkPg6aSjc571Q4eiVHCwmUDlX8PhuuqIIE,92
c2c.template-1.2.0.dist-info/entry_points.txt,sha256=Ksu_rpE94GGC8xYeIsmmhen-3EMiqAAXuMOZ2ckEEhw,52
c2c.template-1.2.0.dist-info/metadata.json,sha256=ZY54ehRXgLL-_dwSLgLhHg43z1SnJT3sTotgEtMYiT4,1120
c2c.template-1.2.0.dist-info/namespace_packages.txt,sha256=WKT_POy7Qj_8h5UKZmZv4253SztKmT1HvVc3hCV8Wso,4
c2c.template-1.2.0.dist-info/top_level.txt,sha256=WKT_POy7Qj_8h5UKZmZv4253SztKmT1HvVc3hCV8Wso,4
PK 4@xHԬ( ( c2c.template-1.2.0-nspkg.pthPK {^Gߏ8R= R= b c2c/template.pyPK 4@xHJ#
#
, > c2c.template-1.2.0.dist-info/DESCRIPTION.rstPK 3@xH،4 4 - NL c2c.template-1.2.0.dist-info/entry_points.txtPK 4@xHϮ` ` * L c2c.template-1.2.0.dist-info/metadata.jsonPK 3@xHug= 3 uQ c2c.template-1.2.0.dist-info/namespace_packages.txtPK 3@xHug= * Q c2c.template-1.2.0.dist-info/top_level.txtPK 4@xH''\ \ " R c2c.template-1.2.0.dist-info/WHEELPK 4@xHD%ۙ % R c2c.template-1.2.0.dist-info/METADATAPK 4@xHhny y # c c2c.template-1.2.0.dist-info/RECORDPK
A Hg