mirror of https://github.com/interlegis/sigi.git
Marcio Mazza
10 years ago
6 changed files with 453 additions and 412 deletions
@ -0,0 +1,2 @@ |
|||||
|
[pytest] |
||||
|
DJANGO_SETTINGS_MODULE=sigi.settings.test |
@ -0,0 +1,8 @@ |
|||||
|
# py.test precisa deste arquivo para que o projeto seja instalado no virtualenv com: |
||||
|
# "pip install -e ." |
||||
|
# vide http://pytest-django.readthedocs.org/en/latest/faq.html#i-see-an-error-saying-could-not-import-myproject-settings |
||||
|
# |
||||
|
from distutils.core import setup |
||||
|
|
||||
|
|
||||
|
setup(name='sigi', version='2.x') |
@ -1,412 +1,259 @@ |
|||||
""" |
""" |
||||
A smarter {% if %} tag for django templates. |
A smarter {% if %} tag for django templates. |
||||
|
|
||||
While retaining current Django functionality, it also handles equality, |
While retaining current Django functionality, it also handles equality, |
||||
greater than and less than operators. Some common case examples:: |
greater than and less than operators. Some common case examples:: |
||||
|
|
||||
{% if articles|length >= 5 %}...{% endif %} |
{% if articles|length >= 5 %}...{% endif %} |
||||
{% if "ifnotequal tag" != "beautiful" %}...{% endif %} |
{% if "ifnotequal tag" != "beautiful" %}...{% endif %} |
||||
""" |
""" |
||||
import unittest |
from django import template |
||||
from django import template |
|
||||
|
|
||||
|
register = template.Library() |
||||
register = template.Library() |
|
||||
|
|
||||
|
#============================================================================== |
||||
#============================================================================== |
# Calculation objects |
||||
# Calculation objects |
#============================================================================== |
||||
#============================================================================== |
|
||||
|
class BaseCalc(object): |
||||
class BaseCalc(object): |
|
||||
|
def __init__(self, var1, var2=None, negate=False): |
||||
def __init__(self, var1, var2=None, negate=False): |
self.var1 = var1 |
||||
self.var1 = var1 |
self.var2 = var2 |
||||
self.var2 = var2 |
self.negate = negate |
||||
self.negate = negate |
|
||||
|
def resolve(self, context): |
||||
def resolve(self, context): |
try: |
||||
try: |
var1, var2 = self.resolve_vars(context) |
||||
var1, var2 = self.resolve_vars(context) |
outcome = self.calculate(var1, var2) |
||||
outcome = self.calculate(var1, var2) |
except: |
||||
except: |
outcome = False |
||||
outcome = False |
if self.negate: |
||||
if self.negate: |
return not outcome |
||||
return not outcome |
return outcome |
||||
return outcome |
|
||||
|
def resolve_vars(self, context): |
||||
def resolve_vars(self, context): |
var2 = self.var2 and self.var2.resolve(context) |
||||
var2 = self.var2 and self.var2.resolve(context) |
return self.var1.resolve(context), var2 |
||||
return self.var1.resolve(context), var2 |
|
||||
|
def calculate(self, var1, var2): |
||||
def calculate(self, var1, var2): |
raise NotImplementedError() |
||||
raise NotImplementedError() |
|
||||
|
|
||||
|
class Or(BaseCalc): |
||||
class Or(BaseCalc): |
|
||||
|
def calculate(self, var1, var2): |
||||
def calculate(self, var1, var2): |
return var1 or var2 |
||||
return var1 or var2 |
|
||||
|
|
||||
|
class And(BaseCalc): |
||||
class And(BaseCalc): |
|
||||
|
def calculate(self, var1, var2): |
||||
def calculate(self, var1, var2): |
return var1 and var2 |
||||
return var1 and var2 |
|
||||
|
|
||||
|
class Equals(BaseCalc): |
||||
class Equals(BaseCalc): |
|
||||
|
def calculate(self, var1, var2): |
||||
def calculate(self, var1, var2): |
return var1 == var2 |
||||
return var1 == var2 |
|
||||
|
|
||||
|
class Greater(BaseCalc): |
||||
class Greater(BaseCalc): |
|
||||
|
def calculate(self, var1, var2): |
||||
def calculate(self, var1, var2): |
return var1 > var2 |
||||
return var1 > var2 |
|
||||
|
|
||||
|
class GreaterOrEqual(BaseCalc): |
||||
class GreaterOrEqual(BaseCalc): |
|
||||
|
def calculate(self, var1, var2): |
||||
def calculate(self, var1, var2): |
return var1 >= var2 |
||||
return var1 >= var2 |
|
||||
|
|
||||
|
class In(BaseCalc): |
||||
class In(BaseCalc): |
|
||||
|
def calculate(self, var1, var2): |
||||
def calculate(self, var1, var2): |
return var1 in var2 |
||||
return var1 in var2 |
|
||||
|
|
||||
|
OPERATORS = { |
||||
#============================================================================== |
'=': (Equals, True), |
||||
# Tests |
'==': (Equals, True), |
||||
#============================================================================== |
'!=': (Equals, False), |
||||
|
'>': (Greater, True), |
||||
class TestVar(object): |
'>=': (GreaterOrEqual, True), |
||||
|
'<=': (Greater, False), |
||||
""" |
'<': (GreaterOrEqual, False), |
||||
A basic self-resolvable object similar to a Django template variable. Used |
'or': (Or, True), |
||||
to assist with tests. |
'and': (And, True), |
||||
""" |
'in': (In, True), |
||||
|
} |
||||
def __init__(self, value): |
BOOL_OPERATORS = ('or', 'and') |
||||
self.value = value |
|
||||
|
|
||||
def resolve(self, context): |
class IfParser(object): |
||||
return self.value |
error_class = ValueError |
||||
|
|
||||
|
def __init__(self, tokens): |
||||
class SmartIfTests(unittest.TestCase): |
self.tokens = tokens |
||||
|
|
||||
def setUp(self): |
def _get_tokens(self): |
||||
self.true = TestVar(True) |
return self._tokens |
||||
self.false = TestVar(False) |
|
||||
self.high = TestVar(9000) |
def _set_tokens(self, tokens): |
||||
self.low = TestVar(1) |
self._tokens = tokens |
||||
|
self.len = len(tokens) |
||||
def assertCalc(self, calc, context=None): |
self.pos = 0 |
||||
""" |
|
||||
Test a calculation is True, also checking the inverse "negate" case. |
tokens = property(_get_tokens, _set_tokens) |
||||
""" |
|
||||
context = context or {} |
def parse(self): |
||||
self.assert_(calc.resolve(context)) |
if self.at_end(): |
||||
calc.negate = not calc.negate |
raise self.error_class('No variables provided.') |
||||
self.assertFalse(calc.resolve(context)) |
var1 = self.get_bool_var() |
||||
|
while not self.at_end(): |
||||
def assertCalcFalse(self, calc, context=None): |
op, negate = self.get_operator() |
||||
""" |
var2 = self.get_bool_var() |
||||
Test a calculation is False, also checking the inverse "negate" case. |
var1 = op(var1, var2, negate=negate) |
||||
""" |
return var1 |
||||
context = context or {} |
|
||||
self.assertFalse(calc.resolve(context)) |
def get_token(self, eof_message=None, lookahead=False): |
||||
calc.negate = not calc.negate |
negate = True |
||||
self.assert_(calc.resolve(context)) |
token = None |
||||
|
pos = self.pos |
||||
def test_or(self): |
while token is None or token == 'not': |
||||
self.assertCalc(Or(self.true)) |
if pos >= self.len: |
||||
self.assertCalcFalse(Or(self.false)) |
if eof_message is None: |
||||
self.assertCalc(Or(self.true, self.true)) |
raise self.error_class() |
||||
self.assertCalc(Or(self.true, self.false)) |
raise self.error_class(eof_message) |
||||
self.assertCalc(Or(self.false, self.true)) |
token = self.tokens[pos] |
||||
self.assertCalcFalse(Or(self.false, self.false)) |
negate = not negate |
||||
|
pos += 1 |
||||
def test_and(self): |
if not lookahead: |
||||
self.assertCalc(And(self.true, self.true)) |
self.pos = pos |
||||
self.assertCalcFalse(And(self.true, self.false)) |
return token, negate |
||||
self.assertCalcFalse(And(self.false, self.true)) |
|
||||
self.assertCalcFalse(And(self.false, self.false)) |
def at_end(self): |
||||
|
return self.pos >= self.len |
||||
def test_equals(self): |
|
||||
self.assertCalc(Equals(self.low, self.low)) |
def create_var(self, value): |
||||
self.assertCalcFalse(Equals(self.low, self.high)) |
raise NotImplementedError() |
||||
|
|
||||
def test_greater(self): |
def get_bool_var(self): |
||||
self.assertCalc(Greater(self.high, self.low)) |
""" |
||||
self.assertCalcFalse(Greater(self.low, self.low)) |
Returns either a variable by itself or a non-boolean operation (such as |
||||
self.assertCalcFalse(Greater(self.low, self.high)) |
``x == 0`` or ``x < 0``). |
||||
|
|
||||
def test_greater_or_equal(self): |
This is needed to keep correct precedence for boolean operations (i.e. |
||||
self.assertCalc(GreaterOrEqual(self.high, self.low)) |
``x or x == 0`` should be ``x or (x == 0)``, not ``(x or x) == 0``). |
||||
self.assertCalc(GreaterOrEqual(self.low, self.low)) |
""" |
||||
self.assertCalcFalse(GreaterOrEqual(self.low, self.high)) |
var = self.get_var() |
||||
|
if not self.at_end(): |
||||
def test_in(self): |
op_token = self.get_token(lookahead=True)[0] |
||||
list_ = TestVar([1, 2, 3]) |
if isinstance(op_token, basestring) and (op_token not in |
||||
invalid_list = TestVar(None) |
BOOL_OPERATORS): |
||||
self.assertCalc(In(self.low, list_)) |
op, negate = self.get_operator() |
||||
self.assertCalcFalse(In(self.low, invalid_list)) |
return op(var, self.get_var(), negate=negate) |
||||
|
return var |
||||
def test_parse_bits(self): |
|
||||
var = IfParser([True]).parse() |
def get_var(self): |
||||
self.assert_(var.resolve({})) |
token, negate = self.get_token('Reached end of statement, still ' |
||||
var = IfParser([False]).parse() |
'expecting a variable.') |
||||
self.assertFalse(var.resolve({})) |
if isinstance(token, basestring) and token in OPERATORS: |
||||
|
raise self.error_class('Expected variable, got operator (%s).' % |
||||
var = IfParser([False, 'or', True]).parse() |
token) |
||||
self.assert_(var.resolve({})) |
var = self.create_var(token) |
||||
|
if negate: |
||||
var = IfParser([False, 'and', True]).parse() |
return Or(var, negate=True) |
||||
self.assertFalse(var.resolve({})) |
return var |
||||
|
|
||||
var = IfParser(['not', False, 'and', 'not', False]).parse() |
def get_operator(self): |
||||
self.assert_(var.resolve({})) |
token, negate = self.get_token('Reached end of statement, still ' |
||||
|
'expecting an operator.') |
||||
var = IfParser(['not', 'not', True]).parse() |
if not isinstance(token, basestring) or token not in OPERATORS: |
||||
self.assert_(var.resolve({})) |
raise self.error_class('%s is not a valid operator.' % token) |
||||
|
if self.at_end(): |
||||
var = IfParser([1, '=', 1]).parse() |
raise self.error_class('No variable provided after "%s".' % token) |
||||
self.assert_(var.resolve({})) |
op, true = OPERATORS[token] |
||||
|
if not true: |
||||
var = IfParser([1, 'not', '=', 1]).parse() |
negate = not negate |
||||
self.assertFalse(var.resolve({})) |
return op, negate |
||||
|
|
||||
var = IfParser([1, 'not', 'not', '=', 1]).parse() |
|
||||
self.assert_(var.resolve({})) |
#============================================================================== |
||||
|
# Actual templatetag code. |
||||
var = IfParser([1, '!=', 1]).parse() |
#============================================================================== |
||||
self.assertFalse(var.resolve({})) |
|
||||
|
class TemplateIfParser(IfParser): |
||||
var = IfParser([3, '>', 2]).parse() |
error_class = template.TemplateSyntaxError |
||||
self.assert_(var.resolve({})) |
|
||||
|
def __init__(self, parser, *args, **kwargs): |
||||
var = IfParser([1, '<', 2]).parse() |
self.template_parser = parser |
||||
self.assert_(var.resolve({})) |
return super(TemplateIfParser, self).__init__(*args, **kwargs) |
||||
|
|
||||
var = IfParser([2, 'not', 'in', [2, 3]]).parse() |
def create_var(self, value): |
||||
self.assertFalse(var.resolve({})) |
return self.template_parser.compile_filter(value) |
||||
|
|
||||
var = IfParser([1, 'or', 1, '=', 2]).parse() |
|
||||
self.assert_(var.resolve({})) |
class SmartIfNode(template.Node): |
||||
|
|
||||
def test_boolean(self): |
def __init__(self, var, nodelist_true, nodelist_false=None): |
||||
var = IfParser([True, 'and', True, 'and', True]).parse() |
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false |
||||
self.assert_(var.resolve({})) |
self.var = var |
||||
var = IfParser([False, 'or', False, 'or', True]).parse() |
|
||||
self.assert_(var.resolve({})) |
def render(self, context): |
||||
var = IfParser([True, 'and', False, 'or', True]).parse() |
if self.var.resolve(context): |
||||
self.assert_(var.resolve({})) |
return self.nodelist_true.render(context) |
||||
var = IfParser([False, 'or', True, 'and', True]).parse() |
if self.nodelist_false: |
||||
self.assert_(var.resolve({})) |
return self.nodelist_false.render(context) |
||||
|
return '' |
||||
var = IfParser([True, 'and', True, 'and', False]).parse() |
|
||||
self.assertFalse(var.resolve({})) |
def __repr__(self): |
||||
var = IfParser([False, 'or', False, 'or', False]).parse() |
return "<Smart If node>" |
||||
self.assertFalse(var.resolve({})) |
|
||||
var = IfParser([False, 'or', True, 'and', False]).parse() |
def __iter__(self): |
||||
self.assertFalse(var.resolve({})) |
for node in self.nodelist_true: |
||||
var = IfParser([False, 'and', True, 'or', False]).parse() |
yield node |
||||
self.assertFalse(var.resolve({})) |
if self.nodelist_false: |
||||
|
for node in self.nodelist_false: |
||||
def test_invalid(self): |
yield node |
||||
self.assertRaises(ValueError, IfParser(['not']).parse) |
|
||||
self.assertRaises(ValueError, IfParser(['==']).parse) |
def get_nodes_by_type(self, nodetype): |
||||
self.assertRaises(ValueError, IfParser([1, 'in']).parse) |
nodes = [] |
||||
self.assertRaises(ValueError, IfParser([1, '>', 'in']).parse) |
if isinstance(self, nodetype): |
||||
self.assertRaises(ValueError, IfParser([1, '==', 'not', 'not']).parse) |
nodes.append(self) |
||||
self.assertRaises(ValueError, IfParser([1, 2]).parse) |
nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype)) |
||||
|
if self.nodelist_false: |
||||
|
nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype)) |
||||
OPERATORS = { |
return nodes |
||||
'=': (Equals, True), |
|
||||
'==': (Equals, True), |
|
||||
'!=': (Equals, False), |
@register.tag('if') |
||||
'>': (Greater, True), |
def smart_if(parser, token): |
||||
'>=': (GreaterOrEqual, True), |
""" |
||||
'<=': (Greater, False), |
A smarter {% if %} tag for django templates. |
||||
'<': (GreaterOrEqual, False), |
|
||||
'or': (Or, True), |
While retaining current Django functionality, it also handles equality, |
||||
'and': (And, True), |
greater than and less than operators. Some common case examples:: |
||||
'in': (In, True), |
|
||||
} |
{% if articles|length >= 5 %}...{% endif %} |
||||
BOOL_OPERATORS = ('or', 'and') |
{% if "ifnotequal tag" != "beautiful" %}...{% endif %} |
||||
|
|
||||
|
Arguments and operators _must_ have a space between them, so |
||||
class IfParser(object): |
``{% if 1>2 %}`` is not a valid smart if tag. |
||||
error_class = ValueError |
|
||||
|
All supported operators are: ``or``, ``and``, ``in``, ``=`` (or ``==``), |
||||
def __init__(self, tokens): |
``!=``, ``>``, ``>=``, ``<`` and ``<=``. |
||||
self.tokens = tokens |
""" |
||||
|
bits = token.split_contents()[1:] |
||||
def _get_tokens(self): |
var = TemplateIfParser(parser, bits).parse() |
||||
return self._tokens |
nodelist_true = parser.parse(('else', 'endif')) |
||||
|
token = parser.next_token() |
||||
def _set_tokens(self, tokens): |
if token.contents == 'else': |
||||
self._tokens = tokens |
nodelist_false = parser.parse(('endif',)) |
||||
self.len = len(tokens) |
parser.delete_first_token() |
||||
self.pos = 0 |
else: |
||||
|
nodelist_false = None |
||||
tokens = property(_get_tokens, _set_tokens) |
return SmartIfNode(var, nodelist_true, nodelist_false) |
||||
|
|
||||
def parse(self): |
|
||||
if self.at_end(): |
|
||||
raise self.error_class('No variables provided.') |
|
||||
var1 = self.get_bool_var() |
|
||||
while not self.at_end(): |
|
||||
op, negate = self.get_operator() |
|
||||
var2 = self.get_bool_var() |
|
||||
var1 = op(var1, var2, negate=negate) |
|
||||
return var1 |
|
||||
|
|
||||
def get_token(self, eof_message=None, lookahead=False): |
|
||||
negate = True |
|
||||
token = None |
|
||||
pos = self.pos |
|
||||
while token is None or token == 'not': |
|
||||
if pos >= self.len: |
|
||||
if eof_message is None: |
|
||||
raise self.error_class() |
|
||||
raise self.error_class(eof_message) |
|
||||
token = self.tokens[pos] |
|
||||
negate = not negate |
|
||||
pos += 1 |
|
||||
if not lookahead: |
|
||||
self.pos = pos |
|
||||
return token, negate |
|
||||
|
|
||||
def at_end(self): |
|
||||
return self.pos >= self.len |
|
||||
|
|
||||
def create_var(self, value): |
|
||||
return TestVar(value) |
|
||||
|
|
||||
def get_bool_var(self): |
|
||||
""" |
|
||||
Returns either a variable by itself or a non-boolean operation (such as |
|
||||
``x == 0`` or ``x < 0``). |
|
||||
|
|
||||
This is needed to keep correct precedence for boolean operations (i.e. |
|
||||
``x or x == 0`` should be ``x or (x == 0)``, not ``(x or x) == 0``). |
|
||||
""" |
|
||||
var = self.get_var() |
|
||||
if not self.at_end(): |
|
||||
op_token = self.get_token(lookahead=True)[0] |
|
||||
if isinstance(op_token, basestring) and (op_token not in |
|
||||
BOOL_OPERATORS): |
|
||||
op, negate = self.get_operator() |
|
||||
return op(var, self.get_var(), negate=negate) |
|
||||
return var |
|
||||
|
|
||||
def get_var(self): |
|
||||
token, negate = self.get_token('Reached end of statement, still ' |
|
||||
'expecting a variable.') |
|
||||
if isinstance(token, basestring) and token in OPERATORS: |
|
||||
raise self.error_class('Expected variable, got operator (%s).' % |
|
||||
token) |
|
||||
var = self.create_var(token) |
|
||||
if negate: |
|
||||
return Or(var, negate=True) |
|
||||
return var |
|
||||
|
|
||||
def get_operator(self): |
|
||||
token, negate = self.get_token('Reached end of statement, still ' |
|
||||
'expecting an operator.') |
|
||||
if not isinstance(token, basestring) or token not in OPERATORS: |
|
||||
raise self.error_class('%s is not a valid operator.' % token) |
|
||||
if self.at_end(): |
|
||||
raise self.error_class('No variable provided after "%s".' % token) |
|
||||
op, true = OPERATORS[token] |
|
||||
if not true: |
|
||||
negate = not negate |
|
||||
return op, negate |
|
||||
|
|
||||
|
|
||||
#============================================================================== |
|
||||
# Actual templatetag code. |
|
||||
#============================================================================== |
|
||||
|
|
||||
class TemplateIfParser(IfParser): |
|
||||
error_class = template.TemplateSyntaxError |
|
||||
|
|
||||
def __init__(self, parser, *args, **kwargs): |
|
||||
self.template_parser = parser |
|
||||
return super(TemplateIfParser, self).__init__(*args, **kwargs) |
|
||||
|
|
||||
def create_var(self, value): |
|
||||
return self.template_parser.compile_filter(value) |
|
||||
|
|
||||
|
|
||||
class SmartIfNode(template.Node): |
|
||||
|
|
||||
def __init__(self, var, nodelist_true, nodelist_false=None): |
|
||||
self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false |
|
||||
self.var = var |
|
||||
|
|
||||
def render(self, context): |
|
||||
if self.var.resolve(context): |
|
||||
return self.nodelist_true.render(context) |
|
||||
if self.nodelist_false: |
|
||||
return self.nodelist_false.render(context) |
|
||||
return '' |
|
||||
|
|
||||
def __repr__(self): |
|
||||
return "<Smart If node>" |
|
||||
|
|
||||
def __iter__(self): |
|
||||
for node in self.nodelist_true: |
|
||||
yield node |
|
||||
if self.nodelist_false: |
|
||||
for node in self.nodelist_false: |
|
||||
yield node |
|
||||
|
|
||||
def get_nodes_by_type(self, nodetype): |
|
||||
nodes = [] |
|
||||
if isinstance(self, nodetype): |
|
||||
nodes.append(self) |
|
||||
nodes.extend(self.nodelist_true.get_nodes_by_type(nodetype)) |
|
||||
if self.nodelist_false: |
|
||||
nodes.extend(self.nodelist_false.get_nodes_by_type(nodetype)) |
|
||||
return nodes |
|
||||
|
|
||||
|
|
||||
@register.tag('if') |
|
||||
def smart_if(parser, token): |
|
||||
""" |
|
||||
A smarter {% if %} tag for django templates. |
|
||||
|
|
||||
While retaining current Django functionality, it also handles equality, |
|
||||
greater than and less than operators. Some common case examples:: |
|
||||
|
|
||||
{% if articles|length >= 5 %}...{% endif %} |
|
||||
{% if "ifnotequal tag" != "beautiful" %}...{% endif %} |
|
||||
|
|
||||
Arguments and operators _must_ have a space between them, so |
|
||||
``{% if 1>2 %}`` is not a valid smart if tag. |
|
||||
|
|
||||
All supported operators are: ``or``, ``and``, ``in``, ``=`` (or ``==``), |
|
||||
``!=``, ``>``, ``>=``, ``<`` and ``<=``. |
|
||||
""" |
|
||||
bits = token.split_contents()[1:] |
|
||||
var = TemplateIfParser(parser, bits).parse() |
|
||||
nodelist_true = parser.parse(('else', 'endif')) |
|
||||
token = parser.next_token() |
|
||||
if token.contents == 'else': |
|
||||
nodelist_false = parser.parse(('endif',)) |
|
||||
parser.delete_first_token() |
|
||||
else: |
|
||||
nodelist_false = None |
|
||||
return SmartIfNode(var, nodelist_true, nodelist_false) |
|
||||
|
|
||||
|
|
||||
if __name__ == '__main__': |
|
||||
unittest.main() |
|
||||
|
@ -0,0 +1,166 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
import pytest |
||||
|
|
||||
|
from smart_if import Or, And, Equals, Greater, GreaterOrEqual, In, IfParser |
||||
|
|
||||
|
|
||||
|
class TestVar(object): |
||||
|
|
||||
|
""" |
||||
|
A basic self-resolvable object similar to a Django template variable. Used |
||||
|
to assist with tests. |
||||
|
""" |
||||
|
|
||||
|
def __init__(self, value): |
||||
|
self.value = value |
||||
|
|
||||
|
def resolve(self, context): |
||||
|
return self.value |
||||
|
|
||||
|
|
||||
|
class TestIfParser(IfParser): |
||||
|
|
||||
|
def create_var(self, value): |
||||
|
return TestVar(value) |
||||
|
|
||||
|
|
||||
|
class ValueHolder(object): |
||||
|
pass |
||||
|
|
||||
|
VALORES = ValueHolder() |
||||
|
VALORES.true = TestVar(True) |
||||
|
VALORES.false = TestVar(False) |
||||
|
VALORES.high = TestVar(9000) |
||||
|
VALORES.low = TestVar(1) |
||||
|
|
||||
|
|
||||
|
def assertCalc(calc, context=None): |
||||
|
""" |
||||
|
Test a calculation is True, also checking the inverse "negate" case. |
||||
|
""" |
||||
|
context = context or {} |
||||
|
assert calc.resolve(context) |
||||
|
calc.negate = not calc.negate |
||||
|
assert not calc.resolve(context) |
||||
|
|
||||
|
|
||||
|
def assertCalcFalse(calc, context=None): |
||||
|
""" |
||||
|
Test a calculation is False, also checking the inverse "negate" case. |
||||
|
""" |
||||
|
context = context or {} |
||||
|
assert not calc.resolve(context) |
||||
|
calc.negate = not calc.negate |
||||
|
assert calc.resolve(context) |
||||
|
|
||||
|
|
||||
|
def test_or(): |
||||
|
assertCalc(Or(VALORES.true)) |
||||
|
assertCalcFalse(Or(VALORES.false)) |
||||
|
assertCalc(Or(VALORES.true, VALORES.true)) |
||||
|
assertCalc(Or(VALORES.true, VALORES.false)) |
||||
|
assertCalc(Or(VALORES.false, VALORES.true)) |
||||
|
assertCalcFalse(Or(VALORES.false, VALORES.false)) |
||||
|
|
||||
|
|
||||
|
def test_and(): |
||||
|
assertCalc(And(VALORES.true, VALORES.true)) |
||||
|
assertCalcFalse(And(VALORES.true, VALORES.false)) |
||||
|
assertCalcFalse(And(VALORES.false, VALORES.true)) |
||||
|
assertCalcFalse(And(VALORES.false, VALORES.false)) |
||||
|
|
||||
|
|
||||
|
def test_equals(): |
||||
|
assertCalc(Equals(VALORES.low, VALORES.low)) |
||||
|
assertCalcFalse(Equals(VALORES.low, VALORES.high)) |
||||
|
|
||||
|
|
||||
|
def test_greater(): |
||||
|
assertCalc(Greater(VALORES.high, VALORES.low)) |
||||
|
assertCalcFalse(Greater(VALORES.low, VALORES.low)) |
||||
|
assertCalcFalse(Greater(VALORES.low, VALORES.high)) |
||||
|
|
||||
|
|
||||
|
def test_greater_or_equal(): |
||||
|
assertCalc(GreaterOrEqual(VALORES.high, VALORES.low)) |
||||
|
assertCalc(GreaterOrEqual(VALORES.low, VALORES.low)) |
||||
|
assertCalcFalse(GreaterOrEqual(VALORES.low, VALORES.high)) |
||||
|
|
||||
|
|
||||
|
def test_in(): |
||||
|
list_ = TestVar([1, 2, 3]) |
||||
|
invalid_list = TestVar(None) |
||||
|
assertCalc(In(VALORES.low, list_)) |
||||
|
assertCalcFalse(In(VALORES.low, invalid_list)) |
||||
|
|
||||
|
|
||||
|
def test_parse_bits(): |
||||
|
var = TestIfParser([True]).parse() |
||||
|
assert var.resolve({}) |
||||
|
var = TestIfParser([False]).parse() |
||||
|
assert not var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([False, 'or', True]).parse() |
||||
|
assert var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([False, 'and', True]).parse() |
||||
|
assert not var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser(['not', False, 'and', 'not', False]).parse() |
||||
|
assert var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser(['not', 'not', True]).parse() |
||||
|
assert var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([1, '=', 1]).parse() |
||||
|
assert var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([1, 'not', '=', 1]).parse() |
||||
|
assert not var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([1, 'not', 'not', '=', 1]).parse() |
||||
|
assert var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([1, '!=', 1]).parse() |
||||
|
assert not var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([3, '>', 2]).parse() |
||||
|
assert var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([1, '<', 2]).parse() |
||||
|
assert var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([2, 'not', 'in', [2, 3]]).parse() |
||||
|
assert not var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([1, 'or', 1, '=', 2]).parse() |
||||
|
assert var.resolve({}) |
||||
|
|
||||
|
|
||||
|
def test_boolean(): |
||||
|
var = TestIfParser([True, 'and', True, 'and', True]).parse() |
||||
|
assert var.resolve({}) |
||||
|
var = TestIfParser([False, 'or', False, 'or', True]).parse() |
||||
|
assert var.resolve({}) |
||||
|
var = TestIfParser([True, 'and', False, 'or', True]).parse() |
||||
|
assert var.resolve({}) |
||||
|
var = TestIfParser([False, 'or', True, 'and', True]).parse() |
||||
|
assert var.resolve({}) |
||||
|
|
||||
|
var = TestIfParser([True, 'and', True, 'and', False]).parse() |
||||
|
assert not var.resolve({}) |
||||
|
var = TestIfParser([False, 'or', False, 'or', False]).parse() |
||||
|
assert not var.resolve({}) |
||||
|
var = TestIfParser([False, 'or', True, 'and', False]).parse() |
||||
|
assert not var.resolve({}) |
||||
|
var = TestIfParser([False, 'and', True, 'or', False]).parse() |
||||
|
assert not var.resolve({}) |
||||
|
|
||||
|
|
||||
|
def test_invalid(): |
||||
|
pytest.raises(ValueError, TestIfParser(['not']).parse) |
||||
|
pytest.raises(ValueError, TestIfParser(['==']).parse) |
||||
|
pytest.raises(ValueError, TestIfParser([1, 'in']).parse) |
||||
|
pytest.raises(ValueError, TestIfParser([1, '>', 'in']).parse) |
||||
|
pytest.raises(ValueError, TestIfParser([1, '==', 'not', 'not']).parse) |
||||
|
pytest.raises(ValueError, TestIfParser([1, 2]).parse) |
@ -0,0 +1,16 @@ |
|||||
|
from base import * |
||||
|
|
||||
|
|
||||
|
# SECURITY WARNING: keep the secret key used in production secret! |
||||
|
SECRET_KEY = '0$ip1fb5xtq%a=)-k_4r^(#jn0t^@+*^kihkxkozg-mip7+w3+' |
||||
|
|
||||
|
DATABASES = { |
||||
|
'default': { |
||||
|
'ENGINE': 'django.db.backends.postgresql_psycopg2', |
||||
|
'NAME': 'sigi_test', |
||||
|
'USER': 'sigi', |
||||
|
'PASSWORD': 'sigi', |
||||
|
'HOST': 'localhost', |
||||
|
'PORT': '5432', |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue