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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 Lqq#Tw$FKhat2y>h 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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�(( 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 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