Skip to content

Commit f3aa1d1

Browse files
committed
Add readlines method to Fs interface and implementations
- Add abstract readlines method to Fs class - Implement readlines in PathFs using file.readlines() - Implement readlines in RecordFs using splitlines(keepends=True) - Add comprehensive tests for both implementations - Test various scenarios: empty files, no final newline, different line endings
1 parent a707336 commit f3aa1d1

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

aws_doc_sdk_examples_tools/fs.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ def glob(self, path: Path, glob: str) -> Generator[Path, None, None]:
2727
def read(self, path: Path) -> str:
2828
pass
2929

30+
@abstractmethod
31+
def readlines(self, path: Path) -> List[str]:
32+
pass
33+
3034
@abstractmethod
3135
def write(self, path: Path, content: str):
3236
pass
@@ -52,6 +56,10 @@ def read(self, path: Path) -> str:
5256
with path.open("r") as file:
5357
return file.read()
5458

59+
def readlines(self, path: Path) -> List[str]:
60+
with path.open("r") as file:
61+
return file.readlines()
62+
5563
def write(self, path: Path, content: str):
5664
with path.open("w") as file:
5765
file.write(content)
@@ -87,6 +95,10 @@ def glob(self, path: Path, glob: str) -> Generator[Path, None, None]:
8795
def read(self, path: Path) -> str:
8896
return self.fs[path]
8997

98+
def readlines(self, path: Path) -> List[str]:
99+
content = self.fs[path]
100+
return content.splitlines(keepends=True)
101+
90102
def write(self, path: Path, content: str):
91103
base = str(path.parent)
92104
assert any(
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
"""
5+
Tests for the Fs interface, particularly the readlines functionality.
6+
"""
7+
8+
import pytest
9+
import tempfile
10+
from pathlib import Path
11+
from typing import List
12+
13+
from .fs import Fs, PathFs, RecordFs
14+
15+
16+
def assert_readlines_result(fs: Fs, path: Path, expected: List[str]):
17+
"""Generic assertion for readlines results."""
18+
lines = fs.readlines(path)
19+
assert lines == expected
20+
assert len(lines) == len(expected)
21+
22+
23+
def run_common_readlines_scenarios(fs: Fs, path_factory):
24+
"""Test common readlines scenarios for any Fs implementation."""
25+
# Basic multi-line content
26+
path = path_factory("Line 1\nLine 2\nLine 3\n")
27+
assert_readlines_result(fs, path, ["Line 1\n", "Line 2\n", "Line 3\n"])
28+
29+
# Empty file
30+
path = path_factory("")
31+
assert_readlines_result(fs, path, [])
32+
33+
# No final newline
34+
path = path_factory("Line 1\nLine 2")
35+
assert_readlines_result(fs, path, ["Line 1\n", "Line 2"])
36+
37+
# Single line
38+
path = path_factory("Single line\n")
39+
assert_readlines_result(fs, path, ["Single line\n"])
40+
41+
42+
class TestPathFs:
43+
"""Test PathFs implementation of readlines."""
44+
45+
def test_readlines_scenarios(self):
46+
"""Test various readlines scenarios with PathFs."""
47+
fs = PathFs()
48+
temp_files = []
49+
50+
def path_factory(content: str) -> Path:
51+
with tempfile.NamedTemporaryFile(
52+
mode="w", delete=False, suffix=".txt"
53+
) as f:
54+
f.write(content)
55+
path = Path(f.name)
56+
temp_files.append(path)
57+
return path
58+
59+
try:
60+
run_common_readlines_scenarios(fs, path_factory)
61+
finally:
62+
# Clean up temp files
63+
for path in temp_files:
64+
if path.exists():
65+
path.unlink()
66+
67+
68+
class TestRecordFs:
69+
"""Test RecordFs implementation of readlines."""
70+
71+
def test_readlines_scenarios(self):
72+
"""Test various readlines scenarios with RecordFs."""
73+
test_cases = [
74+
("Line 1\nLine 2\nLine 3\n", ["Line 1\n", "Line 2\n", "Line 3\n"]),
75+
("", []),
76+
("Line 1\nLine 2", ["Line 1\n", "Line 2"]),
77+
("Single line\n", ["Single line\n"]),
78+
]
79+
80+
for content, expected in test_cases:
81+
fs = RecordFs({Path("test.txt"): content})
82+
assert_readlines_result(fs, Path("test.txt"), expected)
83+
84+
def test_readlines_line_ending_variations(self):
85+
"""Test readlines with different line ending styles."""
86+
test_cases = [
87+
(
88+
"Line 1\r\nLine 2\r\nLine 3\r\n",
89+
["Line 1\r\n", "Line 2\r\n", "Line 3\r\n"],
90+
),
91+
("Line 1\nLine 2\r\nLine 3\n", ["Line 1\n", "Line 2\r\n", "Line 3\n"]),
92+
]
93+
94+
for content, expected in test_cases:
95+
fs = RecordFs({Path("test.txt"): content})
96+
assert_readlines_result(fs, Path("test.txt"), expected)

0 commit comments

Comments
 (0)