New issue 2551: struct.Struct has weird __new__ arguments https://bitbucket.org/pypy/pypy/issues/2551/structstruct-has-weird-__new__-arguments
Steven Noonan: For some reason, CPython and PyPy differ here: ``` $ pypy -c "import struct; help(struct.Struct.__new__)" Help on function __new__: __new__(subtype, format) $ python2 -c "import struct; help(struct.Struct.__new__)" Help on built-in function __new__: __new__(...) T.__new__(S, ...) -> a new object with type S, a subtype of T ``` This difference breaks two Python modules I use (livestreamer and streamlink). Both of those modules have some common code which creates several classes that inherit from struct.Struct. The derived classes can't be constructed properly due to the `__new__` difference: ``` Traceback (most recent call last): File "/opt/pypy/bin/streamlink", line 11, in <module> load_entry_point('streamlink==0.5.0', 'console_scripts', 'streamlink')() File "/opt/pypy/site-packages/pkg_resources/__init__.py", line 565, in load_entry_point return get_distribution(dist).load_entry_point(group, name) File "/opt/pypy/site-packages/pkg_resources/__init__.py", line 2631, in load_entry_point return ep.load() File "/opt/pypy/site-packages/pkg_resources/__init__.py", line 2291, in load return self.resolve() File "/opt/pypy/site-packages/pkg_resources/__init__.py", line 2297, in resolve module = __import__(self.module_name, fromlist=['__name__'], level=0) File "/opt/pypy/site-packages/streamlink_cli/main.py", line 17, in <module> from streamlink.stream import StreamProcess File "/opt/pypy/site-packages/streamlink/stream/__init__.py", line 4, in <module> from streamlink.stream.akamaihd import AkamaiHDStream File "/opt/pypy/site-packages/streamlink/stream/akamaihd.py", line 15, in <module> from ..packages.flashmedia import FLV, FLVError File "/opt/pypy/site-packages/streamlink/packages/flashmedia/__init__.py", line 4, in <module> from .amf import * File "/opt/pypy/site-packages/streamlink/packages/flashmedia/amf.py", line 3, in <module> from .types import AMF0String, AMF0Value, U8, U16BE, U32BE File "/opt/pypy/site-packages/streamlink/packages/flashmedia/types.py", line 298, in <module> U24BE = HighLowCombo(">HB", 8, True) TypeError: __new__() takes exactly 2 arguments (4 given) ``` The arguments for `__init__` are apparently being passed into `__new__` and `Struct.__new__` only accepts two arguments: the first is the class to create an instance of (as with all `__new__` functions) and the second is the format string. Sometimes the derived classes take other kinds of arguments for `__init__` too (such as instances of other derived classes). So in order to get the livestreamer and streamlink modules to work, I came up with this hack: ```diff diff --git a/src/streamlink/packages/flashmedia/types.py b/src/streamlink/packages/flashmedia/types.py index cc4fcca..731bff1 100644 --- a/src/streamlink/packages/flashmedia/types.py +++ b/src/streamlink/packages/flashmedia/types.py @@ -30,6 +30,19 @@ AMF3_MAX_INTEGER = 268435455 class PrimitiveType(Struct): + def __new__(classtype, *args): + try: + return Struct.__new__(classtype, *args) + except: + pass + + try: + return Struct.__new__(classtype, args[0]) + except: + pass + + return Struct.__new__(classtype, '') + def __call__(self, *args): return self.pack(*args) ``` This change makes the modules *work properly*, but it feels like this may be a PyPy library bug. So either: * PyPy needs to make the Struct.__new__ function match CPython's * or, the streamlink and livestreamer modules shouldn't have classes inheriting from Struct Which makes more sense? _______________________________________________ pypy-issue mailing list pypy-issue@python.org https://mail.python.org/mailman/listinfo/pypy-issue