ramonhagenaars / jsons

🐍 A Python lib for (de)serializing Python objects to/from JSON
https://jsons.readthedocs.io
MIT License
288 stars 40 forks source link

'mro' of 'type' object needs an argument #97

Closed T-P-F closed 4 years ago

T-P-F commented 4 years ago

UserWarning: Failed to dump attribute "<class 'MyClassName'>" of object of type "MyType". Reason: descriptor 'mro' of 'type' object needs an argument. Ignoring the attribute.

Hi there, I'm trying to switch to this from jsonpickle and am running into a case in which the above failure happens hundreds of times on a variety of nested objects. Any idea what the issue is?

ramonhagenaars commented 4 years ago

Hmm it seems that .mro is invoked on type, in which case it handles the invocation as a static method invocation (without an instance).

Do you have an example of a class that shows this behavior upon dumping?

mmillsatdp commented 4 years ago

Stumbled across this today. I received it while trying to dump a class that had a nested class. The issue seems to happen because jsons is trying to dump the nested class definition.

javiruiz commented 4 years ago

I was getting the same error message and I solved it by un-nesting the simple class that was provoking the issue: class Response(): """ Response """ def init(self): self.status = 200

georgeharker commented 4 years ago

Here's a quick repro from when I ran into it:

from enum import Enum, auto
from typing import Optional
import jsons

class Foo:
    class Bar:
        class Type(Enum):
            A=auto()
            B=auto()
            C=auto()

        bar_type: Type

        def __init__(self, bar_type: Optional[Type] = None):
            self.bar_type = bar_type if bar_type is not None else self.Type.A

    bar: Bar

    def __init__(self, bar: Optional[Bar] = None):
        self.bar = bar if bar is not None else self.Bar()

f = Foo()
print(jsons.dumps(f))

As noted, unnesting fixes it. It seems like more than the mro() invocation is going awry.

georgeharker commented 4 years ago

I don't have the above nesting any more, but I do now get a crash on serialization involving mro in the exception:

File "lib/jsons/serializers/default_object.py", line 258, in _get_complete_class_dict
    for cls_or_elder in reversed(get_mro(cls)):

  File "/usr/local/lib/python3.7/dist-packages/typish/functions/_get_mro.py", line 19, in get_mro
    return get_mro(origin)

  File "/usr/local/lib/python3.7/dist-packages/typish/functions/_get_mro.py", line 21, in get_mro
    return getmro(cls)

  File "/usr/lib/python3.7/inspect.py", line 480, in getmro
    return cls.__mro__

  File "/usr/lib/python3.7/typing.py", line 699, in __getattr__
    raise AttributeError(attr)

AttributeError: __mro__

I'll try and distill an example - but something definitely regressed in 1.3.0 ;(

georgeharker commented 4 years ago

I think this was due to another bug, reported separately. And I needed to update to typish 1.7