diff --git a/CMakeLists.txt b/CMakeLists.txt index 763c5843c..a6a0edd5d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ endif() ### ### Calamares application info ### -set( CALAMARES_ORGANIZATION_NAME "The Calamares Team" ) +set( CALAMARES_ORGANIZATION_NAME "Calamares" ) set( CALAMARES_ORGANIZATION_DOMAIN "github.com/calamares" ) set( CALAMARES_APPLICATION_NAME "Calamares" ) set( CALAMARES_DESCRIPTION_SUMMARY "The distribution-independent installer framework" ) @@ -108,7 +108,7 @@ file( COPY CalamaresAddLibrary.cmake DESTINATION "${PROJECT_BINARY_DIR}" ) file( COPY CalamaresAddModuleSubdirectory.cmake DESTINATION "${PROJECT_BINARY_DIR}" ) file( COPY CalamaresAddPlugin.cmake DESTINATION "${PROJECT_BINARY_DIR}" ) -set( CALAMARES_LIBRARIES calamareslib ) +set( CALAMARES_LIBRARIES calamares ) add_subdirectory( src ) add_subdirectory( tests ) @@ -118,8 +118,8 @@ macro_display_feature_log() # Add all targets to the build-tree export set set( CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Calamares" CACHE PATH "Installation directory for CMake files" ) set( CMAKE_INSTALL_FULL_CMAKEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_CMAKEDIR}" ) -export(TARGETS calamareslib - FILE "${PROJECT_BINARY_DIR}/CalamaresLibraryDepends.cmake") +export( TARGETS calamares + FILE "${PROJECT_BINARY_DIR}/CalamaresLibraryDepends.cmake" ) # Export the package for use from the build-tree # (this registers the build-tree with a global CMake-registry) diff --git a/CalamaresConfig.cmake.in b/CalamaresConfig.cmake.in index d72596928..5d1b0635f 100644 --- a/CalamaresConfig.cmake.in +++ b/CalamaresConfig.cmake.in @@ -17,5 +17,5 @@ endif() include("${CALAMARES_CMAKE_DIR}/CalamaresLibraryDepends.cmake") # These are IMPORTED targets created by CalamaresLibraryDepends.cmake -set(CALAMARES_LIBRARIES calamareslib) +set(CALAMARES_LIBRARIES calamares) set(CALAMARES_USE_FILE "${CALAMARES_CMAKE_DIR}/CalamaresUse.cmake") diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index 07ca6c12f..5cca7fc74 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -1,4 +1,4 @@ -project( calamareslib ) +project( libcalamares ) add_definitions( ${QT_DEFINITIONS} ) add_definitions( -DQT_SHARED ) @@ -36,6 +36,7 @@ if( WITH_PYTHON ) set( libSources ${libSources} PythonJob.cpp + PythonJobApi.cpp PythonJobHelper.cpp ) @@ -53,19 +54,18 @@ if( WITH_PYTHON ) endif() -add_library( calamareslib SHARED ${libSources} ) -set_target_properties( calamareslib +add_library( calamares SHARED ${libSources} ) +set_target_properties( calamares PROPERTIES AUTOMOC TRUE VERSION ${CALAMARES_VERSION_SHORT} SOVERSION ${CALAMARES_VERSION_SHORT} - OUTPUT_NAME "calamares" ) -qt5_use_modules( calamareslib Core ) +qt5_use_modules( calamares Core ) -target_link_libraries( calamareslib +target_link_libraries( calamares LINK_PRIVATE # internal deps, if any ${OPTIONAL_PRIVATE_LIBRARIES} @@ -75,7 +75,7 @@ target_link_libraries( calamareslib Qt5::Core ) -install( TARGETS calamareslib +install( TARGETS calamares EXPORT CalamaresLibraryDepends RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} diff --git a/src/libcalamares/JobQueue.cpp b/src/libcalamares/JobQueue.cpp index e7b5e2398..331b68613 100644 --- a/src/libcalamares/JobQueue.cpp +++ b/src/libcalamares/JobQueue.cpp @@ -38,7 +38,7 @@ public: , m_queue( queue ) { #ifdef WITH_PYTHON - new PythonJobHelper( this ); + new CalamaresPrivate::PythonJobHelper( this ); #endif } diff --git a/src/libcalamares/PythonJob.cpp b/src/libcalamares/PythonJob.cpp index 0ede795ea..852923b4a 100644 --- a/src/libcalamares/PythonJob.cpp +++ b/src/libcalamares/PythonJob.cpp @@ -26,8 +26,26 @@ #undef slots #include +#include "PythonJobApi.h" + namespace bp = boost::python; + + +BOOST_PYTHON_MODULE( libcalamares ) +{ + bp::scope().attr( "ORGANIZATION_NAME" ) = CALAMARES_ORGANIZATION_NAME; + bp::scope().attr( "ORGANIZATION_DOMAIN" ) = CALAMARES_ORGANIZATION_DOMAIN; + bp::scope().attr( "APPLICATION_NAME" ) = CALAMARES_APPLICATION_NAME; + bp::scope().attr( "VERSION" ) = CALAMARES_VERSION; + bp::scope().attr( "VERSION_SHORT" ) = CALAMARES_VERSION_SHORT; + + bp::class_< CalamaresPrivate::PythonJobInterface >( "job", bp::init< const Calamares::PythonJob* >() ) + .def( "prettyName", &CalamaresPrivate::PythonJobInterface::prettyName ) + .def( "workingPath", &CalamaresPrivate::PythonJobInterface::workingPath ); +} + + namespace Calamares { @@ -84,6 +102,11 @@ PythonJob::exec() { bp::object scriptNamespace = helper()->createCleanNamespace(); + bp::object calamaresModule = bp::import( "libcalamares" ); + bp::dict calamaresNamespace = bp::extract< bp::dict >( calamaresModule.attr( "__dict__" ) ); + + calamaresNamespace[ "job" ] = CalamaresPrivate::PythonJobInterface( this ); + bp::object result = bp::exec_file( scriptFI.absoluteFilePath().toLocal8Bit().data(), scriptNamespace, scriptNamespace ); @@ -94,19 +117,28 @@ PythonJob::exec() cDebug() << "Python job" << prettyName() << "finished with message" << message; } - catch ( bp::error_already_set e ) + catch ( bp::error_already_set ) { - return JobResult::error( tr( "Boost.Python error" ) ); + QString msg; + if ( PyErr_Occurred() ) + { + msg = helper()->handleLastError(); + } + bp::handle_exception(); + PyErr_Clear(); + return JobResult::error( tr( "Boost.Python error" ), + msg ); } return JobResult::ok(); } -PythonJobHelper* +CalamaresPrivate::PythonJobHelper* PythonJob::helper() { - return PythonJobHelper::s_instance; + return CalamaresPrivate::PythonJobHelper::s_instance; + } diff --git a/src/libcalamares/PythonJob.h b/src/libcalamares/PythonJob.h index f4f437697..63312eee4 100644 --- a/src/libcalamares/PythonJob.h +++ b/src/libcalamares/PythonJob.h @@ -21,9 +21,13 @@ #include "Job.h" -namespace Calamares { - +namespace CalamaresPrivate +{ +class PythonJobInterface; class PythonJobHelper; +} + +namespace Calamares { class PythonJob : public Job { @@ -38,8 +42,9 @@ public: JobResult exec() override; private: - friend class PythonJobHelper; - PythonJobHelper* helper(); + friend class CalamaresPrivate::PythonJobHelper; + friend class CalamaresPrivate::PythonJobInterface; + CalamaresPrivate::PythonJobHelper* helper(); QString m_scriptFile; QString m_workingPath; }; diff --git a/src/libcalamares/PythonJobApi.cpp b/src/libcalamares/PythonJobApi.cpp new file mode 100644 index 000000000..31230c626 --- /dev/null +++ b/src/libcalamares/PythonJobApi.cpp @@ -0,0 +1,42 @@ +/* === 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 "PythonJobApi.h" + + +namespace CalamaresPrivate +{ + +PythonJobInterface::PythonJobInterface( const Calamares::PythonJob* parent ) + : m_parent( parent ) +{} + + +std::string +PythonJobInterface::prettyName() const +{ + return m_parent->prettyName().toStdString(); +} + +std::string +PythonJobInterface::workingPath() const +{ + return m_parent->m_workingPath.toStdString(); +} + +} diff --git a/src/libcalamares/PythonJobApi.h b/src/libcalamares/PythonJobApi.h new file mode 100644 index 000000000..1da7ecd9e --- /dev/null +++ b/src/libcalamares/PythonJobApi.h @@ -0,0 +1,44 @@ +/* === 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 PYTHONJOBAPI_H +#define PYTHONJOBAPI_H + +#include "CalamaresVersion.h" + +#include "PythonJob.h" + +namespace CalamaresPrivate +{ + +class PythonJobInterface +{ +public: + explicit PythonJobInterface( const Calamares::PythonJob* parent ); + + std::string prettyName() const; + + std::string workingPath() const; + +private: + const Calamares::PythonJob* m_parent; +}; + +} + +#endif // PYTHONJOBAPI_H diff --git a/src/libcalamares/PythonJobHelper.cpp b/src/libcalamares/PythonJobHelper.cpp index 98521b85a..9a2938918 100644 --- a/src/libcalamares/PythonJobHelper.cpp +++ b/src/libcalamares/PythonJobHelper.cpp @@ -18,13 +18,18 @@ #include "PythonJobHelper.h" +#include "utils/CalamaresUtils.h" #include "utils/Logger.h" +#include +#include + +#undef slots #include namespace bp = boost::python; -namespace Calamares { +namespace CalamaresPrivate { PythonJobHelper* PythonJobHelper::s_instance = nullptr; @@ -38,6 +43,34 @@ PythonJobHelper::PythonJobHelper( QObject* parent ) m_mainModule = bp::import( "__main__" ); m_mainNamespace = m_mainModule.attr( "__dict__" ); + + // If we're running from the build dir + QFileInfo fi( QDir::current().absoluteFilePath( "libcalamares.so" ) ); + if ( fi.exists() && fi.isReadable() ) + { + m_pythonPaths.append( fi.dir().absolutePath() ); + } + + QDir calaPythonPath( CalamaresUtils::systemLibDir().absolutePath() + + QDir::separator() + "calamares" ); + if ( calaPythonPath.exists() && + calaPythonPath.isReadable() ) + { + QFileInfo fi( calaPythonPath.absoluteFilePath( "libcalamares.so" ) ); + if ( fi.exists() && fi.isReadable() ) + { + m_pythonPaths.append( fi.dir().absolutePath() ); + } + } + + + bp::object sys = bp::import( "sys" ); + + foreach ( QString path, m_pythonPaths ) + { + bp::str dir = path.toLocal8Bit().data(); + sys.attr( "path" ).attr( "append" )( dir ); + } } else { @@ -64,4 +97,27 @@ PythonJobHelper::createCleanNamespace() } +QString +PythonJobHelper::handleLastError() +{ + using namespace boost::python; + using namespace boost; + + PyObject *exc,*val,*tb; + object formatted_list, formatted; + PyErr_Fetch(&exc,&val,&tb); + handle<> hexc(exc),hval(allow_null(val)),htb(allow_null(tb)); + object traceback(import("traceback")); + if (!tb) { + object format_exception_only(traceback.attr("format_exception_only")); + formatted_list = format_exception_only(hexc,hval); + } else { + object format_exception(traceback.attr("format_exception")); + formatted_list = format_exception(hexc,hval,htb); + } + formatted = str("\n").join(formatted_list); + return QString::fromStdString( extract(formatted) ); +} + + } // namespace Calamares diff --git a/src/libcalamares/PythonJobHelper.h b/src/libcalamares/PythonJobHelper.h index 277bca10a..e5c17856b 100644 --- a/src/libcalamares/PythonJobHelper.h +++ b/src/libcalamares/PythonJobHelper.h @@ -21,10 +21,12 @@ #include "PythonJob.h" +#include + #undef slots #include -namespace Calamares { +namespace CalamaresPrivate { class PythonJobHelper : public QObject { @@ -35,12 +37,16 @@ public: boost::python::object createCleanNamespace(); + QString handleLastError(); + private: - friend PythonJobHelper* PythonJob::helper(); + friend PythonJobHelper* Calamares::PythonJob::helper(); static PythonJobHelper* s_instance; boost::python::object m_mainModule; boost::python::object m_mainNamespace; + + QStringList m_pythonPaths; }; } // namespace Calamares diff --git a/src/modules/dummypython/main.py b/src/modules/dummypython/main.py index 34c3e7451..eae318f0b 100644 --- a/src/modules/dummypython/main.py +++ b/src/modules/dummypython/main.py @@ -16,9 +16,16 @@ # You should have received a copy of the GNU General Public License # along with Calamares. If not, see . +import sys +import libcalamares import os from time import gmtime, strftime def calamares_main(): os.system( "/bin/sh -c \"touch ~/calamares-dummypython\"" ) - return strftime( "%Y-%m-%d %H:%M:%S", gmtime() ) + accumulator = strftime( "%Y-%m-%d %H:%M:%S", gmtime() ) + "\n" + accumulator += "Calamares version: " + libcalamares.VERSION_SHORT + "\n" + accumulator += "This job's name: " + libcalamares.job.prettyName() + "\n" + accumulator += "This job's path: " + libcalamares.job.workingPath() + "\n" + return accumulator +