Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-pylint for openSUSE:Factory checked in at 2023-01-09 17:24:13 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pylint (Old) and /work/SRC/openSUSE:Factory/.python-pylint.new.32243 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pylint" Mon Jan 9 17:24:13 2023 rev:34 rq:1057060 version:2.15.10 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pylint/python-pylint.changes 2023-01-07 17:23:12.675407660 +0100 +++ /work/SRC/openSUSE:Factory/.python-pylint.new.32243/python-pylint.changes 2023-01-09 17:24:15.527313347 +0100 @@ -1,0 +2,13 @@ +Mon Jan 9 11:54:14 UTC 2023 - Dirk Müller <[email protected]> + +- update to v2.15.10: + * Fix use-sequence-for-iteration when unpacking a set with *. + * Fix false positive assigning-non-slot when a class attribute is + * re-assigned. + * Fixes used-before-assignment false positive when the walrus operator + * is used in a ternary operator. + * Prevent used-before-assignment when imports guarded by if TYPE_CHECKING + * are guarded again when used. + * Using custom braces in msg-template will now work properly. + +------------------------------------------------------------------- Old: ---- pylint-2.15.9-gh.tar.gz New: ---- pylint-2.15.10-gh.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pylint.spec ++++++ --- /var/tmp/diff_new_pack.HDdBrC/_old 2023-01-09 17:24:17.007321722 +0100 +++ /var/tmp/diff_new_pack.HDdBrC/_new 2023-01-09 17:24:17.007321722 +0100 @@ -18,7 +18,7 @@ %bcond_without tests Name: python-pylint -Version: 2.15.9 +Version: 2.15.10 Release: 0 Summary: Syntax and style checker for Python code License: GPL-2.0-or-later ++++++ pylint-2.15.9-gh.tar.gz -> pylint-2.15.10-gh.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/.pre-commit-config.yaml new/pylint-2.15.10/.pre-commit-config.yaml --- old/pylint-2.15.9/.pre-commit-config.yaml 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/.pre-commit-config.yaml 2023-01-09 10:37:24.000000000 +0100 @@ -118,7 +118,7 @@ args: [--prose-wrap=always, --print-width=88] exclude: tests(/\w*)*data/ - repo: https://github.com/DanielNoord/pydocstringformatter - rev: v0.7.0 + rev: v0.7.2 hooks: - id: pydocstringformatter exclude: *fixtures diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/doc/whatsnew/2/2.15/index.rst new/pylint-2.15.10/doc/whatsnew/2/2.15/index.rst --- old/pylint-2.15.9/doc/whatsnew/2/2.15/index.rst 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/doc/whatsnew/2/2.15/index.rst 2023-01-09 10:37:24.000000000 +0100 @@ -29,6 +29,44 @@ .. towncrier release notes start +What's new in Pylint 2.15.10? +----------------------------- +Release date: 2023-01-09 + + +False Positives Fixed +--------------------- + +- Fix ``use-sequence-for-iteration`` when unpacking a set with ``*``. + + Closes #5788 (`#5788 <https://github.com/PyCQA/pylint/issues/5788>`_) + +- Fix false positive ``assigning-non-slot`` when a class attribute is + re-assigned. + + Closes #6001 (`#6001 <https://github.com/PyCQA/pylint/issues/6001>`_) + +- Fixes ``used-before-assignment`` false positive when the walrus operator + is used in a ternary operator. + + Closes #7779 (`#7779 <https://github.com/PyCQA/pylint/issues/7779>`_) + +- Prevent ``used-before-assignment`` when imports guarded by ``if + TYPE_CHECKING`` + are guarded again when used. + + Closes #7979 (`#7979 <https://github.com/PyCQA/pylint/issues/7979>`_) + + + +Other Bug Fixes +--------------- + +- Using custom braces in ``msg-template`` will now work properly. + + Closes #5636 (`#5636 <https://github.com/PyCQA/pylint/issues/5636>`_) + + What's new in Pylint 2.15.9? ---------------------------- Release date: 2022-12-17 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/pylint/__pkginfo__.py new/pylint-2.15.10/pylint/__pkginfo__.py --- old/pylint-2.15.9/pylint/__pkginfo__.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/pylint/__pkginfo__.py 2023-01-09 10:37:24.000000000 +0100 @@ -9,7 +9,7 @@ from __future__ import annotations -__version__ = "2.15.9" +__version__ = "2.15.10" def get_numversion_from_version(v: str) -> tuple[int, int, int]: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/pylint/checkers/classes/class_checker.py new/pylint-2.15.10/pylint/checkers/classes/class_checker.py --- old/pylint-2.15.9/pylint/checkers/classes/class_checker.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/pylint/checkers/classes/class_checker.py 2023-01-09 10:37:24.000000000 +0100 @@ -1627,6 +1627,10 @@ # Properties circumvent the slots mechanism, # so we should not emit a warning for them. return + if node.attrname != "__class__" and utils.is_class_attr( + node.attrname, klass + ): + return if node.attrname in klass.locals: for local_name in klass.locals.get(node.attrname): statement = local_name.statement(future=True) @@ -1642,7 +1646,12 @@ slots, node.parent.value ): return - self.add_message("assigning-non-slot", args=(node.attrname,), node=node) + self.add_message( + "assigning-non-slot", + args=(node.attrname,), + node=node, + confidence=INFERENCE, + ) @only_required_for_messages( "protected-access", "no-classmethod-decorator", "no-staticmethod-decorator" @@ -1777,7 +1786,7 @@ if ( self._is_classmethod(node.frame(future=True)) and self._is_inferred_instance(node.expr, klass) - and self._is_class_attribute(attrname, klass) + and self._is_class_or_instance_attribute(attrname, klass) ): return @@ -1824,7 +1833,7 @@ return inferred._proxied is klass @staticmethod - def _is_class_attribute(name: str, klass: nodes.ClassDef) -> bool: + def _is_class_or_instance_attribute(name: str, klass: nodes.ClassDef) -> bool: """Check if the given attribute *name* is a class or instance member of the given *klass*. @@ -1832,11 +1841,8 @@ ``False`` otherwise. """ - try: - klass.getattr(name) + if utils.is_class_attr(name, klass): return True - except astroid.NotFoundError: - pass try: klass.instance_attr(name) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/pylint/checkers/refactoring/recommendation_checker.py new/pylint-2.15.10/pylint/checkers/refactoring/recommendation_checker.py --- old/pylint-2.15.9/pylint/checkers/refactoring/recommendation_checker.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/pylint/checkers/refactoring/recommendation_checker.py 2023-01-09 10:37:24.000000000 +0100 @@ -9,6 +9,7 @@ from pylint import checkers from pylint.checkers import utils +from pylint.interfaces import HIGH class RecommendationChecker(checkers.BaseChecker): @@ -326,9 +327,16 @@ def _check_use_sequence_for_iteration( self, node: nodes.For | nodes.Comprehension ) -> None: - """Check if code iterates over an in-place defined set.""" - if isinstance(node.iter, nodes.Set): - self.add_message("use-sequence-for-iteration", node=node.iter) + """Check if code iterates over an in-place defined set. + + Sets using `*` are not considered in-place. + """ + if isinstance(node.iter, nodes.Set) and not any( + utils.has_starred_node_recursive(node) + ): + self.add_message( + "use-sequence-for-iteration", node=node.iter, confidence=HIGH + ) @utils.only_required_for_messages("consider-using-f-string") def visit_const(self, node: nodes.Const) -> None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/pylint/checkers/utils.py new/pylint-2.15.10/pylint/checkers/utils.py --- old/pylint-2.15.9/pylint/checkers/utils.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/pylint/checkers/utils.py 2023-01-09 10:37:24.000000000 +0100 @@ -231,6 +231,12 @@ ) ) +SINGLETON_VALUES = {True, False, None} + +TERMINATING_FUNCS_QNAMES = frozenset( + {"_sitebuiltins.Quitter", "sys.exit", "posix._exit", "nt._exit"} +) + class NoSuchArgumentError(Exception): pass @@ -1961,6 +1967,20 @@ yield from find_assigned_names_recursive(elt) +def has_starred_node_recursive( + node: nodes.For | nodes.Comprehension | nodes.Set, +) -> Iterator[bool]: + """Yield ``True`` if a Starred node is found recursively.""" + if isinstance(node, nodes.Starred): + yield True + elif isinstance(node, nodes.Set): + for elt in node.elts: + yield from has_starred_node_recursive(elt) + elif isinstance(node, (nodes.For, nodes.Comprehension)): + for elt in node.iter.elts: + yield from has_starred_node_recursive(elt) + + def is_hashable(node: nodes.NodeNG) -> bool: """Return whether any inferred value of `node` is hashable. @@ -2014,3 +2034,39 @@ return True return False + + +def is_singleton_const(node: nodes.NodeNG) -> bool: + return isinstance(node, nodes.Const) and any( + node.value is value for value in SINGLETON_VALUES + ) + + +def is_terminating_func(node: nodes.Call) -> bool: + """Detect call to exit(), quit(), os._exit(), or sys.exit().""" + if ( + not isinstance(node.func, nodes.Attribute) + and not (isinstance(node.func, nodes.Name)) + or isinstance(node.parent, nodes.Lambda) + ): + return False + + try: + for inferred in node.func.infer(): + if ( + hasattr(inferred, "qname") + and inferred.qname() in TERMINATING_FUNCS_QNAMES + ): + return True + except (StopIteration, astroid.InferenceError): + pass + + return False + + +def is_class_attr(name: str, klass: nodes.ClassDef) -> bool: + try: + klass.getattr(name) + return True + except astroid.NotFoundError: + return False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/pylint/checkers/variables.py new/pylint-2.15.10/pylint/checkers/variables.py --- old/pylint-2.15.9/pylint/checkers/variables.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/pylint/checkers/variables.py 2023-01-09 10:37:24.000000000 +0100 @@ -27,12 +27,7 @@ in_type_checking_block, is_postponed_evaluation_enabled, ) -from pylint.constants import ( - PY39_PLUS, - TYPING_NEVER, - TYPING_NORETURN, - TYPING_TYPE_CHECKS_GUARDS, -) +from pylint.constants import PY39_PLUS, TYPING_NEVER, TYPING_NORETURN from pylint.interfaces import CONTROL_FLOW, HIGH, INFERENCE, INFERENCE_FAILURE from pylint.typing import MessageDefinitionTuple @@ -2003,7 +1998,8 @@ if ( isinstance(defstmt, (nodes.Import, nodes.ImportFrom)) and isinstance(defstmt.parent, nodes.If) - and defstmt.parent.test.as_string() in TYPING_TYPE_CHECKS_GUARDS + and in_type_checking_block(defstmt) + and not in_type_checking_block(node) ): defstmt_parent = defstmt.parent @@ -2059,9 +2055,16 @@ return True if isinstance(value, nodes.Lambda) and isinstance(value.body, nodes.IfExp): return True - return isinstance(value, nodes.Call) and ( - any(isinstance(kwarg.value, nodes.IfExp) for kwarg in value.keywords) - or any(isinstance(arg, nodes.IfExp) for arg in value.args) + if not isinstance(value, nodes.Call): + return False + return any( + any(isinstance(kwarg.value, nodes.IfExp) for kwarg in call.keywords) + or any(isinstance(arg, nodes.IfExp) for arg in call.args) + or ( + isinstance(call.func, nodes.Attribute) + and isinstance(call.func.expr, nodes.IfExp) + ) + for call in value.nodes_of_class(klass=nodes.Call) ) def _is_only_type_assignment( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/pylint/reporters/text.py new/pylint-2.15.10/pylint/reporters/text.py --- old/pylint-2.15.9/pylint/reporters/text.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/pylint/reporters/text.py 2023-01-09 10:37:24.000000000 +0100 @@ -175,7 +175,7 @@ self._template = template # Check to see if all parameters in the template are attributes of the Message - arguments = re.findall(r"\{(.+?)(:.*)?\}", template) + arguments = re.findall(r"\{(\w+?)(:.*)?\}", template) for argument in arguments: if argument[0] not in MESSAGE_FIELDS: warnings.warn( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tbump.toml new/pylint-2.15.10/tbump.toml --- old/pylint-2.15.9/tbump.toml 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tbump.toml 2023-01-09 10:37:24.000000000 +0100 @@ -1,7 +1,7 @@ github_url = "https://github.com/PyCQA/pylint" [version] -current = "2.15.9" +current = "2.15.10" regex = ''' ^(?P<major>0|[1-9]\d*) \. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/a/assigning/assigning_non_slot.py new/pylint-2.15.10/tests/functional/a/assigning/assigning_non_slot.py --- old/pylint-2.15.9/tests/functional/a/assigning/assigning_non_slot.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/a/assigning/assigning_non_slot.py 2023-01-09 10:37:24.000000000 +0100 @@ -2,6 +2,8 @@ will trigger assigning-non-slot warning. """ # pylint: disable=too-few-public-methods, missing-docstring, import-error, redundant-u-string-prefix, unnecessary-dunder-call +# pylint: disable=attribute-defined-outside-init + from collections import deque from missing import Unknown @@ -129,7 +131,7 @@ # This should not emit, because attr is # a data descriptor inst.data_descriptor = 'foo' - inst.non_data_descriptor = 'lala' # [assigning-non-slot] + inst.non_data_descriptor = 'lala' class ClassWithSlots: @@ -147,7 +149,8 @@ __slots__ = [] def release(self): - self.__class__ = ClassWithSlots # [assigning-non-slot] + self.__class__ = ClassWithSlots # [assigning-non-slot] + self.test = 'test' # [assigning-non-slot] # pylint: disable=attribute-defined-outside-init @@ -200,3 +203,39 @@ child = ClassWithParentDefiningSetattr() child.non_existent = "non-existent" + +class ColorCls: + __slots__ = () + COLOR = "red" + + +class Child(ColorCls): + __slots__ = () + + +repro = Child() +Child.COLOR = "blue" + +class MyDescriptor: + """Basic descriptor.""" + + def __get__(self, instance, owner): + return 42 + + def __set__(self, instance, value): + pass + + +# Regression test from https://github.com/PyCQA/pylint/issues/6001 +class Base: + __slots__ = () + + attr2 = MyDescriptor() + + +class Repro(Base): + __slots__ = () + + +repro = Repro() +repro.attr2 = "anything" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/a/assigning/assigning_non_slot.txt new/pylint-2.15.10/tests/functional/a/assigning/assigning_non_slot.txt --- old/pylint-2.15.9/tests/functional/a/assigning/assigning_non_slot.txt 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/a/assigning/assigning_non_slot.txt 2023-01-09 10:37:24.000000000 +0100 @@ -1,5 +1,5 @@ -assigning-non-slot:18:8:18:20:Bad.__init__:Assigning to attribute 'missing' not defined in class slots:UNDEFINED -assigning-non-slot:26:8:26:20:Bad2.__init__:Assigning to attribute 'missing' not defined in class slots:UNDEFINED -assigning-non-slot:36:8:36:20:Bad3.__init__:Assigning to attribute 'missing' not defined in class slots:UNDEFINED -assigning-non-slot:132:4:132:28:dont_emit_for_descriptors:Assigning to attribute 'non_data_descriptor' not defined in class slots:UNDEFINED -assigning-non-slot:150:8:150:22:ClassReassingingInvalidLayoutClass.release:Assigning to attribute '__class__' not defined in class slots:UNDEFINED +assigning-non-slot:20:8:20:20:Bad.__init__:Assigning to attribute 'missing' not defined in class slots:INFERENCE +assigning-non-slot:28:8:28:20:Bad2.__init__:Assigning to attribute 'missing' not defined in class slots:INFERENCE +assigning-non-slot:38:8:38:20:Bad3.__init__:Assigning to attribute 'missing' not defined in class slots:INFERENCE +assigning-non-slot:152:8:152:22:ClassReassingingInvalidLayoutClass.release:Assigning to attribute '__class__' not defined in class slots:INFERENCE +assigning-non-slot:153:8:153:17:ClassReassingingInvalidLayoutClass.release:Assigning to attribute 'test' not defined in class slots:INFERENCE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/a/assigning/assigning_non_slot_4509.txt new/pylint-2.15.10/tests/functional/a/assigning/assigning_non_slot_4509.txt --- old/pylint-2.15.9/tests/functional/a/assigning/assigning_non_slot_4509.txt 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/a/assigning/assigning_non_slot_4509.txt 2023-01-09 10:37:24.000000000 +0100 @@ -1 +1 @@ -assigning-non-slot:18:8:18:17:Foo.__init__:Assigning to attribute '_bar' not defined in class slots:UNDEFINED +assigning-non-slot:18:8:18:17:Foo.__init__:Assigning to attribute '_bar' not defined in class slots:INFERENCE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/ext/code_style/cs_consider_using_tuple.py new/pylint-2.15.10/tests/functional/ext/code_style/cs_consider_using_tuple.py --- old/pylint-2.15.9/tests/functional/ext/code_style/cs_consider_using_tuple.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/ext/code_style/cs_consider_using_tuple.py 2023-01-09 10:37:24.000000000 +0100 @@ -28,4 +28,4 @@ # Don't emit warning for sets as this is handled by builtin checker (x for x in {1, 2, 3}) # [use-sequence-for-iteration] -[x for x in {*var, 2}] # [use-sequence-for-iteration] +[x for x in {*var, 2}] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/ext/code_style/cs_consider_using_tuple.txt new/pylint-2.15.10/tests/functional/ext/code_style/cs_consider_using_tuple.txt --- old/pylint-2.15.9/tests/functional/ext/code_style/cs_consider_using_tuple.txt 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/ext/code_style/cs_consider_using_tuple.txt 2023-01-09 10:37:24.000000000 +0100 @@ -4,5 +4,4 @@ consider-using-tuple:21:9:21:15::Consider using an in-place tuple instead of list:UNDEFINED consider-using-tuple:23:9:23:18::Consider using an in-place tuple instead of list:UNDEFINED consider-using-tuple:26:12:26:21::Consider using an in-place tuple instead of list:UNDEFINED -use-sequence-for-iteration:30:12:30:21::Use a sequence type when iterating over values:UNDEFINED -use-sequence-for-iteration:31:12:31:21::Use a sequence type when iterating over values:UNDEFINED +use-sequence-for-iteration:30:12:30:21::Use a sequence type when iterating over values:HIGH diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/u/use/use_sequence_for_iteration.py new/pylint-2.15.10/tests/functional/u/use/use_sequence_for_iteration.py --- old/pylint-2.15.9/tests/functional/u/use/use_sequence_for_iteration.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/u/use/use_sequence_for_iteration.py 2023-01-09 10:37:24.000000000 +0100 @@ -13,4 +13,16 @@ [x for x in var] [x for x in {1, 2, 3}] # [use-sequence-for-iteration] -[x for x in {*var, 4}] # [use-sequence-for-iteration] +[x for x in {*var, 4}] + +def deduplicate(list_in): + for thing in {*list_in}: + print(thing) + +def deduplicate_two_lists(input1, input2): + for thing in {*input1, *input2}: + print(thing) + +def deduplicate_nested_sets(input1, input2, input3, input4): + for thing in {{*input1, *input2}, {*input3, *input4}}: + print(thing) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/u/use/use_sequence_for_iteration.txt new/pylint-2.15.10/tests/functional/u/use/use_sequence_for_iteration.txt --- old/pylint-2.15.9/tests/functional/u/use/use_sequence_for_iteration.txt 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/u/use/use_sequence_for_iteration.txt 2023-01-09 10:37:24.000000000 +0100 @@ -1,4 +1,3 @@ -use-sequence-for-iteration:7:9:7:18::Use a sequence type when iterating over values:UNDEFINED -use-sequence-for-iteration:11:12:11:21::Use a sequence type when iterating over values:UNDEFINED -use-sequence-for-iteration:14:12:14:21::Use a sequence type when iterating over values:UNDEFINED -use-sequence-for-iteration:16:12:16:21::Use a sequence type when iterating over values:UNDEFINED +use-sequence-for-iteration:7:9:7:18::Use a sequence type when iterating over values:HIGH +use-sequence-for-iteration:11:12:11:21::Use a sequence type when iterating over values:HIGH +use-sequence-for-iteration:14:12:14:21::Use a sequence type when iterating over values:HIGH diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/u/used/used_before_assignment_ternary.py new/pylint-2.15.10/tests/functional/u/used/used_before_assignment_ternary.py --- old/pylint-2.15.9/tests/functional/u/used/used_before_assignment_ternary.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/u/used/used_before_assignment_ternary.py 2023-01-09 10:37:24.000000000 +0100 @@ -0,0 +1,41 @@ +"""Tests for used-before-assignment false positive from ternary expression with walrus operator""" +# pylint: disable=unnecessary-lambda-assignment, unused-variable, disallowed-name, invalid-name + +def invalid(): + """invalid cases that will trigger used-before-assignment""" + var = foo(a, '', '') # [used-before-assignment] + print(str(1 if (a:=-1) else 0)) + var = bar(b) # [used-before-assignment] + var = c*c # [used-before-assignment] + var = 1 if (b:=-1) else 0 + var = 1 if (c:=-1) else 0 + +def attribute_call_valid(): + """assignment with attribute calls""" + var = (a if (a:='a') else '').lower() + var = ('' if (b:='b') else b).lower() + var = (c if (c:='c') else c).upper().lower().replace('', '').strip() + var = ''.strip().replace('', '' + (e if (e:='e') else '').lower()) + +def function_call_arg_valid(): + """assignment as function call arguments""" + var = str(a if (a:='a') else '') + var = str('' if (b:='b') else b) + var = foo(1, c if (c:=1) else 0, 1) + print(foo('', '', foo('', str(int(d if (d:='1') else '')), ''))) + +def function_call_keyword_valid(): + """assignment as function call keywords""" + var = foo(x=a if (a:='1') else '', y='', z='') + var = foo(x='', y=foo(x='', y='', z=b if (b:='1') else ''), z='') + +def complex_valid(): + """assignment within complex call expression""" + var = str(bar(bar(a if (a:=1) else 0))).lower().upper() + print(foo(x=foo(''.replace('', str(b if (b:=1) else 0).upper()), '', z=''), y='', z='')) + +def foo(x, y, z): + """helper function for tests""" + return x+y+z + +bar = lambda x : x diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/u/used/used_before_assignment_ternary.rc new/pylint-2.15.10/tests/functional/u/used/used_before_assignment_ternary.rc --- old/pylint-2.15.9/tests/functional/u/used/used_before_assignment_ternary.rc 1970-01-01 01:00:00.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/u/used/used_before_assignment_ternary.rc 2023-01-09 10:37:24.000000000 +0100 @@ -0,0 +1,2 @@ +[testoptions] +min_pyver=3.8 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/u/used/used_before_assignment_ternary.txt new/pylint-2.15.10/tests/functional/u/used/used_before_assignment_ternary.txt --- old/pylint-2.15.9/tests/functional/u/used/used_before_assignment_ternary.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/u/used/used_before_assignment_ternary.txt 2023-01-09 10:37:24.000000000 +0100 @@ -0,0 +1,3 @@ +used-before-assignment:6:14:6:15:invalid:Using variable 'a' before assignment:HIGH +used-before-assignment:8:14:8:15:invalid:Using variable 'b' before assignment:HIGH +used-before-assignment:9:10:9:11:invalid:Using variable 'c' before assignment:HIGH diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/u/used/used_before_assignment_typing.py new/pylint-2.15.10/tests/functional/u/used/used_before_assignment_typing.py --- old/pylint-2.15.9/tests/functional/u/used/used_before_assignment_typing.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/u/used/used_before_assignment_typing.py 2023-01-09 10:37:24.000000000 +0100 @@ -6,6 +6,7 @@ if TYPE_CHECKING: import datetime + from urllib.request import urlopen class MyClass: """Type annotation or default values for first level methods can't refer to their own class""" @@ -90,3 +91,9 @@ def print_date(self, date) -> None: date: datetime.date = date print(date) + + +class ConditionalImportGuardedWhenUsed: # pylint: disable=too-few-public-methods + """Conditional imports also guarded by TYPE_CHECKING when used.""" + if TYPE_CHECKING: + print(urlopen) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/functional/u/used/used_before_assignment_typing.txt new/pylint-2.15.10/tests/functional/u/used/used_before_assignment_typing.txt --- old/pylint-2.15.9/tests/functional/u/used/used_before_assignment_typing.txt 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tests/functional/u/used/used_before_assignment_typing.txt 2023-01-09 10:37:24.000000000 +0100 @@ -1,4 +1,4 @@ -undefined-variable:14:21:14:28:MyClass.incorrect_typing_method:Undefined variable 'MyClass':UNDEFINED -undefined-variable:19:26:19:33:MyClass.incorrect_nested_typing_method:Undefined variable 'MyClass':UNDEFINED -undefined-variable:24:20:24:27:MyClass.incorrect_default_method:Undefined variable 'MyClass':UNDEFINED -used-before-assignment:88:20:88:28:VariableAnnotationsGuardedByTypeChecking:Using variable 'datetime' before assignment:HIGH +undefined-variable:15:21:15:28:MyClass.incorrect_typing_method:Undefined variable 'MyClass':UNDEFINED +undefined-variable:20:26:20:33:MyClass.incorrect_nested_typing_method:Undefined variable 'MyClass':UNDEFINED +undefined-variable:25:20:25:27:MyClass.incorrect_default_method:Undefined variable 'MyClass':UNDEFINED +used-before-assignment:89:20:89:28:VariableAnnotationsGuardedByTypeChecking:Using variable 'datetime' before assignment:HIGH diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pylint-2.15.9/tests/reporters/unittest_reporting.py new/pylint-2.15.10/tests/reporters/unittest_reporting.py --- old/pylint-2.15.9/tests/reporters/unittest_reporting.py 2022-12-17 15:03:05.000000000 +0100 +++ new/pylint-2.15.10/tests/reporters/unittest_reporting.py 2023-01-09 10:37:24.000000000 +0100 @@ -14,6 +14,7 @@ from typing import TYPE_CHECKING import pytest +from _pytest.recwarn import WarningsRecorder from pylint import checkers from pylint.interfaces import HIGH @@ -88,16 +89,12 @@ """ output = StringIO() linter.reporter.out = output - linter.config.msg_template = ( - "{path}:{line}:{a_new_option}:({a_second_new_option:03d})" - ) + linter.config.msg_template = "{path}:{line}:{categ}:({a_second_new_option:03d})" linter.open() with pytest.warns(UserWarning) as records: linter.set_current_module("my_mod") assert len(records) == 2 - assert ( - "Don't recognize the argument 'a_new_option'" in records[0].message.args[0] - ) + assert "Don't recognize the argument 'categ'" in records[0].message.args[0] assert ( "Don't recognize the argument 'a_second_new_option'" in records[1].message.args[0] @@ -113,7 +110,24 @@ assert out_lines[2] == "my_mod:2::()" -def test_deprecation_set_output(recwarn): +def test_template_option_with_header(linter: PyLinter) -> None: + output = StringIO() + linter.reporter.out = output + linter.config.msg_template = '{{ "Category": "{category}" }}' + linter.open() + linter.set_current_module("my_mod") + + linter.add_message("C0301", line=1, args=(1, 2)) + linter.add_message( + "line-too-long", line=2, end_lineno=2, end_col_offset=4, args=(3, 4) + ) + + out_lines = output.getvalue().split("\n") + assert out_lines[1] == '{ "Category": "convention" }' + assert out_lines[2] == '{ "Category": "convention" }' + + +def test_deprecation_set_output(recwarn: WarningsRecorder) -> None: """TODO remove in 3.0.""" reporter = BaseReporter() # noinspection PyDeprecation
