Index: src/backends/CMakeLists.txt =================================================================== --- src/backends/CMakeLists.txt +++ src/backends/CMakeLists.txt @@ -48,34 +48,14 @@ add_subdirectory(qalculate) endif(QALCULATE_FOUND) -set_package_properties(PythonLibs PROPERTIES DESCRIPTION "A powerful dynamic programming language." - URL "https://www.python.org/" - TYPE OPTIONAL - PURPOSE "Backend to use Python 2 with Cantor.") - -# If PythonInterp has been found (which it is indirectly by KF5I18n), -# find_package(PythonLibs) will prefer that version over whatever -# version information you pass the find_package call. Set a special -# variable to override that: -set(Python_ADDITIONAL_VERSIONS 2.7) -find_package(PythonLibs 2.7) - set_package_properties(PythonLibs3 PROPERTIES DESCRIPTION "A powerful dynamic programming language." URL "https://www.python.org/" TYPE OPTIONAL - PURPOSE "Backend to use Python 3 with Cantor.") + PURPOSE "Backend to use Python with Cantor.") find_package(PythonLibs3) - -if(PYTHONLIBS_FOUND OR PYTHONLIBS3_FOUND) - add_subdirectory(python) -endif(PYTHONLIBS_FOUND OR PYTHONLIBS3_FOUND) - -if(PYTHONLIBS_FOUND) - add_subdirectory(python2) -endif(PYTHONLIBS_FOUND) - if(PYTHONLIBS3_FOUND) + add_subdirectory(python) add_subdirectory(python3) endif(PYTHONLIBS3_FOUND) Index: src/backends/python2/CMakeLists.txt =================================================================== --- src/backends/python2/CMakeLists.txt +++ /dev/null @@ -1,36 +0,0 @@ -set( Python2Backend_SRCS - python2backend.cpp - python2session.cpp -) - -set(Python2Server_SRCS - ../python/pythonservermain.cpp - ../python/pythonserver.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) - -add_executable(cantor_python2server ${Python2Server_SRCS}) -set_target_properties(cantor_python2server PROPERTIES INSTALL_RPATH_USE_LINK_PATH false) -target_link_libraries(cantor_python2server ${PYTHON_LIBRARIES}) - -if(BUILD_TESTING) - 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}) - -install(TARGETS cantor_python2server ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) Index: src/backends/python2/cantor_python2.knsrc =================================================================== --- src/backends/python2/cantor_python2.knsrc +++ /dev/null @@ -1,7 +0,0 @@ -[KNewStuff3] -ProvidersUrl=https://autoconfig.kde.org/ocs/providers.xml -Categories=Cantor (Maxima),Cantor (Sage),Cantor (KAlgebra),Cantor (Qalculate),Cantor (Python 2),Cantor (Python 3),Cantor (Scilab),Cantor (Octave),Cantor (R),Cantor (Lua) -UploadCategories=Cantor (Python2) -TargetDir=cantor/examples -Uncompress=never -CustomName=true Index: src/backends/python2/python2backend.h =================================================================== --- src/backends/python2/python2backend.h +++ /dev/null @@ -1,43 +0,0 @@ - /* - 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) 2014, 2015 Minh Ngo - */ - -#ifndef _PYTHON2BACKEND_H -#define _PYTHON2BACKEND_H - -#include "../python/pythonbackend.h" - -class Python2Backend : public PythonBackend -{ - Q_OBJECT - public: - explicit Python2Backend(QObject* parent = nullptr, const QList args = QList()); - - Cantor::Session* createSession() override; - - QString id() const override; - QString version() const override; - Cantor::Backend::Capabilities capabilities() const override; - QUrl helpUrl() const override; - QString description() const override; - bool requirementsFullfilled(QString* const reason = nullptr) const override; - KConfigSkeleton* config() const override; -}; - -#endif Index: src/backends/python2/python2backend.cpp =================================================================== --- src/backends/python2/python2backend.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - 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) 2014, 2015 Minh Ngo - Copyright (C) 2019 Alexander Semke - */ - -#include "python2backend.h" -#include "python2session.h" -#include "settings.h" - -#include - -Python2Backend::Python2Backend(QObject* parent, const QList args) - : PythonBackend(parent, args) -{ - // Because the plugin may not have been loaded with - // ExportExternalSymbols, we load the python symbols again - // to make sure that python modules such as numpy see them - // (see bug #330032) - QLibrary pythonLib(QLatin1String("python2.7")); - pythonLib.setLoadHints(QLibrary::ExportExternalSymbolsHint); - pythonLib.load(); -} - -Cantor::Session* Python2Backend::createSession() -{ - return new Python2Session(this); -} - -QString Python2Backend::id() const -{ - return QLatin1String("python2"); -} - -QString Python2Backend::version() const -{ - return QLatin1String("2.7"); -} - -Cantor::Backend::Capabilities Python2Backend::capabilities() const -{ - Backend::Capabilities cap = - Cantor::Backend::SyntaxHighlighting | - Cantor::Backend::Completion | - Cantor::Backend::SyntaxHelp; - - if(PythonSettings::variableManagement()) - cap |= Cantor::Backend::VariableManagement; - - return cap; -} - -QUrl Python2Backend::helpUrl() const -{ - const QUrl& localDoc = PythonSettings::self()->localDoc(); - if (!localDoc.isEmpty()) - return localDoc; - else - return QUrl(i18nc("The url to the documentation Python 2", "https://docs.python.org/2/")); -} - -QString Python2Backend::description() const -{ - return i18n("Python is a remarkably powerful dynamic programming language that is used in a wide variety of application domains. " \ - "There are several Python packages to scientific programming. " \ - "This backend supports Python 2."); -} - -KConfigSkeleton* Python2Backend::config() const -{ - return PythonSettings::self(); -} - -bool Python2Backend::requirementsFullfilled(QString* const reason) const -{ - const QString& path = PythonSettings::pythonServerPath().toLocalFile(); - return Cantor::Backend::checkExecutable(QLatin1String("Cantor Python2 Server"), path, reason); -} - -K_PLUGIN_FACTORY_WITH_JSON(python2backend, "python2backend.json", registerPlugin();) -#include "python2backend.moc" Index: src/backends/python2/python2backend.json =================================================================== --- src/backends/python2/python2backend.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "KPlugin": { - "Dependencies": [], - "Description": "Backend for Python 2 Scientific Programming", - "Description[ca@valencia]": "Dorsal per a la programació científica Python2", - "Description[ca]": "Dorsal per a la programació científica Python2", - "Description[cs]": "Podpůrná vrstva pro vědecké programovací v Python 2", - "Description[de]": "Modul für die wissenschaftliche Programmierumgebung Python 2", - "Description[el]": "Σύστημα υποστήριξης για το Python 2 Scientific Programming", - "Description[en_GB]": "Backend for Python 2 Scientific Programming", - "Description[es]": "Motor para programación científica en Python 2", - "Description[et]": "Python 2 teadusliku programmeerimise taustaprogramm", - "Description[fi]": "Python 2 -pohjaisen tieteellisen ohjelmointiympäristön taustajärjestelmä", - "Description[fr]": "Moteur pour la programmation scientifique Python 2", - "Description[gl]": "Infraestrutura para o programación científica con Python 2.", - "Description[it]": "Backend per l'ambiente scientifico di programmazione Python 2", - "Description[nl]": "Backend voor wetenschappelijke programmeeromgeving Python 2", - "Description[nn]": "Motor for Python 2 «Scientific Programming»", - "Description[pl]": "Silnika dla naukowego środowiska programistycznego Python 2", - "Description[pt]": "Infra-Estrutura de Programação Científica com Python 2", - "Description[pt_BR]": "Infraestrutura de programação científica Python 2", - "Description[ru]": "Поддержка языка Python 2 и инженерных и научных расчётов на нём", - "Description[sk]": "Backend pre vedecké programovanie Python 2", - "Description[sl]": "Zaledje za znanstveno programersko okolje Python 2", - "Description[sv]": "Bakgrundsprogram för Python 2 vetenskaplig programmeringsmiljö", - "Description[tr]": "Python 2 Bilimsel Programlama için arka uç", - "Description[uk]": "Модуль наукового програмування мовою Python 2", - "Description[x-test]": "xxBackend for Python 2 Scientific Programmingxx", - "Description[zh_CN]": "Python 2 科学编程环境的后端", - "Description[zh_TW]": "Python 2 科學程式環境的後端介面", - "Icon": "pythonbackend", - "Id": "Python 2", - "License": "GPL", - "Name": "Python 2", - "Name[ca@valencia]": "Python 2", - "Name[ca]": "Python 2", - "Name[cs]": "Python 2", - "Name[da]": "Python 2", - "Name[de]": "Python 2", - "Name[el]": "Python 2", - "Name[en_GB]": "Python 2", - "Name[es]": "Python 2", - "Name[et]": "Python 2", - "Name[fi]": "Python 2", - "Name[fr]": "Python 2", - "Name[gl]": "Python 2", - "Name[it]": "Python 2", - "Name[nl]": "Python 2", - "Name[nn]": "Python 2", - "Name[pl]": "Python 2", - "Name[pt]": "Python 2", - "Name[pt_BR]": "Python 2", - "Name[ru]": "Python 2", - "Name[sk]": "Python 2", - "Name[sl]": "Python 2", - "Name[sv]": "Python 2", - "Name[tr]": "Python 2", - "Name[uk]": "Python 2", - "Name[x-test]": "xxPython 2xx", - "Name[zh_CN]": "Python 2", - "Name[zh_TW]": "Python 2", - "ServiceTypes": [ - "Cantor/Backend" - ], - "Website": "https://python.org/" - } -} Index: src/backends/python2/python2backend.kcfg =================================================================== --- src/backends/python2/python2backend.kcfg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - QUrl::fromLocalFile(QStandardPaths::findExecutable(QLatin1String("cantor_python2server"))) - - - - - - - false - - - - true - - - - - - Index: src/backends/python2/python2session.h =================================================================== --- src/backends/python2/python2session.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - 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 - */ - -#ifndef _PYTHON2SESSION_H -#define _PYTHON2SESSION_H - -#include "../python/pythonsession.h" - -class Python2Session : public PythonSession -{ - public: - explicit Python2Session(Cantor::Backend* backend); - - bool integratePlots() const override; - QStringList autorunScripts() const override; - bool variableManagement() const override; -}; - -#endif Index: src/backends/python2/python2session.cpp =================================================================== --- src/backends/python2/python2session.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - 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 "python2session.h" -#include "settings.h" -#include "../python/pythonexpression.h" -#include "../python/pythonkeywords.h" - -#include -#include -#include -#include - -#include - -Python2Session::Python2Session(Cantor::Backend* backend) - : PythonSession(backend, 2, PythonSettings::pythonServerPath()) -{ -} - -bool Python2Session::integratePlots() const -{ - return PythonSettings::integratePlots(); -} - -QStringList Python2Session::autorunScripts() const -{ - return PythonSettings::autorunScripts(); -} - -bool Python2Session::variableManagement() const -{ - return PythonSettings::variableManagement(); -} Index: src/backends/python2/settings.kcfgc =================================================================== --- src/backends/python2/settings.kcfgc +++ /dev/null @@ -1,3 +0,0 @@ -File=python2backend.kcfg -ClassName=PythonSettings -Singleton=true Index: src/backends/python2/testpython2.h =================================================================== --- src/backends/python2/testpython2.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - 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 - */ - -#ifndef _TESTPYTHON2_H -#define _TESTPYTHON2_H - -#include "backendtest.h" - - -class TestPython2 : public BackendTest -{ - Q_OBJECT - private Q_SLOTS: - void testCodeWithComments(); - void testSimpleCode(); - void testMultilineCode(); - void testCommandQueue(); - - void testSimplePlot(); - - void testImportStatement(); - void testInvalidSyntax(); - - void testSimpleExpressionWithComment(); - void testCommentExpression(); - void testMultilineCommandWithComment(); - - void testVariablesCreatingFromCode(); - void testVariableCleanupAfterRestart(); - void testDictVariable(); - - void testCompletion(); - void testInterrupt(); - - void testWarning(); - private: - QString backendName() override; -}; - -#endif /* _TESTPYTHON2_H */ Index: src/backends/python2/testpython2.cpp =================================================================== --- src/backends/python2/testpython2.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/* - 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::testImportStatement() -{ - Cantor::Expression* e = evalExp(QLatin1String("import sys")); - - 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()); - QVERIFY(e->result()->data().toString() == QLatin1String("3")); - } - - { - Cantor::Expression* e = evalExp(QLatin1String(" #comment\n1+2")); - - QVERIFY(e != nullptr); - QVERIFY(e->result()); - 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() -{ - if (!PythonSettings::variableManagement()) - QSKIP("This test needs enabled variable management in Python2 settings", SkipSingle); - - 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() -{ - if (!PythonSettings::variableManagement()) - QSKIP("This test needs enabled variable management in Python2 settings", SkipSingle); - - 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); - if(session()->status()==Cantor::Session::Running) - waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); - 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); - - if(session()->status()==Cantor::Session::Running) - waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); - //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()" - )); - - QVERIFY(e != nullptr); - if (e->result() == nullptr) - waitForSignal(e, SIGNAL(gotResult())); - 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()); - 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()); - QVERIFY(e->result()->data().toString() == QLatin1String("4\n35")); -} - -void TestPython2::testCompletion() -{ - if(session()->status()==Cantor::Session::Running) - waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); - - 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"))); -} - -void TestPython2::testInterrupt() -{ - Cantor::Expression* e1=session()->evaluateExpression(QLatin1String("import time; time.sleep(45)")); - Cantor::Expression* e2=session()->evaluateExpression(QLatin1String("2")); - - // Wait, because server need time to read input - QTest::qWait(100); - - QCOMPARE(e1->status(), Cantor::Expression::Computing); - QCOMPARE(e2->status(), Cantor::Expression::Queued); - - while(session()->status() != Cantor::Session::Running) - waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); - - session()->interrupt(); - - while(session()->status() != Cantor::Session::Done) - waitForSignal(session(), SIGNAL(statusChanged(Cantor::Session::Status))); - - QCOMPARE(e1->status(), Cantor::Expression::Interrupted); - QCOMPARE(e2->status(), Cantor::Expression::Interrupted); - - Cantor::Expression* e = evalExp(QLatin1String("2+2")); - - QVERIFY(e != nullptr); - QVERIFY(e->result()); - QCOMPARE(e->result()->data().toString(), QLatin1String("4")); -} - -void TestPython2::testWarning() -{ - Cantor::Expression* e = evalExp(QLatin1String("import warnings; warnings.warn('Test')")); - - QVERIFY(e != nullptr); - QCOMPARE(e->status(), Cantor::Expression::Status::Done); - QCOMPARE(e->results().size(), 1); -} - -QTEST_MAIN(TestPython2) - Index: src/backends/python3/python3backend.cpp =================================================================== --- src/backends/python3/python3backend.cpp +++ src/backends/python3/python3backend.cpp @@ -67,14 +67,13 @@ if (!localDoc.isEmpty()) return localDoc; else - return QUrl(i18nc("The url to the documentation Python 3", "https://docs.python.org/3/")); + return QUrl(i18nc("The url to the documentation Python", "https://docs.python.org/3/")); } QString Python3Backend::description() const { return i18n("Python is a remarkably powerful dynamic programming language that is used in a wide variety of application domains. " \ - "There are several Python packages to scientific programming. " \ - "This backend supports Python 3."); + "There are several Python packages to scientific programming."); } KConfigSkeleton* Python3Backend::config() const Index: src/backends/python3/python3backend.json =================================================================== --- src/backends/python3/python3backend.json +++ src/backends/python3/python3backend.json @@ -1,64 +1,64 @@ { "KPlugin": { "Dependencies": [], - "Description": "Backend for Python 3 Scientific Programming", - "Description[ca@valencia]": "Dorsal per a la programació científica Python 3", - "Description[ca]": "Dorsal per a la programació científica Python 3", - "Description[cs]": "Podpůrná vrstva pro vědecké programovací v Python 3", - "Description[de]": "Modul für die wissenschaftliche Programmierumgebung Python 3", - "Description[el]": "Σύστημα υποστήριξης για το Python 3 Scientific Programming", - "Description[en_GB]": "Backend for Python 3 Scientific Programming", - "Description[es]": "Motor para programación científica en Python 3", - "Description[et]": "Python 3 teadusliku programmeerimise taustaprogramm", - "Description[fi]": "Python 3 -pohjaisen tieteellisen ohjelmointiympäristön taustajärjestelmä", - "Description[fr]": "Moteur pour la programmation scientifique Python 3", - "Description[gl]": "Infraestrutura para o programación científica con Python 3.", - "Description[it]": "Backend per l'ambiente scientifico di programmazione Python 3", - "Description[nl]": "Backend voor wetenschappelijke programmeeromgeving Python 3", - "Description[nn]": "Motor for Python 3 «Scientific Programming»", - "Description[pl]": "Silnika dla naukowego środowiska programistycznego Python 3", - "Description[pt]": "Infra-Estrutura de Programação Científica com Python 3", - "Description[pt_BR]": "Infraestrutura de programação científica Python 3", - "Description[ru]": "Поддержка языка Python 3 и инженерных и научных расчётов на нём", - "Description[sk]": "Backend pre vedecké programovanie Python 3", - "Description[sl]": "Zaledje za znanstveno programersko okolje Python 3", - "Description[sv]": "Bakgrundsprogram för Python 3 vetenskaplig programmeringsmiljö", - "Description[tr]": "Python 3 Bilimsel Programlama için arka uç", - "Description[uk]": "Модуль наукового програмування мовою Python 3", - "Description[x-test]": "xxBackend for Python 3 Scientific Programmingxx", - "Description[zh_CN]": "Python 3 科学编程环境的后端", - "Description[zh_TW]": "Python 3 科學程式環境的後端介面", + "Description": "Backend for Python Scientific Programming", + "Description[ca@valencia]": "Dorsal per a la programació científica Python", + "Description[ca]": "Dorsal per a la programació científica Python", + "Description[cs]": "Podpůrná vrstva pro vědecké programovací v Python", + "Description[de]": "Modul für die wissenschaftliche Programmierumgebung Python", + "Description[el]": "Σύστημα υποστήριξης για το Python Scientific Programming", + "Description[en_GB]": "Backend for Python Scientific Programming", + "Description[es]": "Motor para programación científica en Python", + "Description[et]": "Python teadusliku programmeerimise taustaprogramm", + "Description[fi]": "Python -pohjaisen tieteellisen ohjelmointiympäristön taustajärjestelmä", + "Description[fr]": "Moteur pour la programmation scientifique Python", + "Description[gl]": "Infraestrutura para o programación científica con Python.", + "Description[it]": "Backend per l'ambiente scientifico di programmazione Python", + "Description[nl]": "Backend voor wetenschappelijke programmeeromgeving Python", + "Description[nn]": "Motor for Python «Scientific Programming»", + "Description[pl]": "Silnika dla naukowego środowiska programistycznego Python", + "Description[pt]": "Infra-Estrutura de Programação Científica com Python", + "Description[pt_BR]": "Infraestrutura de programação científica Python", + "Description[ru]": "Поддержка языка Python и инженерных и научных расчётов на нём", + "Description[sk]": "Backend pre vedecké programovanie Python", + "Description[sl]": "Zaledje za znanstveno programersko okolje Python", + "Description[sv]": "Bakgrundsprogram för Python vetenskaplig programmeringsmiljö", + "Description[tr]": "Python Bilimsel Programlama için arka uç", + "Description[uk]": "Модуль наукового програмування мовою Python", + "Description[x-test]": "xxBackend for Python Scientific Programmingxx", + "Description[zh_CN]": "Python 科学编程环境的后端", + "Description[zh_TW]": "Python 科學程式環境的後端介面", "Icon": "pythonbackend", - "Id": "Python 3", + "Id": "Python", "License": "GPL", - "Name": "Python 3", - "Name[ca@valencia]": "Python 3", - "Name[ca]": "Python 3", - "Name[cs]": "Python 3", - "Name[da]": "Python 3", - "Name[de]": "Python 3", - "Name[el]": "Python 3", - "Name[en_GB]": "Python 3", - "Name[es]": "Python 3", - "Name[et]": "Python 3", - "Name[fi]": "Python 3", - "Name[fr]": "Python 3", - "Name[gl]": "Python 3", - "Name[it]": "Python 3", - "Name[nl]": "Python 3", - "Name[nn]": "Python 3", - "Name[pl]": "Python 3", - "Name[pt]": "Python 3", - "Name[pt_BR]": "Python 3", - "Name[ru]": "Python 3", - "Name[sk]": "Python 3", - "Name[sl]": "Python 3", - "Name[sv]": "Python 3", - "Name[tr]": "Python 3", - "Name[uk]": "Python 3", - "Name[x-test]": "xxPython 3xx", - "Name[zh_CN]": "Python 3", - "Name[zh_TW]": "Python 3", + "Name": "Python", + "Name[ca@valencia]": "Python", + "Name[ca]": "Python", + "Name[cs]": "Python", + "Name[da]": "Python", + "Name[de]": "Python", + "Name[el]": "Python", + "Name[en_GB]": "Python", + "Name[es]": "Python", + "Name[et]": "Python", + "Name[fi]": "Python", + "Name[fr]": "Python", + "Name[gl]": "Python", + "Name[it]": "Python", + "Name[nl]": "Python", + "Name[nn]": "Python", + "Name[pl]": "Python", + "Name[pt]": "Python", + "Name[pt_BR]": "Python", + "Name[ru]": "Python", + "Name[sk]": "Python", + "Name[sl]": "Python", + "Name[sv]": "Python", + "Name[tr]": "Python", + "Name[uk]": "Python", + "Name[x-test]": "xxPythonxx", + "Name[zh_CN]": "Python", + "Name[zh_TW]": "Python", "ServiceTypes": [ "Cantor/Backend" ], Index: src/worksheet.cpp =================================================================== --- src/worksheet.cpp +++ src/worksheet.cpp @@ -1171,13 +1171,28 @@ const KArchiveFile* content = static_cast(contentEntry); QByteArray data = content->data(); - QDomDocument doc; doc.setContent(data); - QDomElement root=doc.documentElement(); + QDomElement root = doc.documentElement(); + + m_backendName = root.attribute(QLatin1String("backend")); + + //There is "Python" only now, replace "Python 3" by "Python" + if (m_backendName == QLatin1String("Python 3")) + m_backendName = QLatin1String("Python"); + + //"Python 2" in older projects not supported anymore, switch to Python (=Python3) + if (m_backendName == QLatin1String("Python 2")) + { + QApplication::restoreOverrideCursor(); + KMessageBox::information(worksheetView(), + i18n("This worksheet was created using Python2 which is not supported anymore. Python3 will be used."), + i18n("Python2 not supported anymore")); + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + m_backendName = QLatin1String("Python"); + } - m_backendName=root.attribute(QLatin1String("backend")); - Cantor::Backend* b=Cantor::Backend::getBackend(m_backendName); + auto* b = Cantor::Backend::getBackend(m_backendName); if (!b) { QApplication::restoreOverrideCursor(); @@ -1338,6 +1353,22 @@ const QJsonObject& kernalspec = metadata.value(QLatin1String("kernelspec")).toObject(); m_backendName = Cantor::JupyterUtils::getKernelName(kernalspec); + + //There is "Python" only now, replace "python3" by "Python" + if (m_backendName == QLatin1String("python3")) + m_backendName = QLatin1String("Python"); + + //"python 2" in older projects not supported anymore, switch to Python (=Python3) + if (m_backendName == QLatin1String("python2")) + { + QApplication::restoreOverrideCursor(); + KMessageBox::information(worksheetView(), + i18n("This notebook was created using Python2 which is not supported anymore. Python3 will be used."), + i18n("Python2 not supported anymore")); + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + m_backendName = QLatin1String("Python"); + } + if (kernalspec.isEmpty() || m_backendName.isEmpty()) { QApplication::restoreOverrideCursor();