pythonpython-dataclassesslots

Dataclass code that sets slots=true if python version allows


I'm writing a module that needs to run under both Python 3.8 and Python 3.10. I want to have dataclasses that have slots (@dataclasses.dataclass(slots=True)) in Python 3.10 for the purposes of type checking (both static and runtime). Is there a from __future__ import that will make this compatible with Python 3.8? If not, what is the most pytype-friendly way of emulating one?

Additional note: I'm currently using the dataclasses_json module, which to the best of my knowledge is not compatible with attrs. Otherwise I could switch from dataclasses to attrs and easily solve the problem.


Solution

  • If you don't need the slots feature in the older version, that is easy.

    from __future__ ... imports as reserved for language features that change the way the syntax itself works. The slots feature in dataclasses is just another parameter in the library, so, logically, it does not get such a workaround.

    As it is, one have to conditionally insert the slots argument on the decorator call. Python 3.8 decorator expressions are not the same as general expressions - but we can add the inline logic to the arguments part only - that is executed before the call itself, so it will work.

    Python also has no syntax to directly add a keyword parameter in a call or not, according to a condition - but since keyword parameters can be extracted from dictionaries with the use of **, it can be done indirectly.

    Therefore, the lines bellow should work:

    import dataclasses
    import sys
    ...
    
    py310 = sys.version_info.minor >= 10 or sys.version_info.major > 3
    
    @dataclasses.dataclass(**({"slots": True} if py310 else {}))
    class MyData:
       ...