Skip to content

Commit 8c505f2

Browse files
author
Matt Sokoloff
committed
recommended changes
1 parent 9a12f87 commit 8c505f2

File tree

2 files changed

+29
-15
lines changed

2 files changed

+29
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Delete users from organization
1010
* Example notebook added under examples/basics
1111
* Issues and comments export
12-
* Bulk export issues and comments. See `Project.export_labels`
12+
* Bulk export issues and comments. See `Project.export_issues`
1313
* MAL on Tiled Imagery
1414
* Example notebook added under examples/model_assisted_labeling
1515
* `Dataset.create_data_rows` now allows users to upload tms imagery

labelbox/orm/model.py

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from enum import Enum, auto
2-
from typing import Dict, Union
2+
from typing import Dict, List, Union
33

44
from labelbox import utils
55
from labelbox.exceptions import InvalidAttributeError
@@ -239,22 +239,31 @@ class EntityMeta(type):
239239
of the Entity class object so they can be referenced for example like:
240240
Entity.Project.
241241
"""
242-
mappings: Dict[str, "Entity"] = {}
242+
# Maps Entity name to Relationships for all currently defined Entities
243+
relationship_mappings: Dict[str, List[Relationship]] = {}
243244

244245
def __init__(cls, clsname, superclasses, attributedict):
245246
super().__init__(clsname, superclasses, attributedict)
246247
cls.validate_cached_relationships()
247248
if clsname != "Entity":
248249
setattr(Entity, clsname, cls)
249-
EntityMeta.mappings[utils.snake_case(
250+
EntityMeta.relationship_mappings[utils.snake_case(
250251
cls.__name__)] = cls.relationships()
251252

252253
@staticmethod
253-
def raise_for_nested_cache(first: str, middle: str, last: str):
254+
def raise_for_nested_cache(first: str, middle: str, last: List[str]):
254255
raise TypeError(
255256
"Cannot cache a relationship to an Entity with its own cached relationship(s). "
256257
f"`{first}` caches `{middle}` which caches `{last}`")
257258

259+
@staticmethod
260+
def cached_entities(entity_name : str):
261+
"""
262+
Return all cached entites for a given Entity name
263+
"""
264+
cached_entities = EntityMeta.relationship_mappings.get(entity_name, [])
265+
return {entity.name : entity for entity in cached_entities if entity.cache}
266+
258267
def validate_cached_relationships(cls):
259268
"""
260269
Graphql doesn't allow for infinite nesting in queries.
@@ -270,23 +279,28 @@ def validate_cached_relationships(cls):
270279
A two way check is necessary because checks are performed as classes are being defined.
271280
As opposed to after all objects have been created.
272281
"""
282+
# All cached relationships
273283
cached_rels = [r for r in cls.relationships() if r.cache]
284+
274285
# Check if any cached entities have their own cached fields
275286
for rel in cached_rels:
276-
cached_entities = EntityMeta.mappings.get(rel.name, [])
277-
nested = [entity.name for entity in cached_entities if entity.cache]
287+
nested = cls.cached_entities(rel.name)
278288
if nested:
279289
cls.raise_for_nested_cache(utils.snake_case(cls.__name__),
280-
rel.name, nested)
290+
rel.name, list(nested.keys()))
281291

282-
# If this entity caches any other entity
283-
# then check if any entity caches this entity
292+
# If the current Entity (cls) has any cached relationships (cached_rels)
293+
# then no other defined Entity (entities in EntityMeta.relationship_mappings) can cache this Entity.
284294
if cached_rels:
285-
for entity_name, entity_relationships in EntityMeta.mappings.items(
286-
):
287-
attr = {rel.name: rel for rel in entity_relationships
288-
}.get(utils.snake_case(cls.__name__))
289-
if attr and attr.cache:
295+
# For all currently defined Entities
296+
for entity_name in EntityMeta.relationship_mappings:
297+
# Get all cached ToOne relationships
298+
rels = cls.cached_entities(entity_name)
299+
# Check if the current Entity (cls) is referenced by the Entity with `entity_name`
300+
rel = rels.get(utils.snake_case(cls.__name__))
301+
# If rel exists and is cached then raise an exception
302+
# This means `entity_name` caches `cls` which cached items in `cached_rels`
303+
if rel and rel.cache:
290304
cls.raise_for_nested_cache(
291305
utils.snake_case(entity_name),
292306
utils.snake_case(cls.__name__),

0 commit comments

Comments
 (0)