Skip to content

Commit 4cba13d

Browse files
committed
update to clean up some dependencies and utilize Entity more
1 parent 98eb8fd commit 4cba13d

File tree

13 files changed

+98
-76
lines changed

13 files changed

+98
-76
lines changed

labelbox/orm/model.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,10 @@ class Entity(metaclass=EntityMeta):
343343
IAMIntegration: Type[labelbox.IAMIntegration]
344344
LabelingFrontendOptions: Type[labelbox.LabelingFrontendOptions]
345345
Label: Type[labelbox.Label]
346+
MEAPredictionImport: Type[labelbox.MEAPredictionImport]
347+
Invite: Type[labelbox.Invite]
348+
InviteLimit: Type[labelbox.InviteLimit]
349+
ProjectRole: Type[labelbox.ProjectRole]
346350

347351
@classmethod
348352
def _attributes_of_type(cls, attr_type):

labelbox/schema/bulk_import_request.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,19 @@
1212
from pydantic import BaseModel, validator
1313
from typing_extensions import Literal
1414
from typing import (Any, List, Optional, BinaryIO, Dict, Iterable, Tuple, Union,
15-
Type, Set)
15+
Type, Set, TYPE_CHECKING)
1616

17-
import labelbox
17+
from labelbox import exceptions as lb_exceptions
18+
from labelbox.orm.model import Entity
1819
from labelbox import utils
1920
from labelbox.orm import query
2021
from labelbox.orm.db_object import DbObject
2122
from labelbox.orm.model import Field, Relationship
2223
from labelbox.schema.enums import BulkImportRequestState
2324

25+
if TYPE_CHECKING:
26+
from labelbox import Project
27+
2428
NDJSON_MIME_TYPE = "application/x-ndjson"
2529
logger = logging.getLogger(__name__)
2630

