# Buggy code
def shouldPromptForDangerousWrite(self, fn, p):
    """
    Return True if Leo should warn the user that p is an @<file> node that
    was not read during startup. Writing that file might cause data loss.

    See #50: https://github.com/leo-editor/leo-editor/issues/50
    """
    trace = "save" in g.app.debug
    sfn = g.shortFileName(fn)
    c = self.c
    efc = g.app.externalFilesController
    if p.isAtNoSentFileNode():
        # #1450.
        # No danger of overwriting a file.
        # It was never read.
        return False
    if not g.os_path_exists(fn):
        # No danger of overwriting fn.
        if trace:
            g.trace("Return False: does not exist:", sfn)
        return False
    # #1347: Prompt if the external file is newer.
    if efc:
        # Like c.checkFileTimeStamp.
        if c.sqlite_connection and c.mFileName == fn:
            # sqlite database file is never actually overwriten by Leo,
            # so do *not* check its timestamp.
            pass
        elif efc.has_changed(c, fn):
            if trace:
                g.trace("Return True: changed:", sfn)
            return True
    if hasattr(p.v, "at_read"):
        # Fix bug #50: body text lost switching @file to @auto-rst
        d = p.v.at_read
        for k in d:
            if os.path.samefile(k, fn) and p.h in d.get(k, set()):
                d[fn] = d[k]
                if trace:
                    g.trace("Return False: in p.v.at_read:", sfn)
                return False
        aSet = d.get(fn, set())
        if trace:
            g.trace(f"Return {p.h not in aSet()}: p.h not in aSet(): {sfn}")
        return p.h not in aSet
    if trace:
        g.trace("Return True: never read:", sfn)
    return True


# Traceback (FileNotFoundError)
exception writing: /tmp/pytest-of-btheado/pytest-85/test_save_after_external_file_0/1_renamed
Traceback (most recent call last):

File "/home/btheado/src/leo-editor/leo/core/leoAtFile.py", line 1323, in write
if not fileName or not at.precheck(fileName, root):

File "/home/btheado/src/leo-editor/leo/core/leoAtFile.py", line 2524, in precheck
if not at.shouldPromptForDangerousWrite(fileName, root):

File "/home/btheado/src/leo-editor/leo/core/leoAtFile.py", line 3085, in shouldPromptForDangerousWrite
if os.path.samefile(k, fn) and p.h in d.get(k, set()):

File "/usr/lib/python3.7/genericpath.py", line 100, in samefile
s1 = os.stat(f1)

FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pytest-of-btheado/pytest-85/test_save_after_external_file_0/1'

# Fixed code
def shouldPromptForDangerousWrite(self, fn, p):
    """
    Return True if Leo should warn the user that p is an @<file> node that
    was not read during startup. Writing that file might cause data loss.

    See #50: https://github.com/leo-editor/leo-editor/issues/50
    """
    trace = "save" in g.app.debug
    sfn = g.shortFileName(fn)
    c = self.c
    efc = g.app.externalFilesController
    if p.isAtNoSentFileNode():
        # #1450.
        # No danger of overwriting a file.
        # It was never read.
        return False
    if not g.os_path_exists(fn):
        # No danger of overwriting fn.
        if trace:
            g.trace("Return False: does not exist:", sfn)
        return False
    # #1347: Prompt if the external file is newer.
    if efc:
        # Like c.checkFileTimeStamp.
        if c.sqlite_connection and c.mFileName == fn:
            # sqlite database file is never actually overwriten by Leo,
            # so do *not* check its timestamp.
            pass
        elif efc.has_changed(c, fn):
            if trace:
                g.trace("Return True: changed:", sfn)
            return True
    if hasattr(p.v, "at_read"):
        # Fix bug #50: body text lost switching @file to @auto-rst
        d = p.v.at_read
        for k in d:
            # Fix bug # #1469: make sure k still exists.
            if os.path.exists(k) and os.path.samefile(k, fn) and p.h in d.get(k, set()):
                d[fn] = d[k]
                if trace:
                    g.trace("Return False: in p.v.at_read:", sfn)
                return False
        aSet = d.get(fn, set())
        if trace:
            g.trace(f"Return {p.h not in aSet()}: p.h not in aSet(): {sfn}")
        return p.h not in aSet
    if trace:
        g.trace("Return True: never read:", sfn)
    return True