Avogadro::QtGui::PythonScript#

class PythonScript : public QObject#

The PythonScript class implements a interface for calling short-lived python utility scripts.

Unnamed Group

explicit PythonScript(const QString &scriptFilePath_, QObject *parent_ = nullptr)#

Constructors

Parameters:

scriptFilePath_ – Absolute path to python script.

explicit PythonScript(QObject *parent_ = nullptr)#

Constructors

Parameters:

scriptFilePath_ – Absolute path to python script.

Public Functions

~PythonScript() override#
inline bool debug() const#
Returns:

True if debugging of python I/O is enabled.

inline QString scriptFilePath() const#
Returns:

The path to the generator file.

void setScriptFilePath(const QString &scriptFile)#

Set the path to the input generator script file. This will reset any cached data held by this class.

void setPackageInfo(const QString &packageDir, const QString &command, const QString &identifier, const QString &displayName = QString())#

Enable package mode. In this mode, execute() runs “pixi run <command> <identifier> [args]” with packageDir as the working directory, instead of launching a script file via python.

inline bool isPackageMode() const#
Returns:

True if this script is in package mode.

inline QString packageDir() const#
Returns:

The package directory (only meaningful in package mode).

inline QString packageCommand() const#
Returns:

The package command (only meaningful in package mode).

inline QString packageIdentifier() const#
Returns:

The package identifier (only meaningful in package mode).

inline QString packageDisplayName() const#
Returns:

The package display name from metadata, if one was provided.

inline bool hasErrors() const#
Returns:

True if an error is set.

inline void clearErrors()#

Reset the error counter.

inline QStringList errorList() const#
Returns:

A QStringList containing all errors that occurred in the last call to the input generator script.

void setDefaultPythonInterpreter()#

Reset the python interpretor path. The following are checked, in order:

  • The AVO_PYTHON_INTERPRETER environment variable

  • The “interpreters/python” QSettings value

  • The path specified in avogadropython.h.

QByteArray execute(const QStringList &args, const QByteArray &scriptStdin = QByteArray())#

Start a new process to execute: “<m_pythonInterpreter> <scriptFilePath()> [args …]”, optionally passing scriptStdin to the processes standard input. Returns the standard output of the process when finished.

bool asyncExecute(const QStringList &args, const QByteArray &scriptStdin = QByteArray(), bool mergedChannels = true, bool closeWriteChannel = true)#

Start a new process to execute asynchronously “<m_pythonInterpreter> <scriptFilePath()> [args …]”, optionally passing scriptStdin to the processes standard input. If closeWriteChannel is false, stdin remains open for follow-up writes.

Will send asyncFinished() signal when finished

Returns true if the process was started; false if it could not be launched, in which case finished() will never be emitted and errorList() describes the failure.

inline void setProgressScanning(bool enable)#

Enable incremental scanning of the asynchronous process’ standard output for progress envelopes, i.e. single lines of the form {"avogadro": { ... }}. Matching lines are removed from the output and reported through the asyncProgress() signal; every other line is kept and returned by asyncResponse() as usual.

This must be set before asyncExecute(). It is opt-in because scanning drains the process’ output as it arrives, which is incompatible with callers that read the process directly (e.g. asyncWriteAndResponse() in “server mode”).

When enabled, the script is run with AVO_PROGRESS_PROTOCOL set in its environment so it can tell that Avogadro is listening. Scripts must check for it before printing envelopes: releases up to and including Avogadro 2.0.0 read the script’s whole standard output as a single JSON document, and the extra lines make that parse fail outright.

inline bool progressScanning() const#
Returns:

True if standard output is being scanned for progress envelopes.

QByteArray asyncWriteAndResponse(QByteArray input)#

Write input to the asynchronous process’ standard input and return the standard output when ready. Does not wait for the process to terminate before returning (e.g. “server mode”).

Parameters:

input – The input to write to the process’ standard input

Returns:

The standard output of the process

QByteArray asyncWriteAndResponseRaw(const QByteArray &input, int timeoutMs = 5000)#

Write input to the asynchronous process’ standard input and return raw bytes from stdout. Unlike asyncWriteAndResponse(), this does not require line-oriented output and is suitable for framed binary protocols.

void asyncTerminate()#

Terminate the asynchronous process.

QByteArray asyncResponse()#

Returns the standard output of the asynchronous process when finished. If progress scanning is enabled, progress envelope lines have been removed and the remainder is returned even after the process is gone.

inline QByteArray asyncStandardError() const#
Returns:

The standard error collected from the asynchronous process. Only populated when the process was started with separate channels; useful for reporting a python traceback that never reached standard output.

Public Slots

inline void setDebug(bool d)#

Enable/disable debugging.

void processFinished(int exitCode, QProcess::ExitStatus exitStatus)#

Handle a finished process;

Signals

void finished()#

The asynchronous execution is finished or timed out

void asyncProgress(const QJsonObject &payload)#

A progress envelope was read from the asynchronous process’ standard output. Only emitted when setProgressScanning(true) was called before asyncExecute().

Parameters:

payload – The contents of the “avogadro” member of the envelope.

Public Static Functions

static bool parseProgressEnvelope(const QByteArray &line, QJsonObject &payload)#

Test whether a single line of script output is a progress envelope.

To avoid mistaking part of a pretty-printed result for an envelope, the line must parse as a complete JSON object with exactly one member, named “avogadro”.

Parameters:
  • line – The line to test, without its trailing newline.

  • payload – Set to the contents of the “avogadro” member on success.

Returns:

True if line is a progress envelope.

static void filterProgressLines(QByteArray &buffer, QByteArray &output, QList<QJsonObject> &payloads)#

Split buffer into complete lines, appending the payload of any progress envelope to payloads and every other line (newline included) verbatim to output. A trailing partial line is left in buffer for the next call.

Protected Attributes

bool m_debug#
bool m_packageMode = false#
QString m_pythonInterpreter#
QString m_pixi#
QString m_scriptFilePath#
QString m_packageDir#
QString m_packageCommand#
QString m_packageIdentifier#
QString m_packageDisplayName#
QStringList m_errors#
QProcess *m_process#