prompt: 'AsStringVisitor' object has no attribute 'visit_unknown'
  ```python
  >>> import astroid
  >>> astroid.nodes.Unknown().as_string()
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "/Users/tusharsadhwani/code/marvin-python/venv/lib/python3.9/site-packages/astroid/nodes/node_ng.py", line 609, in as_string
      return AsStringVisitor()(self)
    File "/Users/tusharsadhwani/code/marvin-python/venv/lib/python3.9/site-packages/astroid/nodes/as_string.py", line 56, in __call__
      return node.accept(self).replace(DOC_NEWLINE, "\n")
    File "/Users/tusharsadhwani/code/marvin-python/venv/lib/python3.9/site-packages/astroid/nodes/node_ng.py", line 220, in accept
      func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
  AttributeError: 'AsStringVisitor' object has no attribute 'visit_unknown'
  >>> 
  ```
  ### `python -c "from astroid import __pkginfo__; print(__pkginfo__.version)"` output
  
  2.8.6-dev0
  
instance: {"FAIL_TO_PASS": "[\"tests/unittest_nodes.py::AsStringTest::test_as_string_unknown\"]", "PASS_TO_PASS": "[\"tests/unittest_nodes.py::AsStringTest::test_3k_annotations_and_metaclass\", \"tests/unittest_nodes.py::AsStringTest::test_3k_as_string\", \"tests/unittest_nodes.py::AsStringTest::test_as_string\", \"tests/unittest_nodes.py::AsStringTest::test_as_string_for_list_containing_uninferable\", \"tests/unittest_nodes.py::AsStringTest::test_class_def\", \"tests/unittest_nodes.py::AsStringTest::test_ellipsis\", \"tests/unittest_nodes.py::AsStringTest::test_f_strings\", \"tests/unittest_nodes.py::AsStringTest::test_frozenset_as_string\", \"tests/unittest_nodes.py::AsStringTest::test_func_signature_issue_185\", \"tests/unittest_nodes.py::AsStringTest::test_int_attribute\", \"tests/unittest_nodes.py::AsStringTest::test_module2_as_string\", \"tests/unittest_nodes.py::AsStringTest::test_module_as_string\", \"tests/unittest_nodes.py::AsStringTest::test_operator_precedence\", \"tests/unittest_nodes.py::AsStringTest::test_slice_and_subscripts\", \"tests/unittest_nodes.py::AsStringTest::test_slices\", \"tests/unittest_nodes.py::AsStringTest::test_tuple_as_string\", \"tests/unittest_nodes.py::AsStringTest::test_varargs_kwargs_as_string\", \"tests/unittest_nodes.py::IfNodeTest::test_block_range\", \"tests/unittest_nodes.py::IfNodeTest::test_if_elif_else_node\", \"tests/unittest_nodes.py::IfNodeTest::test_if_sys_guard\", \"tests/unittest_nodes.py::IfNodeTest::test_if_typing_guard\", \"tests/unittest_nodes.py::TryExceptNodeTest::test_block_range\", \"tests/unittest_nodes.py::TryFinallyNodeTest::test_block_range\", \"tests/unittest_nodes.py::TryExceptFinallyNodeTest::test_block_range\", \"tests/unittest_nodes.py::ImportNodeTest::test_absolute_import\", \"tests/unittest_nodes.py::ImportNodeTest::test_as_string\", \"tests/unittest_nodes.py::ImportNodeTest::test_bad_import_inference\", \"tests/unittest_nodes.py::ImportNodeTest::test_conditional\", \"tests/unittest_nodes.py::ImportNodeTest::test_conditional_import\", \"tests/unittest_nodes.py::ImportNodeTest::test_from_self_resolve\", \"tests/unittest_nodes.py::ImportNodeTest::test_import_self_resolve\", \"tests/unittest_nodes.py::ImportNodeTest::test_more_absolute_import\", \"tests/unittest_nodes.py::ImportNodeTest::test_real_name\", \"tests/unittest_nodes.py::CmpNodeTest::test_as_string\", \"tests/unittest_nodes.py::ConstNodeTest::test_bool\", \"tests/unittest_nodes.py::ConstNodeTest::test_complex\", \"tests/unittest_nodes.py::ConstNodeTest::test_copy\", \"tests/unittest_nodes.py::ConstNodeTest::test_float\", \"tests/unittest_nodes.py::ConstNodeTest::test_int\", \"tests/unittest_nodes.py::ConstNodeTest::test_none\", \"tests/unittest_nodes.py::ConstNodeTest::test_str\", \"tests/unittest_nodes.py::ConstNodeTest::test_str_kind\", \"tests/unittest_nodes.py::ConstNodeTest::test_unicode\", \"tests/unittest_nodes.py::NameNodeTest::test_assign_to_true\", \"tests/unittest_nodes.py::TestNamedExprNode::test_frame\", \"tests/unittest_nodes.py::TestNamedExprNode::test_scope\", \"tests/unittest_nodes.py::AnnAssignNodeTest::test_as_string\", \"tests/unittest_nodes.py::AnnAssignNodeTest::test_complex\", \"tests/unittest_nodes.py::AnnAssignNodeTest::test_primitive\", \"tests/unittest_nodes.py::AnnAssignNodeTest::test_primitive_without_initial_value\", \"tests/unittest_nodes.py::ArgumentsNodeTC::test_kwoargs\", \"tests/unittest_nodes.py::ArgumentsNodeTC::test_positional_only\", \"tests/unittest_nodes.py::UnboundMethodNodeTest::test_no_super_getattr\", \"tests/unittest_nodes.py::BoundMethodNodeTest::test_is_property\", \"tests/unittest_nodes.py::AliasesTest::test_aliases\", \"tests/unittest_nodes.py::Python35AsyncTest::test_async_await_keywords\", \"tests/unittest_nodes.py::Python35AsyncTest::test_asyncfor_as_string\", \"tests/unittest_nodes.py::Python35AsyncTest::test_asyncwith_as_string\", \"tests/unittest_nodes.py::Python35AsyncTest::test_await_as_string\", \"tests/unittest_nodes.py::Python35AsyncTest::test_decorated_async_def_as_string\", \"tests/unittest_nodes.py::ContextTest::test_list_del\", \"tests/unittest_nodes.py::ContextTest::test_list_load\", \"tests/unittest_nodes.py::ContextTest::test_list_store\", \"tests/unittest_nodes.py::ContextTest::test_starred_load\", \"tests/unittest_nodes.py::ContextTest::test_starred_store\", \"tests/unittest_nodes.py::ContextTest::test_subscript_del\", \"tests/unittest_nodes.py::ContextTest::test_subscript_load\", \"tests/unittest_nodes.py::ContextTest::test_subscript_store\", \"tests/unittest_nodes.py::ContextTest::test_tuple_load\", \"tests/unittest_nodes.py::ContextTest::test_tuple_store\", \"tests/unittest_nodes.py::test_unknown\", \"tests/unittest_nodes.py::test_type_comments_with\", \"tests/unittest_nodes.py::test_type_comments_for\", \"tests/unittest_nodes.py::test_type_coments_assign\", \"tests/unittest_nodes.py::test_type_comments_invalid_expression\", \"tests/unittest_nodes.py::test_type_comments_invalid_function_comments\", \"tests/unittest_nodes.py::test_type_comments_function\", \"tests/unittest_nodes.py::test_type_comments_arguments\", \"tests/unittest_nodes.py::test_type_comments_posonly_arguments\", \"tests/unittest_nodes.py::test_correct_function_type_comment_parent\", \"tests/unittest_nodes.py::test_is_generator_for_yield_assignments\", \"tests/unittest_nodes.py::test_f_string_correct_line_numbering\", \"tests/unittest_nodes.py::test_assignment_expression\", \"tests/unittest_nodes.py::test_assignment_expression_in_functiondef\", \"tests/unittest_nodes.py::test_get_doc\", \"tests/unittest_nodes.py::test_parse_fstring_debug_mode\", \"tests/unittest_nodes.py::test_parse_type_comments_with_proper_parent\", \"tests/unittest_nodes.py::test_const_itered\", \"tests/unittest_nodes.py::test_is_generator_for_yield_in_while\", \"tests/unittest_nodes.py::test_is_generator_for_yield_in_if\", \"tests/unittest_nodes.py::test_is_generator_for_yield_in_aug_assign\"]", "base_commit": "ce5cbce5ba11cdc2f8139ade66feea1e181a7944", "created_at": "2021-11-21T16:15:23Z", "environment_setup_commit": "0d1211558670cfefd95b39984b8d5f7f34837f32", "hints_text": "Thank you for opening the issue.\nI don't believe `Unknown().as_string()` is ever called regularly. AFAIK it's only used during inference. What should the string representation of an `Unknown` node be? So not sure this needs to be addressed.\nProbably just `'Unknown'`.\nIt's mostly only a problem when we do something like this:\n\n```python\ninferred = infer(node)\nif inferred is not Uninferable:\n    if inferred.as_string().contains(some_value):\n        ...\n```\nSo for the most part, as long as it doesn't crash we're good.", "instance_id": "pylint-dev__astroid-1268", "patch": "diff --git a/astroid/nodes/as_string.py b/astroid/nodes/as_string.py\n--- a/astroid/nodes/as_string.py\n+++ b/astroid/nodes/as_string.py\n@@ -36,6 +36,7 @@\n         MatchSingleton,\n         MatchStar,\n         MatchValue,\n+        Unknown,\n     )\n \n # pylint: disable=unused-argument\n@@ -643,6 +644,9 @@ def visit_property(self, node):\n     def visit_evaluatedobject(self, node):\n         return node.original.accept(self)\n \n+    def visit_unknown(self, node: \"Unknown\") -> str:\n+        return str(node)\n+\n \n def _import_string(names):\n     \"\"\"return a list of (name, asname) formatted as a string\"\"\"\n", "problem_statement": "'AsStringVisitor' object has no attribute 'visit_unknown'\n```python\r\n>>> import astroid\r\n>>> astroid.nodes.Unknown().as_string()\r\nTraceback (most recent call last):\r\n  File \"<stdin>\", line 1, in <module>\r\n  File \"/Users/tusharsadhwani/code/marvin-python/venv/lib/python3.9/site-packages/astroid/nodes/node_ng.py\", line 609, in as_string\r\n    return AsStringVisitor()(self)\r\n  File \"/Users/tusharsadhwani/code/marvin-python/venv/lib/python3.9/site-packages/astroid/nodes/as_string.py\", line 56, in __call__\r\n    return node.accept(self).replace(DOC_NEWLINE, \"\\n\")\r\n  File \"/Users/tusharsadhwani/code/marvin-python/venv/lib/python3.9/site-packages/astroid/nodes/node_ng.py\", line 220, in accept\r\n    func = getattr(visitor, \"visit_\" + self.__class__.__name__.lower())\r\nAttributeError: 'AsStringVisitor' object has no attribute 'visit_unknown'\r\n>>> \r\n```\r\n### `python -c \"from astroid import __pkginfo__; print(__pkginfo__.version)\"` output\r\n\r\n2.8.6-dev0\n", "repo": "pylint-dev/astroid", "test_patch": "diff --git a/tests/unittest_nodes.py b/tests/unittest_nodes.py\n--- a/tests/unittest_nodes.py\n+++ b/tests/unittest_nodes.py\n@@ -306,6 +306,11 @@ def test_f_strings(self):\n         ast = abuilder.string_build(code)\n         self.assertEqual(ast.as_string().strip(), code.strip())\n \n+    @staticmethod\n+    def test_as_string_unknown() -> None:\n+        assert nodes.Unknown().as_string() == \"Unknown.Unknown()\"\n+        assert nodes.Unknown(lineno=1, col_offset=0).as_string() == \"Unknown.Unknown()\"\n+\n \n class _NodeTest(unittest.TestCase):\n     \"\"\"test transformation of If Node\"\"\"\n", "version": "2.9"}
parsed_commit_content: {"file_diffs":[{"old_file_content":"# Copyright (c) 2009-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>\n# Copyright (c) 2010 Daniel Harding <dharding@gmail.com>\n# Copyright (c) 2013-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>\n# Copyright (c) 2013-2014 Google, Inc.\n# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>\n# Copyright (c) 2016 Jared Garst <jgarst@users.noreply.github.com>\n# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>\n# Copyright (c) 2017, 2019 Łukasz Rogalski <rogalski.91@gmail.com>\n# Copyright (c) 2017 rr- <rr-@sakuya.pl>\n# Copyright (c) 2018 Serhiy Storchaka <storchaka@gmail.com>\n# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>\n# Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com>\n# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>\n# Copyright (c) 2019 Alex Hall <alex.mojaki@gmail.com>\n# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>\n# Copyright (c) 2021 Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>\n# Copyright (c) 2021 Pierre Sassoulas <pierre.sassoulas@gmail.com>\n# Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com>\n# Copyright (c) 2021 pre-commit-ci[bot] <bot@noreply.github.com>\n\n# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html\n# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE\n\n\"\"\"This module renders Astroid nodes as string\"\"\"\nfrom typing import TYPE_CHECKING, List\n\nif TYPE_CHECKING:\n    from astroid.nodes.node_classes import (\n        Match,\n        MatchAs,\n        MatchCase,\n        MatchClass,\n        MatchMapping,\n        MatchOr,\n        MatchSequence,\n        MatchSingleton,\n        MatchStar,\n        MatchValue,\n    )\n\n# pylint: disable=unused-argument\n\nDOC_NEWLINE = \"\\0\"\n\n\n# Visitor pattern require argument all the time and is not better with staticmethod\n# noinspection PyUnusedLocal,PyMethodMayBeStatic\nclass AsStringVisitor:\n    \"\"\"Visitor to render an Astroid node as a valid python code string\"\"\"\n\n    def __init__(self, indent=\"    \"):\n        self.indent = indent\n\n    def __call__(self, node):\n        \"\"\"Makes this visitor behave as a simple function\"\"\"\n        return node.accept(self).replace(DOC_NEWLINE, \"\\n\")\n\n    def _docs_dedent(self, doc):\n        \"\"\"Stop newlines in docs being indented by self._stmt_list\"\"\"\n        return '\\n{}\"\"\"{}\"\"\"'.format(self.indent, doc.replace(\"\\n\", DOC_NEWLINE))\n\n    def _stmt_list(self, stmts, indent=True):\n        \"\"\"return a list of nodes to string\"\"\"\n        stmts = \"\\n\".join(nstr for nstr in [n.accept(self) for n in stmts] if nstr)\n        if indent:\n            return self.indent + stmts.replace(\"\\n\", \"\\n\" + self.indent)\n\n        return stmts\n\n    def _precedence_parens(self, node, child, is_left=True):\n        \"\"\"Wrap child in parens only if required to keep same semantics\"\"\"\n        if self._should_wrap(node, child, is_left):\n            return f\"({child.accept(self)})\"\n\n        return child.accept(self)\n\n    def _should_wrap(self, node, child, is_left):\n        \"\"\"Wrap child if:\n        - it has lower precedence\n        - same precedence with position opposite to associativity direction\n        \"\"\"\n        node_precedence = node.op_precedence()\n        child_precedence = child.op_precedence()\n\n        if node_precedence > child_precedence:\n            # 3 * (4 + 5)\n            return True\n\n        if (\n            node_precedence == child_precedence\n            and is_left != node.op_left_associative()\n        ):\n            # 3 - (4 - 5)\n            # (2**3)**4\n            return True\n\n        return False\n\n    # visit_<node> methods ###########################################\n\n    def visit_await(self, node):\n        return f\"await {node.value.accept(self)}\"\n\n    def visit_asyncwith(self, node):\n        return f\"async {self.visit_with(node)}\"\n\n    def visit_asyncfor(self, node):\n        return f\"async {self.visit_for(node)}\"\n\n    def visit_arguments(self, node):\n        \"\"\"return an astroid.Function node as string\"\"\"\n        return node.format_args()\n\n    def visit_assignattr(self, node):\n        \"\"\"return an astroid.AssAttr node as string\"\"\"\n        return self.visit_attribute(node)\n\n    def visit_assert(self, node):\n        \"\"\"return an astroid.Assert node as string\"\"\"\n        if node.fail:\n            return f\"assert {node.test.accept(self)}, {node.fail.accept(self)}\"\n        return f\"assert {node.test.accept(self)}\"\n\n    def visit_assignname(self, node):\n        \"\"\"return an astroid.AssName node as string\"\"\"\n        return node.name\n\n    def visit_assign(self, node):\n        \"\"\"return an astroid.Assign node as string\"\"\"\n        lhs = \" = \".join(n.accept(self) for n in node.targets)\n        return f\"{lhs} = {node.value.accept(self)}\"\n\n    def visit_augassign(self, node):\n        \"\"\"return an astroid.AugAssign node as string\"\"\"\n        return f\"{node.target.accept(self)} {node.op} {node.value.accept(self)}\"\n\n    def visit_annassign(self, node):\n        \"\"\"Return an astroid.AugAssign node as string\"\"\"\n\n        target = node.target.accept(self)\n        annotation = node.annotation.accept(self)\n        if node.value is None:\n            return f\"{target}: {annotation}\"\n        return f\"{target}: {annotation} = {node.value.accept(self)}\"\n\n    def visit_binop(self, node):\n        \"\"\"return an astroid.BinOp node as string\"\"\"\n        left = self._precedence_parens(node, node.left)\n        right = self._precedence_parens(node, node.right, is_left=False)\n        if node.op == \"**\":\n            return f\"{left}{node.op}{right}\"\n\n        return f\"{left} {node.op} {right}\"\n\n    def visit_boolop(self, node):\n        \"\"\"return an astroid.BoolOp node as string\"\"\"\n        values = [f\"{self._precedence_parens(node, n)}\" for n in node.values]\n        return (f\" {node.op} \").join(values)\n\n    def visit_break(self, node):\n        \"\"\"return an astroid.Break node as string\"\"\"\n        return \"break\"\n\n    def visit_call(self, node):\n        \"\"\"return an astroid.Call node as string\"\"\"\n        expr_str = self._precedence_parens(node, node.func)\n        args = [arg.accept(self) for arg in node.args]\n        if node.keywords:\n            keywords = [kwarg.accept(self) for kwarg in node.keywords]\n        else:\n            keywords = []\n\n        args.extend(keywords)\n        return f\"{expr_str}({', '.join(args)})\"\n\n    def visit_classdef(self, node):\n        \"\"\"return an astroid.ClassDef node as string\"\"\"\n        decorate = node.decorators.accept(self) if node.decorators else \"\"\n        args = [n.accept(self) for n in node.bases]\n        if node._metaclass and not node.has_metaclass_hack():\n            args.append(\"metaclass=\" + node._metaclass.accept(self))\n        args += [n.accept(self) for n in node.keywords]\n        args = f\"({', '.join(args)})\" if args else \"\"\n        docs = self._docs_dedent(node.doc) if node.doc else \"\"\n        return \"\\n\\n{}class {}{}:{}\\n{}\\n\".format(\n            decorate, node.name, args, docs, self._stmt_list(node.body)\n        )\n\n    def visit_compare(self, node):\n        \"\"\"return an astroid.Compare node as string\"\"\"\n        rhs_str = \" \".join(\n            f\"{op} {self._precedence_parens(node, expr, is_left=False)}\"\n            for op, expr in node.ops\n        )\n        return f\"{self._precedence_parens(node, node.left)} {rhs_str}\"\n\n    def visit_comprehension(self, node):\n        \"\"\"return an astroid.Comprehension node as string\"\"\"\n        ifs = \"\".join(f\" if {n.accept(self)}\" for n in node.ifs)\n        generated = f\"for {node.target.accept(self)} in {node.iter.accept(self)}{ifs}\"\n        return f\"{'async ' if node.is_async else ''}{generated}\"\n\n    def visit_const(self, node):\n        \"\"\"return an astroid.Const node as string\"\"\"\n        if node.value is Ellipsis:\n            return \"...\"\n        return repr(node.value)\n\n    def visit_continue(self, node):\n        \"\"\"return an astroid.Continue node as string\"\"\"\n        return \"continue\"\n\n    def visit_delete(self, node):  # XXX check if correct\n        \"\"\"return an astroid.Delete node as string\"\"\"\n        return f\"del {', '.join(child.accept(self) for child in node.targets)}\"\n\n    def visit_delattr(self, node):\n        \"\"\"return an astroid.DelAttr node as string\"\"\"\n        return self.visit_attribute(node)\n\n    def visit_delname(self, node):\n        \"\"\"return an astroid.DelName node as string\"\"\"\n        return node.name\n\n    def visit_decorators(self, node):\n        \"\"\"return an astroid.Decorators node as string\"\"\"\n        return \"@%s\\n\" % \"\\n@\".join(item.accept(self) for item in node.nodes)\n\n    def visit_dict(self, node):\n        \"\"\"return an astroid.Dict node as string\"\"\"\n        return \"{%s}\" % \", \".join(self._visit_dict(node))\n\n    def _visit_dict(self, node):\n        for key, value in node.items:\n            key = key.accept(self)\n            value = value.accept(self)\n            if key == \"**\":\n                # It can only be a DictUnpack node.\n                yield key + value\n            else:\n                yield f\"{key}: {value}\"\n\n    def visit_dictunpack(self, node):\n        return \"**\"\n\n    def visit_dictcomp(self, node):\n        \"\"\"return an astroid.DictComp node as string\"\"\"\n        return \"{{{}: {} {}}}\".format(\n            node.key.accept(self),\n            node.value.accept(self),\n            \" \".join(n.accept(self) for n in node.generators),\n        )\n\n    def visit_expr(self, node):\n        \"\"\"return an astroid.Discard node as string\"\"\"\n        return node.value.accept(self)\n\n    def visit_emptynode(self, node):\n        \"\"\"dummy method for visiting an Empty node\"\"\"\n        return \"\"\n\n    def visit_excepthandler(self, node):\n        if node.type:\n            if node.name:\n                excs = f\"except {node.type.accept(self)} as {node.name.accept(self)}\"\n            else:\n                excs = f\"except {node.type.accept(self)}\"\n        else:\n            excs = \"except\"\n        return f\"{excs}:\\n{self._stmt_list(node.body)}\"\n\n    def visit_empty(self, node):\n        \"\"\"return an Empty node as string\"\"\"\n        return \"\"\n\n    def visit_for(self, node):\n        \"\"\"return an astroid.For node as string\"\"\"\n        fors = \"for {} in {}:\\n{}\".format(\n            node.target.accept(self), node.iter.accept(self), self._stmt_list(node.body)\n        )\n        if node.orelse:\n            fors = f\"{fors}\\nelse:\\n{self._stmt_list(node.orelse)}\"\n        return fors\n\n    def visit_importfrom(self, node):\n        \"\"\"return an astroid.ImportFrom node as string\"\"\"\n        return \"from {} import {}\".format(\n            \".\" * (node.level or 0) + node.modname, _import_string(node.names)\n        )\n\n    def visit_joinedstr(self, node):\n        string = \"\".join(\n            # Use repr on the string literal parts\n            # to get proper escapes, e.g. \\n, \\\\, \\\"\n            # But strip the quotes off the ends\n            # (they will always be one character: ' or \")\n            repr(value.value)[1:-1]\n            # Literal braces must be doubled to escape them\n            .replace(\"{\", \"{{\").replace(\"}\", \"}}\")\n            # Each value in values is either a string literal (Const)\n            # or a FormattedValue\n            if type(value).__name__ == \"Const\" else value.accept(self)\n            for value in node.values\n        )\n\n        # Try to find surrounding quotes that don't appear at all in the string.\n        # Because the formatted values inside {} can't contain backslash (\\)\n        # using a triple quote is sometimes necessary\n        for quote in (\"'\", '\"', '\"\"\"', \"'''\"):\n            if quote not in string:\n                break\n\n        return \"f\" + quote + string + quote\n\n    def visit_formattedvalue(self, node):\n        result = node.value.accept(self)\n        if node.conversion and node.conversion >= 0:\n            # e.g. if node.conversion == 114: result += \"!r\"\n            result += \"!\" + chr(node.conversion)\n        if node.format_spec:\n            # The format spec is itself a JoinedString, i.e. an f-string\n            # We strip the f and quotes of the ends\n            result += \":\" + node.format_spec.accept(self)[2:-1]\n        return \"{%s}\" % result\n\n    def handle_functiondef(self, node, keyword):\n        \"\"\"return a (possibly async) function definition node as string\"\"\"\n        decorate = node.decorators.accept(self) if node.decorators else \"\"\n        docs = self._docs_dedent(node.doc) if node.doc else \"\"\n        trailer = \":\"\n        if node.returns:\n            return_annotation = \" -> \" + node.returns.as_string()\n            trailer = return_annotation + \":\"\n        def_format = \"\\n%s%s %s(%s)%s%s\\n%s\"\n        return def_format % (\n            decorate,\n            keyword,\n            node.name,\n            node.args.accept(self),\n            trailer,\n            docs,\n            self._stmt_list(node.body),\n        )\n\n    def visit_functiondef(self, node):\n        \"\"\"return an astroid.FunctionDef node as string\"\"\"\n        return self.handle_functiondef(node, \"def\")\n\n    def visit_asyncfunctiondef(self, node):\n        \"\"\"return an astroid.AsyncFunction node as string\"\"\"\n        return self.handle_functiondef(node, \"async def\")\n\n    def visit_generatorexp(self, node):\n        \"\"\"return an astroid.GeneratorExp node as string\"\"\"\n        return \"({} {})\".format(\n            node.elt.accept(self), \" \".join(n.accept(self) for n in node.generators)\n        )\n\n    def visit_attribute(self, node):\n        \"\"\"return an astroid.Getattr node as string\"\"\"\n        left = self._precedence_parens(node, node.expr)\n        if left.isdigit():\n            left = f\"({left})\"\n        return f\"{left}.{node.attrname}\"\n\n    def visit_global(self, node):\n        \"\"\"return an astroid.Global node as string\"\"\"\n        return f\"global {', '.join(node.names)}\"\n\n    def visit_if(self, node):\n        \"\"\"return an astroid.If node as string\"\"\"\n        ifs = [f\"if {node.test.accept(self)}:\\n{self._stmt_list(node.body)}\"]\n        if node.has_elif_block():\n            ifs.append(f\"el{self._stmt_list(node.orelse, indent=False)}\")\n        elif node.orelse:\n            ifs.append(f\"else:\\n{self._stmt_list(node.orelse)}\")\n        return \"\\n\".join(ifs)\n\n    def visit_ifexp(self, node):\n        \"\"\"return an astroid.IfExp node as string\"\"\"\n        return \"{} if {} else {}\".format(\n            self._precedence_parens(node, node.body, is_left=True),\n            self._precedence_parens(node, node.test, is_left=True),\n            self._precedence_parens(node, node.orelse, is_left=False),\n        )\n\n    def visit_import(self, node):\n        \"\"\"return an astroid.Import node as string\"\"\"\n        return f\"import {_import_string(node.names)}\"\n\n    def visit_keyword(self, node):\n        \"\"\"return an astroid.Keyword node as string\"\"\"\n        if node.arg is None:\n            return f\"**{node.value.accept(self)}\"\n        return f\"{node.arg}={node.value.accept(self)}\"\n\n    def visit_lambda(self, node):\n        \"\"\"return an astroid.Lambda node as string\"\"\"\n        args = node.args.accept(self)\n        body = node.body.accept(self)\n        if args:\n            return f\"lambda {args}: {body}\"\n\n        return f\"lambda: {body}\"\n\n    def visit_list(self, node):\n        \"\"\"return an astroid.List node as string\"\"\"\n        return f\"[{', '.join(child.accept(self) for child in node.elts)}]\"\n\n    def visit_listcomp(self, node):\n        \"\"\"return an astroid.ListComp node as string\"\"\"\n        return \"[{} {}]\".format(\n            node.elt.accept(self), \" \".join(n.accept(self) for n in node.generators)\n        )\n\n    def visit_module(self, node):\n        \"\"\"return an astroid.Module node as string\"\"\"\n        docs = f'\"\"\"{node.doc}\"\"\"\\n\\n' if node.doc else \"\"\n        return docs + \"\\n\".join(n.accept(self) for n in node.body) + \"\\n\\n\"\n\n    def visit_name(self, node):\n        \"\"\"return an astroid.Name node as string\"\"\"\n        return node.name\n\n    def visit_namedexpr(self, node):\n        \"\"\"Return an assignment expression node as string\"\"\"\n        target = node.target.accept(self)\n        value = node.value.accept(self)\n        return f\"{target} := {value}\"\n\n    def visit_nonlocal(self, node):\n        \"\"\"return an astroid.Nonlocal node as string\"\"\"\n        return f\"nonlocal {', '.join(node.names)}\"\n\n    def visit_pass(self, node):\n        \"\"\"return an astroid.Pass node as string\"\"\"\n        return \"pass\"\n\n    def visit_raise(self, node):\n        \"\"\"return an astroid.Raise node as string\"\"\"\n        if node.exc:\n            if node.cause:\n                return f\"raise {node.exc.accept(self)} from {node.cause.accept(self)}\"\n            return f\"raise {node.exc.accept(self)}\"\n        return \"raise\"\n\n    def visit_return(self, node):\n        \"\"\"return an astroid.Return node as string\"\"\"\n        if node.is_tuple_return() and len(node.value.elts) > 1:\n            elts = [child.accept(self) for child in node.value.elts]\n            return f\"return {', '.join(elts)}\"\n\n        if node.value:\n            return f\"return {node.value.accept(self)}\"\n\n        return \"return\"\n\n    def visit_set(self, node):\n        \"\"\"return an astroid.Set node as string\"\"\"\n        return \"{%s}\" % \", \".join(child.accept(self) for child in node.elts)\n\n    def visit_setcomp(self, node):\n        \"\"\"return an astroid.SetComp node as string\"\"\"\n        return \"{{{} {}}}\".format(\n            node.elt.accept(self), \" \".join(n.accept(self) for n in node.generators)\n        )\n\n    def visit_slice(self, node):\n        \"\"\"return an astroid.Slice node as string\"\"\"\n        lower = node.lower.accept(self) if node.lower else \"\"\n        upper = node.upper.accept(self) if node.upper else \"\"\n        step = node.step.accept(self) if node.step else \"\"\n        if step:\n            return f\"{lower}:{upper}:{step}\"\n        return f\"{lower}:{upper}\"\n\n    def visit_subscript(self, node):\n        \"\"\"return an astroid.Subscript node as string\"\"\"\n        idx = node.slice\n        if idx.__class__.__name__.lower() == \"index\":\n            idx = idx.value\n        idxstr = idx.accept(self)\n        if idx.__class__.__name__.lower() == \"tuple\" and idx.elts:\n            # Remove parenthesis in tuple and extended slice.\n            # a[(::1, 1:)] is not valid syntax.\n            idxstr = idxstr[1:-1]\n        return f\"{self._precedence_parens(node, node.value)}[{idxstr}]\"\n\n    def visit_tryexcept(self, node):\n        \"\"\"return an astroid.TryExcept node as string\"\"\"\n        trys = [f\"try:\\n{self._stmt_list(node.body)}\"]\n        for handler in node.handlers:\n            trys.append(handler.accept(self))\n        if node.orelse:\n            trys.append(f\"else:\\n{self._stmt_list(node.orelse)}\")\n        return \"\\n\".join(trys)\n\n    def visit_tryfinally(self, node):\n        \"\"\"return an astroid.TryFinally node as string\"\"\"\n        return \"try:\\n{}\\nfinally:\\n{}\".format(\n            self._stmt_list(node.body), self._stmt_list(node.finalbody)\n        )\n\n    def visit_tuple(self, node):\n        \"\"\"return an astroid.Tuple node as string\"\"\"\n        if len(node.elts) == 1:\n            return f\"({node.elts[0].accept(self)}, )\"\n        return f\"({', '.join(child.accept(self) for child in node.elts)})\"\n\n    def visit_unaryop(self, node):\n        \"\"\"return an astroid.UnaryOp node as string\"\"\"\n        if node.op == \"not\":\n            operator = \"not \"\n        else:\n            operator = node.op\n        return f\"{operator}{self._precedence_parens(node, node.operand)}\"\n\n    def visit_while(self, node):\n        \"\"\"return an astroid.While node as string\"\"\"\n        whiles = f\"while {node.test.accept(self)}:\\n{self._stmt_list(node.body)}\"\n        if node.orelse:\n            whiles = f\"{whiles}\\nelse:\\n{self._stmt_list(node.orelse)}\"\n        return whiles\n\n    def visit_with(self, node):  # 'with' without 'as' is possible\n        \"\"\"return an astroid.With node as string\"\"\"\n        items = \", \".join(\n            f\"{expr.accept(self)}\" + (v and f\" as {v.accept(self)}\" or \"\")\n            for expr, v in node.items\n        )\n        return f\"with {items}:\\n{self._stmt_list(node.body)}\"\n\n    def visit_yield(self, node):\n        \"\"\"yield an ast.Yield node as string\"\"\"\n        yi_val = (\" \" + node.value.accept(self)) if node.value else \"\"\n        expr = \"yield\" + yi_val\n        if node.parent.is_statement:\n            return expr\n\n        return f\"({expr})\"\n\n    def visit_yieldfrom(self, node):\n        \"\"\"Return an astroid.YieldFrom node as string.\"\"\"\n        yi_val = (\" \" + node.value.accept(self)) if node.value else \"\"\n        expr = \"yield from\" + yi_val\n        if node.parent.is_statement:\n            return expr\n\n        return f\"({expr})\"\n\n    def visit_starred(self, node):\n        \"\"\"return Starred node as string\"\"\"\n        return \"*\" + node.value.accept(self)\n\n    def visit_match(self, node: \"Match\") -> str:\n        \"\"\"Return an astroid.Match node as string.\"\"\"\n        return f\"match {node.subject.accept(self)}:\\n{self._stmt_list(node.cases)}\"\n\n    def visit_matchcase(self, node: \"MatchCase\") -> str:\n        \"\"\"Return an astroid.MatchCase node as string.\"\"\"\n        guard_str = f\" if {node.guard.accept(self)}\" if node.guard else \"\"\n        return (\n            f\"case {node.pattern.accept(self)}{guard_str}:\\n\"\n            f\"{self._stmt_list(node.body)}\"\n        )\n\n    def visit_matchvalue(self, node: \"MatchValue\") -> str:\n        \"\"\"Return an astroid.MatchValue node as string.\"\"\"\n        return node.value.accept(self)\n\n    @staticmethod\n    def visit_matchsingleton(node: \"MatchSingleton\") -> str:\n        \"\"\"Return an astroid.MatchSingleton node as string.\"\"\"\n        return str(node.value)\n\n    def visit_matchsequence(self, node: \"MatchSequence\") -> str:\n        \"\"\"Return an astroid.MatchSequence node as string.\"\"\"\n        if node.patterns is None:\n            return \"[]\"\n        return f\"[{', '.join(p.accept(self) for p in node.patterns)}]\"\n\n    def visit_matchmapping(self, node: \"MatchMapping\") -> str:\n        \"\"\"Return an astroid.MatchMapping node as string.\"\"\"\n        mapping_strings: List[str] = []\n        if node.keys and node.patterns:\n            mapping_strings.extend(\n                f\"{key.accept(self)}: {p.accept(self)}\"\n                for key, p in zip(node.keys, node.patterns)\n            )\n        if node.rest:\n            mapping_strings.append(f\"**{node.rest.accept(self)}\")\n        return f\"{'{'}{', '.join(mapping_strings)}{'}'}\"\n\n    def visit_matchclass(self, node: \"MatchClass\") -> str:\n        \"\"\"Return an astroid.MatchClass node as string.\"\"\"\n        if node.cls is None:\n            raise Exception(f\"{node} does not have a 'cls' node\")\n        class_strings: List[str] = []\n        if node.patterns:\n            class_strings.extend(p.accept(self) for p in node.patterns)\n        if node.kwd_attrs and node.kwd_patterns:\n            for attr, pattern in zip(node.kwd_attrs, node.kwd_patterns):\n                class_strings.append(f\"{attr}={pattern.accept(self)}\")\n        return f\"{node.cls.accept(self)}({', '.join(class_strings)})\"\n\n    def visit_matchstar(self, node: \"MatchStar\") -> str:\n        \"\"\"Return an astroid.MatchStar node as string.\"\"\"\n        return f\"*{node.name.accept(self) if node.name else '_'}\"\n\n    def visit_matchas(self, node: \"MatchAs\") -> str:\n        \"\"\"Return an astroid.MatchAs node as string.\"\"\"\n        # pylint: disable=import-outside-toplevel\n        # Prevent circular dependency\n        from astroid.nodes.node_classes import MatchClass, MatchMapping, MatchSequence\n\n        if isinstance(node.parent, (MatchSequence, MatchMapping, MatchClass)):\n            return node.name.accept(self) if node.name else \"_\"\n        return (\n            f\"{node.pattern.accept(self) if node.pattern else '_'}\"\n            f\"{f' as {node.name.accept(self)}' if node.name else ''}\"\n        )\n\n    def visit_matchor(self, node: \"MatchOr\") -> str:\n        \"\"\"Return an astroid.MatchOr node as string.\"\"\"\n        if node.patterns is None:\n            raise Exception(f\"{node} does not have pattern nodes\")\n        return \" | \".join(p.accept(self) for p in node.patterns)\n\n    # These aren't for real AST nodes, but for inference objects.\n\n    def visit_frozenset(self, node):\n        return node.parent.accept(self)\n\n    def visit_super(self, node):\n        return node.parent.accept(self)\n\n    def visit_uninferable(self, node):\n        return str(node)\n\n    def visit_property(self, node):\n        return node.function.accept(self)\n\n    def visit_evaluatedobject(self, node):\n        return node.original.accept(self)\n\n\ndef _import_string(names):\n    \"\"\"return a list of (name, asname) formatted as a string\"\"\"\n    _names = []\n    for name, asname in names:\n        if asname is not None:\n            _names.append(f\"{name} as {asname}\")\n        else:\n            _names.append(name)\n    return \", \".join(_names)\n\n\n# This sets the default indent to 4 spaces.\nto_code = AsStringVisitor(\"    \")\n","new_file_content":"# Copyright (c) 2009-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>\n# Copyright (c) 2010 Daniel Harding <dharding@gmail.com>\n# Copyright (c) 2013-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>\n# Copyright (c) 2013-2014 Google, Inc.\n# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>\n# Copyright (c) 2016 Jared Garst <jgarst@users.noreply.github.com>\n# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>\n# Copyright (c) 2017, 2019 Łukasz Rogalski <rogalski.91@gmail.com>\n# Copyright (c) 2017 rr- <rr-@sakuya.pl>\n# Copyright (c) 2018 Serhiy Storchaka <storchaka@gmail.com>\n# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>\n# Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com>\n# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>\n# Copyright (c) 2019 Alex Hall <alex.mojaki@gmail.com>\n# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>\n# Copyright (c) 2021 Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>\n# Copyright (c) 2021 Pierre Sassoulas <pierre.sassoulas@gmail.com>\n# Copyright (c) 2021 Marc Mueller <30130371+cdce8p@users.noreply.github.com>\n# Copyright (c) 2021 pre-commit-ci[bot] <bot@noreply.github.com>\n\n# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html\n# For details: https://github.com/PyCQA/astroid/blob/main/LICENSE\n\n\"\"\"This module renders Astroid nodes as string\"\"\"\nfrom typing import TYPE_CHECKING, List\n\nif TYPE_CHECKING:\n    from astroid.nodes.node_classes import (\n        Match,\n        MatchAs,\n        MatchCase,\n        MatchClass,\n        MatchMapping,\n        MatchOr,\n        MatchSequence,\n        MatchSingleton,\n        MatchStar,\n        MatchValue,\n        Unknown,\n    )\n\n# pylint: disable=unused-argument\n\nDOC_NEWLINE = \"\\0\"\n\n\n# Visitor pattern require argument all the time and is not better with staticmethod\n# noinspection PyUnusedLocal,PyMethodMayBeStatic\nclass AsStringVisitor:\n    \"\"\"Visitor to render an Astroid node as a valid python code string\"\"\"\n\n    def __init__(self, indent=\"    \"):\n        self.indent = indent\n\n    def __call__(self, node):\n        \"\"\"Makes this visitor behave as a simple function\"\"\"\n        return node.accept(self).replace(DOC_NEWLINE, \"\\n\")\n\n    def _docs_dedent(self, doc):\n        \"\"\"Stop newlines in docs being indented by self._stmt_list\"\"\"\n        return '\\n{}\"\"\"{}\"\"\"'.format(self.indent, doc.replace(\"\\n\", DOC_NEWLINE))\n\n    def _stmt_list(self, stmts, indent=True):\n        \"\"\"return a list of nodes to string\"\"\"\n        stmts = \"\\n\".join(nstr for nstr in [n.accept(self) for n in stmts] if nstr)\n        if indent:\n            return self.indent + stmts.replace(\"\\n\", \"\\n\" + self.indent)\n\n        return stmts\n\n    def _precedence_parens(self, node, child, is_left=True):\n        \"\"\"Wrap child in parens only if required to keep same semantics\"\"\"\n        if self._should_wrap(node, child, is_left):\n            return f\"({child.accept(self)})\"\n\n        return child.accept(self)\n\n    def _should_wrap(self, node, child, is_left):\n        \"\"\"Wrap child if:\n        - it has lower precedence\n        - same precedence with position opposite to associativity direction\n        \"\"\"\n        node_precedence = node.op_precedence()\n        child_precedence = child.op_precedence()\n\n        if node_precedence > child_precedence:\n            # 3 * (4 + 5)\n            return True\n\n        if (\n            node_precedence == child_precedence\n            and is_left != node.op_left_associative()\n        ):\n            # 3 - (4 - 5)\n            # (2**3)**4\n            return True\n\n        return False\n\n    # visit_<node> methods ###########################################\n\n    def visit_await(self, node):\n        return f\"await {node.value.accept(self)}\"\n\n    def visit_asyncwith(self, node):\n        return f\"async {self.visit_with(node)}\"\n\n    def visit_asyncfor(self, node):\n        return f\"async {self.visit_for(node)}\"\n\n    def visit_arguments(self, node):\n        \"\"\"return an astroid.Function node as string\"\"\"\n        return node.format_args()\n\n    def visit_assignattr(self, node):\n        \"\"\"return an astroid.AssAttr node as string\"\"\"\n        return self.visit_attribute(node)\n\n    def visit_assert(self, node):\n        \"\"\"return an astroid.Assert node as string\"\"\"\n        if node.fail:\n            return f\"assert {node.test.accept(self)}, {node.fail.accept(self)}\"\n        return f\"assert {node.test.accept(self)}\"\n\n    def visit_assignname(self, node):\n        \"\"\"return an astroid.AssName node as string\"\"\"\n        return node.name\n\n    def visit_assign(self, node):\n        \"\"\"return an astroid.Assign node as string\"\"\"\n        lhs = \" = \".join(n.accept(self) for n in node.targets)\n        return f\"{lhs} = {node.value.accept(self)}\"\n\n    def visit_augassign(self, node):\n        \"\"\"return an astroid.AugAssign node as string\"\"\"\n        return f\"{node.target.accept(self)} {node.op} {node.value.accept(self)}\"\n\n    def visit_annassign(self, node):\n        \"\"\"Return an astroid.AugAssign node as string\"\"\"\n\n        target = node.target.accept(self)\n        annotation = node.annotation.accept(self)\n        if node.value is None:\n            return f\"{target}: {annotation}\"\n        return f\"{target}: {annotation} = {node.value.accept(self)}\"\n\n    def visit_binop(self, node):\n        \"\"\"return an astroid.BinOp node as string\"\"\"\n        left = self._precedence_parens(node, node.left)\n        right = self._precedence_parens(node, node.right, is_left=False)\n        if node.op == \"**\":\n            return f\"{left}{node.op}{right}\"\n\n        return f\"{left} {node.op} {right}\"\n\n    def visit_boolop(self, node):\n        \"\"\"return an astroid.BoolOp node as string\"\"\"\n        values = [f\"{self._precedence_parens(node, n)}\" for n in node.values]\n        return (f\" {node.op} \").join(values)\n\n    def visit_break(self, node):\n        \"\"\"return an astroid.Break node as string\"\"\"\n        return \"break\"\n\n    def visit_call(self, node):\n        \"\"\"return an astroid.Call node as string\"\"\"\n        expr_str = self._precedence_parens(node, node.func)\n        args = [arg.accept(self) for arg in node.args]\n        if node.keywords:\n            keywords = [kwarg.accept(self) for kwarg in node.keywords]\n        else:\n            keywords = []\n\n        args.extend(keywords)\n        return f\"{expr_str}({', '.join(args)})\"\n\n    def visit_classdef(self, node):\n        \"\"\"return an astroid.ClassDef node as string\"\"\"\n        decorate = node.decorators.accept(self) if node.decorators else \"\"\n        args = [n.accept(self) for n in node.bases]\n        if node._metaclass and not node.has_metaclass_hack():\n            args.append(\"metaclass=\" + node._metaclass.accept(self))\n        args += [n.accept(self) for n in node.keywords]\n        args = f\"({', '.join(args)})\" if args else \"\"\n        docs = self._docs_dedent(node.doc) if node.doc else \"\"\n        return \"\\n\\n{}class {}{}:{}\\n{}\\n\".format(\n            decorate, node.name, args, docs, self._stmt_list(node.body)\n        )\n\n    def visit_compare(self, node):\n        \"\"\"return an astroid.Compare node as string\"\"\"\n        rhs_str = \" \".join(\n            f\"{op} {self._precedence_parens(node, expr, is_left=False)}\"\n            for op, expr in node.ops\n        )\n        return f\"{self._precedence_parens(node, node.left)} {rhs_str}\"\n\n    def visit_comprehension(self, node):\n        \"\"\"return an astroid.Comprehension node as string\"\"\"\n        ifs = \"\".join(f\" if {n.accept(self)}\" for n in node.ifs)\n        generated = f\"for {node.target.accept(self)} in {node.iter.accept(self)}{ifs}\"\n        return f\"{'async ' if node.is_async else ''}{generated}\"\n\n    def visit_const(self, node):\n        \"\"\"return an astroid.Const node as string\"\"\"\n        if node.value is Ellipsis:\n            return \"...\"\n        return repr(node.value)\n\n    def visit_continue(self, node):\n        \"\"\"return an astroid.Continue node as string\"\"\"\n        return \"continue\"\n\n    def visit_delete(self, node):  # XXX check if correct\n        \"\"\"return an astroid.Delete node as string\"\"\"\n        return f\"del {', '.join(child.accept(self) for child in node.targets)}\"\n\n    def visit_delattr(self, node):\n        \"\"\"return an astroid.DelAttr node as string\"\"\"\n        return self.visit_attribute(node)\n\n    def visit_delname(self, node):\n        \"\"\"return an astroid.DelName node as string\"\"\"\n        return node.name\n\n    def visit_decorators(self, node):\n        \"\"\"return an astroid.Decorators node as string\"\"\"\n        return \"@%s\\n\" % \"\\n@\".join(item.accept(self) for item in node.nodes)\n\n    def visit_dict(self, node):\n        \"\"\"return an astroid.Dict node as string\"\"\"\n        return \"{%s}\" % \", \".join(self._visit_dict(node))\n\n    def _visit_dict(self, node):\n        for key, value in node.items:\n            key = key.accept(self)\n            value = value.accept(self)\n            if key == \"**\":\n                # It can only be a DictUnpack node.\n                yield key + value\n            else:\n                yield f\"{key}: {value}\"\n\n    def visit_dictunpack(self, node):\n        return \"**\"\n\n    def visit_dictcomp(self, node):\n        \"\"\"return an astroid.DictComp node as string\"\"\"\n        return \"{{{}: {} {}}}\".format(\n            node.key.accept(self),\n            node.value.accept(self),\n            \" \".join(n.accept(self) for n in node.generators),\n        )\n\n    def visit_expr(self, node):\n        \"\"\"return an astroid.Discard node as string\"\"\"\n        return node.value.accept(self)\n\n    def visit_emptynode(self, node):\n        \"\"\"dummy method for visiting an Empty node\"\"\"\n        return \"\"\n\n    def visit_excepthandler(self, node):\n        if node.type:\n            if node.name:\n                excs = f\"except {node.type.accept(self)} as {node.name.accept(self)}\"\n            else:\n                excs = f\"except {node.type.accept(self)}\"\n        else:\n            excs = \"except\"\n        return f\"{excs}:\\n{self._stmt_list(node.body)}\"\n\n    def visit_empty(self, node):\n        \"\"\"return an Empty node as string\"\"\"\n        return \"\"\n\n    def visit_for(self, node):\n        \"\"\"return an astroid.For node as string\"\"\"\n        fors = \"for {} in {}:\\n{}\".format(\n            node.target.accept(self), node.iter.accept(self), self._stmt_list(node.body)\n        )\n        if node.orelse:\n            fors = f\"{fors}\\nelse:\\n{self._stmt_list(node.orelse)}\"\n        return fors\n\n    def visit_importfrom(self, node):\n        \"\"\"return an astroid.ImportFrom node as string\"\"\"\n        return \"from {} import {}\".format(\n            \".\" * (node.level or 0) + node.modname, _import_string(node.names)\n        )\n\n    def visit_joinedstr(self, node):\n        string = \"\".join(\n            # Use repr on the string literal parts\n            # to get proper escapes, e.g. \\n, \\\\, \\\"\n            # But strip the quotes off the ends\n            # (they will always be one character: ' or \")\n            repr(value.value)[1:-1]\n            # Literal braces must be doubled to escape them\n            .replace(\"{\", \"{{\").replace(\"}\", \"}}\")\n            # Each value in values is either a string literal (Const)\n            # or a FormattedValue\n            if type(value).__name__ == \"Const\" else value.accept(self)\n            for value in node.values\n        )\n\n        # Try to find surrounding quotes that don't appear at all in the string.\n        # Because the formatted values inside {} can't contain backslash (\\)\n        # using a triple quote is sometimes necessary\n        for quote in (\"'\", '\"', '\"\"\"', \"'''\"):\n            if quote not in string:\n                break\n\n        return \"f\" + quote + string + quote\n\n    def visit_formattedvalue(self, node):\n        result = node.value.accept(self)\n        if node.conversion and node.conversion >= 0:\n            # e.g. if node.conversion == 114: result += \"!r\"\n            result += \"!\" + chr(node.conversion)\n        if node.format_spec:\n            # The format spec is itself a JoinedString, i.e. an f-string\n            # We strip the f and quotes of the ends\n            result += \":\" + node.format_spec.accept(self)[2:-1]\n        return \"{%s}\" % result\n\n    def handle_functiondef(self, node, keyword):\n        \"\"\"return a (possibly async) function definition node as string\"\"\"\n        decorate = node.decorators.accept(self) if node.decorators else \"\"\n        docs = self._docs_dedent(node.doc) if node.doc else \"\"\n        trailer = \":\"\n        if node.returns:\n            return_annotation = \" -> \" + node.returns.as_string()\n            trailer = return_annotation + \":\"\n        def_format = \"\\n%s%s %s(%s)%s%s\\n%s\"\n        return def_format % (\n            decorate,\n            keyword,\n            node.name,\n            node.args.accept(self),\n            trailer,\n            docs,\n            self._stmt_list(node.body),\n        )\n\n    def visit_functiondef(self, node):\n        \"\"\"return an astroid.FunctionDef node as string\"\"\"\n        return self.handle_functiondef(node, \"def\")\n\n    def visit_asyncfunctiondef(self, node):\n        \"\"\"return an astroid.AsyncFunction node as string\"\"\"\n        return self.handle_functiondef(node, \"async def\")\n\n    def visit_generatorexp(self, node):\n        \"\"\"return an astroid.GeneratorExp node as string\"\"\"\n        return \"({} {})\".format(\n            node.elt.accept(self), \" \".join(n.accept(self) for n in node.generators)\n        )\n\n    def visit_attribute(self, node):\n        \"\"\"return an astroid.Getattr node as string\"\"\"\n        left = self._precedence_parens(node, node.expr)\n        if left.isdigit():\n            left = f\"({left})\"\n        return f\"{left}.{node.attrname}\"\n\n    def visit_global(self, node):\n        \"\"\"return an astroid.Global node as string\"\"\"\n        return f\"global {', '.join(node.names)}\"\n\n    def visit_if(self, node):\n        \"\"\"return an astroid.If node as string\"\"\"\n        ifs = [f\"if {node.test.accept(self)}:\\n{self._stmt_list(node.body)}\"]\n        if node.has_elif_block():\n            ifs.append(f\"el{self._stmt_list(node.orelse, indent=False)}\")\n        elif node.orelse:\n            ifs.append(f\"else:\\n{self._stmt_list(node.orelse)}\")\n        return \"\\n\".join(ifs)\n\n    def visit_ifexp(self, node):\n        \"\"\"return an astroid.IfExp node as string\"\"\"\n        return \"{} if {} else {}\".format(\n            self._precedence_parens(node, node.body, is_left=True),\n            self._precedence_parens(node, node.test, is_left=True),\n            self._precedence_parens(node, node.orelse, is_left=False),\n        )\n\n    def visit_import(self, node):\n        \"\"\"return an astroid.Import node as string\"\"\"\n        return f\"import {_import_string(node.names)}\"\n\n    def visit_keyword(self, node):\n        \"\"\"return an astroid.Keyword node as string\"\"\"\n        if node.arg is None:\n            return f\"**{node.value.accept(self)}\"\n        return f\"{node.arg}={node.value.accept(self)}\"\n\n    def visit_lambda(self, node):\n        \"\"\"return an astroid.Lambda node as string\"\"\"\n        args = node.args.accept(self)\n        body = node.body.accept(self)\n        if args:\n            return f\"lambda {args}: {body}\"\n\n        return f\"lambda: {body}\"\n\n    def visit_list(self, node):\n        \"\"\"return an astroid.List node as string\"\"\"\n        return f\"[{', '.join(child.accept(self) for child in node.elts)}]\"\n\n    def visit_listcomp(self, node):\n        \"\"\"return an astroid.ListComp node as string\"\"\"\n        return \"[{} {}]\".format(\n            node.elt.accept(self), \" \".join(n.accept(self) for n in node.generators)\n        )\n\n    def visit_module(self, node):\n        \"\"\"return an astroid.Module node as string\"\"\"\n        docs = f'\"\"\"{node.doc}\"\"\"\\n\\n' if node.doc else \"\"\n        return docs + \"\\n\".join(n.accept(self) for n in node.body) + \"\\n\\n\"\n\n    def visit_name(self, node):\n        \"\"\"return an astroid.Name node as string\"\"\"\n        return node.name\n\n    def visit_namedexpr(self, node):\n        \"\"\"Return an assignment expression node as string\"\"\"\n        target = node.target.accept(self)\n        value = node.value.accept(self)\n        return f\"{target} := {value}\"\n\n    def visit_nonlocal(self, node):\n        \"\"\"return an astroid.Nonlocal node as string\"\"\"\n        return f\"nonlocal {', '.join(node.names)}\"\n\n    def visit_pass(self, node):\n        \"\"\"return an astroid.Pass node as string\"\"\"\n        return \"pass\"\n\n    def visit_raise(self, node):\n        \"\"\"return an astroid.Raise node as string\"\"\"\n        if node.exc:\n            if node.cause:\n                return f\"raise {node.exc.accept(self)} from {node.cause.accept(self)}\"\n            return f\"raise {node.exc.accept(self)}\"\n        return \"raise\"\n\n    def visit_return(self, node):\n        \"\"\"return an astroid.Return node as string\"\"\"\n        if node.is_tuple_return() and len(node.value.elts) > 1:\n            elts = [child.accept(self) for child in node.value.elts]\n            return f\"return {', '.join(elts)}\"\n\n        if node.value:\n            return f\"return {node.value.accept(self)}\"\n\n        return \"return\"\n\n    def visit_set(self, node):\n        \"\"\"return an astroid.Set node as string\"\"\"\n        return \"{%s}\" % \", \".join(child.accept(self) for child in node.elts)\n\n    def visit_setcomp(self, node):\n        \"\"\"return an astroid.SetComp node as string\"\"\"\n        return \"{{{} {}}}\".format(\n            node.elt.accept(self), \" \".join(n.accept(self) for n in node.generators)\n        )\n\n    def visit_slice(self, node):\n        \"\"\"return an astroid.Slice node as string\"\"\"\n        lower = node.lower.accept(self) if node.lower else \"\"\n        upper = node.upper.accept(self) if node.upper else \"\"\n        step = node.step.accept(self) if node.step else \"\"\n        if step:\n            return f\"{lower}:{upper}:{step}\"\n        return f\"{lower}:{upper}\"\n\n    def visit_subscript(self, node):\n        \"\"\"return an astroid.Subscript node as string\"\"\"\n        idx = node.slice\n        if idx.__class__.__name__.lower() == \"index\":\n            idx = idx.value\n        idxstr = idx.accept(self)\n        if idx.__class__.__name__.lower() == \"tuple\" and idx.elts:\n            # Remove parenthesis in tuple and extended slice.\n            # a[(::1, 1:)] is not valid syntax.\n            idxstr = idxstr[1:-1]\n        return f\"{self._precedence_parens(node, node.value)}[{idxstr}]\"\n\n    def visit_tryexcept(self, node):\n        \"\"\"return an astroid.TryExcept node as string\"\"\"\n        trys = [f\"try:\\n{self._stmt_list(node.body)}\"]\n        for handler in node.handlers:\n            trys.append(handler.accept(self))\n        if node.orelse:\n            trys.append(f\"else:\\n{self._stmt_list(node.orelse)}\")\n        return \"\\n\".join(trys)\n\n    def visit_tryfinally(self, node):\n        \"\"\"return an astroid.TryFinally node as string\"\"\"\n        return \"try:\\n{}\\nfinally:\\n{}\".format(\n            self._stmt_list(node.body), self._stmt_list(node.finalbody)\n        )\n\n    def visit_tuple(self, node):\n        \"\"\"return an astroid.Tuple node as string\"\"\"\n        if len(node.elts) == 1:\n            return f\"({node.elts[0].accept(self)}, )\"\n        return f\"({', '.join(child.accept(self) for child in node.elts)})\"\n\n    def visit_unaryop(self, node):\n        \"\"\"return an astroid.UnaryOp node as string\"\"\"\n        if node.op == \"not\":\n            operator = \"not \"\n        else:\n            operator = node.op\n        return f\"{operator}{self._precedence_parens(node, node.operand)}\"\n\n    def visit_while(self, node):\n        \"\"\"return an astroid.While node as string\"\"\"\n        whiles = f\"while {node.test.accept(self)}:\\n{self._stmt_list(node.body)}\"\n        if node.orelse:\n            whiles = f\"{whiles}\\nelse:\\n{self._stmt_list(node.orelse)}\"\n        return whiles\n\n    def visit_with(self, node):  # 'with' without 'as' is possible\n        \"\"\"return an astroid.With node as string\"\"\"\n        items = \", \".join(\n            f\"{expr.accept(self)}\" + (v and f\" as {v.accept(self)}\" or \"\")\n            for expr, v in node.items\n        )\n        return f\"with {items}:\\n{self._stmt_list(node.body)}\"\n\n    def visit_yield(self, node):\n        \"\"\"yield an ast.Yield node as string\"\"\"\n        yi_val = (\" \" + node.value.accept(self)) if node.value else \"\"\n        expr = \"yield\" + yi_val\n        if node.parent.is_statement:\n            return expr\n\n        return f\"({expr})\"\n\n    def visit_yieldfrom(self, node):\n        \"\"\"Return an astroid.YieldFrom node as string.\"\"\"\n        yi_val = (\" \" + node.value.accept(self)) if node.value else \"\"\n        expr = \"yield from\" + yi_val\n        if node.parent.is_statement:\n            return expr\n\n        return f\"({expr})\"\n\n    def visit_starred(self, node):\n        \"\"\"return Starred node as string\"\"\"\n        return \"*\" + node.value.accept(self)\n\n    def visit_match(self, node: \"Match\") -> str:\n        \"\"\"Return an astroid.Match node as string.\"\"\"\n        return f\"match {node.subject.accept(self)}:\\n{self._stmt_list(node.cases)}\"\n\n    def visit_matchcase(self, node: \"MatchCase\") -> str:\n        \"\"\"Return an astroid.MatchCase node as string.\"\"\"\n        guard_str = f\" if {node.guard.accept(self)}\" if node.guard else \"\"\n        return (\n            f\"case {node.pattern.accept(self)}{guard_str}:\\n\"\n            f\"{self._stmt_list(node.body)}\"\n        )\n\n    def visit_matchvalue(self, node: \"MatchValue\") -> str:\n        \"\"\"Return an astroid.MatchValue node as string.\"\"\"\n        return node.value.accept(self)\n\n    @staticmethod\n    def visit_matchsingleton(node: \"MatchSingleton\") -> str:\n        \"\"\"Return an astroid.MatchSingleton node as string.\"\"\"\n        return str(node.value)\n\n    def visit_matchsequence(self, node: \"MatchSequence\") -> str:\n        \"\"\"Return an astroid.MatchSequence node as string.\"\"\"\n        if node.patterns is None:\n            return \"[]\"\n        return f\"[{', '.join(p.accept(self) for p in node.patterns)}]\"\n\n    def visit_matchmapping(self, node: \"MatchMapping\") -> str:\n        \"\"\"Return an astroid.MatchMapping node as string.\"\"\"\n        mapping_strings: List[str] = []\n        if node.keys and node.patterns:\n            mapping_strings.extend(\n                f\"{key.accept(self)}: {p.accept(self)}\"\n                for key, p in zip(node.keys, node.patterns)\n            )\n        if node.rest:\n            mapping_strings.append(f\"**{node.rest.accept(self)}\")\n        return f\"{'{'}{', '.join(mapping_strings)}{'}'}\"\n\n    def visit_matchclass(self, node: \"MatchClass\") -> str:\n        \"\"\"Return an astroid.MatchClass node as string.\"\"\"\n        if node.cls is None:\n            raise Exception(f\"{node} does not have a 'cls' node\")\n        class_strings: List[str] = []\n        if node.patterns:\n            class_strings.extend(p.accept(self) for p in node.patterns)\n        if node.kwd_attrs and node.kwd_patterns:\n            for attr, pattern in zip(node.kwd_attrs, node.kwd_patterns):\n                class_strings.append(f\"{attr}={pattern.accept(self)}\")\n        return f\"{node.cls.accept(self)}({', '.join(class_strings)})\"\n\n    def visit_matchstar(self, node: \"MatchStar\") -> str:\n        \"\"\"Return an astroid.MatchStar node as string.\"\"\"\n        return f\"*{node.name.accept(self) if node.name else '_'}\"\n\n    def visit_matchas(self, node: \"MatchAs\") -> str:\n        \"\"\"Return an astroid.MatchAs node as string.\"\"\"\n        # pylint: disable=import-outside-toplevel\n        # Prevent circular dependency\n        from astroid.nodes.node_classes import MatchClass, MatchMapping, MatchSequence\n\n        if isinstance(node.parent, (MatchSequence, MatchMapping, MatchClass)):\n            return node.name.accept(self) if node.name else \"_\"\n        return (\n            f\"{node.pattern.accept(self) if node.pattern else '_'}\"\n            f\"{f' as {node.name.accept(self)}' if node.name else ''}\"\n        )\n\n    def visit_matchor(self, node: \"MatchOr\") -> str:\n        \"\"\"Return an astroid.MatchOr node as string.\"\"\"\n        if node.patterns is None:\n            raise Exception(f\"{node} does not have pattern nodes\")\n        return \" | \".join(p.accept(self) for p in node.patterns)\n\n    # These aren't for real AST nodes, but for inference objects.\n\n    def visit_frozenset(self, node):\n        return node.parent.accept(self)\n\n    def visit_super(self, node):\n        return node.parent.accept(self)\n\n    def visit_uninferable(self, node):\n        return str(node)\n\n    def visit_property(self, node):\n        return node.function.accept(self)\n\n    def visit_evaluatedobject(self, node):\n        return node.original.accept(self)\n\n    def visit_unknown(self, node: \"Unknown\") -> str:\n        return str(node)\n\n\ndef _import_string(names):\n    \"\"\"return a list of (name, asname) formatted as a string\"\"\"\n    _names = []\n    for name, asname in names:\n        if asname is not None:\n            _names.append(f\"{name} as {asname}\")\n        else:\n            _names.append(name)\n    return \", \".join(_names)\n\n\n# This sets the default indent to 4 spaces.\nto_code = AsStringVisitor(\"    \")\n","header":{"file":{"path":"astroid/nodes/as_string.py"},"misc_line":null},"index_line":null,"is_binary_file":false,"binary_line":null,"minus_file":{"path":"a/astroid/nodes/as_string.py"},"plus_file":{"path":"b/astroid/nodes/as_string.py"},"hunks":[{"descriptor":{"old_range":{"start":36,"length":6},"new_range":{"start":36,"length":7},"section":""},"line_group":{"all_lines":[{"content":"        MatchSingleton,","type":"context"},{"content":"        MatchStar,","type":"context"},{"content":"        MatchValue,","type":"context"},{"content":"        Unknown,","type":"added"},{"content":"    )","type":"context"},{"content":"","type":"context"},{"content":"# pylint: disable=unused-argument","type":"context"}]},"modified_entities":[],"added_entities":[],"deleted_entities":[]},{"descriptor":{"old_range":{"start":643,"length":6},"new_range":{"start":644,"length":9},"section":"def visit_property(self, node):"},"line_group":{"all_lines":[{"content":"    def visit_evaluatedobject(self, node):","type":"context"},{"content":"        return node.original.accept(self)","type":"context"},{"content":"","type":"context"},{"content":"    def visit_unknown(self, node: \"Unknown\") -> str:","type":"added"},{"content":"        return str(node)","type":"added"},{"content":"","type":"added"},{"content":"","type":"context"},{"content":"def _import_string(names):","type":"context"},{"content":"    \"\"\"return a list of (name, asname) formatted as a string\"\"\"","type":"context"},{"content":"","type":"context"}]},"modified_entities":[],"added_entities":[],"deleted_entities":[]}]}],"old_commit_hash":"ce5cbce5ba11cdc2f8139ade66feea1e181a7944","new_commit_hash":"9b6ebb18f75f49da85fd3543b71ed532911b1ede","commit_message":"Update ChangeLog","commit_date":"2021-11-21T17:53:21+01:00","metadata":{}}