Repository: apytypes/apytypes (language: python)

Issue:
windows-latest runner failing to build apytypes
Since about yesterday, June 6th, the windows-latest runners are failing to build the apytypes project with an MSVC internal compiler error, for all versions of Python.

It's likely a problem upstream. Possibly in the GitHub windows-server runner, but I'm not 100 % sure about this. 

Related issues:
* https://github.com/wjakob/nanobind/issues/613
* https://github.com/actions/runner-images/issues/10004


Discussion / hints:
A temporary fix, falling back to the GitHub runner `windows-2019` and adding a MSVC2019 hot-fix, was added in #471 (d2de1d4).

Before closing this issue, revert all changes added in d2de1d4.
Should also revert the change in #472 for the CI Build Wheel (not the version bump).

Fix patch:
diff --git a/src/python_util.h b/src/python_util.h
index c82128a42..b667c8d46 100644
--- a/src/python_util.h
+++ b/src/python_util.h
@@ -358,62 +358,9 @@ python_sequence_extract_shape(const nanobind::sequence& bit_pattern_sequence)
  * `bit_pattern_sequence` does not match `<T>` or another Python sequence a
  * `std::domain_error` exception to be raised.
  */
-// template <typename... PyTypes>
-//[[maybe_unused]] static std::vector<nanobind::object>
-// python_sequence_walk(const nanobind::sequence& py_seq)
-//{
-//     namespace nb = nanobind;
-//
-//     // Result output iterator
-//     std::vector<nb::object> result {};
-//
-//     // Walk the Python sequences and extract the data
-//     struct seq_it_pair {
-//         decltype(std::begin(py_seq)) iterator;
-//         decltype(std::end(py_seq)) sentinel;
-//     };
-//     std::stack<seq_it_pair, std::vector<seq_it_pair>> it_stack;
-//     it_stack.push({ py_seq.begin(), py_seq.end() });
-//
-//     while (!it_stack.empty()) {
-//         if (it_stack.top().iterator == it_stack.top().sentinel) {
-//             // End of current iterator/sentinel pair. Pop it.
-//             it_stack.pop();
-//         } else {
-//             if (nb::isinstance<nb::sequence>(*it_stack.top().iterator)) {
-//                 // New sequence found. We need to go deeper
-//                 auto new_sequence =
-//                 nb::cast<nb::sequence>(*it_stack.top().iterator++); it_stack.push({
-//                 new_sequence.begin(), new_sequence.end() });
-//             } else if ((nb::isinstance<PyTypes>(*it_stack.top().iterator) || ...)) {
-//                 // Element matching one of the PyTypes found, store it in container
-//                 result.push_back(nb::cast<nb::object>(*it_stack.top().iterator++));
-//             } else {
-//                 nb::object obj = nb::cast<nb::object>(*it_stack.top().iterator);
-//                 nb::type_object type = nb::cast<nb::type_object>(obj.type());
-//                 nb::str type_string = nb::str(type);
-//                 nb::str repr = nb::repr(obj);
-//                 std::string repr_string = repr.c_str();
-//                 throw std::domain_error(
-//                     std::string("Non <type>/sequence found when walking: '")
-//                     + repr_string + "' of type: '" + type_string.c_str()
-//                 );
-//             }
-//         }
-//     }
-//
-//     // Return the result
-//     return result;
-// }
-//
-//  MSVC2019 hot-fix:
-//
 template <typename... PyTypes>
 [[maybe_unused]] static std::vector<nanobind::object>
