Desparately try to re-use the tried-and-true IPC Python script for communications with the driver
Creates a wrapper script around the existing IPC library that makes for simpler invocations
This commit is contained in:
parent
0d8fb02388
commit
843f7907e7
|
|
@ -4,3 +4,4 @@ __pycache__
|
|||
gschemas.compiled
|
||||
out/
|
||||
*.po~
|
||||
kwin/src/xrdriveripc/xrdriveripc.py
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ rm -rf $XR_DRIVER_TMP_DIR
|
|||
cp $XR_DRIVER_BINARY $PACKAGE_DIR/xrDriver.tar.gz
|
||||
cp $XR_DRIVER_DIR/bin/xr_driver_setup $PACKAGE_DIR/bin
|
||||
|
||||
# alternative to symlinking, since the Docker build can't resolve to the parent directory
|
||||
# this file is in .gitignore so it doesn't get duplicated
|
||||
cp ui/modules/PyXRLinuxDriverIPC/xrdriveripc.py $KWIN_DIR/src/xrdriveripc/xrdriveripc.py
|
||||
|
||||
pushd $KWIN_DIR
|
||||
docker-build/init.sh
|
||||
docker-build/run-build.sh $BUILD_ARCH
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ if [ -n "\$QT_PLUGIN_PATH" ]; then
|
|||
else
|
||||
export QT_PLUGIN_PATH="$QT_PLUGIN_DIR"
|
||||
fi
|
||||
export QT_DEBUG_PLUGINS=1
|
||||
EOF
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@ RUN pacman -Sy --noconfirm --needed \
|
|||
kwindowsystem \
|
||||
kwin \
|
||||
&& pacman -Scc --noconfirm
|
||||
RUN pacman -Sy --noconfirm --needed \
|
||||
python \
|
||||
&& pacman -Scc --noconfirm
|
||||
|
||||
WORKDIR /source
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ RUN pacman -Sy --noconfirm --needed \
|
|||
kwindowsystem \
|
||||
kwin \
|
||||
&& pacman -Scc --noconfirm
|
||||
RUN pacman -Sy --noconfirm --needed \
|
||||
python \
|
||||
&& pacman -Scc --noconfirm
|
||||
|
||||
WORKDIR /source
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
add_subdirectory(xrdriveripc)
|
||||
add_subdirectory(kcm)
|
||||
|
||||
kcoreaddons_add_plugin(breezy_desktop INSTALL_NAMESPACE "kwin/effects/plugins/")
|
||||
|
|
@ -38,6 +39,7 @@ target_compile_definitions(breezy_desktop PRIVATE
|
|||
KWIN_VERSION_ENCODED=${KWIN_VERSION_ENCODED}
|
||||
)
|
||||
target_include_directories(breezy_desktop PRIVATE /usr/include/kwin)
|
||||
target_include_directories(breezy_desktop PRIVATE xrdriveripc)
|
||||
target_link_libraries(breezy_desktop
|
||||
Qt6::Core
|
||||
Qt6::Gui
|
||||
|
|
@ -51,6 +53,9 @@ target_link_libraries(breezy_desktop
|
|||
KF6::WindowSystem
|
||||
|
||||
KWin::kwin
|
||||
|
||||
xr_driver_ipc
|
||||
)
|
||||
|
||||
install(DIRECTORY qml DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/breezy_desktop)
|
||||
|
||||
install(DIRECTORY qml DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/breezy_desktop)
|
||||
|
|
@ -1,11 +1,13 @@
|
|||
|
||||
#include "core/rendertarget.h"
|
||||
#include "core/renderviewport.h"
|
||||
#include "kcm/shortcuts.h"
|
||||
#include "breezydesktopeffect.h"
|
||||
#include "breezydesktopconfig.h"
|
||||
#include "effect/effect.h"
|
||||
#include "effect/effecthandler.h"
|
||||
#include "opengl/glutils.h"
|
||||
#include "core/rendertarget.h"
|
||||
#include "core/renderviewport.h"
|
||||
#include "xrdriveripc.h"
|
||||
|
||||
#include <kwin/main.h>
|
||||
#include <core/outputbackend.h>
|
||||
|
|
@ -80,11 +82,17 @@ BreezyDesktopEffect::BreezyDesktopEffect()
|
|||
);
|
||||
setupGlobalShortcut(
|
||||
BreezyShortcuts::RECENTER,
|
||||
[this]() { this->recenter(); }
|
||||
[this]() {
|
||||
XRDriverIPCBridge::instance().writeControlFlags({
|
||||
{"recenter_screen", true}
|
||||
});
|
||||
}
|
||||
);
|
||||
setupGlobalShortcut(
|
||||
BreezyShortcuts::TOGGLE_ZOOM_ON_FOCUS,
|
||||
[this]() { this->toggleZoomOnFocus(); }
|
||||
[this]() {
|
||||
this->setZoomOnFocusEnabled(!m_zoomOnFocusEnabled);
|
||||
}
|
||||
);
|
||||
|
||||
connect(effects, &EffectsHandler::cursorShapeChanged, this, &BreezyDesktopEffect::updateCursorImage);
|
||||
|
|
@ -209,60 +217,11 @@ void BreezyDesktopEffect::deactivate()
|
|||
void BreezyDesktopEffect::enableDriver()
|
||||
{
|
||||
qCCritical(KWIN_XR) << "\t\t\tBreezy - enableDriver";
|
||||
QByteArray homeEnv = qgetenv("HOME");
|
||||
QString program = QString::fromUtf8(homeEnv) + QStringLiteral("/.local/bin/xr_driver_cli");
|
||||
|
||||
// Helper lambda to start the second call
|
||||
auto setBreezyDesktopMode = [this, program]() {
|
||||
QProcess *proc2 = new QProcess(this);
|
||||
proc2->setProgram(program);
|
||||
proc2->setArguments({QStringLiteral("-bd")}); // change the mode to Breezy Desktop
|
||||
proc2->setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
connect(proc2, &QProcess::readyReadStandardOutput, this, [proc2]() {
|
||||
const QByteArray out = proc2->readAllStandardOutput();
|
||||
if (!out.isEmpty()) {
|
||||
qCInfo(KWIN_XR) << "xr_driver_cli -bd:" << out;
|
||||
}
|
||||
});
|
||||
connect(proc2, &QProcess::errorOccurred, this, [proc2](QProcess::ProcessError err) {
|
||||
qCCritical(KWIN_XR) << "xr_driver_cli -bd error" << err << proc2->errorString();
|
||||
});
|
||||
connect(proc2, QOverload<int,QProcess::ExitStatus>::of(&QProcess::finished),
|
||||
this, [this, proc2](int code, QProcess::ExitStatus status) {
|
||||
qCInfo(KWIN_XR) << "xr_driver_cli -bd exited" << code << "status" << status;
|
||||
proc2->deleteLater();
|
||||
});
|
||||
|
||||
proc2->start();
|
||||
};
|
||||
|
||||
QProcess *proc1 = new QProcess(this);
|
||||
proc1->setProgram(program);
|
||||
proc1->setArguments({QStringLiteral("-e")}); // enable flag
|
||||
proc1->setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
connect(proc1, &QProcess::readyReadStandardOutput, this, [proc1]() {
|
||||
const QByteArray out = proc1->readAllStandardOutput();
|
||||
if (!out.isEmpty()) {
|
||||
qCInfo(KWIN_XR) << "xr_driver_cli -e:" << out;
|
||||
}
|
||||
XRDriverIPCBridge::instance().writeConfig({
|
||||
{"disabled", false},
|
||||
{"output_mode", "external_only"},
|
||||
{"external_mode", "breezy_desktop"}
|
||||
});
|
||||
connect(proc1, &QProcess::errorOccurred, this, [proc1](QProcess::ProcessError err) {
|
||||
qCCritical(KWIN_XR) << "xr_driver_cli -e error" << err << proc1->errorString();
|
||||
});
|
||||
connect(proc1, QOverload<int,QProcess::ExitStatus>::of(&QProcess::finished),
|
||||
this, [proc1, setBreezyDesktopMode](int code, QProcess::ExitStatus status) {
|
||||
qCInfo(KWIN_XR) << "xr_driver_cli -e exited" << code << "status" << status;
|
||||
proc1->deleteLater();
|
||||
if (status == QProcess::NormalExit && code == 0) {
|
||||
setBreezyDesktopMode();
|
||||
} else {
|
||||
qCCritical(KWIN_XR) << "First call failed; not starting second.";
|
||||
}
|
||||
});
|
||||
|
||||
proc1->start();
|
||||
}
|
||||
|
||||
void BreezyDesktopEffect::realDeactivate()
|
||||
|
|
@ -271,20 +230,6 @@ void BreezyDesktopEffect::realDeactivate()
|
|||
setRunning(false);
|
||||
}
|
||||
|
||||
void BreezyDesktopEffect::recenter()
|
||||
{
|
||||
QFile controlFile(QStringLiteral("/dev/shm/xr_driver_control"));
|
||||
if (controlFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
controlFile.write("recenter_screen=true\n");
|
||||
controlFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
void BreezyDesktopEffect::toggleZoomOnFocus()
|
||||
{
|
||||
setZoomOnFocusEnabled(!m_zoomOnFocusEnabled);
|
||||
}
|
||||
|
||||
void BreezyDesktopEffect::addVirtualDisplay(QSize size)
|
||||
{
|
||||
// QSize size(2560, 1440);
|
||||
|
|
|
|||
|
|
@ -68,8 +68,6 @@ namespace KWin
|
|||
void deactivate();
|
||||
void enableDriver();
|
||||
void toggle();
|
||||
void recenter();
|
||||
void toggleZoomOnFocus();
|
||||
void addVirtualDisplay(QSize size);
|
||||
void updateImuRotation();
|
||||
void updateCursorImage();
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
# SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
set(breezy_desktop_config_SOURCES breezydesktopeffectkcm.cpp)
|
||||
ki18n_wrap_ui(breezy_desktop_config_SOURCES breezydesktopeffectkcm.ui)
|
||||
qt_add_dbus_interface(breezy_desktop_config_SOURCES ${KWIN_EFFECTS_INTERFACE} kwineffects_interface)
|
||||
|
|
@ -17,4 +13,6 @@ target_link_libraries(breezy_desktop_config
|
|||
KF6::I18n
|
||||
KF6::KCMUtils
|
||||
KF6::XmlGui
|
||||
|
||||
xr_driver_ipc
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
add_library(xr_driver_ipc STATIC
|
||||
xrdriveripc.cpp
|
||||
)
|
||||
|
||||
# Ensure position independent code so the static archive can link into the KWin effect plugin (a shared module)
|
||||
set_target_properties(xr_driver_ipc PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
# Generate an export header so symbols can be visible outside the shared lib
|
||||
include(GenerateExportHeader)
|
||||
generate_export_header(xr_driver_ipc EXPORT_FILE_NAME xr_driver_ipc_export.h)
|
||||
|
||||
target_include_directories(xr_driver_ipc
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_BINARY_DIR} # for generated export header
|
||||
)
|
||||
|
||||
target_compile_options(xr_driver_ipc PRIVATE
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/EHsc>
|
||||
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-fexceptions>
|
||||
)
|
||||
|
||||
target_link_libraries(xr_driver_ipc
|
||||
PRIVATE Qt6::Core
|
||||
)
|
||||
|
||||
install(FILES xrdriveripc.py xrdriveripc_runner.py DESTINATION ${KDE_INSTALL_DATADIR}/kwin/effects/breezy_desktop)
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
// New implementation using QProcess to call python
|
||||
#include "xrdriveripc.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QStandardPaths>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
|
||||
XRDriverIPCBridge &XRDriverIPCBridge::instance() {
|
||||
static XRDriverIPCBridge inst;
|
||||
if (!inst.m_initialized) {
|
||||
QString installedFile = QStandardPaths::locate(
|
||||
QStandardPaths::GenericDataLocation,
|
||||
QStringLiteral("kwin/effects/breezy_desktop/xrdriveripc.py"),
|
||||
QStandardPaths::LocateFile);
|
||||
if (installedFile.isEmpty()) {
|
||||
throw std::runtime_error("Cannot locate kwin/effects/breezy_desktop/xrdriveripc.py");
|
||||
}
|
||||
inst.m_pythonDir = QFileInfo(installedFile).path();
|
||||
inst.m_initialized = true;
|
||||
}
|
||||
return inst;
|
||||
}
|
||||
|
||||
std::string XRDriverIPCBridge::configHome() const {
|
||||
QString configHome = QString::fromUtf8(qgetenv("XDG_CONFIG_HOME"));
|
||||
if (configHome.isEmpty()) {
|
||||
QString homeDir = QString::fromUtf8(qgetenv("HOME"));
|
||||
configHome = homeDir + QStringLiteral("/.config");
|
||||
}
|
||||
return configHome.toStdString();
|
||||
}
|
||||
|
||||
QByteArray XRDriverIPCBridge::invokePython(const QString &method,
|
||||
const QByteArray &payloadJson,
|
||||
const QString &singleArg) const {
|
||||
QProcess proc;
|
||||
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
|
||||
env.insert(QStringLiteral("BREEZY_METHOD"), method);
|
||||
env.insert(QStringLiteral("BREEZY_CONFIG_HOME"), QString::fromStdString(configHome()));
|
||||
if (!singleArg.isEmpty()) env.insert(QStringLiteral("BREEZY_ARG"), singleArg);
|
||||
if (!payloadJson.isEmpty()) env.insert(QStringLiteral("BREEZY_PAYLOAD"), QString::fromUtf8(payloadJson));
|
||||
proc.setProcessEnvironment(env);
|
||||
// Expect xrdriveripc_runner.py to reside in the same directory as xrdriveripc.py (m_pythonDir)
|
||||
QString wrapperPath = m_pythonDir + QStringLiteral("/xrdriveripc_runner.py");
|
||||
proc.start(QStringLiteral("python3"), QStringList() << wrapperPath);
|
||||
if (!proc.waitForStarted(5000)) {
|
||||
std::cerr << "Failed to start python process" << std::endl;
|
||||
return {};
|
||||
}
|
||||
proc.closeWriteChannel();
|
||||
if (!proc.waitForFinished(15000)) {
|
||||
proc.kill();
|
||||
std::cerr << "Python process timeout" << std::endl;
|
||||
return {};
|
||||
}
|
||||
if (proc.exitStatus() != QProcess::NormalExit || proc.exitCode() != 0) {
|
||||
std::cerr << "Python process failed (" << proc.exitCode() << "):\n"
|
||||
<< proc.readAllStandardError().toStdString() << std::endl;
|
||||
return {};
|
||||
}
|
||||
return proc.readAllStandardOutput().trimmed();
|
||||
}
|
||||
|
||||
static XRDict jsonToXRDict(const QJsonObject &obj) {
|
||||
XRDict out;
|
||||
for (auto it = obj.begin(); it != obj.end(); ++it) {
|
||||
const QString &k = it.key();
|
||||
const QJsonValue &v = it.value();
|
||||
if (v.isBool()) out[k.toStdString()] = v.toBool();
|
||||
else if (v.isDouble() && std::floor(v.toDouble()) == v.toDouble())
|
||||
out[k.toStdString()] = (int)v.toDouble();
|
||||
else if (v.isDouble()) out[k.toStdString()] = v.toDouble();
|
||||
else if (v.isString()) out[k.toStdString()] = v.toString().toStdString();
|
||||
else out[k.toStdString()] = std::monostate{};
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::optional<XRDict> XRDriverIPCBridge::retrieveConfig() {
|
||||
QByteArray out = invokePython(QStringLiteral("retrieve_config"), {}, QStringLiteral("1"));
|
||||
if (out.isEmpty()) return std::nullopt;
|
||||
QJsonParseError err; auto doc = QJsonDocument::fromJson(out, &err);
|
||||
if (err.error != QJsonParseError::NoError || !doc.isObject()) return std::nullopt;
|
||||
return jsonToXRDict(doc.object());
|
||||
}
|
||||
|
||||
std::optional<XRDict> XRDriverIPCBridge::retrieveDriverState() {
|
||||
QByteArray out = invokePython(QStringLiteral("retrieve_driver_state"), {}, {});
|
||||
if (out.isEmpty()) return std::nullopt;
|
||||
QJsonParseError err; auto doc = QJsonDocument::fromJson(out, &err);
|
||||
if (err.error != QJsonParseError::NoError || !doc.isObject()) return std::nullopt;
|
||||
return jsonToXRDict(doc.object());
|
||||
}
|
||||
|
||||
bool XRDriverIPCBridge::writeConfig(const XRDict &configUpdate) {
|
||||
QJsonObject obj;
|
||||
for (const auto &kv : configUpdate) {
|
||||
const std::string &k = kv.first; const XRValue &v = kv.second;
|
||||
if (std::holds_alternative<bool>(v)) obj.insert(QString::fromStdString(k), std::get<bool>(v));
|
||||
else if (std::holds_alternative<int>(v)) obj.insert(QString::fromStdString(k), std::get<int>(v));
|
||||
else if (std::holds_alternative<double>(v)) obj.insert(QString::fromStdString(k), std::get<double>(v));
|
||||
else if (std::holds_alternative<std::string>(v)) obj.insert(QString::fromStdString(k), QString::fromStdString(std::get<std::string>(v)));
|
||||
}
|
||||
QByteArray payload = QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||
QByteArray out = invokePython(QStringLiteral("write_config"), payload, {});
|
||||
return !out.isEmpty();
|
||||
}
|
||||
|
||||
bool XRDriverIPCBridge::writeControlFlags(const std::map<std::string, bool> &flags) {
|
||||
QJsonObject obj; for (const auto &kv : flags) obj.insert(QString::fromStdString(kv.first), kv.second);
|
||||
QByteArray payload = QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||
QByteArray out = invokePython(QStringLiteral("write_control_flags"), payload, {});
|
||||
return !out.isEmpty();
|
||||
}
|
||||
|
||||
bool XRDriverIPCBridge::requestToken(const std::string &email) {
|
||||
QByteArray out = invokePython(QStringLiteral("request_token"), {}, QString::fromStdString(email));
|
||||
if (out.isEmpty()) return false;
|
||||
auto value = QJsonValue(QString::fromStdString(out.toStdString()));
|
||||
return value.isBool() ? value.toBool() : false;
|
||||
}
|
||||
|
||||
bool XRDriverIPCBridge::verifyToken(const std::string &token) {
|
||||
QByteArray out = invokePython(QStringLiteral("verify_token"), {}, QString::fromStdString(token));
|
||||
if (out.isEmpty()) return false;
|
||||
auto value = QJsonValue(QString::fromStdString(out.toStdString()));
|
||||
return value.isBool() ? value.toBool() : false;
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// C++ bridge now invoking xrdriveripc via external python process
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
|
||||
// Export header generated by CMake (GenerateExportHeader)
|
||||
#ifdef __has_include
|
||||
# if __has_include("xr_driver_ipc_export.h")
|
||||
# include "xr_driver_ipc_export.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef XR_DRIVER_IPC_EXPORT
|
||||
# define XR_DRIVER_IPC_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
// Simple variant type for config/state key values we care about
|
||||
using XRValue = std::variant<std::monostate, bool, int, double, std::string>;
|
||||
using XRDict = std::map<std::string, XRValue>;
|
||||
|
||||
class XR_DRIVER_IPC_EXPORT XRDriverIPCBridge {
|
||||
public:
|
||||
static XRDriverIPCBridge &instance();
|
||||
|
||||
std::optional<XRDict> retrieveConfig();
|
||||
std::optional<XRDict> retrieveDriverState();
|
||||
bool writeConfig(const XRDict &configUpdate);
|
||||
bool writeControlFlags(const std::map<std::string, bool> &flags);
|
||||
bool requestToken(const std::string &email);
|
||||
bool verifyToken(const std::string &token);
|
||||
|
||||
private:
|
||||
XRDriverIPCBridge() = default;
|
||||
~XRDriverIPCBridge() = default;
|
||||
XRDriverIPCBridge(const XRDriverIPCBridge&) = delete;
|
||||
XRDriverIPCBridge& operator=(const XRDriverIPCBridge&) = delete;
|
||||
|
||||
std::string configHome() const;
|
||||
QByteArray invokePython(const QString &method,
|
||||
const QByteArray &payloadJson,
|
||||
const QString &singleArg) const;
|
||||
|
||||
bool m_initialized = false;
|
||||
QString m_pythonDir; // directory containing xrdriveripc.py
|
||||
};
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env python3
|
||||
"""Wrapper script invoked by xrdriveripc.cpp via QProcess.
|
||||
|
||||
It reads environment variables to determine which XRDriverIPC method to call
|
||||
and prints the JSON-serialized result to stdout, mirroring the prior inline
|
||||
python one-liner implementation.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
|
||||
def main() -> int:
|
||||
# Ensure the current directory (where xrdriveripc.py lives) is in sys.path
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
if script_dir not in sys.path:
|
||||
sys.path.insert(0, script_dir)
|
||||
|
||||
try:
|
||||
import xrdriveripc # type: ignore
|
||||
except Exception as e: # pragma: no cover - import failure path
|
||||
print("Failed to import xrdriveripc: %s" % e, file=sys.stderr)
|
||||
return 2
|
||||
|
||||
method = os.environ.get("BREEZY_METHOD")
|
||||
if not method:
|
||||
print("BREEZY_METHOD not set", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
config_home = os.environ.get("BREEZY_CONFIG_HOME")
|
||||
inst = xrdriveripc.XRDriverIPC(config_home=config_home)
|
||||
|
||||
arg = os.environ.get("BREEZY_ARG")
|
||||
payload_raw = os.environ.get("BREEZY_PAYLOAD")
|
||||
|
||||
# Dispatch replicating previous inline logic
|
||||
try:
|
||||
if method == "retrieve_config":
|
||||
res = getattr(inst, method)(int(arg) if arg else 1)
|
||||
elif method in ("write_config", "write_control_flags") and payload_raw:
|
||||
res = getattr(inst, method)(json.loads(payload_raw))
|
||||
elif method in ("request_token", "verify_token") and arg:
|
||||
res = getattr(inst, method)(arg)
|
||||
else:
|
||||
res = getattr(inst, method)()
|
||||
except Exception: # pragma: no cover - runtime failure path
|
||||
traceback.print_exc()
|
||||
return 3
|
||||
|
||||
try:
|
||||
print(json.dumps(res))
|
||||
except Exception: # pragma: no cover
|
||||
traceback.print_exc()
|
||||
return 3
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
sys.exit(main())
|
||||
Loading…
Reference in New Issue