Skip to content

Commit

Permalink
Merge branch 'master' into bug_xfer_default
Browse files Browse the repository at this point in the history
  • Loading branch information
tangkong authored Sep 19, 2023
2 parents e1bc7b8 + d7594fe commit 0b4780d
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 14 deletions.
23 changes: 23 additions & 0 deletions docs/source/upcoming_release_notes/304-remove_temporary_file.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
304 remove_temporary_file
#################

API Changes
-----------
- N/A

Features
--------
- N/A

Bugfixes
--------
- N/A

Maintenance
-----------
- Adds error handling for the temporary file created when initializing a json backend object.
- Changes format of temporary file name generation to contain only a unique hash.

Contributors
------------
- laura-king
28 changes: 14 additions & 14 deletions happi/backends/json_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
Backend implemenation using the ``simplejson`` package.
"""
import contextlib
import getpass
import logging
import math
import os
import os.path
import re
import shutil
import time
import uuid
from typing import Any, Callable, Optional, Union

Expand Down Expand Up @@ -138,27 +136,29 @@ def store(self, db: dict[str, ItemMeta]) -> None:
Dictionary to store in JSON.
"""
temp_path = self._temp_path()

with open(temp_path, 'w') as fd:
json.dump(db, fd, sort_keys=True, indent=4)

if os.path.exists(self.path):
shutil.copymode(self.path, temp_path)
shutil.move(temp_path, self.path)
try:
with open(temp_path, 'w') as fd:
json.dump(db, fd, sort_keys=True, indent=4)

if os.path.exists(self.path):
shutil.copymode(self.path, temp_path)
shutil.move(temp_path, self.path)
except BaseException as ex:
logger.debug('JSON db move failed: %s', ex, exc_info=ex)
# remove temporary file
if os.path.exists(temp_path):
os.remove(temp_path)
raise

def _temp_path(self) -> str:
"""
Return a temporary path to write the json file to during "store".
Includes a username and a timestamp for sorting
(in the cases where the temp file isn't cleaned up)
and a hash for uniqueness
Includes a hash for uniqueness
(in the cases where multiple temp files are written at once).
"""
directory = os.path.dirname(self.path)
filename = (
f".{getpass.getuser()}"
f"_{int(time.time())}"
f"_{str(uuid.uuid4())[:8]}"
f"_{os.path.basename(self.path)}"
)
Expand Down
19 changes: 19 additions & 0 deletions happi/tests/test_backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,25 @@ def test_json_tempfile_uniqueness():
assert len(set(tempfiles)) == len(tempfiles)


def test_json_tempfile_remove(monkeypatch):
# Set consistent temppath
jb = JSONBackend("testing.json", initialize=False)
temp_path = jb._temp_path()
jb._temp_path = lambda: temp_path

# Ensure file is created, then throw error through patching
def shutil_move_patch(*args, **kwargs):
assert os.path.isfile(os.path.join(os.getcwd(), temp_path))
raise RuntimeError('Simulated testing error.')

monkeypatch.setattr('shutil.move', shutil_move_patch)

# Test, and ensure file is deleted appropriately
with pytest.raises(RuntimeError):
jb.initialize()
assert os.path.exists(temp_path) is False


@requires_questionnaire
def test_qs_find(mockqsbackend):
assert len(list(mockqsbackend.find(dict(beamline='TST')))) == 14
Expand Down

0 comments on commit 0b4780d

Please sign in to comment.