Skip to content

Commit 5ab8335

Browse files
committed
Upgrade fastapi to 0.100.0 and pydantic to v2
1 parent 56c0a19 commit 5ab8335

3 files changed

Lines changed: 48 additions & 31 deletions

File tree

requirements.txt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
setuptools>=62.0.0
1+
setuptools>=68.0.0
22
uvicorn[standard]==0.22.0
3-
fastapi==0.95.2
3+
fastapi==0.100.0
4+
pydantic==2.0.2
45
gunicorn==20.1.0
5-
numpy==1.24.3
6-
pandas==2.0.1
7-
scikit-learn==1.2.2
8-
joblib==1.2.0
6+
numpy==1.25.0
7+
pandas==2.0.3
8+
scikit-learn==1.3.0
9+
joblib==1.3.1
910
eli5==0.13.0

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@
2727
keywords="python3 fastapi machine-learning rest-api",
2828
packages=find_packages(),
2929
install_requires=[
30-
"fastapi>=0.87.0",
30+
"fastapi>=0.100.0",
3131
"uvicorn>=0.19.0",
3232
"numpy>=1.22.0",
3333
"pandas>=1.4.0",
34+
"pydantic>=2.0",
3435
],
3536
)

tests/basic_test.py

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from openapi_spec_validator import (
88
openapi_v2_spec_validator,
99
openapi_v30_spec_validator,
10+
openapi_v31_spec_validator,
1011
)
1112
from openapi_spec_validator.validation.exceptions import OpenAPIValidationError
1213

@@ -41,9 +42,9 @@
4142
MOCK_PREDICTION = "mock_prediction"
4243
NOT_A_DATETIME_MSG = "is not a 'date-time'"
4344
NOT_A_DATE_MSG = "is not a 'date'"
44-
VALUE_ERROR_MISSING = "value_error.missing"
45-
VALUE_ERROR_DATE = "value_error.date"
46-
VALUE_ERROR_DATETIME = "value_error.datetime"
45+
VALUE_ERROR_MISSING = "missing"
46+
VALUE_ERROR_DATE = "date_from_datetime_parsing"
47+
VALUE_ERROR_DATETIME = "datetime_parsing"
4748

4849

