From bfb23b3b843ffae65d26a3030b11c474c15e1d41 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 12 Sep 2023 13:35:21 +0200 Subject: [PATCH] Python: get pretty_name from Python module Add a convenience method for logging pybind11 objects. --- src/libcalamares/python/Api.cpp | 8 +-- src/libcalamares/python/Logger.h | 32 ++++++++++++ src/libcalamares/python/PythonJob.cpp | 72 +++++++++++++++++++++++++-- 3 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 src/libcalamares/python/Logger.h diff --git a/src/libcalamares/python/Api.cpp b/src/libcalamares/python/Api.cpp index 7bd348ac3..97e5ec781 100644 --- a/src/libcalamares/python/Api.cpp +++ b/src/libcalamares/python/Api.cpp @@ -191,9 +191,10 @@ load_yaml( const std::string& path ) return variantMapToPyDict( map ); } -static Calamares::GlobalStorage * _global_storage() +static Calamares::GlobalStorage* +_global_storage() { - static Calamares::GlobalStorage * p = new Calamares::GlobalStorage; + static Calamares::GlobalStorage* p = new Calamares::GlobalStorage; return p; } @@ -209,8 +210,7 @@ _gettext_languages() // own GlobalStoragePythonWrapper, which then holds a // GlobalStorage object for all of Python. Calamares::JobQueue* jq = Calamares::JobQueue::instance(); - Calamares::GlobalStorage* gs - = jq ? jq->globalStorage() : _global_storage(); + Calamares::GlobalStorage* gs = jq ? jq->globalStorage() : _global_storage(); QString lang = Calamares::Locale::readGS( *gs, QStringLiteral( "LANG" ) ); if ( !lang.isEmpty() ) diff --git a/src/libcalamares/python/Logger.h b/src/libcalamares/python/Logger.h new file mode 100644 index 000000000..f49d98833 --- /dev/null +++ b/src/libcalamares/python/Logger.h @@ -0,0 +1,32 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2023 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + * + */ + +#ifndef CALAMARES_PYTHON_LOGGER_H +#define CALAMARES_PYTHON_LOGGER_H + +/** @file + * + * Additional logging helpers for pybind11 types. + */ + +#include "utils/Logger.h" + +#undef slots +#include + +#include + +inline QDebug& +operator<<( QDebug& s, const pybind11::handle & h ) +{ + return s << pybind11::str(h).cast(); +} + +#endif diff --git a/src/libcalamares/python/PythonJob.cpp b/src/libcalamares/python/PythonJob.cpp index 23e8a6ee9..476fb2ef5 100644 --- a/src/libcalamares/python/PythonJob.cpp +++ b/src/libcalamares/python/PythonJob.cpp @@ -8,6 +8,9 @@ */ #include "python/PythonJob.h" +#include "python/Logger.h" +#include "utils/Logger.h" + #include #include #include @@ -18,6 +21,56 @@ namespace py = pybind11; +namespace +{ + +QString +getPrettyNameFromScope( const py::dict& scope ) +{ + static constexpr char key_name[] = "pretty_name"; + + if ( scope.contains( key_name ) ) + { + const py::object func = scope[ key_name ]; + try + { + const auto s = func().cast< std::string >(); + return QString::fromUtf8( s.c_str() ); + } + catch ( const py::cast_error& e ) + { + // Ignore, we will try __doc__ next + } + } + + static constexpr char key_doc[] = "__doc__"; + if ( scope.contains( key_doc ) ) + { + const py::object doc = scope[ key_doc ]; + try + { + const auto s = doc.cast< std::string >(); + auto string = QString::fromUtf8( s.c_str() ).trimmed(); + const auto newline_index = string.indexOf( '\n' ); + if ( newline_index >= 0 ) + { + string.truncate( newline_index ); + return string; + } + // __doc__ is apparently empty, try next fallback + } + catch ( const py::cast_error& e ) + { + // Ignore, try next fallback + } + } + + // No more fallbacks + return QString(); +} + +} // namespace + namespace Calamares { namespace Python @@ -31,9 +84,12 @@ struct Job::Private , configurationMap( configuration ) { } - QString scriptFile; + QString scriptFile; // From the module descriptor QString workingPath; - QVariantMap configurationMap; + + QVariantMap configurationMap; // The module configuration + + QString description; // Obtained from the Python code }; Job::Job( const QString& scriptFile, @@ -55,7 +111,15 @@ Job::prettyName() const QString Job::prettyStatusMessage() const { - return QStringLiteral( "Python Status" ); + // The description is updated when progress is reported, see emitProgress() + if ( m_d->description.isEmpty() ) + { + return tr( "Running %1 operation." ).arg( prettyName() ); + } + else + { + return m_d->description; + } } JobResult @@ -84,6 +148,8 @@ Job::exec() auto scope = py::module_::import( "__main__" ).attr( "__dict__" ); py::eval_file( scriptFI.absoluteFilePath().toUtf8().constData(), scope ); + m_d->description = getPrettyNameFromScope( scope ); + return JobResult::ok(); }