| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
Hello, and thanks for your contribution! I'm a bot set up to make sure that the project can legally accept your contribution by verifying you have signed the PSF contributor agreement (CLA). Unfortunately our records indicate you have not signed the CLA. For legal reasons we need you to sign this before we can look at your contribution. Please follow the steps outlined in the CPython devguide to rectify this issue. Thanks again to your contribution and we look forward to looking at it! |
Sorry, something went wrong.
Without this fix, it would never include padding bytes - an assumption that was only valid in the case when `_pack_` was set - and this case was explicitly not implemented. This should allow conversion from ctypes structs to numpy structs.
There was a problem hiding this comment.
LGTM. The PR is sufficient to fix the problems described. Perhaps judicious use of spacing between fields could make the format clearer, especially when anonymous padding is added. For instance, I would find "<b:x:7x<Q:y:" clearer as "<b:x: 7x <Q:y:". Not critical as the format is probably going to be machine-parsed anyway.
Sorry, something went wrong.
|
That's looks like a reasonable suggestion, bit possibly out of scope for this PR. Less intrusively, I could add whitespace in the test expectations, and remove it before comparing. Let's see how the core devs feel. Thanks for the review! |
Sorry, something went wrong.
|
@abalkin: Any chance you could take a look at this? |
Sorry, something went wrong.
|
@brettcannon: I'd argue this is type-bugfix, not type-enhancement - the implementation in master produces invalid buffers in almost all cases. This isn't just adding support for _pack_ (an enhancement), but also fixing the behavior for when _pack_ is absent. |
Sorry, something went wrong.
| Py_ssize_t log_n = 0; | ||
| while (n > 0) { | ||
| log_n++; | ||
| n /= 10; |
There was a problem hiding this comment.
Multiplication is often faster than division. Can this be rewritten by computing powers of 10 until n is exceeded?
Better yet, just inline linear search.
if (n < 10ULL)
return 1;
if (n < 100ULL)
return 2;
...
if (n < 10_000_000_000_000_000_000ULL)
return 20;
Sorry, something went wrong.
There was a problem hiding this comment.
On the second thought, I would be surprised if this has not been implemented elsewhere in cpython code base. Off the top of my head, I cannot recall where it could be, but I will try to search. If someone beats me to it - please leave a note.
Sorry, something went wrong.
There was a problem hiding this comment.
Can this be rewritten by computing powers of 10 until n is exceeded?
This is risky because the power can overflow
Sorry, something went wrong.
There was a problem hiding this comment.
I would be surprised if this has not been implemented elsewhere in cpython code base. Off the top of my head, I cannot recall where it could be, but I will try to search.
It took me a little longer than I expected to get back to this, but the code that I was looking for is in Python/dtoa.c.
@mdickinson - Is the approximation used in dtoa applicable to the problem at hand? If so, do you think that code can be factored out and called here?
Sorry, something went wrong.
There was a problem hiding this comment.
@abalkin Looks like the relevant code is no longer part of the PR. But the Python/dtoa.c code is for floats, and assumes IEEE 754 format; it's not clear to me how it could be used here. (In general, I'm reluctant to add floating-point dependence to code that doesn't need it.)
Sorry, something went wrong.
| } | ||
|
|
||
| /* decimal characters + x + null */ | ||
| buf = PyMem_Malloc(clog10(padding) + 2); |
There was a problem hiding this comment.
I left a comment about log10 implementation above, but looking at the actual use, I don't see why it is needed. Can't we just make buf
char buf[20];and not allocate it on the heap?
Sorry, something went wrong.
There was a problem hiding this comment.
I wanted to avoid risking introducing a buffer overflow by accident by choosing too short a buffer; especially since I don't think we care about performance here. The whole framework for building the format strings here consists of repeated heap allocations, so one more allocation doesn't seem like a big deal.
I think 20 isn't actually enough, as an int64 can need up to 19 digits, and then we need the x and the null.
I could ask PyOS_snprintf to compute the size for me if you'd prefer? Although I can't see any evidence that PyOS_snprintf is actually called with a null buffer anywhere in CPython. Nevermind, PyOS_snprintf does not support this feature of snprintf (#95993)
Sorry, something went wrong.
There was a problem hiding this comment.
I've pushed the version with stack allocation as requested
Sorry, something went wrong.
|
@mdickinson, I really appreciate that you were able to review #5576 a few weeks ago. Do you think you'd be able to take a look at this one too? |
Sorry, something went wrong.
|
@eric-wieser Yes, I'll take a look. It won't be this weekend, though, I'm afraid. |
Sorry, something went wrong.
There was a problem hiding this comment.
This LGTM, and behaves as expected in my manual testing; the code looks good. I left a couple of nitpick-level comments / suggestions.
@abalkin This is still assigned to you; is there anything you're aware of that would mean this shouldn't be merged?
The issue is marked as a "bug" (which makes some sense), but I think this is sufficiently new-feature'y that the changes shouldn't be backported to Python <3.12. @abalkin: thoughts?
The way we build up the format string doesn't seem ideal - it looks as though it would take time quadratic in the number of fields of the struct. But AFAICT that's a pre-existing issue, not introduced in this PR. Presumably for the sort of things for which this is used in practice this hasn't yet been a real issue.
Observation: it seems there's no documentation of the "data format description" language outside PEP 3118 itself, unless I'm missing something. I'd expect the ctypes documentation to at least have a pointer to PEP 3118 (though it would be better to have a description in the docs themselves at some point, since PEPs are historical documents that shouldn't generally by relied upon to be up to date with implementations.) Anyway, that's off-topic for this PR.
Sorry, something went wrong.
…80.Dtiz8z.rst Co-authored-by: Mark Dickinson <dickinsm@gmail.com>
|
@eric-wieser: Changes LGTM; thank you. @abalkin Python 3.12a5 is due tomorrow, which means that if we leave this PR open for another couple of days we'll end up having to nudge the news entry again. (That was poor timing on my part - sorry about that.) But I think this is ready, so I'll take the EAFP approach: I'll merge, and we can tweak later if necessary. |
Sorry, something went wrong.
|
@mdickinson - my only concern was with the floor log10 computation that I felt could be done better. If it looks good enough to you, I have no objections to the merge. |
Sorry, something went wrong.
⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️Hi! The buildbot x86 Gentoo Installed with X 3.x has failed when building commit 90d85a9. What do you need to do:
You can take a look at the buildbot page here: https://buildbot.python.org/all/#builders/464/builds/3771 Failed tests:
Failed subtests:
Summary of the results of the build (if available): == Tests result: FAILURE then FAILURE == 413 tests OK. 1 test failed: 17 tests skipped: 1 re-run test: Total duration: 22 min Click to see traceback logsTraceback (most recent call last):
File "/buildbot/buildarea/cpython/3.x.ware-gentoo-x86.installed/build/target/lib/python3.12/test/test_ctypes/test_pep3118.py", line 27, in test_native_types
self.assertEqual(normalize(v.format), normalize(fmt))
AssertionError: 'T{<b:x:3x<Q:y:}' != 'T{<b:x:7x<Q:y:}'
- T{<b:x:3x<Q:y:}
? ^
+ T{<b:x:7x<Q:y:}
? ^
|
Sorry, something went wrong.
|
Urgh. That looks like a legitimate failure on 32-bit platforms, introduced by this PR. @eric-wieser I think this is a problem with the test rather than the core logic. Do you agree? |
Sorry, something went wrong.
|
Yes, you're right; the cases that don't set _pack_ at all are platform-dependent. I think a test written for 32 bit platforms would pass on both; so replacing the uint64 with uint32s should make the problem go away |
Sorry, something went wrong.
⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️Hi! The buildbot x86 Gentoo Non-Debug with X 3.x has failed when building commit 90d85a9. What do you need to do:
You can take a look at the buildbot page here: https://buildbot.python.org/all/#builders/58/builds/3813 Failed tests:
Failed subtests:
Summary of the results of the build (if available): == Tests result: FAILURE then FAILURE == 419 tests OK. 10 slowest tests:
1 test failed: 14 tests skipped: 1 re-run test: Total duration: 26 min 53 sec Click to see traceback logsTraceback (most recent call last):
File "/buildbot/buildarea/cpython/3.x.ware-gentoo-x86.nondebug/build/Lib/test/test_ctypes/test_pep3118.py", line 27, in test_native_types
self.assertEqual(normalize(v.format), normalize(fmt))
AssertionError: 'T{<b:x:3x<Q:y:}' != 'T{<b:x:7x<Q:y:}'
- T{<b:x:3x<Q:y:}
? ^
+ T{<b:x:7x<Q:y:}
? ^
|
Sorry, something went wrong.
I'll give that a go; PR shortly. I'm wondering whether I'm going to end up hitting problems with ILP32 platforms not being consistent about whether uint32 is aliased to unsigned int or to unsigned long, though. |
Sorry, something went wrong.
|
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
The summary of this diff is that it:
This patch does not affect any existing aligment computation; all it does is use subtraction to deduce the amount of paddnig introduced by the existing code.
Without this fix, it would never include padding bytes - an assumption that was only
valid in the case when _pack_ was set - and this case was explicitly not implemented.
This should allow conversion from ctypes structs to numpy structs
Fixes numpy/numpy#10528
https://bugs.python.org/issue32780
Fixes #76961