Skip to content
Open
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
7 changes: 6 additions & 1 deletion bindings/pyroot/cppyy/CPyCppyy/src/Pythonize.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,12 @@ static bool FillVector(PyObject* vecin, PyObject* args, ItemGetter* getter)
// reserve memory as applicable
if (0 < sz) {
PyObject* res = PyObject_CallMethod(vecin, (char*)"reserve", (char*)"n", sz);
Py_DECREF(res);
// TODO: Actually this "res" should never be nullptr, but somehow this
// call can fail on Windows 64 bit, resulting in "res" being a nullptr.
// This needs to be fixed, and then we can use again Py_DECREF(res),
// which doesn't do the nullptr check. Alternatively, there should be a
// proper error if calling reserve() fails.
Py_XDECREF(res);
} else // i.e. sz == 0, so empty container: done
return true;

Expand Down
4 changes: 1 addition & 3 deletions bindings/pyroot/cppyy/cppyy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,4 @@ install(DIRECTORY ${localruntimedir}/cppyy
COMPONENT libraries
PATTERN *.so EXCLUDE)

if(NOT MSVC)
ROOT_ADD_TEST_SUBDIRECTORY(test)
endif()
ROOT_ADD_TEST_SUBDIRECTORY(test)
143 changes: 55 additions & 88 deletions bindings/pyroot/cppyy/cppyy/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,96 +4,63 @@
# For the licensing terms see $ROOTSYS/LICENSE.
# For the list of contributors see $ROOTSYS/README/CREDITS.

# Dictionary list
set(CPPYY_TEST_DICTS
advancedcpp
advancedcpp2
conversions
cpp11features
crossinheritance
datatypes
doc_helper
example01
fragile
operators
overloads
pythonizables
std_streams
templates
stltypes)
set(common_args GENERIC PYTHON_DEPS pytest)

foreach(DICT ${CPPYY_TEST_DICTS})
set(CMAKE_ROOTTEST_NOROOTMAP OFF)
# only disable rootmap for all but example01 and stltypes which require them
if(NOT DICT STREQUAL "example01" AND NOT DICT STREQUAL "stltypes")
set(CMAKE_ROOTTEST_NOROOTMAP ON)
endif()
# Generate dictionary for the tests
ROOT_GENERATE_DICTIONARY(G__${DICT}Dict ${CMAKE_CURRENT_SOURCE_DIR}/${DICT}.h LINKDEF ${CMAKE_CURRENT_SOURCE_DIR}/${DICT}.xml)
# Create necessary shared libraries for the tests
add_library(${DICT}Dict SHARED ${CMAKE_CURRENT_SOURCE_DIR}/${DICT}.cxx G__${DICT}Dict.cxx)
target_include_directories(${DICT}Dict PUBLIC ${Python3_INCLUDE_DIRS} ${CMAKE_BINARY_DIR}/include)
target_link_libraries(${DICT}Dict PUBLIC ROOT::Core)
target_compile_options(${DICT}Dict PRIVATE "-w")
if(MSVC)
target_link_libraries(${DICT}Dict PUBLIC Python3::Python)
elseif(APPLE)
target_link_libraries(${DICT}Dict PUBLIC -Wl,-bind_at_load -Wl,-w -Wl,-undefined -Wl,dynamic_lookup)
else()
target_link_libraries(${DICT}Dict PUBLIC -Wl,--unresolved-symbols=ignore-all)
endif()
endforeach()
unset(CMAKE_ROOTTEST_NOROOTMAP)
if(NOT MSVC)
list(APPEND common_args ENVIRONMENT ${ld_library_path}=${CMAKE_CURRENT_BINARY_DIR})
endif()

# Tests list
set(CPPYY_TESTS
test_aclassloader
test_advancedcpp
test_api
test_boost
test_conversions
test_crossinheritance
test_datatypes
test_doc_features
test_eigen
test_fragile
# The leakcheck test is disabled due to its sporadic nature, especially fragile on VMs
# test_leakcheck
test_lowlevel
test_numba
test_operators
test_overloads
test_pythonify
test_pythonization
test_regression
test_streams
test_templates
test_concurrent)
set(root_cmd $<TARGET_FILE:root.exe> -b -q -l)

if(NOT CMAKE_CXX_STANDARD EQUAL 23)
# test_cpp11features crashes when run with C++23
if(APPLE)
execute_process(
COMMAND sw_vers -productVersion
OUTPUT_VARIABLE MACOS_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(MACOS_VERSION VERSION_LESS "26.0")
# Parts of this test suite fail with std::make_unique
list(APPEND CPPYY_TEST_DICTS test_cpp11features)
endif()
else()
list(APPEND CPPYY_TESTS test_cpp11features)
endif()
endif()
function(ADD_PYUNITTEST_ACLIC TESTNAME)
set(options)
set(oneValueArgs)
set(multiValueArgs DICTNAME)
cmake_parse_arguments(ARG
"${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}
)

if(NOT APPLE)
# test_stltypes completely fails on OSX
# because it is unable to load the necessary shared libraries
list(APPEND CPPYY_TESTS test_stltypes)
endif()
ROOT_ADD_PYUNITTEST(${TESTNAME} ${TESTNAME}.py ${common_args}
COPY_TO_BUILDDIR ${ARG_DICTNAME}.cxx ${ARG_DICTNAME}.h
PRECMD ${root_cmd} -e ".L ${ARG_DICTNAME}.cxx++"
)
endfunction()

ADD_PYUNITTEST_ACLIC(test_conversions DICTNAME conversions)
ADD_PYUNITTEST_ACLIC(test_cpp11features DICTNAME cpp11features)
ADD_PYUNITTEST_ACLIC(test_crossinheritance DICTNAME crossinheritance)
ADD_PYUNITTEST_ACLIC(test_doc_features DICTNAME doc_helper)
ADD_PYUNITTEST_ACLIC(test_fragile DICTNAME fragile)
ADD_PYUNITTEST_ACLIC(test_operators DICTNAME operators)
ADD_PYUNITTEST_ACLIC(test_overloads DICTNAME overloads)
ADD_PYUNITTEST_ACLIC(test_pythonization DICTNAME pythonizables)
ADD_PYUNITTEST_ACLIC(test_stltypes DICTNAME stltypes)
ADD_PYUNITTEST_ACLIC(test_streams DICTNAME std_streams)
ADD_PYUNITTEST_ACLIC(test_templates DICTNAME templates)

ROOT_ADD_PYUNITTEST(test_pythonify test_pythonify.py ${common_args}
COPY_TO_BUILDDIR example01.cxx example01.h
PRECMD ${root_cmd} -e ".L example01.cxx++"
FIXTURES_SETUP example01_dict_fixture
)

ROOT_ADD_PYUNITTEST(test_advancedcpp test_advancedcpp.py ${common_args}
COPY_TO_BUILDDIR advancedcpp.cxx advancedcpp.h advancedcpp2.cxx advancedcpp2.h
PRECMD ${root_cmd} -e ".L advancedcpp.cxx++" -e ".L advancedcpp2.cxx++"
)

ROOT_ADD_PYUNITTEST(test_lowlevel test_lowlevel.py ${common_args}
COPY_TO_BUILDDIR datatypes.cxx datatypes.h
PRECMD ${root_cmd} -e ".L datatypes.cxx++"
FIXTURES_SETUP datatypes_dict_fixture
)

# Configure the tests
foreach(TEST ${CPPYY_TESTS})
ROOT_ADD_PYUNITTEST(${TEST} ${TEST}.py GENERIC ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_CURRENT_BINARY_DIR} PYTHON_DEPS pytest)
endforeach()
ROOT_ADD_PYUNITTEST(test_aclassloader test_aclassloader.py ${common_args} FIXTURES_REQUIRED example01_dict_fixture)
ROOT_ADD_PYUNITTEST(test_api test_api.py ${common_args})
ROOT_ADD_PYUNITTEST(test_boost test_boost.py ${common_args})
ROOT_ADD_PYUNITTEST(test_concurrent test_concurrent.py ${common_args})
ROOT_ADD_PYUNITTEST(test_datatypes test_datatypes.py ${common_args} FIXTURES_REQUIRED datatypes_dict_fixture)
ROOT_ADD_PYUNITTEST(test_eigen test_eigen.py ${common_args})
ROOT_ADD_PYUNITTEST(test_leakcheck test_leakcheck.py ${common_args})
ROOT_ADD_PYUNITTEST(test_numba test_numba.py ${common_args})
ROOT_ADD_PYUNITTEST(test_regression test_regression.py ${common_args})
12 changes: 0 additions & 12 deletions bindings/pyroot/cppyy/cppyy/test/cpp11features.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,3 @@ namespace FunctionNS {
struct FNTestStruct { FNTestStruct(int i) : t(i) {} int t; };
std::function<int(const FNTestStruct& t)> FNCreateTestStructFunc();
}


//===========================================================================
struct StructWithHash {}; // for std::hash<> testing
struct StructWithoutHash {};

namespace std {
template<>
struct hash<StructWithHash> {
size_t operator()(const StructWithHash&) const { return 17; }
};
} // namespace std
47 changes: 0 additions & 47 deletions bindings/pyroot/cppyy/cppyy/test/pythonizables.cxx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#include "pythonizables.h"

#include "Python.h"


//===========================================================================
pyzables::NakedBuffers::NakedBuffers(int size, double valx, double valy) : m_size(size) {
m_Xbuf = new double[size];
Expand Down Expand Up @@ -54,47 +51,3 @@ unsigned int pyzables::pass_mine_rp_ref(const Countable& c) { return c.m_check;
unsigned int pyzables::pass_mine_rp_ptr(const Countable* c) { return c->m_check; }

pyzables::Countable* pyzables::gime_naked_countable() { return new Countable{}; }


//===========================================================================
pyzables::WithCallback1::WithCallback1(int i) : m_int(i) {}

int pyzables::WithCallback1::get_int() { return m_int; }
void pyzables::WithCallback1::set_int(int i) { m_int = i; }

static inline void replace_method_name(PyObject* klass, const char* n1, const char* n2) {
PyObject* meth = PyObject_GetAttrString(klass, n1);
PyObject_SetAttrString(klass, n2, meth);
Py_DECREF(meth);
PyObject_DelAttrString(klass, n1);
}

void pyzables::WithCallback1::WithCallback1::__cppyy_explicit_pythonize__(PyObject* klass, const std::string& name) {
// change methods to camel case
replace_method_name(klass, "get_int", "GetInt");
replace_method_name(klass, "set_int", "SetInt");

// store the provided class name
klass_name = name;
}

std::string pyzables::WithCallback1::klass_name{"not set"};

pyzables::WithCallback2::WithCallback2(int i) : m_int(i) {}

int pyzables::WithCallback2::get_int() { return m_int; }
void pyzables::WithCallback2::set_int(int i) { m_int = i; }

void pyzables::WithCallback2::WithCallback2::__cppyy_pythonize__(PyObject* klass, const std::string& name) {
// change methods to camel case
replace_method_name(klass, "get_int", "GetInt");
replace_method_name(klass, "set_int", "SetInt");

// store the provided class name
klass_name = name;
}

std::string pyzables::WithCallback2::klass_name{"not set"};

int pyzables::WithCallback3::get_int() { return 2*m_int; }
void pyzables::WithCallback3::set_int(int i) { m_int = 2*i; }
43 changes: 0 additions & 43 deletions bindings/pyroot/cppyy/cppyy/test/pythonizables.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,47 +123,4 @@ class IndexableBase {

class IndexableDerived : public IndexableBase {};


//===========================================================================
class WithCallback1 {
public:
WithCallback1(int i);

public:
int get_int();
void set_int(int i);

private:
int m_int;

public:
static void __cppyy_explicit_pythonize__(PyObject* klass, const std::string&);
static std::string klass_name;
};

class WithCallback2 {
public:
WithCallback2(int i);

public:
int get_int();
void set_int(int i);

protected:
int m_int;

public:
static void __cppyy_pythonize__(PyObject* klass, const std::string&);
static std::string klass_name;
};

class WithCallback3 : public WithCallback2 {
public:
using WithCallback2::WithCallback2;

public:
int get_int();
void set_int(int i);
};

} // namespace pyzables
20 changes: 11 additions & 9 deletions bindings/pyroot/cppyy/cppyy/test/support.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import print_function
import os, py, sys, subprocess

Check failure on line 2 in bindings/pyroot/cppyy/cppyy/test/support.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E401)

bindings/pyroot/cppyy/cppyy/test/support.py:2:1: E401 Multiple imports on one line
from contextlib import contextmanager

Check failure on line 3 in bindings/pyroot/cppyy/cppyy/test/support.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (I001)

bindings/pyroot/cppyy/cppyy/test/support.py:1:1: I001 Import block is un-sorted or un-formatted

currpath = py.path.local(__file__).dirpath()

Expand All @@ -21,31 +21,33 @@
pyunicode = str
maxvalue = sys.maxsize
else:
pylong = long

Check failure on line 24 in bindings/pyroot/cppyy/cppyy/test/support.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F821)

bindings/pyroot/cppyy/cppyy/test/support.py:24:14: F821 Undefined name `long`
pyunicode = unicode

Check failure on line 25 in bindings/pyroot/cppyy/cppyy/test/support.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F821)

bindings/pyroot/cppyy/cppyy/test/support.py:25:17: F821 Undefined name `unicode`
maxvalue = sys.maxint

IS_WINDOWS = 0
if 'win32' in sys.platform:
IS_WINDOWS = 'win32' in sys.platform
WINDOWS_BITS = 0

if IS_WINDOWS:
import platform
if '64' in platform.architecture()[0]:
IS_WINDOWS = 64
WINDOWS_BITS = 64
maxvalue = 2**31-1
else:
IS_WINDOWS = 32
WINDOWS_BITS = 32

IS_MAC_ARM = 0
IS_MAC_X86 = 0
IS_MAC_ARM = False
IS_MAC_X86 = False
if 'darwin' in sys.platform:
import platform
if 'arm64' in platform.machine():
IS_MAC_ARM = 64
IS_MAC_ARM = True
os.environ["CPPYY_UNCAUGHT_QUIET"] = "1"
else:
IS_MAC_X86 = 1
IS_MAC_X86 =True

IS_MAC = IS_MAC_ARM or IS_MAC_X86
IS_LINUX = not (IS_WINDOWS or IS_MAC)
IS_LINUX = not (IS_WINDOWS or IS_MAC)

def _register_root_error_counter():

Expand Down Expand Up @@ -91,7 +93,7 @@


try:
import __pypy__

Check failure on line 96 in bindings/pyroot/cppyy/cppyy/test/support.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F401)

bindings/pyroot/cppyy/cppyy/test/support.py:96:12: F401 `__pypy__` imported but unused; consider using `importlib.util.find_spec` to test for availability
ispypy = True
except ImportError:
ispypy = False
26 changes: 2 additions & 24 deletions bindings/pyroot/cppyy/cppyy/test/templates.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#ifndef CPPYY_TEST_TEMPLATES_H
#define CPPYY_TEST_TEMPLATES_H

#include <sstream>
#include <stdexcept>
#include <string>
#include <sstream>
#include <typeinfo>
#include <vector>

#ifndef _WIN32
Expand Down Expand Up @@ -259,29 +260,6 @@ template<typename T> using DA_vector = std::vector<T>;

namespace using_problem {

template <typename T, size_t SZ>
struct vector {
vector() : m_val(SZ) {}
T m_val;
};

template <typename T, size_t ... sizes>
struct matryoshka {
typedef T type;
};

template <typename T, size_t SZ, size_t ... sizes>
struct matryoshka<T, SZ, sizes ... > {
typedef vector<typename matryoshka<T, sizes ...>::type, SZ> type;
};

template <typename T, size_t ... sizes>
using make_vector = typename matryoshka<T, sizes ...>::type;
typedef make_vector<int, 2, 3> iiv_t;
};

namespace using_problem {

template<typename T>
class Base {
public:
Expand Down
7 changes: 3 additions & 4 deletions bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import py, pytest, os
import pytest, os

Check failure on line 1 in bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F401)

bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py:1:16: F401 `os` imported but unused

Check failure on line 1 in bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (E401)

bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py:1:1: E401 Multiple imports on one line
from pytest import raises, mark

Check failure on line 2 in bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F401)

bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py:2:20: F401 `pytest.raises` imported but unused
from support import setup_make, IS_MAC

Check failure on line 3 in bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (F401)

bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py:3:21: F401 `support.setup_make` imported but unused

Check failure on line 3 in bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (I001)

bindings/pyroot/cppyy/cppyy/test/test_aclassloader.py:1:1: I001 Import block is un-sorted or un-formatted

currpath = os.getcwd()
test_dct = currpath + "/libexample01Dict"
test_dct = "libexample_cxx"


class TestACLASSLOADER:

def setup_class(cls):
import cppyy

@mark.xfail(condition=IS_MAC, reason="Fails on OSX")
@mark.xfail(reason="rootmap files are a legacy feature")
def test01_class_autoloading(self):
"""Test whether a class can be found through .rootmap."""
import cppyy
Expand Down
Loading
Loading