Unverified Commit 6493f496 authored by Ralf W. Grosse-Kunstleve's avatar Ralf W. Grosse-Kunstleve Committed by GitHub
Browse files

Python 2 removal part 1: tests (C++ code is intentionally ~untouched) (#3688)



* `#error BYE_BYE_GOLDEN_SNAKE`

* Removing everything related to 2.7 from ci.yml

* Commenting-out Centos7

* Removing `PYTHON: 27` from .appveyor.yml

* "PY2" removal, mainly from tests. C++ code is not touched.

* Systematic removal of `u` prefix from `u"..."` and `u'...'` literals. Collateral cleanup of a couple minor other things.

* Cleaning up around case-insensitive hits for `[^a-z]py.*2` in tests/.

* Removing obsolete Python 2 mention in compiling.rst

* Proper `#error` for Python 2.

* Using PY_VERSION_HEX to guard `#error "PYTHON 2 IS NO LONGER SUPPORTED.`

* chore: bump pre-commit

* style: run pre-commit for pyupgrade 3+

* tests: use sys.version_info, not PY

* chore: more Python 2 removal

* Uncommenting Centos7 block (PR #3691 showed that it is working again).

* Update pre-commit hooks

* Fix pre-commit hook

* refactor: remove Python 2 from CMake

* refactor: remove Python 2 from setup code

* refactor: simplify, better static typing

* feat: fail with nice messages

* refactor: drop Python 2 C++ code

* docs: cleanup for Python 3

* revert: intree

revert: intree

* docs: minor touchup to py2 statement
Co-authored-by: default avatarHenry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: default avatarAaron Gokaslan <skylion.aaron@gmail.com>
parent 46dcd9bc
......@@ -82,7 +82,7 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass);
# define PYBIND11_TLS_KEY_INIT(var) PYBIND11_TLS_KEY_REF var = 0;
# define PYBIND11_TLS_KEY_CREATE(var) (((var) = PyThread_create_key()) != -1)
# define PYBIND11_TLS_GET_VALUE(key) PyThread_get_key_value((key))
# if PY_MAJOR_VERSION < 3 || defined(PYPY_VERSION)
# if defined(PYPY_VERSION)
// On CPython < 3.4 and on PyPy, `PyThread_set_key_value` strangely does not set
// the value if it has already been set. Instead, it must first be deleted and
// then set again.
......@@ -294,7 +294,6 @@ inline internals **&get_internals_pp() {
return internals_pp;
}
#if PY_VERSION_HEX >= 0x03030000
// forward decl
inline void translate_exception(std::exception_ptr);
......@@ -318,21 +317,11 @@ bool handle_nested_exception(const T &exc, const std::exception_ptr &p) {
return false;
}
#else
template <class T>
bool handle_nested_exception(const T &, std::exception_ptr &) {
return false;
}
#endif
inline bool raise_err(PyObject *exc_type, const char *msg) {
#if PY_VERSION_HEX >= 0x03030000
if (PyErr_Occurred()) {
raise_from(exc_type, msg);
return true;
}
#endif
PyErr_SetString(exc_type, msg);
return false;
}
......
......@@ -443,17 +443,10 @@ PYBIND11_NOINLINE void instance::allocate_layout() {
// they default to using pymalloc, which is designed to be efficient for small allocations
// like the one we're doing here; in earlier versions (and for larger allocations) they are
// just wrappers around malloc.
#if PY_VERSION_HEX >= 0x03050000
nonsimple.values_and_holders = (void **) PyMem_Calloc(space, sizeof(void *));
if (!nonsimple.values_and_holders) {
throw std::bad_alloc();
}
#else
nonsimple.values_and_holders = (void **) PyMem_New(void *, space);
if (!nonsimple.values_and_holders)
throw std::bad_alloc();
std::memset(nonsimple.values_and_holders, 0, space * sizeof(void *));
#endif
nonsimple.status
= reinterpret_cast<std::uint8_t *>(&nonsimple.values_and_holders[flags_at]);
}
......@@ -494,11 +487,9 @@ PYBIND11_NOINLINE std::string error_string() {
PyErr_NormalizeException(&scope.type, &scope.value, &scope.trace);
#if PY_MAJOR_VERSION >= 3
if (scope.trace != nullptr) {
PyException_SetTraceback(scope.value, scope.trace);
}
#endif
#if !defined(PYPY_VERSION)
if (scope.trace) {
......@@ -547,10 +538,6 @@ PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_i
inline PyThreadState *get_thread_state_unchecked() {
#if defined(PYPY_VERSION)
return PyThreadState_GET();
#elif PY_VERSION_HEX < 0x03000000
return _PyThreadState_Current;
#elif PY_VERSION_HEX < 0x03050000
return (PyThreadState *) _Py_atomic_load_relaxed(&_PyThreadState_Current);
#elif PY_VERSION_HEX < 0x03050200
return (PyThreadState *) _PyThreadState_Current.value;
#else
......
......@@ -19,15 +19,9 @@
# error Embedding the interpreter is not supported with PyPy
#endif
#if PY_MAJOR_VERSION >= 3
# define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
extern "C" PyObject *pybind11_init_impl_##name(); \
extern "C" PyObject *pybind11_init_impl_##name() { return pybind11_init_wrapper_##name(); }
#else
# define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
extern "C" void pybind11_init_impl_##name(); \
extern "C" void pybind11_init_impl_##name() { pybind11_init_wrapper_##name(); }
#endif
#define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
extern "C" PyObject *pybind11_init_impl_##name(); \
extern "C" PyObject *pybind11_init_impl_##name() { return pybind11_init_wrapper_##name(); }
/** \rst
Add a new module to the table of builtins for the interpreter. Must be
......@@ -67,11 +61,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
/// Python 2.7/3.x compatible version of `PyImport_AppendInittab` and error checks.
struct embedded_module {
#if PY_MAJOR_VERSION >= 3
using init_t = PyObject *(*) ();
#else
using init_t = void (*)();
#endif
embedded_module(const char *name, init_t init) {
if (Py_IsInitialized() != 0) {
pybind11_fail("Can't add new modules after the interpreter has been initialized");
......@@ -86,42 +76,13 @@ struct embedded_module {
struct wide_char_arg_deleter {
void operator()(wchar_t *ptr) const {
#if PY_VERSION_HEX >= 0x030500f0
// API docs: https://docs.python.org/3/c-api/sys.html#c.Py_DecodeLocale
PyMem_RawFree(ptr);
#else
delete[] ptr;
#endif
}
};
inline wchar_t *widen_chars(const char *safe_arg) {
#if PY_VERSION_HEX >= 0x030500f0
wchar_t *widened_arg = Py_DecodeLocale(safe_arg, nullptr);
#else
wchar_t *widened_arg = nullptr;
// warning C4996: 'mbstowcs': This function or variable may be unsafe.
# if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4996)
# endif
# if defined(HAVE_BROKEN_MBSTOWCS) && HAVE_BROKEN_MBSTOWCS
size_t count = std::strlen(safe_arg);
# else
size_t count = std::mbstowcs(nullptr, safe_arg, 0);
# endif
if (count != static_cast<size_t>(-1)) {
widened_arg = new wchar_t[count + 1];
std::mbstowcs(widened_arg, safe_arg, count + 1);
}
# if defined(_MSC_VER)
# pragma warning(pop)
# endif
#endif
return widened_arg;
}
......@@ -138,7 +99,6 @@ inline void set_interpreter_argv(int argc, const char *const *argv, bool add_pro
}
auto argv_size = static_cast<size_t>(argc);
#if PY_MAJOR_VERSION >= 3
// SetArgv* on python 3 takes wchar_t, so we have to convert.
std::unique_ptr<wchar_t *[]> widened_argv(new wchar_t *[argv_size]);
std::vector<std::unique_ptr<wchar_t[], wide_char_arg_deleter>> widened_argv_entries;
......@@ -154,15 +114,6 @@ inline void set_interpreter_argv(int argc, const char *const *argv, bool add_pro
}
auto *pysys_argv = widened_argv.get();
#else
// python 2.x
std::vector<std::string> strings{safe_argv, safe_argv + argv_size};
std::vector<char *> char_strings{argv_size};
for (std::size_t i = 0; i < argv_size; ++i)
char_strings[i] = &strings[i][0];
char **pysys_argv = char_strings.data();
#endif
PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(add_program_dir_to_path));
}
......
......@@ -20,10 +20,10 @@ PYBIND11_NAMESPACE_BEGIN(detail)
inline void ensure_builtins_in_globals(object &global) {
#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x03080000
// Running exec and eval on Python 2 and 3 adds `builtins` module under
// `__builtins__` key to globals if not yet present.
// Python 3.8 made PyRun_String behave similarly. Let's also do that for
// older versions, for consistency. This was missing from PyPy3.8 7.3.7.
// Running exec and eval adds `builtins` module under `__builtins__` key to
// globals if not yet present. Python 3.8 made PyRun_String behave
// similarly. Let's also do that for older versions, for consistency. This
// was missing from PyPy3.8 7.3.7.
if (!global.contains("__builtins__"))
global["__builtins__"] = module_::import(PYBIND11_BUILTINS_MODULE);
#else
......@@ -94,7 +94,7 @@ void exec(const char (&s)[N], object global = globals(), object local = object()
eval<eval_statements>(s, global, local);
}
#if defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03000000
#if defined(PYPY_VERSION)
template <eval_mode mode = eval_statements>
object eval_file(str, object, object) {
pybind11_fail("eval_file not supported in PyPy3. Use eval");
......@@ -133,40 +133,18 @@ object eval_file(str fname, object global = globals(), object local = object())
int closeFile = 1;
std::string fname_str = (std::string) fname;
# if PY_VERSION_HEX >= 0x03040000
FILE *f = _Py_fopen_obj(fname.ptr(), "r");
# elif PY_VERSION_HEX >= 0x03000000
FILE *f = _Py_fopen(fname.ptr(), "r");
# else
/* No unicode support in open() :( */
auto fobj = reinterpret_steal<object>(
PyFile_FromString(const_cast<char *>(fname_str.c_str()), const_cast<char *>("r")));
FILE *f = nullptr;
if (fobj)
f = PyFile_AsFile(fobj.ptr());
closeFile = 0;
# endif
if (!f) {
PyErr_Clear();
pybind11_fail("File \"" + fname_str + "\" could not be opened!");
}
// In Python2, this should be encoded by getfilesystemencoding.
// We don't boher setting it since Python2 is past EOL anyway.
// See PR#3233
# if PY_VERSION_HEX >= 0x03000000
if (!global.contains("__file__")) {
global["__file__"] = std::move(fname);
}
# endif
# if PY_VERSION_HEX < 0x03000000 && defined(PYPY_VERSION)
PyObject *result = PyRun_File(f, fname_str.c_str(), start, global.ptr(), local.ptr());
(void) closeFile;
# else
PyObject *result
= PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(), local.ptr(), closeFile);
# endif
if (!result) {
throw error_already_set();
......
......@@ -263,11 +263,7 @@ private:
static npy_api lookup() {
module_ m = module_::import("numpy.core.multiarray");
auto c = m.attr("_ARRAY_API");
#if PY_MAJOR_VERSION >= 3
void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), NULL);
#else
void **api_ptr = (void **) PyCObject_AsVoidPtr(c.ptr());
#endif
npy_api api;
#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
DECL_NPY_API(PyArray_GetNDArrayCFeatureVersion);
......
......@@ -91,16 +91,6 @@ struct op_ {
using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>;
using op = op_impl<id, ot, Base, L_type, R_type>;
cl.def(op::name(), &op::execute, is_operator(), extra...);
#if PY_MAJOR_VERSION < 3
if (PYBIND11_SILENCE_MSVC_C4127(id == op_truediv)
|| PYBIND11_SILENCE_MSVC_C4127(id == op_itruediv))
cl.def(id == op_itruediv ? "__idiv__"
: ot == op_l ? "__div__"
: "__rdiv__",
&op::execute,
is_operator(),
extra...);
#endif
}
template <typename Class, typename... Extra>
void execute_cast(Class &cl, const Extra &...extra) const {
......@@ -109,15 +99,6 @@ struct op_ {
using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>;
using op = op_impl<id, ot, Base, L_type, R_type>;
cl.def(op::name(), &op::execute_cast, is_operator(), extra...);
#if PY_MAJOR_VERSION < 3
if (id == op_truediv || id == op_itruediv)
cl.def(id == op_itruediv ? "__idiv__"
: ot == op_l ? "__div__"
: "__rdiv__",
&op::execute,
is_operator(),
extra...);
#endif
}
};
......
......@@ -431,9 +431,8 @@ protected:
}
if (auto *tinfo = detail::get_type_info(*t)) {
handle th((PyObject *) tinfo->type);
signature += th.attr("__module__").cast<std::string>() + "." +
// Python 3.3+, but we backport it to earlier versions
th.attr("__qualname__").cast<std::string>();
signature += th.attr("__module__").cast<std::string>() + "."
+ th.attr("__qualname__").cast<std::string>();
} else if (rec->is_new_style_constructor && arg_index == 0) {
// A new-style `__init__` takes `self` as `value_and_holder`.
// Rewrite it to the proper class type.
......@@ -453,15 +452,6 @@ protected:
pybind11_fail("Internal error while parsing type signature (2)");
}
#if PY_MAJOR_VERSION < 3
if (std::strcmp(rec->name, "__next__") == 0) {
std::free(rec->name);
rec->name = guarded_strdup("next");
} else if (std::strcmp(rec->name, "__bool__") == 0) {
std::free(rec->name);
rec->name = guarded_strdup("__nonzero__");
}
#endif
rec->signature = guarded_strdup(signature.c_str());
rec->args.shrink_to_fit();
rec->nargs = (std::uint16_t) args;
......@@ -1107,14 +1097,12 @@ protected:
}
append_note_if_missing_header_is_suspected(msg);
#if PY_VERSION_HEX >= 0x03030000
// Attach additional error info to the exception if supported
if (PyErr_Occurred()) {
// #HelpAppreciated: unit test coverage for this branch.
raise_from(PyExc_TypeError, msg.c_str());
return nullptr;
}
#endif
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
}
......@@ -1123,13 +1111,11 @@ protected:
"Python type! The signature was\n\t";
msg += it->signature;
append_note_if_missing_header_is_suspected(msg);
#if PY_VERSION_HEX >= 0x03030000
// Attach additional error info to the exception if supported
if (PyErr_Occurred()) {
raise_from(PyExc_TypeError, msg.c_str());
return nullptr;
}
#endif
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
}
......@@ -1149,11 +1135,7 @@ public:
/// Create a new top-level Python module with the given name and docstring
PYBIND11_DEPRECATED("Use PYBIND11_MODULE or module_::create_extension_module instead")
explicit module_(const char *name, const char *doc = nullptr) {
#if PY_MAJOR_VERSION >= 3
*this = create_extension_module(name, doc, new PyModuleDef());
#else
*this = create_extension_module(name, doc, nullptr);
#endif
}
/** \rst
......@@ -1231,20 +1213,14 @@ public:
PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */);
}
#if PY_MAJOR_VERSION >= 3
using module_def = PyModuleDef;
#else
struct module_def {};
#endif
/** \rst
Create a new top-level module that can be used as the main module of a C extension.
For Python 3, ``def`` should point to a statically allocated module_def.
For Python 2, ``def`` can be a nullptr and is completely ignored.
``def`` should point to a statically allocated module_def.
\endrst */
static module_ create_extension_module(const char *name, const char *doc, module_def *def) {
#if PY_MAJOR_VERSION >= 3
// module_def is PyModuleDef
// Placement new (not an allocation).
def = new (def)
......@@ -1258,12 +1234,6 @@ public:
/* m_clear */ nullptr,
/* m_free */ nullptr};
auto *m = PyModule_Create(def);
#else
// Ignore module_def *def; only necessary for Python 3
(void) def;
auto m = Py_InitModule3(
name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr);
#endif
if (m == nullptr) {
if (PyErr_Occurred()) {
throw error_already_set();
......@@ -1290,14 +1260,12 @@ inline dict globals() {
return reinterpret_borrow<dict>(p ? p : module_::import("__main__").attr("__dict__").ptr());
}
#if PY_VERSION_HEX >= 0x03030000
template <typename... Args, typename = detail::enable_if_t<args_are_all_keyword_or_ds<Args...>()>>
PYBIND11_DEPRECATED("make_simple_namespace should be replaced with "
"py::module_::import(\"types\").attr(\"SimpleNamespace\") ")
object make_simple_namespace(Args &&...args_) {
return module_::import("types").attr("SimpleNamespace")(std::forward<Args>(args_)...);
}
#endif
PYBIND11_NAMESPACE_BEGIN(detail)
/// Generic support for creating new Python heap types
......@@ -2173,9 +2141,6 @@ public:
def_property_readonly("value", [](Type value) { return (Scalar) value; });
def("__int__", [](Type value) { return (Scalar) value; });
def("__index__", [](Type value) { return (Scalar) value; });
#if PY_MAJOR_VERSION < 3
def("__long__", [](Type value) { return (Scalar) value; });
#endif
attr("__setstate__") = cpp_function(
[](detail::value_and_holder &v_h, Scalar arg) {
detail::initimpl::setstate<Base>(
......
......@@ -434,8 +434,6 @@ private:
# pragma warning(pop)
#endif
#if PY_VERSION_HEX >= 0x03030000
/// Replaces the current Python error indicator with the chosen error, performing a
/// 'raise from' to indicate that the chosen error was caused by the original error.
inline void raise_from(PyObject *type, const char *message) {
......@@ -473,8 +471,6 @@ inline void raise_from(error_already_set &err, PyObject *type, const char *messa
raise_from(type, message);
}
#endif
/** \defgroup python_builtins const_name
Unless stated otherwise, the following C++ functions behave the same
as their Python counterparts.
......@@ -591,12 +587,9 @@ inline ssize_t hash(handle obj) {
PYBIND11_NAMESPACE_BEGIN(detail)
inline handle get_function(handle value) {
if (value) {
#if PY_MAJOR_VERSION >= 3
if (PyInstanceMethod_Check(value.ptr())) {
value = PyInstanceMethod_GET_FUNCTION(value.ptr());
} else
#endif
if (PyMethod_Check(value.ptr())) {
} else if (PyMethod_Check(value.ptr())) {
value = PyMethod_GET_FUNCTION(value.ptr());
}
}
......@@ -608,7 +601,6 @@ inline handle get_function(handle value) {
// copied from cpython _PyDict_GetItemStringWithError
inline PyObject *dict_getitemstring(PyObject *v, const char *key) {
#if PY_MAJOR_VERSION >= 3
PyObject *kv = nullptr, *rv = nullptr;
kv = PyUnicode_FromString(key);
if (kv == NULL) {
......@@ -621,21 +613,14 @@ inline PyObject *dict_getitemstring(PyObject *v, const char *key) {
throw error_already_set();
}
return rv;
#else
return PyDict_GetItemString(v, key);
#endif
}
inline PyObject *dict_getitem(PyObject *v, PyObject *key) {
#if PY_MAJOR_VERSION >= 3
PyObject *rv = PyDict_GetItemWithError(v, key);
if (rv == NULL && PyErr_Occurred()) {
throw error_already_set();
}
return rv;
#else
return PyDict_GetItem(v, key);
#endif
}
// Helper aliases/functions to support implicit casting of values given to python
......@@ -1273,13 +1258,6 @@ private:
/// Return string representation -- always returns a new reference, even if already a str
static PyObject *raw_str(PyObject *op) {
PyObject *str_value = PyObject_Str(op);
#if PY_MAJOR_VERSION < 3
if (!str_value)
throw error_already_set();
PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr);
Py_XDECREF(str_value);
str_value = unicode;
#endif
return str_value;
}
};
......@@ -1459,11 +1437,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
// unsigned type: (A)-1 != (B)-1 when A and B are unsigned types of different sizes).
template <typename Unsigned>
Unsigned as_unsigned(PyObject *o) {
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(Unsigned) <= sizeof(unsigned long))
#if PY_VERSION_HEX < 0x03000000
|| PyInt_Check(o)
#endif
) {
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(Unsigned) <= sizeof(unsigned long))) {
unsigned long v = PyLong_AsUnsignedLong(o);
return v == (unsigned long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v;
}
......@@ -1922,7 +1896,6 @@ public:
return memoryview::from_buffer(const_cast<T *>(ptr), shape, strides, true);
}
#if PY_MAJOR_VERSION >= 3
/** \rst
Creates ``memoryview`` from static memory.
......@@ -1930,8 +1903,6 @@ public:
managed by Python. The caller is responsible for managing the lifetime
of ``mem``, which MUST outlive the memoryview constructed here.
This method is not available in Python 2.
See also: Python C API documentation for `PyMemoryView_FromBuffer`_.
.. _PyMemoryView_FromMemory:
......@@ -1950,12 +1921,10 @@ public:
return memoryview::from_memory(const_cast<void *>(mem), size, true);
}
# ifdef PYBIND11_HAS_STRING_VIEW
#ifdef PYBIND11_HAS_STRING_VIEW
static memoryview from_memory(std::string_view mem) {
return from_memory(const_cast<char *>(mem.data()), static_cast<ssize_t>(mem.size()), true);
}
# endif
#endif
};
......@@ -2010,11 +1979,7 @@ inline size_t len(handle h) {
/// Get the length hint of a Python object.
/// Returns 0 when this cannot be determined.
inline size_t len_hint(handle h) {
#if PY_VERSION_HEX >= 0x03040000
ssize_t result = PyObject_LengthHint(h.ptr(), 0);
#else
ssize_t result = PyObject_Length(h.ptr());
#endif
if (result < 0) {
// Sometimes a length can't be determined at all (eg generators)
// In which case simply return 0
......@@ -2029,13 +1994,6 @@ inline str repr(handle h) {
if (!str_value) {
throw error_already_set();
}
#if PY_MAJOR_VERSION < 3
PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr);
Py_XDECREF(str_value);
str_value = unicode;
if (!str_value)
throw error_already_set();
#endif
return reinterpret_steal<str>(str_value);
}
......
......@@ -2,7 +2,7 @@ import nox
nox.options.sessions = ["lint", "tests", "tests_packaging"]
PYTHON_VERISONS = ["2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
PYTHON_VERISONS = ["3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
@nox.session(reuse_venv=True)
......
# -*- coding: utf-8 -*-
import sys
if sys.version_info < (3, 5):
msg = "pybind11 does not support Python < 3.5. 2.9 was the last release supporting older Pythons."
raise ImportError(msg)
from ._version import __version__, version_info
from .commands import get_cmake_dir, get_include
......
# -*- coding: utf-8 -*-
from __future__ import print_function
import argparse
import sys
import sysconfig
......@@ -8,8 +5,7 @@ import sysconfig
from .commands import get_cmake_dir, get_include
def print_includes():
# type: () -> None
def print_includes() -> None:
dirs = [
sysconfig.get_path("include"),
sysconfig.get_path("platinclude"),
......@@ -25,8 +21,7 @@ def print_includes():
print(" ".join("-I" + d for d in unique_dirs))
def main():
# type: () -> None
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument(
......
# -*- coding: utf-8 -*-
from typing import Union
def _to_int(s):
def _to_int(s: str) -> Union[int, str]:
try:
return int(s)
except ValueError:
......
from typing import Tuple, Union
def _to_int(s: str) -> Union[int, str]: ...
__version__: str
version_info: Tuple[Union[int, str], ...]
# -*- coding: utf-8 -*-
import os
DIR = os.path.abspath(os.path.dirname(__file__))
def get_include(user=False):
# type: (bool) -> str
def get_include(user: bool = False) -> str:
installed_path = os.path.join(DIR, "include")
source_path = os.path.join(os.path.dirname(DIR), "include")
return installed_path if os.path.exists(installed_path) else source_path
def get_cmake_dir():
# type: () -> str
def get_cmake_dir() -> str:
cmake_installed_path = os.path.join(DIR, "share", "cmake", "pybind11")
if os.path.exists(cmake_installed_path):
return cmake_installed_path
......
# -*- coding: utf-8 -*-
"""
This module provides helpers for C++11+ projects using pybind11.
......@@ -49,6 +47,20 @@ import sysconfig
import tempfile
import threading
import warnings
from functools import lru_cache
from pathlib import Path
from typing import (
Any,
Callable,
Dict,
Iterable,
Iterator,
List,
Optional,
Tuple,
TypeVar,
Union,
)
try:
from setuptools import Extension as _Extension
......@@ -61,7 +73,6 @@ import distutils.ccompiler
import distutils.errors
WIN = sys.platform.startswith("win32") and "mingw" not in sysconfig.get_platform()
PY2 = sys.version_info[0] < 3
MACOS = sys.platform.startswith("darwin")
STD_TMPL = "/std:c++{}" if WIN else "-std=c++{}"
......@@ -73,7 +84,7 @@ STD_TMPL = "/std:c++{}" if WIN else "-std=c++{}"
# directory into your path if it sits beside your setup.py.
class Pybind11Extension(_Extension):
class Pybind11Extension(_Extension): # type: ignore[misc]
"""
Build a C++11+ Extension module with pybind11. This automatically adds the
recommended flags when you init the extension and assumes C++ sources - you
......@@ -95,21 +106,18 @@ class Pybind11Extension(_Extension):
If you want to add pybind11 headers manually, for example for an exact
git checkout, then set ``include_pybind11=False``.
Warning: do not use property-based access to the instance on Python 2 -
this is an ugly old-style class due to Distutils.
"""
# flags are prepended, so that they can be further overridden, e.g. by
# ``extra_compile_args=["-g"]``.
def _add_cflags(self, flags):
def _add_cflags(self, flags: List[str]) -> None:
self.extra_compile_args[:0] = flags
def _add_ldflags(self, flags):
def _add_ldflags(self, flags: List[str]) -> None:
self.extra_link_args[:0] = flags
def __init__(self, *args, **kwargs):
def __init__(self, *args: Any, **kwargs: Any) -> None:
self._cxx_level = 0
cxx_std = kwargs.pop("cxx_std", 0)
......@@ -119,9 +127,7 @@ class Pybind11Extension(_Extension):
include_pybind11 = kwargs.pop("include_pybind11", True)
# Can't use super here because distutils has old-style classes in
# Python 2!
_Extension.__init__(self, *args, **kwargs)
super().__init__(*args, **kwargs)
# Include the installed package pybind11 headers
if include_pybind11:
......@@ -133,11 +139,10 @@ class Pybind11Extension(_Extension):
if pyinc not in self.include_dirs:
self.include_dirs.append(pyinc)
except ImportError:
except ModuleNotFoundError:
pass
# Have to use the accessor manually to support Python 2 distutils
Pybind11Extension.cxx_std.__set__(self, cxx_std)
self.cxx_std = cxx_std
cflags = []
ldflags = []
......@@ -157,18 +162,18 @@ class Pybind11Extension(_Extension):
self._add_ldflags(ldflags)
@property
def cxx_std(self):
def cxx_std(self) -> int:
"""
The CXX standard level. If set, will add the required flags. If left
at 0, it will trigger an automatic search when pybind11's build_ext
is used. If None, will have no effect. Besides just the flags, this
may add a register warning/error fix for Python 2 or macos-min 10.9
or 10.14.
The CXX standard level. If set, will add the required flags. If left at
0, it will trigger an automatic search when pybind11's build_ext is
used. If None, will have no effect. Besides just the flags, this may
add a macos-min 10.9 or 10.14 flag if MACOSX_DEPLOYMENT_TARGET is
unset.
"""
return self._cxx_level
@cxx_std.setter
def cxx_std(self, level):
def cxx_std(self, level: int) -> None:
if self._cxx_level:
warnings.warn("You cannot safely change the cxx_level after setting it!")
......@@ -195,31 +200,20 @@ class Pybind11Extension(_Extension):
current_macos = tuple(int(x) for x in platform.mac_ver()[0].split(".")[:2])
desired_macos = (10, 9) if level < 17 else (10, 14)
macos_string = ".".join(str(x) for x in min(current_macos, desired_macos))
macosx_min = "-mmacosx-version-min=" + macos_string
macosx_min = "-mmacosx-version-min={}".format(macos_string)
cflags += [macosx_min]
ldflags += [macosx_min]
if PY2:
if WIN:
# Will be ignored on MSVC 2015, where C++17 is not supported so
# this flag is not valid.
cflags += ["/wd5033"]
elif level >= 17:
cflags += ["-Wno-register"]
elif level >= 14:
cflags += ["-Wno-deprecated-register"]
self._add_cflags(cflags)
self._add_ldflags(ldflags)
# Just in case someone clever tries to multithread
tmp_chdir_lock = threading.Lock()
cpp_cache_lock = threading.Lock()
@contextlib.contextmanager
def tmp_chdir():
def tmp_chdir() -> Iterator[str]:
"Prepare and enter a temporary directory, cleanup when done"
# Threadsafe
......@@ -235,7 +229,7 @@ def tmp_chdir():
# cf http://bugs.python.org/issue26689
def has_flag(compiler, flag):
def has_flag(compiler: Any, flag: str) -> bool:
"""
Return the flag if a flag name is supported on the
specified compiler, otherwise None (can be used as a boolean).
......@@ -243,13 +237,12 @@ def has_flag(compiler, flag):
"""
with tmp_chdir():
fname = "flagcheck.cpp"
with open(fname, "w") as f:
# Don't trigger -Wunused-parameter.
f.write("int main (int, char **) { return 0; }")
fname = Path("flagcheck.cpp")
# Don't trigger -Wunused-parameter.
fname.write_text("int main (int, char **) { return 0; }")
try:
compiler.compile([fname], extra_postargs=[flag])
compiler.compile([str(fname)], extra_postargs=[flag])
except distutils.errors.CompileError:
return False
return True
......@@ -259,7 +252,8 @@ def has_flag(compiler, flag):
cpp_flag_cache = None
def auto_cpp_level(compiler):
@lru_cache()
def auto_cpp_level(compiler: Any) -> Union[str, int]:
"""
Return the max supported C++ std level (17, 14, or 11). Returns latest on Windows.
"""
......@@ -267,48 +261,38 @@ def auto_cpp_level(compiler):
if WIN:
return "latest"
global cpp_flag_cache
# If this has been previously calculated with the same args, return that
with cpp_cache_lock:
if cpp_flag_cache:
return cpp_flag_cache
levels = [17, 14, 11]
for level in levels:
if has_flag(compiler, STD_TMPL.format(level)):
with cpp_cache_lock:
cpp_flag_cache = level
return level
msg = "Unsupported compiler -- at least C++11 support is needed!"
raise RuntimeError(msg)
class build_ext(_build_ext): # noqa: N801
class build_ext(_build_ext): # type: ignore[misc] # noqa: N801
"""
Customized build_ext that allows an auto-search for the highest supported
C++ level for Pybind11Extension. This is only needed for the auto-search
for now, and is completely optional otherwise.
"""
def build_extensions(self):
def build_extensions(self) -> None:
"""
Build extensions, injecting C++ std for Pybind11Extension if needed.
"""
for ext in self.extensions:
if hasattr(ext, "_cxx_level") and ext._cxx_level == 0:
# Python 2 syntax - old-style distutils class
ext.__class__.cxx_std.__set__(ext, auto_cpp_level(self.compiler))
ext.cxx_std = auto_cpp_level(self.compiler)
# Python 2 doesn't allow super here, since distutils uses old-style
# classes!
_build_ext.build_extensions(self)
super().build_extensions()
def intree_extensions(paths, package_dir=None):
def intree_extensions(
paths: Iterable[str], package_dir: Optional[Dict[str, str]] = None
) -> List[Pybind11Extension]:
"""
Generate Pybind11Extensions from source files directly located in a Python
source tree.
......@@ -318,6 +302,7 @@ def intree_extensions(paths, package_dir=None):
not contain an ``__init__.py`` file.
"""
exts = []
for path in paths:
if package_dir is None:
parent, _ = os.path.split(path)
......@@ -327,24 +312,25 @@ def intree_extensions(paths, package_dir=None):
qualified_name = relname.replace(os.path.sep, ".")
exts.append(Pybind11Extension(qualified_name, [path]))
else:
found = False
for prefix, parent in package_dir.items():
if path.startswith(parent):
found = True
relname, _ = os.path.splitext(os.path.relpath(path, parent))
qualified_name = relname.replace(os.path.sep, ".")
if prefix:
qualified_name = prefix + "." + qualified_name
exts.append(Pybind11Extension(qualified_name, [path]))
if not found:
raise ValueError(
"path {} is not a child of any of the directories listed "
"in 'package_dir' ({})".format(path, package_dir)
)
if not exts:
msg = (
"path {path} is not a child of any of the directories listed "
"in 'package_dir' ({package_dir})"
).format(path=path, package_dir=package_dir)
raise ValueError(msg)
return exts
def naive_recompile(obj, src):
def naive_recompile(obj: str, src: str) -> bool:
"""
This will recompile only if the source file changes. It does not check
header files, so a more advanced function or Ccache is better if you have
......@@ -353,7 +339,7 @@ def naive_recompile(obj, src):
return os.stat(obj).st_mtime < os.stat(src).st_mtime
def no_recompile(obg, src):
def no_recompile(obg: str, src: str) -> bool:
"""
This is the safest but slowest choice (and is the default) - will always
recompile sources.
......@@ -361,15 +347,33 @@ def no_recompile(obg, src):
return True
S = TypeVar("S", bound="ParallelCompile")
CCompilerMethod = Callable[
[
distutils.ccompiler.CCompiler,
List[str],
Optional[str],
Optional[Union[Tuple[str], Tuple[str, Optional[str]]]],
Optional[List[str]],
bool,
Optional[List[str]],
Optional[List[str]],
Optional[List[str]],
],
List[str],
]
# Optional parallel compile utility
# inspired by: http://stackoverflow.com/questions/11013851/speeding-up-build-process-with-distutils
# and: https://github.com/tbenthompson/cppimport/blob/stable/cppimport/build_module.py
# and NumPy's parallel distutils module:
# https://github.com/numpy/numpy/blob/master/numpy/distutils/ccompiler.py
class ParallelCompile(object):
class ParallelCompile:
"""
Make a parallel compile function. Inspired by
numpy.distutils.ccompiler.CCompiler_compile and cppimport.
numpy.distutils.ccompiler.CCompiler.compile and cppimport.
This takes several arguments that allow you to customize the compile
function created:
......@@ -404,35 +408,41 @@ class ParallelCompile(object):
__slots__ = ("envvar", "default", "max", "_old", "needs_recompile")
def __init__(self, envvar=None, default=0, max=0, needs_recompile=no_recompile):
def __init__(
self,
envvar: Optional[str] = None,
default: int = 0,
max: int = 0,
needs_recompile: Callable[[str, str], bool] = no_recompile,
) -> None:
self.envvar = envvar
self.default = default
self.max = max
self.needs_recompile = needs_recompile
self._old = []
self._old = [] # type: List[CCompilerMethod]
def function(self):
def function(self) -> CCompilerMethod:
"""
Builds a function object usable as distutils.ccompiler.CCompiler.compile.
"""
def compile_function(
compiler,
sources,
output_dir=None,
macros=None,
include_dirs=None,
debug=0,
extra_preargs=None,
extra_postargs=None,
depends=None,
):
compiler: distutils.ccompiler.CCompiler,
sources: List[str],
output_dir: Optional[str] = None,
macros: Optional[Union[Tuple[str], Tuple[str, Optional[str]]]] = None,
include_dirs: Optional[List[str]] = None,
debug: bool = False,
extra_preargs: Optional[List[str]] = None,
extra_postargs: Optional[List[str]] = None,
depends: Optional[List[str]] = None,
) -> Any:
# These lines are directly from distutils.ccompiler.CCompiler
macros, objects, extra_postargs, pp_opts, build = compiler._setup_compile(
macros, objects, extra_postargs, pp_opts, build = compiler._setup_compile( # type: ignore[attr-defined]
output_dir, macros, include_dirs, sources, depends, extra_postargs
)
cc_args = compiler._get_cc_args(pp_opts, debug, extra_preargs)
cc_args = compiler._get_cc_args(pp_opts, debug, extra_preargs) # type: ignore[attr-defined]
# The number of threads; start with default.
threads = self.default
......@@ -441,14 +451,14 @@ class ParallelCompile(object):
if self.envvar is not None:
threads = int(os.environ.get(self.envvar, self.default))
def _single_compile(obj):
def _single_compile(obj: Any) -> None:
try:
src, ext = build[obj]
except KeyError:
return
if not os.path.exists(obj) or self.needs_recompile(obj, src):
compiler._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
compiler._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) # type: ignore[attr-defined]
try:
# Importing .synchronize checks for platforms that have some multiprocessing
......@@ -466,14 +476,9 @@ class ParallelCompile(object):
threads = 1
if threads > 1:
pool = ThreadPool(threads)
# In Python 2, ThreadPool can't be used as a context manager.
# Once we are no longer supporting it, this can be 'with pool:'
try:
with ThreadPool(threads) as pool:
for _ in pool.imap_unordered(_single_compile, objects):
pass
finally:
pool.terminate()
else:
for ob in objects:
_single_compile(ob)
......@@ -482,13 +487,13 @@ class ParallelCompile(object):
return compile_function
def install(self):
distutils.ccompiler.CCompiler.compile = self.function()
def install(self: S) -> S:
distutils.ccompiler.CCompiler.compile = self.function() # type: ignore[assignment]
return self
def __enter__(self):
def __enter__(self: S) -> S:
self._old.append(distutils.ccompiler.CCompiler.compile)
return self.install()
def __exit__(self, *args):
distutils.ccompiler.CCompiler.compile = self._old.pop()
def __exit__(self, *args: Any) -> None:
distutils.ccompiler.CCompiler.compile = self._old.pop() # type: ignore[assignment]
# IMPORTANT: Should stay in sync with setup_helpers.py (mostly checked by CI /
# pre-commit).
import contextlib
import distutils.ccompiler
from distutils.command.build_ext import build_ext as _build_ext # type: ignore
from distutils.extension import Extension as _Extension
from types import TracebackType
from typing import Any, Callable, Dict, Iterator, List, Optional, Type, TypeVar, Union
WIN: bool
PY2: bool
MACOS: bool
STD_TMPL: str
class Pybind11Extension(_Extension):
def _add_cflags(self, *flags: str) -> None: ...
def _add_lflags(self, *flags: str) -> None: ...
def __init__(
self, *args: Any, cxx_std: int = 0, language: str = "c++", **kwargs: Any
) -> None: ...
@property
def cxx_std(self) -> int: ...
@cxx_std.setter
def cxx_std(self, level: int) -> None: ...
@contextlib.contextmanager
def tmp_chdir() -> Iterator[str]: ...
def has_flag(compiler: distutils.ccompiler.CCompiler, flag: str) -> bool: ...
def auto_cpp_level(compiler: distutils.ccompiler.CCompiler) -> Union[int, str]: ...
class build_ext(_build_ext): # type: ignore
def build_extensions(self) -> None: ...
def intree_extensions(
paths: Iterator[str], package_dir: Optional[Dict[str, str]] = None
) -> List[Pybind11Extension]: ...
def no_recompile(obj: str, src: str) -> bool: ...
def naive_recompile(obj: str, src: str) -> bool: ...
T = TypeVar("T", bound="ParallelCompile")
class ParallelCompile:
envvar: Optional[str]
default: int
max: int
needs_recompile: Callable[[str, str], bool]
def __init__(
self,
envvar: Optional[str] = None,
default: int = 0,
max: int = 0,
needs_recompile: Callable[[str, str], bool] = no_recompile,
) -> None: ...
def function(self) -> Any: ...
def install(self: T) -> T: ...
def __enter__(self: T) -> T: ...
def __exit__(
self,
exc_type: Optional[Type[BaseException]],
exc_value: Optional[BaseException],
traceback: Optional[TracebackType],
) -> None: ...
......@@ -22,20 +22,11 @@ known_first_party = "env,pybind11_cross_module_tests,pybind11_tests,"
profile = "black"
[tool.mypy]
files = "pybind11"
python_version = "2.7"
files = ["pybind11"]
python_version = "3.6"
warn_unused_configs = true
strict = true
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_return_any = true
no_implicit_reexport = true
strict_equality = true
[[tool.mypy.overrides]]
module = ["ghapi.*", "setuptools.*"]
ignore_missing_imports = true
......@@ -13,8 +13,7 @@ classifiers =
Topic :: Software Development :: Libraries :: Python Modules
Topic :: Utilities
Programming Language :: C++
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
......@@ -39,15 +38,12 @@ project_urls =
Chat = https://gitter.im/pybind/Lobby
[options]
python_requires = >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
python_requires = >=3.5
zip_safe = False
[bdist_wheel]
universal=1
[flake8]
max-line-length = 99
max-line-length = 120
show_source = True
exclude = .git, __pycache__, build, dist, docs, tools, venv
ignore =
......
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Setup script for PyPI; use CMakeFile.txt to build extension modules
import contextlib
import io
import os
import re
import shutil
import string
import subprocess
import sys
import tempfile
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Dict, Iterator, List, Union
import setuptools.command.sdist
DIR = os.path.abspath(os.path.dirname(__file__))
DIR = Path(__file__).parent.absolute()
VERSION_REGEX = re.compile(
r"^\s*#\s*define\s+PYBIND11_VERSION_([A-Z]+)\s+(.*)$", re.MULTILINE
)
VERSION_FILE = Path("pybind11/_version.py")
COMMON_FILE = Path("include/pybind11/detail/common.h")
def build_expected_version_hex(matches):
def build_expected_version_hex(matches: Dict[str, str]) -> str:
patch_level_serial = matches["PATCH"]
serial = None
try:
major = int(matches["MAJOR"])
minor = int(matches["MINOR"])
flds = patch_level_serial.split(".")
if flds:
patch = int(flds[0])
level = None
if len(flds) == 1:
level = "0"
serial = 0
elif len(flds) == 2:
level_serial = flds[1]
for level in ("a", "b", "c", "dev"):
if level_serial.startswith(level):
serial = int(level_serial[len(level) :])
break
except ValueError:
pass
major = int(matches["MAJOR"])
minor = int(matches["MINOR"])
flds = patch_level_serial.split(".")
if flds:
patch = int(flds[0])
if len(flds) == 1:
level = "0"
serial = 0
elif len(flds) == 2:
level_serial = flds[1]
for level in ("a", "b", "c", "dev"):
if level_serial.startswith(level):
serial = int(level_serial[len(level) :])
break
if serial is None:
msg = 'Invalid PYBIND11_VERSION_PATCH: "{}"'.format(patch_level_serial)
raise RuntimeError(msg)
return (
"0x"
+ "{:02x}{:02x}{:02x}{}{:x}".format(
major, minor, patch, level[:1], serial
).upper()
version_hex_str = "{:02x}{:02x}{:02x}{}{:x}".format(
major, minor, patch, level[:1], serial
)
return "0x{}".format(version_hex_str.upper())
# PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers
......@@ -58,24 +54,25 @@ def build_expected_version_hex(matches):
global_sdist = os.environ.get("PYBIND11_GLOBAL_SDIST", False)
setup_py = "tools/setup_global.py.in" if global_sdist else "tools/setup_main.py.in"
setup_py = Path(
"tools/setup_global.py.in" if global_sdist else "tools/setup_main.py.in"
)
extra_cmd = 'cmdclass["sdist"] = SDist\n'
to_src = (
("pyproject.toml", "tools/pyproject.toml"),
("setup.py", setup_py),
(Path("pyproject.toml"), Path("tools/pyproject.toml")),
(Path("setup.py"), setup_py),
)
# Read the listed version
with open("pybind11/_version.py") as f:
code = compile(f.read(), "pybind11/_version.py", "exec")
loc = {}
loc = {} # type: Dict[str, str]
code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
exec(code, loc)
version = loc["__version__"]
# Verify that the version matches the one in C++
with io.open("include/pybind11/detail/common.h", encoding="utf8") as f:
matches = dict(VERSION_REGEX.findall(f.read()))
matches = dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding="utf8")))
cpp_version = "{MAJOR}.{MINOR}.{PATCH}".format(**matches)
if version != cpp_version:
msg = "Python version {} does not match C++ version {}!".format(
......@@ -84,56 +81,44 @@ if version != cpp_version:
raise RuntimeError(msg)
version_hex = matches.get("HEX", "MISSING")
expected_version_hex = build_expected_version_hex(matches)
if version_hex != expected_version_hex:
exp_version_hex = build_expected_version_hex(matches)
if version_hex != exp_version_hex:
msg = "PYBIND11_VERSION_HEX {} does not match expected value {}!".format(
version_hex,
expected_version_hex,
version_hex, exp_version_hex
)
raise RuntimeError(msg)
def get_and_replace(filename, binary=False, **opts):
with open(filename, "rb" if binary else "r") as f:
contents = f.read()
# Replacement has to be done on text in Python 3 (both work in Python 2)
# TODO: use literals & overload (typing extensions or Python 3.8)
def get_and_replace(
filename: Path, binary: bool = False, **opts: str
) -> Union[bytes, str]:
if binary:
contents = filename.read_bytes()
return string.Template(contents.decode()).substitute(opts).encode()
else:
return string.Template(contents).substitute(opts)
return string.Template(filename.read_text()).substitute(opts)
# Use our input files instead when making the SDist (and anything that depends
# on it, like a wheel)
class SDist(setuptools.command.sdist.sdist):
def make_release_tree(self, base_dir, files):
setuptools.command.sdist.sdist.make_release_tree(self, base_dir, files)
class SDist(setuptools.command.sdist.sdist): # type: ignore[misc]
def make_release_tree(self, base_dir: str, files: List[str]) -> None:
super().make_release_tree(base_dir, files)
for to, src in to_src:
txt = get_and_replace(src, binary=True, version=version, extra_cmd="")
dest = os.path.join(base_dir, to)
dest = Path(base_dir) / to
# This is normally linked, so unlink before writing!
os.unlink(dest)
with open(dest, "wb") as f:
f.write(txt)
# Backport from Python 3
@contextlib.contextmanager
def TemporaryDirectory(): # noqa: N802
"Prepare a temporary directory, cleanup when done"
try:
tmpdir = tempfile.mkdtemp()
yield tmpdir
finally:
shutil.rmtree(tmpdir)
dest.unlink()
dest.write_bytes(txt) # type: ignore[arg-type]
# Remove the CMake install directory when done
@contextlib.contextmanager
def remove_output(*sources):
def remove_output(*sources: str) -> Iterator[None]:
try:
yield
finally:
......@@ -156,9 +141,14 @@ with remove_output("pybind11/include", "pybind11/share"):
if "DCMAKE_INSTALL_PREFIX" not in c
]
cmd += fcommand
cmake_opts = dict(cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
subprocess.check_call(cmd, **cmake_opts)
subprocess.check_call(["cmake", "--install", tmpdir], **cmake_opts)
subprocess.run(cmd, check=True, cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
subprocess.run(
["cmake", "--install", tmpdir],
check=True,
cwd=DIR,
stdout=sys.stdout,
stderr=sys.stderr,
)
txt = get_and_replace(setup_py, version=version, extra_cmd=extra_cmd)
code = compile(txt, setup_py, "exec")
......
......@@ -179,11 +179,6 @@ if(PYBIND11_TEST_FILTER)
pybind11_filter_tests(PYBIND11_TEST_FILES ${PYBIND11_TEST_FILTER})
endif()
if(PYTHON_VERSION VERSION_LESS 3.5)
pybind11_filter_tests(PYBIND11_TEST_FILES test_async.cpp MESSAGE
"Skipping test_async on Python 2")
endif()
# Skip tests for CUDA check:
# /pybind11/tests/test_constants_and_functions.cpp(125):
# error: incompatible exception specifications
......@@ -388,17 +383,6 @@ function(pybind11_enable_warnings target_name)
-diag-disable 11074,11076)
endif()
endif()
# Needs to be re-added since the ordering requires these to be after the ones above
if(CMAKE_CXX_STANDARD
AND CMAKE_CXX_COMPILER_ID MATCHES "Clang"
AND PYTHON_VERSION VERSION_LESS 3.0)
if(CMAKE_CXX_STANDARD LESS 17)
target_compile_options(${target_name} PUBLIC -Wno-deprecated-register)
else()
target_compile_options(${target_name} PUBLIC -Wno-register)
endif()
endif()
endfunction()
set(test_targets pybind11_tests)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment