From 403728b8ad89cf2cf7d826e46603e953905c766e Mon Sep 17 00:00:00 2001 From: Christopher Lam Date: Fri, 27 Oct 2023 18:11:07 +0800 Subject: [PATCH] [gnucash-commands.cpp] don't use m_, extract python funcs, modify argv now argv will have either datafile or "" -- this is accepted by python and guile alike --- gnucash/gnucash-commands.cpp | 117 ++++++++++++++++++----------------- 1 file changed, 61 insertions(+), 56 deletions(-) diff --git a/gnucash/gnucash-commands.cpp b/gnucash/gnucash-commands.cpp index 28c49c4bc5b..8776a377f76 100644 --- a/gnucash/gnucash-commands.cpp +++ b/gnucash/gnucash-commands.cpp @@ -577,81 +577,84 @@ run_guile_cli (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **ar } +#ifdef HAVE_PYTHON_H +static void +python_cleanup (PyConfig& config, PyStatus& status) +{ + if (qof_book_session_not_saved (gnc_get_current_book())) + std::cerr << _("Book is readonly. Unsaved changes will be lost.") << std::endl; + gnc_clear_current_session (); + + PyConfig_Clear(&config); + if (PyStatus_IsExit(status)) + gnc_shutdown_cli (status.exitcode); + + Py_ExitStatusException(status); +} + static void run_python_cli (int argc, char **argv, scripting_args* args) { -#ifdef HAVE_PYTHON_H PyConfig config; PyConfig_InitPythonConfig(&config); PyStatus status = PyConfig_SetBytesArgv(&config, argc, argv); - try - { - if (PyStatus_Exception(status)) - throw; + if (PyStatus_Exception(status)) + python_cleanup (config, status); - status = Py_InitializeFromConfig(&config); - if (PyStatus_Exception(status)) - throw; + status = Py_InitializeFromConfig(&config); + if (PyStatus_Exception(status)) + python_cleanup (config, status); - PyConfig_Clear(&config); + PyConfig_Clear(&config); - if (args->script) - { - auto script_filename = args->script->c_str(); - PINFO ("Running python script %s...", script_filename); - auto fp = fopen (script_filename, "r"); - if (fp) - PyRun_SimpleFileEx (fp, script_filename, 1); - else - std::cerr << bl::format (_("Unable to load Python script {1}")) % script_filename - << std::endl; - } - if (args->interactive) + if (args->script) + { + auto script_filename = args->script->c_str(); + PINFO ("Running python script %s...", script_filename); + auto fp = fopen (script_filename, "rb"); + if (!fp) + std::cerr << bl::format (_("Unable to load Python script {1}")) % script_filename + << std::endl; + else if (PyRun_SimpleFileEx (fp, script_filename, 1) != 0) { - std::cout << _("Welcome to Gnucash Interactive Python Session") << std::endl; - PyRun_InteractiveLoop (stdin, "foo"); + std::cerr << bl::format (_("Python script {1} execution failed.")) % script_filename; + Py_Finalize(); + python_cleanup (config, status); } - Py_Finalize(); - cleanup_and_exit_with_save (); } - catch (const std::exception&) + if (args->interactive) { - if (qof_book_session_not_saved (gnc_get_current_book())) - std::cerr << _("Book is readonly. Unsaved changes will be lost.") << std::endl; - gnc_clear_current_session (); - - PyConfig_Clear(&config); - if (PyStatus_IsExit(status)) - gnc_shutdown_cli (status.exitcode); - - Py_ExitStatusException(status); + std::cout << _("Welcome to Gnucash Interactive Python Session") << std::endl; + PyRun_InteractiveLoop (stdin, "foo"); } -#endif + Py_Finalize(); + cleanup_and_exit_with_save (); } +#endif int -Gnucash::run_scripting (std::vector m_script_args, - const bo_str& m_file_to_load, - std::string& m_language, - const bo_str& m_script, - bool m_open_readwrite, - bool m_interactive) +Gnucash::run_scripting (std::vector script_args, + const bo_str& file_to_load, + std::string& language, + const bo_str& script, + bool open_readwrite, + bool interactive) { std::vector errors; static const std::vector languages = { "guile", "python" }; - if (m_open_readwrite && !m_file_to_load) + if (open_readwrite && !file_to_load) errors.push_back (_ ("--readwrite: missing datafile!")); - if (m_script && (!boost::filesystem::is_regular_file (*m_script))) - errors.push_back ((bl::format (_("--script: {1} is not a file")) % *m_script).str()); + if (script && (!boost::filesystem::is_regular_file (*script))) + errors.push_back ((bl::format (_("--script: {1} is not a file")) % *script).str()); if (std::none_of (languages.begin(), languages.end(), - [&m_language](auto& lang){ return m_language == lang; })) + [&language](auto& lang){ return language == lang; })) errors.push_back (_ ("--language: must be 'python' or 'guile'")); #ifndef HAVE_PYTHON_H - else if (m_language == "python") + else if (language == "python") errors.push_back (_("--language: python wasn't compiled in this build")); #endif @@ -663,28 +666,30 @@ Gnucash::run_scripting (std::vector m_script_args, gnc_shutdown_cli (1); } - std::vector newArgv {"gnucash-cli"}; - std::transform (m_script_args.begin(), m_script_args.end(), std::back_inserter(newArgv), + std::vector newArgv = + { "gnucash-cli", file_to_load ? file_to_load->c_str() : ""}; + std::transform (script_args.begin(), script_args.end(), std::back_inserter(newArgv), [](const std::string& s) { return s.c_str(); }); - // note the vector is valid as long as m_script_args's strings are not damaged! + // note the vector is valid as long as script_args's strings are not damaged! gnc_prefs_init (); gnc_ui_util_init(); - if (m_file_to_load) - load_file (*m_file_to_load, m_open_readwrite); + if (file_to_load && boost::filesystem::is_regular_file (*file_to_load)) + load_file (*file_to_load, open_readwrite); - scripting_args args { m_script, m_interactive }; - if (m_language == "guile") + scripting_args args { script, interactive }; + if (language == "guile") { scm_boot_guile (newArgv.size(), (char**)newArgv.data(), run_guile_cli, &args); return 0; // never reached... } - else if (m_language == "python") +#ifdef HAVE_PYTHON_H + else if (language == "python") { run_python_cli (newArgv.size(), (char**)newArgv.data(), &args); return 0; // never reached... } - +#endif return 0; // never reached }