-python_sequence_walk(const nanobind::sequence& py_seq);
-template <>
-[[maybe_unused]] std::vector<nanobind::object>
-python_sequence_walk<nanobind::int_>(const nanobind::sequence& py_seq)
+python_sequence_walk(const nanobind::sequence& py_seq)
 {
     namespace nb = nanobind;
 
@@ -437,101 +384,7 @@ python_sequence_walk<nanobind::int_>(const nanobind::sequence& py_seq)
                 // New sequence found. We need to go deeper
                 auto new_sequence = nb::cast<nb::sequence>(*it_stack.top().iterator++);
                 it_stack.push({ new_sequence.begin(), new_sequence.end() });
-            } else if ((nb::isinstance<nb::int_>(*it_stack.top().iterator))) {
-                // Element matching one of the PyTypes found, store it in container
-                result.push_back(nb::cast<nb::object>(*it_stack.top().iterator++));
-            } else {
-                nb::object obj = nb::cast<nb::object>(*it_stack.top().iterator);
-                nb::type_object type = nb::cast<nb::type_object>(obj.type());
-                nb::str type_string = nb::str(type);
-                nb::str repr = nb::repr(obj);
-                std::string repr_string = repr.c_str();
-                throw std::domain_error(
-                    std::string("Non <type>/sequence found when walking: '")
-                    + repr_string + "' of type: '" + type_string.c_str()
-                );
-            }
-        }
-    }
-
-    // Return the result
-    return result;
-}
-template <>
-[[maybe_unused]] std::vector<nanobind::object>
-python_sequence_walk<nanobind::float_, nanobind::int_>(const nanobind::sequence& py_seq)
-{
-    namespace nb = nanobind;
-
-    // Result output iterator
-    std::vector<nb::object> result {};
-
-    // Walk the Python sequences and extract the data
-    struct seq_it_pair {
-        decltype(std::begin(py_seq)) iterator;
-        decltype(std::end(py_seq)) sentinel;
-    };
-    std::stack<seq_it_pair, std::vector<seq_it_pair>> it_stack;
-    it_stack.push({ py_seq.begin(), py_seq.end() });
-
-    while (!it_stack.empty()) {
-        if (it_stack.top().iterator == it_stack.top().sentinel) {
-            // End of current iterator/sentinel pair. Pop it.
-            it_stack.pop();
-        } else {
-            if (nb::isinstance<nb::sequence>(*it_stack.top().iterator)) {
-                // New sequence found. We need to go deeper
-                auto new_sequence = nb::cast<nb::sequence>(*it_stack.top().iterator++);
-                it_stack.push({ new_sequence.begin(), new_sequence.end() });
-            } else if ((nb::isinstance<nb::int_>(*it_stack.top().iterator)
-                        || nb::isinstance<nb::float_>(*it_stack.top().iterator))) {
-                // Element matching one of the PyTypes found, store it in container
-                result.push_back(nb::cast<nb::object>(*it_stack.top().iterator++));
-            } else {
-                nb::object obj = nb::cast<nb::object>(*it_stack.top().iterator);
-                nb::type_object type = nb::cast<nb::type_object>(obj.type());
-                nb::str type_string = nb::str(type);
-                nb::str repr = nb::repr(obj);
-                std::string repr_string = repr.c_str();
-                throw std::domain_error(
-                    std::string("Non <type>/sequence found when walking: '")
-                    + repr_string + "' of type: '" + type_string.c_str()
-                );
-            }
-        }
-    }
-
-    // Return the result
-    return result;
-}
-template <>
-[[maybe_unused]] std::vector<nanobind::object>
-python_sequence_walk<nanobind::int_, nanobind::bool_>(const nanobind::sequence& py_seq)
-{
-    namespace nb = nanobind;
-
-    // Result output iterator
-    std::vector<nb::object> result {};
-
-    // Walk the Python sequences and extract the data
-    struct seq_it_pair {
-        decltype(std::begin(py_seq)) iterator;
-        decltype(std::end(py_seq)) sentinel;
-    };
-    std::stack<seq_it_pair, std::vector<seq_it_pair>> it_stack;
-    it_stack.push({ py_seq.begin(), py_seq.end() });
-
-    while (!it_stack.empty()) {
-        if (it_stack.top().iterator == it_stack.top().sentinel) {
-            // End of current iterator/sentinel pair. Pop it.
-            it_stack.pop();
-        } else {
-            if (nb::isinstance<nb::sequence>(*it_stack.top().iterator)) {
-                // New sequence found. We need to go deeper
-                auto new_sequence = nb::cast<nb::sequence>(*it_stack.top().iterator++);
-                it_stack.push({ new_sequence.begin(), new_sequence.end() });
-            } else if ((nb::isinstance<nb::int_>(*it_stack.top().iterator)
-                        || nb::isinstance<nb::bool_>(*it_stack.top().iterator))) {
+            } else if ((nb::isinstance<PyTypes>(*it_stack.top().iterator) || ...)) {
                 // Element matching one of the PyTypes found, store it in container
                 result.push_back(nb::cast<nb::object>(*it_stack.top().iterator++));
             } else {


Test patch:
diff --git a/.github/workflows/publish-test-pypi.yml b/.github/workflows/publish-test-pypi.yml
index e05302e2a..64f4e9cc1 100644
--- a/.github/workflows/publish-test-pypi.yml
+++ b/.github/workflows/publish-test-pypi.yml
@@ -35,7 +35,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
-        os: ["ubuntu-latest", "macos-12", "macos-14", "windows-2019"]
+        os: ["ubuntu-latest", "macos-12", "macos-14", "windows-latest"]
 
     steps:
       - uses: actions/checkout@v4
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 4f5ca364d..1e0c7c559 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -23,7 +23,7 @@ jobs:
       fail-fast: false
       matrix:
         python-version: ["3.9", "3.10", "3.11", "3.12", "3.13-dev"]
-        os: ["macos-12", "ubuntu-latest", "windows-2019", "macos-14"]
+        os: ["macos-12", "ubuntu-latest", "windows-latest", "macos-14"]
         numpy-version: ["1.26.4", "2.0.0rc2"]
         exclude:
           # Only test NumPy2 on 3.12 for now