22from itertools import islice
33import json
44import os
5- import re
65import sys
76import time
87import uuid
9- from enum import Enum
108from types import SimpleNamespace
11- from typing import Type , List , Union
9+ from typing import Type , List
1210
1311import pytest
1412import requests
1513
16- from labelbox import Client , Dataset
14+ from labelbox import Dataset
1715from labelbox import LabelingFrontend
1816from labelbox import OntologyBuilder , Tool , Option , Classification , MediaType
1917from labelbox .orm import query
2018from labelbox .pagination import PaginatedCollection
2119from labelbox .schema .annotation_import import LabelImport
2220from labelbox .schema .enums import AnnotationImportState
2321from labelbox .schema .invite import Invite
24- from labelbox .schema .project import Project
2522from labelbox .schema .quality_mode import QualityMode
2623from labelbox .schema .queue_mode import QueueMode
2724from labelbox .schema .user import User
25+ from support .integration_client import Environ , IntegrationClient , EphemeralClient , AdminClient
2826
2927IMG_URL = "https://picsum.photos/200/300.jpg"
3028SMALL_DATASET_URL = "https://storage.googleapis.com/lb-artifacts-testing-public/sdk_integration_test/potato.jpeg"
3129DATA_ROW_PROCESSING_WAIT_TIMEOUT_SECONDS = 30
3230DATA_ROW_PROCESSING_WAIT_SLEEP_INTERNAL_SECONDS = 3
3331
3432
35- class Environ (Enum ):
36- LOCAL = 'local'
37- PROD = 'prod'
38- STAGING = 'staging'
39- ONPREM = 'onprem'
40- CUSTOM = 'custom'
41- STAGING_EU = 'staging-eu'
42- EPHEMERAL = 'ephemeral' # Used for testing PRs with ephemeral environments
43-
44-
45- EPHEMERAL_BASE_URL = "http://lb-api-public"
46-
47-
4833@pytest .fixture (scope = "session" )
4934def environ () -> Environ :
5035 """
@@ -60,69 +45,6 @@ def environ() -> Environ:
6045 raise Exception (f'Missing LABELBOX_TEST_ENVIRON in: { os .environ } ' )
6146
6247
63- def graphql_url (environ : str ) -> str :
64- if environ == Environ .PROD :
65- return 'https://api.labelbox.com/graphql'
66- elif environ == Environ .STAGING :
67- return 'https://api.lb-stage.xyz/graphql'
68- elif environ == Environ .STAGING_EU :
69- return 'https://api.eu-de.lb-stage.xyz/graphql'
70- elif environ == Environ .ONPREM :
71- hostname = os .environ .get ('LABELBOX_TEST_ONPREM_HOSTNAME' , None )
72- if hostname is None :
73- raise Exception (f"Missing LABELBOX_TEST_ONPREM_INSTANCE" )
74- return f"{ hostname } /api/_gql"
75- elif environ == Environ .CUSTOM :
76- graphql_api_endpoint = os .environ .get (
77- 'LABELBOX_TEST_GRAPHQL_API_ENDPOINT' )
78- if graphql_api_endpoint is None :
79- raise Exception (f"Missing LABELBOX_TEST_GRAPHQL_API_ENDPOINT" )
80- return graphql_api_endpoint
81- elif environ == Environ .EPHEMERAL :
82- return f"{ EPHEMERAL_BASE_URL } /graphql"
83- return 'http://host.docker.internal:8080/graphql'
84-
85-
86- def rest_url (environ : str ) -> str :
87- if environ == Environ .PROD :
88- return 'https://api.labelbox.com/api/v1'
89- elif environ == Environ .STAGING :
90- return 'https://api.lb-stage.xyz/api/v1'
91- elif environ == Environ .STAGING_EU :
92- return 'https://api.eu-de.lb-stage.xyz/api/v1'
93- elif environ == Environ .CUSTOM :
94- rest_api_endpoint = os .environ .get ('LABELBOX_TEST_REST_API_ENDPOINT' )
95- if rest_api_endpoint is None :
96- raise Exception (f"Missing LABELBOX_TEST_REST_API_ENDPOINT" )
97- return rest_api_endpoint
98- elif environ == Environ .EPHEMERAL :
99- return f"{ EPHEMERAL_BASE_URL } /api/v1"
100- return 'http://host.docker.internal:8080/api/v1'
101-
102-
103- def admin_url (environ : str ) -> Union [str , None ]:
104- if environ == Environ .EPHEMERAL :
105- return f"{ EPHEMERAL_BASE_URL } /admin/v1"
106-
107- return 'http://host.docker.internal:8080/admin/v1'
108-
109-
110- def testing_api_key (environ : str ) -> str :
111- if environ == Environ .PROD :
112- return os .environ ["LABELBOX_TEST_API_KEY_PROD" ]
113- elif environ == Environ .STAGING :
114- return os .environ ["LABELBOX_TEST_API_KEY_STAGING" ]
115- elif environ == Environ .STAGING_EU :
116- return os .environ ["LABELBOX_TEST_API_KEY_STAGING_EU" ]
117- elif environ == Environ .ONPREM :
118- return os .environ ["LABELBOX_TEST_API_KEY_ONPREM" ]
119- elif environ == Environ .CUSTOM :
120- return os .environ ["LABELBOX_TEST_API_KEY_CUSTOM" ]
121- elif environ == Environ .EPHEMERAL :
122- return os .environ ["LABELBOX_TEST_API_KEY_EPHEMERAL" ]
123- return os .environ ["LABELBOX_TEST_API_KEY_LOCAL" ]
124-
125-
12648def cancel_invite (client , invite_id ):
12749 """
12850 Do not use. Only for testing.
@@ -172,121 +94,15 @@ def queries():
17294 get_invites = get_invites )
17395
17496
175- class IntegrationClient (Client ):
176-
177- def __init__ (self , environ : str ) -> None :
178- api_url = graphql_url (environ )
179- api_key = testing_api_key (environ )
180- rest_endpoint = rest_url (environ )
181- self ._admin_endpoint = admin_url (environ )
182-
183- super ().__init__ (api_key ,
184- api_url ,
185- enable_experimental = True ,
186- rest_endpoint = rest_endpoint )
187- self .queries = []
188-
189- def execute (self , query = None , params = None , check_naming = True , ** kwargs ):
190- if check_naming and query is not None :
191- assert re .match (r"(?:query|mutation) \w+PyApi" , query ) is not None
192- self .queries .append ((query , params ))
193- return super ().execute (query , params , ** kwargs )
194-
195- def create_organization (self ) -> str :
196- endpoint = f"{ self ._admin_endpoint } /organizations/"
197- response = requests .post (
198- endpoint ,
199- headers = self .headers ,
200- json = {"name" : f"Test Org { uuid .uuid4 ()} " },
201- )
202- if response .status_code != requests .codes .created :
203- raise Exception ("Failed to create ephemeral org, message: " +
204- str (response .json ()['message' ]))
205-
206- return response .json ()['id' ]
207-
208- def create_user (self , organization_id ) -> tuple [str , str ]:
209- endpoint = f"{ self ._admin_endpoint } /user-identities/"
210- identity_id = f"e2e+{ uuid .uuid4 ()} "
211-
212- response = requests .post (
213- endpoint ,
214- headers = self .headers ,
215- json = {
216- "identityId" : identity_id ,
217- "email" : "email@email.com" ,
218- "name" : f"tester{ uuid .uuid4 ()} " ,
219- "verificationStatus" : "VERIFIED" ,
220- },
221- )
222- if response .status_code != requests .codes .created :
223- raise Exception ("Failed to create ephemeral org, message: " +
224- str (response .json ()['message' ]))
225-
226- user_identity_id = response .json ()['identityId' ]
227-
228- endpoint = f"{ self ._admin_endpoint } /organizations/{ organization_id } /users/"
229- response = requests .post (
230- endpoint ,
231- headers = self .headers ,
232- json = {
233- "identityId" : user_identity_id ,
234- "organizationRole" : "Admin"
235- },
236- )
237- if response .status_code != requests .codes .created :
238- raise Exception ("Failed to create ephemeral org, message: " +
239- str (response .json ()['message' ]))
240-
241- user_id = response .json ()['id' ]
242-
243- endpoint = f"{ self ._admin_endpoint } /users/{ user_id } /token"
244- response = requests .get (
245- endpoint ,
246- headers = self .headers ,
247- )
248- if response .status_code != requests .codes .created :
249- raise Exception ("Failed to create ephemeral org, message: " +
250- str (response .json ()['message' ]))
251-
252- token = response ["token" ]
253-
254- return user_id , token
255-
256- def create_api_key_for_user (self , user_token ) -> str :
257- key_name = f"test-key+{ uuid .uuid4 ()} "
258- query = """
259- mutation CreateApiKey($name: String!) {
260- createApiKey(data: {name: $name}) {
261- id
262- jwt
263- __typename
264- }
265- }
266- """
267- params = {"name" : key_name }
268- req = self ._make_gql_request (query = query , params = params )
269-
270- return req ["createApiKey" ]["jwt" ]
271- mutation_name = "deleteDataRowsByQuery"
272- query = """mutation DeleteDataRowsByQueryPyApi($searchQueryInput: SearchServiceQueryInput!) {
273- %s(where: {searchQuery: $searchQueryInput})
274- { taskId }
275- }
276- """ % (mutation_name )
277- query_params = {
278- "searchQueryInput" : {
279- "query" : search_query ,
280- "scope" : None
281- }
282- }
283-
284- res = self .execute (query , query_params , error_log_key = "errors" )
285- res = res [mutation_name ]
97+ @pytest .fixture (scope = "session" )
98+ def admin_client (environ : str ):
99+ return AdminClient (environ )
286100
287101
288102@pytest .fixture (scope = "session" )
289103def client (environ : str ):
104+ if environ == Environ .EPHEMERAL :
105+ return EphemeralClient ()
290106 return IntegrationClient (environ )
291107
292108
0 commit comments