@@ -67,7 +71,7 @@ def _send_create_file_command(
6771
response = client.execute(data=request_data, files={file_name: file_data})
6872

6973
if not response.get("createBulkImportRequest", None):
70-
raise labelbox.exceptions.LabelboxError(
74+
raise lb_exceptions.LabelboxError(
7175
"Failed to create BulkImportRequest, message: %s" %
7276
response.get("errors", None) or response.get("error", None))
7377

@@ -192,9 +196,8 @@ def wait_until_done(self, sleep_time_seconds: int = 5) -> None:
192196
self.__exponential_backoff_refresh()
193197

194198
@backoff.on_exception(
195-
backoff.expo,
196-
(labelbox.exceptions.ApiLimitError, labelbox.exceptions.TimeoutError,
197-
labelbox.exceptions.NetworkError),
199+
backoff.expo, (lb_exceptions.ApiLimitError, lb_exceptions.TimeoutError,
200+
lb_exceptions.NetworkError),
198201
max_tries=10,
199202
jitter=None)
200203
def __exponential_backoff_refresh(self) -> None:
@@ -387,7 +390,7 @@ def delete(self) -> None:
387390

388391

389392
def _validate_ndjson(lines: Iterable[Dict[str, Any]],
390-
project: "labelbox.Project") -> None:
393+
project: "Project") -> None:
391394
"""
392395
Client side validation of an ndjson object.
393396
@@ -413,12 +416,12 @@ def _validate_ndjson(lines: Iterable[Dict[str, Any]],
413416
annotation.validate_instance(feature_schemas)
414417
uuid = str(annotation.uuid)
415418
if uuid in uids:
416-
raise labelbox.exceptions.UuidError(
419+
raise lb_exceptions.UuidError(
417420
f'{uuid} already used in this import job, '
418421
'must be unique for the project.')
419422
uids.add(uuid)
420423
except (pydantic.ValidationError, ValueError, TypeError, KeyError) as e:
421-
raise labelbox.exceptions.MALValidationError(
424+
raise lb_exceptions.MALValidationError(
422425
f"Invalid NDJson on line {idx}") from e
423426

424427

labelbox/schema/data_row.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import logging
22
from datetime import datetime
3-
from typing import List, Dict, Union
3+
from typing import List, Dict, Union, TYPE_CHECKING
44

55
from labelbox.orm import query
66
from labelbox.orm.db_object import DbObject, Updateable, BulkDeletable
77
from labelbox.orm.model import Entity, Field, Relationship
8-
from labelbox.schema.asset_attachment import AssetAttachment
8+
9+
if TYPE_CHECKING:
10+
from labelbox import AssetAttachment
911

1012
logger = logging.getLogger(__name__)
1113

@@ -41,7 +43,7 @@ class DataRow(DbObject, Updateable, BulkDeletable):
4143
attachments = Relationship.ToMany("AssetAttachment", False, "attachments")
4244

4345
supported_meta_types = supported_attachment_types = set(
44-
AssetAttachment.AttachmentType.__members__)
46+
Entity.AssetAttachment.AttachmentType.__members__)
4547

4648
def __init__(self, *args, **kwargs):
4749
super().__init__(*args, **kwargs)
@@ -58,7 +60,7 @@ def bulk_delete(data_rows) -> None:
5860
BulkDeletable._bulk_delete(data_rows, True)
5961

6062
def create_attachment(self, attachment_type,
61-
attachment_value) -> AssetAttachment:
63+
attachment_value) -> "AssetAttachment":
6264
""" Adds an AssetAttachment to a DataRow.
6365
Labelers can view these attachments while labeling.
6466
@@ -73,7 +75,7 @@ def create_attachment(self, attachment_type,
7375
Raises:
7476
ValueError: asset_type must be one of the supported types.
7577
"""
76-
AssetAttachment.validate_attachment_type(attachment_type)
78+
Entity.AssetAttachment.validate_attachment_type(attachment_type)
7779

7880
attachment_type_param = "type"
7981
attachment_value_param = "value"

labelbox/schema/dataset.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Generator, List, Union, Any
1+
from typing import Generator, List, Union, Any, TYPE_CHECKING
22
import os
33
import json
44
import logging
@@ -7,19 +7,18 @@
77
import ndjson
88
from itertools import islice
99

10-
from labelbox.data.serialization.ndjson.base import DataRow
11-
from labelbox.schema import iam_integration
12-
from labelbox.schema.task import Task
13-
from labelbox.schema.user import User
14-
from labelbox import utils
1510
from concurrent.futures import ThreadPoolExecutor, as_completed
1611
from io import StringIO
1712
import requests
1813

14+
from labelbox import utils
1915
from labelbox.exceptions import InvalidQueryError, LabelboxError, ResourceNotFoundError, InvalidAttributeError
2016
from labelbox.orm.db_object import DbObject, Updateable, Deletable
2117
from labelbox.orm.model import Entity, Field, Relationship
2218

19+
if TYPE_CHECKING:
20+
from labelbox import Task, User, DataRow
21+
2322
logger = logging.getLogger(__name__)
2423

2524

@@ -53,7 +52,7 @@ class Dataset(DbObject, Updateable, Deletable):
5352
iam_integration = Relationship.ToOne("IAMIntegration", False,
5453
"iam_integration", "signer")
5554

56-
def create_data_row(self, **kwargs) -> DataRow:
55+
def create_data_row(self, **kwargs) -> "DataRow":
5756
""" Creates a single DataRow belonging to this dataset.
5857
5958
>>> dataset.create_data_row(row_data="http://my_site.com/photos/img_01.jpg")
@@ -122,7 +121,7 @@ def create_data_rows_sync(self, items) -> None:
122121
url_param: descriptor_url
123122
})
124123

125-
def create_data_rows(self, items) -> Union[Task, List[Any]]:
124+
def create_data_rows(self, items) -> Union["Task", List[Any]]:
126125
""" Asynchronously bulk upload data rows
127126
128127
Use this instead of `Dataset.create_data_rows_sync` uploads for batches that contain more than 1000 data rows.
@@ -317,7 +316,9 @@ def convert_item(item):
317316
data = json.dumps(items)
318317
return self.client.upload_data(data)
319318

320-
def data_rows_for_external_id(self, external_id, limit=10) -> List[DataRow]:
319+
def data_rows_for_external_id(self,
320+
external_id,
321+
limit=10) -> List["DataRow"]:
321322
""" Convenience method for getting a multiple `DataRow` belonging to this
322323
`Dataset` that has the given `external_id`.
323324
@@ -344,7 +345,7 @@ def data_rows_for_external_id(self, external_id, limit=10) -> List[DataRow]:
344345
raise ResourceNotFoundError(DataRow, where)
345346
return data_rows
346347

347-
def data_row_for_external_id(self, external_id) -> DataRow:
348+
def data_row_for_external_id(self, external_id) -> "DataRow":
348349
""" Convenience method for getting a single `DataRow` belonging to this
349350
`Dataset` that has the given `external_id`.
350351

labelbox/schema/label.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
from labelbox.data.serialization.labelbox_v1.label import Review
1+
from typing import TYPE_CHECKING
2+
23
from labelbox.orm import query
34
from labelbox.orm.db_object import DbObject, Updateable, BulkDeletable
45
from labelbox.orm.model import Entity, Field, Relationship
5-
from labelbox.schema.benchmark import Benchmark
6+
7+
if TYPE_CHECKING:
8+
from labelbox import Benchmark, Review
69
""" Client-side object type definitions. """
710

811

@@ -50,7 +53,7 @@ def bulk_delete(labels) -> None:
5053
"""
5154
BulkDeletable._bulk_delete(labels, False)
5255

53-
def create_review(self, **kwargs) -> Review:
56+
def create_review(self, **kwargs) -> "Review":
5457
""" Creates a Review for this label.
5558
5659
Args:
@@ -60,7 +63,7 @@ def create_review(self, **kwargs) -> Review:
6063
kwargs[Entity.Review.project.name] = self.project()
6164
return self.client._create(Entity.Review, kwargs)
6265

63-
def create_benchmark(self) -> Benchmark:
66+
def create_benchmark(self) -> "Benchmark":
6467
""" Creates a Benchmark for this Label.
6568
6669
Returns:

labelbox/schema/model.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
from typing import TYPE_CHECKING
12
from labelbox.orm import query
23
from labelbox.orm.db_object import DbObject
34
from labelbox.orm.model import Entity, Field, Relationship
4-
from labelbox.schema.model_run import ModelRun
5+
6+
if TYPE_CHECKING:
7+
from labelbox import ModelRun
58

69

710
class Model(DbObject):
@@ -15,7 +18,7 @@ class Model(DbObject):
1518
name = Field.String("name")
1619
model_runs = Relationship.ToMany("ModelRun", False)
1720

18-
def create_model_run(self, name) -> ModelRun:
21+
def create_model_run(self, name) -> "ModelRun":
1922
""" Creates a model run belonging to this model.
2023
2124
Args:

labelbox/schema/model_run.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
from typing import Dict, Iterable, Union
1+
from typing import TYPE_CHECKING, Dict, Iterable, Union
22
from pathlib import Path
33
import os
44
import time
55

66
from labelbox.pagination import PaginatedCollection
7-
from labelbox.schema.annotation_import import MEAPredictionImport
87
from labelbox.orm.query import results_query_part
9-
from labelbox.orm.model import Field, Relationship
8+
from labelbox.orm.model import Field, Relationship, Entity
109
from labelbox.orm.db_object import DbObject
1110

11+
if TYPE_CHECKING:
12+
from labelbox import MEAPredictionImport
13+
1214

1315
class ModelRun(DbObject):
1416
name = Field.String("name")
@@ -119,13 +121,13 @@ def add_predictions(
119121
kwargs = dict(client=self.client, model_run_id=self.uid, name=name)
120122
if isinstance(predictions, str) or isinstance(predictions, Path):
121123
if os.path.exists(predictions):
122-
return MEAPredictionImport.create_from_file(
124+
return Entity.MEAPredictionImport.create_from_file(
123125
path=str(predictions), **kwargs)
124126
else:
125-
return MEAPredictionImport.create_from_url(url=str(predictions),
126-
**kwargs)
127+
return Entity.MEAPredictionImport.create_from_url(
128+
url=str(predictions), **kwargs)
127129
elif isinstance(predictions, Iterable):
128-
return MEAPredictionImport.create_from_objects(
130+
return Entity.MEAPredictionImport.create_from_objects(
129131
predictions=predictions, **kwargs)
130132
else:
131133
raise ValueError(

labelbox/schema/ontology.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88
from pydantic import constr
99

10-
# from labelbox.schema import project
1110
from labelbox.exceptions import InconsistentOntologyException
1211
from labelbox.orm.db_object import DbObject
1312
from labelbox.orm.model import Field, Relationship

labelbox/schema/organization.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
1-
from typing import List, Optional
1+
from typing import TYPE_CHECKING, List, Optional
22

33
from labelbox.exceptions import LabelboxError
44
from labelbox import utils
55
from labelbox.orm.db_object import DbObject, query, Entity
66
from labelbox.orm.model import Field, Relationship
7-
from labelbox.schema.iam_integration import IAMIntegration
8-
from labelbox.schema.invite import Invite, InviteLimit, ProjectRole
9-
from labelbox.schema.user import User
10-
from labelbox.schema.role import Role
7+
8+
if TYPE_CHECKING:
9+
from labelbox import Role, User, ProjectRole, Invite, InviteLimit, IAMIntegration
1110

1211

1312
class Organization(DbObject):
@@ -46,8 +45,8 @@ def __init__(self, *args, **kwargs):
4645
def invite_user(
4746
self,
4847
email: str,
49-
role: Role,
50-
project_roles: Optional[List[ProjectRole]] = None) -> Invite:
48+
role: "Role",
49+
project_roles: Optional[List["ProjectRole"]] = None) -> "Invite":
5150
"""
5251
Invite a new member to the org. This will send the user an email invite
5352
@@ -73,7 +72,7 @@ def invite_user(
7372
data_param = "data"
7473
query_str = """mutation createInvitesPyApi($%s: [CreateInviteInput!]){
7574
createInvites(data: $%s){ invite { id createdAt organizationRoleName inviteeEmail inviter { %s } }}}""" % (
76-
data_param, data_param, query.results_query_part(User))
75+
data_param, data_param, query.results_query_part(Entity.User))
7776

7877
projects = [{
7978
"projectId": project_role.project.uid,
@@ -93,9 +92,9 @@ def invite_user(
9392
invite_response = res['createInvites'][0]['invite']
9493
if not invite_response:
9594
raise LabelboxError(f"Unable to send invite for email {email}")
96-
return Invite(self.client, invite_response)
95+
return Entity.Invite(self.client, invite_response)
9796

98-
def invite_limit(self) -> InviteLimit:
97+
def invite_limit(self) -> "InviteLimit":
9998
""" Retrieve invite limits for the org
10099
This already accounts for users currently in the org
101100
Meaining that `used = users + invites, remaining = limit - (users + invites)`
@@ -109,10 +108,10 @@ def invite_limit(self) -> InviteLimit:
109108
"""query InvitesLimitPyApi($%s: ID!) {
110109
invitesLimit(where: {id: $%s}) { used limit remaining }
111110
}""" % (org_id_param, org_id_param), {org_id_param: self.uid})
112-
return InviteLimit(
111+
return Entity.InviteLimit(
113112
**{utils.snake_case(k): v for k, v in res['invitesLimit'].items()})
114113

115-
def remove_user(self, user: User) -> None:
114+
def remove_user(self, user: "User") -> None:
116115
"""
117116
Deletes a user from the organization. This cannot be undone without sending another invite.
118117
@@ -126,7 +125,7 @@ def remove_user(self, user: User) -> None:
126125
updateUser(where: {id: $%s}, data: {deleted: true}) { id deleted }
127126
}""" % (user_id_param, user_id_param), {user_id_param: user.uid})
128127

129-
def get_iam_integrations(self) -> List[IAMIntegration]:
128+
def get_iam_integrations(self) -> List["IAMIntegration"]:
130129
"""
131130
Returns all IAM Integrations for an organization
132131
"""
@@ -145,7 +144,7 @@ def get_iam_integrations(self) -> List[IAMIntegration]:
145144
for integration_data in res['iamIntegrations']
146145
]
147146

148-
def get_default_iam_integration(self) -> Optional[IAMIntegration]:
147+
def get_default_iam_integration(self) -> Optional["IAMIntegration"]:
149148
"""
150149
Returns the default IAM integration for the organization.
151150
Will return None if there are no default integrations for the org.

0 commit comments

Comments
 (0)