Search code examples
pythonpython-dataclasses

dataclass inheritance: Fields without default values cannot appear after fields with default values


Context

I created two data classes to handle table metadata. TableMetadata apply to any kind of tables, while RestTableMetadata contains information relevant for data extracted from REST apis

@dataclass
class TableMetadata:
    """
    - entity: business entity represented by the table
    - origin: path / query / url from which data withdrawn
    - id: field to be used as ID (unique)
    - historicity: full, delta
    - upload: should the table be uploaded
    """

    entity: str
    origin: str
    view: str
    id: str = None
    historicity: str = "full"
    upload: bool = True
    columns: list = field(default_factory=list)


@dataclass
class RestTableMetadata(TableMetadata):
    """
    - method: HTTP method to be used
    - payloadpath: portion of the response payload to use to build the dataframe
    """

    method: str
    payloadpath: str = None

Problem

Because of inheritance, method (without default values) comes after columns, resulting in the following Pylance error: Fields without default values cannot appear after fields with default values

I'm looking for a way to fix it without overriding __init__ (if there is such a way). I also noticed a method called __init_subclass__ (This method is called when a class is subclassed.) that might affect how RestTableMetadata.__init__ and other subclasses is generated.


Solution

  • Here is a working solution for python > 3.10

    @dataclass(kw_only=True)
    class TableMetadata:
        """
        - entity: business entity represented by the table
        - origin: path / query / url from which data withdrawn
        - id: field to be used as ID (unique)
        - historicity: full, delta
        - upload: should the table be uploaded
        """
    
        entity: str
        origin: str
        view: str
        id: str = None
        historicity: str = "full"
        upload: bool = True
        columns: list = field(default_factory=list)
    
    
    @dataclass(kw_only=True)
    class RestTableMetadata(TableMetadata):
        """
        - method: HTTP method to be used
        - payloadpath: portion of the response payload to use to build the dataframe
        """
    
        method: str
        payloadpath: str = None