changeset 49306:2e726c934fcd

py3: catch FileNotFoundError instead of checking errno == ENOENT
author Manuel Jacob <me@manueljacob.de>
date Tue, 31 May 2022 22:50:01 +0200
parents 53e9422a9b45
children 6f2a57ba2d13
files hgext/convert/common.py hgext/convert/darcs.py hgext/fsmonitor/state.py hgext/git/dirstate.py hgext/infinitepush/__init__.py hgext/journal.py hgext/largefiles/lfcommands.py hgext/mq.py hgext/rebase.py hgext/releasenotes.py hgext/remotefilelog/basepack.py hgext/remotefilelog/basestore.py hgext/share.py mercurial/bookmarks.py mercurial/commands.py mercurial/context.py mercurial/debugcommands.py mercurial/dirstate.py mercurial/dirstatemap.py mercurial/grep.py mercurial/localrepo.py mercurial/lock.py mercurial/merge.py mercurial/mergestate.py mercurial/obsolete.py mercurial/patch.py mercurial/phases.py mercurial/posix.py mercurial/revlog.py mercurial/revlogutils/docket.py mercurial/revlogutils/nodemap.py mercurial/scmutil.py mercurial/shelve.py mercurial/statichttprepo.py mercurial/store.py mercurial/subrepoutil.py mercurial/tags.py mercurial/transaction.py mercurial/txnutil.py mercurial/ui.py mercurial/upgrade_utils/engine.py mercurial/util.py mercurial/vfs.py tests/run-tests.py tests/test-push-race.t
diffstat 45 files changed, 127 insertions(+), 291 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/convert/common.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/convert/common.py	Tue May 31 22:50:01 2022 +0200
@@ -7,7 +7,6 @@
 
 import base64
 import datetime
-import errno
 import os
 import pickle
 import re
@@ -528,9 +527,7 @@
             return
         try:
             fp = open(self.path, b'rb')
-        except IOError as err:
-            if err.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             return
         for i, line in enumerate(fp):
             line = line.splitlines()[0].rstrip()
--- a/hgext/convert/darcs.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/convert/darcs.py	Tue May 31 22:50:01 2022 +0200
@@ -5,7 +5,6 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import errno
 import os
 import re
 import shutil
@@ -230,10 +229,8 @@
         try:
             data = util.readfile(path)
             mode = os.lstat(path).st_mode
-        except IOError as inst:
-            if inst.errno == errno.ENOENT:
-                return None, None
-            raise
+        except FileNotFoundError:
+            return None, None
         mode = (mode & 0o111) and b'x' or b''
         return data, mode
 
--- a/hgext/fsmonitor/state.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/fsmonitor/state.py	Tue May 31 22:50:01 2022 +0200
@@ -137,9 +137,8 @@
     def invalidate(self):
         try:
             os.unlink(os.path.join(self._rootdir, b'.hg', b'fsmonitor.state'))
-        except OSError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
         self._identity = util.filestat(None)
 
     def setlastclock(self, clock):
--- a/hgext/git/dirstate.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/git/dirstate.py	Tue May 31 22:50:01 2022 +0200
@@ -1,5 +1,4 @@
 import contextlib
-import errno
 import os
 
 from mercurial.node import sha1nodeconstants
@@ -318,9 +317,7 @@
             # TODO construct the stat info from the status object?
             try:
                 s = os.stat(os.path.join(cwd, path))
-            except OSError as e:
-                if e.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
                 continue
             r[path] = s
         return r
--- a/hgext/infinitepush/__init__.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/infinitepush/__init__.py	Tue May 31 22:50:01 2022 +0200
@@ -90,7 +90,6 @@
 
 import collections
 import contextlib
-import errno
 import functools
 import logging
 import os
@@ -1307,9 +1306,8 @@
     finally:
         try:
             os.unlink(bundlefile)
-        except OSError as e:
-            if e.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
 
     return 1
 
--- a/hgext/journal.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/journal.py	Tue May 31 22:50:01 2022 +0200
@@ -13,7 +13,6 @@
 
 
 import collections
-import errno
 import os
 import weakref
 
@@ -140,9 +139,7 @@
     """A set of shared features for this repository"""
     try:
         return set(repo.vfs.read(b'shared').splitlines())
-    except IOError as inst:
-        if inst.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
         return set()
 
 
--- a/hgext/largefiles/lfcommands.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/largefiles/lfcommands.py	Tue May 31 22:50:01 2022 +0200
@@ -9,7 +9,6 @@
 '''High-level command function for lfconvert, plus the cmdtable.'''
 
 import binascii
-import errno
 import os
 import shutil
 
@@ -474,10 +473,8 @@
     for lfile in lfiles:
         try:
             expectedhash = lfutil.readasstandin(ctx[lfutil.standin(lfile)])
-        except IOError as err:
-            if err.errno == errno.ENOENT:
-                continue  # node must be None and standin wasn't found in wctx
-            raise
+        except FileNotFoundError:
+            continue  # node must be None and standin wasn't found in wctx
         if not lfutil.findfile(repo, expectedhash):
             toget.append((lfile, expectedhash))
 
--- a/hgext/mq.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/mq.py	Tue May 31 22:50:01 2022 +0200
@@ -63,7 +63,6 @@
 '''
 
 
-import errno
 import os
 import re
 import shutil
@@ -551,19 +550,15 @@
         try:
             lines = self.opener.read(self.statuspath).splitlines()
             return list(parselines(lines))
-        except IOError as e:
-            if e.errno == errno.ENOENT:
-                return []
-            raise
+        except FileNotFoundError:
+            return []
 
     @util.propertycache
     def fullseries(self):
         try:
             return self.opener.read(self.seriespath).splitlines()
-        except IOError as e:
-            if e.errno == errno.ENOENT:
-                return []
-            raise
+        except FileNotFoundError:
+            return []
 
     @util.propertycache
     def series(self):
@@ -691,9 +686,7 @@
             self.activeguards = []
             try:
                 guards = self.opener.read(self.guardspath).split()
-            except IOError as err:
-                if err.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
                 guards = []
             for i, guard in enumerate(guards):
                 bad = self.checkguard(guard)
@@ -1140,9 +1133,8 @@
             for p in patches:
                 try:
                     os.unlink(self.join(p))
-                except OSError as inst:
-                    if inst.errno != errno.ENOENT:
-                        raise
+                except FileNotFoundError:
+                    pass
 
         qfinished = []
         if numrevs:
--- a/hgext/rebase.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/rebase.py	Tue May 31 22:50:01 2022 +0200
@@ -15,7 +15,6 @@
 '''
 
 
-import errno
 import os
 
 from mercurial.i18n import _
@@ -1940,9 +1939,7 @@
         f = repo.vfs(b"last-message.txt")
         collapsemsg = f.readline().strip()
         f.close()
-    except IOError as err:
-        if err.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
         if isabort:
             # Oh well, just abort like normal
             collapsemsg = b''
--- a/hgext/releasenotes.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/releasenotes.py	Tue May 31 22:50:01 2022 +0200
@@ -13,7 +13,6 @@
 
 
 import difflib
-import errno
 import re
 
 from mercurial.i18n import _
@@ -688,10 +687,7 @@
     try:
         with open(file_, b'rb') as fh:
             notes = parsereleasenotesfile(sections, fh.read())
-    except IOError as e:
-        if e.errno != errno.ENOENT:
-            raise
-
+    except FileNotFoundError:
         notes = parsedreleasenotes()
 
     notes.merge(ui, incoming)
--- a/hgext/remotefilelog/basepack.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/remotefilelog/basepack.py	Tue May 31 22:50:01 2022 +0200
@@ -166,9 +166,8 @@
                         )
                     else:
                         ids.add(id)
-        except OSError as ex:
-            if ex.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
 
     def _getavailablepackfilessorted(self):
         """Like `_getavailablepackfiles`, but also sorts the files by mtime,
--- a/hgext/remotefilelog/basestore.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/remotefilelog/basestore.py	Tue May 31 22:50:01 2022 +0200
@@ -1,4 +1,3 @@
-import errno
 import os
 import shutil
 import stat
@@ -344,10 +343,7 @@
                 count += 1
                 try:
                     pathstat = os.stat(path)
-                except OSError as e:
-                    # errno.ENOENT = no such file or directory
-                    if e.errno != errno.ENOENT:
-                        raise
+                except FileNotFoundError:
                     msg = _(
                         b"warning: file %s was removed by another process\n"
                     )
@@ -362,10 +358,7 @@
                 else:
                     try:
                         shallowutil.unlinkfile(path)
-                    except OSError as e:
-                        # errno.ENOENT = no such file or directory
-                        if e.errno != errno.ENOENT:
-                            raise
+                    except FileNotFoundError:
                         msg = _(
                             b"warning: file %s was removed by another "
                             b"process\n"
@@ -388,10 +381,7 @@
                 atime, oldpath, oldpathstat = queue.get()
                 try:
                     shallowutil.unlinkfile(oldpath)
-                except OSError as e:
-                    # errno.ENOENT = no such file or directory
-                    if e.errno != errno.ENOENT:
-                        raise
+                except FileNotFoundError:
                     msg = _(
                         b"warning: file %s was removed by another process\n"
                     )
--- a/hgext/share.py	Tue May 31 21:16:17 2022 +0200
+++ b/hgext/share.py	Tue May 31 22:50:01 2022 +0200
@@ -66,7 +66,6 @@
 '''
 
 
-import errno
 from mercurial.i18n import _
 from mercurial import (
     bookmarks,
@@ -177,9 +176,7 @@
         return False
     try:
         shared = repo.vfs.read(b'shared').splitlines()
-    except IOError as inst:
-        if inst.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
         return False
     return hg.sharedbookmarks in shared
 
@@ -199,9 +196,8 @@
                     # is up-to-date.
                     return fp
                 fp.close()
-            except IOError as inst:
-                if inst.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
+                pass
 
             # otherwise, we should read bookmarks from srcrepo,
             # because .hg/bookmarks in srcrepo might be already
--- a/mercurial/bookmarks.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/bookmarks.py	Tue May 31 22:50:01 2022 +0200
@@ -6,7 +6,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
 import struct
 
 from .i18n import _
@@ -114,9 +113,8 @@
                             _(b'malformed line in %s: %r\n')
                             % (bookmarkspath, pycompat.bytestr(line))
                         )
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
         self._active = _readactive(repo, self)
 
     @property
--- a/mercurial/commands.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/commands.py	Tue May 31 22:50:01 2022 +0200
@@ -6,7 +6,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
 import os
 import re
 import sys
@@ -6175,9 +6174,8 @@
                 a = repo.wjoin(f)
                 try:
                     util.copyfile(a, a + b".resolve")
-                except (IOError, OSError) as inst:
-                    if inst.errno != errno.ENOENT:
-                        raise
+                except FileNotFoundError:
+                    pass
 
                 try:
                     # preresolve file
@@ -6194,9 +6192,8 @@
                     util.rename(
                         a + b".resolve", scmutil.backuppath(ui, repo, f)
                     )
-                except OSError as inst:
-                    if inst.errno != errno.ENOENT:
-                        raise
+                except FileNotFoundError:
+                    pass
 
         if hasconflictmarkers:
             ui.warn(
--- a/mercurial/context.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/context.py	Tue May 31 22:50:01 2022 +0200
@@ -6,7 +6,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
 import filecmp
 import os
 import stat
@@ -1737,9 +1736,7 @@
     def copy(self, source, dest):
         try:
             st = self._repo.wvfs.lstat(dest)
-        except OSError as err:
-            if err.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             self._repo.ui.warn(
                 _(b"%s does not exist!\n") % self._repo.dirstate.pathto(dest)
             )
@@ -2169,9 +2166,7 @@
         t, tz = self._changectx.date()
         try:
             return (self._repo.wvfs.lstat(self._path)[stat.ST_MTIME], tz)
-        except OSError as err:
-            if err.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             return (t, tz)
 
     def exists(self):
--- a/mercurial/debugcommands.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/debugcommands.py	Tue May 31 22:50:01 2022 +0200
@@ -2350,9 +2350,8 @@
                         )
                 ui.writenoi18n(b"%-6s %s (%ds)\n" % (name + b":", locker, age))
                 return 1
-            except OSError as e:
-                if e.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
+                pass
 
         ui.writenoi18n(b"%-6s free\n" % (name + b":"))
         return 0
--- a/mercurial/dirstate.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/dirstate.py	Tue May 31 22:50:01 2022 +0200
@@ -195,9 +195,7 @@
     def _branch(self):
         try:
             return self._opener.read(b"branch").strip() or b"default"
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             return b"default"
 
     @property
--- a/mercurial/dirstatemap.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/dirstatemap.py	Tue May 31 22:50:01 2022 +0200
@@ -4,8 +4,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
-
 from .i18n import _
 
 from . import (
@@ -95,9 +93,7 @@
         try:
             with self._opendirstatefile() as fp:
                 return fp.read(size)
-        except IOError as err:
-            if err.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             # File doesn't exist, so the current state is empty
             return b''
 
--- a/mercurial/grep.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/grep.py	Tue May 31 22:50:01 2022 +0200
@@ -7,7 +7,6 @@
 
 
 import difflib
-import errno
 
 from .i18n import _
 
@@ -158,9 +157,8 @@
             fctx = ctx[fn]
             try:
                 return fctx.data()
-            except IOError as e:
-                if e.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
+                pass
         else:
             flog = self._getfile(fn)
             fnode = ctx.filenode(fn)
--- a/mercurial/localrepo.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/localrepo.py	Tue May 31 22:50:01 2022 +0200
@@ -7,7 +7,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
 import functools
 import os
 import random
@@ -517,7 +516,7 @@
     """reads the require file present at root of this vfs
     and return a set of requirements
 
-    If allowmissing is True, we suppress ENOENT if raised"""
+    If allowmissing is True, we suppress FileNotFoundError if raised"""
     # requires file contains a newline-delimited list of
     # features/capabilities the opener (us) must have in order to use
     # the repository. This file was introduced in Mercurial 0.9.2,
@@ -525,8 +524,8 @@
     # a missing file translates to no requirements.
     try:
         requirements = set(vfs.read(b'requires').splitlines())
-    except IOError as e:
-        if not (allowmissing and e.errno == errno.ENOENT):
+    except FileNotFoundError:
+        if not allowmissing:
             raise
         requirements = set()
     return requirements
@@ -583,9 +582,8 @@
     if not hgvfs.isdir():
         try:
             hgvfs.stat()
-        except OSError as e:
-            if e.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
         except ValueError as e:
             # Can be raised on Python 3.8 when path is invalid.
             raise error.Abort(
@@ -3503,9 +3501,8 @@
             vfs.tryunlink(dest)
             try:
                 vfs.rename(src, dest)
-            except OSError as exc:  # journal file does not yet exist
-                if exc.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:  # journal file does not yet exist
+                pass
 
     return a
 
--- a/mercurial/lock.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/lock.py	Tue May 31 22:50:01 2022 +0200
@@ -311,10 +311,8 @@
         """
         try:
             return self.vfs.readlock(self.f)
-        except (OSError, IOError) as why:
-            if why.errno == errno.ENOENT:
-                return None
-            raise
+        except FileNotFoundError:
+            return None
 
     def _lockshouldbebroken(self, locker):
         if locker is None:
--- a/mercurial/merge.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/merge.py	Tue May 31 22:50:01 2022 +0200
@@ -7,7 +7,6 @@
 
 
 import collections
-import errno
 import struct
 
 from .i18n import _
@@ -1306,10 +1305,8 @@
 def _getcwd():
     try:
         return encoding.getcwd()
-    except OSError as err:
-        if err.errno == errno.ENOENT:
-            return None
-        raise
+    except FileNotFoundError:
+        return None
 
 
 def batchremove(repo, wctx, actions):
--- a/mercurial/mergestate.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/mergestate.py	Tue May 31 22:50:01 2022 +0200
@@ -1,5 +1,4 @@
 import collections
-import errno
 import shutil
 import struct
 import weakref
@@ -629,9 +628,8 @@
                 else:
                     records.append((RECORD_MERGED, l[:-1]))
             f.close()
-        except IOError as err:
-            if err.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
         return records
 
     def _readrecordsv2(self):
@@ -669,9 +667,8 @@
                     rtype, record = record[0:1], record[1:]
                 records.append((rtype, record))
             f.close()
-        except IOError as err:
-            if err.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
         return records
 
     def commit(self):
--- a/mercurial/obsolete.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/obsolete.py	Tue May 31 22:50:01 2022 +0200
@@ -69,7 +69,6 @@
 """
 
 import binascii
-import errno
 import struct
 
 from .i18n import _
@@ -582,11 +581,10 @@
         if not self._cached('_all'):
             try:
                 return self.svfs.stat(b'obsstore').st_size > 1
-            except OSError as inst:
-                if inst.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
                 # just build an empty _all list if no obsstore exists, which
                 # avoids further stat() syscalls
+                pass
         return bool(self._all)
 
     __bool__ = __nonzero__
--- a/mercurial/patch.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/patch.py	Tue May 31 22:50:01 2022 +0200
@@ -10,7 +10,6 @@
 import collections
 import contextlib
 import copy
-import errno
 import os
 import re
 import shutil
@@ -503,14 +502,11 @@
         isexec = False
         try:
             isexec = self.opener.lstat(fname).st_mode & 0o100 != 0
-        except OSError as e:
-            if e.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
         try:
             return (self.opener.read(fname), (False, isexec))
-        except IOError as e:
-            if e.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             return None, None
 
     def setfile(self, fname, data, mode, copysource):
--- a/mercurial/phases.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/phases.py	Tue May 31 22:50:01 2022 +0200
@@ -101,7 +101,6 @@
 """
 
 
-import errno
 import struct
 
 from .i18n import _
@@ -202,9 +201,7 @@
                 roots[int(phase)].add(bin(nh))
         finally:
             f.close()
-    except IOError as inst:
-        if inst.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
         if phasedefaults:
             for f in phasedefaults:
                 roots = f(repo, roots)
--- a/mercurial/posix.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/posix.py	Tue May 31 22:50:01 2022 +0200
@@ -175,9 +175,7 @@
     using umask."""
     try:
         st_mode = os.lstat(src).st_mode & 0o777
-    except OSError as inst:
-        if inst.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
         st_mode = mode
         if st_mode is None:
             st_mode = ~umask
@@ -226,19 +224,16 @@
 
             try:
                 m = os.stat(checkisexec).st_mode
-            except OSError as e:
-                if e.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
                 # checkisexec does not exist - fall through ...
+                pass
             else:
                 # checkisexec exists, check if it actually is exec
                 if m & EXECFLAGS != 0:
                     # ensure checkisexec exists, check it isn't exec
                     try:
                         m = os.stat(checknoexec).st_mode
-                    except OSError as e:
-                        if e.errno != errno.ENOENT:
-                            raise
+                    except FileNotFoundError:
                         open(checknoexec, b'w').close()  # might fail
                         m = os.stat(checknoexec).st_mode
                     if m & EXECFLAGS == 0:
--- a/mercurial/revlog.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/revlog.py	Tue May 31 22:50:01 2022 +0200
@@ -16,7 +16,6 @@
 import binascii
 import collections
 import contextlib
-import errno
 import io
 import os
 import struct
@@ -486,9 +485,7 @@
                     return fp.read()
                 else:
                     return fp.read(size)
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             return b''
 
     def _loadindex(self, docket=None):
@@ -701,9 +698,7 @@
             else:
                 f.seek(self._docket.index_end, os.SEEK_SET)
             return f
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             return self.opener(
                 self._indexfile, mode=b"w+", checkambig=self._checkambig
             )
@@ -2116,9 +2111,7 @@
                             dfh.seek(0, os.SEEK_END)
                         else:
                             dfh.seek(self._docket.data_end, os.SEEK_SET)
-                    except IOError as inst:
-                        if inst.errno != errno.ENOENT:
-                            raise
+                    except FileNotFoundError:
                         dfh = self._datafp(b"w+")
                     transaction.add(self._datafile, dsize)
                 if self._sidedatafile is not None:
@@ -2127,9 +2120,7 @@
                     try:
                         sdfh = self.opener(self._sidedatafile, mode=b"r+")
                         dfh.seek(self._docket.sidedata_end, os.SEEK_SET)
-                    except IOError as inst:
-                        if inst.errno != errno.ENOENT:
-                            raise
+                    except FileNotFoundError:
                         sdfh = self.opener(self._sidedatafile, mode=b"w+")
                     transaction.add(
                         self._sidedatafile, self._docket.sidedata_end
@@ -2832,9 +2823,7 @@
                 f.seek(0, io.SEEK_END)
                 actual = f.tell()
             dd = actual - expected
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             dd = 0
 
         try:
@@ -2851,9 +2840,7 @@
                     databytes += max(0, self.length(r))
                 dd = 0
                 di = actual - len(self) * s - databytes
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             di = 0
 
         return (dd, di)
--- a/mercurial/revlogutils/docket.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/revlogutils/docket.py	Tue May 31 22:50:01 2022 +0200
@@ -16,7 +16,6 @@
 # * a data file, containing variable width data for these revisions,
 
 
-import errno
 import os
 import random
 import struct
@@ -51,9 +50,7 @@
         try:
             with open(stable_docket_file, mode='rb') as f:
                 seed = f.read().strip()
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             seed = b'04'  # chosen by a fair dice roll. garanteed to be random
         iter_seed = iter(seed)
         # some basic circular sum hashing on 64 bits
--- a/mercurial/revlogutils/nodemap.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/revlogutils/nodemap.py	Tue May 31 22:50:01 2022 +0200
@@ -7,7 +7,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
 import re
 import struct
 
@@ -83,11 +82,8 @@
                     data = b''
             else:
                 data = fd.read(data_length)
-    except (IOError, OSError) as e:
-        if e.errno == errno.ENOENT:
-            return None
-        else:
-            raise
+    except FileNotFoundError:
+        return None
     if len(data) < data_length:
         return None
     return docket, data
--- a/mercurial/scmutil.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/scmutil.py	Tue May 31 22:50:01 2022 +0200
@@ -1619,9 +1619,8 @@
     def stat(path):
         try:
             return util.cachestat(path)
-        except OSError as e:
-            if e.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
 
 
 class filecacheentry:
--- a/mercurial/shelve.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/shelve.py	Tue May 31 22:50:01 2022 +0200
@@ -22,7 +22,6 @@
 """
 
 import collections
-import errno
 import itertools
 import stat
 
@@ -82,9 +81,7 @@
         """return all shelves in repo as list of (time, name)"""
         try:
             names = self.vfs.listdir()
-        except OSError as err:
-            if err.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             return []
         info = []
         seen = set()
@@ -724,9 +721,7 @@
         state = shelvedstate.load(repo)
         if opts.get(b'keep') is None:
             opts[b'keep'] = state.keep
-    except IOError as err:
-        if err.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
         cmdutil.wrongtooltocontinue(repo, _(b'unshelve'))
     except error.CorruptedState as err:
         ui.debug(pycompat.bytestr(err) + b'\n')
--- a/mercurial/statichttprepo.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/statichttprepo.py	Tue May 31 22:50:01 2022 +0200
@@ -181,9 +181,7 @@
 
         try:
             requirements = set(self.vfs.read(b'requires').splitlines())
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             requirements = set()
 
             # check if it is a non-empty old-style repository
@@ -191,9 +189,7 @@
                 fp = self.vfs(b"00changelog.i")
                 fp.read(1)
                 fp.close()
-            except IOError as inst:
-                if inst.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
                 # we do not care about empty old-style repositories here
                 msg = _(b"'%s' does not appear to be an hg repository") % path
                 raise error.RepoError(msg)
--- a/mercurial/store.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/store.py	Tue May 31 22:50:01 2022 +0200
@@ -6,7 +6,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
 import functools
 import os
 import re
@@ -788,9 +787,8 @@
                 assert t is not None, f
                 t |= FILEFLAGS_FILELOG
                 yield t, f, self.getsize(ef)
-            except OSError as err:
-                if err.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
+                pass
 
     def copylist(self):
         d = (
@@ -825,10 +823,7 @@
         try:
             self.getsize(ef)
             return True
-        except OSError as err:
-            if err.errno != errno.ENOENT:
-                raise
-            # nonexistent entry
+        except FileNotFoundError:
             return False
 
     def __contains__(self, path):
--- a/mercurial/subrepoutil.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/subrepoutil.py	Tue May 31 22:50:01 2022 +0200
@@ -6,7 +6,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
 import os
 import posixpath
 import re
@@ -63,9 +62,7 @@
         if f in ctx:
             try:
                 data = ctx[f].data()
-            except IOError as err:
-                if err.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
                 # handle missing subrepo spec files as removed
                 ui.warn(
                     _(b"warning: subrepo spec file \'%s\' not found\n")
@@ -102,9 +99,8 @@
                         % (repo.pathto(b'.hgsubstate'), (i + 1))
                     )
                 rev[path] = revision
-        except IOError as err:
-            if err.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
 
     def remap(src):
         # type: (bytes) -> bytes
--- a/mercurial/tags.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/tags.py	Tue May 31 22:50:01 2022 +0200
@@ -12,7 +12,6 @@
 
 
 import binascii
-import errno
 import io
 
 from .node import (
@@ -242,9 +241,7 @@
     '''Read local tags in repo. Update alltags and tagtypes.'''
     try:
         data = repo.vfs.read(b"localtags")
-    except IOError as inst:
-        if inst.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
         return
 
     # localtags is in the local encoding; re-encode to UTF-8 on
@@ -652,9 +649,7 @@
 
     try:
         fp = repo.wvfs(b'.hgtags', b'rb+')
-    except IOError as e:
-        if e.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
         fp = repo.wvfs(b'.hgtags', b'ab')
     else:
         prevtags = fp.read()
--- a/mercurial/transaction.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/transaction.py	Tue May 31 22:50:01 2022 +0200
@@ -12,8 +12,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
-
 from .i18n import _
 from . import (
     error,
@@ -71,9 +69,8 @@
         else:
             try:
                 opener.unlink(f)
-            except (IOError, OSError) as inst:
-                if inst.errno != errno.ENOENT:
-                    raise
+            except FileNotFoundError:
+                pass
 
     backupfiles = []
     for l, f, b, c in backupentries:
@@ -95,9 +92,8 @@
                 target = f or b
                 try:
                     vfs.unlink(target)
-                except (IOError, OSError) as inst:
-                    if inst.errno != errno.ENOENT:
-                        raise
+                except FileNotFoundError:
+                    pass
         except (IOError, OSError, error.Abort):
             if not c:
                 raise
--- a/mercurial/txnutil.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/txnutil.py	Tue May 31 22:50:01 2022 +0200
@@ -6,8 +6,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
-
 from . import encoding
 
 
@@ -29,7 +27,6 @@
     if mayhavepending(root):
         try:
             return (vfs(b'%s.pending' % filename, **kwargs), True)
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
     return (vfs(filename, **kwargs), False)
--- a/mercurial/ui.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/ui.py	Tue May 31 22:50:01 2022 +0200
@@ -1517,8 +1517,8 @@
                 stderr=procutil.stderr,
                 env=procutil.tonativeenv(procutil.shellenviron(env)),
             )
-        except OSError as e:
-            if e.errno == errno.ENOENT and not shell:
+        except FileNotFoundError:
+            if not shell:
                 self.warn(
                     _(b"missing pager command '%s', skipping pager\n") % command
                 )
--- a/mercurial/upgrade_utils/engine.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/upgrade_utils/engine.py	Tue May 31 22:50:01 2022 +0200
@@ -6,7 +6,6 @@
 # GNU General Public License version 2 or any later version.
 
 
-import errno
 import stat
 
 from ..i18n import _
@@ -646,11 +645,10 @@
             util.copyfile(
                 srcrepo.vfs.join(b'dirstate'), backupvfs.join(b'dirstate')
             )
-        except (IOError, OSError) as e:
+        except FileNotFoundError:
             # The dirstate does not exist on an empty repo or a repo with no
             # revision checked out
-            if e.errno != errno.ENOENT:
-                raise
+            pass
 
     assert srcrepo.dirstate._use_dirstate_v2 == (old == b'v2')
     srcrepo.dirstate._map.preload()
@@ -659,11 +657,10 @@
     srcrepo.dirstate._dirty = True
     try:
         srcrepo.vfs.unlink(b'dirstate')
-    except (IOError, OSError) as e:
+    except FileNotFoundError:
         # The dirstate does not exist on an empty repo or a repo with no
         # revision checked out
-        if e.errno != errno.ENOENT:
-            raise
+        pass
 
     srcrepo.dirstate.write(None)
 
--- a/mercurial/util.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/util.py	Tue May 31 22:50:01 2022 +0200
@@ -2426,9 +2426,7 @@
     def frompath(cls, path):
         try:
             stat = os.stat(path)
-        except OSError as err:
-            if err.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             stat = None
         return cls(stat)
 
@@ -2612,12 +2610,11 @@
 
 def tryunlink(f):
     # type: (bytes) -> None
-    """Attempt to remove a file, ignoring ENOENT errors."""
+    """Attempt to remove a file, ignoring FileNotFoundError."""
     try:
         unlink(f)
-    except OSError as e:
-        if e.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
+        pass
 
 
 def makedirs(name, mode=None, notindexed=False):
--- a/mercurial/vfs.py	Tue May 31 21:16:17 2022 +0200
+++ b/mercurial/vfs.py	Tue May 31 22:50:01 2022 +0200
@@ -6,7 +6,6 @@
 # GNU General Public License version 2 or any later version.
 
 import contextlib
-import errno
 import os
 import shutil
 import stat
@@ -74,18 +73,16 @@
         '''gracefully return an empty string for missing files'''
         try:
             return self.read(path)
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
         return b""
 
     def tryreadlines(self, path, mode=b'rb'):
         '''gracefully return an empty array for missing files'''
         try:
             return self.readlines(path, mode=mode)
-        except IOError as inst:
-            if inst.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
+            pass
         return []
 
     @util.propertycache
@@ -476,9 +473,7 @@
                             nlink = util.nlinks(f)
                             if nlink < 1:
                                 nlink = 2  # force mktempcopy (issue1922)
-                except (OSError, IOError) as e:
-                    if e.errno != errno.ENOENT:
-                        raise
+                except FileNotFoundError:
                     nlink = 0
                     if makeparentdirs:
                         util.makedirs(dirname, self.createmode, notindexed)
--- a/tests/run-tests.py	Tue May 31 21:16:17 2022 +0200
+++ b/tests/run-tests.py	Tue May 31 22:50:01 2022 +0200
@@ -362,9 +362,7 @@
         try:
             path = os.path.expanduser(os.path.expandvars(filename))
             f = open(path, "rb")
-        except IOError as err:
-            if err.errno != errno.ENOENT:
-                raise
+        except FileNotFoundError:
             if warn:
                 print("warning: no such %s file: %s" % (listtype, filename))
             continue
@@ -390,9 +388,8 @@
             for l in f:
                 if l.startswith(b'#testcases '):
                     cases.append(sorted(l[11:].split()))
-    except IOError as ex:
-        if ex.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
+        pass
     return cases
 
 
@@ -1110,12 +1107,11 @@
         if os.path.exists(self.errpath):
             try:
                 os.remove(self.errpath)
-            except OSError as e:
-                # We might have raced another test to clean up a .err
-                # file, so ignore ENOENT when removing a previous .err
+            except FileNotFoundError:
+                # We might have raced another test to clean up a .err file,
+                # so ignore FileNotFoundError when removing a previous .err
                 # file.
-                if e.errno != errno.ENOENT:
-                    raise
+                pass
 
         if self._usechg:
             self._chgsockdir = os.path.join(
@@ -2622,9 +2618,8 @@
                 times.append(
                     (m.group(1), [float(t) for t in m.group(2).split()])
                 )
-    except IOError as err:
-        if err.errno != errno.ENOENT:
-            raise
+    except FileNotFoundError:
+        pass
     return times
 
 
@@ -2979,9 +2974,7 @@
             except KeyError:
                 try:
                     val = -os.stat(f).st_size
-                except OSError as e:
-                    if e.errno != errno.ENOENT:
-                        raise
+                except FileNotFoundError:
                     perf[f] = -1e9  # file does not exist, tell early
                     return -1e9
                 for kw, mul in slow.items():
@@ -3584,9 +3577,8 @@
                     if os.readlink(mypython) == sysexecutable:
                         continue
                     os.unlink(mypython)
-                except OSError as err:
-                    if err.errno != errno.ENOENT:
-                        raise
+                except FileNotFoundError:
+                    pass
                 if self._findprogram(pyexename) != sysexecutable:
                     try:
                         os.symlink(sysexecutable, mypython)
@@ -3714,9 +3706,8 @@
             if not self.options.verbose:
                 try:
                     os.remove(installerrs)
-                except OSError as e:
-                    if e.errno != errno.ENOENT:
-                        raise
+                except FileNotFoundError:
+                    pass
         else:
             with open(installerrs, 'rb') as f:
                 for line in f:
--- a/tests/test-push-race.t	Tue May 31 21:16:17 2022 +0200
+++ b/tests/test-push-race.t	Tue May 31 22:50:01 2022 +0200
@@ -58,9 +58,8 @@
   >             def delete():
   >                 try:
   >                     os.unlink(watchpath)
-  >                 except OSError as exc:
-  >                     if exc.errno != errno.ENOENT:
-  >                         raise
+  >                 except FileNotFoundError:
+  >                     pass
   >             ui.atexit(delete)
   >     return orig(pushop)
   >