Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-24.04, macos-14, macos-15]

os: [ubuntu-22.04, ubuntu-24.04, macos-14]

build_type: [static_build, shared_build]

steps:
Expand Down Expand Up @@ -136,11 +138,12 @@ jobs:
shell: cmd /C call {0}
run: pytest . -vvv

- name: Test xeus-python C++
- name: Test xeus-python C++ (100 iterations)
shell: cmd /C call {0}
run: |
micromamba activate xeus-python
test_xeus_python
timeout-minutes: 4
working-directory: build\test

for /L %%i in (1,1,50) do (
echo Running iteration %%i
test_xeus_python || exit /b 1
)
timeout-minutes: 60
working-directory: build\test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ docs/build/

# Build directory
build/
/build-*/

# generated kernel specs
/share/jupyter/kernels/xpython/kernel.json
Expand Down
4 changes: 4 additions & 0 deletions environment-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ dependencies:
- jupyter_kernel_test<0.8
- doctest
- pluggy=1.3
- libboost
- libboost-devel
- libboost-headers

13 changes: 13 additions & 0 deletions include/xeus-python/xdebugger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <memory>
#include <mutex>
#include <set>
#include <thread>

#include "nlohmann/json.hpp"
#include "pybind11/pybind11.h"
Expand Down Expand Up @@ -69,7 +70,19 @@ namespace xpyt
std::string m_debugpy_host;
std::string m_debugpy_port;
nl::json m_debugger_config;

struct after { ~after(){ std::cout << "\n### " << std::this_thread::get_id() << " DESTROYING PYDEBUGGER - DONE" << std::endl; } } after_pydebugger;
py::object m_pydebugger;
struct before {
py::object& ref_pydebugger;
~before(){
std::cout << "\n### " << std::this_thread::get_id() << " DESTROYING PYDEBUGGER ..." << std::endl;
py::gil_scoped_acquire acquire;
auto pydebugger = std::move(ref_pydebugger);
std::cout << "\n### " << std::this_thread::get_id() << " DESTROYING PYDEBUGGER - local destroy ..." << std::endl;
}
} before_pydebugger{ m_pydebugger };

xeus::xthread m_client_runner;
bool m_copy_to_globals_available;
};
Expand Down
4 changes: 4 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ int main(int argc, char* argv[])
// Setting Program Name
static const std::string executable(xpyt::get_python_path());
static const std::wstring wexecutable(executable.cbegin(), executable.cend());
if (!std::filesystem::exists(wexecutable))
{
throw std::runtime_error(std::string("cannot find python executable, tried ") + executable);
}
config.program_name = const_cast<wchar_t*>(wexecutable.c_str());

