8000 bpo-33178: Add BigEndianUnion, LittleEndianUnion classes to ctypes by ringof · Pull Request #25480 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-33178: Add BigEndianUnion, LittleEndianUnion classes to ctypes #25480

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

Merged
merged 14 commits into from
Mar 29, 2022

Conversation

ringof
Copy link
Contributor
@ringof ringof commented Apr 20, 2021

https://bugs.python.org/issue33178

Adds the BigEndianUnion, LittleEndianUnion classes documented here: https://docs.python.org/3/library/ctypes.html#structure-union-alignment-and-byte-order but are unimplemented in ctypes.

Co-authored-by: syeberman (Sye van Der Veen)
Source for this PR is derived from a patch submitted by syeberman for bpo-19023:
https://bugs.python.org/issue19023
https://bugs.python.org/file31769/75843d82f6cf.diff
for which these changes were not included in the final patch used to close that issue.

https://bugs.python.org/issue33178

@the-knights-who-say-ni
Copy link

Hello, and thanks for your contribution!

I'm a bot set up to make sure that the project can legally accept this contribution by verifying everyone involved has signed the PSF contributor agreement (CLA).

CLA Missing

Our records indicate the following people have not signed the CLA:

@ringof

For legal reasons we need all the people listed to sign the CLA before we can look at your contribution. Please follow the steps outlined in the CPython devguide to rectify this issue.

If you have recently signed the CLA, please wait at least one business day
before our records are updated.

You can check yourself to see if the CLA has been received.

Thanks again for the contribution, we look forward to reviewing it!

@@ -311,5 +311,68 @@ class S(Structure):
s2 = struct.pack(fmt, 0x12, 0x1234, 0x12345678, 3.14)
self.assertEqual(bin(s1), bin(s2))

