New GlobalStorage map. With Python API support.

This commit is contained in:
Teo Mrnjavac 2014-07-21 17:08:06 +02:00
parent 4c88603872
commit 0753e6ccde
8 changed files with 295 additions and 7 deletions

View File

@ -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

View File

@ -0,0 +1,122 @@
/* === This file is part of Calamares - <http://github.com/calamares> ===
*
* Copyright 2014, Teo Mrnjavac <teo@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "GlobalStorage.h"
#ifdef WITH_PYTHON
#include "PythonHelper.h"
#undef slots
#include <boost/python/list.hpp>
#include <boost/python/str.hpp>
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

View File

@ -0,0 +1,70 @@
/* === This file is part of Calamares - <http://github.com/calamares> ===
*
* Copyright 2014, Teo Mrnjavac <teo@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef CALAMARES_GLOBALSTORAGE_H
#define CALAMARES_GLOBALSTORAGE_H
#include "CalamaresConfig.h"
#include <QVariantMap>
#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

View File

@ -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()
{

View File

@ -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;
};
}

View File

@ -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 )

View File

@ -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

View File

@ -20,6 +20,8 @@
#include "PythonHelper.h"
#include "utils/Logger.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include <QDir>
@ -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,