summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Feldmann <mail@tfeldmann.de>2022-08-17 18:38:55 +0200
committerThomas Feldmann <mail@tfeldmann.de>2022-08-17 18:38:55 +0200
commit750ec7b6a45f2ad13fd35b1eb3220311f564b570 (patch)
tree03cbde8a313500e669ea48ad95ea0df28f2f63e8
parent084e6200b6e7e6206ca6ea6051fe1769ea3ea1d2 (diff)
rename write_text to write
-rw-r--r--organize/actions/write.py120
-rw-r--r--tests/actions/test_write_text.py13
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:
+
+ """