Commit a0c25348 authored by Alexander Semke's avatar Alexander Semke
Browse files

The python community is sunsetting the support of python2 (https://python3statement.org/)

and we should follow these activities to drop python2 in 2020.

This patch removes python2 from Cantor. Old worksheets created with python2 will be moved
to using python3 on load - there is a info message box to the user to notify him/her about this.

Differential Revision: https://phabricator.kde.org/D27331
parent 271290d3
......@@ -48,34 +48,14 @@ if(QALCULATE_FOUND)
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)
......
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})
[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
/*
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 <minh@fedoraproject.org>
Copyright (C) 2019 Alexander Semke <alexander.semke@web.de>
*/
#include "python2backend.h"
#include "python2session.h"
#include "settings.h"
#include <KLocalizedString>
Python2Backend::Python2Backend(QObject* parent, const QList<QVariant> 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("<b>Python</b> 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<Python2Backend>();)
#include "python2backend.moc"
/*
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 <minh@fedoraproject.org>
*/
#ifndef _PYTHON2BACKEND_H
#define _PYTHON2BACKEND_H
#include "../python/pythonbackend.h"
class Python2Backend : public PythonBackend
{
Q_OBJECT
public:
explicit Python2Backend(QObject* parent = nullptr, const QList<QVariant> args = QList<QVariant>());
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
{
"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/"
}
}
<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="https://www.kde.org/standards/kcfg/1.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.kde.org/standards/kcfg/1.0
https://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
<kcfgfile name="cantorrc"/>
<group name="Python2Backend">
<entry name="pythonServerPath" type="Url">
<label>Path to Cantor python3 server executable</label>
<default code="true">QUrl::fromLocalFile(QStandardPaths::findExecutable(QLatin1String("cantor_python2server")))</default>
</entry>
<entry name="localDoc" type="Url">
<label>Url to the local Python documentation</label>
</entry>
<entry name="integratePlots" type="Bool">
<label>Integrate Plots into the Worksheet</label>
<default>false</default>
</entry>
<entry name="variableManagement" type="Bool">
<label>Enable Variable Management</label>
<default>true</default>
</entry>
<entry name="autorunScripts" type="StringList">
<label>List of scripts to autorun at the beginning of session</label>
</entry>
</group>
</kcfg>
/*
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 <minh@fedoraproject.org>
*/
#include "python2session.h"
#include "settings.h"
#include "../python/pythonexpression.h"
#include "../python/pythonkeywords.h"
#include <QDebug>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>
#include <KProcess>
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();
}
/*
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 <minh@fedoraproject.org>
*/
#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
File=python2backend.kcfg
ClassName=PythonSettings
Singleton=true
/*
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 <tuukka.verho@aalto.fi>
*/
#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<QAbstractItemModel*>(model)->rowCount());
session()->logout();
session()->login();
QCOMPARE(0, static_cast<QAbstractItemModel*>(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<QAbstractItemModel*>(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 );
}