Skip to content

Commit b79317e

Browse files
aditya1503axl1313
andauthored
fix model validation in pydantic; (#27)
Co-authored-by: Angela <[email protected]>
1 parent 705b9d3 commit b79317e

File tree

6 files changed

+40
-16
lines changed

6 files changed

+40
-16
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- Pydantic model validation error when querying Project and listing Organizations.
13+
1014
## [0.0.1a3] - 2025-02-06
1115

1216
### Added

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ classifiers = [
2626
]
2727
dependencies = [
2828
"codex-sdk==0.1.0a9",
29-
"pydantic>=1.9.0, <3",
29+
"pydantic>=2.0.0, <3",
3030
]
3131

3232
[project.urls]

src/cleanlab_codex/internal/organization.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@
99

1010

1111
def list_organizations(client: _Codex) -> list[Organization]:
12-
return [Organization.model_validate(org) for org in client.users.myself.organizations.list().organizations]
12+
return [
13+
Organization.model_validate(org.model_dump()) for org in client.users.myself.organizations.list().organizations
14+
]

src/cleanlab_codex/internal/project.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,16 @@ def query_project(
2525
) -> tuple[Optional[str], Optional[Entry]]:
2626
maybe_entry = client.projects.entries.query(project_id, question=question)
2727
if maybe_entry is not None:
28-
entry = Entry.model_validate(maybe_entry)
28+
entry = Entry.model_validate(maybe_entry.model_dump())
2929
if entry.answer is not None:
3030
return entry.answer, entry
3131

3232
return fallback_answer, entry
3333

3434
if not read_only:
35-
created_entry = Entry.model_validate(client.projects.entries.add_question(project_id, question=question))
35+
created_entry = Entry.model_validate(
36+
client.projects.entries.add_question(project_id, question=question).model_dump()
37+
)
3638
return fallback_answer, created_entry
3739

3840
return fallback_answer, None

tests/test_client.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
from codex import AuthenticationError
99
from codex.types.project_return_schema import Config as ProjectReturnConfig
1010
from codex.types.project_return_schema import ProjectReturnSchema
11+
from codex.types.users.myself.user_organizations_schema import Organization as SDKOrganization
1112
from codex.types.users.myself.user_organizations_schema import UserOrganizationsSchema
1213

1314
from cleanlab_codex.client import Client
1415
from cleanlab_codex.project import MissingProjectError
15-
from cleanlab_codex.types.organization import Organization
1616
from cleanlab_codex.types.project import ProjectConfig
1717

1818
FAKE_PROJECT_ID = str(uuid.uuid4())
@@ -29,7 +29,7 @@ def test_client_uses_default_organization(mock_client_from_api_key: MagicMock) -
2929
default_org_id = "default-org-id"
3030
mock_client_from_api_key.users.myself.organizations.list.return_value = UserOrganizationsSchema(
3131
organizations=[
32-
Organization(
32+
SDKOrganization(
3333
organization_id=default_org_id,
3434
created_at=datetime.now(),
3535
updated_at=datetime.now(),
@@ -98,7 +98,7 @@ def test_get_project_not_found(mock_client_from_api_key: MagicMock) -> None:
9898
def test_list_organizations(mock_client_from_api_key: MagicMock) -> None:
9999
mock_client_from_api_key.users.myself.organizations.list.return_value = UserOrganizationsSchema(
100100
organizations=[
101-
Organization(
101+
SDKOrganization(
102102
organization_id=FAKE_ORGANIZATION_ID,
103103
created_at=datetime.now(),
104104
updated_at=datetime.now(),

tests/test_project.py

+25-9
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
from codex import AuthenticationError
77
from codex.types.project_create_params import Config
88
from codex.types.projects.access_key_retrieve_project_id_response import AccessKeyRetrieveProjectIDResponse
9+
from codex.types.projects.entry import Entry as SDKEntry
910

1011
from cleanlab_codex.project import MissingProjectError, Project
11-
from cleanlab_codex.types.entry import Entry, EntryCreate
12+
from cleanlab_codex.types.entry import EntryCreate
1213

1314
FAKE_PROJECT_ID = str(uuid.uuid4())
1415
FAKE_USER_ID = "Test User"
@@ -138,11 +139,12 @@ def test_query_read_only(mock_client_from_access_key: MagicMock) -> None:
138139
FAKE_PROJECT_ID, question="What is the capital of France?"
139140
)
140141
mock_client_from_access_key.projects.entries.add_question.assert_not_called()
141-
assert res == (None, None)
142+
assert res[0] is None
143+
assert res[1] is None
142144

143145

144146
def test_query_question_found_fallback_answer(mock_client_from_access_key: MagicMock) -> None:
145-
unanswered_entry = Entry(
147+
unanswered_entry = SDKEntry(
146148
id=str(uuid.uuid4()),
147149
created_at=datetime.now(tz=timezone.utc),
148150
question="What is the capital of France?",
@@ -151,22 +153,32 @@ def test_query_question_found_fallback_answer(mock_client_from_access_key: Magic
151153
mock_client_from_access_key.projects.entries.query.return_value = unanswered_entry
152154
project = Project(mock_client_from_access_key, FAKE_PROJECT_ID)
153155
res = project.query("What is the capital of France?")
154-
assert res == (None, unanswered_entry)
156+
assert res[0] is None
157+
assert res[1] is not None
158+
assert res[1].model_dump() == unanswered_entry.model_dump()
155159

156160

157161
def test_query_question_not_found_fallback_answer(mock_client_from_access_key: MagicMock) -> None:
158162
mock_client_from_access_key.projects.entries.query.return_value = None
159-
mock_client_from_access_key.projects.entries.add_question.return_value = MagicMock(spec=Entry)
163+
mock_entry = SDKEntry(
164+
id="fake-id",
165+
created_at=datetime.now(tz=timezone.utc),
166+
question="What is the capital of France?",
167+
answer=None,
168+
)
169+
mock_client_from_access_key.projects.entries.add_question.return_value = mock_entry
160170

161171
project = Project(mock_client_from_access_key, FAKE_PROJECT_ID)
162172
res = project.query("What is the capital of France?", fallback_answer="Paris")
163173
assert res[0] == "Paris"
174+
assert res[1] is not None
175+
assert res[1].model_dump() == mock_entry.model_dump()
164176

165177

166178
def test_query_add_question_when_not_found(mock_client_from_access_key: MagicMock) -> None:
167179
"""Test that query adds question when not found and not read_only"""
168180
mock_client_from_access_key.projects.entries.query.return_value = None
169-
new_entry = Entry(
181+
new_entry = SDKEntry(
170182
id=str(uuid.uuid4()),
171183
created_at=datetime.now(tz=timezone.utc),
172184
question="What is the capital of France?",
@@ -180,11 +192,13 @@ def test_query_add_question_when_not_found(mock_client_from_access_key: MagicMoc
180192
mock_client_from_access_key.projects.entries.add_question.assert_called_once_with(
181193
FAKE_PROJECT_ID, question="What is the capital of France?"
182194
)
183-
assert res == (None, new_entry)
195+
assert res[0] is None
196+
assert res[1] is not None
197+
assert res[1].model_dump() == new_entry.model_dump()
184198

185199

186200
def test_query_answer_found(mock_client_from_access_key: MagicMock) -> None:
187-
answered_entry = Entry(
201+
answered_entry = SDKEntry(
188202
id=str(uuid.uuid4()),
189203
created_at=datetime.now(tz=timezone.utc),
190204
question="What is the capital of France?",
@@ -193,7 +207,9 @@ def test_query_answer_found(mock_client_from_access_key: MagicMock) -> None:
193207
mock_client_from_access_key.projects.entries.query.return_value = answered_entry
194208
project = Project(mock_client_from_access_key, FAKE_PROJECT_ID)
195209
res = project.query("What is the capital of France?")
196-
assert res == ("Paris", answered_entry)
210+
assert res[0] == answered_entry.answer
211+
assert res[1] is not None
212+
assert res[1].model_dump() == answered_entry.model_dump()
197213

198214

199215
def test_add_entries_empty_list(mock_client_from_access_key: MagicMock) -> None:

0 commit comments

Comments
 (0)