66from labelbox .alignerr .schema .project_rate import BillingMode
77from labelbox .alignerr .schema .project_rate import ProjectRateInput
88from labelbox .alignerr .schema .project_domain import ProjectDomain
9- from labelbox .alignerr .schema .enchanced_resource_tags import EnhancedResourceTag , ResourceTagType
10- from labelbox .alignerr .schema .project_boost_workforce import ProjectBoostWorkforce
9+ from labelbox .alignerr .schema .enchanced_resource_tags import (
10+ EnhancedResourceTag ,
11+ ResourceTagType ,
12+ )
13+ from labelbox .alignerr .schema .project_boost_workforce import (
14+ ProjectBoostWorkforce ,
15+ )
1116from labelbox .schema .media_type import MediaType
1217
1318logger = logging .getLogger (__name__ )
1419
1520
1621class ValidationType (Enum ):
1722 """Enum for validation types that can be selectively skipped."""
23+
1824 ALIGNERR_RATE = "AlignerrRate"
1925 CUSTOMER_RATE = "CustomerRate"
2026 PROJECT_OWNER = "ProjectOwner"
@@ -123,11 +129,11 @@ def set_domains(self, domains: list[str]):
123129
124130 def set_tags (self , tag_texts : list [str ], tag_type : ResourceTagType ):
125131 """Set enhanced resource tags for the project.
126-
132+
127133 Args:
128134 tag_texts: List of tag text values to search for and attach
129135 tag_type: Type filter for searching tags
130-
136+
131137 Returns:
132138 Self for method chaining
133139 """
@@ -136,7 +142,7 @@ def set_tags(self, tag_texts: list[str], tag_type: ResourceTagType):
136142 existing_tags = EnhancedResourceTag .search_by_text (
137143 self .client , search_text = tag_text , tag_type = tag_type
138144 )
139-
145+
140146 if existing_tags :
141147 # Use the first matching tag
142148 self ._enhanced_resource_tags .append (existing_tags [0 ])
@@ -146,25 +152,26 @@ def set_tags(self, tag_texts: list[str], tag_type: ResourceTagType):
146152 self .client ,
147153 text = tag_text ,
148154 color = "#007bff" , # Default blue color
149- tag_type = tag_type
155+ tag_type = tag_type ,
150156 )
151157 self ._enhanced_resource_tags .append (new_tag )
152158 return self
153159
154160 def set_project_owner (self , project_owner_email : str ):
155161 """Set the project owner for the ProjectBoostWorkforce.
156-
162+
157163 Args:
158164 project_owner_email: Email of the user to set as project owner
159-
165+
160166 Returns:
161167 Self for method chaining
162168 """
163169 self ._project_owner_email = project_owner_email
164170 return self
165171
166-
167- def create (self , skip_validation : Union [bool , List [ValidationType ]] = False ):
172+ def create (
173+ self , skip_validation : Union [bool , List [ValidationType ]] = False
174+ ):
168175 if not skip_validation :
169176 self ._validate ()
170177 elif isinstance (skip_validation , list ):
@@ -220,7 +227,7 @@ def _create_resource_tags(self, alignerr_project: "AlignerrProject"):
220227 if tag_type not in tags_by_type :
221228 tags_by_type [tag_type ] = []
222229 tags_by_type [tag_type ].append (tag .text )
223-
230+
224231 # Set tags for each type
225232 for tag_type_str , tag_names in tags_by_type .items ():
226233 # Convert string back to enum
@@ -230,17 +237,19 @@ def _create_resource_tags(self, alignerr_project: "AlignerrProject"):
230237 def _create_project_owner (self , alignerr_project : "AlignerrProject" ):
231238 if self ._project_owner_email :
232239 logger .info (f"Setting project owner: { self ._project_owner_email } " )
233-
240+
234241 # Find user by email in the organization
235242 user_id = self ._find_user_by_email (self ._project_owner_email )
236243 if not user_id :
237244 current_org = self .client .get_organization ()
238- raise ValueError (f"User with email { self ._project_owner_email } not found in organization { current_org .uid } " )
239-
245+ raise ValueError (
246+ f"User with email { self ._project_owner_email } not found in organization { current_org .uid } "
247+ )
248+
240249 ProjectBoostWorkforce .set_project_owner (
241250 client = self .client ,
242251 project_id = alignerr_project .project .uid ,
243- project_owner_user_id = user_id
252+ project_owner_user_id = user_id ,
244253 )
245254
246255 def _validate_alignerr_rates (self ):
@@ -273,16 +282,16 @@ def _validate(self):
273282
274283 def _validate_selective (self , skip_validations : List [ValidationType ]):
275284 """Run validations selectively, skipping those in the provided list.
276-
285+
277286 Args:
278287 skip_validations: List of ValidationType enums to skip
279288 """
280289 if ValidationType .ALIGNERR_RATE not in skip_validations :
281290 self ._validate_alignerr_rates ()
282-
291+
283292 if ValidationType .CUSTOMER_RATE not in skip_validations :
284293 self ._validate_customer_rate ()
285-
294+
286295 if ValidationType .PROJECT_OWNER not in skip_validations :
287296 self ._validate_project_owner ()
288297
@@ -292,31 +301,33 @@ def _get_role_name_to_id(self) -> dict[str, str]:
292301
293302 def _find_user_by_email (self , email : str ) -> Optional [str ]:
294303 """Find user ID by email in the organization.
295-
304+
296305 Args:
297306 email: Email address to search for
298-
307+
299308 Returns:
300309 User ID if found, None otherwise
301310 """
302311 try :
303312 # Import here to avoid circular imports
304313 from labelbox .schema .user import User
305-
314+
306315 # Get the current organization
307316 current_org = self .client .get_organization ()
308-
317+
309318 # Use client.get_users with where clause to find user by email
310319 users = self .client .get_users (where = User .email == email )
311-
320+
312321 # Get the first matching user and verify they belong to the same organization
313322 user = next (users , None )
314323 if user and user .organization ().uid == current_org .uid :
315324 return user .uid
316325 else :
317- logger .warning (f"User with email { email } not found in organization { current_org .uid } " )
326+ logger .warning (
327+ f"User with email { email } not found in organization { current_org .uid } "
328+ )
318329 return None
319-
330+
320331 except Exception as e :
321332 logger .error (f"Error finding user by email { email } : { e } " )
322333 return None
0 commit comments