Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds negative operators to string variables. #92

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
26 changes: 26 additions & 0 deletions business_rules/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,31 +71,57 @@ def _assert_valid_value_and_cast(self, value):
def equal_to(self, other_string):
return self.value == other_string

@type_operator(FIELD_TEXT)
def not_equal_to(self, other_string):
return self.value != other_string

@type_operator(FIELD_TEXT, label="Equal To (case insensitive)")
def equal_to_case_insensitive(self, other_string):
return self.value.lower() == other_string.lower()

@type_operator(FIELD_TEXT, label="Not Equal To (case insensitive)")
def not_equal_to_case_insensitive(self, other_string):
return self.value.lower() != other_string.lower()

@type_operator(FIELD_TEXT)
def starts_with(self, other_string):
return self.value.startswith(other_string)

@type_operator(FIELD_TEXT)
def does_not_start_with(self, other_string):
return not self.value.startswith(other_string)

@type_operator(FIELD_TEXT)
def ends_with(self, other_string):
return self.value.endswith(other_string)

@type_operator(FIELD_TEXT)
def does_not_end_with(self, other_string):
return not self.value.endswith(other_string)

@type_operator(FIELD_TEXT)
def contains(self, other_string):
return other_string in self.value

@type_operator(FIELD_TEXT)
def does_not_contain(self, other_string):
return other_string not in self.value

@type_operator(FIELD_TEXT)
def matches_regex(self, regex):
return re.search(regex, self.value)

@type_operator(FIELD_TEXT)
def does_not_match_regex(self, regex):
return not re.search(regex, self.value)

@type_operator(FIELD_NO_INPUT)
def non_empty(self):
return bool(self.value)




@export_type
class NumericType(BaseType):
EPSILON = Decimal('0.000001')
Expand Down
110 changes: 65 additions & 45 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,48 +126,68 @@ def test_export_rule_data(self):
'options': []}])

self.assertEqual(all_data.get("variable_type_operators"),
{'boolean': [{'input_type': 'none',
'label': 'Is False',
'name': 'is_false'},
{'input_type': 'none',
'label': 'Is True',
'name': 'is_true'}],
'numeric': [{'input_type': 'numeric',
'label': 'Equal To',
'name': 'equal_to'},
{'input_type': 'numeric', 'label': 'Greater Than', 'name': 'greater_than'},
{'input_type': 'numeric',
'label': 'Greater Than Or Equal To',
'name': 'greater_than_or_equal_to'},
{'input_type': 'numeric', 'label': 'Less Than', 'name': 'less_than'},
{'input_type': 'numeric',
'label': 'Less Than Or Equal To',
'name': 'less_than_or_equal_to'}],
'select': [{'input_type': 'select', 'label': 'Contains', 'name': 'contains'},
{'input_type': 'select',
'label': 'Does Not Contain',
'name': 'does_not_contain'}],
'select_multiple': [{'input_type': 'select_multiple',
'label': 'Contains All',
'name': 'contains_all'},
{'input_type': 'select_multiple',
'label': 'Is Contained By',
'name': 'is_contained_by'},
{'input_type': 'select_multiple',
'label': 'Shares At Least One Element With',
'name': 'shares_at_least_one_element_with'},
{'input_type': 'select_multiple',
'label': 'Shares Exactly One Element With',
'name': 'shares_exactly_one_element_with'},
{'input_type': 'select_multiple',
'label': 'Shares No Elements With',
'name': 'shares_no_elements_with'}],
'string': [{'input_type': 'text', 'label': 'Contains', 'name': 'contains'},
{'input_type': 'text', 'label': 'Ends With', 'name': 'ends_with'},
{'input_type': 'text', 'label': 'Equal To', 'name': 'equal_to'},
{'input_type': 'text',
'label': 'Equal To (case insensitive)',
'name': 'equal_to_case_insensitive'},
{'input_type': 'text', 'label': 'Matches Regex', 'name': 'matches_regex'},
{'input_type': 'none', 'label': 'Non Empty', 'name': 'non_empty'},
{'input_type': 'text', 'label': 'Starts With', 'name': 'starts_with'}]})
{'boolean': [{'input_type': 'none', 'label': 'Is False', 'name': 'is_false'},
{'input_type': 'none', 'label': 'Is True', 'name': 'is_true'}],
'numeric': [{'input_type': 'numeric', 'label': 'Equal To', 'name': 'equal_to'},
{'input_type': 'numeric',
'label': 'Greater Than',
'name': 'greater_than'},
{'input_type': 'numeric',
'label': 'Greater Than Or Equal To',
'name': 'greater_than_or_equal_to'},
{'input_type': 'numeric',
'label': 'Less Than',
'name': 'less_than'},
{'input_type': 'numeric',
'label': 'Less Than Or Equal To',
'name': 'less_than_or_equal_to'}],
'select': [{'input_type': 'select', 'label': 'Contains', 'name': 'contains'},
{'input_type': 'select',
'label': 'Does Not Contain',
'name': 'does_not_contain'}],
'select_multiple': [{'input_type': 'select_multiple',
'label': 'Contains All',
'name': 'contains_all'},
{'input_type': 'select_multiple',
'label': 'Is Contained By',
'name': 'is_contained_by'},
{'input_type': 'select_multiple',
'label': 'Shares At Least One Element With',
'name': 'shares_at_least_one_element_with'},
{'input_type': 'select_multiple',
'label': 'Shares Exactly One Element With',
'name': 'shares_exactly_one_element_with'},
{'input_type': 'select_multiple',
'label': 'Shares No Elements With',
'name': 'shares_no_elements_with'}],
'string': [{'input_type': 'text', 'label': 'Contains', 'name': 'contains'},
{'input_type': 'text',
'label': 'Does Not Contain',
'name': 'does_not_contain'},
{'input_type': 'text',
'label': 'Does Not End With',
'name': 'does_not_end_with'},
{'input_type': 'text',
'label': 'Does Not Match Regex',
'name': 'does_not_match_regex'},
{'input_type': 'text',
'label': 'Does Not Start With',
'name': 'does_not_start_with'},
{'input_type': 'text', 'label': 'Ends With', 'name': 'ends_with'},
{'input_type': 'text', 'label': 'Equal To', 'name': 'equal_to'},
{'input_type': 'text',
'label': 'Equal To (case insensitive)',
'name': 'equal_to_case_insensitive'},
{'input_type': 'text',
'label': 'Matches Regex',
'name': 'matches_regex'},
{'input_type': 'none', 'label': 'Non Empty', 'name': 'non_empty'},
{'input_type': 'text',
'label': 'Not Equal To',
'name': 'not_equal_to'},
{'input_type': 'text',
'label': 'Not Equal To (case insensitive)',
'name': 'not_equal_to_case_insensitive'},
{'input_type': 'text',
'label': 'Starts With',
'name': 'starts_with'}]})
30 changes: 30 additions & 0 deletions tests/test_operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,62 @@ def test_string_equal_to(self):
self.assertTrue(StringType("foo").equal_to("foo"))
self.assertFalse(StringType("foo").equal_to("Foo"))

