Skip to content
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

bug: parameter kinds for dataclasses should match the non-dataclass equivalents #234

Closed
has2k1 opened this issue Feb 8, 2024 · 0 comments
Assignees

Comments

@has2k1
Copy link
Contributor

has2k1 commented Feb 8, 2024

Currently, parameters derived from dataclass fields have no kind information.

This is mainly for python 3.10+ which have keyword_only specification for dataclass fields. Here are failing test cases.

from griffe.tests import temporary_visited_module

code = """
from dataclasses import dataclass, field, KW_ONLY

# Pair of dataclass and equivalent non-dataclass
# The parameter kinds for each pair should be the same
    
@dataclass
class PointA:
    x: float
    y: float = field(kw_only=True)

class PointA_:
    def __init__(self, x: float, *, y: float): ...

@dataclass
class PointB:
    x: float = field(kw_only=True)
    y: float

class PointB_:
    def __init__(self, y: float, *, x: float): ...

@dataclass
class PointC:
    x: float
    _: KW_ONLY
    y: float

class PointC_:
    def __init__(self, x: float, *, y: float): ...

@dataclass
class PointD:
    _: KW_ONLY
    x: float
    y: float

class PointD_:
    def __init__(self, *, x: float, y: float): ...

@dataclass(kw_only=True)
class PointE:
    x: float
    y: float

class PointE_:
    def __init__(self, *, x: float, y: float): ...
"""

def parameter_kinds(obj):
    return [(p.kind and p.kind.value) or None for p in obj.parameters]

with temporary_visited_module(code) as module:
    def both_parameter_kinds(s):
        return [parameter_kinds(obj) for obj in (module[s], module[f"{s}_"])]

    kindsA, kindsA_ = both_parameter_kinds("PointA")
    kindsB, kindsB_ = both_parameter_kinds("PointB")
    kindsC, kindsC_ = both_parameter_kinds("PointC")
    kindsD, kindsD_ = both_parameter_kinds("PointD")
    kindsE, kindsE_ = both_parameter_kinds("PointE")

    assert kindsA == kindsA_
    assert kindsB == kindsB_
    assert kindsC == kindsC_
    assert kindsD == kindsD_
    assert kindsE == kindsE_
pawamoy added a commit that referenced this issue Mar 5, 2024
Instead of generating parameters on the fly by (wrongly) checking attributes of the class,
we always load a Griffe extension that re-creates `__init__` methods and their parameters.

Issue-33: #233
Issue-34: #234
Issue-38: #238
Issue-39: #239
PR-240: #240
@pawamoy pawamoy closed this as completed Mar 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants