bpo-40726: handle uninitalized end_lineno on ast.increment_lineno (GH-20312)

(cherry picked from commit 8f4380d2f5839a321475104765221a7394a9d649)

Co-authored-by: Batuhan Taskaya <batuhanosmantaskaya@gmail.com>
diff --git a/Lib/ast.py b/Lib/ast.py
index 6a5b39e..65ebd01 100644
--- a/Lib/ast.py
+++ b/Lib/ast.py
@@ -180,7 +180,11 @@
     for attr in 'lineno', 'col_offset', 'end_lineno', 'end_col_offset':
         if attr in old_node._attributes and attr in new_node._attributes:
             value = getattr(old_node, attr, None)
-            if value is not None:
+            # end_lineno and end_col_offset are optional attributes, and they
+            # should be copied whether the value is None or not.
+            if value is not None or (
+                hasattr(old_node, attr) and attr.startswith("end_")
+            ):
                 setattr(new_node, attr, value)
     return new_node
 
@@ -229,8 +233,11 @@
     for child in walk(node):
         if 'lineno' in child._attributes:
             child.lineno = getattr(child, 'lineno', 0) + n
-        if 'end_lineno' in child._attributes:
-            child.end_lineno = getattr(child, 'end_lineno', 0) + n
+        if (
+            "end_lineno" in child._attributes
+            and (end_lineno := getattr(child, "end_lineno", 0)) is not None
+        ):
+            child.end_lineno = end_lineno + n
     return node