commit 4c3a0249efdb14acf63eb3a8e37034354fa3fe7e
Author: kobarity <kobarity@gmail.com>
Date:   Mon Jun 20 20:53:09 2022 +0900

    Fix nested defuns handling in `python-nav-beginning-of-defun'
    
    * lisp/progmodes/python.el (python-nav--beginning-of-defun): Fix
    handling of nested defuns (bug#56105).

diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index c2483436fe..e0c937d7ce 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1455,11 +1455,17 @@ python-nav--beginning-of-defun
          (line-beg-pos (line-beginning-position))
          (line-content-start (+ line-beg-pos (current-indentation)))
          (pos (point-marker))
+         (min-indentation (+ (current-indentation)
+                             (if (python-info-looking-at-beginning-of-defun)
+                                 python-indent-offset 0)))
          (body-indentation
           (and (> arg 0)
                (save-excursion
                  (while (and
-                         (not (python-info-looking-at-beginning-of-defun))
+                         (or (not (python-info-looking-at-beginning-of-defun))
+                             (>= (current-indentation) min-indentation))
+                         (setq min-indentation
+                               (min min-indentation (current-indentation)))
                          (python-nav-backward-block)))
                  (or (and (python-info-looking-at-beginning-of-defun)
                           (+ (current-indentation) python-indent-offset))
diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el
index 8db0a07170..e17bc0df92 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -1736,6 +1736,27 @@ python-mark-defun-3
      (should (= (marker-position (mark-marker))
                 expected-mark-end-position)))))
 
+(ert-deftest python-mark-defun-4 ()
+  "Test `python-mark-defun' with nested functions."
+  (python-tests-with-temp-buffer
+   "
+def foo(x):
+    def bar():
+        return x
+    if True:
+        return bar
+"
+   (let ((expected-mark-beginning-position
+          (progn
+            (python-tests-look-at "def foo(x):")
+            (1- (line-beginning-position))))
+         (expected-mark-end-position (point-max)))
+     (python-tests-look-at "return bar")
+     (python-mark-defun 1)
+     (should (= (point) expected-mark-beginning-position))
+     (should (= (marker-position (mark-marker))
+                expected-mark-end-position)))))
+
 
 ;;; Navigation
 
@@ -1762,12 +1783,20 @@ python-nav-beginning-of-defun-1
         return wrapped_f
     return wwrap
 "
-   (python-tests-look-at "return wrap")
+   (python-tests-look-at "return wwrap")
    (should (= (save-excursion
                 (python-nav-beginning-of-defun)
                 (point))
               (save-excursion
-                (python-tests-look-at "def wrapped_f(*args):" -1)
+                (python-tests-look-at "def decoratorFunctionWithArguments" -1)
+                (beginning-of-line)
+                (point))))
+   (python-tests-look-at "return wrap" -1)
+   (should (= (save-excursion
+                (python-nav-beginning-of-defun)
+                (point))
+              (save-excursion
+                (python-tests-look-at "def wwrap(f):" -1)
                 (beginning-of-line)
                 (point))))
    (python-tests-look-at "def wrapped_f(*args):" -1)
@@ -1801,11 +1830,23 @@ python-nav-beginning-of-defun-2
         def a():
             pass
 
+        if True:
+            return a
+
     def c(self):
         pass
 "
    ;; Nested defuns, are handled with care.
    (python-tests-look-at "def c(self):")
+   (should (= (save-excursion
+                (python-nav-beginning-of-defun)
+                (point))
+              (save-excursion
+                (python-tests-look-at "def m(self):" -1)
+                (beginning-of-line)
+                (point))))
+   ;; Nested defuns shuld be skipped.
+   (python-tests-look-at "return a" -1)
    (should (= (save-excursion
                 (python-nav-beginning-of-defun)
                 (point))
