-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Hey, thanks for writing ruff!! The following example illustrates two violations of N815, on the mixed-case variable myOtherVar. The first violation is of course appropriate. However, I think the second is misleading, and this rule should not apply to TypedDict.
from typing import TypedDict
class Foo:
my_var: int
myOtherVar: str # Violation! Makes sense.
class Bar(TypedDict):
my_var: int
myOtherVar: str # Violation! But shouldn't be.
A TypedDict is less of a real class, and more syntactic sugar to add typing to the keys of a dictionary. The argument here would be that if {"my_var": 0, "myOtherVar": "xyz"} would be appropriate, then the TypedDict form should be too. It may also be worth noting that the equivalent example:
Bar = TypedDict("Bar", {"my_var": int, "myOtherVar": str})
does not flag this check (although it does flag UP013, as it should).
There is a practical reason to relax the rule here: a TypedDict is a useful and lightweight way to deal with adding static typing to an untyped blob of JSON with known structure sent over the wire (say, the body of an HTTP request). The writer of the TypedDict may not have control over the structure of the untyped dict, so it becomes awkward to comply with N815 without:
- Writing an awkward camel_to_snake parser
- Using a functional
TypedDictdefinition (and falling afoul of UP013) - Dropping a
noqaon every camelCased field - Disabling N815
- Using a heavier ser/de library
All of which are undesirable.
I want to point out that the current behavior of N815 does conform to the behavior of the rule upstream in pep8-naming. I'm not sure about Ruff's overall stance on modifying how rules behave, so if enforcing exact parity is important, then there probably isn't anything to be done here.