From ce08d5b99afe2063a1018ab67d5f9902792a00ca Mon Sep 17 00:00:00 2001 From: Robert Smallshire Date: Tue, 12 May 2015 10:59:09 +0200 Subject: [PATCH] Adds tests for textual reel header with arbitrary content. Removes seek() calls from write_textual_reel_header() and write_binary_reel_header(). --- segpy/toolkit.py | 9 ++----- segpy/writer.py | 2 +- test/test_roundtrip.py | 57 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/segpy/toolkit.py b/segpy/toolkit.py index d519191..a741afb 100644 --- a/segpy/toolkit.py +++ b/segpy/toolkit.py @@ -576,7 +576,7 @@ def parse_template(template): def write_textual_reel_header(fh, lines, encoding): - """Write the SEG Y card image header, also known as the textual header + """Write the SEG Y card image header, also known as the textual header. Args: fh: A file-like object open in binary mode positioned such that the @@ -594,7 +594,7 @@ def write_textual_reel_header(fh, lines, encoding): warning. Any excess lines over CARDS_PER_HEADER will be discarded. Short or omitted lines will be padded with spaces. - encoding: Typically 'cp037' for EBCDIC or 'ascii' for ASCII. + encoding: Either 'cp037' for EBCDIC or 'ascii' for ASCII. Post-condition: The file pointer in fh will be positioned at the first byte following the textual @@ -607,16 +607,12 @@ def write_textual_reel_header(fh, lines, encoding): if not is_supported_encoding(encoding): raise UnsupportedEncodingError("Writing textual reel header", encoding) - fh.seek(0) - padded_lines = [line.encode(encoding).ljust(CARD_LENGTH, ' '.encode(encoding))[:CARD_LENGTH] for line in pad(lines, padding='', size=CARDS_PER_HEADER)] joined_header = EMPTY_BYTE_STRING.join(padded_lines) assert len(joined_header) == 3200 fh.write(joined_header) - fh.seek(TEXTUAL_HEADER_NUM_BYTES) - def write_binary_reel_header(fh, binary_reel_header, endian='>'): """Write the binary_reel_header to the given file-like object. @@ -633,7 +629,6 @@ def write_binary_reel_header(fh, binary_reel_header, endian='>'): header_packer = make_header_packer(type(binary_reel_header), endian) buffer = header_packer.pack(binary_reel_header) fh.write(buffer) - fh.seek(REEL_HEADER_NUM_BYTES) def format_extended_textual_header(text, encoding, include_text_stop=False): diff --git a/segpy/writer.py b/segpy/writer.py index 54656b8..62c3b4f 100644 --- a/segpy/writer.py +++ b/segpy/writer.py @@ -14,7 +14,7 @@ def write_segy(fh, progress=None): """ Args: - fh: A file-like object open for binary write. + fh: A file-like object open for binary write, positioned to write the textual reel header. seg_y_data: An object from which the headers and trace_samples data can be retrieved. Requires the following properties and methods: diff --git a/test/test_roundtrip.py b/test/test_roundtrip.py index f202302..86cdd05 100644 --- a/test/test_roundtrip.py +++ b/test/test_roundtrip.py @@ -1,12 +1,15 @@ +from itertools import zip_longest import unittest from hypothesis import given from io import BytesIO from hypothesis.specifiers import sampled_from from segpy.binary_reel_header import BinaryReelHeader +from segpy.encoding import ASCII, EBCDIC from segpy.header import are_equal -from segpy.toolkit import write_binary_reel_header, read_binary_reel_header -from test.strategies import header +from segpy.toolkit import write_binary_reel_header, read_binary_reel_header, write_textual_reel_header, \ + read_textual_reel_header, CARDS_PER_HEADER, CARD_LENGTH +from test.strategies import header, multiline_ascii_encodable_text class TestBinaryReelHeader(unittest.TestCase): @@ -16,9 +19,55 @@ class TestBinaryReelHeader(unittest.TestCase): def test_roundtrip(self, write_header, endian): with BytesIO() as write_stream: write_binary_reel_header(write_stream, write_header, endian) - written_steam = write_stream.getvalue() + written_stream = write_stream.getvalue() - with BytesIO(written_steam) as read_stream: + with BytesIO(written_stream) as read_stream: read_header = read_binary_reel_header(read_stream, endian) self.assertTrue(are_equal(write_header, read_header)) + + +class TestTextualReelHeader(unittest.TestCase): + + @given(multiline_ascii_encodable_text(0, CARDS_PER_HEADER), + sampled_from([ASCII, EBCDIC])) + def test_roundtrip(self, write_header_text, encoding): + write_header_lines = write_header_text.splitlines() + with BytesIO() as write_stream: + write_textual_reel_header(write_stream, write_header_lines, encoding) + written_stream = write_stream.getvalue() + + with BytesIO(written_stream) as read_stream: + read_header_lines = read_textual_reel_header(read_stream, encoding) + + for written_line, read_line in zip_longest(write_header_lines[:CARDS_PER_HEADER], + read_header_lines, + fillvalue=""): + self.assertEqual(written_line[:CARD_LENGTH].rstrip().ljust(CARD_LENGTH), + read_line) + + @given(multiline_ascii_encodable_text(0, CARDS_PER_HEADER), + sampled_from([ASCII, EBCDIC])) + def test_header_num_lines(self, write_header_text, encoding): + write_header_lines = write_header_text.splitlines() + with BytesIO() as write_stream: + write_textual_reel_header(write_stream, write_header_lines, encoding) + written_stream = write_stream.getvalue() + + with BytesIO(written_stream) as read_stream: + read_header_lines = read_textual_reel_header(read_stream, encoding) + + self.assertEqual(len(read_header_lines), CARDS_PER_HEADER) + + @given(multiline_ascii_encodable_text(0, CARDS_PER_HEADER), + sampled_from([ASCII, EBCDIC])) + def test_header_line_length(self, write_header_text, encoding): + write_header_lines = write_header_text.splitlines() + with BytesIO() as write_stream: + write_textual_reel_header(write_stream, write_header_lines, encoding) + written_stream = write_stream.getvalue() + + with BytesIO(written_stream) as read_stream: + read_header_lines = read_textual_reel_header(read_stream, encoding) + + self.assertTrue(all(len(line) == CARD_LENGTH for line in read_header_lines)) \ No newline at end of file