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

SG-37203 [Mockgun] Ensure string comparison are case insensitive #217

Open
wants to merge 2 commits 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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion shotgun_api3/lib/mockgun/mockgun.py
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,22 @@ def _compare(self, field_type, lval, operator, rval):
if operator == "is":
return lval == rval
elif field_type == "text":
# Some operations expect a list but can deal with a single value
if operator in ("in", "not_in") and not isinstance(rval, list):
rval = [rval]

# Some operation expect a string but can deal with None
elif operator in ("starts_with", "ends_with", "contains", "not_contains"):
lval = lval or ''
rval = rval or ''

# Shotgun string comparison is case insensitive
lval = lval.lower() if lval is not None else None
if isinstance(rval, list):
rval = [val.lower() if val is not None else None for val in rval]
else:
rval = rval.lower() if rval is not None else None

if operator == "is":
return lval == rval
elif operator == "is_not":
Expand All @@ -605,7 +621,7 @@ def _compare(self, field_type, lval, operator, rval):
elif operator == "contains":
return rval in lval
elif operator == "not_contains":
return lval not in rval
return rval not in lval
elif operator == "starts_with":
return lval.startswith(rval)
elif operator == "ends_with":
Expand Down
169 changes: 165 additions & 4 deletions tests/test_mockgun.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,175 @@ def setUp(self):
Creates test data.
"""
self._mockgun = Mockgun("https://test.shotgunstudio.com", login="user", password="1234")
self._user = self._mockgun.create("HumanUser", {"login": "user"})
self._user1 = self._mockgun.create("HumanUser", {"login": "user"})
self._user2 = self._mockgun.create("HumanUser", {"login": None})

def test_operator_is(self):
"""
Ensure is operator work.
"""
actual = self._mockgun.find("HumanUser", [["login", "is", "user"]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_is_none(self):
"""
Ensure is operator work when used with None.
"""
actual = self._mockgun.find("HumanUser", [["login", "is", None]])
expected = [{"type": "HumanUser", "id": self._user2["id"]}]
self.assertEqual(expected, actual)

def test_operator_is_case_sensitivity(self):
"""
Ensure is operator is case insensitive.
"""
actual = self._mockgun.find("HumanUser", [["login", "is", "USER"]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_is_not(self):
"""
Ensure the is_not operator works.
"""
actual = self._mockgun.find("HumanUser", [["login", "is_not", "user"]])
expected = [{"type": "HumanUser", "id": self._user2["id"]}]
self.assertEqual(expected, actual)

def test_operator_is_not_none(self):
"""
Ensure the is_not operator works when used with None.
"""
actual = self._mockgun.find("HumanUser", [["login", "is_not", None]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_is_not_case_sensitivity(self):
"""
Ensure the is_not operator is case insensitive.
"""
actual = self._mockgun.find("HumanUser", [["login", "is_not", "USER"]])
expected = [{"type": "HumanUser", "id": self._user2["id"]}]
self.assertEqual(expected, actual)

def test_operator_in(self):
"""
Ensure the in operator works.
"""
actual = self._mockgun.find("HumanUser", [["login", "in", ["user"]]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_in_none(self):
"""
Ensure the in operator works with a list containing None.
"""
actual = self._mockgun.find("HumanUser", [["login", "in", [None]]])
expected = [{"type": "HumanUser", "id": self._user2["id"]}]
self.assertEqual(expected, actual)

def test_operator_in_case_sensitivity(self):
"""
Ensure the in operator is case insensitive.
"""
actual = self._mockgun.find("HumanUser", [["login", "in", ["USER"]]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_not_in(self):
"""
Ensure the not_in operator works.
"""
actual = self._mockgun.find("HumanUser", [["login", "not_in", ["foo"]]])
expected = [
{"type": "HumanUser", "id": self._user1["id"]},
{"type": "HumanUser", "id": self._user2["id"]}
]
self.assertEqual(expected, actual)

def test_operator_not_in_none(self):
"""
Ensure the not_not operator works with a list containing None.
"""
actual = self._mockgun.find("HumanUser", [["login", "not_in", [None]]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_not_in_case_sensitivity(self):
"""
Ensure the not_in operator is case insensitive.
"""
actual = self._mockgun.find("HumanUser", [["login", "not_in", ["USER"]]])
expected = [{"type": "HumanUser", "id": self._user2["id"]}]
self.assertEqual(expected, actual)

def test_operator_contains(self):
"""
Ensures contains operator works.
Ensures the contains operator works.
"""
actual = self._mockgun.find("HumanUser", [["login", "contains", "se"]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_contains_case_sensitivity(self):
"""
Ensure the contains operator is case insensitive.
"""
actual = self._mockgun.find("HumanUser", [["login", "contains", "SE"]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_not_contains(self):
"""
Ensure the not_contains operator works.
"""
actual = self._mockgun.find("HumanUser", [["login", "not_contains", "user"]])
expected = [
{"type": "HumanUser", "id": self._user2["id"]}
]
self.assertEqual(expected, actual)

def test_operator_not_contains_case_sensitivity(self):
"""
Ensure the not_contains operator is case insensitive.
"""
actual = self._mockgun.find("HumanUser", [["login", "not_contains", "USER"]])
expected = [
{"type": "HumanUser", "id": self._user2["id"]}
]
self.assertEqual(expected, actual)

def test_operator_starts_with(self):
"""
Ensure the starts_with operator works.
"""
actual = self._mockgun.find("HumanUser", [["login", "starts_with", "us"]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_starts_with_case_sensitivity(self):
"""
Ensure the starts_with operator is case insensitive.
"""
actual = self._mockgun.find("HumanUser", [["login", "starts_with", "US"]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_ends_with(self):
"""
Ensure the ends_with operator works.
"""
actual = self._mockgun.find("HumanUser", [["login", "ends_with", "er"]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)

def test_operator_ends_with_case_sensitivity(self):
"""
Ensure the starts_with operator is case insensitive.
"""
item = self._mockgun.find_one("HumanUser", [["login", "contains", "se"]])
self.assertTrue(item)
actual = self._mockgun.find("HumanUser", [["login", "ends_with", "ER"]])
expected = [{"type": "HumanUser", "id": self._user1["id"]}]
self.assertEqual(expected, actual)


class TestMultiEntityFieldComparison(TestBaseWithExceptionTests):
Expand Down