4950
def _get_request(url):
@@ -81,16 +82,25 @@ def _post_request_good_json_with_overrides(override_key=None, override_value=Non
8182
return response
8283

8384

84-
def test_get_swagger_json_is_valid_openapi_v3():
85-
"""Verify that /api/swagger.json file complies with OpenAPI v2."""
85+
def test_get_swagger_json_is_valid_openapi_v3_1():
86+
"""Verify that /api/swagger.json file complies with OpenAPI v3.1"""
8687
response = _get_request(ROOT_URL + SWAGGER_JSON_PATH)
8788
spec_dict = loads(response.text)
88-
openapi_v30_spec_validator.validate(spec_dict)
89+
openapi_v31_spec_validator.validate(spec_dict)
90+
assert response.status_code == HTTPStatus.OK
91+
92+
93+
def test_get_swagger_json_is_not_valid_openapi_v3_0():
94+
"""Verify that /api/swagger.json file does NOT comply with OpenAPI v3.0."""
95+
response = _get_request(ROOT_URL + SWAGGER_JSON_PATH)
96+
spec_dict = loads(response.text)
97+
with pytest.raises(OpenAPIValidationError):
98+
openapi_v30_spec_validator.validate(spec_dict)
8999
assert response.status_code == HTTPStatus.OK
90100

91101

92102
def test_get_swagger_json_is_not_valid_openapi_v2():
93-
"""Verify that /api/swagger.json file does NOT comply with OpenAPI v3."""
103+
"""Verify that /api/swagger.json file does NOT comply with OpenAPI v2."""
94104
response = _get_request(ROOT_URL + SWAGGER_JSON_PATH)
95105
spec_dict = loads(response.text)
96106
with pytest.raises(OpenAPIValidationError):
@@ -169,30 +179,35 @@ def test_post_model_predict_datetime_param_missing_z_status_code_equals_200():
169179
assert MOCK_PREDICTION in response.text
170180

171181

172-
def test_post_model_predict_string_param_float_status_code_equals_200():
173-
"""Verify that calling /model/predict with float as string_param works fine
174-
(yes, that's now pydantic rolls)."""
175-
response = _post_request_good_json_with_overrides(STRING_PARAM, 10.1)
176-
assert response.status_code == HTTPStatus.OK
177-
assert MOCK_PREDICTION in response.text
178-
179-
180-
def test_post_model_predict_int_param_float_status_code_equals_200():
181-
"""Verify that calling /model/predict with float as int_param works fine
182-
(yes, that's now pydantic rolls)."""
183-
response = _post_request_good_json_with_overrides(INT_PARAM, 10.1)
182+
def test_post_model_predict_float_param_int_value_status_code_equals_200():
183+
"""Verify that calling /model/predict with integer value as float_param works fine."""
184+
response = _post_request_good_json_with_overrides(FLOAT_PARAM, 10)
184185
assert response.status_code == HTTPStatus.OK
185186
assert MOCK_PREDICTION in response.text
186187

187188

188189
def test_post_model_predict_bool_param_string_true_status_code_equals_200():
189-
"""Verify that calling /model/predict with string "2"True" as bool_param works fine
190+
"""Verify that calling /model/predict with string "True" as bool_param works fine
190191
(yes, that's now pydantic rolls)."""
191192
response = _post_request_good_json_with_overrides(BOOL_PARAM, "True")
192193
assert response.status_code == HTTPStatus.OK
193194
assert MOCK_PREDICTION in response.text
194195

195196

197+
def test_post_model_predict_string_param_float_status_code_equals_422():
198+
"""Verify that calling /model/predict with float as string_param fails with 422."""
199+
response = _post_request_good_json_with_overrides(STRING_PARAM, 10.1)
200+
assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY
201+
assert "string_type" in response.text
202+
203+
204+
def test_post_model_predict_int_param_float_status_code_equals_422():
205+
"""Verify that calling /model/predict with float as int_param fails with 422."""
206+
response = _post_request_good_json_with_overrides(INT_PARAM, 10.1)
207+
assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY
208+
assert "int_from_float" in response.text
209+
210+
196211
def test_post_model_predict_int_param_missing_status_code_equals_422():
197212
"""Verify that calling /model/predict with no int_param fails with 422 and flags missing
198213
properties as required."""
@@ -252,7 +267,7 @@ def test_post_model_predict_int_param_string_status_code_equals_422():
252267
wrong type."""
253268
response = _post_request_good_json_with_overrides(INT_PARAM, "a")
254269
assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY
255-
assert "type_error.integer" in response.text
270+
assert "int_parsing" in response.text
256271
assert INT_PARAM in response.text
257272

258273

@@ -261,7 +276,7 @@ def test_post_model_predict_float_param_string_status_code_equals_422():
261276
wrong type."""
262277
response = _post_request_good_json_with_overrides(FLOAT_PARAM, "a")
263278
assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY
264-
assert "type_error.float" in response.text
279+
assert "float_parsing" in response.text
265280
assert FLOAT_PARAM in response.text
266281

267282

@@ -270,7 +285,7 @@ def test_post_model_predict_bool_param_string_status_code_equals_422():
270285
wrong type."""
271286
response = _post_request_good_json_with_overrides(BOOL_PARAM, "foo")
272287
assert response.status_code == HTTPStatus.UNPROCESSABLE_ENTITY
273-
assert "type_error.bool" in response.text
288+
assert "bool_parsing" in response.text
274289
assert BOOL_PARAM in response.text
275290

276291

@@ -363,7 +378,7 @@ def test_post_model_predict_datetime_param_bad_minute_status_code_equals_422():
363378

364379

365380
def test_post_model_predict_datetime_param_bad_second_status_code_equals_422():
366-
"""Verify that calling /model/predict with bad datetime_param (impossible second number)
381+
"""Verify that calling /model/predict with bad datetime_param (impossible seconds number)
367382
fails with 422 and flags wrong type."""
368383
response = _post_request_good_json_with_overrides(
369384
DATETIME_PARAM, "2021-11-30T14:37:64.15Z"

0 commit comments

Comments
 (0)