mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-07 02:59:05 +00:00
fix(lint): disqualify the LIT002 exemption in files with star imports
This commit is contained in:
parent
8e7f2bf449
commit
9914e3c5da
2 changed files with 15 additions and 6 deletions
|
|
@ -30,9 +30,11 @@ LIT002 Mutable-collection *construction*: a list/dict/set literal or comprehens
|
|||
spelling of the `MyTd(...)` call, which was never construction, and an
|
||||
all-ReadOnly payload cannot be grown or rewritten. The exemption is
|
||||
conservative: the TypedDict's name must be bound exactly once in the file
|
||||
(a name also bound as a function, another class, an assignment target, or
|
||||
an import alias might resolve to something mutable at the annotation
|
||||
site), every field it declares or inherits in-module must be
|
||||
(a name also bound in any other form, another def, an assignment or loop
|
||||
target, an import alias, a parameter, might resolve to something mutable
|
||||
at the annotation site, and a `from x import *` anywhere in the file
|
||||
disqualifies every name, since what it binds is statically invisible),
|
||||
every field it declares or inherits in-module must be
|
||||
`ReadOnly[...]`, only the display itself is exempt (nested mutables still
|
||||
count), and a TypedDict imported from another module is out of reach,
|
||||
exactly as in LIT012. Suppress with `# mutable-ok: <reason>`.
|
||||
|
|
@ -536,9 +538,10 @@ def _typeddict_assigned_value_ids(tree: ast.AST) -> frozenset[int]:
|
|||
exactly as in LIT012's base-class resolution); its name is bound exactly once
|
||||
in the file (resolution here is scope-blind, so a name the file also binds in
|
||||
any other form, another def, an assignment or loop target, an import alias, a
|
||||
parameter, could resolve to something mutable at the annotation site); and
|
||||
every field it declares or inherits within the module is `ReadOnly[...]`, so
|
||||
no holder can statically
|
||||
parameter, could resolve to something mutable at the annotation site, and a
|
||||
`from x import *` anywhere disqualifies every name in the file, since what it
|
||||
binds is statically invisible); and every field it declares or inherits
|
||||
within the module is `ReadOnly[...]`, so no holder can statically
|
||||
rewrite a key even where LIT012 was suppressed or is riding its budget. Only
|
||||
the display itself is exempt; anything mutable nested inside it still trips
|
||||
LIT002.
|
||||
|
|
@ -558,6 +561,8 @@ def _typeddict_assigned_value_ids(tree: ast.AST) -> frozenset[int]:
|
|||
)
|
||||
|
||||
bindings = tuple(name for node in ast.walk(tree) for name in _binding_names(node))
|
||||
if "*" in bindings:
|
||||
return frozenset()
|
||||
frozen_names = frozenset(
|
||||
cls.name for cls in classes if bindings.count(cls.name) == 1 and frozen_lineage(cls.name, frozenset())
|
||||
)
|
||||
|
|
|
|||
|
|
@ -250,6 +250,10 @@ def test_typeddict_name_rebound_elsewhere_gets_no_exemption(tmp_path):
|
|||
assert "LIT002" in _codes(tmp_path, _TYPEDDICT_PREFIX + "def scope(Td):\n return Td\nx: Td = {'a': 1}\n")
|
||||
|
||||
|
||||
def test_star_import_disqualifies_typeddict_exemption(tmp_path):
|
||||
assert "LIT002" in _codes(tmp_path, _TYPEDDICT_PREFIX + "from elsewhere import *\nx: Td = {'a': 1}\n")
|
||||
|
||||
|
||||
def test_dict_literal_annotated_as_imported_or_unknown_type_still_counts(tmp_path):
|
||||
assert "LIT002" in _codes(tmp_path, "from other_module import Td\nx: Td = {'a': 1}\n")
|
||||
assert "LIT002" in _codes(tmp_path, "from typing import Final\ny: Final = {'a': 1}\n")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue