calamares/src/libcalamares/PythonJobApi.cpp

298 lines
8.8 KiB
C++
Raw Normal View History

/* === This file is part of Calamares - <https://calamares.io> ===
*
[libcalamares] Update SPDX identifiers. Update CppJob.h Update CalamaresConfig.h.in Update DllMacro.h Update GlobalStorage.cpp Update GlobalStorage.h Update Job.cpp Update Job.h Update JobExample.cpp Update JobExample.h Update JobQueue.cpp Update CalamaresConfig.h.in Update CppJob.cpp Update CppJob.h Update DllMacro.h Update GlobalStorage.cpp Update GlobalStorage.h Update Job.cpp Update Job.h Update JobExample.cpp Update JobExample.h Update JobQueue.h Update ProcessJob.cpp Update ProcessJob.h Update PythonHelper.cpp Update PythonJob.cpp Update PythonJob.h Update PythonHelper.h Update PythonJobApi.cpp Update PythonJobApi.h Update Settings.cpp Update Settings.h Update GeoIPJSON.cpp Update GeoIPJSON.h Update GeoIPTests.cpp Update GeoIPTests.h Update GeoIPXML.cpp Update GeoIPXML.h Update Handler.cpp Update Handler.h Update Interface.cpp Update Interface.h Update test_geoip.cpp Update CountryData_p.cpp Update Label.cpp Update Label.h Update LabelModel.cpp Update LabelModel.h Update CountryData_p.cpp Update CountryData_p.cpp Update Lookup.cpp Update Lookup.h Update Tests.cpp Update Tests.h Update TimeZone.cpp Update TimeZone.h Update TranslatableConfiguration.cpp Update TranslatableConfiguration.h Update ZoneData_p.cxxtr Update cldr-extractor.py Update zone-extractor.py Update Actions.h Update Actions.h Update Descriptor.h Update InstanceKey.cpp Update Module.cpp Update Module.h Update Requirement.cpp Update RequirementsChecker.h Update RequirementsModel.cpp Update RequirementsModel.h Update Tests.cpp Update Manager.cpp Update Manager.h Update Tests.cpp Update FileSystem.cpp Update FileSystem.h Update KPMManager.cpp Update KPMManager.h Update KPMTests.cpp Update FileSystem.cpp Update FileSystem.cpp Update FileSystem.h Update KPMManager.cpp Update KPMManager.h Update Mount.cpp Update Mount.h Update PartitionIterator.cpp Update PartitionIterator.h Update PartitionIterator.h Update PartitionQuery.cpp Update PartitionQuery.h Update PartitionSize.cpp Update PartitionSize.h Update Sync.cpp Update Sync.h Update Tests.cpp Update Tests.h Update BoostPython.h Update CalamaresUtilsSystem.cpp Update CalamaresUtilsSystem.h Update CommandList.cpp Update CommandList.h Update Dirs.cpp Update Dirs.h Update Entropy.cpp Update Entropy.h Update Entropy.cpp Update Logger.cpp Update Logger.h Update NamedEnum.h Update NamedSuffix.h Update PluginFactory.cpp Update PluginFactory.h Update RAII.h Update RAII.h Update Retranslator.cpp Update Retranslator.h Update String.cpp Update String.h Update TestPaths.cpp Update Tests.cpp Update Tests.h Update UMask.cpp Update UMask.h Update Units.h Update Variant.cpp Update Variant.h Update Yaml.cpp Update Yaml.h Update moc-warnings.h
2020-05-30 16:15:03 +02:00
* SPDX-FileCopyrightText: 2014-2016 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2017-2020 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
[libcalamares] Update SPDX identifiers. Update CppJob.h Update CalamaresConfig.h.in Update DllMacro.h Update GlobalStorage.cpp Update GlobalStorage.h Update Job.cpp Update Job.h Update JobExample.cpp Update JobExample.h Update JobQueue.cpp Update CalamaresConfig.h.in Update CppJob.cpp Update CppJob.h Update DllMacro.h Update GlobalStorage.cpp Update GlobalStorage.h Update Job.cpp Update Job.h Update JobExample.cpp Update JobExample.h Update JobQueue.h Update ProcessJob.cpp Update ProcessJob.h Update PythonHelper.cpp Update PythonJob.cpp Update PythonJob.h Update PythonHelper.h Update PythonJobApi.cpp Update PythonJobApi.h Update Settings.cpp Update Settings.h Update GeoIPJSON.cpp Update GeoIPJSON.h Update GeoIPTests.cpp Update GeoIPTests.h Update GeoIPXML.cpp Update GeoIPXML.h Update Handler.cpp Update Handler.h Update Interface.cpp Update Interface.h Update test_geoip.cpp Update CountryData_p.cpp Update Label.cpp Update Label.h Update LabelModel.cpp Update LabelModel.h Update CountryData_p.cpp Update CountryData_p.cpp Update Lookup.cpp Update Lookup.h Update Tests.cpp Update Tests.h Update TimeZone.cpp Update TimeZone.h Update TranslatableConfiguration.cpp Update TranslatableConfiguration.h Update ZoneData_p.cxxtr Update cldr-extractor.py Update zone-extractor.py Update Actions.h Update Actions.h Update Descriptor.h Update InstanceKey.cpp Update Module.cpp Update Module.h Update Requirement.cpp Update RequirementsChecker.h Update RequirementsModel.cpp Update RequirementsModel.h Update Tests.cpp Update Manager.cpp Update Manager.h Update Tests.cpp Update FileSystem.cpp Update FileSystem.h Update KPMManager.cpp Update KPMManager.h Update KPMTests.cpp Update FileSystem.cpp Update FileSystem.cpp Update FileSystem.h Update KPMManager.cpp Update KPMManager.h Update Mount.cpp Update Mount.h Update PartitionIterator.cpp Update PartitionIterator.h Update PartitionIterator.h Update PartitionQuery.cpp Update PartitionQuery.h Update PartitionSize.cpp Update PartitionSize.h Update Sync.cpp Update Sync.h Update Tests.cpp Update Tests.h Update BoostPython.h Update CalamaresUtilsSystem.cpp Update CalamaresUtilsSystem.h Update CommandList.cpp Update CommandList.h Update Dirs.cpp Update Dirs.h Update Entropy.cpp Update Entropy.h Update Entropy.cpp Update Logger.cpp Update Logger.h Update NamedEnum.h Update NamedSuffix.h Update PluginFactory.cpp Update PluginFactory.h Update RAII.h Update RAII.h Update Retranslator.cpp Update Retranslator.h Update String.cpp Update String.h Update TestPaths.cpp Update Tests.cpp Update Tests.h Update UMask.cpp Update UMask.h Update Units.h Update Variant.cpp Update Variant.h Update Yaml.cpp Update Yaml.h Update moc-warnings.h
2020-05-30 16:15:03 +02:00
*
*/
#include "PythonJobApi.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "PythonHelper.h"
#include "partition/Mount.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/Logger.h"
#include "utils/RAII.h"
#include "utils/String.h"
#include <QCoreApplication>
#include <QDir>
#include <QStandardPaths>
namespace bp = boost::python;
static int
_handle_check_target_env_call_error( const CalamaresUtils::ProcessResult& ec, const QString& cmd )
{
if ( !ec.first )
{
return ec.first;
}
QString raise = QString( "import subprocess\n"
"e = subprocess.CalledProcessError(%1,\"%2\")\n" )
.arg( ec.first )
.arg( cmd );
if ( !ec.second.isEmpty() )
{
raise.append( QStringLiteral( "e.output = \"\"\"%1\"\"\"\n" ).arg( ec.second ) );
}
raise.append( "raise e" );
bp::exec( raise.toStdString().c_str() );
bp::throw_error_already_set();
return ec.first;
}
2014-07-18 11:59:12 +02:00
namespace CalamaresPython
{
int
mount( const std::string& device_path,
const std::string& mount_point,
const std::string& filesystem_name,
const std::string& options )
{
return CalamaresUtils::Partition::mount( QString::fromStdString( device_path ),
QString::fromStdString( mount_point ),
QString::fromStdString( filesystem_name ),
QString::fromStdString( options ) );
}
static inline QStringList
_bp_list_to_qstringlist( const bp::list& args )
{
QStringList list;
for ( int i = 0; i < bp::len( args ); ++i )
{
list.append( QString::fromStdString( bp::extract< std::string >( args[ i ] ) ) );
}
return list;
}
static inline CalamaresUtils::ProcessResult
_target_env_command( const QStringList& args, const std::string& stdin, int timeout )
{
// Since Python doesn't give us the type system for distinguishing
// seconds from other integral types, massage to seconds here.
return CalamaresUtils::System::instance()->targetEnvCommand(
args, QString(), QString::fromStdString( stdin ), std::chrono::seconds( timeout ) );
}
int
target_env_call( const std::string& command, const std::string& stdin, int timeout )
{
return _target_env_command( QStringList { QString::fromStdString( command ) }, stdin, timeout ).first;
}
int
target_env_call( const bp::list& args, const std::string& stdin, int timeout )
{
return _target_env_command( _bp_list_to_qstringlist( args ), stdin, timeout ).first;
}
2014-07-28 18:55:01 +02:00
int
check_target_env_call( const std::string& command, const std::string& stdin, int timeout )
{
auto ec = _target_env_command( QStringList { QString::fromStdString( command ) }, stdin, timeout );
return _handle_check_target_env_call_error( ec, QString::fromStdString( command ) );
}
int
check_target_env_call( const bp::list& args, const std::string& stdin, int timeout )
{
auto ec = _target_env_command( _bp_list_to_qstringlist( args ), stdin, timeout );
if ( !ec.first )
{
return ec.first;
}
QStringList failedCmdList = _bp_list_to_qstringlist( args );
return _handle_check_target_env_call_error( ec, failedCmdList.join( ' ' ) );
}
std::string
check_target_env_output( const std::string& command, const std::string& stdin, int timeout )
{
auto ec = _target_env_command( QStringList { QString::fromStdString( command ) }, stdin, timeout );
_handle_check_target_env_call_error( ec, QString::fromStdString( command ) );
return ec.second.toStdString();
}
std::string
check_target_env_output( const bp::list& args, const std::string& stdin, int timeout )
{
QStringList list = _bp_list_to_qstringlist( args );
auto ec = _target_env_command( list, stdin, timeout );
_handle_check_target_env_call_error( ec, list.join( ' ' ) );
return ec.second.toStdString();
}
static const char output_prefix[] = "[PYTHON JOB]:";
2014-07-28 18:55:01 +02:00
void
debug( const std::string& s )
{
Logger::CDebug( Logger::LOGDEBUG ) << output_prefix << QString::fromStdString( s );
2014-07-28 18:55:01 +02:00
}
void
warning( const std::string& s )
{
Logger::CDebug( Logger::LOGWARNING ) << output_prefix << QString::fromStdString( s );
}
2014-07-28 18:55:01 +02:00
2014-07-23 12:54:53 +02:00
PythonJobInterface::PythonJobInterface( Calamares::PythonJob* parent )
: m_parent( parent )
{
auto moduleDir = QDir( m_parent->m_workingPath );
moduleName = moduleDir.dirName().toStdString();
prettyName = m_parent->prettyName().toStdString();
workingPath = m_parent->m_workingPath.toStdString();
configuration = CalamaresPython::variantMapToPyDict( m_parent->m_configurationMap );
}
2014-07-22 18:05:58 +02:00
void
2014-07-23 12:54:53 +02:00
PythonJobInterface::setprogress( qreal progress )
2014-07-22 18:05:58 +02:00
{
2020-03-05 03:40:40 +01:00
if ( progress >= 0.0 && progress <= 1.0 )
{
2014-07-22 18:05:58 +02:00
m_parent->emitProgress( progress );
}
2014-07-22 18:05:58 +02:00
}
int
target_env_process_output( const boost::python::list& args, boost::python::object& callback )
{
cWarning() << "target env" << _bp_list_to_qstringlist( args );
callback( std::string( "derp" ) );
return 0;
}
std::string
obscure( const std::string& string )
{
return CalamaresUtils::obscure( QString::fromStdString( string ) ).toStdString();
}
static QStringList
_gettext_languages()
{
QStringList languages;
// There are two ways that Python jobs can be initialised:
// - through JobQueue, in which case that has an instance which holds
// a GlobalStorage object, or
// - through the Python test-script, which initialises its
// own GlobalStoragePythonWrapper, which then holds a
// GlobalStorage object for all of Python.
Calamares::JobQueue* jq = Calamares::JobQueue::instance();
Calamares::GlobalStorage* gs
= jq ? jq->globalStorage() : CalamaresPython::GlobalStoragePythonWrapper::globalStorageInstance();
QVariant localeConf_ = gs->value( "localeConf" );
if ( localeConf_.canConvert< QVariantMap >() )
{
QVariant lang_ = localeConf_.value< QVariantMap >()[ "LANG" ];
if ( lang_.canConvert< QString >() )
{
QString lang = lang_.value< QString >();
2017-08-21 18:36:04 +02:00
languages.append( lang );
if ( lang.indexOf( '.' ) > 0 )
{
lang.truncate( lang.indexOf( '.' ) );
2017-08-21 18:36:04 +02:00
languages.append( lang );
}
2017-08-21 18:36:04 +02:00
if ( lang.indexOf( '_' ) > 0 )
{
lang.truncate( lang.indexOf( '_' ) );
2017-08-21 18:36:04 +02:00
languages.append( lang );
}
}
}
return languages;
}
bp::list
gettext_languages()
{
bp::list pyList;
2017-08-21 18:36:04 +02:00
for ( auto lang : _gettext_languages() )
{
pyList.append( lang.toStdString() );
}
return pyList;
}
static void
2017-08-21 18:36:04 +02:00
_add_localedirs( QStringList& pathList, const QString& candidate )
{
2017-08-21 18:36:04 +02:00
if ( !candidate.isEmpty() && !pathList.contains( candidate ) )
{
2017-08-21 18:36:04 +02:00
pathList.prepend( candidate );
if ( QDir( candidate ).cd( "lang" ) )
{
2017-08-21 18:36:04 +02:00
pathList.prepend( candidate + "/lang" );
}
}
}
bp::object
gettext_path()
{
// Going to log informatively just once
static bool first_time = true;
cScopedAssignment( &first_time, false );
// TODO: distinguish between -d runs and normal runs
// TODO: can we detect DESTDIR-installs?
QStringList candidatePaths
= QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, "locale", QStandardPaths::LocateDirectory );
QString extra = QCoreApplication::applicationDirPath();
_add_localedirs( candidatePaths, extra ); // Often /usr/local/bin
if ( !extra.isEmpty() )
{
2017-08-21 18:36:04 +02:00
QDir d( extra );
if ( d.cd( "../share/locale" ) ) // Often /usr/local/bin/../share/locale -> /usr/local/share/locale
{
2017-08-21 18:36:04 +02:00
_add_localedirs( candidatePaths, d.canonicalPath() );
}
}
_add_localedirs( candidatePaths, QDir().canonicalPath() ); // .
if ( first_time )
{
cDebug() << "Determining gettext path from" << candidatePaths;
}
QStringList candidateLanguages = _gettext_languages();
for ( const auto& lang : candidateLanguages )
{
2017-08-21 18:36:04 +02:00
for ( auto localedir : candidatePaths )
{
2017-08-21 18:36:04 +02:00
QDir ldir( localedir );
if ( ldir.cd( lang ) )
{
Logger::CDebug( Logger::LOGDEBUG )
<< output_prefix << "Found gettext" << lang << "in" << ldir.canonicalPath();
return bp::object( localedir.toStdString() );
}
}
}
cWarning() << "No translation found for languages" << candidateLanguages;
return bp::object(); // None
}
} // namespace CalamaresPython