• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

SEED-platform / seed / #8936

14 Apr 2025 03:48PM UTC coverage: 86.881%. Remained the same
#8936

push

coveralls-python

web-flow
Update precommit, a few dependencies, and spelling issues (#4967)

* update precommit ruff version and rerun

* noqa the unsafe fixes

* more spelling

* more spelling

* formatting

---------

Co-authored-by: Katherine Fleming <2205659+kflemin@users.noreply.github.com>

24 of 42 new or added lines in 28 files covered. (57.14%)

41992 of 48333 relevant lines covered (86.88%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

40.48
/seed/tests/test_numeric_expression_parser.py
1
"""
2
SEED Platform (TM), Copyright (c) Alliance for Sustainable Energy, LLC, and other contributors.
3
See also https://github.com/SEED-platform/seed/blob/main/LICENSE.md
4

5
:author 'Piper Merriam <pmerriam@quickleft.com>'
6
"""
7

8
import itertools
1✔
9

10
from django.test import TestCase
11

12
from seed.utils.search import NUMERIC_EXPRESSION_REGEX, is_numeric_expression, parse_expression
1✔
13

14

15
# Metaclass to create individual test methods per test case.
16
class TestCaseFactory(type):
1✔
17
    def __new__(cls, name, bases, attrs):
1✔
18
        cases = attrs["cases"]
×
19
        method_maker = attrs["method_maker"]
×
20
        prefix = attrs["prefix"]
×
21

22
        for doc, value, expected in cases:
×
23
            test = method_maker(value, expected)
×
NEW
24
            test_name = f"{prefix}_{doc.lower().replace(' ', '_')}"
×
25
            if test_name in attrs:
×
26
                raise KeyError(f"Test name {test_name} duplicated")
×
27
            test.__name__ = test_name
×
28
            test.__doc__ = doc
×
29
            attrs[test_name] = test
×
30
        return super().__new__(cls, name, bases, attrs)
×
31

32

33
def make_is_numeric_expression_method(value, expected):
1✔
34
    def run(self):
×
35
        result = is_numeric_expression(value)
×
36
        self.assertEqual(bool(expected), bool(result))
×
37

38
    return run
×
39

40

41
class IsNumericExpressionTests(TestCase):
1✔
42
    __metaclass__ = TestCaseFactory
1✔
43
    method_maker = make_is_numeric_expression_method
1✔
44
    prefix = "test_is_numeric_expression"
1✔
45

46
    # test name, input, expected output
47
    cases = [
1✔
48
        # Non expressions
49
        ("not_expression_1", "1234", False),
50
        ("not_expression_2", "", False),
51
        ("not_expression_3", None, False),
52
        # Incomplete expressions
53
        ("not_expression_4", "=", False),
54
        ("not_expression_5", "==", False),
55
        ("not_expression_6", "!=", False),
56
        ("not_expression_7", "!", False),
57
        ("not_expression_8", "<>", False),
58
        ("not_expression_9", "<", False),
59
        ("not_expression_10", "<=", False),
60
        ("not_expression_11", ">", False),
61
        ("not_expression_12", ">=", False),
62
        # Basic expressions
63
        ("equality_1", "=1234", True),
64
        ("equality_2", "==1234", True),
65
        ("inequality_1", "!=1234", True),
66
        ("inequality_2", "!1234", True),
67
        ("inequality_3", "<>1234", True),
68
        ("less_than", "<1234", True),
69
        ("less_than_or_equal", "<=1234", True),
70
        ("greater_than", ">1234", True),
71
        ("greater_than_or_equal", ">=1234", True),
72
        # Whitespace
73
        ("whitespace_1", "=  1234", True),
74
        ("whitespace_2", " == 1234 ", True),
75
        # Nulls checks
76
        ("is_null_1", "=null", True),
77
        ("is_null_2", "==null", True),
78
        ("is_not_null_1", "!=null", True),
79
        ("is_not_null_2", "!null", True),
80
        ("is_not_null_3", "<>null", True),
81
        # Complex Expressions
82
        ("complex_1", ">123,<456", True),
83
        ("complex_2", ">123, <456", True),
84
        ("complex_3", ">123 , <456", True),
85
        ("complex_4", ">123,<456,!null", True),
86
        ("complex_5", ">123,<", True),
87
    ]
88

89

90
def query_to_child_tuples(query):
1✔
91
    """
92
    Takes a Q object and extracts the underlying queries.  Returns an iterable
93
    of 3-tuples who's values are (negated, field_lookup, value)
94
    """
95
    if isinstance(query, tuple):
×
96
        return query
×
97
    return list(
×
98
        itertools.chain.from_iterable(
99
            ([tuple(itertools.chain.from_iterable(([query.negated], c)))] if isinstance(c, tuple) else query_to_child_tuples(c))
100
            for c in query.children
101
        )
102
    )
103

104

105
def make_parse_expression_method(value, expected):
1✔
106
    def run(self):
×
107
        parts = NUMERIC_EXPRESSION_REGEX.findall(value)
×
108
        result = parse_expression("field", parts)
×
109
        query_children = query_to_child_tuples(result)
×
110
        self.assertEqual(expected, query_children)
×
111

112
    return run
×
113

114

115
class ExpressionParserTests(TestCase):
1✔
116
    __metaclass__ = TestCaseFactory
1✔
117
    method_maker = make_parse_expression_method
1✔
118
    prefix = "test_numeric_expression_parser"
1✔
119

120
    # test name, input, expected output
121
    cases = [
1✔
122
        ("equality_1", "=1234", [(False, "field", "1234")]),
123
        ("equality_2", "==1234", [(False, "field", "1234")]),
124
        ("inequality_1", "!=1234", [(True, "field", "1234")]),
125
        ("inequality_2", "!1234", [(True, "field", "1234")]),
126
        ("inequality_3", "<>1234", [(True, "field", "1234")]),
127
        ("greater_than", ">1234", [(False, "field__gt", "1234")]),
128
        ("greater_than_or_equal", ">=1234", [(False, "field__gte", "1234")]),
129
        ("less_than", "<1234", [(False, "field__lt", "1234")]),
130
        ("less_than_or_equal", "<=1234", [(False, "field__lte", "1234")]),
131
        # null
132
        ("is_null_1", "=null", [(False, "field__isnull", True)]),
133
        ("is_null_2", "==null", [(False, "field__isnull", True)]),
134
        ("is_not_null_1", "!null", [(False, "field__isnull", False)]),
135
        ("is_not_null_2", "!=null", [(False, "field__isnull", False)]),
136
        ("is_not_null_3", "<>null", [(False, "field__isnull", False)]),
137
        # complex expressions
138
        ("complex_1", "!=1234,<1234", [(True, "field", "1234"), (False, "field__lt", "1234")]),
139
        ("complex_2", ">1234,<4567", [(False, "field__gt", "1234"), (False, "field__lt", "4567")]),
140
        # invalid
141
        ("invalid_null_1", ">null", []),
142
        ("invalid_null_2", ">=null", []),
143
        ("invalid_null_3", "<null", []),
144
        ("invalid_null_4", "<=null", []),
145
    ]
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc