Skip to content

Commit 10cf8de

Browse files
author
Matt Sokoloff
committed
update pagination, other small changes
1 parent 132ffc6 commit 10cf8de

File tree

4 files changed

+74
-56
lines changed

4 files changed

+74
-56
lines changed

labelbox/pagination.py

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@ def __init__(self,
4242
self.obj_class = obj_class
4343
self.experimental = experimental
4444

45-
self._fetched_pages = 0
4645
self._fetched_all = False
4746
self._data = []
4847
self._data_ind = 0
49-
self.next_cursor = None
50-
self.cursor_path = cursor_path
48+
49+
if cursor_path:
50+
self.paginator = _CursorPagination(client, cursor_path)
51+
else:
52+
self.paginator = _OffsetPagination(client)
5153

5254
def __iter__(self):
5355
self._data_ind = 0
@@ -56,47 +58,64 @@ def __iter__(self):
5658
def get_page_data(self, results):
5759
for deref in self.dereferencing:
5860
results = results[deref]
59-
6061
return [self.obj_class(self.client, result) for result in results]
6162

62-
def get_next_cursor(self, results):
63-
for path in self.cursor_path:
64-
results = results[path]
65-
return results
66-
67-
def get_query(self):
68-
if self.cursor_path:
69-
# Cursor Pagination
70-
self.params.update({'from': self.next_cursor, 'first': _PAGE_SIZE})
71-
return self.query
72-
73-
# Offset Pagination
74-
return self.query % (self._fetched_pages * _PAGE_SIZE, _PAGE_SIZE)
75-
7663
def __next__(self):
7764
if len(self._data) <= self._data_ind:
7865
if self._fetched_all:
7966
raise StopIteration()
8067

81-
results = self.client.execute(self.get_query(),
82-
self.params,
83-
experimental=self.experimental)
84-
self._fetched_pages += 1
85-
68+
results = self.paginator.fetch_results(self.query, self.params,
69+
self.experimental)
8670
page_data = self.get_page_data(results)
8771
self._data.extend(page_data)
72+
n_items = len(page_data)
8873

89-
if len(page_data) < _PAGE_SIZE:
90-
self._fetched_all = True
91-
92-
if len(page_data) == 0:
74+
if n_items == 0:
9375
raise StopIteration()
9476

95-
if self.cursor_path:
96-
self.next_cursor = self.get_next_cursor(results)
97-
if self.next_cursor is None:
98-
self._fetched_all = True
77+
self._fetched_all = self.paginator.fetched_all(n_items, results)
9978

10079
rval = self._data[self._data_ind]
10180
self._data_ind += 1
10281
return rval
82+
83+
84+
class _CursorPagination:
85+
86+
def __init__(self, client, cursor_path):
87+
self.client = client
88+
self.cursor_path = cursor_path
89+
self.next_cursor = None
90+
91+
def get_next_cursor(self, results):
92+
for path in self.cursor_path:
93+
results = results[path]
94+
return results
95+
96+
def fetched_all(self, n_items, results):
97+
self.next_cursor = self.get_next_cursor(results)
98+
if self.next_cursor is None:
99+
return True
100+
return False
101+
102+
def fetch_results(self, query, params, experimental):
103+
params.update({'from': self.next_cursor, 'first': _PAGE_SIZE})
104+
return self.client.execute(query, params, experimental=experimental)
105+
106+
107+
class _OffsetPagination:
108+
109+
def __init__(self, client):
110+
self.client = client
111+
self._fetched_pages = 0
112+
113+
def fetched_all(self, n_items, results):
114+
self._fetched_pages += 1
115+
if n_items < _PAGE_SIZE:
116+
return True
117+
return False
118+
119+
def fetch_results(self, query, params, experimental):
120+
query = query % (self._fetched_pages * _PAGE_SIZE, _PAGE_SIZE)
121+
return self.client.execute(query, params, experimental=experimental)

labelbox/schema/invite.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ def __init__(self, client, invite_response):
4545
super().__init__(client, invite_response)
4646

4747
self.project_roles = [
48-
ProjectRole(
49-
project=client.get_project(r['projectId']),
50-
role=client.get_roles()[r['projectRoleName'].upper().replace(
51-
" ", "_")]) for r in project_roles
48+
ProjectRole(project=client.get_project(r['projectId']),
49+
role=client.get_roles()[r['projectRoleName']])
50+
for r in project_roles
5251
]
5352

5453
def revoke(self):

labelbox/schema/organization.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Dict, List
1+
from typing import Any, Dict, List, Optional
22

33
from labelbox.exceptions import LabelboxError
44
from labelbox import utils
@@ -78,9 +78,9 @@ def _assign_user_role(self, email: str, role: Role,
7878
data_param, data_param)
7979

8080
projects = [{
81-
"projectId": x.project.uid,
82-
"projectRoleId": x.role.uid
83-
} for x in project_roles]
81+
"projectId": project_role.project.uid,
82+
"projectRoleId": project_role.role.uid
83+
} for project_role in project_roles]
8484

8585
res = self.client.execute(
8686
query_str, {
@@ -97,30 +97,29 @@ def _assign_user_role(self, email: str, role: Role,
9797
invite_info = res['createInvites'][0]['invite']
9898
return invite_info
9999

100-
def invite_user(self,
101-
email: str,
102-
role: Role,
103-
project_roles: List[ProjectRole] = []) -> Invite:
100+
def invite_user(
101+
self,
102+
email: str,
103+
role: Role,
104+
project_roles: Optional[List[ProjectRole]] = None) -> Invite:
104105
"""
105106
Invite a new member to the org. This will send the user an email invite
106107
107108
Args:
108109
email (str): email address of the user to invite
109110
role (Role): Role to assign to the user
110-
project_roles (List[ProjectRoles]): List of project roles to assign to the User (if they have a project based org role).
111+
project_roles (Optional[List[ProjectRoles]]): List of project roles to assign to the User (if they have a project based org role).
111112
112113
Returns:
113114
Invite for the user
114115
115116
"""
116117
remaining_invites = self.invite_limit().remaining
117118
if remaining_invites == 0:
118-
if next(self.users((User.email == email) &
119-
(User.deleted == True)), None) is None:
120-
raise LabelboxError(
121-
"Invite(s) cannot be sent because you do not have enough available seats in your organization. "
122-
"Please upgrade your account, revoke pending invitations or remove other users."
123-
)
119+
raise LabelboxError(
120+
"Invite(s) cannot be sent because you do not have enough available seats in your organization. "
121+
"Please upgrade your account, revoke pending invitations or remove other users."
122+
)
124123
for invite in self.invites():
125124
if invite.email == email:
126125
raise ValueError(
@@ -130,18 +129,19 @@ def invite_user(self,
130129
if not isinstance(role, Role):
131130
raise TypeError(f"role must be Role type. Found {role}")
132131

133-
if len(project_roles) and role.name != "NONE":
132+
if project_roles and role.name != "NONE":
134133
raise ValueError(
135134
"Project roles cannot be set for a user with organization level permissions. Found role name `{role.name}`, expected `NONE`"
136135
)
137136

138-
for project_role in project_roles:
137+
_project_roles = [] if project_roles is None else project_roles
138+
for project_role in _project_roles:
139139
if not isinstance(project_role, ProjectRole):
140140
raise TypeError(
141141
f"project_roles must be a list of `ProjectRole`s. Found {project_role}"
142142
)
143143

144-
invite_response = self._assign_user_role(email, role, project_roles)
144+
invite_response = self._assign_user_role(email, role, _project_roles)
145145
return Invite(self.client, invite_response)
146146

147147
def user_limit(self) -> UserLimit:

labelbox/schema/role.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@ def __repr__(self):
3838
return str({k: getattr(self, k) for k in self.valid_roles})
3939

4040
def __getitem__(self, name):
41-
if name in self.valid_roles:
42-
return getattr(self, name)
43-
else:
41+
name = name.replace(' ', '_').upper()
42+
if name not in self.valid_roles:
4443
raise ValueError(
4544
f"No role named {name} exists. Valid names are one of {self.valid_roles}"
4645
)
46+
return getattr(self, name)
4747

4848
def __iter__(self):
4949
self.key_iter = iter(self.valid_roles)

0 commit comments

Comments
 (0)