Home Assistant Unofficial Reference 2024.12.1
file.py
Go to the documentation of this file.
1 """File utility functions."""
2 
3 from __future__ import annotations
4 
5 import logging
6 import os
7 import tempfile
8 
9 from atomicwrites import AtomicWriter
10 
11 from homeassistant.exceptions import HomeAssistantError
12 
13 _LOGGER = logging.getLogger(__name__)
14 
15 
17  """Error writing the data."""
18 
19 
21  filename: str, utf8_data: bytes | str, private: bool = False, mode: str = "w"
22 ) -> None:
23  """Write a file and rename it into place using atomicwrites.
24 
25  Writes all or nothing.
26 
27  This function uses fsync under the hood. It should
28  only be used to write mission critical files as
29  fsync can block for a few seconds or longer is the
30  disk is busy.
31 
32  Using this function frequently will significantly
33  negatively impact performance.
34  """
35  try:
36  with AtomicWriter(filename, mode=mode, overwrite=True).open() as fdesc:
37  if not private:
38  os.fchmod(fdesc.fileno(), 0o644)
39  fdesc.write(utf8_data)
40  except OSError as error:
41  _LOGGER.exception("Saving file failed: %s", filename)
42  raise WriteError(error) from error
43 
44 
46  filename: str, utf8_data: bytes | str, private: bool = False, mode: str = "w"
47 ) -> None:
48  """Write a file and rename it into place.
49 
50  Writes all or nothing.
51  """
52  tmp_filename = ""
53  encoding = "utf-8" if "b" not in mode else None
54  try:
55  # Modern versions of Python tempfile create this file with mode 0o600
56  with tempfile.NamedTemporaryFile(
57  mode=mode, encoding=encoding, dir=os.path.dirname(filename), delete=False
58  ) as fdesc:
59  fdesc.write(utf8_data)
60  tmp_filename = fdesc.name
61  if not private:
62  os.fchmod(fdesc.fileno(), 0o644)
63  os.replace(tmp_filename, filename)
64  except OSError as error:
65  _LOGGER.exception("Saving file failed: %s", filename)
66  raise WriteError(error) from error
67  finally:
68  if os.path.exists(tmp_filename):
69  try:
70  os.remove(tmp_filename)
71  except OSError as err:
72  # If we are cleaning up then something else went wrong, so
73  # we should suppress likely follow-on errors in the cleanup
74  _LOGGER.error(
75  "File replacement cleanup failed for %s while saving %s: %s",
76  tmp_filename,
77  filename,
78  err,
79  )
None open(self, **Any kwargs)
Definition: lock.py:86
None write_utf8_file_atomic(str filename, bytes|str utf8_data, bool private=False, str mode="w")
Definition: file.py:22
None write_utf8_file(str filename, bytes|str utf8_data, bool private=False, str mode="w")
Definition: file.py:47