From b00a6b54a75c152e8b1a1e7cdff639b4ed43919d Mon Sep 17 00:00:00 2001 From: TayHobbs Date: Mon, 21 Dec 2015 13:15:24 -0600 Subject: [PATCH 1/5] Refactor: Clean up _compat import --- jinja2schema/visitors/stmt.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/jinja2schema/visitors/stmt.py b/jinja2schema/visitors/stmt.py index 83946fa..3dd4d2b 100644 --- a/jinja2schema/visitors/stmt.py +++ b/jinja2schema/visitors/stmt.py @@ -8,14 +8,14 @@ """ import functools -from jinja2 import nodes +from jinja2 import nodes, Environment, PackageLoader from jinja2schema.config import default_config from ..model import Scalar, Dictionary, List, Unknown, Tuple, Boolean from ..macro import Macro from ..mergers import merge, merge_many from ..exceptions import InvalidExpression -from .. import _compat +from .._compat import iteritems, izip, zip_longest from .expr import Context, visit_expr from .util import visit_many @@ -46,7 +46,7 @@ def visit_stmt(ast, macroses=None, config=default_config): """ visitor = stmt_visitors.get(type(ast)) if not visitor: - for node_cls, visitor_ in stmt_visitors.iteritems(): + for node_cls, visitor_ in iteritems(stmt_visitors): if isinstance(ast, node_cls): visitor = visitor_ if not visitor: @@ -95,7 +95,7 @@ def visit_if(ast, macroses=None, config=default_config): else_struct = visit_many(ast.else_, macroses, config, predicted_struct_cls=Scalar) if ast.else_ else Dictionary() struct = merge_many(test_struct, if_struct, else_struct) - for var_name, var_struct in test_struct.iteritems(): + for var_name, var_struct in iteritems(test_struct): if var_struct.checked_as_defined or var_struct.checked_as_undefined: if var_struct.checked_as_undefined: lookup_struct = if_struct @@ -125,7 +125,7 @@ def visit_assign(ast, macroses=None, config=default_config): if len(ast.target.items) != len(ast.node.items): raise InvalidExpression(ast, 'number of items in left side is different ' 'from right side') - for name_ast, var_ast in _compat.izip(ast.target.items, ast.node.items): + for name_ast, var_ast in izip(ast.target.items, ast.node.items): variables.append((name_ast.name, var_ast)) for var_name, var_ast in variables: var_rtype, var_struct = visit_expr(var_ast, Context(predicted_struct=Unknown.from_ast(var_ast)), macroses, config) @@ -160,7 +160,7 @@ def visit_macro(ast, macroses=None, config=default_config): kwargs = [] body_struct = visit_many(ast.body, macroses, config, predicted_struct_cls=Scalar) - for i, (arg, default_value_ast) in enumerate(reversed(list(_compat.zip_longest(reversed(ast.args), + for i, (arg, default_value_ast) in enumerate(reversed(list(zip_longest(reversed(ast.args), reversed(ast.defaults)))), start=1): has_default_value = bool(default_value_ast) if has_default_value: From feec7ebd3b460472c9dfe2c8d49bb7f510f05b4f Mon Sep 17 00:00:00 2001 From: TayHobbs Date: Mon, 21 Dec 2015 13:16:05 -0600 Subject: [PATCH 2/5] Feature: Allow block tags to be used in templates --- jinja2schema/visitors/stmt.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jinja2schema/visitors/stmt.py b/jinja2schema/visitors/stmt.py index 3dd4d2b..676be6e 100644 --- a/jinja2schema/visitors/stmt.py +++ b/jinja2schema/visitors/stmt.py @@ -188,3 +188,8 @@ def visit_macro(ast, macroses=None, config=default_config): for arg in args_struct.iterkeys(): body_struct.pop(arg, None) return body_struct + + +@visits_stmt(nodes.Block) +def visit_block(ast, macroses=None, config=default_config): + return visit_many(ast.body, macroses, config) From 16869110b11d3977d0c5bd6199a697c03ddfcc53 Mon Sep 17 00:00:00 2001 From: TayHobbs Date: Mon, 21 Dec 2015 13:16:45 -0600 Subject: [PATCH 3/5] Feature: Allow include tags to be used in templates --- jinja2schema/config.py | 24 ++++++++++++++++++++++-- jinja2schema/visitors/stmt.py | 7 +++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/jinja2schema/config.py b/jinja2schema/config.py index 6de2c93..7f48cad 100644 --- a/jinja2schema/config.py +++ b/jinja2schema/config.py @@ -31,10 +31,28 @@ class Config(object): unknown structure. If this variable is set, ``xs`` will be a boolean. """ + PACKAGE_NAME = '' + """Name of the package where you want to load templates from. + + This configuration is for if you are using includes in your jinja templates. This tells jinja + where to look to be able to load the included template from. If you do not plan on using ``includes`` + this configuration is not needed. + """ + + TEMPLATE_DIR = 'templates' + """Name of the directory where you want to load templates from. Defaulted to ``templates`` + + This configuration is for if you are using includes in your jinja templates. This tells jinja + which directoy to look to be able to load the included template from. If you do not plan on using ``includes`` + this configuration is not needed. + """ + def __init__(self, TYPE_OF_VARIABLE_INDEXED_WITH_VARIABLE_TYPE='dictionary', TYPE_OF_VARIABLE_INDEXED_WITH_INTEGER_TYPE='list', - BOOLEAN_CONDITIONS=False): + BOOLEAN_CONDITIONS=False, + PACKAGE_NAME='', + TEMPLATE_DIR='templates'): if TYPE_OF_VARIABLE_INDEXED_WITH_VARIABLE_TYPE not in ('dictionary', 'list'): raise ValueError('TYPE_OF_VARIABLE_INDEXED_WITH_VARIABLE_TYPE must be' 'either "dictionary" or "list"') @@ -44,6 +62,8 @@ def __init__(self, self.TYPE_OF_VARIABLE_INDEXED_WITH_INTEGER_TYPE = TYPE_OF_VARIABLE_INDEXED_WITH_INTEGER_TYPE self.TYPE_OF_VARIABLE_INDEXED_WITH_VARIABLE_TYPE = TYPE_OF_VARIABLE_INDEXED_WITH_VARIABLE_TYPE self.BOOLEAN_CONDITIONS = BOOLEAN_CONDITIONS + self.PACKAGE_NAME = PACKAGE_NAME + self.TEMPLATE_DIR = TEMPLATE_DIR -default_config = Config() \ No newline at end of file +default_config = Config() diff --git a/jinja2schema/visitors/stmt.py b/jinja2schema/visitors/stmt.py index 676be6e..a8ddeb0 100644 --- a/jinja2schema/visitors/stmt.py +++ b/jinja2schema/visitors/stmt.py @@ -190,6 +190,13 @@ def visit_macro(ast, macroses=None, config=default_config): return body_struct +@visits_stmt(nodes.Include) +def visit_include(ast, macroses=None, config=default_config): + env = Environment(loader=PackageLoader(config.PACKAGE_NAME, config.TEMPLATE_DIR)) + template = env.parse(env.loader.get_source(env, ast.template.value)[0]) + return visit_many(template.body, macroses, config) + + @visits_stmt(nodes.Block) def visit_block(ast, macroses=None, config=default_config): return visit_many(ast.body, macroses, config) From 106790ada8470ec73d30f59d946290f73568ff4c Mon Sep 17 00:00:00 2001 From: TayHobbs Date: Mon, 21 Dec 2015 13:17:11 -0600 Subject: [PATCH 4/5] Feature: Allow extend tags to be used in templates --- jinja2schema/visitors/stmt.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/jinja2schema/visitors/stmt.py b/jinja2schema/visitors/stmt.py index a8ddeb0..34ca34e 100644 --- a/jinja2schema/visitors/stmt.py +++ b/jinja2schema/visitors/stmt.py @@ -197,6 +197,13 @@ def visit_include(ast, macroses=None, config=default_config): return visit_many(template.body, macroses, config) +@visits_stmt(nodes.Extends) +def visit_extends(ast, macroses=None, config=default_config): + env = Environment(loader=PackageLoader(config.PACKAGE_NAME, config.TEMPLATE_DIR)) + template = env.parse(env.loader.get_source(env, ast.template.value)[0]) + return visit_many(template.body, macroses, config) + + @visits_stmt(nodes.Block) def visit_block(ast, macroses=None, config=default_config): return visit_many(ast.body, macroses, config) From 071722114064c2a7194225142b195c93d36f21da Mon Sep 17 00:00:00 2001 From: Pachwenko <32424503+Pachwenko@users.noreply.github.com> Date: Thu, 26 Sep 2019 11:06:46 -0500 Subject: [PATCH 5/5] Debugging: short circuit loop cycle --- jinja2schema/visitors/expr.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jinja2schema/visitors/expr.py b/jinja2schema/visitors/expr.py index 5685c37..4acb804 100644 --- a/jinja2schema/visitors/expr.py +++ b/jinja2schema/visitors/expr.py @@ -137,7 +137,6 @@ def wrapped_func(ast, ctx, macroses=None, config=default_config): return wrapped_func return decorator - def visit_expr(ast, ctx, macroses=None, config=default_config): """Returns a structure of ``ast``. @@ -398,7 +397,9 @@ def visit_call(ast, ctx, macroses=None, config=default_config): else: raise InvalidExpression(ast, '"{0}" call is not supported'.format(ast.node.name)) elif isinstance(ast.node, nodes.Getattr): - if ast.node.attr in ('keys', 'iterkeys', 'values', 'itervalues'): + if ast.node.node.name in ('loop'): + return Unknown(), Unknown() + elif ast.node.attr in ('keys', 'iterkeys', 'values', 'itervalues'): ctx.meet(List(Unknown()), ast) rtype, struct = visit_expr( ast.node.node, Context(