Skip to content

Commit d91921c

Browse files
committed
refactor: rename preview terminology to free tier cloud
Replace preview-client wording with free tier cloud across the SDK, docs, and tests. Rename JUDGE0_SUPPRESS_PREVIEW_WARNING to JUDGE0_SUPPRESS_FREE_TIER_CLOUD_WARNING and PreviewClientLimitError to FreeTierCloudClientLimitError. Closes #45
1 parent df8b018 commit d91921c

10 files changed

Lines changed: 79 additions & 38 deletions

File tree

AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@
1919
- `clients.py` implements the base HTTP client and the provider- and flavor-specific clients for Judge0 Cloud, RapidAPI, and AllThingsDev.
2020
- `common.py` contains shared base64 encoding and decoding helpers and iterable batching.
2121
- `data.py` maps language aliases to Judge0 language IDs by server version and flavor.
22-
- `errors.py` defines SDK-specific exception types for client resolution and preview-client usage limits.
22+
- `errors.py` defines SDK-specific exception types for client resolution and free-tier-cloud-client usage limits.
2323
- `filesystem.py` models individual files and ZIP-backed collections used for additional and post-execution files.
2424
- `retry.py` defines the polling strategy interface and retry-count, wait-time, and periodic retry implementations.
2525
- `submission.py` models submission request and response data, including serialization, response updates, completion checks, and execution filesystem handling.
26-
- `utils.py` detects HTTP rate-limit responses and translates preview-client rate limits into SDK-specific errors.
26+
- `utils.py` detects HTTP rate-limit responses and translates free-tier-cloud-client rate limits into SDK-specific errors.
2727
- `version.py` exposes the package version constant.
2828
- `tests/` contains the pytest suite. Shared fixtures belong in `conftest.py`, and focused tests should use `test_<area>.py` modules that correspond to SDK behavior.
2929
- `examples/` contains runnable SDK usage examples, including the standalone HTTP callback example in `examples/1000_http_callback_aka_webhook/`.

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## v0.1.0-dev
44

5+
- Rename "preview" terminology to "free tier cloud" and rename the
6+
`JUDGE0_SUPPRESS_PREVIEW_WARNING` environment variable to
7+
`JUDGE0_SUPPRESS_FREE_TIER_CLOUD_WARNING`.
58
- Fix Sphinx autodoc imports for Pydantic-backed submission types.
69
- Add complete static typing across the SDK and tests, with typed single and batch
710
submission return values.

docs/source/in_depth/client_resolution.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ If a custom client is not configured, the SDK will try to find API keys for one
3434

3535
The first API key found determines the client that will be used.
3636

37-
3. **Preview Client**
37+
3. **Free Tier Cloud Client**
3838

39-
If none of the above environment variables are set, the SDK falls back to using a **preview client**. This is an unauthenticated client that connects to the official Judge0 Cloud service. It initializes ``Judge0CloudCE()`` and ``Judge0CloudExtraCE()`` for the CE and Extra CE flavors, respectively.
39+
If none of the above environment variables are set, the SDK falls back to using a **free tier cloud client**. This is an unauthenticated client that connects to the official Judge0 Cloud service. It initializes ``Judge0CloudCE()`` and ``Judge0CloudExtraCE()`` for the CE and Extra CE flavors, respectively.
4040

41-
When the preview client is used, a warning message is logged to the console, as this option is not recommended for production use. To suppress this warning, you can set the ``JUDGE0_SUPPRESS_PREVIEW_WARNING`` environment variable.
41+
When the free tier cloud client is used, a warning message is logged to the console, as this option is not recommended for production use. To suppress this warning, you can set the ``JUDGE0_SUPPRESS_FREE_TIER_CLOUD_WARNING`` environment variable.
4242

4343
Example Resolution Flow
4444
-----------------------
@@ -50,6 +50,6 @@ When you call a function like ``judge0.run(..., flavor=judge0.CE)``, the SDK wil
5050
3. Check for ``JUDGE0_CLOUD_CE_AUTH_HEADERS`` to configure a ``Judge0CloudCE`` client.
5151
4. Check for ``JUDGE0_RAPID_API_KEY`` to configure a ``RapidJudge0CE`` client.
5252
5. Check for ``JUDGE0_ATD_API_KEY`` to configure an ``ATDJudge0CE`` client.
53-
6. If none of the above are found, initialize a preview ``Judge0CloudCE`` client and log a warning.
53+
6. If none of the above are found, initialize a free tier cloud ``Judge0CloudCE`` client and log a warning.
5454

