From e9903b81627dca360250c86223cfbab7933ab6a1 Mon Sep 17 00:00:00 2001 From: Madhava Jay Date: Fri, 18 Sep 2020 00:42:07 +1000 Subject: [PATCH] Test coverage fix (#4564) * add pprint test for Specific * add tests for _deserialize * add serde test for RunFunctionOrConstructorAction * add tests for object search permission update * lint * address comments * Fixing linting issues and test - Fixed failing test_Floatconversion test - Removed @pytest.mark.xfail Co-authored-by: Jasopaum --- docs/basics.rst | 2 +- docs/codebase_walkthrough.rst | 2 +- docs/coding_standards.rst | 2 +- docs/dev_environment.rst | 2 +- docs/duet.rst | 2 +- docs/finding_an_issue.rst | 2 +- docs/installing.rst | 80 +++++++++--------- docs/joining_a_team.rst | 2 +- requirements.txt | 1 + setup.cfg | 2 +- src/syft/core/common/serde/deserialize.py | 13 ++- tests/syft/core/common/serde/__init__.py | 0 .../core/common/serde/deserialize_test.py | 17 ++++ tests/syft/core/io/location/specific_test.py | 8 ++ .../function_or_constructor_action_test.py | 43 ++++++++++ .../obj_search_permission_service_test.py | 82 +++++++++++++++++++ tests/syft/lib/python/float/float_test.py | 22 +++-- 17 files changed, 220 insertions(+), 62 deletions(-) create mode 100644 tests/syft/core/common/serde/__init__.py create mode 100644 tests/syft/core/common/serde/deserialize_test.py create mode 100644 tests/syft/core/node/common/action/function_or_constructor_action_test.py create mode 100644 tests/syft/core/node/common/service/obj_search_permission_service_test.py diff --git a/docs/basics.rst b/docs/basics.rst index 13abf7251c0..98dc6398db3 100644 --- a/docs/basics.rst +++ b/docs/basics.rst @@ -1,3 +1,3 @@ *************************** Getting Started with PySyft -*************************** \ No newline at end of file +*************************** diff --git a/docs/codebase_walkthrough.rst b/docs/codebase_walkthrough.rst index a249f11df8e..886b30f20bd 100644 --- a/docs/codebase_walkthrough.rst +++ b/docs/codebase_walkthrough.rst @@ -1,3 +1,3 @@ ********************************** Step 2 - Learn the PySyft Codebase -********************************** \ No newline at end of file +********************************** diff --git a/docs/coding_standards.rst b/docs/coding_standards.rst index a0e9e0acf93..61b2495986e 100644 --- a/docs/coding_standards.rst +++ b/docs/coding_standards.rst @@ -1,3 +1,3 @@ ******************************** Step 4 - Your First Pull Request -******************************** \ No newline at end of file +******************************** diff --git a/docs/dev_environment.rst b/docs/dev_environment.rst index b2bd8347a6b..08ac429eda9 100644 --- a/docs/dev_environment.rst +++ b/docs/dev_environment.rst @@ -1,3 +1,3 @@ *********************************** Step 1 - Setup Your Dev Environment -*********************************** \ No newline at end of file +*********************************** diff --git a/docs/duet.rst b/docs/duet.rst index 633e68a9e3a..c91f424f6e1 100644 --- a/docs/duet.rst +++ b/docs/duet.rst @@ -1,3 +1,3 @@ ************************* Launch a Duet with PySyft -************************* \ No newline at end of file +************************* diff --git a/docs/finding_an_issue.rst b/docs/finding_an_issue.rst index 85119eff534..a7f49557eba 100644 --- a/docs/finding_an_issue.rst +++ b/docs/finding_an_issue.rst @@ -1,3 +1,3 @@ *************************** Step 3 - Your First Project -*************************** \ No newline at end of file +*************************** diff --git a/docs/installing.rst b/docs/installing.rst index 2b325ff71b2..fedf94b3c5f 100644 --- a/docs/installing.rst +++ b/docs/installing.rst @@ -2,10 +2,10 @@ Install PySyft ************** -This page shows how to install Syft version 0.3.0. As this software is currently in alpha, -there are changes happening every day. Thus, the best way to install PySyft is to build -it from source. Each of the tutorials below describe how to build PySyft from source -within each respective operating system. +This page shows how to install Syft version 0.3.0. As this software is currently in +alpha, there are changes happening every day. Thus, the best way to install PySyft is +to build it from source. Each of the tutorials below describe how to build PySyft from +source within each respective operating system. If you get stuck anywhere in this tutorial, please `join OpenMined's slack `_ and ask a question in the channel called `#topic_beginner_questions `_. @@ -60,9 +60,9 @@ are running one of these versions. Run the following: > python --version Python 3.8.1 -If the version printed underneath your command is less than 3.6, then you MUST use anaconda -in the next step (which is recommended anyway). Technically, you could try to upgrade your -version of python but fair warning... e're be dragons. +If the version printed underneath your command is less than 3.6, then you MUST use +anaconda in the next step (which is recommended anyway). Technically, you could try to +upgrade your version of python but fair warning... e're be dragons. Step 3 - Setup Environment @@ -72,19 +72,21 @@ I'm sure you're tempted to skip this step. Word from the wise... `Don't skip this step. `_ -You are about to install a library with lots of complex dependencies. You don't want to break -something on your computer because you're installing PySyft. And vice versa, you don't want -to later break your PySyft install when installing some other tool later! Friends don't -let friends build libraries from source without using a virtual environment. +You are about to install a library with lots of complex dependencies. You don't want to +break something on your computer because you're installing PySyft. And vice versa, you +don't want to later break your PySyft install when installing some other tool later! +Friends don't let friends build libraries from source without using a virtual +environment. And since PySyft uses (and will use more and more) non-python dependencies, the best -virtual environment to use for PySyft is conda. Note, if you're tempted to use virtualenv -instead, `read this warning `_. +virtual environment to use for PySyft is conda. Note, if you're tempted to use +virtualenv instead, `read this warning `_. Step 3.1 - Install Conda ^^^^^^^^^^^^^^^^^^^^^^^^ -First, let's see if you have conda installed! Type "conda" into your Terminal app and hit enter. +First, let's see if you have conda installed! Type "conda" into your Terminal app and +hit enter. .. code:: console @@ -103,15 +105,15 @@ First, let's see if you have conda installed! Type "conda" into your Terminal ap file (/Users/atrask/.condarc) by default. create Create a new conda environment from a list of specified -If calling "conda" doesn't return something like this, then you need to install conda. Just -follow the `installation instructions `_ +If calling "conda" doesn't return something like this, then you need to install conda. +Just follow the `installation instructions `_ and you'll be fine. Step 3.2 - Create conda Env ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Now, we want to create a conda virtual environment with the latest verison of Python supported -by syft which, at the time of writing, is 3.8. +Now, we want to create a conda virtual environment with the latest verison of Python +supported by syft which, at the time of writing, is 3.8. .. code:: console @@ -123,8 +125,9 @@ Then follow the instructions it gives you to create your environment. Step 3.3 - Activate Conda Env ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To activate the environment you created in the last step, simply enter `activate ` -which if you simply copy pasted the line above, the environment name was "my_syft_env". +To activate the environment you created in the last step, simply enter +`activate ` which if you simply copy pasted the line above, the +environment name was "my_syft_env". .. code:: console @@ -132,32 +135,32 @@ which if you simply copy pasted the line above, the environment name was "my_syf .. note:: - You will need to activate this my_syft_env environment whenever you want to use syft, - unless of course you install syft in another environment. + You will need to activate this my_syft_env environment whenever you want to use + syft, unless of course you install syft in another environment. Step 4 - Install Dependencies ----------------------------- -Assuming you're still in the base directory of PySyft (as you came to be in step 1), you can -now install the dependencies that PySyft relies on using the following command: +Assuming you're still in the base directory of PySyft (as you came to be in step 1), +you can now install the dependencies that PySyft relies on using the following command: .. code:: console pip install -r requirements.txt -This should install all the libraries you need for PySyft. Just in case, let's make sure -you have a compatible version of PyTorch. Your PyTorch version should be 1.3 or later. Open -up a python shell (by running `python` in your Terminal client) and then execute the following -python code. +This should install all the libraries you need for PySyft. Just in case, let's make +sure you have a compatible version of PyTorch. Your PyTorch version should be 1.3 or +later. Open up a python shell (by running `python` in your Terminal client) and then +execute the following python code. .. code:: python import torch print(torch.__version__) -As long as this reads 1.3 or later, you should be good. If it's 1.3 or earlier, then upgrade -it by installing the latest version. +As long as this reads 1.3 or later, you should be good. If it's 1.3 or earlier, then +upgrade it by installing the latest version. .. code:: console @@ -166,16 +169,17 @@ it by installing the latest version. Step 5 - Install PySyft ----------------------- -You are now ready to install PySyft! We recommend the following just in case you later decide -you want to help edit the codebase. +You are now ready to install PySyft! We recommend the following just in case you later +decide you want to help edit the codebase. .. code:: python pip install -e . -This will create a permanent pointer from the PySyft code to your conda VM. That means that if -you make any changes to the code you won't have to re-install PySyft to be able to use them! -If you don't want this fanciness you can also run the good ole fashioned setup.py install. +This will create a permanent pointer from the PySyft code to your conda VM. That means +that if you make any changes to the code you won't have to re-install PySyft to be able +to use them! If you don't want this fanciness you can also run the good ole fashioned +setup.py install. .. code:: python @@ -184,9 +188,9 @@ If you don't want this fanciness you can also run the good ole fashioned setup.p Step 6 - Run Light Tests ------------------------ -At the time of writing, we have quite a few unit tests but most of them are simply testing -the PyTorch runtime. To run the abbreviated set of tests (and make sure your installation -is happy), run the following. +At the time of writing, we have quite a few unit tests but most of them are simply +testing the PyTorch runtime. To run the abbreviated set of tests (and make sure your +installation is happy), run the following. .. code:: python diff --git a/docs/joining_a_team.rst b/docs/joining_a_team.rst index 6279962352a..c40159fcfd6 100644 --- a/docs/joining_a_team.rst +++ b/docs/joining_a_team.rst @@ -1,3 +1,3 @@ ************************ Step 5 - Join a Dev Team -************************ \ No newline at end of file +************************ diff --git a/requirements.txt b/requirements.txt index 92c0ec4c021..5762a9e13e7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -18,6 +18,7 @@ bandit black dataclasses # backport to python 3.6 +doc8 flake8 flask forbiddenfruit>=0.1.3 diff --git a/setup.cfg b/setup.cfg index cc110a91ff2..52370dabf51 100644 --- a/setup.cfg +++ b/setup.cfg @@ -169,4 +169,4 @@ import_heading_syft=syft absolute import_heading_localfolder=syft relative ignore_comments=False force_grid_wrap=True -honor_noqa=True \ No newline at end of file +honor_noqa=True diff --git a/src/syft/core/common/serde/deserialize.py b/src/syft/core/common/serde/deserialize.py index 1c8ad452f8a..e9a4c1e6a15 100644 --- a/src/syft/core/common/serde/deserialize.py +++ b/src/syft/core/common/serde/deserialize.py @@ -81,14 +81,13 @@ def _deserialize( obj_type = type(blob).schema2type # type: ignore # uh-oh! Looks like the type doesn't exist. Let's throw an informative error. - except KeyError: - + except AttributeError: raise TypeError( - """You tried to deserialize an unsupported type. This can be caused by - several reasons. Either you are actively writing Syft code and forgot - to create one, or you are trying to deserialize an object which was - serialized using a different version of Syft and the object you tried - to deserialize is not supported in this version.""" + "You tried to deserialize an unsupported type. This can be caused by " + "several reasons. Either you are actively writing Syft code and forgot " + "to create one, or you are trying to deserialize an object which was " + "serialized using a different version of Syft and the object you tried " + "to deserialize is not supported in this version." ) return obj_type._proto2object(proto=blob) diff --git a/tests/syft/core/common/serde/__init__.py b/tests/syft/core/common/serde/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/syft/core/common/serde/deserialize_test.py b/tests/syft/core/common/serde/deserialize_test.py new file mode 100644 index 00000000000..71860cb6ad0 --- /dev/null +++ b/tests/syft/core/common/serde/deserialize_test.py @@ -0,0 +1,17 @@ +# third party +from pytest import raises + +# syft absolute +from syft.core.common.serde.deserialize import _deserialize + + +def test_fail_deserialize_no_format() -> None: + with raises( + ValueError, match="Please pick the format of the data on the deserialization" + ): + _deserialize(blob="to deserialize", from_proto=False) + + +def test_fail_deserialize_wrong_format() -> None: + with raises(TypeError, match="You tried to deserialize an unsupported type."): + _deserialize(blob="to deserialize") diff --git a/tests/syft/core/io/location/specific_test.py b/tests/syft/core/io/location/specific_test.py index 3f3e5f0342f..3ca1f6d50f9 100644 --- a/tests/syft/core/io/location/specific_test.py +++ b/tests/syft/core/io/location/specific_test.py @@ -70,6 +70,14 @@ def test_to_string() -> None: assert obj.__repr__() == "" +def test_pprint() -> None: + """Tests that SpecificLocation generates a pretty representation.""" + + uid = UID(value=uuid.UUID(int=333779996850170035686993356951732753684)) + obj = SpecificLocation(id=uid, name="location") + assert obj.pprint == "📌 location (SpecificLocation)@" + + # --------------------- SERDE --------------------- diff --git a/tests/syft/core/node/common/action/function_or_constructor_action_test.py b/tests/syft/core/node/common/action/function_or_constructor_action_test.py new file mode 100644 index 00000000000..6ba7d0434ba --- /dev/null +++ b/tests/syft/core/node/common/action/function_or_constructor_action_test.py @@ -0,0 +1,43 @@ +# third party +import torch as th + +# syft absolute +import syft as sy +from syft.core.common.uid import UID +from syft.core.node.common.action.function_or_constructor_action import ( + RunFunctionOrConstructorAction, +) + +# TODO test execution +# TODO test permissions + + +def test_run_function_or_constructor_action_serde() -> None: + alice = sy.VirtualMachine(name="alice") + alice_client = alice.get_client() + + args = ( + th.tensor([1, 2, 3]).send(alice_client), + th.tensor([4, 5, 5]).send(alice_client), + ) + + msg = RunFunctionOrConstructorAction( + path="torch.Tensor.add", + args=args, + kwargs={}, + id_at_location=UID(), + address=alice_client.address, + msg_id=UID(), + ) + + blob = msg.serialize() + + msg2 = sy.deserialize(blob=blob) + + assert msg2.path == msg.path + # FIXME this cannot be checked before we fix the Pointer serde problem (see _proto2object in Pointer) + # assert msg2.args == msg.args + assert msg2.kwargs == msg.kwargs + assert msg2.address == msg.address + assert msg2.id == msg.id + assert msg2.id_at_location == msg.id_at_location diff --git a/tests/syft/core/node/common/service/obj_search_permission_service_test.py b/tests/syft/core/node/common/service/obj_search_permission_service_test.py new file mode 100644 index 00000000000..e6c695f11a2 --- /dev/null +++ b/tests/syft/core/node/common/service/obj_search_permission_service_test.py @@ -0,0 +1,82 @@ +# third party +import torch as th + +# syft absolute +import syft as sy +from syft.core.node.common.service.obj_search_permission_service import ( + ImmediateObjectSearchPermissionUpdateService, +) +from syft.core.node.common.service.obj_search_permission_service import ( + ObjectSearchPermissionUpdateMessage, +) + + +def test_object_search_permissons_update_message_serde() -> None: + bob_phone = sy.Device(name="Bob's iPhone") + bob_phone_client = bob_phone.get_client() + + ptr = th.tensor([1, 2, 3]).send(bob_phone_client) + + msg = ObjectSearchPermissionUpdateMessage( + add_instead_of_remove=True, + target_verify_key=bob_phone_client.verify_key, + target_object_id=ptr.id_at_location, + address=bob_phone_client.address, + ) + + blob = msg.serialize() + msg2 = sy.deserialize(blob=blob) + + assert msg.id == msg2.id + assert msg.address == msg2.address + assert msg.add_instead_of_remove == msg2.add_instead_of_remove + assert msg.target_verify_key == msg2.target_verify_key + assert msg.target_object_id == msg2.target_object_id + + +def test_object_search_permissons_update_execute_add() -> None: + bob_phone = sy.Device(name="Bob's iPhone") + bob_phone_client = bob_phone.get_client() + + ptr = th.tensor([1, 2, 3]).send(bob_phone_client) + + msg = ObjectSearchPermissionUpdateMessage( + add_instead_of_remove=True, + target_verify_key=bob_phone_client.verify_key, + target_object_id=ptr.id_at_location, + address=bob_phone_client.address, + ) + + ImmediateObjectSearchPermissionUpdateService.process( + node=bob_phone, msg=msg, verify_key=bob_phone.verify_key + ) + + assert ( + bob_phone.store[ptr.id_at_location].search_permissions[bob_phone.verify_key] + == msg.id + ) + + +def test_object_search_permissons_update_execute_remove() -> None: + bob_phone = sy.Device(name="Bob's iPhone") + bob_phone_client = bob_phone.get_client() + + ptr = th.tensor([1, 2, 3]).send(bob_phone_client) + + msg = ObjectSearchPermissionUpdateMessage( + add_instead_of_remove=False, + target_verify_key=bob_phone_client.verify_key, + target_object_id=ptr.id_at_location, + address=bob_phone_client.address, + ) + + bob_phone.store[ptr.id_at_location].search_permissions[bob_phone.verify_key] = None + + ImmediateObjectSearchPermissionUpdateService.process( + node=bob_phone, msg=msg, verify_key=bob_phone.verify_key + ) + + assert ( + bob_phone.verify_key + not in bob_phone.store[ptr.id_at_location].search_permissions + ) diff --git a/tests/syft/lib/python/float/float_test.py b/tests/syft/lib/python/float/float_test.py index 10eaa7b73f2..ba3af0db645 100644 --- a/tests/syft/lib/python/float/float_test.py +++ b/tests/syft/lib/python/float/float_test.py @@ -3,6 +3,7 @@ from math import isnan import operator import random +import sys import time # third party @@ -288,7 +289,6 @@ def test_Float_with_comma() -> None: assert Float(" 25.e-1 ") == 2.5 -@pytest.mark.xfail def test_Floatconversion() -> None: # Make sure that calls to __float__() work properly class Foo1(object): @@ -330,16 +330,20 @@ def __Float__(self): with pytest.raises(TypeError): time.sleep(Foo5()) - class MyIndex: - def __init__(self, value): - self.value = value + # using __index__ in init was added in python 3.8 + # https://github.com/python/cpython/commit/bdbad71b9def0b86433de12cecca022eee91bd9f + if sys.version_info >= (3, 8): - def __index__(self): - return self.value + class MyIndex: + def __init__(self, value): + self.value = value - assert Float(MyIndex(42)) == 42.0 - with pytest.raises(OverflowError): - Float(MyIndex(2 ** 2000)) + def __index__(self): + return self.value + + assert Float(MyIndex(42)) == 42.0 + with pytest.raises(OverflowError): + Float(MyIndex(2 ** 2000)) class MyInt: def __int__(self):