def test_string_not_equal_to(self):
self.assertFalse(StringType("foo").not_equal_to("foo"))
self.assertTrue(StringType("foo").not_equal_to("Foo"))

def test_string_equal_to_case_insensitive(self):
self.assertTrue(StringType("foo").equal_to_case_insensitive("FOo"))
self.assertTrue(StringType("foo").equal_to_case_insensitive("foo"))
self.assertFalse(StringType("foo").equal_to_case_insensitive("blah"))

def test_string_not_equal_to_case_insensitive(self):
self.assertFalse(StringType("foo").not_equal_to_case_insensitive("FOo"))
self.assertFalse(StringType("foo").not_equal_to_case_insensitive("foo"))
self.assertTrue(StringType("foo").not_equal_to_case_insensitive("blah"))

def test_string_starts_with(self):
self.assertTrue(StringType("hello").starts_with("he"))
self.assertFalse(StringType("hello").starts_with("hey"))
self.assertFalse(StringType("hello").starts_with("He"))

def test_string_does_not_start_with(self):
self.assertFalse(StringType("hello").does_not_start_with("he"))
self.assertTrue(StringType("hello").does_not_start_with("hey"))
self.assertTrue(StringType("hello").does_not_start_with("He"))

def test_string_ends_with(self):
self.assertTrue(StringType("hello").ends_with("lo"))
self.assertFalse(StringType("hello").ends_with("boom"))
self.assertFalse(StringType("hello").ends_with("Lo"))

def test_string_does_not_end_with(self):
self.assertFalse(StringType("hello").does_not_end_with("lo"))
self.assertTrue(StringType("hello").does_not_end_with("boom"))
self.assertTrue(StringType("hello").does_not_end_with("Lo"))

def test_string_contains(self):
self.assertTrue(StringType("hello").contains("ell"))
self.assertTrue(StringType("hello").contains("he"))
self.assertTrue(StringType("hello").contains("lo"))
self.assertFalse(StringType("hello").contains("asdf"))
self.assertFalse(StringType("hello").contains("ElL"))

def test_string_does_not_contain(self):
self.assertFalse(StringType("hello").does_not_contain("ell"))
self.assertFalse(StringType("hello").does_not_contain("he"))
self.assertFalse(StringType("hello").does_not_contain("lo"))
self.assertTrue(StringType("hello").does_not_contain("asdf"))
self.assertTrue(StringType("hello").does_not_contain("ElL"))

def test_string_matches_regex(self):
self.assertTrue(StringType("hello").matches_regex(r"^h"))
self.assertFalse(StringType("hello").matches_regex(r"^sh"))

def test_string_does_not_match_regex(self):
self.assertFalse(StringType("hello").does_not_match_regex(r"^h"))
self.assertTrue(StringType("hello").does_not_match_regex(r"^sh"))

def test_non_empty(self):
self.assertTrue(StringType("hello").non_empty())
self.assertFalse(StringType("").non_empty())
Expand Down