5555
This implicit client resolution makes it easy to get started with the Judge0 Python SDK while providing the flexibility to configure it for different environments and services.

src/judge0/__init__.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@
7676
if os.getenv("JUDGE0_ENABLE_LOGGING"):
7777
setup_logging()
7878

79-
suppress_preview_warning = os.getenv("JUDGE0_SUPPRESS_PREVIEW_WARNING") is not None
79+
suppress_free_tier_cloud_warning = (
80+
os.getenv("JUDGE0_SUPPRESS_FREE_TIER_CLOUD_WARNING") is not None
81+
)
8082

8183

8284
# TODO: I belive that the whole logic for importing implicit client can be moved
@@ -105,9 +107,9 @@ def _get_implicit_client(flavor: Flavor) -> Client:
105107
client = _get_hub_client(flavor)
106108

107109
# If we didn't find any of the possible keys, initialize
108-
# the preview client based on the flavor.
110+
# the free tier cloud client based on the flavor.
109111
if client is None:
110-
client = _get_preview_client(flavor)
112+
client = _get_free_tier_cloud_client(flavor)
111113

112114
if flavor == Flavor.CE:
113115
JUDGE0_IMPLICIT_CE_CLIENT = client
@@ -117,10 +119,10 @@ def _get_implicit_client(flavor: Flavor) -> Client:
117119
return client
118120

119121

120-
def _get_preview_client(flavor: Flavor) -> Judge0CloudCE | Judge0CloudExtraCE:
121-
if not suppress_preview_warning:
122+
def _get_free_tier_cloud_client(flavor: Flavor) -> Judge0CloudCE | Judge0CloudExtraCE:
123+
if not suppress_free_tier_cloud_warning:
122124
logger.warning(
123-
"You are using a preview version of the client which is not recommended"
125+
"You are using the free tier cloud client which is not recommended"
124126
" for production.\n"
125127
"For production, please specify your API key in the environment variable."
126128
)

src/judge0/api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020

2121
def get_client(flavor: Flavor = Flavor.CE) -> Client:
22-
"""Resolve client from API keys from environment or default to preview client.
22+
"""Resolve client from API keys or default to the free tier cloud client.
2323
2424
Parameters
2525
----------

src/judge0/clients.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from .data import LANGUAGE_TO_LANGUAGE_ID
1414
from .retry import RetryStrategy
1515
from .submission import Submission, Submissions
16-
from .utils import handle_too_many_requests_error_for_preview_client
16+
from .utils import handle_too_many_requests_error_for_free_tier_cloud_client
1717
from .version import __version__
1818

1919

