Sprinkle open(..., encoding=utf-8) (#48006)

Add missing encoding=utf-8 to various open calls. This makes
files like spec.json, spack.yaml, spack.lock, config.yaml etc locale
independent w.r.t. text encoding. In practice this is not often an
issue since Python 3.7, where the C locale is promoted to
C.UTF-8. But it's better to enforce UTF-8 explicitly, since there is
no guarantee text files are written in the right encoding.

Also avoid opening in text mode if it can be avoided.
This commit is contained in:
Harmen Stoppels
2024-12-12 21:46:08 +01:00
committed by GitHub
parent 334a8b0991
commit 526af1cbe7
158 changed files with 575 additions and 561 deletions

View File

@@ -96,8 +96,8 @@ def get_fh(self, path: str) -> IO:
Arguments:
path: path to lock file we want a filehandle for
"""
# Open writable files as 'r+' so we can upgrade to write later
os_mode, fh_mode = (os.O_RDWR | os.O_CREAT), "r+"
# Open writable files as rb+ so we can upgrade to write later
os_mode, fh_mode = (os.O_RDWR | os.O_CREAT), "rb+"
pid = os.getpid()
open_file = None # OpenFile object, if there is one
@@ -124,7 +124,7 @@ def get_fh(self, path: str) -> IO:
# we know path exists but not if it's writable. If it's read-only,
# only open the file for reading (and fail if we're trying to get
# an exclusive (write) lock on it)
os_mode, fh_mode = os.O_RDONLY, "r"
os_mode, fh_mode = os.O_RDONLY, "rb"
fd = os.open(path, os_mode)
fh = os.fdopen(fd, fh_mode)
@@ -243,7 +243,7 @@ def __init__(
helpful for distinguishing between different Spack locks.
"""
self.path = path
self._file: Optional[IO] = None
self._file: Optional[IO[bytes]] = None
self._reads = 0
self._writes = 0
@@ -329,9 +329,9 @@ def _lock(self, op: int, timeout: Optional[float] = None) -> Tuple[float, int]:
self._ensure_parent_directory()
self._file = FILE_TRACKER.get_fh(self.path)
if LockType.to_module(op) == fcntl.LOCK_EX and self._file.mode == "r":
if LockType.to_module(op) == fcntl.LOCK_EX and self._file.mode == "rb":
# Attempt to upgrade to write lock w/a read-only file.
# If the file were writable, we'd have opened it 'r+'
# If the file were writable, we'd have opened it rb+
raise LockROFileError(self.path)
self._log_debug(
@@ -426,7 +426,7 @@ def _read_log_debug_data(self) -> None:
line = self._file.read()
if line:
pid, host = line.strip().split(",")
pid, host = line.decode("utf-8").strip().split(",")
_, _, pid = pid.rpartition("=")
_, _, self.host = host.rpartition("=")
self.pid = int(pid)
@@ -442,7 +442,7 @@ def _write_log_debug_data(self) -> None:
# write pid, host to disk to sync over FS
self._file.seek(0)
self._file.write("pid=%s,host=%s" % (self.pid, self.host))
self._file.write(f"pid={self.pid},host={self.host}".encode("utf-8"))
self._file.truncate()
self._file.flush()
os.fsync(self._file.fileno())