diff --git a/src/backends/python2/CMakeLists.txt b/src/backends/python2/CMakeLists.txt index 56371c65..adc06197 100644 --- a/src/backends/python2/CMakeLists.txt +++ b/src/backends/python2/CMakeLists.txt @@ -1,32 +1,32 @@ set( Python2Backend_SRCS python2backend.cpp python2session.cpp ) kconfig_add_kcfg_files(Python2Backend_SRCS settings.kcfgc) if(MSVC) # ssize_t is typedef'd in both kdewin and python headers, this prevents using the kdewin one add_definitions(-D_SSIZE_T_DEFINED) endif(MSVC) include_directories(${PYTHON_LIBRARIES_DIR}) include_directories(${PYTHON_INCLUDE_DIR}) add_backend(python2backend ${Python2Backend_SRCS}) target_link_libraries(cantor_python2backend ${PYTHON_LIBRARIES} cantor_pythonbackend ) if(BUILD_TESTING) - add_executable(testpython2 testpython2.cpp) + add_executable(testpython2 testpython2.cpp settings.cpp) target_link_libraries(testpython2 ${QT_QTTEST_LIBRARY} cantorlibs cantortest) add_test(NAME testpython2 COMMAND testpython2) endif() install(FILES cantor_python2.knsrc DESTINATION ${KDE_INSTALL_CONFDIR}) install(FILES python2backend.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) add_subdirectory(python2server) diff --git a/src/backends/python2/testpython2.cpp b/src/backends/python2/testpython2.cpp index 55ba4132..ede583f2 100644 --- a/src/backends/python2/testpython2.cpp +++ b/src/backends/python2/testpython2.cpp @@ -1,261 +1,266 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2013 Tuukka Verho */ #include "testpython2.h" #include "session.h" #include "backend.h" #include "expression.h" #include "result.h" #include "defaultvariablemodel.h" #include "imageresult.h" #include "completionobject.h" +#include "settings.h" + QString TestPython2::backendName() { return QLatin1String("python2"); } void TestPython2::testCommandQueue() { Cantor::Expression* e1=session()->evaluateExpression(QLatin1String("0+1")); Cantor::Expression* e2=session()->evaluateExpression(QLatin1String("1+1")); Cantor::Expression* e3=evalExp(QLatin1String("1+2")); QVERIFY(e1!=nullptr); QVERIFY(e2!=nullptr); QVERIFY(e3!=nullptr); QVERIFY(e1->result()); QVERIFY(e2->result()); QVERIFY(e3->result()); QCOMPARE(cleanOutput(e1->result()->data().toString()), QLatin1String("1")); QCOMPARE(cleanOutput(e2->result()->data().toString()), QLatin1String("2")); QCOMPARE(cleanOutput(e3->result()->data().toString()), QLatin1String("3")); } void TestPython2::testImportNumpy() { Cantor::Expression* e = evalExp(QLatin1String("import numpy")); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Done); } void TestPython2::testCodeWithComments() { { Cantor::Expression* e = evalExp(QLatin1String("#comment\n1+2")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("3")); } { Cantor::Expression* e = evalExp(QLatin1String(" #comment\n1+2")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("3")); } } void TestPython2::testSimpleCode() { Cantor::Expression* e=evalExp( QLatin1String("2+2")); QVERIFY( e!=nullptr ); QVERIFY( e->result()!=nullptr ); QCOMPARE( cleanOutput(e->result()->data().toString()), QLatin1String("4") ); } void TestPython2::testMultilineCode() { Cantor::Expression* e=evalExp(QLatin1String( "a = 2+2\n" "b = 3+3\n" "print a,b" )); QVERIFY( e!=nullptr ); QVERIFY( e->result()!=nullptr ); QCOMPARE( cleanOutput(e->result()->data().toString()), QLatin1String("4 6") ); evalExp(QLatin1String("del a; del b")); } void TestPython2::testVariablesCreatingFromCode() { QAbstractItemModel* model = session()->variableModel(); QVERIFY(model != nullptr); Cantor::Expression* e=evalExp(QLatin1String("a = 15; b = 'S';")); QVERIFY(e!=nullptr); if(session()->status()==Cantor::Session::Running) waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); QCOMPARE(2, model->rowCount()); QCOMPARE(model->index(0,0).data().toString(), QLatin1String("a")); QCOMPARE(model->index(0,1).data().toString(), QLatin1String("15")); QCOMPARE(model->index(1,0).data().toString(), QLatin1String("b")); QCOMPARE(model->index(1,1).data().toString(), QLatin1String("'S'")); evalExp(QLatin1String("del a; del b")); } void TestPython2::testVariableCleanupAfterRestart() { Cantor::DefaultVariableModel* model = session()->variableModel(); QVERIFY(model != nullptr); Cantor::Expression* e=evalExp(QLatin1String("a = 15; b = 'S';")); QVERIFY(e!=nullptr); if(session()->status()==Cantor::Session::Running) waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); QCOMPARE(2, static_cast(model)->rowCount()); session()->logout(); session()->login(); QCOMPARE(0, static_cast(model)->rowCount()); } void TestPython2::testDictVariable() { Cantor::DefaultVariableModel* model = session()->variableModel(); QVERIFY(model != nullptr); Cantor::Expression* e=evalExp(QLatin1String("d = {'value': 33}")); QVERIFY(e!=nullptr); if(session()->status()==Cantor::Session::Running) waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); QCOMPARE(1, static_cast(model)->rowCount()); QCOMPARE(model->index(0,0).data().toString(), QLatin1String("d")); QCOMPARE(model->index(0,1).data().toString(), QLatin1String("{'value': 33}")); evalExp(QLatin1String("del d")); } void TestPython2::testCommentExpression() { Cantor::Expression* e = evalExp(QLatin1String("#only comment")); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Status::Done); QCOMPARE(e->results().size(), 0); } void TestPython2::testInvalidSyntax() { Cantor::Expression* e=evalExp( QLatin1String("2+2*+.") ); QVERIFY( e!=nullptr ); QCOMPARE( e->status(), Cantor::Expression::Error ); } void TestPython2::testSimplePlot() { + if (!PythonSettings::integratePlots()) + QSKIP("This test needs enabled plots integration in Python2 settings", SkipSingle); + Cantor::Expression* e = evalExp(QLatin1String( "import matplotlib\n" "import matplotlib.pyplot as plt\n" "import numpy as np" )); QVERIFY(e != nullptr); QVERIFY(e->errorMessage().isEmpty() == true); //the variable model shouldn't have any entries after the module imports QAbstractItemModel* model = session()->variableModel(); QVERIFY(model != nullptr); QVERIFY(model->rowCount() == 0); //create data for plotting e = evalExp(QLatin1String( "t = np.arange(0.0, 2.0, 0.01)\n" "s = 1 + np.sin(2 * np.pi * t)" )); QVERIFY(e != nullptr); QVERIFY(e->errorMessage().isEmpty() == true); //the variable model should have two entries now QVERIFY(model->rowCount() == 2); //plot the data and check the results e = evalExp(QLatin1String( "plt.plot(t,s)\n" "plt.show()" )); waitForSignal(e, SIGNAL(gotResult())); QVERIFY(e != nullptr); - QVERIFY(e->errorMessage().isEmpty() == true || e->errorMessage().contains(QLatin1String("UserWarning"))); + QVERIFY(e->errorMessage().isEmpty() == true); QVERIFY(model->rowCount() == 2); //still only two variables //there must be one single image result QVERIFY(e->results().size() == 1); const Cantor::ImageResult* result = dynamic_cast(e->result()); QVERIFY(result != nullptr); evalExp(QLatin1String("del t; del s")); } void TestPython2::testSimpleExpressionWithComment() { Cantor::Expression* e = evalExp(QLatin1String("2+2 # comment")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("4")); } void TestPython2::testMultilineCommandWithComment() { Cantor::Expression* e = evalExp(QLatin1String( "print 2+2 \n" "#comment in middle \n" "print 7*5")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("4\n35")); } void TestPython2::testCompletion() { Cantor::CompletionObject* help = session()->completionFor(QLatin1String("ma"), 2); waitForSignal(help, SIGNAL(fetchingDone())); // Checks all completions for this request // This correct for Python 2.7.15 const QStringList& completions = help->completions(); qDebug() << completions; QCOMPARE(completions.size(), 2); QVERIFY(completions.contains(QLatin1String("map"))); QVERIFY(completions.contains(QLatin1String("max"))); } QTEST_MAIN(TestPython2) diff --git a/src/backends/python3/CMakeLists.txt b/src/backends/python3/CMakeLists.txt index 5136dfd0..b7f9f629 100644 --- a/src/backends/python3/CMakeLists.txt +++ b/src/backends/python3/CMakeLists.txt @@ -1,27 +1,29 @@ set(Python3Backend_SRCS python3backend.cpp python3session.cpp ) kconfig_add_kcfg_files(Python3Backend_SRCS settings.kcfgc) add_backend(python3backend ${Python3Backend_SRCS}) target_link_libraries(cantor_python3backend cantor_pythonbackend Qt5::DBus) add_subdirectory(python3server) if(BUILD_TESTING) - add_executable(testpython3 testpython3.cpp) + add_executable(testpython3 testpython3.cpp settings.cpp) add_test(NAME testpython3 COMMAND testpython3) target_link_libraries(testpython3 Qt5::Test + KF5::ConfigCore + KF5::ConfigGui cantorlibs cantortest ) endif(BUILD_TESTING) install(FILES cantor_python3.knsrc DESTINATION ${KDE_INSTALL_CONFDIR}) install(FILES python3backend.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR}) diff --git a/src/backends/python3/testpython3.cpp b/src/backends/python3/testpython3.cpp index 5599b10c..4467b910 100644 --- a/src/backends/python3/testpython3.cpp +++ b/src/backends/python3/testpython3.cpp @@ -1,270 +1,275 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. --- Copyright (C) 2015 Minh Ngo */ #include "testpython3.h" #include "session.h" #include "backend.h" #include "expression.h" #include "imageresult.h" #include "defaultvariablemodel.h" #include "completionobject.h" +#include "settings.h" + QString TestPython3::backendName() { return QLatin1String("python3"); } void TestPython3::testSimpleCommand() { Cantor::Expression* e = evalExp(QLatin1String("2+2")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("4")); } void TestPython3::testMultilineCommand() { Cantor::Expression* e = evalExp(QLatin1String("print(2+2)\nprint(7*5)")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("4\n35")); } void TestPython3::testCommandQueue() { Cantor::Expression* e1=session()->evaluateExpression(QLatin1String("0+1")); Cantor::Expression* e2=session()->evaluateExpression(QLatin1String("1+1")); Cantor::Expression* e3=evalExp(QLatin1String("1+2")); QVERIFY(e1!=nullptr); QVERIFY(e2!=nullptr); QVERIFY(e3!=nullptr); QVERIFY(e1->result()); QVERIFY(e2->result()); QVERIFY(e3->result()); QCOMPARE(cleanOutput(e1->result()->data().toString()), QLatin1String("1")); QCOMPARE(cleanOutput(e2->result()->data().toString()), QLatin1String("2")); QCOMPARE(cleanOutput(e3->result()->data().toString()), QLatin1String("3")); } void TestPython3::testCommentExpression() { Cantor::Expression* e = evalExp(QLatin1String("#only comment")); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Status::Done); QCOMPARE(e->results().size(), 0); } void TestPython3::testSimpleExpressionWithComment() { Cantor::Expression* e = evalExp(QLatin1String("2+2 # comment")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("4")); } void TestPython3::testMultilineCommandWithComment() { Cantor::Expression* e = evalExp(QLatin1String( "print(2+2) \n" "#comment in middle \n" "print(7*5)")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("4\n35")); } void TestPython3::testInvalidSyntax() { Cantor::Expression* e=evalExp( QLatin1String("2+2*+.") ); QVERIFY( e!=nullptr ); QCOMPARE( e->status(), Cantor::Expression::Error ); } void TestPython3::testCompletion() { Cantor::CompletionObject* help = session()->completionFor(QLatin1String("p"), 1); waitForSignal(help, SIGNAL(fetchingDone())); // Checks all completions for this request // This correct for Python 3.6.7 const QStringList& completions = help->completions(); qDebug() << completions; QCOMPARE(completions.size(), 4); QVERIFY(completions.contains(QLatin1String("pass"))); QVERIFY(completions.contains(QLatin1String("pow"))); QVERIFY(completions.contains(QLatin1String("print"))); QVERIFY(completions.contains(QLatin1String("property"))); } void TestPython3::testImportNumpy() { Cantor::Expression* e = evalExp(QLatin1String("import numpy")); QVERIFY(e != nullptr); QCOMPARE(e->status(), Cantor::Expression::Done); } void TestPython3::testCodeWithComments() { { Cantor::Expression* e = evalExp(QLatin1String("#comment\n1+2")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("3")); } { Cantor::Expression* e = evalExp(QLatin1String(" #comment\n1+2")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("3")); } } void TestPython3::testPython3Code() { { Cantor::Expression* e = evalExp(QLatin1String("print 1 + 2")); QVERIFY(e != nullptr); QVERIFY(!e->errorMessage().isEmpty()); } { Cantor::Expression* e = evalExp(QLatin1String("print(1 + 2)")); QVERIFY(e != nullptr); QVERIFY(e->result()->data().toString() == QLatin1String("3")); } } void TestPython3::testSimplePlot() { + if (!PythonSettings::integratePlots()) + QSKIP("This test needs enabled plots integration in Python3 settings", SkipSingle); + Cantor::Expression* e = evalExp(QLatin1String( "import matplotlib\n" "import matplotlib.pyplot as plt\n" "import numpy as np" )); QVERIFY(e != nullptr); QVERIFY(e->errorMessage().isEmpty() == true); //the variable model shouldn't have any entries after the module imports QAbstractItemModel* model = session()->variableModel(); QVERIFY(model != nullptr); QVERIFY(model->rowCount() == 0); //create data for plotting e = evalExp(QLatin1String( "t = np.arange(0.0, 2.0, 0.01)\n" "s = 1 + np.sin(2 * np.pi * t)" )); QVERIFY(e != nullptr); QVERIFY(e->errorMessage().isEmpty() == true); //the variable model should have two entries now QVERIFY(model->rowCount() == 2); //plot the data and check the results e = evalExp(QLatin1String( "plt.plot(t,s)\n" "plt.show()" )); waitForSignal(e, SIGNAL(gotResult())); QVERIFY(e != nullptr); - QVERIFY(e->errorMessage().isEmpty() == true || e->errorMessage().contains(QLatin1String("UserWarning"))); + QVERIFY(e->errorMessage().isEmpty() == true); QVERIFY(model->rowCount() == 2); //still only two variables //there must be one single image result QVERIFY(e->results().size() == 1); const Cantor::ImageResult* result = dynamic_cast(e->result()); QVERIFY(result != nullptr); evalExp(QLatin1String("del t; del s")); } void TestPython3::testVariablesCreatingFromCode() { QAbstractItemModel* model = session()->variableModel(); QVERIFY(model != nullptr); Cantor::Expression* e=evalExp(QLatin1String("a = 15; b = 'S';")); QVERIFY(e!=nullptr); if(session()->status()==Cantor::Session::Running) waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); QCOMPARE(2, model->rowCount()); QCOMPARE(model->index(0,0).data().toString(), QLatin1String("a")); QCOMPARE(model->index(0,1).data().toString(), QLatin1String("15")); QCOMPARE(model->index(1,0).data().toString(), QLatin1String("b")); QCOMPARE(model->index(1,1).data().toString(), QLatin1String("'S'")); evalExp(QLatin1String("del a; del b")); } void TestPython3::testVariableCleanupAfterRestart() { Cantor::DefaultVariableModel* model = session()->variableModel(); QVERIFY(model != nullptr); Cantor::Expression* e=evalExp(QLatin1String("a = 15; b = 'S';")); QVERIFY(e!=nullptr); if(session()->status()==Cantor::Session::Running) waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); QCOMPARE(2, static_cast(model)->rowCount()); session()->logout(); session()->login(); QCOMPARE(0, static_cast(model)->rowCount()); } void TestPython3::testDictVariable() { Cantor::DefaultVariableModel* model = session()->variableModel(); QVERIFY(model != nullptr); Cantor::Expression* e=evalExp(QLatin1String("d = {'value': 33}")); QVERIFY(e!=nullptr); if(session()->status()==Cantor::Session::Running) waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); QCOMPARE(1, static_cast(model)->rowCount()); QCOMPARE(model->index(0,0).data().toString(), QLatin1String("d")); QCOMPARE(model->index(0,1).data().toString(), QLatin1String("{'value': 33}")); evalExp(QLatin1String("del d")); } QTEST_MAIN(TestPython3)