From b13d2854bd4c5c61bd0fc70d780cb85d510153a9 Mon Sep 17 00:00:00 2001 From: "d.kovalenko" Date: Wed, 8 Jul 2026 14:16:50 +0300 Subject: [PATCH] OsOperations::touch is corrected Declaration: def touch(self, filename: str) -> None: LocalOperations: - uses pathlib.Path(filename).touch(exist_ok=True) Test is updated, too. --- src/local_ops.py | 12 ++++++------ src/os_ops.py | 4 +++- src/remote_ops.py | 2 +- tests/test_os_ops_common.py | 26 ++++++++++++++++++++++++-- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/local_ops.py b/src/local_ops.py index 7d3d440..b044837 100644 --- a/src/local_ops.py +++ b/src/local_ops.py @@ -18,6 +18,7 @@ import copy import signal as os_signal import datetime +import pathlib from .exceptions import ExecUtilException from .exceptions import InvalidOperationException @@ -578,17 +579,16 @@ def _prepare_data_to_write( raise InvalidOperationException("Unknown type of data type [{0}].".format(type(data).__name__)) - def touch(self, filename): + def touch(self, filename: str) -> None: """ Create a new file or update the access and modification times of an existing file. Args: filename (str): The name of the file to touch. - - This method behaves as the 'touch' command in Unix. It's equivalent to calling 'touch filename' in the shell. """ - # cross-python touch(). It is vulnerable to races, but who cares? - with open(filename, "a"): - os.utime(filename, None) + assert type(filename) is str + assert filename != "" + + pathlib.Path(filename).touch(exist_ok=True) return def read( diff --git a/src/os_ops.py b/src/os_ops.py index dc41e3b..1c92480 100644 --- a/src/os_ops.py +++ b/src/os_ops.py @@ -224,7 +224,9 @@ def write( raise NotImplementedError() - def touch(self, filename): + def touch(self, filename: str) -> None: + assert type(filename) is str + assert filename != "" raise NotImplementedError() def read( diff --git a/src/remote_ops.py b/src/remote_ops.py index 3a59bf4..c46fbea 100644 --- a/src/remote_ops.py +++ b/src/remote_ops.py @@ -765,7 +765,7 @@ def _single_chunk_to_bytes( raise InvalidOperationException("Unknown type of data type [{0}].".format(type(data).__name__)) - def touch(self, filename): + def touch(self, filename: str) -> None: """ Create a new file or update the access and modification times of an existing file on the remote server. diff --git a/tests/test_os_ops_common.py b/tests/test_os_ops_common.py index ec2654d..afbe405 100644 --- a/tests/test_os_ops_common.py +++ b/tests/test_os_ops_common.py @@ -1562,25 +1562,47 @@ def test_write( def test_touch( self, os_ops_descr: OsOpsDescr, + name_with_surprize: tagNameWithSurprize, ): """ Test touch for creating a new file or updating access and modification times of an existing file. """ assert type(os_ops_descr) is OsOpsDescr assert isinstance(os_ops_descr.os_ops, OsOperations) + assert type(name_with_surprize) is __class__.tagNameWithSurprize os_ops = os_ops_descr.os_ops assert isinstance(os_ops, OsOperations) - filename = os_ops.mkstemp() + tmpdir = os_ops.mkdtemp() - # TODO: this test does not check the result of 'touch' command! + filename = os_ops.build_path(tmpdir, name_with_surprize.value) os_ops.touch(filename) + assert os_ops.path_exists(filename) assert os_ops.isfile(filename) + stat1 = os_ops.get_file_stat(filename) + assert type(stat1) is dict + + time.sleep(1.1) + + os_ops.touch(filename) + + stat2 = os_ops.get_file_stat(filename) + assert type(stat2) is dict + + mtime1 = stat1[os_ops.C_FILE_STAT_PROP__MTIME] + mtime2 = stat2[os_ops.C_FILE_STAT_PROP__MTIME] + + assert type(mtime1) is datetime.datetime + assert type(mtime2) is datetime.datetime + + assert mtime1 < mtime2 + os_ops.remove_file(filename) + os_ops.rmdir(tmpdir) return def test_is_port_free__true(