From 42d6a9b55392b1fcfa1b00b833e75bfd710adde5 Mon Sep 17 00:00:00 2001 From: ElmiRakh Date: Wed, 19 Aug 2020 21:43:02 +0300 Subject: [PATCH 1/6] EBNT-420 Something like this? --- examples/cv_kot_example/nvidia_image_test.py | 9 +++++++++ src/ebonite/ext/cv_streaming/__init__.py | 0 src/ebonite/ext/cv_streaming/build/app.py | 6 ++++++ src/ebonite/ext/cv_streaming/server.py | 19 +++++++++++++++++++ tests/ext/test_cvstreaming/__init__.py | 0 5 files changed, 34 insertions(+) create mode 100644 examples/cv_kot_example/nvidia_image_test.py create mode 100644 src/ebonite/ext/cv_streaming/__init__.py create mode 100644 src/ebonite/ext/cv_streaming/build/app.py create mode 100644 src/ebonite/ext/cv_streaming/server.py create mode 100644 tests/ext/test_cvstreaming/__init__.py diff --git a/examples/cv_kot_example/nvidia_image_test.py b/examples/cv_kot_example/nvidia_image_test.py new file mode 100644 index 00000000..382dd538 --- /dev/null +++ b/examples/cv_kot_example/nvidia_image_test.py @@ -0,0 +1,9 @@ +import ebonite +from ebonite.build.builder.base import use_local_installation +from ebonite.ext.cv_streaming.server import CvStreamingServer + +with use_local_installation(): + ebnt = ebonite.client.Ebonite.local(clear=True) + task = ebnt.get_or_create_task('Proj', 'Task') + model = ebnt.create_model(lambda x: x, 'test_input', 'model', task_name='Task') + image = ebnt.create_image(model, 'image_name', server=CvStreamingServer, builder_args={'force_overwrite': True}) diff --git a/src/ebonite/ext/cv_streaming/__init__.py b/src/ebonite/ext/cv_streaming/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/ebonite/ext/cv_streaming/build/app.py b/src/ebonite/ext/cv_streaming/build/app.py new file mode 100644 index 00000000..5c928756 --- /dev/null +++ b/src/ebonite/ext/cv_streaming/build/app.py @@ -0,0 +1,6 @@ +from ebonite import start_runtime +from ebonite.ext.cv_streaming.server import CvStreamingServer + + +# STUB APP +start_runtime(CvStreamingServer) diff --git a/src/ebonite/ext/cv_streaming/server.py b/src/ebonite/ext/cv_streaming/server.py new file mode 100644 index 00000000..f9be55d6 --- /dev/null +++ b/src/ebonite/ext/cv_streaming/server.py @@ -0,0 +1,19 @@ +from ebonite.runtime.interface.base import Interface +from ebonite.runtime.server.base import Server +from ebonite.utils.fs import current_module_path + + +class CvStreamingServer(Server): + + additional_sources = [ + current_module_path('build', 'app.py') # replace stub in base image + ] + + additional_options = {'docker': { + 'templates_dir': current_module_path('build'), + 'run_cmd': False, # base image has already specified command + 'base_image': 'nvcr.io/nvidia/tensorrt:20.07.1-py3' + }} + + def run(self, executor: Interface): + pass diff --git a/tests/ext/test_cvstreaming/__init__.py b/tests/ext/test_cvstreaming/__init__.py new file mode 100644 index 00000000..e69de29b From 4eca592edcec7a49755dd29316a393489c897c76 Mon Sep 17 00:00:00 2001 From: ElmiRakh Date: Wed, 19 Aug 2020 21:44:07 +0300 Subject: [PATCH 2/6] Revert "EBNT-420 Something like this?" This reverts commit 42d6a9b5 --- examples/cv_kot_example/nvidia_image_test.py | 9 --------- src/ebonite/ext/cv_streaming/__init__.py | 0 src/ebonite/ext/cv_streaming/build/app.py | 6 ------ src/ebonite/ext/cv_streaming/server.py | 19 ------------------- tests/ext/test_cvstreaming/__init__.py | 0 5 files changed, 34 deletions(-) delete mode 100644 examples/cv_kot_example/nvidia_image_test.py delete mode 100644 src/ebonite/ext/cv_streaming/__init__.py delete mode 100644 src/ebonite/ext/cv_streaming/build/app.py delete mode 100644 src/ebonite/ext/cv_streaming/server.py delete mode 100644 tests/ext/test_cvstreaming/__init__.py diff --git a/examples/cv_kot_example/nvidia_image_test.py b/examples/cv_kot_example/nvidia_image_test.py deleted file mode 100644 index 382dd538..00000000 --- a/examples/cv_kot_example/nvidia_image_test.py +++ /dev/null @@ -1,9 +0,0 @@ -import ebonite -from ebonite.build.builder.base import use_local_installation -from ebonite.ext.cv_streaming.server import CvStreamingServer - -with use_local_installation(): - ebnt = ebonite.client.Ebonite.local(clear=True) - task = ebnt.get_or_create_task('Proj', 'Task') - model = ebnt.create_model(lambda x: x, 'test_input', 'model', task_name='Task') - image = ebnt.create_image(model, 'image_name', server=CvStreamingServer, builder_args={'force_overwrite': True}) diff --git a/src/ebonite/ext/cv_streaming/__init__.py b/src/ebonite/ext/cv_streaming/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/ebonite/ext/cv_streaming/build/app.py b/src/ebonite/ext/cv_streaming/build/app.py deleted file mode 100644 index 5c928756..00000000 --- a/src/ebonite/ext/cv_streaming/build/app.py +++ /dev/null @@ -1,6 +0,0 @@ -from ebonite import start_runtime -from ebonite.ext.cv_streaming.server import CvStreamingServer - - -# STUB APP -start_runtime(CvStreamingServer) diff --git a/src/ebonite/ext/cv_streaming/server.py b/src/ebonite/ext/cv_streaming/server.py deleted file mode 100644 index f9be55d6..00000000 --- a/src/ebonite/ext/cv_streaming/server.py +++ /dev/null @@ -1,19 +0,0 @@ -from ebonite.runtime.interface.base import Interface -from ebonite.runtime.server.base import Server -from ebonite.utils.fs import current_module_path - - -class CvStreamingServer(Server): - - additional_sources = [ - current_module_path('build', 'app.py') # replace stub in base image - ] - - additional_options = {'docker': { - 'templates_dir': current_module_path('build'), - 'run_cmd': False, # base image has already specified command - 'base_image': 'nvcr.io/nvidia/tensorrt:20.07.1-py3' - }} - - def run(self, executor: Interface): - pass diff --git a/tests/ext/test_cvstreaming/__init__.py b/tests/ext/test_cvstreaming/__init__.py deleted file mode 100644 index e69de29b..00000000 From f70216d6ed0d16d665600206cf31cbf7e335225c Mon Sep 17 00:00:00 2001 From: ElmiRakh Date: Wed, 9 Sep 2020 15:16:43 +0300 Subject: [PATCH 3/6] EBNT-398 Added couple tests for core --- tests/core/objects/test_core.py | 35 +++++++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/tests/core/objects/test_core.py b/tests/core/objects/test_core.py index bd5625c9..fc144bc2 100644 --- a/tests/core/objects/test_core.py +++ b/tests/core/objects/test_core.py @@ -3,18 +3,18 @@ from pyjackson import deserialize, serialize from pyjackson.core import Unserializable -from ebonite.core.errors import (EboniteError, MetadataError, NonExistingModelError, NonExistingTaskError, - UnboundObjectError) +from ebonite.core.errors import (EboniteError, MetadataError, NonExistingModelError, NonExistingProjectError, + NonExistingTaskError, UnboundObjectError) from ebonite.core.objects import ModelWrapper from ebonite.core.objects.artifacts import Blobs, InMemoryBlob -from ebonite.core.objects.core import Model, Pipeline, Project, Task, _WrapperMethodAccessor +from ebonite.core.objects.core import Image, Model, Pipeline, Project, Task, _WrapperMethodAccessor from ebonite.core.objects.dataset_source import DatasetSource from ebonite.core.objects.metric import Metric from ebonite.core.objects.requirements import InstallableRequirement, Requirement, Requirements from ebonite.ext.sklearn import SklearnModelWrapper from ebonite.repository import MetadataRepository from ebonite.repository.artifact.inmemory import InMemoryArtifactRepository -from tests.core.objects.conftest import serde_and_compare +from tests.core.objects.conftest import BuildableMock, serde_and_compare def test_project__add_task__unbind(project: Project, task_factory): @@ -93,6 +93,12 @@ def test_project_serde(project_saved): serde_and_compare(project_saved) +def test_task_wo_project(meta): + task = Task(name='task', project_id=666) + with pytest.raises(NonExistingProjectError): + meta.create_task(task) + + def test_task__project_property(project_saved_art, task): assert project_saved_art.has_artifact_repo assert project_saved_art.has_meta_repo @@ -179,6 +185,9 @@ def test_task__delete_model_with_artifacts(task_saved, model, artifact_repo): assert model.id is None assert model.task_id is None + task_saved.unbind_artifact_repo() + assert task_saved.has_artifact_repo is False + def test_task__delete_model__nonexistent(task_factory, model): model_task = task_factory(True) @@ -239,6 +248,8 @@ def test_task__delete_metric_non_existing(task_saved): def test_task__add_dataset(task_saved, dataset): + assert task_saved.has_dataset_repo is True + task_saved.add_dataset('data', dataset) assert 'data' in task_saved.datasets assert isinstance(task_saved.datasets['data'], DatasetSource) @@ -250,6 +261,9 @@ def test_task__add_dataset(task_saved, dataset): assert isinstance(task.datasets['data'], DatasetSource) assert not isinstance(task.datasets['data'], Unserializable) + task_saved.unbind_dataset_repo() + assert task_saved.has_dataset_repo is False + def test_task__add_dataset_exists(task_saved, dataset): task_saved.add_dataset('data', dataset) @@ -449,6 +463,13 @@ def f2(a): return model +def test_pipeline_wo_task(meta, len_model): + len_model.task_id = 666 + pipeline = len_model.as_pipeline() + with pytest.raises(NonExistingTaskError): + meta.create_pipeline(pipeline) + + def test_pipeline__append(double_model, len_model): p1 = double_model.as_pipeline() p2 = p1.append(len_model) @@ -548,6 +569,12 @@ def test_task__delete_pipeline(task_factory, pipeline_factory): # ################IMAGES########### +def test_image_wo_task(meta): + image = Image('image_name', params={'test': 'test'}, source=BuildableMock(), task_id=666) + with pytest.raises(NonExistingTaskError): + meta.create_image(image) + + def test_task__no_images(task_factory): task = task_factory(True) From c27f469cc8e0342fffaf79c53ed90583ee12ea85 Mon Sep 17 00:00:00 2001 From: ElmiRakh Date: Wed, 9 Sep 2020 16:50:23 +0300 Subject: [PATCH 4/6] EBNT-398 Experimenting with coveralls --- tests/core/objects/test_core.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/core/objects/test_core.py b/tests/core/objects/test_core.py index fc144bc2..27d3fbea 100644 --- a/tests/core/objects/test_core.py +++ b/tests/core/objects/test_core.py @@ -93,10 +93,10 @@ def test_project_serde(project_saved): serde_and_compare(project_saved) -def test_task_wo_project(meta): - task = Task(name='task', project_id=666) +def test_task_wo_project(task_saved): + task_saved.project_id = 666 with pytest.raises(NonExistingProjectError): - meta.create_task(task) + task_saved.project def test_task__project_property(project_saved_art, task): From e45f47b51c2b0b881317f6eea0c60a2fb3aa5832 Mon Sep 17 00:00:00 2001 From: ElmiRakh Date: Fri, 11 Sep 2020 14:09:40 +0300 Subject: [PATCH 5/6] EBNT-398 Core tests finalized --- tests/core/objects/test_core.py | 47 ++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/tests/core/objects/test_core.py b/tests/core/objects/test_core.py index 27d3fbea..5a00b644 100644 --- a/tests/core/objects/test_core.py +++ b/tests/core/objects/test_core.py @@ -3,18 +3,20 @@ from pyjackson import deserialize, serialize from pyjackson.core import Unserializable -from ebonite.core.errors import (EboniteError, MetadataError, NonExistingModelError, NonExistingProjectError, - NonExistingTaskError, UnboundObjectError) +from ebonite.core.errors import (EboniteError, MetadataError, NonExistingEnvironmentError, NonExistingModelError, + NonExistingPipelineError, NonExistingProjectError, NonExistingTaskError, + UnboundObjectError) from ebonite.core.objects import ModelWrapper from ebonite.core.objects.artifacts import Blobs, InMemoryBlob -from ebonite.core.objects.core import Image, Model, Pipeline, Project, Task, _WrapperMethodAccessor +from ebonite.core.objects.core import (Model, Pipeline, PipelineStep, Project, RuntimeEnvironment, Task, + _WrapperMethodAccessor) from ebonite.core.objects.dataset_source import DatasetSource from ebonite.core.objects.metric import Metric from ebonite.core.objects.requirements import InstallableRequirement, Requirement, Requirements from ebonite.ext.sklearn import SklearnModelWrapper from ebonite.repository import MetadataRepository from ebonite.repository.artifact.inmemory import InMemoryArtifactRepository -from tests.core.objects.conftest import BuildableMock, serde_and_compare +from tests.core.objects.conftest import serde_and_compare def test_project__add_task__unbind(project: Project, task_factory): @@ -99,6 +101,12 @@ def test_task_wo_project(task_saved): task_saved.project +def test_task_delete_nonexistant_pipe(task_saved): + pipe = Pipeline(id=666, name='pipe', steps=[PipelineStep('a', 'b'), ], input_data=str, output_data=str) + with pytest.raises(NonExistingPipelineError): + task_saved.delete_pipeline(pipe) + + def test_task__project_property(project_saved_art, task): assert project_saved_art.has_artifact_repo assert project_saved_art.has_meta_repo @@ -463,11 +471,13 @@ def f2(a): return model -def test_pipeline_wo_task(meta, len_model): - len_model.task_id = 666 +def test_pipeline_wo_task(meta, len_model, task_saved): pipeline = len_model.as_pipeline() + pipeline.task_id = task_saved.id + pipeline = meta.create_pipeline(pipeline) + pipeline.task_id = 666 with pytest.raises(NonExistingTaskError): - meta.create_pipeline(pipeline) + pipeline.task def test_pipeline__append(double_model, len_model): @@ -569,10 +579,27 @@ def test_task__delete_pipeline(task_factory, pipeline_factory): # ################IMAGES########### -def test_image_wo_task(meta): - image = Image('image_name', params={'test': 'test'}, source=BuildableMock(), task_id=666) +def test_image_wo_task(meta, image_factory, task_saved): + image = image_factory() + image.task_id = task_saved.id + image = meta.create_image(image) + image.task_id = 666 with pytest.raises(NonExistingTaskError): - meta.create_image(image) + image.task + + with pytest.raises(UnboundObjectError): + image.environment + + env = RuntimeEnvironment('env') + env = meta.create_environment(env) + + image_2 = image_factory() + image_2.task_id = task_saved.id + image_2.environment_id = env.id + image_2 = meta.create_image(image_2) + image_2.environment_id = 666 + with pytest.raises(NonExistingEnvironmentError): + image_2.environment def test_task__no_images(task_factory): From c0bf45b582b8b5504091773531428fd5c5362eea Mon Sep 17 00:00:00 2001 From: ElmiRakh Date: Fri, 11 Sep 2020 15:46:58 +0300 Subject: [PATCH 6/6] EBNT-398 Client tests --- tests/client/client_common.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/client/client_common.py b/tests/client/client_common.py index 7037b791..15a8d8ba 100644 --- a/tests/client/client_common.py +++ b/tests/client/client_common.py @@ -260,6 +260,16 @@ def test_delete_image__not_only_meta_ok(ebnt: Ebonite, image_to_delete: Image, m assert ebnt.meta_repo.get_image_by_id(image_to_delete.id) is None +def test_get_default_environment(ebnt: Ebonite): + ebnt.default_env = 'Pseudo_env' + env = ebnt.get_default_environment() + assert env == 'Pseudo_env' + + ebnt.default_env = None + ebnt.get_default_environment() + assert ebnt.get_environment('docker_localhost') is not None + + @docker_test def test_build_and_run_instance(ebnt: Ebonite, regression_and_data, container_name, mock_env): reg, data = regression_and_data