Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package krunner for openSUSE:Factory checked in at 2021-08-16 10:08:08 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/krunner (Old) and /work/SRC/openSUSE:Factory/.krunner.new.1899 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "krunner" Mon Aug 16 10:08:08 2021 rev:92 rq:912160 version:5.85.0 Changes: -------- --- /work/SRC/openSUSE:Factory/krunner/krunner.changes 2021-07-16 00:01:47.060899606 +0200 +++ /work/SRC/openSUSE:Factory/.krunner.new.1899/krunner.changes 2021-08-16 10:12:18.119048099 +0200 @@ -1,0 +2,13 @@ +Fri Aug 6 12:13:10 UTC 2021 - Christophe Giboudeaux <[email protected]> + +- Update to 5.85.0 + * New feature release + * For more details please see: + * https://kde.org/announcements/frameworks/5/5.85.0 +- Changes since 5.84.0: + * Deprecate RunnerManager::runnerMetaDataList(QString parentApp) method + * Deprecate TryExec property for runners + * Use KFileUtils::findAllUniqueFiles to locate DBus runners + * Port away from deprecated QMutex constructor + +------------------------------------------------------------------- Old: ---- krunner-5.84.0.tar.xz krunner-5.84.0.tar.xz.sig New: ---- krunner-5.85.0.tar.xz krunner-5.85.0.tar.xz.sig ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ krunner.spec ++++++ --- /var/tmp/diff_new_pack.hYSI79/_old 2021-08-16 10:12:18.523047624 +0200 +++ /var/tmp/diff_new_pack.hYSI79/_new 2021-08-16 10:12:18.531047616 +0200 @@ -17,7 +17,7 @@ %define lname libKF5Runner5 -%define _tar_path 5.84 +%define _tar_path 5.85 # Full KF5 version (e.g. 5.33.0) %{!?_kf5_version: %global _kf5_version %{version}} # Last major and minor KF5 version (e.g. 5.33) @@ -25,7 +25,7 @@ # Only needed for the package signature condition %bcond_without lang Name: krunner -Version: 5.84.0 +Version: 5.85.0 Release: 0 Summary: KDE Framework for providing different actions given a string query License: LGPL-2.1-or-later ++++++ krunner-5.84.0.tar.xz -> krunner-5.85.0.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/.gitignore new/krunner-5.85.0/.gitignore --- old/krunner-5.84.0/.gitignore 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/.gitignore 2021-08-04 17:53:33.000000000 +0200 @@ -26,3 +26,4 @@ .vscode /compile_commands.json .clangd +.cache diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/CMakeLists.txt new/krunner-5.85.0/CMakeLists.txt --- old/krunner-5.84.0/CMakeLists.txt 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/CMakeLists.txt 2021-08-04 17:53:33.000000000 +0200 @@ -1,12 +1,12 @@ cmake_minimum_required(VERSION 3.16) -set(KF_VERSION "5.84.0") # handled by release scripts -set(KF_DEP_VERSION "5.84.0") # handled by release scripts +set(KF_VERSION "5.85.0") # handled by release scripts +set(KF_DEP_VERSION "5.85.0") # handled by release scripts project(KRunner VERSION ${KF_VERSION}) # ECM setup include(FeatureSummary) -find_package(ECM 5.84.0 NO_MODULE) +find_package(ECM 5.85.0 NO_MODULE) set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake Modules." URL "https://commits.kde.org/extra-cmake-modules") feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND FATAL_ON_MISSING_REQUIRED_PACKAGES) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/autotests/runnermatchmethodstest.cpp new/krunner-5.85.0/autotests/runnermatchmethodstest.cpp --- old/krunner-5.84.0/autotests/runnermatchmethodstest.cpp 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/autotests/runnermatchmethodstest.cpp 2021-08-04 17:53:33.000000000 +0200 @@ -169,6 +169,7 @@ QVERIFY(!ctx->match(QStringLiteral("does_not_exist")).isValid()); QCOMPARE(ctx->match(QStringLiteral("does_not_exist")).runner(), nullptr); } +#endif void RunnerContextMatchMethodsTest::testDuplicateIds() { @@ -192,7 +193,6 @@ QCOMPARE(matches.at(2), match4); } -#endif QTEST_MAIN(RunnerContextMatchMethodsTest) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/autotests/testremoterunner.h new/krunner-5.85.0/autotests/testremoterunner.h --- old/krunner-5.84.0/autotests/testremoterunner.h 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/autotests/testremoterunner.h 2021-08-04 17:53:33.000000000 +0200 @@ -7,7 +7,7 @@ { Q_OBJECT public: - TestRemoteRunner(const QString &serviceName); + explicit TestRemoteRunner(const QString &serviceName); public Q_SLOTS: RemoteActions Actions(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/src/CMakeLists.txt new/krunner-5.85.0/src/CMakeLists.txt --- old/krunner-5.84.0/src/CMakeLists.txt 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/src/CMakeLists.txt 2021-08-04 17:53:33.000000000 +0200 @@ -36,7 +36,7 @@ GROUP_BASE_NAME KF VERSION ${KF_VERSION} DEPRECATED_BASE_VERSION 0 - DEPRECATION_VERSIONS 5.28 5.71 5.72 5.73 5.76 5.77 5.79 5.81 5.82 + DEPRECATION_VERSIONS 5.28 5.71 5.72 5.73 5.76 5.77 5.79 5.81 5.82 5.85 EXCLUDE_DEPRECATED_BEFORE_AND_AT ${EXCLUDE_DEPRECATED_BEFORE_AND_AT} ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/src/abstractrunner.h new/krunner-5.85.0/src/abstractrunner.h --- old/krunner-5.84.0/src/abstractrunner.h 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/src/abstractrunner.h 2021-08-04 17:53:33.000000000 +0200 @@ -654,7 +654,7 @@ // clang-format off #if KRUNNER_ENABLE_DEPRECATED_SINCE(5, 72) -// Boilerplate to emit a version-controlled warning about the deprecated macro at leats with GCC +// Boilerplate to emit a version-controlled warning about the deprecated macro at least with GCC #if KRUNNER_DEPRECATED_WARNINGS_SINCE >= 0x054800 // 5.72.0 # if defined(__GNUC__) # define K_EXPORT_PLASMA_RUNNER_DO_PRAGMA(x) _Pragma (#x) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/src/data/org.kde.krunner1.xml new/krunner-5.85.0/src/data/org.kde.krunner1.xml --- old/krunner-5.84.0/src/data/org.kde.krunner1.xml 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/src/data/org.kde.krunner1.xml 2021-08-04 17:53:33.000000000 +0200 @@ -52,7 +52,7 @@ - Subtext - Action Ids (StringList). In case you don't want to display any actions set this to an empty list. Otherwise all the actions will be shown for compatibility with the previous versions of the D-Bus API. - When the actions ony need to be fetched once you can set the X-Plasma-Request-Actions-Once property of + When the actions only need to be fetched once you can set the X-Plasma-Request-Actions-Once property of the service file to true. - icon-data (iiibiiay). Custom icon pixmap. Icon name should be preferred, if available. Format is the same as org.freedesktop.Notifications icon-data, in order: width, height, row stride, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/src/data/servicetypes/plasma-runner.desktop new/krunner-5.85.0/src/data/servicetypes/plasma-runner.desktop --- old/krunner-5.84.0/src/data/servicetypes/plasma-runner.desktop 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/src/data/servicetypes/plasma-runner.desktop 2021-08-04 17:53:33.000000000 +0200 @@ -57,6 +57,7 @@ [PropertyDef::X-Plasma-AdvertiseSingleRunnerQueryMode] Type=bool +# TODO KF6 remove [PropertyDef::TryExec] Type=QString diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/src/dbusrunner.cpp new/krunner-5.85.0/src/dbusrunner.cpp --- old/krunner-5.84.0/src/dbusrunner.cpp 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/src/dbusrunner.cpp 2021-08-04 17:53:33.000000000 +0200 @@ -24,7 +24,6 @@ DBusRunner::DBusRunner(const KPluginMetaData &pluginMetaData, QObject *parent) : Plasma::AbstractRunner(pluginMetaData, parent) - , m_mutex(QMutex::NonRecursive) { qDBusRegisterMetaType<RemoteMatch>(); qDBusRegisterMetaType<RemoteMatches>(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/src/runnermanager.cpp new/krunner-5.85.0/src/runnermanager.cpp --- old/krunner-5.84.0/src/runnermanager.cpp 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/src/runnermanager.cpp 2021-08-04 17:53:33.000000000 +0200 @@ -16,6 +16,7 @@ #include <QTimer> #include <KConfigWatcher> +#include <KFileUtils> #include <KPluginMetaData> #include <KServiceTypeTrader> #include <KSharedConfig> @@ -36,30 +37,10 @@ #include "querymatch.h" #include "runnerjobs_p.h" -using ThreadWeaver::Job; using ThreadWeaver::Queue; namespace Plasma { -void forEachDBusPlugin(std::function<void(const KPluginMetaData &)> callback) -{ - const QStringList dBusPlugindirs = - QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("krunner/dbusplugins"), QStandardPaths::LocateDirectory); - const QStringList serviceTypeFiles(QStringLiteral("plasma-runner.desktop")); - QSet<QString> addedPluginIds; - for (const QString &dir : dBusPlugindirs) { - const QStringList desktopFiles = QDir(dir).entryList(QStringList(QStringLiteral("*.desktop"))); - for (const QString &file : desktopFiles) { - const QString desktopFilePath = dir + QLatin1Char('/') + file; - KPluginMetaData pluginMetaData = KPluginMetaData::fromDesktopFile(desktopFilePath, serviceTypeFiles); - if (pluginMetaData.isValid() && !addedPluginIds.contains(pluginMetaData.pluginId())) { - callback(pluginMetaData); - addedPluginIds << pluginMetaData.pluginId(); - } - } - } -} - #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 0) void warnAboutDeprecatedMetaData(const KPluginInfo &pluginInfo) { @@ -73,10 +54,6 @@ } #endif -/***************************************************** - * RunnerManager::Private class - * - *****************************************************/ class RunnerManagerPrivate { public: @@ -177,11 +154,16 @@ KPluginMetaData &description = it.next(); qCDebug(KRUNNER) << "Loading runner: " << description.pluginId(); +#if KRUNNER_BUILD_DEPRECATED_SINCE(5, 85) const QString tryExec = description.value(QStringLiteral("TryExec")); - if (!tryExec.isEmpty() && QStandardPaths::findExecutable(tryExec).isEmpty()) { - // we don't actually have this application! - continue; + if (!tryExec.isEmpty()) { + qCDebug(KRUNNER) << description.pluginId() << "The TryExec property is deprecated, manually check if the application exists if needed"; + if (QStandardPaths::findExecutable(tryExec).isEmpty()) { + // we don't actually have this application! + continue; + } } +#endif const QString runnerName = description.pluginId(); const bool isPluginEnabled = pluginConf.readEntry(runnerName + QLatin1String("Enabled"), description.isEnabledByDefault()); @@ -506,10 +488,6 @@ #endif }; -/***************************************************** - * RunnerManager::Public class - * - *****************************************************/ RunnerManager::RunnerManager(QObject *parent) : RunnerManager(QString(), parent) { @@ -767,6 +745,7 @@ return match.isValid() ? match.runner()->mimeDataForMatch(match) : nullptr; } +#if KRUNNER_BUILD_DEPRECATED_SINCE(5, 85) QVector<KPluginMetaData> RunnerManager::runnerMetaDataList(const QString &parentApp) { // get binary plugins @@ -782,11 +761,16 @@ knownRunnerIds.insert(pluginMetaData.pluginId()); } - // get D-Bus plugins - forEachDBusPlugin([&](const KPluginMetaData &pluginMetaData) { - pluginMetaDatas.append(pluginMetaData); - knownRunnerIds.insert(pluginMetaData.pluginId()); - }); + const QStringList dBusPlugindirs = + QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("krunner/dbusplugins"), QStandardPaths::LocateDirectory); + const QStringList dbusRunnerFiles = KFileUtils::findAllUniqueFiles(dBusPlugindirs, QStringList(QStringLiteral("*.desktop"))); + for (const QString &dbusRunnerFile : dbusRunnerFiles) { + KPluginMetaData pluginMetaData = KPluginMetaData::fromDesktopFile(dbusRunnerFile, QStringList(QStringLiteral("plasma-runner.desktop"))); + if (pluginMetaData.isValid() && !knownRunnerIds.contains(pluginMetaData.pluginId())) { + pluginMetaDatas.append(pluginMetaData); + knownRunnerIds.insert(pluginMetaData.pluginId()); + } + } #if KSERVICE_BUILD_DEPRECATED_SINCE(5, 0) // also search for deprecated kservice-based KRunner plugins metadata @@ -797,6 +781,47 @@ QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations") QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations") + const KPluginInfo::List backwardCompatPluginInfos = KPluginInfo::fromServices(offers); + QT_WARNING_POP + + for (const KPluginInfo &pluginInfo : backwardCompatPluginInfos) { + if (!knownRunnerIds.contains(pluginInfo.pluginName())) { + warnAboutDeprecatedMetaData(pluginInfo); + pluginMetaDatas.append(pluginInfo.toMetaData()); + } + } +#endif + + return pluginMetaDatas; +} +#endif + +QVector<KPluginMetaData> RunnerManager::runnerMetaDataList() +{ + QVector<KPluginMetaData> pluginMetaDatas = KPluginLoader::findPlugins(QStringLiteral("kf5/krunner")); + QSet<QString> knownRunnerIds; + knownRunnerIds.reserve(pluginMetaDatas.size()); + for (const KPluginMetaData &pluginMetaData : qAsConst(pluginMetaDatas)) { + knownRunnerIds.insert(pluginMetaData.pluginId()); + } + + const QStringList dBusPlugindirs = + QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("krunner/dbusplugins"), QStandardPaths::LocateDirectory); + const QStringList dbusRunnerFiles = KFileUtils::findAllUniqueFiles(dBusPlugindirs, QStringList(QStringLiteral("*.desktop"))); + for (const QString &dbusRunnerFile : dbusRunnerFiles) { + KPluginMetaData pluginMetaData = KPluginMetaData::fromDesktopFile(dbusRunnerFile, QStringList(QStringLiteral("plasma-runner.desktop"))); + if (pluginMetaData.isValid() && !knownRunnerIds.contains(pluginMetaData.pluginId())) { + pluginMetaDatas.append(pluginMetaData); + knownRunnerIds.insert(pluginMetaData.pluginId()); + } + } + +#if KSERVICE_BUILD_DEPRECATED_SINCE(5, 0) + // also search for deprecated kservice-based KRunner plugins metadata + const KService::List offers = KServiceTypeTrader::self()->query(QStringLiteral("Plasma/Runner")); + QT_WARNING_PUSH + QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations") + QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations") const KPluginInfo::List backwardCompatPluginInfos = KPluginInfo::fromServices(offers); QT_WARNING_POP diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/src/runnermanager.h new/krunner-5.85.0/src/runnermanager.h --- old/krunner-5.84.0/src/runnermanager.h 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/src/runnermanager.h 2021-08-04 17:53:33.000000000 +0200 @@ -340,6 +340,7 @@ QMimeData *mimeDataForMatch(const QString &matchId) const; #endif +#if KRUNNER_ENABLE_DEPRECATED_SINCE(5, 85) /** * Returns a list of all known Runner implementations * @@ -350,8 +351,17 @@ * registered to an application. * @return list of metadata of known runners * @since 5.72 + * @deprecated Since 5.85, the concept of parent apps for runners is deprecated, use no-arg overload instead **/ - static QVector<KPluginMetaData> runnerMetaDataList(const QString &parentApp = QString()); + KRUNNER_DEPRECATED_VERSION(5, 85, "The concept of parent apps for runners is deprecated, use no-arg overload instead") + static QVector<KPluginMetaData> runnerMetaDataList(const QString &parentApp); +#endif + + /** + * @return metadata list of all known Runner implementations + * @since 5.72 + */ + static QVector<KPluginMetaData> runnerMetaDataList(); #if KRUNNER_ENABLE_DEPRECATED_SINCE(5, 72) /** diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/src/runnersyntax.h new/krunner-5.85.0/src/runnersyntax.h --- old/krunner-5.84.0/src/runnersyntax.h 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/src/runnersyntax.h 2021-08-04 17:53:33.000000000 +0200 @@ -120,7 +120,7 @@ #if KRUNNER_ENABLE_DEPRECATED_SINCE(5, 76) /** * @return a description of the search term for this syntax - * @deprecated Since 5.76, the desciption should be directly set when creating the example query. + * @deprecated Since 5.76, the description should be directly set when creating the example query. */ KRUNNER_DEPRECATED_VERSION(5, 76, "Feature is obsolete, the search term description should be set inside of the example query directly") QString searchTermDescription() const; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/templates/runnerpython/README.md new/krunner-5.85.0/templates/runnerpython/README.md --- old/krunner-5.84.0/templates/runnerpython/README.md 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/templates/runnerpython/README.md 2021-08-04 17:53:33.000000000 +0200 @@ -3,7 +3,7 @@ This plugin provides a simple template for a KRunner plugin using dbus. The install script copies the Krunner config file and a dbus activation service file -to their appropiate locations. +to their appropriate locations. This way the python script gets executed when KRunner requests matches and it does not need to be autostarted. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/krunner-5.84.0/templates/runnerpython/runnerpy.kdevtemplate new/krunner-5.85.0/templates/runnerpython/runnerpy.kdevtemplate --- old/krunner-5.84.0/templates/runnerpython/runnerpy.kdevtemplate 2021-06-29 06:08:27.000000000 +0200 +++ new/krunner-5.85.0/templates/runnerpython/runnerpy.kdevtemplate 2021-08-04 17:53:33.000000000 +0200 @@ -1,5 +1,6 @@ [General] Name=Python KRunner Plugin +Name[ar]=?????????? ???????????? ?????????????? Name[az]=Python KRunner qo??mas?? Name[ca]=Connector Python del KRunner Name[cs]=Modul KRunneru pr Python @@ -9,6 +10,7 @@ Name[en_GB]=Python KRunner Plugin Name[es]=Complemento en Python para KRunner Name[et]=Pythoni KRunneri plugin +Name[eu]=Python KRunner plugina Name[fi]=Python-KRunner-liit??nn??inen Name[fr]=module externe ????KRunner???? pour Python Name[hi]=??????????????? ??????????????? ?????????????????? @@ -27,10 +29,12 @@ Name[sk]=Z??suvn?? modul Python pre KRunner Name[sl]=Vti??nik za Python KRunner Name[sv]=Python-insticksprogram f??r K??r program +Name[tr]=Python KRunner Eklentisi Name[uk]=?????????????? ???? KRunner ?????????? Python Name[x-test]=xxPython KRunner Pluginxx Name[zh_CN]=Python KRunner ?????? Comment=Template for a KRunner Python Plugin using D-Bus +Comment[ar]=???????? ?????????? ???????????? ???????????? ???????????????? D-Bus Comment[az]=D-Bus il?? istifad?? olunan KRunner Python Qo??mas?? ??????n n??mun?? Comment[ca]=Plantilla per a un connector Python del KRunner usant D-Bus Comment[da]=Skabelon til et KRunner Python-plugin med brug af D-Bus @@ -39,6 +43,7 @@ Comment[en_GB]=Template for a KRunner Python Plugin using D-Bus Comment[es]=Plantilla para un complemento en Python para KRunner que usa D-Bus Comment[et]=D-Busi kasutav KRunneri Pythoni plugina mall +Comment[eu]=KRunner Python plugin batentzako D-Bus erabiltzen duen txantiloi bat Comment[fi]=Malli KRunnerin Python-liit??nn??iseksi D-Busia k??ytt??en Comment[fr]=Mod??le pour le module externe ????KRunner???? pour Python, utilisant ????D-Bus???? Comment[hi]=??????-?????? ?????? ?????????????????? ???????????? ????????? ?????? ??????????????? ??????????????? ?????????????????? ?????? ??????????????? @@ -56,6 +61,7 @@ Comment[sk]=??abl??na pre KRunner Python plugin vyu????vaj??ci D-Bus Comment[sl]=Predloga za vti??nik Python KRunner z uporabo D-Bus Comment[sv]=Mall f??r ett Python-insticksprogram f??r K??r program med anv??ndning av D-Bus +Comment[tr]=D-Bus kullanan bir KRunner Python Eklentisi i??in ??ablon Comment[uk]=???????????? ?????? ?????????????? Python KRunner ?? ?????????????????????????? D-Bus Comment[x-test]=xxTemplate for a KRunner Python Plugin using D-Busxx Comment[zh_CN]=?????? D-Bus ??? KRunner Python ????????????
