Skip to content

Commit 22c4763

Browse files
OsOps::write method is corrected (#183)
LocalOperations - [BUG FIX] (read_write=true and truncate=false) writes to begging of a file - Preparation of data is added (verification/encoding/decoding/eol) RemoteOperations - Preparation of data is corrected (verification/encoding/decoding/eol) - Temp file is always opened with "w+"/"w+b" modes. Tests are added.
1 parent 4493d69 commit 22c4763

File tree

4 files changed

+201
-25
lines changed

4 files changed

+201
-25
lines changed

testgres/operations/local_ops.py

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -235,27 +235,54 @@ def write(self, filename, data, truncate=False, binary=False, read_and_write=Fal
235235
Args:
236236
filename: The file path where the data will be written.
237237
data: The data to be written to the file.
238-
truncate: If True, the file will be truncated before writing ('w' or 'wb' option);
239-
if False (default), data will be appended ('a' or 'ab' option).
240-
binary: If True, the data will be written in binary mode ('wb' or 'ab' option);
241-
if False (default), the data will be written in text mode ('w' or 'a' option).
242-
read_and_write: If True, the file will be opened with read and write permissions ('r+' option);
243-
if False (default), only write permission will be used ('w', 'a', 'wb', or 'ab' option)
238+
truncate: If True, the file will be truncated before writing ('w' option);
239+
if False (default), data will be appended ('a' option).
240+
binary: If True, the data will be written in binary mode ('b' option);
241+
if False (default), the data will be written in text mode.
242+
read_and_write: If True, the file will be opened with read and write permissions ('+' option);
243+
if False (default), only write permission will be used.
244244
"""
245-
# If it is a bytes str or list
246245
if isinstance(data, bytes) or isinstance(data, list) and all(isinstance(item, bytes) for item in data):
247246
binary = True
248-
mode = "wb" if binary else "w"
249-
if not truncate:
250-
mode = "ab" if binary else "a"
247+
248+
mode = "w" if truncate else "a"
249+
251250
if read_and_write:
252-
mode = "r+b" if binary else "r+"
251+
mode += "+"
252+
253+
# If it is a bytes str or list
254+
if binary:
255+
mode += "b"
256+
257+
assert type(mode) == str # noqa: E721
258+
assert mode != ""
253259

254260
with open(filename, mode) as file:
255261
if isinstance(data, list):
256-
file.writelines(data)
262+
data2 = [__class__._prepare_line_to_write(s, binary) for s in data]
263+
file.writelines(data2)
257264
else:
258-
file.write(data)
265+
data2 = __class__._prepare_data_to_write(data, binary)
266+
file.write(data2)
267+
268+
def _prepare_line_to_write(data, binary):
269+
data = __class__._prepare_data_to_write(data, binary)
270+
271+
if binary:
272+
assert type(data) == bytes # noqa: E721
273+
return data.rstrip(b'\n') + b'\n'
274+
275+
assert type(data) == str # noqa: E721
276+
return data.rstrip('\n') + '\n'
277+
278+
def _prepare_data_to_write(data, binary):
279+
if isinstance(data, bytes):
280+
return data if binary else data.decode()
281+
282+
if isinstance(data, str):
283+
return data if not binary else data.encode()
284+
285+
raise InvalidOperationException("Unknown type of data type [{0}].".format(type(data).__name__))
259286

260287
def touch(self, filename):
261288
"""

testgres/operations/remote_ops.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,6 @@ def write(self, filename, data, truncate=False, binary=False, read_and_write=Fal
278278
if not encoding:
279279
encoding = get_default_encoding()
280280
mode = "wb" if binary else "w"
281-
if not truncate:
282-
mode = "ab" if binary else "a"
283-
if read_and_write:
284-
mode = "r+b" if binary else "r+"
285281

286282
with tempfile.NamedTemporaryFile(mode=mode, delete=False) as tmp_file:
287283
# For scp the port is specified by a "-P" option
@@ -292,16 +288,12 @@ def write(self, filename, data, truncate=False, binary=False, read_and_write=Fal
292288
subprocess.run(scp_cmd, check=False) # The file might not exist yet
293289
tmp_file.seek(0, os.SEEK_END)
294290

295-
if isinstance(data, bytes) and not binary:
296-
data = data.decode(encoding)
297-
elif isinstance(data, str) and binary:
298-
data = data.encode(encoding)
299-
300291
if isinstance(data, list):
301-
data = [(s if isinstance(s, str) else s.decode(get_default_encoding())).rstrip('\n') + '\n' for s in data]
302-
tmp_file.writelines(data)
292+
data2 = [__class__._prepare_line_to_write(s, binary, encoding) for s in data]
293+
tmp_file.writelines(data2)
303294
else:
304-
tmp_file.write(data)
295+
data2 = __class__._prepare_data_to_write(data, binary, encoding)
296+
tmp_file.write(data2)
305297

306298
tmp_file.flush()
307299
scp_cmd = ['scp'] + scp_args + [tmp_file.name, f"{self.ssh_dest}:{filename}"]
@@ -313,6 +305,25 @@ def write(self, filename, data, truncate=False, binary=False, read_and_write=Fal
313305

314306
os.remove(tmp_file.name)
315307

308+
def _prepare_line_to_write(data, binary, encoding):
309+
data = __class__._prepare_data_to_write(data, binary, encoding)
310+
311+
if binary:
312+
assert type(data) == bytes # noqa: E721
313+
return data.rstrip(b'\n') + b'\n'
314+
315+
assert type(data) == str # noqa: E721
316+
return data.rstrip('\n') + '\n'
317+
318+
def _prepare_data_to_write(data, binary, encoding):
319+
if isinstance(data, bytes):
320+
return data if binary else data.decode(encoding)
321+
322+
if isinstance(data, str):
323+
return data if not binary else data.encode(encoding)
324+
325+
raise InvalidOperationException("Unknown type of data type [{0}].".format(type(data).__name__))
326+
316327
def touch(self, filename):
317328
"""
318329
Create a new file or update the access and modification times of an existing file on the remote server.

tests/test_local.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44
import re
5+
import tempfile
56

67
from testgres import ExecUtilException
78
from testgres import InvalidOperationException
@@ -273,3 +274,71 @@ def test_cwd(self):
273274

274275
# Comp result
275276
assert v == expectedValue
277+
278+
class tagWriteData001:
279+
def __init__(self, sign, source, cp_rw, cp_truncate, cp_binary, cp_data, result):
280+
self.sign = sign
281+
self.source = source
282+
self.call_param__rw = cp_rw
283+
self.call_param__truncate = cp_truncate
284+
self.call_param__binary = cp_binary
285+
self.call_param__data = cp_data
286+
self.result = result
287+
288+
sm_write_data001 = [
289+
tagWriteData001("A001", "1234567890", False, False, False, "ABC", "1234567890ABC"),
290+
tagWriteData001("A002", b"1234567890", False, False, True, b"ABC", b"1234567890ABC"),
291+
292+
tagWriteData001("B001", "1234567890", False, True, False, "ABC", "ABC"),
293+
tagWriteData001("B002", "1234567890", False, True, False, "ABC1234567890", "ABC1234567890"),
294+
tagWriteData001("B003", b"1234567890", False, True, True, b"ABC", b"ABC"),
295+
tagWriteData001("B004", b"1234567890", False, True, True, b"ABC1234567890", b"ABC1234567890"),
296+
297+
tagWriteData001("C001", "1234567890", True, False, False, "ABC", "1234567890ABC"),
298+
tagWriteData001("C002", b"1234567890", True, False, True, b"ABC", b"1234567890ABC"),
299+
300+
tagWriteData001("D001", "1234567890", True, True, False, "ABC", "ABC"),
301+
tagWriteData001("D002", "1234567890", True, True, False, "ABC1234567890", "ABC1234567890"),
302+
tagWriteData001("D003", b"1234567890", True, True, True, b"ABC", b"ABC"),
303+
tagWriteData001("D004", b"1234567890", True, True, True, b"ABC1234567890", b"ABC1234567890"),
304+
305+
tagWriteData001("E001", "\0001234567890\000", False, False, False, "\000ABC\000", "\0001234567890\000\000ABC\000"),
306+
tagWriteData001("E002", b"\0001234567890\000", False, False, True, b"\000ABC\000", b"\0001234567890\000\000ABC\000"),
307+
308+
tagWriteData001("F001", "a\nb\n", False, False, False, ["c", "d"], "a\nb\nc\nd\n"),
309+
tagWriteData001("F002", b"a\nb\n", False, False, True, [b"c", b"d"], b"a\nb\nc\nd\n"),
310+
311+
tagWriteData001("G001", "a\nb\n", False, False, False, ["c\n\n", "d\n"], "a\nb\nc\nd\n"),
312+
tagWriteData001("G002", b"a\nb\n", False, False, True, [b"c\n\n", b"d\n"], b"a\nb\nc\nd\n"),
313+
]
314+
315+
@pytest.fixture(
316+
params=sm_write_data001,
317+
ids=[x.sign for x in sm_write_data001],
318+
)
319+
def write_data001(self, request):
320+
assert isinstance(request, pytest.FixtureRequest)
321+
assert type(request.param) == __class__.tagWriteData001 # noqa: E721
322+
return request.param
323+
324+
def test_write(self, write_data001):
325+
assert type(write_data001) == __class__.tagWriteData001 # noqa: E721
326+
327+
mode = "w+b" if write_data001.call_param__binary else "w+"
328+
329+
with tempfile.NamedTemporaryFile(mode=mode, delete=True) as tmp_file:
330+
tmp_file.write(write_data001.source)
331+
tmp_file.flush()
332+
333+
self.operations.write(
334+
tmp_file.name,
335+
write_data001.call_param__data,
336+
read_and_write=write_data001.call_param__rw,
337+
truncate=write_data001.call_param__truncate,
338+
binary=write_data001.call_param__binary)
339+
340+
tmp_file.seek(0)
341+
342+
s = tmp_file.read()
343+
344+
assert s == write_data001.result

tests/test_remote.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44
import re
5+
import tempfile
56

67
from testgres import ExecUtilException
78
from testgres import InvalidOperationException
@@ -402,3 +403,71 @@ def test_cwd(self):
402403
assert v is not None
403404
assert type(v) == str # noqa: E721
404405
assert v != ""
406+
407+
class tagWriteData001:
408+
def __init__(self, sign, source, cp_rw, cp_truncate, cp_binary, cp_data, result):
409+
self.sign = sign
410+
self.source = source
411+
self.call_param__rw = cp_rw
412+
self.call_param__truncate = cp_truncate
413+
self.call_param__binary = cp_binary
414+
self.call_param__data = cp_data
415+
self.result = result
416+
417+
sm_write_data001 = [
418+
tagWriteData001("A001", "1234567890", False, False, False, "ABC", "1234567890ABC"),
419+
tagWriteData001("A002", b"1234567890", False, False, True, b"ABC", b"1234567890ABC"),
420+
421+
tagWriteData001("B001", "1234567890", False, True, False, "ABC", "ABC"),
422+
tagWriteData001("B002", "1234567890", False, True, False, "ABC1234567890", "ABC1234567890"),
423+
tagWriteData001("B003", b"1234567890", False, True, True, b"ABC", b"ABC"),
424+
tagWriteData001("B004", b"1234567890", False, True, True, b"ABC1234567890", b"ABC1234567890"),
425+
426+
tagWriteData001("C001", "1234567890", True, False, False, "ABC", "1234567890ABC"),
427+
tagWriteData001("C002", b"1234567890", True, False, True, b"ABC", b"1234567890ABC"),
428+
429+
tagWriteData001("D001", "1234567890", True, True, False, "ABC", "ABC"),
430+
tagWriteData001("D002", "1234567890", True, True, False, "ABC1234567890", "ABC1234567890"),
431+
tagWriteData001("D003", b"1234567890", True, True, True, b"ABC", b"ABC"),
432+
tagWriteData001("D004", b"1234567890", True, True, True, b"ABC1234567890", b"ABC1234567890"),
433+
434+
tagWriteData001("E001", "\0001234567890\000", False, False, False, "\000ABC\000", "\0001234567890\000\000ABC\000"),
435+
tagWriteData001("E002", b"\0001234567890\000", False, False, True, b"\000ABC\000", b"\0001234567890\000\000ABC\000"),
436+
437+
tagWriteData001("F001", "a\nb\n", False, False, False, ["c", "d"], "a\nb\nc\nd\n"),
438+
tagWriteData001("F002", b"a\nb\n", False, False, True, [b"c", b"d"], b"a\nb\nc\nd\n"),
439+
440+
tagWriteData001("G001", "a\nb\n", False, False, False, ["c\n\n", "d\n"], "a\nb\nc\nd\n"),
441+
tagWriteData001("G002", b"a\nb\n", False, False, True, [b"c\n\n", b"d\n"], b"a\nb\nc\nd\n"),
442+
]
443+
444+
@pytest.fixture(
445+
params=sm_write_data001,
446+
ids=[x.sign for x in sm_write_data001],
447+
)
448+
def write_data001(self, request):
449+
assert isinstance(request, pytest.FixtureRequest)
450+
assert type(request.param) == __class__.tagWriteData001 # noqa: E721
451+
return request.param
452+
453+
def test_write(self, write_data001):
454+
assert type(write_data001) == __class__.tagWriteData001 # noqa: E721
455+
456+
mode = "w+b" if write_data001.call_param__binary else "w+"
457+
458+
with tempfile.NamedTemporaryFile(mode=mode, delete=True) as tmp_file:
459+
tmp_file.write(write_data001.source)
460+
tmp_file.flush()
461+
462+
self.operations.write(
463+
tmp_file.name,
464+
write_data001.call_param__data,
465+
read_and_write=write_data001.call_param__rw,
466+
truncate=write_data001.call_param__truncate,
467+
binary=write_data001.call_param__binary)
468+
469+
tmp_file.seek(0)
470+
471+
s = tmp_file.read()
472+
473+
assert s == write_data001.result

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy