python3-cyberfusion-file-support 1.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,63 @@
1
+ Metadata-Version: 2.1
2
+ Name: python3-cyberfusion-file-support
3
+ Version: 1.1.1
4
+ Summary: Library for idempotent writing to files.
5
+ Home-page: https://vcs.cyberfusion.nl/shared/python3-cyberfusion-file-support
6
+ Author: Cyberfusion
7
+ Author-email: support@cyberfusion.io
8
+ Platform: linux
9
+ Description-Content-Type: text/markdown
10
+
11
+ # python3-cyberfusion-file-support
12
+
13
+ Library for idempotent writing to files.
14
+
15
+ # Install
16
+
17
+ ## PyPI
18
+
19
+ Run the following command to install the package from PyPI:
20
+
21
+ pip3 install python3-cyberfusion-file-support
22
+
23
+ ## Generic
24
+
25
+ Run the following command to create a source distribution:
26
+
27
+ python3 setup.py sdist
28
+
29
+ ## Debian
30
+
31
+ Run the following commands to build a Debian package:
32
+
33
+ mk-build-deps -i -t 'apt -o Debug::pkgProblemResolver=yes --no-install-recommends -y'
34
+ dpkg-buildpackage -us -uc
35
+
36
+ # Configure
37
+
38
+ No configuration is supported.
39
+
40
+ # Usage
41
+
42
+ ## Example
43
+
44
+ ```python
45
+ from cyberfusion.QueueSupport import Queue
46
+ from cyberfusion.FileSupport import DestinationFileReplacement
47
+
48
+ queue = Queue()
49
+
50
+ tmp_file = DestinationFileReplacement(
51
+ queue,
52
+ contents="foobar",
53
+ destination_file_path="/tmp/foobar.txt",
54
+ default_comment_character=None,
55
+ command=["true"],
56
+ )
57
+
58
+ print(tmp_file.differences)
59
+
60
+ tmp_file.add_copy_to_queue()
61
+
62
+ queue.process(preview=...)
63
+ ```
@@ -0,0 +1,53 @@
1
+ # python3-cyberfusion-file-support
2
+
3
+ Library for idempotent writing to files.
4
+
5
+ # Install
6
+
7
+ ## PyPI
8
+
9
+ Run the following command to install the package from PyPI:
10
+
11
+ pip3 install python3-cyberfusion-file-support
12
+
13
+ ## Generic
14
+
15
+ Run the following command to create a source distribution:
16
+
17
+ python3 setup.py sdist
18
+
19
+ ## Debian
20
+
21
+ Run the following commands to build a Debian package:
22
+
23
+ mk-build-deps -i -t 'apt -o Debug::pkgProblemResolver=yes --no-install-recommends -y'
24
+ dpkg-buildpackage -us -uc
25
+
26
+ # Configure
27
+
28
+ No configuration is supported.
29
+
30
+ # Usage
31
+
32
+ ## Example
33
+
34
+ ```python
35
+ from cyberfusion.QueueSupport import Queue
36
+ from cyberfusion.FileSupport import DestinationFileReplacement
37
+
38
+ queue = Queue()
39
+
40
+ tmp_file = DestinationFileReplacement(
41
+ queue,
42
+ contents="foobar",
43
+ destination_file_path="/tmp/foobar.txt",
44
+ default_comment_character=None,
45
+ command=["true"],
46
+ )
47
+
48
+ print(tmp_file.differences)
49
+
50
+ tmp_file.add_copy_to_queue()
51
+
52
+ queue.process(preview=...)
53
+ ```
@@ -0,0 +1,21 @@
1
+ [tool.isort]
2
+ profile = "black"
3
+ line_length = 79
4
+ known_first_party = ["cyberfusion"]
5
+ default_section = "THIRDPARTY"
6
+
7
+ [tool.black]
8
+ line-length = 79
9
+ exclude = '''
10
+ (
11
+ /(
12
+ \.eggs # exclude a few common directories in the
13
+ | \.git # root of the project
14
+ | \.hg
15
+ | \.mypy_cache
16
+ | \.tox
17
+ | \.venv
18
+ | venv
19
+ )/
20
+ )
21
+ '''
@@ -0,0 +1,12 @@
1
+ [aliases]
2
+ test = pytest
3
+
4
+ [tool:pytest]
5
+ norecursedirs = .git build dist *.egg __pycache__ .cache
6
+ testpaths = tests
7
+ junit_suite_name = python3-cyberfusion-file-support
8
+
9
+ [egg_info]
10
+ tag_build =
11
+ tag_date = 0
12
+
@@ -0,0 +1,21 @@
1
+ """A setuptools based setup module."""
2
+
3
+ from setuptools import setup
4
+
5
+ with open("README.md", "r", encoding="utf-8") as fh:
6
+ long_description = fh.read()
7
+
8
+ setup(
9
+ name="python3-cyberfusion-file-support",
10
+ version="1.1.1",
11
+ description="Library for idempotent writing to files.",
12
+ long_description=long_description,
13
+ long_description_content_type="text/markdown",
14
+ author="Cyberfusion",
15
+ author_email="support@cyberfusion.io",
16
+ url="https://vcs.cyberfusion.nl/shared/python3-cyberfusion-file-support",
17
+ platforms=["linux"],
18
+ packages=["cyberfusion.FileSupport"],
19
+ package_dir={"": "src"},
20
+ data_files=[],
21
+ )
@@ -0,0 +1,160 @@
1
+ """Classes for files."""
2
+
3
+ import difflib
4
+ import filecmp
5
+ import os
6
+ from typing import List, Optional, Union
7
+
8
+ from cyberfusion.Common import get_tmp_file
9
+ from cyberfusion.QueueSupport import Queue
10
+ from cyberfusion.QueueSupport.items.command import CommandItem
11
+ from cyberfusion.QueueSupport.items.copy import CopyItem
12
+ from cyberfusion.QueueSupport.items.unlink import UnlinkItem
13
+
14
+
15
+ class _DestinationFile:
16
+ """Represents destination file."""
17
+
18
+ def __init__(self, *, path: str) -> None:
19
+ """Set attributes."""
20
+ self.path = path
21
+
22
+ @property
23
+ def exists(self) -> bool:
24
+ """Get if exists."""
25
+ return os.path.exists(self.path)
26
+
27
+ @property
28
+ def contents(self) -> Optional[str]:
29
+ """Get contents."""
30
+ if self.exists:
31
+ with open(self.path, "r") as f:
32
+ return f.read()
33
+
34
+ return None
35
+
36
+
37
+ class DestinationFileReplacement:
38
+ """Represents file that will replace destination file."""
39
+
40
+ def __init__(
41
+ self,
42
+ queue: Queue,
43
+ *,
44
+ contents: Union[str, bytes],
45
+ destination_file_path: str,
46
+ default_comment_character: Optional[str] = None,
47
+ command: Optional[List[str]] = None,
48
+ reference: Optional[str] = None,
49
+ ) -> None:
50
+ """Set attributes.
51
+
52
+ 'default_comment_character' has no effect when 'contents' is not string.
53
+ """
54
+ self.queue = queue
55
+ self._contents = contents
56
+ self.default_comment_character = default_comment_character
57
+ self.command = command
58
+ self.reference = reference
59
+
60
+ self.tmp_path = get_tmp_file()
61
+ self.destination_file = _DestinationFile(path=destination_file_path)
62
+
63
+ self._write_to_tmp_file()
64
+
65
+ @property
66
+ def contents(self) -> Union[str, bytes]:
67
+ """Get contents."""
68
+ if not isinstance(self._contents, str):
69
+ return self._contents
70
+
71
+ if self._contents != "" and not self._contents.endswith(
72
+ "\n"
73
+ ): # Some programs require newline to consider last line completed
74
+ raise ValueError
75
+
76
+ if not self.default_comment_character:
77
+ return self._contents
78
+
79
+ default_comment = f"{self.default_comment_character} Update this file via your management interface.\n"
80
+ default_comment += f"{self.default_comment_character} Your changes will be overwritten.\n"
81
+ default_comment += "\n"
82
+
83
+ return default_comment + self._contents
84
+
85
+ def _write_to_tmp_file(self) -> None:
86
+ """Write contents to tmp file."""
87
+ if isinstance(self.contents, bytes):
88
+ open_mode = "wb"
89
+ else:
90
+ open_mode = "w"
91
+
92
+ with open(self.tmp_path, open_mode) as f:
93
+ f.write(self.contents)
94
+
95
+ @property
96
+ def changed(self) -> bool:
97
+ """Get if destination file will change."""
98
+ return not self.destination_file.exists or not filecmp.cmp(
99
+ self.tmp_path, self.destination_file.path
100
+ )
101
+
102
+ @property
103
+ def differences(self) -> List[str]:
104
+ """Get differences with destination file.
105
+
106
+ No differences are returned when contents is not string.
107
+ """
108
+ if not isinstance(self._contents, str):
109
+ return []
110
+
111
+ results = []
112
+
113
+ for line in difflib.unified_diff(
114
+ (
115
+ self.destination_file.contents.splitlines()
116
+ if self.destination_file.contents
117
+ else []
118
+ ),
119
+ self.contents.splitlines(), # type: ignore[arg-type]
120
+ fromfile=self.tmp_path,
121
+ tofile=self.destination_file.path,
122
+ lineterm="",
123
+ n=0,
124
+ ):
125
+ results.append(line)
126
+
127
+ return results
128
+
129
+ def add_to_queue(self) -> None:
130
+ """Add items for replacement to queue."""
131
+ if self.changed:
132
+ # Copy when changed and always unlink, instead of move when changed
133
+ # and unlink when changed. MoveItem copies metadata (which means
134
+ # mode etc. of destination file is incorrect, as set to the tmp file
135
+ # until corrected by later queue items). CopyItem does not copy
136
+ # metadata, so if the destination file already exists, its mode
137
+ # etc. is unchanged.
138
+
139
+ self.queue.add(
140
+ CopyItem(
141
+ source=self.tmp_path,
142
+ destination=self.destination_file.path,
143
+ reference=self.reference,
144
+ ),
145
+ )
146
+
147
+ if self.command:
148
+ self.queue.add(
149
+ CommandItem(
150
+ command=self.command, reference=self.reference
151
+ ),
152
+ )
153
+
154
+ self.queue.add(
155
+ UnlinkItem(
156
+ path=self.tmp_path,
157
+ hide_outcomes=True,
158
+ reference=self.reference,
159
+ ),
160
+ )
@@ -0,0 +1,63 @@
1
+ Metadata-Version: 2.1
2
+ Name: python3-cyberfusion-file-support
3
+ Version: 1.1.1
4
+ Summary: Library for idempotent writing to files.
5
+ Home-page: https://vcs.cyberfusion.nl/shared/python3-cyberfusion-file-support
6
+ Author: Cyberfusion
7
+ Author-email: support@cyberfusion.io
8
+ Platform: linux
9
+ Description-Content-Type: text/markdown
10
+
11
+ # python3-cyberfusion-file-support
12
+
13
+ Library for idempotent writing to files.
14
+
15
+ # Install
16
+
17
+ ## PyPI
18
+
19
+ Run the following command to install the package from PyPI:
20
+
21
+ pip3 install python3-cyberfusion-file-support
22
+
23
+ ## Generic
24
+
25
+ Run the following command to create a source distribution:
26
+
27
+ python3 setup.py sdist
28
+
29
+ ## Debian
30
+
31
+ Run the following commands to build a Debian package:
32
+
33
+ mk-build-deps -i -t 'apt -o Debug::pkgProblemResolver=yes --no-install-recommends -y'
34
+ dpkg-buildpackage -us -uc
35
+
36
+ # Configure
37
+
38
+ No configuration is supported.
39
+
40
+ # Usage
41
+
42
+ ## Example
43
+
44
+ ```python
45
+ from cyberfusion.QueueSupport import Queue
46
+ from cyberfusion.FileSupport import DestinationFileReplacement
47
+
48
+ queue = Queue()
49
+
50
+ tmp_file = DestinationFileReplacement(
51
+ queue,
52
+ contents="foobar",
53
+ destination_file_path="/tmp/foobar.txt",
54
+ default_comment_character=None,
55
+ command=["true"],
56
+ )
57
+
58
+ print(tmp_file.differences)
59
+
60
+ tmp_file.add_copy_to_queue()
61
+
62
+ queue.process(preview=...)
63
+ ```
@@ -0,0 +1,9 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.cfg
4
+ setup.py
5
+ src/cyberfusion/FileSupport/__init__.py
6
+ src/python3_cyberfusion_file_support.egg-info/PKG-INFO
7
+ src/python3_cyberfusion_file_support.egg-info/SOURCES.txt
8
+ src/python3_cyberfusion_file_support.egg-info/dependency_links.txt
9
+ src/python3_cyberfusion_file_support.egg-info/top_level.txt