From 0753e6ccde6d8752ef4577193196d78db7f4732a Mon Sep 17 00:00:00 2001 From: Teo Mrnjavac Date: Mon, 21 Jul 2014 17:08:06 +0200 Subject: [PATCH] New GlobalStorage map. With Python API support. --- src/libcalamares/CMakeLists.txt | 1 + src/libcalamares/GlobalStorage.cpp | 122 +++++++++++++++++++++++++++++ src/libcalamares/GlobalStorage.h | 70 +++++++++++++++++ src/libcalamares/JobQueue.cpp | 15 ++++ src/libcalamares/JobQueue.h | 5 ++ src/libcalamares/PythonHelper.cpp | 67 +++++++++++++++- src/libcalamares/PythonHelper.h | 11 ++- src/libcalamares/PythonJob.cpp | 11 +++ 8 files changed, 295 insertions(+), 7 deletions(-) create mode 100644 src/libcalamares/GlobalStorage.cpp create mode 100644 src/libcalamares/GlobalStorage.h diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index f88e34ddc..98be31795 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -11,6 +11,7 @@ configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/../calamares/CalamaresVersion.h.in ${CMAKE_CURRENT_BINARY_DIR}/CalamaresVersion.h ) set( libSources + GlobalStorage.cpp Job.cpp JobQueue.cpp ProcessJob.cpp diff --git a/src/libcalamares/GlobalStorage.cpp b/src/libcalamares/GlobalStorage.cpp new file mode 100644 index 000000000..fd4d10c53 --- /dev/null +++ b/src/libcalamares/GlobalStorage.cpp @@ -0,0 +1,122 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Calamares 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 3 of the License, or + * (at your option) any later version. + * + * Calamares 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 Calamares. If not, see . + */ + +#include "GlobalStorage.h" + +#ifdef WITH_PYTHON +#include "PythonHelper.h" + +#undef slots +#include +#include + +namespace bp = boost::python; +#endif + +namespace Calamares { + +GlobalStorage::GlobalStorage() +{ +} + + +bool +GlobalStorage::contains( const QString& key ) const +{ + return m.contains( key ); +} + + +int +GlobalStorage::count() const +{ + return m.count(); +} + + +void +GlobalStorage::insert( const QString& key, const QVariant& value ) +{ + m.insert( key, value ); +} + + +QStringList +GlobalStorage::keys() const +{ + return m.keys(); +} + + +int +GlobalStorage::remove( const QString& key ) +{ + return m.remove( key ); +} + + +QVariant +GlobalStorage::value( const QString& key ) const +{ + return m.value( key ); +} + +#ifdef WITH_PYTHON + +bool +GlobalStorage::python_contains( const std::string& key ) const +{ + return contains( QString::fromStdString( key ) ); +} + + +void +GlobalStorage::python_insert( const std::string& key, + const bp::object& value ) +{ + insert( QString::fromStdString( key ), + CalamaresPython::variantFromPyObject( value ) ); +} + + +bp::list +GlobalStorage::python_keys() const +{ + bp::list pyList; + foreach( const QString& key, keys() ) + pyList.append( key.toStdString() ); + return pyList; +} + + +int +GlobalStorage::python_remove( const std::string& key ) +{ + return remove( QString::fromStdString( key ) ); +} + + +bp::object +GlobalStorage::python_value( const std::string& key ) const +{ + return CalamaresPython::variantToPyObject( value( QString::fromStdString( key ) ) ); +} + +#endif // WITH_PYTHON + +} // namespace Calamares diff --git a/src/libcalamares/GlobalStorage.h b/src/libcalamares/GlobalStorage.h new file mode 100644 index 000000000..9e72e3c76 --- /dev/null +++ b/src/libcalamares/GlobalStorage.h @@ -0,0 +1,70 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * Calamares 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 3 of the License, or + * (at your option) any later version. + * + * Calamares 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 Calamares. If not, see . + */ + +#ifndef CALAMARES_GLOBALSTORAGE_H +#define CALAMARES_GLOBALSTORAGE_H + +#include "CalamaresConfig.h" + +#include + +#ifdef WITH_PYTHON +namespace boost +{ +namespace python +{ +namespace api +{ +class object; +} +class list; +} +} +#endif + +namespace Calamares +{ + +class GlobalStorage +{ +public: + explicit GlobalStorage(); + + //NOTE: thread safety is guaranteed by JobQueue, which executes jobs one by one. + // If at any time jobs become concurrent, this class must be made thread-safe. + bool contains( const QString& key ) const; + int count() const; + void insert( const QString& key, const QVariant& value ); + QStringList keys() const; + int remove( const QString& key ); + QVariant value( const QString& key ) const; + +#ifdef WITH_PYTHON + bool python_contains( const std::string& key ) const; + void python_insert( const std::string& key, const boost::python::api::object& value ); + boost::python::list python_keys() const; + int python_remove( const std::string& key ); + boost::python::api::object python_value( const std::string& key ) const; +#endif +private: + QVariantMap m; +}; + +} // namespace Calamares + +#endif // CALAMARES_GLOBALSTORAGE_H diff --git a/src/libcalamares/JobQueue.cpp b/src/libcalamares/JobQueue.cpp index e6de2f3df..e40fe5466 100644 --- a/src/libcalamares/JobQueue.cpp +++ b/src/libcalamares/JobQueue.cpp @@ -19,6 +19,7 @@ #include "JobQueue.h" #include "Job.h" +#include "GlobalStorage.h" #include "CalamaresConfig.h" #ifdef WITH_PYTHON @@ -98,15 +99,29 @@ JobQueue::instance() } +GlobalStorage* +JobQueue::globalStorage() const +{ + return m_storage; +} + + JobQueue::JobQueue( QObject* parent ) : QObject( parent ) , m_thread( new JobThread( this ) ) + , m_storage( new GlobalStorage() ) { Q_ASSERT( !s_instance ); s_instance = this; } +JobQueue::~JobQueue() +{ + delete m_storage; +} + + void JobQueue::start() { diff --git a/src/libcalamares/JobQueue.h b/src/libcalamares/JobQueue.h index 2772707be..505fa91e6 100644 --- a/src/libcalamares/JobQueue.h +++ b/src/libcalamares/JobQueue.h @@ -27,6 +27,7 @@ namespace Calamares { +class GlobalStorage; class JobThread; class DLLEXPORT JobQueue : public QObject @@ -34,9 +35,12 @@ class DLLEXPORT JobQueue : public QObject Q_OBJECT public: explicit JobQueue( QObject* parent = nullptr ); + virtual ~JobQueue(); static JobQueue* instance(); + GlobalStorage* globalStorage() const; + void enqueue( const Calamares::job_ptr& job ); void enqueue( const QList< Calamares::job_ptr >& jobs ); void start(); @@ -50,6 +54,7 @@ private: QList< Calamares::job_ptr > m_jobs; JobThread* m_thread; + GlobalStorage* m_storage; }; } diff --git a/src/libcalamares/PythonHelper.cpp b/src/libcalamares/PythonHelper.cpp index 693b61e81..c8ec49a65 100644 --- a/src/libcalamares/PythonHelper.cpp +++ b/src/libcalamares/PythonHelper.cpp @@ -37,13 +37,13 @@ variantToPyObject( const QVariant& variant ) { switch ( variant.type() ) { + case QVariant::Map: + return variantMapToPyDict( variant.toMap() ); + case QVariant::List: case QVariant::StringList: return variantListToPyList( variant.toList() ); - case QVariant::Map: - return variantMapToPyDict( variant.toMap() ); - case QVariant::Int: return bp::object( variant.toInt() ); @@ -51,7 +51,6 @@ variantToPyObject( const QVariant& variant ) return bp::object( variant.toDouble() ); case QVariant::String: - case QVariant::Char: return bp::object( variant.toString().toStdString() ); default: @@ -60,6 +59,30 @@ variantToPyObject( const QVariant& variant ) } +QVariant +variantFromPyObject( const boost::python::object& pyObject ) +{ + std::string pyType = bp::extract< std::string >( pyObject.attr( "__class__" ).attr( "__name__" ) ); + if ( pyType == "dict" ) + return variantMapFromPyDict( bp::extract< bp::dict >( pyObject ) ); + + else if ( pyType == "list" ) + return variantListFromPyList( bp::extract< bp::list >( pyObject ) ); + + else if ( pyType == "int" ) + return QVariant( bp::extract< int >( pyObject ) ); + + else if ( pyType == "float" ) + return QVariant( bp::extract< double >( pyObject ) ); + + else if ( pyType == "str" ) + return QVariant( QString::fromStdString( bp::extract< std::string >( pyObject ) ) ); + + else + return QVariant(); +} + + boost::python::list variantListToPyList( const QVariantList& variantList ) { @@ -72,6 +95,18 @@ variantListToPyList( const QVariantList& variantList ) } +QVariantList +variantListFromPyList( const boost::python::list& pyList ) +{ + QVariantList list; + for ( int i = 0; i < bp::len( pyList ); ++i ) + { + list.append( variantFromPyObject( pyList[ i ] ) ); + } + return list; +} + + boost::python::dict variantMapToPyDict( const QVariantMap& variantMap ) { @@ -84,6 +119,30 @@ variantMapToPyDict( const QVariantMap& variantMap ) } +QVariantMap +variantMapFromPyDict( const boost::python::dict& pyDict ) +{ + QVariantMap map; + bp::list keys = pyDict.keys(); + for ( int i = 0; i < bp::len( keys ); ++i ) + { + bp::extract< std::string > extracted_key( keys[ i ] ); + if ( !extracted_key.check() ) + { + cDebug() << "Key invalid, map might be incomplete."; + continue; + } + + std::string key = extracted_key; + + bp::object obj = pyDict[ key ]; + + map.insert( QString::fromStdString( key ), variantFromPyObject( obj ) ); + } + return map; +} + + Helper* Helper::s_instance = nullptr; Helper::Helper( QObject* parent ) diff --git a/src/libcalamares/PythonHelper.h b/src/libcalamares/PythonHelper.h index 3049eef59..631e596f5 100644 --- a/src/libcalamares/PythonHelper.h +++ b/src/libcalamares/PythonHelper.h @@ -30,9 +30,14 @@ namespace CalamaresPython { -boost::python::object variantToPyObject( const QVariant& variant ); -boost::python::list variantListToPyList( const QVariantList& variantList ); -boost::python::dict variantMapToPyDict( const QVariantMap& variantMap ); +boost::python::object variantToPyObject( const QVariant& variant ); +QVariant variantFromPyObject( const boost::python::object& pyObject ); + +boost::python::list variantListToPyList( const QVariantList& variantList ); +QVariantList variantListFromPyList( const boost::python::list& pyList ); + +boost::python::dict variantMapToPyDict( const QVariantMap& variantMap ); +QVariantMap variantMapFromPyDict( const boost::python::dict& pyDict ); class Helper : public QObject diff --git a/src/libcalamares/PythonJob.cpp b/src/libcalamares/PythonJob.cpp index 1c45b0033..9be5c7b93 100644 --- a/src/libcalamares/PythonJob.cpp +++ b/src/libcalamares/PythonJob.cpp @@ -20,6 +20,8 @@ #include "PythonHelper.h" #include "utils/Logger.h" +#include "GlobalStorage.h" +#include "JobQueue.h" #include @@ -44,6 +46,14 @@ BOOST_PYTHON_MODULE( libcalamares ) .def_readonly( "prettyName", &CalamaresPython::PythonJobInterface::prettyName ) .def_readonly( "workingPath", &CalamaresPython::PythonJobInterface::workingPath ) .def_readonly( "configuration", &CalamaresPython::PythonJobInterface::configuration ); + + bp::class_< Calamares::GlobalStorage >( "GlobalStorage", bp::init<>() ) + .def( "contains", &Calamares::GlobalStorage::python_contains ) + .def( "count", &Calamares::GlobalStorage::count ) + .def( "insert", &Calamares::GlobalStorage::python_insert ) + .def( "keys", &Calamares::GlobalStorage::python_keys ) + .def( "remove", &Calamares::GlobalStorage::python_remove ) + .def( "value", &Calamares::GlobalStorage::python_value ); } @@ -109,6 +119,7 @@ PythonJob::exec() bp::dict calamaresNamespace = bp::extract< bp::dict >( calamaresModule.attr( "__dict__" ) ); calamaresNamespace[ "job" ] = CalamaresPython::PythonJobInterface( this ); + calamaresNamespace[ "global_storage" ] = JobQueue::instance()->globalStorage(); bp::object result = bp::exec_file( scriptFI.absoluteFilePath().toLocal8Bit().data(), scriptNamespace,