33from __future__ import annotations
44
55import os
6- from typing import Any , Union , Mapping
7- from typing_extensions import Self , override
6+ from typing import Any , Dict , Union , Mapping , cast
7+ from typing_extensions import Self , Literal , override
88
99import httpx
1010
3737from .resources .projects import projects
3838from .resources .organizations import organizations
3939
40- __all__ = ["Timeout" , "Transport" , "ProxiesTypes" , "RequestOptions" , "Codex" , "AsyncCodex" , "Client" , "AsyncClient" ]
40+ __all__ = [
41+ "ENVIRONMENTS" ,
42+ "Timeout" ,
43+ "Transport" ,
44+ "ProxiesTypes" ,
45+ "RequestOptions" ,
46+ "Codex" ,
47+ "AsyncCodex" ,
48+ "Client" ,
49+ "AsyncClient" ,
50+ ]
51+
52+ ENVIRONMENTS : Dict [str , str ] = {
53+ "production" : "https://api-alpha-o3gxj3oajfu.cleanlab.ai" ,
54+ "staging" : "https://api-alpha-staging-o3gxj3oajfu.cleanlab.ai" ,
55+ "local" : "http://localhost:8080" ,
56+ }
4157
4258
4359class Codex (SyncAPIClient ):
@@ -53,13 +69,16 @@ class Codex(SyncAPIClient):
5369 api_key : str | None
5470 access_key : str | None
5571
72+ _environment : Literal ["production" , "staging" , "local" ] | NotGiven
73+
5674 def __init__ (
5775 self ,
5876 * ,
5977 bearer_token : str | None = None ,
6078 api_key : str | None = None ,
6179 access_key : str | None = None ,
62- base_url : str | httpx .URL | None = None ,
80+ environment : Literal ["production" , "staging" , "local" ] | NotGiven = NOT_GIVEN ,
81+ base_url : str | httpx .URL | None | NotGiven = NOT_GIVEN ,
6382 timeout : Union [float , Timeout , None , NotGiven ] = NOT_GIVEN ,
6483 max_retries : int = DEFAULT_MAX_RETRIES ,
6584 default_headers : Mapping [str , str ] | None = None ,
@@ -97,10 +116,31 @@ def __init__(
97116 access_key = os .environ .get ("PUBLIC_ACCESS_KEY" )
98117 self .access_key = access_key
99118
100- if base_url is None :
101- base_url = os .environ .get ("CODEX_BASE_URL" )
102- if base_url is None :
103- base_url = f"https://localhost:8080/test-api"
119+ self ._environment = environment
120+
121+ base_url_env = os .environ .get ("CODEX_BASE_URL" )
122+ if is_given (base_url ) and base_url is not None :
123+ # cast required because mypy doesn't understand the type narrowing
124+ base_url = cast ("str | httpx.URL" , base_url ) # pyright: ignore[reportUnnecessaryCast]
125+ elif is_given (environment ):
126+ if base_url_env and base_url is not None :
127+ raise ValueError (
128+ "Ambiguous URL; The `CODEX_BASE_URL` env var and the `environment` argument are given. If you want to use the environment, you must pass base_url=None" ,
129+ )
130+
131+ try :
132+ base_url = ENVIRONMENTS [environment ]
133+ except KeyError as exc :
134+ raise ValueError (f"Unknown environment: { environment } " ) from exc
135+ elif base_url_env is not None :
136+ base_url = base_url_env
137+ else :
138+ self ._environment = environment = "production"
139+
140+ try :
141+ base_url = ENVIRONMENTS [environment ]
142+ except KeyError as exc :
143+ raise ValueError (f"Unknown environment: { environment } " ) from exc
104144
105145 super ().__init__ (
106146 version = __version__ ,
@@ -193,6 +233,7 @@ def copy(
193233 bearer_token : str | None = None ,
194234 api_key : str | None = None ,
195235 access_key : str | None = None ,
236+ environment : Literal ["production" , "staging" , "local" ] | None = None ,
196237 base_url : str | httpx .URL | None = None ,
197238 timeout : float | Timeout | None | NotGiven = NOT_GIVEN ,
198239 http_client : httpx .Client | None = None ,
@@ -230,6 +271,7 @@ def copy(
230271 api_key = api_key or self .api_key ,
231272 access_key = access_key or self .access_key ,
232273 base_url = base_url or self .base_url ,
274+ environment = environment or self ._environment ,
233275 timeout = self .timeout if isinstance (timeout , NotGiven ) else timeout ,
234276 http_client = http_client ,
235277 max_retries = max_retries if is_given (max_retries ) else self .max_retries ,
@@ -289,13 +331,16 @@ class AsyncCodex(AsyncAPIClient):
289331 api_key : str | None
290332 access_key : str | None
291333
334+ _environment : Literal ["production" , "staging" , "local" ] | NotGiven
335+
292336 def __init__ (
293337 self ,
294338 * ,
295339 bearer_token : str | None = None ,
296340 api_key : str | None = None ,
297341 access_key : str | None = None ,
298- base_url : str | httpx .URL | None = None ,
342+ environment : Literal ["production" , "staging" , "local" ] | NotGiven = NOT_GIVEN ,
343+ base_url : str | httpx .URL | None | NotGiven = NOT_GIVEN ,
299344 timeout : Union [float , Timeout , None , NotGiven ] = NOT_GIVEN ,
300345 max_retries : int = DEFAULT_MAX_RETRIES ,
301346 default_headers : Mapping [str , str ] | None = None ,
@@ -333,10 +378,31 @@ def __init__(
333378 access_key = os .environ .get ("PUBLIC_ACCESS_KEY" )
334379 self .access_key = access_key
335380
336- if base_url is None :
337- base_url = os .environ .get ("CODEX_BASE_URL" )
338- if base_url is None :
339- base_url = f"https://localhost:8080/test-api"
381+ self ._environment = environment
382+
383+ base_url_env = os .environ .get ("CODEX_BASE_URL" )
384+ if is_given (base_url ) and base_url is not None :
385+ # cast required because mypy doesn't understand the type narrowing
386+ base_url = cast ("str | httpx.URL" , base_url ) # pyright: ignore[reportUnnecessaryCast]
387+ elif is_given (environment ):
388+ if base_url_env and base_url is not None :
389+ raise ValueError (
390+ "Ambiguous URL; The `CODEX_BASE_URL` env var and the `environment` argument are given. If you want to use the environment, you must pass base_url=None" ,
391+ )
392+
393+ try :
394+ base_url = ENVIRONMENTS [environment ]
395+ except KeyError as exc :
396+ raise ValueError (f"Unknown environment: { environment } " ) from exc
397+ elif base_url_env is not None :
398+ base_url = base_url_env
399+ else :
400+ self ._environment = environment = "production"
401+
402+ try :
403+ base_url = ENVIRONMENTS [environment ]
404+ except KeyError as exc :
405+ raise ValueError (f"Unknown environment: { environment } " ) from exc
340406
341407 super ().__init__ (
342408 version = __version__ ,
@@ -429,6 +495,7 @@ def copy(
429495 bearer_token : str | None = None ,
430496 api_key : str | None = None ,
431497 access_key : str | None = None ,
498+ environment : Literal ["production" , "staging" , "local" ] | None = None ,
432499 base_url : str | httpx .URL | None = None ,
433500 timeout : float | Timeout | None | NotGiven = NOT_GIVEN ,
434501 http_client : httpx .AsyncClient | None = None ,
@@ -466,6 +533,7 @@ def copy(
466533 api_key = api_key or self .api_key ,
467534 access_key = access_key or self .access_key ,
468535 base_url = base_url or self .base_url ,
536+ environment = environment or self ._environment ,
469537 timeout = self .timeout if isinstance (timeout , NotGiven ) else timeout ,
470538 http_client = http_client ,
471539 max_retries = max_retries if is_given (max_retries ) else self .max_retries ,
0 commit comments