Skip to content
This repository was archived by the owner on Apr 4, 2024. It is now read-only.

Trickybrain Creating the LineReader file #14

Merged
merged 25 commits into from
Feb 28, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
50c908b
make some changes to edwin-pr
Trickybrain Feb 22, 2024
041af02
Resolved merge conflicts
Trickybrain Feb 22, 2024
f4dfcce
Trickybrain Adding LineReader
Trickybrain Feb 22, 2024
3d675eb
Merge branch 'main' into Trickybrain-LineReader
Trickybrain Feb 22, 2024
9fa6352
Make changes to LineReader, fixing the type issue
Trickybrain Feb 22, 2024
5805966
Merge branch 'Trickybrain-LineReader' of https://github.com/Trickybra…
Trickybrain Feb 22, 2024
2005fdb
Make changes to assigned in python
Trickybrain Feb 22, 2024
888f072
Line Reader Translation
Trickybrain Feb 27, 2024
0759e42
Merge branch 'main' into Trickybrain-LineReader
Trickybrain Feb 27, 2024
74a22fb
importing LineReader at init
Trickybrain Feb 27, 2024
15546f1
Merge branch 'Trickybrain-LineReader' of https://github.com/Trickybra…
Trickybrain Feb 27, 2024
4881e0f
Make changes to LineReader
Trickybrain Feb 27, 2024
2427d97
Make changes to LineReader
Trickybrain Feb 27, 2024
2ac95ec
Merge branch 'main' into Trickybrain-LineReader
Trickybrain Feb 27, 2024
419a64b
Make changes to linereader test
Trickybrain Feb 27, 2024
fe9adc7
Merge branch 'Trickybrain-LineReader' of https://github.com/Trickybra…
Trickybrain Feb 27, 2024
ef49c27
Make changes to LineReader
Trickybrain Feb 27, 2024
013a094
Make changes to the errors
Trickybrain Feb 27, 2024
2d06b69
Merge branch 'main' into Trickybrain-LineReader
Trickybrain Feb 27, 2024
c78c424
Make change LineReader
Trickybrain Feb 27, 2024
5ddbbd3
Merge branch 'Trickybrain-LineReader' of https://github.com/Trickybra…
Trickybrain Feb 27, 2024
4596ba9
Make changes to LineReader and rename LineReader_test
Trickybrain Feb 27, 2024
66aa871
Make detect_newline_type private
Trickybrain Feb 28, 2024
aab9d49
Make changes to detect new line and add get line number
Trickybrain Feb 28, 2024
ab1fe76
We want things to be as private as possible. private is two underscor…
nedtwigg Feb 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions python/selfie-lib/selfie_lib/LineReader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from typing import Optional, Union
import io

class LineTerminatorReader(io.BufferedReader):
"""Overrides read operations to detect carriage returns."""
def __init__(self, reader: io.TextIOWrapper) -> None:
super().__init__(reader.buffer)
self._unix_newlines = True

def read(self, size: int = -1) -> bytes:
chunk = super().read(size)
if b'\r' in chunk:
self._unix_newlines = False
return chunk

def unix_newlines(self) -> bool:
"""Check if the newlines are Unix style."""
return self._unix_newlines

class LineTerminatorAware(io.TextIOWrapper):
"""Keeps track of the first line to determine newline style."""
def __init__(self, reader: LineTerminatorReader) -> None:
super().__init__(reader, encoding='utf-8')
self._first_line: Optional[str] = self.readline()

def readline(self, limit: int = -1) -> str:
if self._first_line is not None:
result, self._first_line = self._first_line, None
return result
return super().readline(limit)

class LineReader:
"""A reader that is aware of line terminators and line numbers."""
def __init__(self, reader: Union[io.StringIO, io.BufferedReader]) -> None:
self._reader = LineTerminatorAware(LineTerminatorReader(reader))

@staticmethod
def for_string(content: str) -> 'LineReader':
"""Create a LineReader for string content."""
return LineReader(io.StringIO(content))

@staticmethod
def for_binary(content: bytes) -> 'LineReader':
"""Create a LineReader for binary content."""
return LineReader(io.BufferedReader(io.BytesIO(content)))

def get_line_number(self) -> int:
"""Get the current line number."""
# Assuming a way to track line numbers or using a wrapper that does.
# This is a placeholder as Python's io does not provide a direct lineno attribute.
return 0

def read_line(self) -> Optional[str]:
"""Read the next line from the reader."""
return self._reader.readline()

def unix_newlines(self) -> bool:
"""Check if the reader uses Unix newlines."""
return self._reader.unix_newlines()
2 changes: 2 additions & 0 deletions python/selfie-lib/selfie_lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
from .selina import get_interesting_fact as get_interesting_fact
from .harvir import silly_addition as silly_addition
from .edwin import simple_subtraction as simple_subtraction
from .LineReader import LineReader as LineReader
from .Slice import Slice as Slice

42 changes: 42 additions & 0 deletions python/selfie-lib/tests/lineReaderTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from selfie_lib import LineReader

def test_should_find_unix_separator_from_binary():
reader = LineReader.for_binary(b"This is a new line\n")
assert reader.unix_newlines() == True
assert reader.read_line() == "This is a new line"

def test_should_find_windows_separator_from_binary():
reader = LineReader.for_binary(b"This is a new line\r\n")
assert reader.unix_newlines() == False
assert reader.read_line() == "This is a new line"

def test_should_find_unix_separator_from_string():
reader = LineReader.for_string("This is a new line\n")
assert reader.unix_newlines() == True
assert reader.read_line() == "This is a new line"

def test_should_find_windows_separator_from_string():
reader = LineReader.for_string("This is a new line\r\n")
assert reader.unix_newlines() == False
assert reader.read_line() == "This is a new line"

def test_should_get_unix_line_separator_when_there_is_none():
reader = LineReader.for_binary(b"This is a new line")
assert reader.unix_newlines() == True
assert reader.read_line() == "This is a new line"

def test_should_read_next_line_without_problem():
reader = LineReader.for_binary(b"First\r\nSecond\r\n")
assert reader.unix_newlines() == False
assert reader.read_line() == "First"
assert reader.unix_newlines() == False
assert reader.read_line() == "Second"
assert reader.unix_newlines() == False

def test_should_use_first_line_separator_and_ignore_next():
reader = LineReader.for_binary(b"First\r\nAnother separator\n")
assert reader.unix_newlines() == False
assert reader.read_line() == "First"
assert reader.unix_newlines() == False
assert reader.read_line() == "Another separator"
assert reader.unix_newlines() == False