@@ -70,7 +70,7 @@ def __init__(
7070
def __del__(self) -> None:
7171
self.client.close()
7272

73-
@handle_too_many_requests_error_for_preview_client
73+
@handle_too_many_requests_error_for_free_tier_cloud_client
7474
def get_about(self) -> JsonObject:
7575
"""Get general information about judge0.
7676
@@ -86,7 +86,7 @@ def get_about(self) -> JsonObject:
8686
response.raise_for_status()
8787
return cast(JsonObject, response.json())
8888

89-
@handle_too_many_requests_error_for_preview_client
89+
@handle_too_many_requests_error_for_free_tier_cloud_client
9090
def get_config_info(self) -> Config:
9191
"""Get information about client's configuration.
9292
@@ -102,7 +102,7 @@ def get_config_info(self) -> Config:
102102
response.raise_for_status()
103103
return Config.model_validate(response.json())
104104

105-
@handle_too_many_requests_error_for_preview_client
105+
@handle_too_many_requests_error_for_free_tier_cloud_client
106106
def get_language(self, language_id: int) -> Language:
107107
"""Get language corresponding to the id.
108108
@@ -121,7 +121,7 @@ def get_language(self, language_id: int) -> Language:
121121
response.raise_for_status()
122122
return Language.model_validate(response.json())
123123

124-
@handle_too_many_requests_error_for_preview_client
124+
@handle_too_many_requests_error_for_free_tier_cloud_client
125125
def get_languages(self) -> list[Language]:
126126
"""Get a list of supported languages.
127127
@@ -135,7 +135,7 @@ def get_languages(self) -> list[Language]:
135135
languages = cast(list[JsonObject], response.json())
136136
return [Language.model_validate(language) for language in languages]
137137

138-
@handle_too_many_requests_error_for_preview_client
138+
@handle_too_many_requests_error_for_free_tier_cloud_client
139139
def get_statuses(self) -> list[JsonObject]:
140140
"""Get a list of possible submission statuses.
141141
@@ -192,7 +192,7 @@ def is_language_supported(self, language: LanguageAlias | int) -> bool:
192192
language_id = self.get_language_id(language)
193193
return any(language_id == lang.id for lang in self.languages)
194194

195-
@handle_too_many_requests_error_for_preview_client
195+
@handle_too_many_requests_error_for_free_tier_cloud_client
196196
def create_submission(self, submission: Submission) -> Submission:
197197
"""Send submission for execution to a client.
198198
@@ -234,7 +234,7 @@ def create_submission(self, submission: Submission) -> Submission:
234234

235235
return submission
236236

237-
@handle_too_many_requests_error_for_preview_client
237+
@handle_too_many_requests_error_for_free_tier_cloud_client
238238
def get_submission(
239239
self,
240240
submission: Submission,
@@ -279,7 +279,7 @@ def get_submission(
279279

280280
return submission
281281

282-
@handle_too_many_requests_error_for_preview_client
282+
@handle_too_many_requests_error_for_free_tier_cloud_client
283283
def create_submissions(self, submissions: Submissions) -> Submissions:
284284
"""Send submissions for execution to a client.
285285
@@ -319,7 +319,7 @@ def create_submissions(self, submissions: Submissions) -> Submissions:
319319

320320
return submissions
321321

322-
@handle_too_many_requests_error_for_preview_client
322+
@handle_too_many_requests_error_for_free_tier_cloud_client
323323
def get_submissions(
324324
self,
325325
submissions: Submissions,

src/judge0/errors.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
"""Library specific errors."""
22

33

4-
class PreviewClientLimitError(RuntimeError):
5-
"""Limited usage of a preview client exceeded."""
4+
class FreeTierCloudClientLimitError(RuntimeError):
5+
"""Limited usage of the free tier cloud client exceeded."""
66

77

88
class ClientResolutionError(RuntimeError):

src/judge0/utils.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from httpx import HTTPError, HTTPStatusError
99

10-
from .errors import PreviewClientLimitError
10+
from .errors import FreeTierCloudClientLimitError
1111

1212
P = ParamSpec("P")
1313
R = TypeVar("R")
@@ -20,7 +20,7 @@ def is_http_too_many_requests_error(exception: Exception) -> bool:
2020
)
2121

2222

23-
def handle_too_many_requests_error_for_preview_client(
23+
def handle_too_many_requests_error_for_free_tier_cloud_client(
2424
func: Callable[P, R],
2525
) -> Callable[P, R]:
2626
@wraps(func)
@@ -33,13 +33,13 @@ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
3333
# let's check if we are dealing with the implicit client.
3434
instance = args[0]
3535
class_name = instance.__class__.__name__
36-
# Check if we are using a preview version of the client.
36+
# Check if we are using the free tier cloud client.
3737
if (
3838
class_name in ("Judge0CloudCE", "Judge0CloudExtraCE")
3939
and getattr(instance, "api_key", None) is None
4040
):
41-
raise PreviewClientLimitError(
42-
"You are using a preview version of a client and "
41+
raise FreeTierCloudClientLimitError(
42+
"You are using the free tier cloud client and "
4343
"you've hit a rate limit on it. Visit "
4444
f"{getattr(instance, 'HOME_URL', None)} "
4545
"to get your authentication credentials."

tests/conftest.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,12 @@ def judge0_cloud_extra_ce_client() -> clients.Judge0CloudExtraCE | None:
116116

117117

118118
@pytest.fixture(scope="session")
119-
def preview_ce_client() -> clients.Judge0CloudCE:
119+
def free_tier_cloud_ce_client() -> clients.Judge0CloudCE:
120120
return clients.Judge0CloudCE(retry_strategy=RegularPeriodRetry(0.5))
121121

122122

123123
@pytest.fixture(scope="session")
124-
def preview_extra_ce_client() -> clients.Judge0CloudExtraCE:
124+
def free_tier_cloud_extra_ce_client() -> clients.Judge0CloudExtraCE:
125125
return clients.Judge0CloudExtraCE(retry_strategy=RegularPeriodRetry(0.5))
126126

127127

@@ -131,7 +131,7 @@ def ce_client(
131131
judge0_cloud_ce_client: clients.Judge0CloudCE | None,
132132
rapid_ce_client: clients.RapidJudge0CE | None,
133133
# atd_ce_client,
134-
preview_ce_client: clients.Judge0CloudCE,
134+
free_tier_cloud_ce_client: clients.Judge0CloudCE,
135135
) -> clients.Client:
136136
if custom_ce_client is not None:
137137
return custom_ce_client
@@ -141,8 +141,8 @@ def ce_client(
141141
return rapid_ce_client
142142
# if atd_ce_client is not None:
143143
# return atd_ce_client
144-
if preview_ce_client is not None:
145-
return preview_ce_client
144+
if free_tier_cloud_ce_client is not None:
145+
return free_tier_cloud_ce_client
146146

147147
pytest.fail("No CE client available for testing. This error should not happen!")
148148

@@ -153,7 +153,7 @@ def extra_ce_client(
153153
judge0_cloud_extra_ce_client: clients.Judge0CloudExtraCE | None,
154154
rapid_extra_ce_client: clients.RapidJudge0ExtraCE | None,
155155
# atd_extra_ce_client,
156-
preview_extra_ce_client: clients.Judge0CloudExtraCE,
156+
free_tier_cloud_extra_ce_client: clients.Judge0CloudExtraCE,
157157
) -> clients.Client:
158158
if custom_extra_ce_client is not None:
159159
return custom_extra_ce_client
@@ -163,8 +163,8 @@ def extra_ce_client(
163163
return rapid_extra_ce_client
164164
# if atd_extra_ce_client is not None:
165165
# return atd_extra_ce_client
166-
if preview_extra_ce_client is not None:
167-
return preview_extra_ce_client
166+
if free_tier_cloud_extra_ce_client is not None:
167+
return free_tier_cloud_extra_ce_client
168168

169169
pytest.fail(
170170
"No Extra CE client available for testing. This error should not happen!"

tests/test_free_tier_cloud.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from http import HTTPStatus
2+
3+
import httpx
4+
import pytest
5+
6+
from judge0 import errors, utils
7+
from judge0.errors import FreeTierCloudClientLimitError
8+
from judge0.utils import handle_too_many_requests_error_for_free_tier_cloud_client
9+
10+
11+
class Judge0CloudCE:
12+
HOME_URL = "https://ce.judge0.com"
13+
api_key = None
14+
15+
@handle_too_many_requests_error_for_free_tier_cloud_client
16+
def ping(self) -> None:
17+
request = httpx.Request("GET", "https://ce.judge0.com")
18+
response = httpx.Response(HTTPStatus.TOO_MANY_REQUESTS, request=request)
19+
raise httpx.HTTPStatusError(
20+
"rate limited",
21+
request=request,
22+
response=response,
23+
)
24+
25+
26+
def test_preview_error_and_handler_names_are_removed() -> None:
27+
assert not hasattr(errors, "PreviewClientLimitError")
28+
assert not hasattr(utils, "handle_too_many_requests_error_for_preview_client")
29+
30+
31+
def test_rate_limit_raises_free_tier_cloud_client_limit_error() -> None:
32+
with pytest.raises(
33+
FreeTierCloudClientLimitError,
34+
match="free tier cloud client",
35+
):
36+
Judge0CloudCE().ping()

0 commit comments

Comments
 (0)