def check_requirements(self): """ Check if Python requirements need to be installed """ req_file = self.get_path("requirements.txt") if os.path.exists(req_file): reqs_installed = requirements_installed( req_file, self.get_python_packages_path()) md5_file = self.get_python_packages_path("install_md5") md5_mismatch = False req_md5 = compute_file_md5(req_file) if os.path.exists(md5_file): with open(md5_file, 'r') as f: md5_mismatch = f.read().strip() != req_md5 else: reqs_installed = False if not reqs_installed or md5_mismatch: logger.info("Installing requirements.txt for {}".format(self)) if not os.path.exists(self.get_python_packages_path()): os.makedirs(self.get_python_packages_path(), exist_ok=True) p = subprocess.Popen([ 'python', '-m', 'pip', 'install', '-U', '-r', 'requirements.txt', '--target', self.get_python_packages_path() ], cwd=self.get_path()) p.wait() # Verify if requirements_installed(self.get_path("requirements.txt"), self.get_python_packages_path()): logger.info( "Installed requirements.txt for {}".format(self)) # Write MD5 if req_md5: with open(md5_file, 'w') as f: f.write(req_md5) else: logger.warning( "Failed to install requirements.txt for {}".format( self))
def test_core_plugins(self): client = Client() # We cannot access public files core plugins (plugin is disabled) res = client.get('/plugins/test/file.txt') self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND) # Cannot access mount point (plugin is disabled) res = client.get('/plugins/test/app_mountpoint/') self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND) # No python packages have been installed (plugin is disabled) self.assertFalse( os.path.exists(get_plugins_persistent_path("test", "site-packages"))) enable_plugin("test") # Python packages have been installed self.assertTrue( os.path.exists(get_plugins_persistent_path("test", "site-packages"))) # We can access public files core plugins (without auth) res = client.get('/plugins/test/file.txt') self.assertEqual(res.status_code, status.HTTP_200_OK) # We mounted an endpoint res = client.get('/plugins/test/app_mountpoint/') self.assertEqual(res.status_code, status.HTTP_200_OK) self.assertTemplateUsed(res, 'coreplugins/test/templates/app.html') # Form was rendered correctly self.assertContains( res, '<input type="text" name="testField" class="form-control" required id="id_testField" />', count=1, status_code=200, html=True) # It uses regex properly res = client.get('/plugins/test/app_mountpoint/a') self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND) # Querying a page should show the included CSS/JS files client.login(username='******', password='******') res = client.get('/dashboard/') self.assertEqual(res.status_code, status.HTTP_200_OK) self.assertContains( res, "<link href='/plugins/test/test.css' rel='stylesheet' type='text/css'>", html=True) self.assertContains(res, "<script src='/plugins/test/test.js'></script>", html=True) # And our menu entry self.assertContains( res, '<li><a href="/plugins/test/menu_url/"><i class="test-icon"></i> Test</a></li>', html=True) # A node_modules directory has been created as a result of npm install # because we have a package.json in the public director test_plugin = get_plugin_by_name("test") self.assertTrue( os.path.exists(test_plugin.get_path("public/node_modules"))) # This is a persistent plugin self.assertTrue(test_plugin.is_persistent()) # A webpack file and build directory have been created as a # result of the build_jsx_components directive self.assertTrue( os.path.exists(test_plugin.get_path("public/webpack.config.js"))) self.assertTrue(os.path.exists(test_plugin.get_path("public/build"))) self.assertTrue( os.path.exists(test_plugin.get_path("public/build/component.js"))) # Test task view user = User.objects.get(username="******") project = Project.objects.get(owner=user) task = Task.objects.create(project=project, name="Test") client.logout() # Cannot see the task view without logging-in res = client.get('/plugins/test/task/{}/'.format(task.id)) self.assertEqual(res.status_code, status.HTTP_404_NOT_FOUND) client.login(username='******', password='******') res = client.get('/plugins/test/task/{}/'.format(task.id)) self.assertEqual(res.status_code, status.HTTP_200_OK) self.assertContains(res, str(task.id)) # Test dynamic script res = client.get('/plugins/test/app_dynamic_script.js') self.assertEqual(res.status_code, status.HTTP_200_OK) self.assertTrue(res.content.decode('utf-8') == '') # Empty res = client.get('/plugins/test/app_dynamic_script.js?print=1') self.assertEqual(res.status_code, status.HTTP_200_OK) self.assertTrue( res.content.decode('utf-8') == "console.log('Hello WebODM');") # Empty # Check that the plugins media dirs have been created self.assertTrue(os.path.exists(get_plugins_persistent_path())) self.assertTrue( os.path.exists(get_plugins_persistent_path("test", "site-packages"))) self.assertEqual(get_plugins_persistent_path("test", "site-packages"), test_plugin.get_python_packages_path()) # Check MD5 install has been created self.assertTrue( os.path.exists( test_plugin.get_python_packages_path("install_md5"))) with open(test_plugin.get_python_packages_path("install_md5"), "r") as f: md5 = f.read().strip() self.assertTrue(len(md5) > 20) self.assertEqual( md5, compute_file_md5(test_plugin.get_path("requirements.txt"))) self.assertTrue( requirements_installed(test_plugin.get_path("requirements.txt"), test_plugin.get_python_packages_path())) # Test python imports context self.assertFalse(test_plugin.get_python_packages_path() in sys.path) with test_plugin.python_imports(): self.assertTrue(test_plugin.get_python_packages_path() in sys.path) self.assertFalse(test_plugin.get_python_packages_path() in sys.path) # Parse requirements test self.assertEqual( parse_requirements(test_plugin.get_path("requirements.txt"))[0], "pyodm") # Current plugin test self.assertEqual(test_plugin.get_current_plugin_test(), test_plugin)