From c4233d6eb8c6811e61609853ab156ddf7bd9e801 Mon Sep 17 00:00:00 2001 From: Luc Guyot <luc.guyot@epfl.ch> Date: Wed, 17 Jul 2019 09:38:50 +0000 Subject: [PATCH] Merged in NRRPLT-7445 (pull request #16) [NRRPLT-7445] Implements the import_experiment() function * [NRRPLT-7445] Implements the import_experiment() function * [NRRPLT-7445] Fixes pylint and pep8 errors * [NRRPLT-7445] Fixes remaining pep8 error in it.py * [NRRPLT-7445] Adds missing folder required by the unit tests * [NRRPLT-7445] Adds the missing value experiment-import to the key proxy-services of the Config object * [NRRPLT-7445] Addresses code review comments: uses request.codes.ok instead of httplib.OK Approved-by: Manos Angelidis <angelidis@fortiss.org> --- bitbucket-pipelines.yml | 2 +- examples/integration_test/it.py | 36 +++++++-- .../test_experiment_folder.zip | Bin 0 -> 26769 bytes .../ExDTemplateHusky.exc | 22 ++++++ .../ExDTemplateHusky.ini | 1 + .../ExDTemplateHusky.jpg | Bin 0 -> 22424 bytes .../ExDTemplateHusky.uis | 9 +++ .../all_neurons_spike_monitor.py | 12 +++ .../brainvisualizer.json | 1 + .../test_experiment_folder/grab_image.py | 12 +++ .../template_husky.bibi | 12 +++ .../test_experiment_folder/turn_around.py | 14 ++++ .../hbp_nrp_virtual_coach/config.py | 2 +- .../hbp_nrp_virtual_coach/tests/test.zip | 0 .../test_experiment_folder/empty_file.txt | 0 .../tests/test_virtual_coach.py | 17 ++++ .../hbp_nrp_virtual_coach/virtual_coach.py | 74 ++++++++++++++++++ verify.sh | 4 +- 18 files changed, 209 insertions(+), 9 deletions(-) create mode 100644 examples/integration_test/test_experiment_folder.zip create mode 100644 examples/integration_test/test_experiment_folder/ExDTemplateHusky.exc create mode 100644 examples/integration_test/test_experiment_folder/ExDTemplateHusky.ini create mode 100644 examples/integration_test/test_experiment_folder/ExDTemplateHusky.jpg create mode 100644 examples/integration_test/test_experiment_folder/ExDTemplateHusky.uis create mode 100644 examples/integration_test/test_experiment_folder/all_neurons_spike_monitor.py create mode 100644 examples/integration_test/test_experiment_folder/brainvisualizer.json create mode 100644 examples/integration_test/test_experiment_folder/grab_image.py create mode 100644 examples/integration_test/test_experiment_folder/template_husky.bibi create mode 100644 examples/integration_test/test_experiment_folder/turn_around.py create mode 100644 hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test.zip create mode 100644 hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_experiment_folder/empty_file.txt diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index 962df51..54ea51d 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -29,7 +29,7 @@ pipelines: - cp -af $HBP/user-scripts/config_files/platform_venv/* $VIRTUAL_ENV_PATH/lib/python2.7/site-packages/ # Build - - export IGNORE_LINT='platform_venv|config_files' + - export IGNORE_LINT='platform_venv|config_files|examples/integration_test/test_experiment_folder' - make verify_base || { if [ -f pylint.txt ]; then echo "----------"; echo "PYLINT.TXT"; echo "----------";cat pylint.txt; fi; if [ -f pep8.txt ]; then echo "----------"; echo "PEP8.TXT"; echo "----------";cat pep8.txt; fi; exit 1; } # Coverage check diff --git a/examples/integration_test/it.py b/examples/integration_test/it.py index b544d7c..acdac7b 100644 --- a/examples/integration_test/it.py +++ b/examples/integration_test/it.py @@ -39,12 +39,12 @@ try: except ImportError: print - print 'Failed to import the VirtualCoach or access packages in the platform_venv! Aborting.' + print('Failed to import the VirtualCoach or access packages in the platform_venv! Aborting.') print - print 'Please make sure you have:' + print('Please make sure you have:') print - print '\t1. run "make devinstall" in the VirtualCoach repo' - print '\t2. use "cle-virtual-coach it.py" to run this script' + print('\t1. run "make devinstall" in the VirtualCoach repo') + print('\t2. use "cle-virtual-coach it.py" to run this script') print sys.exit(-1) @@ -110,7 +110,7 @@ def run(oidc_username, storage_username): # running array of test case results, unfortunately we have to hardcode the number of # test cases because the indeterminate progress bar is not helpful for the tester - NUM_TEST_CASES = 28 + NUM_TEST_CASES = 30 results = TestCases(NUM_TEST_CASES) try: @@ -174,6 +174,32 @@ def run(oidc_username, storage_username): raise TestCaseError('Deleting a cloned Experiment failed') results.done(True) + ## + ## Import an Experiment Folder + ## + + results.start('Importing an experiment folder') + response = vc.import_experiment('test_experiment_folder') + new_experiment_id = json.loads(response.text)['destFolderName'] + if new_experiment_id not in vc._VirtualCoach__get_experiment_list(cloned=True): + raise TestCaseError('Importing an experiment folder failed') + else: + vc.delete_cloned_experiment(new_experiment_id) + results.done(True) + + ## + ## Import an Experiment Zipped Folder + ## + + results.start('Importing a zipped experiment folder') + response = vc.import_experiment('test_experiment_folder.zip') + new_experiment_id = json.loads(response.text)['destFolderName'] + if new_experiment_id not in vc._VirtualCoach__get_experiment_list(cloned=True): + raise TestCaseError('Importing an experiment folder failed') + else: + vc.delete_cloned_experiment(new_experiment_id) + results.done(True) + ## ## Experiment Launch and Simulation State Interaction ## diff --git a/examples/integration_test/test_experiment_folder.zip b/examples/integration_test/test_experiment_folder.zip new file mode 100644 index 0000000000000000000000000000000000000000..ffb8e92506759a282c0ad578cc09427da0d7c6ec GIT binary patch literal 26769 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 JYTT!QcmS(8_D=u+ literal 0 HcmV?d00001 diff --git a/examples/integration_test/test_experiment_folder/ExDTemplateHusky.exc b/examples/integration_test/test_experiment_folder/ExDTemplateHusky.exc new file mode 100644 index 0000000..3701f06 --- /dev/null +++ b/examples/integration_test/test_experiment_folder/ExDTemplateHusky.exc @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<ExD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://schemas.humanbrainproject.eu/SP10/2014/ExDConfig" + xsi:schemaLocation="http://schemas.humanbrainproject.eu/SP10/2014/ExDConfig ../ExDConfFile.xsd"> + <name>Template Husky in empty environment</name> + <thumbnail>ExDTemplateHusky.jpg</thumbnail> + <description>This experiment loads the Husky robot in an empty world, with an idle brain and basic transfer functions. You are free to edit it.</description> + <tags>template husky robotics empty</tags> + <timeout>840</timeout> + <configuration type="3d-settings" src="ExDTemplateHusky.ini"/> + <configuration type="brainvisualizer" src="brainvisualizer.json"/> + <configuration type="user-interaction-settings" src="ExDTemplateHusky.uis"/> + <maturity>production</maturity> + <environmentModel src="empty_world/empty_world.sdf"> + <robotPose robotId="husky" x="0.0" y="0.0" z="0.5" roll="0.0" pitch="-0.0" yaw="0.0"/> + </environmentModel> + <bibiConf src="template_husky.bibi"/> + <cameraPose> + <cameraPosition x="4.5" y="0" z="1.8"/> + <cameraLookAt x="0" y="0" z="0.6"/> + </cameraPose> +</ExD> diff --git a/examples/integration_test/test_experiment_folder/ExDTemplateHusky.ini b/examples/integration_test/test_experiment_folder/ExDTemplateHusky.ini new file mode 100644 index 0000000..0091df9 --- /dev/null +++ b/examples/integration_test/test_experiment_folder/ExDTemplateHusky.ini @@ -0,0 +1 @@ +{"dynamicEnvMap":true,"shadows":true,"antiAliasing":true,"ssao":false,"ssaoDisplay":false,"ssaoClamp":"0.94","ssaoLumInfluence":"1","rgbCurve":{"red":[[0,0],[0.410400390625,0.4481201171875],[0.761962890625,0.7957763671875],[1,1]],"green":[[0,0],[0.261962890625,0.2801513671875],[0.718994140625,0.7371826171875],[1,1]],"blue":[[0,0],[0.265869140625,0.2606201171875],[0.840087890625,0.7645263671875],[1,1]]},"levelsInBlack":"0.09","levelsInGamma":0.52,"levelsInWhite":"0.8","levelsOutBlack":0,"levelsOutWhite":1,"skyBox":"softgradient","sun":"","bloom":false,"bloomStrength":"0.83","bloomRadius":"0.29","bloomThreshold":"0.91","fog":true,"fogDensity":"0.02","fogColor":"#97a2af","pbrMaterial":true,"shadowSettings":[{"lightName":"sun","mapSize":4096,"cameraBottom":-10,"cameraLeft":-10,"cameraRight":10,"cameraTop":25,"bias":0.0003,"radius":1.2}]} \ No newline at end of file diff --git a/examples/integration_test/test_experiment_folder/ExDTemplateHusky.jpg b/examples/integration_test/test_experiment_folder/ExDTemplateHusky.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9838a4aa4f1e13bd6abcbcdf9eb72de33979104a GIT binary patch literal 22424 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 IV*Y;<0K!XyB>(^b literal 0 HcmV?d00001 diff --git a/examples/integration_test/test_experiment_folder/ExDTemplateHusky.uis b/examples/integration_test/test_experiment_folder/ExDTemplateHusky.uis new file mode 100644 index 0000000..cca085f --- /dev/null +++ b/examples/integration_test/test_experiment_folder/ExDTemplateHusky.uis @@ -0,0 +1,9 @@ +{ + "camera": { + "defaultMode": "free-camera", + "sensitivity": { + "translation": 1.0, + "rotation": 1.0 + } + } +} diff --git a/examples/integration_test/test_experiment_folder/all_neurons_spike_monitor.py b/examples/integration_test/test_experiment_folder/all_neurons_spike_monitor.py new file mode 100644 index 0000000..34a270b --- /dev/null +++ b/examples/integration_test/test_experiment_folder/all_neurons_spike_monitor.py @@ -0,0 +1,12 @@ +# Imported Python Transfer Function +# +import hbp_nrp_cle.tf_framework as nrp +# This specifies that the neurons 0 to 2 of the circuit population +# should be monitored. You can see them in the spike train widget +@nrp.NeuronMonitor(nrp.brain.record, nrp.spike_recorder) +def all_neurons_spike_monitor(t): + # Uncomment to log into the 'log-console' visible in the simulation + # clientLogger.info("Time: ", t) + return True +# + diff --git a/examples/integration_test/test_experiment_folder/brainvisualizer.json b/examples/integration_test/test_experiment_folder/brainvisualizer.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/examples/integration_test/test_experiment_folder/brainvisualizer.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/examples/integration_test/test_experiment_folder/grab_image.py b/examples/integration_test/test_experiment_folder/grab_image.py new file mode 100644 index 0000000..3209ff7 --- /dev/null +++ b/examples/integration_test/test_experiment_folder/grab_image.py @@ -0,0 +1,12 @@ +# Imported Python Transfer Function +# +import sensor_msgs.msg +@nrp.MapRobotSubscriber("camera", Topic('/husky/husky/camera', sensor_msgs.msg.Image)) +@nrp.MapSpikeSource("input_neuron", nrp.brain.neurons[0], nrp.poisson) +@nrp.Robot2Neuron() +# Example TF: get image and fire at constant rate. You could do something with the image here and fire accordingly. +def grab_image(t, camera, input_neuron): + image = camera.value + input_neuron.rate = 10 +# + diff --git a/examples/integration_test/test_experiment_folder/template_husky.bibi b/examples/integration_test/test_experiment_folder/template_husky.bibi new file mode 100644 index 0000000..a7452ca --- /dev/null +++ b/examples/integration_test/test_experiment_folder/template_husky.bibi @@ -0,0 +1,12 @@ +<?xml version="1.0" ?> +<ns1:bibi xmlns:ns1="http://schemas.humanbrainproject.eu/SP10/2014/BIBI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <ns1:brainModel> + <ns1:file>brain_model/idle_brain.py</ns1:file> + <ns1:populations from="0" population="neurons" to="2" xsi:type="ns1:Range"/> + <ns1:populations from="0" population="record" to="2" xsi:type="ns1:Range"/> + </ns1:brainModel> + <ns1:bodyModel robotId="husky">husky_model/model.sdf</ns1:bodyModel> + <ns1:transferFunction src="all_neurons_spike_monitor.py" xsi:type="ns1:PythonTransferFunction"/> + <ns1:transferFunction src="turn_around.py" xsi:type="ns1:PythonTransferFunction"/> + <ns1:transferFunction src="grab_image.py" xsi:type="ns1:PythonTransferFunction"/> +</ns1:bibi> diff --git a/examples/integration_test/test_experiment_folder/turn_around.py b/examples/integration_test/test_experiment_folder/turn_around.py new file mode 100644 index 0000000..ba5da46 --- /dev/null +++ b/examples/integration_test/test_experiment_folder/turn_around.py @@ -0,0 +1,14 @@ +# Imported Python Transfer Function +# +import hbp_nrp_cle.tf_framework as nrp +from hbp_nrp_cle.robotsim.RobotInterface import Topic +import geometry_msgs.msg +@nrp.MapSpikeSink("output_neuron", nrp.brain.neurons[1], nrp.leaky_integrator_alpha) +@nrp.Neuron2Robot(Topic('/husky/husky/cmd_vel', geometry_msgs.msg.Twist)) +# Example TF: get output neuron voltage and output constant on robot actuator. You could do something with the voltage here and command the robot accordingly. +def turn_around(t, output_neuron): + voltage=output_neuron.voltage + return geometry_msgs.msg.Twist(linear=geometry_msgs.msg.Vector3(0,0,0), + angular=geometry_msgs.msg.Vector3(0,0,5)) +# + diff --git a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/config.py b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/config.py index 53d8425..118d9a7 100644 --- a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/config.py +++ b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/config.py @@ -86,7 +86,7 @@ class Config(dict): self.__validate('proxy-services', ['experiment-list', 'available-servers', 'server-info', 'experiment-clone', 'experiment-delete', 'storage-authentication', 'storage-experiment-list', - 'csv-files', 'experiment-file']) + 'csv-files', 'experiment-file', 'experiment-import']) self.__validate('simulation-services', ['create', 'state', 'reset']) self.__validate('simulation-scripts', ['state-machine', 'transfer-function', 'brain', 'sdf-world']) diff --git a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test.zip b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test.zip new file mode 100644 index 0000000..e69de29 diff --git a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_experiment_folder/empty_file.txt b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_experiment_folder/empty_file.txt new file mode 100644 index 0000000..e69de29 diff --git a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_virtual_coach.py b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_virtual_coach.py index 77741b6..5a98e3a 100644 --- a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_virtual_coach.py +++ b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/tests/test_virtual_coach.py @@ -39,6 +39,7 @@ import copy from dateutil import parser import json from StringIO import StringIO +import os class TestVirtualCoach(unittest.TestCase): @@ -58,6 +59,7 @@ class TestVirtualCoach(unittest.TestCase): return realimport(name, globals, locals, fromlist, level) builtins.__import__ = rospy_import_fail + self._tests_path = os.path.dirname(os.path.realpath(__file__)) self._vc = VirtualCoach(environment='local', storage_username='nrpuser') @@ -626,3 +628,18 @@ mock-server-5 request.return_value = Request() self._vc.set_experiment_file('exp_id', 'file_name', 'file_content') + @patch('requests.post') + def test_import_experiment_zip(self, mock_request): + mock_request.side_effect = [MagicMock(status_code=requests.codes.ok)] + self.assertRaises(Exception, self._vc.import_experiment, 'imaginary_file.zip') + path = os.path.join(self._tests_path, 'test.zip') + response = self._vc.import_experiment(path) + self.assertEqual(response.status_code, requests.codes.ok) + + @patch('requests.post') + def test_import_experiment_folder(self, mock_request): + mock_request.side_effect = [MagicMock(status_code=requests.codes.ok)] + self.assertRaises(Exception, self._vc.import_experiment, 'imaginary_experiment_folder') + path = os.path.join(self._tests_path, 'test_experiment_folder') + response = self._vc.import_experiment(path) + self.assertEqual(response.status_code, requests.codes.ok) diff --git a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/virtual_coach.py b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/virtual_coach.py index 3edcd02..b5a5e89 100644 --- a/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/virtual_coach.py +++ b/hbp_nrp_virtual_coach/hbp_nrp_virtual_coach/virtual_coach.py @@ -38,6 +38,9 @@ import requests import logging import getpass import httplib +import os +import zipfile +import tempfile from texttable import Texttable from copy import copy @@ -603,3 +606,74 @@ class VirtualCoach(object): % (response.status_code, response)) return response.content + + @staticmethod + def __zip_directory(dirpath, zip_filehandle): + """ + Internal helper function + It zips the target directory + + :param dirpath: Path to the experiment folder to be zipped + :param zip_filehandle: Handle of the zip file to be populated + """ + dirpath = os.path.abspath(dirpath) + dirname = os.path.dirname(dirpath) + basename = os.path.basename(dirpath) + os.chdir(dirname) + for root, _, files in os.walk(basename): + for f in files: + zip_filehandle.write(os.path.join(root, f)) + + @staticmethod + def __get_directory_content(dirpath): + """ + Internal helper function + It zips the target folder and returns its content + + :param dirpath: path to the experiment folder to be zipped + """ + temp = tempfile.mktemp() + zip_file = zipfile.ZipFile(temp, 'w', zipfile.ZIP_DEFLATED) + try: + VirtualCoach.__zip_directory(dirpath, zip_file) + except Exception as e: + logger.error('The folder %s could not be zipped', dirpath) + raise e + zip_file.close() + content = open(temp, 'r').read() + os.remove(temp) + return content + + def import_experiment(self, path): + """ + Imports an experiment folder, possibly a zipped folder, into user storage + + :param path: path to the experiment folder or to the zip file to be imported + :type path: str + """ + if not isinstance(path, str): + raise TypeError('The provided argument is not a string.') + if not os.path.isfile(path) and not os.path.isdir(path): + raise ValueError('The file or folder named %(path)s does not exist.' % {'path': path}) + + url = self.__config['proxy-services']['experiment-import'] + file_headers = copy(self.__http_headers) + file_headers['Content-Type'] = 'application/octet-stream' + content = None + if os.path.isdir(path): + # Handles an experiment folder + content = VirtualCoach.__get_directory_content(path) + else: + # Handles a zip file + try: + content = open(path, 'r').read() + except Exception as e: + logger.error('The file %s could not be open', path) + raise e + + response = requests.post(url, data=content, headers=file_headers) + # pylint: disable=no-member + if response.status_code != requests.codes.ok: + raise Exception('Error when importing experiment: %d. Error: %s' + % (response.status_code, response)) + return response diff --git a/verify.sh b/verify.sh index 58373b3..d09f05f 100755 --- a/verify.sh +++ b/verify.sh @@ -1,8 +1,8 @@ #!/bin/bash # This script is designed for local usage. -# Ignore generated files. -export IGNORE_LINT="platform_venv" +# Ignore generated files and files provided for testing. +export IGNORE_LINT="platform_venv|config_files|examples/integration_test/test_experiment_folder" export VIRTUAL_ENV=$NRP_VIRTUAL_ENV # This script only runs static code analysis, the tests can be run separately using run_tests.sh -- GitLab