Skip to content

Commit a3388f0

Browse files
committed
updates to be compliant with new fastapi and pydantic
All changes are internal. The main changes are in prototypes and API errors. Prototypes now are created from dictionaries of tuples of (type, value). API errors are now a list of dictionaries, giving the type, location, error message, erroneous input, and a url to pydantic's website with more about the error.
1 parent 5662b98 commit a3388f0

5 files changed

Lines changed: 20 additions & 16 deletions

File tree

vetiver/prototype.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,8 +156,10 @@ def _item(value):
156156

157157
dict_data = dict(enumerate(data[0], 0))
158158
# pydantic requires strings as indicies
159+
# if its a numpy type, we have to take the Python type due to Pydantic
160+
159161
dict_data = {
160-
f"{key}": (type(value), _item(value)) for key, value in dict_data.items()
162+
f"{key}": (type(value.item()), _item(value)) for key, value in dict_data.items()
161163
}
162164
prototype = create_prototype(**dict_data)
163165
return prototype

vetiver/tests/test_build_vetiver_model.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
import pandas as pd
99
import pydantic
1010
import pins
11+
import numpy as np
12+
13+
np.random.seed(50)
1114

1215
# Load data, model
1316
X_df, y = get_mock_data()
@@ -33,8 +36,8 @@ def test_vetiver_model_array_prototype():
3336

3437
assert vt1.model == model
3538
assert issubclass(vt1.prototype, vt.Prototype)
36-
assert isinstance(vt1.prototype.construct(), pydantic.BaseModel)
37-
assert list(vt1.prototype.__fields__.values())[0].type_ == int
39+
assert isinstance(vt1.prototype.model_construct(), pydantic.BaseModel)
40+
assert vt1.prototype.model_construct().__dict__ == {"0": 96, "1": 11, "2": 33}
3841

3942

4043
def test_vetiver_model_df_prototype():
@@ -48,8 +51,8 @@ def test_vetiver_model_df_prototype():
4851
)
4952

5053
assert vt2.model == model
51-
assert isinstance(vt2.prototype.construct(), pydantic.BaseModel)
52-
assert list(vt2.prototype.__fields__.values())[0].type_ == int
54+
assert isinstance(vt2.prototype.model_construct(), pydantic.BaseModel)
55+
assert vt2.prototype.model_construct().B == 96
5356

5457

5558
def test_vetiver_model_dict_prototype():
@@ -64,8 +67,8 @@ def test_vetiver_model_dict_prototype():
6467
)
6568

6669
assert vt3.model == model
67-
assert isinstance(vt3.prototype.construct(), pydantic.BaseModel)
68-
assert list(vt3.prototype.__fields__.values())[0].type_ == int
70+
assert isinstance(vt3.prototype.model_construct(), pydantic.BaseModel)
71+
assert vt3.prototype.model_construct().B == 0
6972

7073

7174
def test_vetiver_model_basemodel_prototype():
@@ -135,7 +138,7 @@ def test_vetiver_model_from_pin():
135138

136139
assert isinstance(v2, vt.VetiverModel)
137140
assert isinstance(v2.model, sklearn.base.BaseEstimator)
138-
assert isinstance(v2.prototype.construct(), pydantic.BaseModel)
141+
assert isinstance(v2.prototype.model_construct(), pydantic.BaseModel)
139142
assert v2.metadata.user == {"test": 123}
140143
assert v2.metadata.version is not None
141144
assert v2.metadata.required_pkgs == ["scikit-learn"]
@@ -170,7 +173,7 @@ def test_vetiver_model_from_pin_user_metadata():
170173

171174
assert isinstance(v2, vt.VetiverModel)
172175
assert isinstance(v2.model, sklearn.base.BaseEstimator)
173-
assert isinstance(v2.prototype.construct(), pydantic.BaseModel)
176+
assert isinstance(v2.prototype.model_construct(), pydantic.BaseModel)
174177
assert v2.metadata.user == custom_meta
175178
assert v2.metadata.version is not None
176179
assert v2.metadata.required_pkgs == loaded_pkgs

vetiver/tests/test_custom_handler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def test_custom_vetiver_model():
4040
assert v.description == "A DummyRegressor model"
4141
assert not v.metadata.required_pkgs
4242
assert isinstance(v.model, sklearn.dummy.DummyRegressor)
43-
assert isinstance(v.prototype.construct(), pydantic.BaseModel)
43+
assert isinstance(v.prototype.model_construct(), pydantic.BaseModel)
4444

4545

4646
def test_custom_vetiver_model_no_ptype():
@@ -58,4 +58,4 @@ def test_custom_vetiver_model_no_ptype():
5858

5959
assert v.description == "A regression model for testing purposes"
6060
assert isinstance(v.model, sklearn.dummy.DummyRegressor)
61-
assert isinstance(v.prototype.construct(), pydantic.BaseModel)
61+
assert isinstance(v.prototype.model_construct(), pydantic.BaseModel)

vetiver/tests/test_sklearn.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,10 @@ def test_predict_sklearn_no_ptype(data, length, vetiver_client_check_ptype_false
7373

7474
@pytest.mark.parametrize("data", [(0), 0, 0.0, "0"])
7575
def test_predict_sklearn_type_error(data, vetiver_client):
76-
import re
7776

78-
msg = re.sub(
79-
r"\n",
80-
": ",
81-
"1 validation error for Request\nbody\n value is not a valid list \(type=type_error.list\)", # noqa
77+
msg = str(
78+
"[{'type': 'list_type', 'loc': ('body',), 'msg': 'Input should be a valid list', \
79+
'input': '0', 'url': 'https://errors.pydantic.dev/2.0.3/v/list_type'}]"
8280
)
8381

8482
with pytest.raises(TypeError, match=msg):

vetiver/vetiver_model.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def __init__(
8484
translator = create_handler(model, prototype_data)
8585

8686
self.model = translator.model
87+
self.prototype_data = prototype_data
8788
self.prototype = translator.construct_prototype()
8889
self.model_name = model_name
8990
self.description = description if description else translator.describe()

0 commit comments

Comments
 (0)