pyflakes 3.3.0__tar.gz → 3.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyflakes-3.3.0 → pyflakes-3.3.2}/NEWS.rst +8 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/PKG-INFO +1 -1
- pyflakes-3.3.2/pyflakes/__init__.py +1 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/checker.py +16 -10
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_other.py +37 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes.egg-info/PKG-INFO +1 -1
- pyflakes-3.3.0/pyflakes/__init__.py +0 -1
- {pyflakes-3.3.0 → pyflakes-3.3.2}/AUTHORS +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/LICENSE +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/MANIFEST.in +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/README.rst +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/bin/pyflakes +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/__main__.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/api.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/messages.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/reporter.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/scripts/__init__.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/scripts/pyflakes.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/__init__.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/harness.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_api.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_builtin.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_code_segment.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_dict.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_doctests.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_imports.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_is_literal.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_match.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_type_annotations.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes/test/test_undefined_names.py +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes.egg-info/SOURCES.txt +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes.egg-info/dependency_links.txt +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes.egg-info/entry_points.txt +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/pyflakes.egg-info/top_level.txt +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/setup.cfg +0 -0
- {pyflakes-3.3.0 → pyflakes-3.3.2}/setup.py +0 -0
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
3.3.2 (2025-03-31)
|
|
2
|
+
|
|
3
|
+
- Fix crash with ``global`` / ``nonlocal`` in class bodies (regressed in 3.3.0)
|
|
4
|
+
|
|
5
|
+
3.3.1 (2025-03-30)
|
|
6
|
+
|
|
7
|
+
- Allow assignment expressions to redefine annotations (regressed in 3.3.0)
|
|
8
|
+
|
|
1
9
|
3.3.0 (2025-03-29)
|
|
2
10
|
|
|
3
11
|
- Add ``__debuggerskip__`` as a special local
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '3.3.2'
|
|
@@ -526,7 +526,10 @@ class Scope(dict):
|
|
|
526
526
|
|
|
527
527
|
|
|
528
528
|
class ClassScope(Scope):
|
|
529
|
-
|
|
529
|
+
def __init__(self):
|
|
530
|
+
super().__init__()
|
|
531
|
+
# {name: node}
|
|
532
|
+
self.indirect_assignments = {}
|
|
530
533
|
|
|
531
534
|
|
|
532
535
|
class FunctionScope(Scope):
|
|
@@ -566,9 +569,6 @@ class FunctionScope(Scope):
|
|
|
566
569
|
if not binding.used and isinstance(binding, Annotation):
|
|
567
570
|
yield name, binding
|
|
568
571
|
|
|
569
|
-
def unused_indirect_assignments(self):
|
|
570
|
-
return self.indirect_assignments.items()
|
|
571
|
-
|
|
572
572
|
|
|
573
573
|
class TypeScope(Scope):
|
|
574
574
|
pass
|
|
@@ -835,6 +835,10 @@ class Checker:
|
|
|
835
835
|
which were imported but unused.
|
|
836
836
|
"""
|
|
837
837
|
for scope in self.deadScopes:
|
|
838
|
+
if isinstance(scope, (ClassScope, FunctionScope)):
|
|
839
|
+
for name, node in scope.indirect_assignments.items():
|
|
840
|
+
self.report(messages.UnusedIndirectAssignment, node, name)
|
|
841
|
+
|
|
838
842
|
# imports in classes are public members
|
|
839
843
|
if isinstance(scope, ClassScope):
|
|
840
844
|
continue
|
|
@@ -844,8 +848,6 @@ class Checker:
|
|
|
844
848
|
self.report(messages.UnusedVariable, binding.source, name)
|
|
845
849
|
for name, binding in scope.unused_annotations():
|
|
846
850
|
self.report(messages.UnusedAnnotation, binding.source, name)
|
|
847
|
-
for name, node in scope.unused_indirect_assignments():
|
|
848
|
-
self.report(messages.UnusedIndirectAssignment, node, name)
|
|
849
851
|
|
|
850
852
|
all_binding = scope.get('__all__')
|
|
851
853
|
if all_binding and not isinstance(all_binding, ExportBinding):
|
|
@@ -988,7 +990,7 @@ class Checker:
|
|
|
988
990
|
self.report(messages.RedefinedWhileUnused,
|
|
989
991
|
node, value.name, existing.source)
|
|
990
992
|
|
|
991
|
-
if isinstance(scope, FunctionScope):
|
|
993
|
+
if isinstance(scope, (ClassScope, FunctionScope)):
|
|
992
994
|
scope.indirect_assignments.pop(value.name, None)
|
|
993
995
|
|
|
994
996
|
elif isinstance(existing, Importation) and value.redefines(existing):
|
|
@@ -1008,8 +1010,12 @@ class Checker:
|
|
|
1008
1010
|
for scope in reversed(self.scopeStack)
|
|
1009
1011
|
if not isinstance(scope, GeneratorScope)
|
|
1010
1012
|
)
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
+
if value.name in scope and isinstance(scope[value.name], Annotation):
|
|
1014
|
+
# re-assignment to name that was previously only an annotation
|
|
1015
|
+
scope[value.name] = value
|
|
1016
|
+
else:
|
|
1017
|
+
# it may be a re-assignment to an already existing name
|
|
1018
|
+
scope.setdefault(value.name, value)
|
|
1013
1019
|
else:
|
|
1014
1020
|
self.scope[value.name] = value
|
|
1015
1021
|
|
|
@@ -1187,7 +1193,7 @@ class Checker:
|
|
|
1187
1193
|
# be executed.
|
|
1188
1194
|
return
|
|
1189
1195
|
|
|
1190
|
-
if isinstance(self.scope, FunctionScope):
|
|
1196
|
+
if isinstance(self.scope, (ClassScope, FunctionScope)):
|
|
1191
1197
|
self.scope.indirect_assignments.pop(name, None)
|
|
1192
1198
|
|
|
1193
1199
|
if isinstance(self.scope, FunctionScope) and name in self.scope.globals:
|
|
@@ -1121,6 +1121,36 @@ class Test(TestCase):
|
|
|
1121
1121
|
g = 2
|
|
1122
1122
|
''', m.UnusedIndirectAssignment, m.UnusedVariable)
|
|
1123
1123
|
|
|
1124
|
+
def test_global_nonlocal_in_class_bodies(self):
|
|
1125
|
+
self.flakes('''
|
|
1126
|
+
g = 0
|
|
1127
|
+
class C:
|
|
1128
|
+
global g
|
|
1129
|
+
g = 1
|
|
1130
|
+
def f():
|
|
1131
|
+
nl = 0
|
|
1132
|
+
class C:
|
|
1133
|
+
nonlocal nl
|
|
1134
|
+
nl = 1
|
|
1135
|
+
''')
|
|
1136
|
+
|
|
1137
|
+
def test_unused_global_in_class(self):
|
|
1138
|
+
self.flakes('''
|
|
1139
|
+
g = 0
|
|
1140
|
+
class C:
|
|
1141
|
+
global g
|
|
1142
|
+
u = g
|
|
1143
|
+
''', m.UnusedIndirectAssignment)
|
|
1144
|
+
|
|
1145
|
+
def test_unused_nonlocal_in_clas(self):
|
|
1146
|
+
self.flakes('''
|
|
1147
|
+
def f():
|
|
1148
|
+
nl = 1
|
|
1149
|
+
class C:
|
|
1150
|
+
nonlocal nl
|
|
1151
|
+
u = nl
|
|
1152
|
+
''', m.UnusedIndirectAssignment)
|
|
1153
|
+
|
|
1124
1154
|
def test_function_arguments(self):
|
|
1125
1155
|
"""
|
|
1126
1156
|
Test to traverse ARG and ARGUMENT handler
|
|
@@ -1744,6 +1774,13 @@ class TestUnusedAssignment(TestCase):
|
|
|
1744
1774
|
print(x)
|
|
1745
1775
|
''')
|
|
1746
1776
|
|
|
1777
|
+
def test_assign_expr_after_annotation(self):
|
|
1778
|
+
self.flakes("""
|
|
1779
|
+
a: int
|
|
1780
|
+
print(a := 3)
|
|
1781
|
+
print(a)
|
|
1782
|
+
""")
|
|
1783
|
+
|
|
1747
1784
|
def test_assign_expr_generator_scope(self):
|
|
1748
1785
|
"""Test assignment expressions in generator expressions."""
|
|
1749
1786
|
self.flakes('''
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '3.3.0'
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|