diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..d611e1496 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +docs/*.svg binary diff --git a/.github/matchers/pylint.json b/.github/matchers/pylint.json new file mode 100644 index 000000000..e3a6bd16b --- /dev/null +++ b/.github/matchers/pylint.json @@ -0,0 +1,32 @@ +{ + "problemMatcher": [ + { + "severity": "warning", + "pattern": [ + { + "regexp": "^([^:]+):(\\d+):(\\d+): ([A-DF-Z]\\d+): \\033\\[[\\d;]+m([^\\033]+).*$", + "file": 1, + "line": 2, + "column": 3, + "code": 4, + "message": 5 + } + ], + "owner": "pylint-warning" + }, + { + "severity": "error", + "pattern": [ + { + "regexp": "^([^:]+):(\\d+):(\\d+): (E\\d+): \\033\\[[\\d;]+m([^\\033]+).*$", + "file": 1, + "line": 2, + "column": 3, + "code": 4, + "message": 5 + } + ], + "owner": "pylint-error" + } + ] +} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d6b74dfbe..3eb4e7b42 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,8 +30,8 @@ jobs: - '3.6' - '3.9' - '3.10' - - 'pypy-3.7-v7.3.7' - - 'pypy-3.8-v7.3.7' + - 'pypy-3.7' + - 'pypy-3.8' # Items in here will either be added to the build matrix (if not # present), or add new keys to an existing matrix element if all the @@ -45,7 +45,7 @@ jobs: args: > -DPYBIND11_FINDPYTHON=ON -DCMAKE_CXX_FLAGS="-D_=1" - - runs-on: windows-latest + - runs-on: windows-2019 python: '3.6' args: > -DPYBIND11_FINDPYTHON=ON @@ -713,12 +713,12 @@ jobs: include: - python: 3.9 - args: -DCMAKE_CXX_STANDARD=20 -DDOWNLOAD_EIGEN=OFF + args: -DCMAKE_CXX_STANDARD=20 - python: 3.8 args: -DCMAKE_CXX_STANDARD=17 name: "🐍 ${{ matrix.python }} • MSVC 2019 • x86 ${{ matrix.args }}" - runs-on: windows-latest + runs-on: windows-2019 steps: - uses: actions/checkout@v2 @@ -836,7 +836,7 @@ jobs: cmake -S . -B build -DPYBIND11_WERROR=ON -DDOWNLOAD_CATCH=ON - -DDOWNLOAD_EIGEN=OFF + -DDOWNLOAD_EIGEN=ON -DCMAKE_CXX_STANDARD=20 - name: Build C++20 diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index ab7b40503..46140fe0c 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -12,6 +12,9 @@ on: - stable - "v*" +env: + FORCE_COLOR: 3 + jobs: pre-commit: name: Format @@ -19,6 +22,8 @@ jobs: steps: - uses: actions/checkout@v2 - uses: actions/setup-python@v2 + - name: Add matchers + run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/matchers/pylint.json" - uses: pre-commit/action@v2.0.3 with: # Slow hooks are marked with manual - slow is okay here, run them too diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8ab7117fe..e9a0e03f2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -59,7 +59,7 @@ repos: # Changes tabs to spaces - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: "v1.1.12" + rev: "v1.1.13" hooks: - id: remove-tabs @@ -71,7 +71,7 @@ repos: # Autoremoves unused imports - repo: https://github.com/hadialqattan/pycln - rev: "v1.1.0" + rev: "v1.2.4" hooks: - id: pycln @@ -87,23 +87,30 @@ repos: - id: rst-directive-colons - id: rst-inline-touching-normal -# Flake8 also supports pre-commit natively (same author) -- repo: https://github.com/PyCQA/flake8 - rev: "4.0.1" - hooks: - - id: flake8 - additional_dependencies: &flake8_dependencies - - flake8-bugbear - - pep8-naming - exclude: ^(docs/.*|tools/.*)$ - # Automatically remove noqa that are not used - repo: https://github.com/asottile/yesqa rev: "v1.3.0" hooks: - id: yesqa + additional_dependencies: &flake8_dependencies + - flake8-bugbear + - pep8-naming + +# Flake8 also supports pre-commit natively (same author) +- repo: https://github.com/PyCQA/flake8 + rev: "4.0.1" + hooks: + - id: flake8 + exclude: ^(docs/.*|tools/.*)$ additional_dependencies: *flake8_dependencies +# PyLint has native support - not always usable, but works for us +- repo: https://github.com/PyCQA/pylint + rev: "v2.12.2" + hooks: + - id: pylint + files: ^pybind11 + # CMake formatting - repo: https://github.com/cheshirekow/cmake-format-precommit rev: "v0.6.13" @@ -156,6 +163,7 @@ repos: # Clang format the codebase automatically - repo: https://github.com/pre-commit/mirrors-clang-format - rev: "v13.0.0" + rev: "v13.0.1" hooks: - id: clang-format + types_or: [c++, c, cuda] diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 553d7616c..d45b49c52 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -85,11 +85,15 @@ protected: \ public: \ static constexpr auto name = py_name; \ - template >::value, int> = 0> \ - static handle cast(T_ *src, return_value_policy policy, handle parent) { \ + template >::value, \ + int> = 0> \ + static ::pybind11::handle cast( \ + T_ *src, ::pybind11::return_value_policy policy, ::pybind11::handle parent) { \ if (!src) \ - return none().release(); \ - if (policy == return_value_policy::take_ownership) { \ + return ::pybind11::none().release(); \ + if (policy == ::pybind11::return_value_policy::take_ownership) { \ auto h = cast(std::move(*src), policy, parent); \ delete src; \ return h; \ @@ -100,7 +104,7 @@ public: operator type &() { return value; } /* NOLINT(bugprone-macro-parentheses) */ \ operator type &&() && { return std::move(value); } /* NOLINT(bugprone-macro-parentheses) */ \ template \ - using cast_op_type = pybind11::detail::movable_cast_op_type + using cast_op_type = ::pybind11::detail::movable_cast_op_type template using is_std_char_type = any_of, /* std::string */ @@ -380,7 +384,7 @@ struct string_caster { return false; } if (!PyUnicode_Check(load_src.ptr())) { - return load_bytes(load_src); + return load_raw(load_src); } // For UTF-8 we avoid the need for a temporary `bytes` object by using @@ -458,26 +462,37 @@ private: #endif } - // When loading into a std::string or char*, accept a bytes object as-is (i.e. + // When loading into a std::string or char*, accept a bytes/bytearray object as-is (i.e. // without any encoding/decoding attempt). For other C++ char sizes this is a no-op. // which supports loading a unicode from a str, doesn't take this path. template - bool load_bytes(enable_if_t::value, handle> src) { + bool load_raw(enable_if_t::value, handle> src) { if (PYBIND11_BYTES_CHECK(src.ptr())) { // We were passed raw bytes; accept it into a std::string or char* // without any encoding attempt. const char *bytes = PYBIND11_BYTES_AS_STRING(src.ptr()); - if (bytes) { - value = StringType(bytes, (size_t) PYBIND11_BYTES_SIZE(src.ptr())); - return true; + if (!bytes) { + pybind11_fail("Unexpected PYBIND11_BYTES_AS_STRING() failure."); } + value = StringType(bytes, (size_t) PYBIND11_BYTES_SIZE(src.ptr())); + return true; + } + if (PyByteArray_Check(src.ptr())) { + // We were passed a bytearray; accept it into a std::string or char* + // without any encoding attempt. + const char *bytearray = PyByteArray_AsString(src.ptr()); + if (!bytearray) { + pybind11_fail("Unexpected PyByteArray_AsString() failure."); + } + value = StringType(bytearray, (size_t) PyByteArray_Size(src.ptr())); + return true; } return false; } template - bool load_bytes(enable_if_t::value, handle>) { + bool load_raw(enable_if_t::value, handle>) { return false; } }; diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h index ebdc07271..e52ec1d3e 100644 --- a/include/pybind11/detail/class.h +++ b/include/pybind11/detail/class.h @@ -101,14 +101,14 @@ inline PyTypeObject *make_static_property_type() { inline PyTypeObject *make_static_property_type() { auto d = dict(); PyObject *result = PyRun_String(R"(\ - class pybind11_static_property(property): - def __get__(self, obj, cls): - return property.__get__(self, cls, cls) +class pybind11_static_property(property): + def __get__(self, obj, cls): + return property.__get__(self, cls, cls) - def __set__(self, obj, value): - cls = obj if isinstance(obj, type) else type(obj) - property.__set__(self, cls, value) - )", + def __set__(self, obj, value): + cls = obj if isinstance(obj, type) else type(obj) + property.__set__(self, cls, value) +)", Py_file_input, d.ptr(), d.ptr()); diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 1070d686e..ea09bb3fd 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -822,7 +822,9 @@ struct is_template_base_of_impl { /// Check if a template is the base of a type. For example: /// `is_template_base_of` is true if `struct T : Base {}` where U can be anything template