Skip to content

Commit 4b5764b

Browse files
authored
For #46904, site wide tk-config-default2 (#172)
Adds support for a None entity link during sub-entity searches in Mockgun and PEP8ed mockgun.py
1 parent 21dc3a9 commit 4b5764b

File tree

2 files changed

+72
-32
lines changed

2 files changed

+72
-32
lines changed

shotgun_api3/lib/mockgun/mockgun.py

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@
116116

117117
import datetime
118118

119-
from ... import sg_timezone, ShotgunError
119+
from ... import ShotgunError
120120
from ...shotgun import _Config
121121
from .errors import MockgunError
122122
from .schema import SchemaFactory
@@ -220,7 +220,6 @@ def __init__(self,
220220
###################################################################################################
221221
# public API methods
222222

223-
224223
def get_session_token(self):
225224
return "bogus_session_token"
226225

@@ -245,15 +244,16 @@ def schema_field_read(self, entity_type, field_name=None):
245244
else:
246245
return dict((k, v) for k, v in self._schema[entity_type].items() if k == field_name)
247246

248-
249-
def find(self, entity_type, filters, fields=None, order=None, filter_operator=None, limit=0, retired_only=False, page=0):
250-
247+
def find(
248+
self, entity_type, filters, fields=None, order=None, filter_operator=None,
249+
limit=0, retired_only=False, page=0
250+
):
251251

252252
self.finds += 1
253253

254254
self._validate_entity_type(entity_type)
255255
# do not validate custom fields - this makes it hard to mock up a field quickly
256-
#self._validate_entity_fields(entity_type, fields)
256+
# self._validate_entity_fields(entity_type, fields)
257257

258258
# FIXME: This should be refactored so that we can use the complex filer
259259
# style in nested filter operations.
@@ -271,10 +271,10 @@ def find(self, entity_type, filters, fields=None, order=None, filter_operator=No
271271

272272
if len(f["values"]) != 1:
273273
# {'path': 'id', 'relation': 'in', 'values': [1,2,3]} --> ["id", "in", [1,2,3]]
274-
resolved_filters.append([ f["path"], f["relation"], f["values"] ])
274+
resolved_filters.append([f["path"], f["relation"], f["values"]])
275275
else:
276276
# {'path': 'id', 'relation': 'is', 'values': [3]} --> ["id", "is", 3]
277-
resolved_filters.append([ f["path"], f["relation"], f["values"][0] ])
277+
resolved_filters.append([f["path"], f["relation"], f["values"][0]])
278278

279279
else:
280280
# traditiona style sg filters
@@ -315,9 +315,14 @@ def find(self, entity_type, filters, fields=None, order=None, filter_operator=No
315315

316316
return val
317317

318-
319-
def find_one(self, entity_type, filters, fields=None, order=None, filter_operator=None, retired_only=False):
320-
results = self.find(entity_type, filters, fields=fields, order=order, filter_operator=filter_operator, retired_only=retired_only)
318+
def find_one(
319+
self, entity_type, filters, fields=None, order=None, filter_operator=None,
320+
retired_only=False
321+
):
322+
results = self.find(
323+
entity_type, filters, fields=fields,
324+
order=order, filter_operator=filter_operator, retired_only=retired_only
325+
)
321326
return results[0] if results else None
322327

323328
def batch(self, requests):
@@ -440,22 +445,44 @@ def _validate_entity_data(self, entity_type, data):
440445

441446
if field_info["data_type"]["value"] == "multi_entity":
442447
if not isinstance(item, list):
443-
raise ShotgunError("%s.%s is of type multi_entity, but data %s is not a list" % (entity_type, field, item))
448+
raise ShotgunError(
449+
"%s.%s is of type multi_entity, but data %s is not a list" %
450+
(entity_type, field, item)
451+
)
444452
elif item and any(not isinstance(sub_item, dict) for sub_item in item):
445-
raise ShotgunError("%s.%s is of type multi_entity, but data %s contains a non-dictionary" % (entity_type, field, item))
453+
raise ShotgunError(
454+
"%s.%s is of type multi_entity, but data %s contains a non-dictionary" %
455+
(entity_type, field, item)
456+
)
446457
elif item and any("id" not in sub_item or "type" not in sub_item for sub_item in item):
447-
raise ShotgunError("%s.%s is of type multi-entity, but an item in data %s does not contain 'type' and 'id'" % (entity_type, field, item))
448-
elif item and any(sub_item["type"] not in field_info["properties"]["valid_types"]["value"] for sub_item in item):
449-
raise ShotgunError("%s.%s is of multi-type entity, but an item in data %s has an invalid type (expected one of %s)" % (entity_type, field, item, field_info["properties"]["valid_types"]["value"]))
450-
458+
raise ShotgunError(
459+
"%s.%s is of type multi-entity, but an item in data %s does not contain 'type' and 'id'" %
460+
(entity_type, field, item)
461+
)
462+
elif item and any(
463+
sub_item["type"] not in field_info["properties"]["valid_types"]["value"] for sub_item in item
464+
):
465+
raise ShotgunError(
466+
"%s.%s is of multi-type entity, but an item in data %s has an invalid type (expected one of %s)"
467+
% (entity_type, field, item, field_info["properties"]["valid_types"]["value"])
468+
)
451469

452470
elif field_info["data_type"]["value"] == "entity":
453471
if not isinstance(item, dict):
454-
raise ShotgunError("%s.%s is of type entity, but data %s is not a dictionary" % (entity_type, field, item))
472+
raise ShotgunError(
473+
"%s.%s is of type entity, but data %s is not a dictionary" %
474+
(entity_type, field, item)
475+
)
455476
elif "id" not in item or "type" not in item:
456-
raise ShotgunError("%s.%s is of type entity, but data %s does not contain 'type' and 'id'" % (entity_type, field, item))
457-
#elif item["type"] not in field_info["properties"]["valid_types"]["value"]:
458-
# raise ShotgunError("%s.%s is of type entity, but data %s has an invalid type (expected one of %s)" % (entity_type, field, item, field_info["properties"]["valid_types"]["value"]))
477+
raise ShotgunError(
478+
"%s.%s is of type entity, but data %s does not contain 'type' and 'id'"
479+
% (entity_type, field, item)
480+
)
481+
# elif item["type"] not in field_info["properties"]["valid_types"]["value"]:
482+
# raise ShotgunError(
483+
# "%s.%s is of type entity, but data %s has an invalid type (expected one of %s)" %
484+
# (entity_type, field, item, field_info["properties"]["valid_types"]["value"])
485+
# )
459486

460487
else:
461488
try:
@@ -472,10 +499,16 @@ def _validate_entity_data(self, entity_type, data):
472499
"status_list": basestring,
473500
"url": dict}[sg_type]
474501
except KeyError:
475-
raise ShotgunError("Field %s.%s: Handling for Shotgun type %s is not implemented" % (entity_type, field, sg_type))
502+
raise ShotgunError(
503+
"Field %s.%s: Handling for Shotgun type %s is not implemented" %
504+
(entity_type, field, sg_type)
505+
)
476506

477507
if not isinstance(item, python_type):
478-
raise ShotgunError("%s.%s is of type %s, but data %s is not of type %s" % (entity_type, field, type(item), sg_type, python_type))
508+
raise ShotgunError(
509+
"%s.%s is of type %s, but data %s is not of type %s" %
510+
(entity_type, field, type(item), sg_type, python_type)
511+
)
479512

480513
# TODO: add check for correct timezone
481514

@@ -641,6 +674,9 @@ def _get_field_from_row(self, entity_type, row, field):
641674
sub_field_value = self._get_field_from_row(entity_type2, entity, field3)
642675
values.append(sub_field_value)
643676
return values
677+
# The field is not set, so return None.
678+
elif field_value is None:
679+
return None
644680
# not multi entity, must be entity.
645681
elif not isinstance(field_value, dict):
646682
raise ShotgunError("Invalid deep query field %s.%s" % (entity_type, field))
@@ -652,7 +688,7 @@ def _get_field_from_row(self, entity_type, row, field):
652688

653689
# ok so looks like the value is an entity link
654690
# e.g. db contains: {"sg_sequence": {"type":"Sequence", "id": 123 } }
655-
linked_row = self._db[ field_value["type"] ][ field_value["id"] ]
691+
linked_row = self._db[field_value["type"]][field_value["id"]]
656692

657693
return self._get_field_from_row(entity_type2, linked_row, field3)
658694
else:
@@ -769,7 +805,6 @@ def _row_matches_filters(self, entity_type, row, filters, filter_operator, retir
769805
else:
770806
raise ShotgunError("%s is not a valid filter operator" % filter_operator)
771807

772-
773808
def _update_row(self, entity_type, row, data):
774809
for field in data:
775810
field_type = self._get_field_type(entity_type, field)
@@ -780,11 +815,6 @@ def _update_row(self, entity_type, row, data):
780815
else:
781816
row[field] = data[field]
782817

783-
784818
def _validate_entity_exists(self, entity_type, entity_id):
785819
if entity_id not in self._db[entity_type]:
786820
raise ShotgunError("No entity of type %s exists with id %s" % (entity_type, entity_id))
787-
788-
789-
790-

tests/test_mockgun.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,12 +148,12 @@ def setUp(self):
148148
"""
149149
self._mockgun = Mockgun("https://test.shotgunstudio.com", login="user", password="1234")
150150

151-
self._project_link = self._mockgun.create("Project", {"name": "project"})
151+
self._project_link = self._mockgun.create("Project", {"name": "project", "archived": False})
152152

153153
# This entity will ensure that a populated link field will be comparable.
154154
self._mockgun.create(
155155
"PipelineConfiguration",
156-
{"code": "with_project", "project": self._project_link}
156+
{"code": "with_project", "project": self._project_link, }
157157
)
158158

159159
# This entity will ensure that an unpopulated link field will be comparable.
@@ -180,6 +180,16 @@ def test_searching_for_initialized_entity_field(self):
180180
items = self._mockgun.find("PipelineConfiguration", [["project", "is_not", self._project_link]])
181181
self.assertEqual(len(items), 1)
182182

183+
def test_find_entity_with_none_link(self):
184+
"""
185+
Make sure that we can search for sub entity fields on entities that have the field not set.
186+
"""
187+
# The pipeline configuration without_project doesn't have the project field set, so we're expecting
188+
# it to not be returned here.
189+
items = self._mockgun.find("PipelineConfiguration", [["project.Project.archived", "is", False]])
190+
self.assertEqual(len(items), 1)
191+
self.assertEqual(items[0]["id"], self._project_link["id"])
192+
183193

184194
class TestTextFieldOperators(TestBaseWithExceptionTests):
185195
"""

0 commit comments

Comments
 (0)