From dd7af02428d261e7c4c69c44cfb944850f85e960 Mon Sep 17 00:00:00 2001 From: ganesh-k13 Date: Fri, 13 Jan 2023 19:57:39 +0530 Subject: [PATCH 1/3] ENH: Added python version to metadata --- vetiver/meta.py | 5 ++++- vetiver/pin_read_write.py | 1 + vetiver/vetiver_model.py | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/vetiver/meta.py b/vetiver/meta.py index d2a10f93..ff4dda3f 100644 --- a/vetiver/meta.py +++ b/vetiver/meta.py @@ -1,3 +1,4 @@ +import sys from dataclasses import dataclass, asdict, field from typing import Mapping @@ -10,6 +11,7 @@ class VetiverMeta: version: "str | None" = None url: "str | None" = None required_pkgs: "list | None" = field(default_factory=list) + python_version: "str | None" = None def to_dict(self) -> Mapping: data = asdict(self) @@ -25,9 +27,10 @@ def from_dict(cls, metadata, pip_name=None) -> "VetiverMeta": version = metadata.get("version", None) url = metadata.get("url", None) required_pkgs = metadata.get("required_pkgs", []) + python_version = metadata.get("python_version", sys.version) if pip_name: if not list(filter(lambda x: pip_name in x, required_pkgs)): required_pkgs = required_pkgs + [f"{pip_name}"] - return cls(user, version, url, required_pkgs) + return cls(user, version, url, required_pkgs, python_version) diff --git a/vetiver/pin_read_write.py b/vetiver/pin_read_write.py index 8da5c872..aaa4dab1 100644 --- a/vetiver/pin_read_write.py +++ b/vetiver/pin_read_write.py @@ -70,6 +70,7 @@ def vetiver_pin_write(board, model: VetiverModel, versioned: bool = True): "vetiver_meta": { "required_pkgs": model.metadata.required_pkgs, "prototype": None if not model.prototype else model.prototype().json(), + "python_version": model.metadata.python_version, }, }, versioned=versioned, diff --git a/vetiver/vetiver_model.py b/vetiver/vetiver_model.py index 9cef84c5..cfa7868b 100644 --- a/vetiver/vetiver_model.py +++ b/vetiver/vetiver_model.py @@ -102,6 +102,7 @@ def from_pin(cls, board, name: str, version: str = None): if "vetiver_meta" in meta.user: get_prototype = meta.user.get("vetiver_meta").get("prototype", None) required_pkgs = meta.user.get("vetiver_meta").get("required_pkgs", None) + python_version = meta.user.get("vetiver_meta").get("python_version", None) meta.user.pop("vetiver_meta") else: # ptype = meta.user.get("ptype", None) @@ -113,6 +114,7 @@ def from_pin(cls, board, name: str, version: str = None): # get_prototype = None required_pkgs = meta.user.get("required_pkgs") + python_version = meta.user.get("python_version") return cls( model=model, @@ -123,6 +125,7 @@ def from_pin(cls, board, name: str, version: str = None): "version": meta.version.version, "url": meta.local.get("url"), # None all the time, besides Connect, "required_pkgs": required_pkgs, + "python_version": python_version, }, prototype_data=json.loads(get_prototype) if get_prototype else None, versioned=True, From ab15a7344f4ce1d5ca37e3fad84a1716298d1fb0 Mon Sep 17 00:00:00 2001 From: ganesh-k13 Date: Fri, 13 Jan 2023 20:21:26 +0530 Subject: [PATCH 2/3] TST: Added testcase for user metadata --- vetiver/tests/test_build_vetiver_model.py | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/vetiver/tests/test_build_vetiver_model.py b/vetiver/tests/test_build_vetiver_model.py index 2832ea0c..dd635515 100644 --- a/vetiver/tests/test_build_vetiver_model.py +++ b/vetiver/tests/test_build_vetiver_model.py @@ -1,4 +1,5 @@ import sklearn +import sys import vetiver as vt from vetiver.meta import VetiverMeta @@ -113,6 +114,7 @@ def test_vetiver_model_use_ptype(): version=None, url=None, required_pkgs=["scikit-learn"], + python_version=sys.version, ) @@ -137,5 +139,41 @@ def test_vetiver_model_from_pin(): assert v2.metadata.user == {"test": 123} assert v2.metadata.version is not None assert v2.metadata.required_pkgs == ["scikit-learn"] + assert v2.metadata.python_version == sys.version + + board.pin_delete("model") + + +def test_vetiver_model_from_pin_user_metadata(): + """ + Test if standard keys as part of :dataclass:`VetiverMeta` are picked + """ + custom_meta = { + "test": 123, + "required_pkgs": ["foo", "bar"], + "python_version": "baz", + } + loaded_pkgs = custom_meta["required_pkgs"] + ["scikit-learn"] + + v = vt.VetiverModel( + model=model, + prototype_data=X_df, + model_name="model", + versioned=None, + description=None, + metadata=custom_meta, + ) + + board = pins.board_temp(allow_pickle_read=True) + vt.vetiver_pin_write(board=board, model=v) + v2 = vt.VetiverModel.from_pin(board, "model") + + assert isinstance(v2, vt.VetiverModel) + assert isinstance(v2.model, sklearn.base.BaseEstimator) + assert isinstance(v2.prototype.construct(), pydantic.BaseModel) + assert v2.metadata.user == custom_meta + assert v2.metadata.version is not None + assert v2.metadata.required_pkgs == loaded_pkgs + assert v2.metadata.python_version == custom_meta["python_version"] board.pin_delete("model") From 9325d3565851776bd36efe90c79fd755d2d18ab1 Mon Sep 17 00:00:00 2001 From: ganesh-k13 Date: Mon, 23 Jan 2023 17:58:41 +0530 Subject: [PATCH 3/3] MAINT: Changed `version` -> `version_info` --- vetiver/meta.py | 4 ++-- vetiver/pin_read_write.py | 2 +- vetiver/tests/test_build_vetiver_model.py | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/vetiver/meta.py b/vetiver/meta.py index ff4dda3f..a09e2e02 100644 --- a/vetiver/meta.py +++ b/vetiver/meta.py @@ -11,7 +11,7 @@ class VetiverMeta: version: "str | None" = None url: "str | None" = None required_pkgs: "list | None" = field(default_factory=list) - python_version: "str | None" = None + python_version: "tuple | None" = None def to_dict(self) -> Mapping: data = asdict(self) @@ -27,7 +27,7 @@ def from_dict(cls, metadata, pip_name=None) -> "VetiverMeta": version = metadata.get("version", None) url = metadata.get("url", None) required_pkgs = metadata.get("required_pkgs", []) - python_version = metadata.get("python_version", sys.version) + python_version = tuple(metadata.get("python_version", sys.version_info)) if pip_name: if not list(filter(lambda x: pip_name in x, required_pkgs)): diff --git a/vetiver/pin_read_write.py b/vetiver/pin_read_write.py index aaa4dab1..db2b44ea 100644 --- a/vetiver/pin_read_write.py +++ b/vetiver/pin_read_write.py @@ -70,7 +70,7 @@ def vetiver_pin_write(board, model: VetiverModel, versioned: bool = True): "vetiver_meta": { "required_pkgs": model.metadata.required_pkgs, "prototype": None if not model.prototype else model.prototype().json(), - "python_version": model.metadata.python_version, + "python_version": list(model.metadata.python_version), }, }, versioned=versioned, diff --git a/vetiver/tests/test_build_vetiver_model.py b/vetiver/tests/test_build_vetiver_model.py index dd635515..354c5482 100644 --- a/vetiver/tests/test_build_vetiver_model.py +++ b/vetiver/tests/test_build_vetiver_model.py @@ -114,7 +114,7 @@ def test_vetiver_model_use_ptype(): version=None, url=None, required_pkgs=["scikit-learn"], - python_version=sys.version, + python_version=tuple(sys.version_info), ) @@ -139,7 +139,7 @@ def test_vetiver_model_from_pin(): assert v2.metadata.user == {"test": 123} assert v2.metadata.version is not None assert v2.metadata.required_pkgs == ["scikit-learn"] - assert v2.metadata.python_version == sys.version + assert v2.metadata.python_version == tuple(sys.version_info) board.pin_delete("model") @@ -151,7 +151,7 @@ def test_vetiver_model_from_pin_user_metadata(): custom_meta = { "test": 123, "required_pkgs": ["foo", "bar"], - "python_version": "baz", + "python_version": [3, 10, 6, "final", 0], } loaded_pkgs = custom_meta["required_pkgs"] + ["scikit-learn"] @@ -174,6 +174,6 @@ def test_vetiver_model_from_pin_user_metadata(): assert v2.metadata.user == custom_meta assert v2.metadata.version is not None assert v2.metadata.required_pkgs == loaded_pkgs - assert v2.metadata.python_version == custom_meta["python_version"] + assert v2.metadata.python_version == tuple(custom_meta["python_version"]) board.pin_delete("model")