// Setting Python Home
Expand Down
3 changes: 3 additions & 0 deletions src/xdebugger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ namespace xpyt
if (std::getenv("XEUS_LOG") != nullptr)
{
std::ofstream out("xeus.log", std::ios_base::app);
//auto& out = std::cout;
out << "===== DEBUGGER CONFIG =====" << std::endl;
out << m_debugger_config.dump() << std::endl;
}
Expand Down Expand Up @@ -283,9 +284,11 @@ namespace xpyt
}
else
{
std::cout << "\n### " << std::this_thread::get_id() << " CREATING PYDEBUGGER ..." << std::endl;
py::gil_scoped_acquire acquire;
py::module xeus_python_shell = py::module::import("xeus_python_shell.debugger");
m_pydebugger = xeus_python_shell.attr("XDebugger")();
std::cout << "\n### " << std::this_thread::get_id() << " CREATING PYDEBUGGER - DONE" << std::endl;

// Get debugpy version
std::string expression = "debugpy.__version__";
Expand Down
89 changes: 80 additions & 9 deletions src/xinterpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
#include "xinternal_utils.hpp"
#include "xstream.hpp"

// TODO REMOVE AFTER DEBUGGING
#include <iostream>

namespace py = pybind11;
namespace nl = nlohmann;
using namespace pybind11::literals;
Expand Down Expand Up @@ -334,32 +337,100 @@ namespace xpyt

nl::json interpreter::internal_request_impl(const nl::json& content)
{
std::cout << "Received internal request with content: " << content.dump(4) << std::endl;
py::gil_scoped_acquire acquire;
std::string code = content.value("code", "");

std::cout<<"reset traceback"<<std::endl;
// Reset traceback
m_ipython_shell.attr("last_error") = py::none();

std::cout<<"entering try block"<<std::endl;
try
{
std::cout<<"executing code: "<<code<<std::endl;
exec(py::str(code));
std::cout<<"code executed successfully"<<std::endl;
return xeus::create_successful_reply();
}
catch (py::error_already_set& e)
{
// This will grab the latest traceback and set shell.last_error
m_ipython_shell.attr("showtraceback")();
try{
std::cout<<"an error occurred during code execution: "<<e.what()<<std::endl;

py::list pyerror = m_ipython_shell.attr("last_error");
std::cout<<"grabbing traceback"<<std::endl;
// This will grab the latest traceback and set shell.last_error
m_ipython_shell.attr("showtraceback")();

xerror error = extract_error(pyerror);
std::cout<<"extracting error from shell.last_error"<<std::endl;
py::list pyerror = m_ipython_shell.attr("last_error");

std::cout<<"create xerror from pyerror"<<std::endl;
xerror error = extract_error(pyerror);

std::cout<<"publishing execution error"<<std::endl;
publish_execution_error(error.m_ename, error.m_evalue, error.m_traceback);

std::cout<<"creating error reply"<<std::endl;
error.m_traceback.resize(1);
error.m_traceback[0] = code;
return xeus::create_error_reply(error.m_ename, error.m_evalue, error.m_traceback);
}
catch (py::error_already_set& e)
{
std::cout<<"an error occurred during error handling: "<<e.what()<<std::endl;
return xeus::create_error_reply("ErrorDuringErrorHandling", e.what(), std::vector<std::string>());
}
catch(std::exception& e)
{
std::cout<<"a standard exception occurred during error handling: "<<e.what()<<std::endl;
return xeus::create_error_reply("ExceptionDuringErrorHandling", e.what(), std::vector<std::string>());
}
catch (...)
{
std::cout<<"an unknown error occurred during error handling"<<std::endl;
return xeus::create_error_reply("UnknownErrorDuringErrorHandling", "", std::vector<std::string>());
}
}
catch(std::exception& e)
{
std::cout<<"a standard exception occurred during code execution: "<<e.what()<<std::endl;
return xeus::create_error_reply("Exception", e.what(), std::vector<std::string>());
}
catch (...)
{
std::cout<<"an unknown error occurred during code execution"<<std::endl;
return xeus::create_error_reply("UnknownError", "", std::vector<std::string>());
}

publish_execution_error(error.m_ename, error.m_evalue, error.m_traceback);
error.m_traceback.resize(1);
error.m_traceback[0] = code;
std::cout << "\n--> processing error ... " << std::endl;
py::list pyerror = [&]() -> py::list {
try {
auto last_error = m_ipython_shell.attr("last_error");
std::cout << "\n--> converting last_error to list ... " << std::endl;
return py::list(last_error);
}
catch (py::error_already_set& e)
{
std::cout << "\n--> processing error: failed acquiring `last_error` " << std::endl;
return py::list{};
}
}();

return xeus::create_error_reply(error.m_ename, error.m_evalue, error.m_traceback);
if (pyerror.empty())
{
return xeus::create_error_reply("SNAFU", "python SNAFU");
}

std::cout << "\n--> A " << std::endl;
xerror error = extract_error(pyerror);
std::cout << "\n--> B " << std::endl;
publish_execution_error(error.m_ename, error.m_evalue, error.m_traceback);
std::cout << "\n--> C " << std::endl;
error.m_traceback.resize(1);
error.m_traceback[0] = code;
std::cout << "\n--> D " << std::endl;
return xeus::create_error_reply(error.m_ename, error.m_evalue, error.m_traceback);

}

void interpreter::set_request_context(xeus::xrequest_context context)
Expand Down
13 changes: 13 additions & 0 deletions src/xpaths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <iostream>
#include <string>
#include <cstring>
#include <filesystem>

#include "pybind11/pybind11.h"

Expand Down Expand Up @@ -44,14 +45,26 @@ namespace xpyt
#elif defined(XEUS_PYTHONHOME_ABSPATH)
static const std::string pythonhome = XPYT_STRINGIFY(XEUS_PYTHONHOME_ABSPATH);
#else
# ifdef _WIN32
using namespace std::filesystem;
static const std::string pythonhome = canonical(xeus::prefix_path()).parent_path().string(); // wont work with unicode paths
# else
static const std::string pythonhome = xeus::prefix_path();
# endif
#endif
return pythonhome;
}
}

std::string get_python_path()
{
const char* python_exe_environment = std::getenv("PYTHON_EXECUTABLE");
if (python_exe_environment != nullptr && std::strlen(python_exe_environment) != 0)
{
static const std::string python_exe_path = python_exe_environment;
return python_exe_path;
}

std::string python_prefix = get_python_prefix();
#ifdef _WIN32
if (python_prefix.back() != '\\')
Expand Down
7 changes: 5 additions & 2 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
endif()

find_package(Threads)
find_package(doctest)
find_package(doctest REQUIRED)

cmake_policy(SET CMP0167 OLD) # use find boost from old cmake
find_package(Boost REQUIRED COMPONENTS process filesystem)

include_directories(${GTEST_INCLUDE_DIRS} SYSTEM)

Expand All @@ -70,7 +73,7 @@ set_target_properties(test_xeus_python PROPERTIES
)

include_directories(${PYTHON_INCLUDE_DIRS})
target_link_libraries(test_xeus_python ${PYTHON_LIBRARIES} xeus-zmq doctest::doctest ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(test_xeus_python ${PYTHON_LIBRARIES} xeus-zmq doctest::doctest Boost::headers Boost::filesystem Boost::process ${CMAKE_THREAD_LIBS_INIT})
target_include_directories(test_xeus_python PRIVATE ${XEUS_PYTHON_INCLUDE_DIR})

add_custom_target(xtest COMMAND test_xeus_python DEPENDS test_xeus_python)
Expand Down
Loading