Repository: pylint-dev/astroid

Issue:
Add kind field to Const
Python 3.8 added the optional `kind` field to `ast.Constant`. This is used to store the string prefix, like `u` for `u"foo"`. `astroid.Const` should include this field too.


Discussion / hints:
@federicobond thanks for this suggestion!



Fix (patch):
diff --git a/ChangeLog b/ChangeLog
index 63e9816d51..4343be3fee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,6 +23,11 @@ Release Date: TBA
 
   Closes #926
 
+* Add ``kind`` field to ``Const`` nodes, matching the structure of the built-in ast Const.
+  The kind field is "u" if the literal is a u-prefixed string, and ``None`` otherwise.
+
+  Closes #898
+
 
 What's New in astroid 2.5.6?
 ============================
diff --git a/astroid/node_classes.py b/astroid/node_classes.py
index 7faf681275..f8d0b23c52 100644
--- a/astroid/node_classes.py
+++ b/astroid/node_classes.py
@@ -2557,7 +2557,7 @@ class Const(mixins.NoChildrenMixin, NodeNG, bases.Instance):
 
     _other_fields = ("value",)
 
-    def __init__(self, value, lineno=None, col_offset=None, parent=None):
+    def __init__(self, value, lineno=None, col_offset=None, parent=None, kind=None):
         """
         :param value: The value that the constant represents.
         :type value: object
@@ -2571,12 +2571,12 @@ def __init__(self, value, lineno=None, col_offset=None, parent=None):
 
         :param parent: The parent node in the syntax tree.
         :type parent: NodeNG or None
-        """
-        self.value = value
-        """The value that the constant represents.
 
-        :type: object
+        :param kind: The string prefix. "u" for u-prefixed strings and ``None`` otherwise. Python 3.8+ only.
+        :type kind: str or None
         """
+        self.value = value
+        self.kind = kind
 
         super().__init__(lineno, col_offset, parent)
 
diff --git a/astroid/rebuilder.py b/astroid/rebuilder.py
index bb6a23b852..2532b61d1f 100644
--- a/astroid/rebuilder.py
+++ b/astroid/rebuilder.py
@@ -425,6 +425,7 @@ def visit_const(self, node, parent):
             getattr(node, "lineno", None),
             getattr(node, "col_offset", None),
             parent,
+            getattr(node, "kind", None),
         )
 
     def visit_continue(self, node, parent):
@@ -814,6 +815,7 @@ def visit_constant(self, node, parent):
             getattr(node, "lineno", None),
             getattr(node, "col_offset", None),
             parent,
+            getattr(node, "kind", None),
         )
 
     # Not used in Python 3.8+.


Test changes:
diff --git a/tests/unittest_nodes.py b/tests/unittest_nodes.py
index 4ce73be9b8..14f713a51b 100644
--- a/tests/unittest_nodes.py
+++ b/tests/unittest_nodes.py
@@ -542,6 +542,19 @@ def test_str(self):
     def test_unicode(self):
         self._test("a")
 
+    @pytest.mark.skipif(
+        not PY38, reason="kind attribute for ast.Constant was added in 3.8"
+    )
+    def test_str_kind(self):
+        node = builder.extract_node(
+            """
+            const = u"foo"
+        """
+        )
+        assert isinstance(node.value, nodes.Const)
+        assert node.value.value == "foo"
+        assert node.value.kind, "u"
+
     def test_copy(self):
         """
         Make sure copying a Const object doesn't result in infinite recursion