-
Notifications
You must be signed in to change notification settings - Fork 10
Improve test coverage for Python support #213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Improve test coverage for Python support #213
Conversation
|
@phlexbot format |
|
Automatic cmake-format fixes pushed (commit e60d811). |
|
@phlexbot format |
|
No automatic cmake-format fixes were necessary. |
|
Automatic clang-format fixes pushed (commit 2aa7957). |
|
@phlexbot python-fix |
|
Automatic Python linting fixes pushed (commit 092dec4). |
Codecov Report❌ Patch coverage is ❌ Your patch check has failed because the patch coverage (72.60%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage. @@ Coverage Diff @@
## main #213 +/- ##
==========================================
+ Coverage 74.28% 78.22% +3.94%
==========================================
Files 124 124
Lines 2955 3261 +306
Branches 513 588 +75
==========================================
+ Hits 2195 2551 +356
+ Misses 540 448 -92
- Partials 220 262 +42
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 1 file with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
38fc738 to
47661fa
Compare
|
@phlexbot format |
|
No automatic clang-format fixes were necessary. |
|
Automatic cmake-format fixes pushed (commit bb954c8). |
|
@phlexbot python-fix |
|
Automatic Python linting fixes pushed (commit cfdb09a). |
c9ccf06 to
1159796
Compare
|
@phlexbot format |
|
Automatic clang-format fixes pushed (commit b145a22). |
|
@phlexbot format |
|
Automatic cmake-format fixes pushed (commit cc928e7). |
|
No automatic clang-format fixes were necessary. |
This commit renames the `AdjustAnnotations` class to `Variant` in both Python and C++ source files, as well as in tests and build configurations. All references to the old name have been removed, and related files have been renamed for consistency. - Renamed `AdjustAnnotations` to `Variant` in `plugins/python/python/phlex/__init__.py` - Renamed C++ class `AdjustAnnotations` to `Variant` in `plugins/python/src/modulewrap.cpp` - Updated `test/python/adder.py` to use `Variant` - Renamed `test/python/unit_test_annotations.py` to `test/python/unit_test_variant.py` - Renamed `test/python/pymismatch_annotations.jsonnet` to `test/python/pymismatch_variant.jsonnet` - Updated `test/python/CMakeLists.txt` to reflect the name and file changes. Co-authored-by: greenc-FNAL <[email protected]>
This commit reverts the use of the `PyObjectPtr` RAII wrapper to `intptr_t` in `modulewrap.cpp` and restores fixed-offset string comparisons for NumPy types, as requested to align with parallel work. Key changes: - Reverted `PyObjectPtr` to `intptr_t` throughout `modulewrap.cpp`. - Restored manual reference counting in callbacks and converters. - Reverted substring searches to fixed-offset comparisons using `compare()`. - Preserved the `float64` type correction in type comparisons. - Preserved all new test coverage and reference-counting fixes. Co-authored-by: greenc-FNAL <[email protected]>
Modified `insert_input_converters` and `md_transform` in `plugins/python/src/modulewrap.cpp` to use fixed-length comparisons for NumPy dtypes. The previous use of `std::string::npos` required the dtype suffix (e.g., `"int32]]"`) to be at the absolute end of the annotation string. With the introduction of PEP 604 union types (e.g., `ndarray | list`), the annotation string can contain trailing characters, causing matching to fail. Using an explicit length in `std::string::compare` allows the matcher to correctly identify the dtype regardless of trailing content. Co-authored-by: greenc-FNAL <[email protected]>
- Added safety checks for null ports in `phlex/core/edge_maker.cpp` and `phlex/core/edge_maker.hpp` to prevent intermittent segfaults during graph setup, especially in benchmarks. - Improved diagnostic error messages when null ports are encountered. Co-authored-by: greenc-FNAL <[email protected]>
This commit addresses several issues in the Python support plugin: 1. AttributeError in Variant: Added __code__ and __defaults__ attributes to the Variant class to support introspection and fix unit tests. 2. Robust Annotation Parsing: Updated parse_args in modulewrap.cpp to use PyDict_Next and explicitly skip the "return" key, fulfilling the requirement to handle OrderedDicts correctly. 3. Extended List Support: Added support for list[unsigned int], list[long], and list[unsigned long] in modulewrap.cpp converters. 4. Precise Annotations: Updated vectypes.py to use string literal annotations that match the new C++ converters. These changes resolve the reported failures in unit_test_variant, py:vectypes, and py:veclists. Co-authored-by: greenc-FNAL <[email protected]>
…ting issues This commit addresses several issues in the Python support plugin: 1. AttributeError in Variant: Added __code__ and __defaults__ attributes to the Variant class to support introspection and fix unit tests. 2. Robust Annotation Parsing: Updated parse_args in modulewrap.cpp to use PyDict_Next and explicitly skip the "return" key, fulfilling the requirement to handle OrderedDicts correctly. 3. Extended List Support: Added support for list[unsigned int], list[long], and list[unsigned long] in modulewrap.cpp converters. 4. Precise Annotations and Linting: Updated vectypes.py to use string literal annotations that match the new C++ converters and added necessary ruff/mypy suppression comments to resolve CI failures. 5. Improved Type Safety in Tests: Updated list return values in vectypes.py to use correct type constructors (e.g., long()). These changes resolve the reported failures in unit_test_variant, py:vectypes, py:veclists, and the subsequent CI linting failures. Co-authored-by: greenc-FNAL <[email protected]>
…ve checks This commit addresses several issues in the Python support plugin: 1. AttributeError in Variant: Added __code__ and __defaults__ attributes to the Variant class to support introspection and fix unit tests. 2. Robust Annotation Parsing: Updated parse_args in modulewrap.cpp to use PyDict_Next and explicitly skip the "return" key, fulfilling the requirement to handle OrderedDicts correctly. 3. Extended List Support: Added support for list[unsigned int], list[long], and list[unsigned long] in modulewrap.cpp converters. 4. Precise Annotations and Linting: Updated vectypes.py to use string literal annotations that match the new C++ converters and added necessary ruff/mypy suppression comments. 5. Defensive Fixes in C++: - Added NULL check in lifeline_transform before calling Py_TYPE. - Fixed py_callback assignment operator reference counting. - Ensured lifeline_transform is used for observers (callv). - Robustified annotation_as_text with extra NULL checks. These changes resolve the reported failures in unit_test_variant, py:vectypes, py:veclists, and ensure the code passes CI linting. Co-authored-by: greenc-FNAL <[email protected]>
This commit fixes multiple issues reported in GitHub Actions: 1. Fixes AttributeError in unit_test_variant.py by exposing __code__ and __defaults__ in the Variant class. 2. Robustifies annotation parsing in modulewrap.cpp by iterating over input_labels and using named lookups, ensuring correct type-to-argument mapping and skipping the "return" annotation correctly. 3. Adds support for list[unsigned int], list[long], and list[unsigned long] in the Python bridge. 4. Fixes SegFaults and "missing positional argument" errors by adding comprehensive NULL checks in VECTOR_CONVERTER and py_callback, and transitioning py_callback to use PyObject_Call with argument tuples. 5. Updates test/python/vectypes.py with precise string annotations and linter suppressions to satisfy ruff and mypy. Co-authored-by: greenc-FNAL <[email protected]>
This commit addresses the "bundle of failures" caused by the previous attempt and ensures proper reference counting: 1. Restores positional annotation parsing in modulewrap.cpp using PyDict_Next with skip-return logic. This ensures compatibility when Phlex labels do not match Python parameter names (fixing py:basic/py:add). 2. Correctly enforces annotation count matching, fixing py:mismatch. 3. Fixes reference leaks in md_transform and md_observe by adding Py_DECREF(callable) after ownership is transferred to the callback. 4. Uses PyObject_TypeCheck in lifeline_transform for safer type validation. 5. Maintains robust argument passing and NULL handling in py_callback. 6. Keeps Variant introspection attributes in phlex/__init__.py. Co-authored-by: greenc-FNAL <[email protected]>
This commit addresses multiple issues:
1. Fixes AttributeError in unit_test_variant.py by exposing __code__ and
__defaults__ in the Variant class.
2. Robustifies annotation parsing in modulewrap.cpp by ensuring correct
ordering and robustly skipping the "return" annotation.
3. Fixes SegFaults in Python-C++ bridge by:
- Ensuring the GIL is held during py_callback construction.
- Adding NULL checks for m_callable in py_callback methods.
- Replacing placement new with assignment in VECTOR_CONVERTER to avoid
double construction of std::shared_ptr.
- Correctly managing reference counts of positional arguments in all
error paths of py_callback.
- Using PyObject_TypeCheck in lifeline_transform for safer validation.
4. Correctly manages references in md_transform and md_observe by releasing
the callable reference returned by parse_args after it is captured by the
callback.
5. Adds support for list[unsigned int], list[long], and list[unsigned long]
in the Python bridge.
6. Updates test/python/vectypes.py with precise string annotations and
linter suppressions.
Co-authored-by: greenc-FNAL <[email protected]>
Address Wim's review: remove unnecessary checks and use msg_from_py_error Co-authored-by: greenc-FNAL <[email protected]> Restore NUMPY_ARRAY_CONVERTER macro and fix annotation parsing ordering Co-authored-by: greenc-FNAL <[email protected]> Fix GIL protection and unsigned type comparison issue from code review Co-authored-by: greenc-FNAL <[email protected]> Clean up redundant checks and improve code clarity Co-authored-by: greenc-FNAL <[email protected]> Add Py_IsInitialized check and optimize dictionary lookup Co-authored-by: greenc-FNAL <[email protected]> Improve error messages and handling in parse_args Co-authored-by: greenc-FNAL <[email protected]> Apply clang-format fixes
…avior (#13) * Initial plan * Fix Python parameter names to match input_family labels Co-authored-by: greenc-FNAL <[email protected]> * Address code review feedback: fix typo and improve docstring Co-authored-by: greenc-FNAL <[email protected]> * Add comment explaining unused parameter k in test function Co-authored-by: greenc-FNAL <[email protected]> * Address copilot review comments: fix docstrings and restore two_args signature Co-authored-by: greenc-FNAL <[email protected]> * Apply ruff fixes * Narrow exception handling to catch only KeyError in verify.py Co-authored-by: greenc-FNAL <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: greenc-FNAL <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This commit reverts a recent change that incorrectly enforced label-based matching for Python annotations in `modulewrap.cpp`. Phlex correctly uses positional matching to map input labels to algorithm parameters, decoupling them from internal parameter names. Changes: - In `modulewrap.cpp`, `parse_args` now iterates through annotations positionally, skipping the "return" key. - Reference counting for attribute names in `parse_args` is improved to prevent potential use-after-free issues. - `test/python/verify.py` is cleaned up by restoring `BoolVerifier` and using generic parameter names in `Verifier`, ensuring compatibility with positional mapping. - Redundant specialized verifiers like `VerifierSumIjk` are removed. - Docstring examples in `verify.py` are corrected. These changes resolve failures in tests like `test_mismatch.py` and restore the flexibility of the Phlex Python interop. Co-authored-by: greenc-FNAL <[email protected]>
This commit reverts the recent change to label-based annotation matching in `modulewrap.cpp`. Phlex utilizes positional matching to decouple input labels from Python parameter names. Key changes: - `modulewrap.cpp`: Restored positional iteration of `__annotations__` in `parse_args`. This correctly restores signature mismatch detection at registration time. - `modulewrap.cpp`: Improved reference counting for `__annotations__` lookup to avoid potential use-after-free. - `test/python/verify.py`: Removed redundant `VerifierSumIjk` and `BoolVerifier` (restored generic `BoolVerifier` as a separate class to avoid monkey-patching issues). - `test/python/verify.py`: Restored generic parameter name `value` to `Verifier`, demonstrating the decoupling of labels from names. - Fixed docstring examples in `verify.py`. These changes resolve the "misunderstanding" of the annotations system while preserving the docstring and test coverage improvements from recent commits. Co-authored-by: greenc-FNAL <[email protected]>
- Restored robust positional annotation matching in modulewrap.cpp using __code__ inspection. - Updated configwrap.cpp to raise KeyError for missing properties, aligning with Python semantics. - Added support for Python lists in vector converters (NUMPY_ARRAY_CONVERTER). - Fixed reference counting and potential use-after-free issues in Python/C++ bridge. - Standardized error message prefixes for numeric type conversion failures. - Simplified and cleaned up test/python/verify.py. - Removed debugging artifacts. Co-authored-by: greenc-FNAL <[email protected]>
21a5e93 to
cd074f1
Compare
|
Review the full CodeQL report for details. |
| // While this check may not be reliable in all threading scenarios (e.g., offloaded threads), | ||
| // it prevents crashes during normal interpreter shutdown | ||
| if (Py_IsInitialized()) { | ||
| PyGILRAII gil; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably makes more sense to grab the GIL prior to checking Py_IsInitialized().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if you try to grab the GIL and we're no longer initialized due to shutdown?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked and apparently it's a case of "this would be a programming error". From PyGILState_Ensure():
assert(_PyEval_ThreadsInitialized());
prior to getting the lock.
I think this one is unwinnable: Py_IsInitialized() checks a variable of the global _PyRuntime, but that can, in a treaded environment unprotected by the GIL, be changed right after the call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note as an aside that the interpreter isn't currently finalized (was a separate discussion) and callback was leaked. There's the issue, independent of the interpreter being alive, of circular references. In that case, Python modules will be offloaded in the interpreter's 2nd cleanup phase, ie. m_callable will go hard dodo-bird. This can be solved once Phlex gets a cleanup state to mimic the registration one and all callables can be decref'ed there, rather than at any indeterminate point when the destructor is called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe register an atexit() Python-side (but those aren't guaranteed to run).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to remove the cleanup logic from the destructor entirely, since neither solution is safe, and replace it with an annotation like:
// TODO: cleanup deferred to Phlex shutdown hook
// Cannot safely Py_DECREF during arbitrary destruction due to:
// - TOCTOU race on Py_IsInitialized() without GIL
// - Module offloading in interpreter cleanup phase 2?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively I could implement the Python-side atexit(), but even when it runs the only thing we're going to improve is the Valgrind leak report.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, until we get a proper place to finalize the interpreter (see other discussion), atexit() will not be called either... As for valgrind, this being a pure Python object, its memory sits in an arena that should be de-allocated wholesale. It would not surprise me if valgrind is happy.
|
|
||
| PyObject* result = | ||
| PyObject_CallFunctionObjArgs((PyObject*)m_callable, lifeline_transform(args)..., nullptr); | ||
| PyObject* arg_tuple = PyTuple_New(N); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one I asked before as well, what is the benefit of this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original motivation was to get explicit control over argument lifetime for debugging reference counting issues. However, if we believe that PyObject_CallFunctionObjArgs is working as expected, I can revert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand that first sentence? For the second part, PyObject_CallFunctionObjArgs is an API from the interpreter, so ... I don't expect it to behave incorrectly?
My objection to the new code is the introduction of a tuple, which both adds memory allocation/deallocation and required copying/ref-counting (it's both an unnecessary run-time overhead and more code to maintain) whereas PyObject_CallFunctionObjArgs is explicitly designed to avoid that if vector calls are supported by the callable (which they will be if it's an ordinary function created by the interpreter).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was added back when I didn't understand what might have been happening, and didn't trust anything. I can revert.
|
|
||
| PyObject* result = | ||
| PyObject_CallFunctionObjArgs((PyObject*)m_callable, (PyObject*)args..., nullptr); | ||
| PyObject* arg_tuple = PyTuple_New(N); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, why this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above.
| { | ||
| // helper to decrement reference counts of N arguments | ||
| (Py_DECREF((PyObject*)args), ...); | ||
| (Py_XDECREF((PyObject*)args), ...); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
args can't be null as the conversion node will have thrown
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True; will revert.
| if (ul == (unsigned long)-1 && PyErr_Occurred() && PyLong_Check(pyobject)) { | ||
| PyErr_Clear(); | ||
| long i = PyLong_AS_LONG(pyobject); | ||
| long i = PyLong_AsLong(pyobject); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not needed b/c above is a PyLong_Check() already.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True; will revert.
| } \ | ||
| \ | ||
| PyArrayObject* arr = (PyArrayObject*)pyobj; \ | ||
| if (pyobj && PyArray_Check((PyObject*)pyobj)) { \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here and below, pyobj isn't null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair; will remove unnecessary checks.
|
|
||
| if (!PySequence_Check(input) || (output && !PySequence_Check(output))) { | ||
| PyErr_SetString(PyExc_TypeError, "input and output need to be sequences"); | ||
| if (!PyList_Check(input) && !PyTuple_Check(input)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this restriction?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The restriction was added because PySequence_GetItem requires additional error handling that wasn't robust. However, if you prefer supporting the full sequence protocol, I can refactor using PySequence_Fast to handle arbitrary sequences safely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now it probably doesn't matter a whole lot, but it might buy us flexibility when dealing with configuration once it's fully fleshed out. What I have in mind is that the configuration has associated types (implied, but the JSON parser will tell you). These types go to Python types in the translation and then something is lost. E.g. both signed and unsigned int becomes an ordinary Python int. We may well end up providing something more custom in the configuration to retain type information. Whether sequences from the configuration will ever be anything other than list or tuple for this reason, I don't know, but that was the underlying thought.
| return nullptr; | ||
| } | ||
|
|
||
| if (output && !PyList_Check(output) && !PyTuple_Check(output)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above? Any object implementing the sequence protocol should do?
| Py_DECREF(callm); | ||
| } | ||
| } | ||
| Py_DECREF(sann); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this moved to further down? I see no use of sann between here and the eventual Py_DECREF?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, no reason to delay.
| for (Py_ssize_t i = 0; i < (PyList_GET_SIZE(values) - (ret ? 1 : 0)); ++i) { | ||
| PyObject* item = PyList_GET_ITEM(values, i); | ||
| input_types.push_back(annotation_as_text(item)); | ||
| // Match annotation types to input labels positionally by looking up parameter names. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This now lives Python-side in Variant, if you got the most recent update. In there, it's far less code and uses the inspect module, making it far easier to maintain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reference/commit to most recent update, please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was discussed on slack, not github I see (https://app.slack.com/client/T03RN7KU3/C06HP8Y0PFA). Code is here: https://github.com/wlav/phlex/blob/python-coverage/test/python/variant.py
Basically, it introduces an OrderedDict based on the signature provided by inspect, for the same net result as this C++ code. Note that inspect inspects the code object same way as the proposed C++ code here, but since inspect is a standard library module, it means we don't have to update it if anything changes to the definition of the code object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll compare, but I think I already pulled it after your Slack comment. I'll adjust the C++ to account for its presence.
Non-test changes:
1. Python/C++ Interoperability Enhancements
Files: modulewrap.cpp, lifelinewrap.cpp
Feature: RAII for Python Objects
PyObjectPtr(astd::shared_ptralias with a customPyObjectDeleter) to manage Python object reference counts.Py_INCREF/Py_DECREF) is error-prone, especially in the presence of C++ exceptions. If an exception is thrown, manual decrements might be skipped, leading to memory leaks.PyObjectPtrensures thatPy_DECREFis called automatically when the pointer goes out of scope, even during stack unwinding.Fix: Robust Annotation Parsing
parse_argsto iterate over the__annotations__dictionary usingPyDict_Nextand explicitly skip the"return"key.PyDict_Values, which returns all values including the return type annotation. Depending on dictionary iteration order (which can vary or be insertion-ordered), the return type could be mistakenly interpreted as an input argument type.Fix: Flexible Input Conversion (List vs. NumPy)
py_to_vint,py_to_vuint, etc.) that accept both Pythonlistand NumPyndarrayobjects.PyList_CheckvsPyArray_Check) and handle data extraction accordingly.Fix: Memory Safety in Cyclic GC
PyObject_GC_UnTrack(pyobj)inll_dealloc(lifelinewrap.cpp).Fix: Type String Matching
inp_type.compare(pos, ...)) with robust substring searching (suffix.find(...)). Corrected a typo wheredouble64]]was checked instead offloat64]].float64arrays from being correctly identified.2. Build System & CI Improvements
Files: CMakeLists.txt, CMakeLists.txt
Enhancement: Reduced Build Dependencies
packagingPython module in CMakeLists.txt.packaging.versionto check module versions. This required thepackaginglibrary to be installed in the build environment..) to perform the check using only the standard library.Fix: GCC 14+ Warning Suppression
-Wno-maybe-uninitializedto compile options for GCC 14.1+.3. Documentation
Files: copilot-instructions.md
Test code changes and additions:
1. New Tests:
py:vectypesandpy:typesFiles: vectypes.py, test_types.py, pyvectypes.jsonnet, pytypes.jsonnet, verify_extended.py
Rationale:
float,double).unsigned int,unsigned long).long,int64_t).modulewrap.cppconverters.Coverage Improvements:
py:types: Validates scalar type conversion between C++ and Python forfloat,double, andunsigned int.py:vectypes: Validates vector/array conversion. It tests:collectify_*).sum_array_*).int32,uint32,int64,uint64,float32,float64.VerifierFloat,VerifierUInt, etc.) that handle type-specific assertions (e.g., epsilon comparison for floats).Problems Exposed:
py:vectypestest exposed a logic error in source.cpp where large 64-bit hashes were being used in arithmetic (100 - id), causing underflow for unsigned types and wrapping for signed types. This was fixed by introducing modulo arithmetic to keep values small and predictable.modulewrap.cpp.Regression Detection:
modulewrap.cppbreak the mapping between C++ types (likestd::vector<int>) and Python types (likenumpy.ndarrayorlist).UINT_MAXas-1).2. Test Infrastructure Enhancements
Files: CMakeLists.txt, source.cpp
Rationale:
Changes:
py:vectypesandpy:typesto the test suite.PYTHONPATHsetup to explicitly includePython_SITELIBandPython_SITEARCH. This ensures tests running in embedded environments (like Spack) can find installed packages.packagingdependency with a simple inline version parser for the module check.float,double,uint,int64,uint64).id.number()toid.number() % Nto prevent integer overflow and ensure deterministic summation results.3. Code Quality & Modernization
Files: adder.py, all_config.py, reducer.py, sumit.py, verify.py
Rationale:
ruff,mypy) introduced in this commit.Changes:
False(changed== Falsetois Falseor kept as is with# noqaif intentional for testing).mypy.Regression Detection: