11import logging
2+ from enum import Enum
3+ from typing import Iterable , List
4+
25from labelbox .orm import query
36from labelbox .orm .db_object import DbObject , Updateable
47from labelbox .orm .model import Entity , Field , Relationship
@@ -16,35 +19,41 @@ class Webhook(DbObject, Updateable):
1619 created_at (datetime)
1720 url (str)
1821 topics (str): LABEL_CREATED, LABEL_UPDATED, LABEL_DELETED
22+ REVIEW_CREATED, REVIEW_UPDATED, REVIEW_DELETED
1923 status (str): ACTIVE, INACTIVE, REVOKED
2024
2125 """
2226
23- # Status
24- ACTIVE = "ACTIVE"
25- INACTIVE = "INACTIVE"
26- REVOKED = "REVOKED"
27+ class WebhookStatus ( Enum ):
28+ ACTIVE = "ACTIVE"
29+ INACTIVE = "INACTIVE"
30+ REVOKED = "REVOKED"
2731
28- # Topic
29- LABEL_CREATED = "LABEL_CREATED"
30- LABEL_UPDATED = "LABEL_UPDATED"
31- LABEL_DELETED = "LABEL_DELETED"
32+ class WebhookTopic (Enum ):
33+ LABEL_CREATED = "LABEL_CREATED"
34+ LABEL_UPDATED = "LABEL_UPDATED"
35+ LABEL_DELETED = "LABEL_DELETED"
36+ REVIEW_CREATED = "REVIEW_CREATED"
37+ REVIEW_UPDATED = "REVIEW_UPDATED"
38+ REVIEW_DELETED = "REVIEW_DELETED"
3239
33- REVIEW_CREATED = "REVIEW_CREATED"
34- REVIEW_UPDATED = "REVIEW_UPDATED"
35- REVIEW_DELETED = "REVIEW_DELETED"
40+ #For backwards compatibility
41+ for topic in WebhookStatus :
42+ vars ()[ topic . name ] = topic . value
3643
37- SUPPORTED_TOPICS = {
38- LABEL_CREATED , LABEL_UPDATED , LABEL_DELETED , REVIEW_CREATED ,
39- REVIEW_UPDATED , REVIEW_DELETED
40- }
44+ for status in WebhookTopic :
45+ vars ()[status .name ] = status .value
4146
4247 updated_at = Field .DateTime ("updated_at" )
4348 created_at = Field .DateTime ("created_at" )
4449 url = Field .String ("url" )
4550 topics = Field .String ("topics" )
4651 status = Field .String ("status" )
4752
53+ created_by = Relationship .ToOne ("User" , False , "created_by" )
54+ organization = Relationship .ToOne ("Organization" )
55+ project = Relationship .ToOne ("Project" )
56+
4857 @staticmethod
4958 def create (client , topics , url , secret , project ):
5059 """ Creates a Webhook.
@@ -53,7 +62,7 @@ def create(client, topics, url, secret, project):
5362 client (Client): The Labelbox client used to connect
5463 to the server.
5564 topics (list of str): A list of topics this Webhook should
56- get notifications for. Must be one of Webhook.SUPPORTED_TOPICS
65+ get notifications for. Must be one of Webhook.WebhookTopic
5766 url (str): The URL to which notifications should be sent
5867 by the Labelbox server.
5968 secret (str): A secret key used for signing notifications.
@@ -63,10 +72,14 @@ def create(client, topics, url, secret, project):
6372 Returns:
6473 A newly created Webhook.
6574
75+ Raises:
76+ ValueError: If the topic is not one of WebhookTopic or status is not one of WebhookStatus
77+
6678 Information on configuring your server can be found here (this is where the url points to and the secret is set).
6779 https://docs.labelbox.com/en/configure-editor/webhooks-setup#setup-steps
68-
80+
6981 """
82+ Webhook .validate_topics (topics )
7083
7184 project_str = "" if project is None \
7285 else ("project:{id:\" %s\" }," % project .uid )
@@ -78,30 +91,47 @@ def create(client, topics, url, secret, project):
7891
7992 return Webhook (client , client .execute (query_str )["createWebhook" ])
8093
81- created_by = Relationship .ToOne ("User" , False , "created_by" )
82- organization = Relationship .ToOne ("Organization" )
83- project = Relationship .ToOne ("Project" )
94+ @staticmethod
95+ def validate_topics (topics : List ["Webhook.WebhookTopic" ]):
96+ if not isinstance (topics , list ):
97+ raise TypeError (
98+ f"Topics must be List[Webhook.WebhookTopic]. Found `{ topics } `" )
99+
100+ for topic in topics :
101+ Webhook .validate_value (topic , Webhook .WebhookTopic )
102+
103+ @staticmethod
104+ def validate_value (value , enum ):
105+ supported_values = [x .value for x in enum ]
106+ if value not in supported_values :
107+ raise ValueError (
108+ f"Value `{ value } ` does not exist in supported values. Expected one of { supported_values } "
109+ )
84110
85111 def delete (self ):
86- self .update (status = " INACTIVE" )
112+ self .update (status = self . WebhookStatus . INACTIVE )
87113
88114 def update (self , topics = None , url = None , status = None ):
89- """ Updates this Webhook.
115+ """ Updates the Webhook.
90116
91117 Args:
92- topics (list of str): The new topics value, optional .
93- url (str): The new URL value, optional .
94- status (str): The new status value, optional .
118+ topics (List[ str] ): The new topics.
119+ url (str): The new URL value.
120+ status (str): The new status.
95121
96122 If values are set to None then there are no updates made to that field.
97123
98- The following code will delete the webhook.
99- >>> self.update(status = Webhook.INACTIVE)
100-
101124 """
102125
103126 # Webhook has a custom `update` function due to custom types
104127 # in `status` and `topics` fields.
128+
129+ if topics is not None :
130+ self .validate_topics (topics )
131+
132+ if status is not None :
133+ self .validate_value (status , self .WebhookStatus )
134+
105135 topics_str = "" if topics is None \
106136 else "topics: {set: [%s]}" % " " .join (topics )
107137 url_str = "" if url is None else "url: \" %s\" " % url
0 commit comments