def test_union_fields(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this test would be better named something like test_union_fields_unsupported_byte_order.


# these fields do not support different byte order:
for typ in c_wchar, c_void_p, POINTER(c_int):
_fields_.append(("x", typ))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field appended here will not be removed and so will be available in the next iteration, which I assume is not what you want. I recommend using the + operator instead to avoid modifying the original list.

I would do something like this.

fields = [
    ("a", c_ubyte),
    ("b", c_byte),
    ("c", c_short),
    ("d", c_ushort),
    ("e", c_int),
    ("f", c_uint),
    ("g", c_long),
    ("h", c_ulong),
    ("i", c_longlong),
    ("k", c_ulonglong),
    ("l", c_float),
    ("m", c_double),
    ("n", c_char),
    ("b1", c_byte, 3),
    ("b2", c_byte, 3),
    ("b3", c_byte, 2),
    ("a", c_int * 3 * 3 * 3),
]

for typ in (c_wchar, c_void_p, POINTER(c_int)):
    with self.assertRaises(TypeError):
        class T(base):
            _fields_ = fields + [("x", typ)]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review!

def test_struct_fields_1(self):
if sys.byteorder == "little":
base = BigEndianStructure
else:
base = LittleEndianStructure
class T(base):
pass
_fields_ = [("a", c_ubyte),
("b", c_byte),
("c", c_short),
("d", c_ushort),
("e", c_int),
("f", c_uint),
("g", c_long),
("h", c_ulong),
("i", c_longlong),
("k", c_ulonglong),
("l", c_float),
("m", c_double),
("n", c_char),
("b1", c_byte, 3),
("b2", c_byte, 3),
("b3", c_byte, 2),
("a", c_int * 3 * 3 * 3)]
T._fields_ = _fields_
# these fields do not support different byte order:
for typ in c_wchar, c_void_p, POINTER(c_int):
_fields_.append(("x", typ))
class T(base):
pass
self.assertRaises(TypeError, setattr, T, "_fields_", [("x", typ)])

test_struct_field_1 is nearly the same as the code you raised this comment on; will fix for the same issue.

Copy link
Member
@FFY00 FFY00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks alright to me now 😊

@FFY00
Copy link
Member
FFY00 commented May 19, 2021

The only improvement I could suggest at the moment is maybe using subtests so that we can easily distinguish what failed if the tests break. But I'll leave that to the person who will do the final review.

https://docs.python.org/3/library/unittest.html#distinguishing-test-iterations-using-subtests

@FFY00
Copy link
Member
FFY00 commented May 29, 2021

@iritkatriel since you have been active lately, would you mind having a look at this? No worries if you are not comfortable enough to review it.

(let me know if you don't want me to ping you like this in the future)

@iritkatriel
Copy link
Member

@FFY00 I don't mind the ping, but I also don't know much at all about ctypes.

@ringof
Copy link
Contributor Author
ringof commented May 30, 2021

edit: @abalkin is listed as an expert on ctypes in the Python Developer's Guide, and as active on the Developer Log.

@ringof
Copy link
Contributor Author
ringof commented Jun 20, 2021

@pablogsal any suggestions on a core developer to review this PR?

@shawwn
Copy link
shawwn commented Dec 29, 2021

@FFY00 @ringof @pablogsal What's the status of this PR? Projects such as pyembc could benefit from BigEndianUnion and LittleEndianUnion:

https://github.com/waszil/pyembc/blob/52fd5c13317f822e8ef0a330c4bcbb7f2d7e0521/pyembc/_pyembc.py#L297-L312

    # ctypes currently does not implement the BigEndianUnion and LittleEndianUnion despite its documentation
    # sais so. Therefore, we use simple Union for now. Details:
    # https://stackoverflow.com/questions/49524952/bigendianunion-is-not-part-of-pythons-ctypes
    # https://bugs.python.org/issue33178
    if endian == "little":
        _bases = {
            _PyembcTarget.STRUCT: ctypes.LittleEndianStructure,
            _PyembcTarget.UNION: ctypes.Union
        }
    elif endian == "big":
        _bases = {
            _PyembcTarget.STRUCT: ctypes.BigEndianStructure,
            _PyembcTarget.UNION: ctypes.Union
        }
    else:
        raise ValueError("Invalid endianness")

I discovered this PR via https://bugs.python.org/issue33178#msg397291:

Author: David Goncalves (dpg) * | Date: 2021-07-12 09:37

PR 25480 passes checks and awaits core review. All comments thus far have been addressed.

So there appears to be no activity on this since July 2021. (In a few days it'll be January 2022.)

Is there any way I can help out? What would be the most productive thing I could do to help get this merged?

Thanks for your time!

@ringof
Copy link
Contributor Author
ringof commented Dec 29, 2021

@shawwn its awaiting core developer review - I wasn't able to find one with the experience and bandwidth to review this. I'm willing to do my part to respond to requests for changes.

@ringof
Copy link
Contributor Author
ringof commented Jan 14, 2022

The following list of names is from recently closed PRs or PRs with a glancing involvement with ctypes.

@iritkatriel @tiran @ericsnowcurrently @vstinner @pablogsal @markshannon @ambv @serhiy-storchaka

I'm looking for a core review for this PR, but the Experts list does not suggest anybody who is recently active. Anybody have a suggestions who to reach out to do so?

@gpshead gpshead self-assigned this Feb 3, 2022
@ringof
Copy link
Contributor Author
ringof commented Mar 21, 2022

@gpshead All your comments are addressed. I'm not sure about the line length for what I did for the class definitions in the unsupported types tests - is there a general maximum and preferred line breaking style, I'll be glad to fix that.

@gpshead gpshead added the type-feature A feature request or enhancement label Mar 29, 2022
@gpshead gpshead merged commit dc2d840 into python:main Mar 29, 2022
@ringof ringof deleted the bpo-33178-ctypes-endianunion branch March 30, 2022 00:48
@ringof
Copy link
Contributor Author
ringof commented Mar 30, 2022

Thanks - glad it made it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-feature A feature request or enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants
0