diff --git a/ops/testing.py b/ops/testing.py index 9710e6098..9fd0f7d6c 100755 --- a/ops/testing.py +++ b/ops/testing.py @@ -2592,7 +2592,11 @@ def push( elif isinstance(source, bytes): file_path.write_bytes(source) else: - with file_path.open('wb' if encoding is None else 'w', encoding=encoding) as f: + # If source is binary, open file in binary mode and ignore encoding param + is_binary = isinstance(source.read(0), bytes) + open_mode = 'wb' if is_binary else 'w' + open_encoding = None if is_binary else encoding + with file_path.open(open_mode, encoding=open_encoding) as f: shutil.copyfileobj(cast(IOBase, source), cast(IOBase, f)) os.chmod(file_path, permissions) except FileNotFoundError as e: diff --git a/test/test_testing.py b/test/test_testing.py index e7e07941b..8db8587db 100644 --- a/test/test_testing.py +++ b/test/test_testing.py @@ -3998,6 +3998,22 @@ def _test_push_and_pull_data(self, original_data, encoding, stream_class): received_data = infile.read() self.assertEqual(original_data, received_data) + def test_push_bytes_ignore_encoding(self): + # push() encoding param should be ignored if source is bytes + client = self.client + client.push(f"{self.prefix}/test", b'\x00\x01', encoding='utf-8') + with client.pull(f"{self.prefix}/test", encoding=None) as infile: + received_data = infile.read() + self.assertEqual(received_data, b'\x00\x01') + + def test_push_bytesio_ignore_encoding(self): + # push() encoding param should be ignored if source is binary stream + client = self.client + client.push(f"{self.prefix}/test", io.BytesIO(b'\x00\x01'), encoding='utf-8') + with client.pull(f"{self.prefix}/test", encoding=None) as infile: + received_data = infile.read() + self.assertEqual(received_data, b'\x00\x01') + def test_push_and_pull_larger_file(self): # Intent: to ensure things work appropriately with larger files. # Larger files may be sent/received in multiple chunks; this should help for