diff options
author | Thomas Feldmann <mail@tfeldmann.de> | 2022-08-17 18:38:55 +0200 |
---|---|---|
committer | Thomas Feldmann <mail@tfeldmann.de> | 2022-08-17 18:38:55 +0200 |
commit | 750ec7b6a45f2ad13fd35b1eb3220311f564b570 (patch) | |
tree | 03cbde8a313500e669ea48ad95ea0df28f2f63e8 | |
parent | 084e6200b6e7e6206ca6ea6051fe1769ea3ea1d2 (diff) |
rename write_text to write
-rw-r--r-- | organize/actions/write.py | 120 | ||||
-rw-r--r-- | tests/actions/test_write_text.py | 13 |
2 files changed, 133 insertions, 0 deletions
diff --git a/organize/actions/write.py b/organize/actions/write.py new file mode 100644 index 0000000..efeea15 --- /dev/null +++ b/organize/actions/write.py @@ -0,0 +1,120 @@ +import logging +from typing import Union + +from fs.base import FS +from fs.opener import manage_fs +from schema import Optional, Or + +from organize.utils import Template + +from ._utils import open_create_fs_path +from .action import Action + +logger = logging.getLogger(__name__) + +MODES = ( + "prepend", + "append", + "overwrite", +) + + +class Write(Action): + + """Write text to a file. + + If the specified path does not exist it will be created. + + Args: + msg (str): + The text that should be written. Supports templates. + + file (str): + The file `msg` should be written into. Supports templates. + + mode (str): + Can be either `append` (append text to the file), `prepend` (insert text as + first line) or `overwrite` (overwrite content with text). + Defaults to `append`. + + newline (str): + (Optional) Whether to append a newline to the given `text`. + Defaults to `true`. + + clear_before_first_write (bool): + (Optional) Clears the file before first appending / prepending text to it. + This happens only the first time write_file is run. If the rule filters + don't match anything the file is left as it is. + Defaults to `false`. + + filesystem (str): + (Optional) A pyfilesystem opener url of the filesystem the textfile is on. + If this is not given, the local filesystem is used. + """ + + name = "write" + arg_schema = Or( + { + "msg": str, + "path": str, + Optional("mode"): Or(*MODES), + Optional("newline"): bool, + Optional("clear_before_first_write"): bool, + Optional("filesystem"): object, + }, + ) + + def __init__( + self, + msg: str, + path: str, + mode: str = "append", + newline: bool = True, + clear_before_first_write: bool = False, + filesystem: Union[FS, str, None] = None, + ) -> None: + self.msg = Template.from_string(msg) + self.path = Template.from_string(path) + self.mode = mode.lower() + self.clear_before_first_write = clear_before_first_write + self.newline = newline + self.filesystem = filesystem or self.Meta.default_filesystem + + self._is_first_write = True + + if self.mode not in MODES: + raise ValueError("mode must be one of %s" % ", ".join(MODES)) + + def pipeline(self, args: dict, simulate: bool): + path = self.path.render(args) + msg = self.msg.render(args) + + dst_fs, dst_path = open_create_fs_path( + fs=self.filesystem, + path=path, + args=args, + simulate=simulate, + ) + + if self._is_first_write and self.clear_before_first_write: + self.print(f"Clearing file {dst_path}") + if not simulate: + dst_fs.create(dst_path, wipe=True) + + self.print(f'{path}: {self.mode} "{msg}"') + if self.newline: + msg += "\n" + + if not simulate: + with manage_fs(dst_fs): + if self.mode == "append": + dst_fs.appendtext(dst_path, msg) + elif self.mode == "prepend": + content = "" + if dst_fs.exists(dst_path): + content = dst_fs.readtext(dst_path) + dst_fs.writetext(dst_path, msg + content) + elif self.mode == "overwrite": + dst_fs.writetext(dst_path, msg) + + self._is_first_write = False diff --git a/tests/actions/test_write_text.py b/tests/actions/test_write_text.py new file mode 100644 index 0000000..3f25e10 --- /dev/null +++ b/tests/actions/test_write_text.py @@ -0,0 +1,13 @@ +from conftest import make_files + + +def test_append(testfs): + files = ["a.txt", "b.txt", "c.txt"] + make_files(testfs, files) + config = """ + rules: + - locations: . + actions: + - write_text: + + """ |