Skip to content

Commit 3534448

Browse files
committed
Fixed issue where idents were being stripped from the start of lines in StringList, and added some missing methods.
1 parent 2eaaa5f commit 3534448

File tree

2 files changed

+128
-13
lines changed

2 files changed

+128
-13
lines changed

domdf_python_tools/stringlist.py

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@
2828
from typing import Any, Iterable, Iterator, List, Tuple, Union, cast, overload
2929

3030
# 3rd party
31-
from typing_extensions import Protocol
31+
from typing_extensions import Protocol, runtime_checkable
3232

3333
# this package
3434
from domdf_python_tools.utils import convert_indents
3535

3636
__all__ = ["String", "Indent", "StringList"]
3737

3838

39+
@runtime_checkable
3940
class String(Protocol):
4041
"""
4142
Protocol for classes that implement ``__str__``.
@@ -134,12 +135,12 @@ def __init__(self, iterable: Iterable[String] = (), convert_indents: bool = Fals
134135
if isinstance(iterable, str):
135136
iterable = iterable.split("\n")
136137

137-
super().__init__([str(x).strip() for x in iterable])
138138
self.indent = Indent()
139139
self.convert_indents = convert_indents
140+
super().__init__([self._make_line(str(x)) for x in iterable])
140141

141142
def _make_line(self, line: str) -> str:
142-
if not str(self.indent).strip(" \t") and self.convert_indents:
143+
if not str(self.indent_type).strip(" \t") and self.convert_indents:
143144
if self.indent_type == '\t':
144145
line = convert_indents(line, tab_width=1, from_=' ', to='\t')
145146
else: # pragma: no cover
@@ -149,17 +150,44 @@ def _make_line(self, line: str) -> str:
149150

150151
def append(self, line: String) -> None:
151152
"""
152-
Append a line to the end of the StringList.
153+
Append a line to the end of the :class:`~domdf_python_tools.stringlist.StringList`.
153154
154155
:param line:
155156
"""
156157

157158
for inner_line in str(line).split("\n"):
158159
super().append(self._make_line(inner_line))
159160

161+
def extend(self, iterable: Iterable[String]) -> None:
162+
"""
163+
Extend the :class:`~domdf_python_tools.stringlist.StringList` with lines from ``iterable``.
164+
165+
:param iterable: An iterable of string-like objects to add to the end of the
166+
:class:`~domdf_python_tools.stringlist.StringList`.
167+
"""
168+
169+
for line in iterable:
170+
self.append(line)
171+
172+
def copy(self) -> "StringList":
173+
"""
174+
Returns a shallow copy of the :class:`~domdf_python_tools.stringlist.StringList`.
175+
176+
Equivalent to ``a[:]``.
177+
"""
178+
179+
return self.__class__(super().copy())
180+
181+
def count_blanklines(self) -> int:
182+
"""
183+
Returns a count of the blank lines in the :class:`~domdf_python_tools.stringlist.StringList`.
184+
"""
185+
186+
return self.count('')
187+
160188
def insert(self, index: int, line: String) -> None:
161189
"""
162-
Insert a line into the StringList at the given position.
190+
Insert a line into the :class:`~domdf_python_tools.stringlist.StringList` at the given position.
163191
164192
:param index:
165193
:param line:
@@ -240,7 +268,7 @@ def set_indent_size(self, size: int = 0):
240268
"""
241269
Sets the size of the indent to insert at the beginning of new lines.
242270
243-
:param size:
271+
:param size: The indent size to use for new lines.
244272
"""
245273

246274
self.indent.size = int(size)
@@ -249,7 +277,7 @@ def set_indent_type(self, indent_type: str = "\t"):
249277
"""
250278
Sets the type of the indent to insert at the beginning of new lines.
251279
252-
:param indent_type:
280+
:param indent_type: The type of indent to use for new lines.
253281
"""
254282

255283
self.indent.type = str(indent_type)
@@ -258,8 +286,8 @@ def set_indent(self, indent: Union[String, Indent], size: int = 0):
258286
"""
259287
Sets the indent to insert at the beginning of new lines.
260288
261-
:param indent:
262-
:param size:
289+
:param indent: The :class:`~.Indent` to use for new lines, or the indent type.
290+
:param size: If ``indent`` is an indent type, the indent size to use for new lines.
263291
"""
264292

265293
if isinstance(indent, Indent):
@@ -330,8 +358,8 @@ def with_indent(self, indent: Union[String, Indent], size: int = 0):
330358
>>> with sl.with_indent(" ", 1):
331359
... sl.append("Hello World")
332360
333-
:param indent:
334-
:param size:
361+
:param indent: The :class:`~.Indent` to use within the ``with`` block, or the indent type.
362+
:param size: If ``indent`` is an indent type, the indent size to use within the ``with`` block.
335363
"""
336364

337365
original_indent: Tuple[int, str] = tuple(self.indent) # type: ignore
@@ -353,7 +381,7 @@ def with_indent_size(self, size: int = 0):
353381
>>> with sl.with_indent_size(1):
354382
... sl.append("Hello World")
355383
356-
:param size:
384+
:param size: The indent size to use within the ``with`` block.
357385
"""
358386

359387
original_indent_size = self.indent_size
@@ -375,7 +403,7 @@ def with_indent_type(self, indent_type: str = "\t"):
375403
>>> with sl.with_indent_type(" "):
376404
... sl.append("Hello World")
377405
378-
:param indent_type:
406+
:param indent_type: The type of indent to use within the ``with`` block.
379407
"""
380408

381409
original_indent_type = self.indent_type

tests/test_stringlist.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,32 @@ def test_blankline(self):
9191
sl.blankline(ensure_single=True)
9292
assert sl == ["", '', "hello", "world", '', '', '', "1234", '']
9393

94+
sl.blankline(ensure_single=True)
95+
assert sl == ["", '', "hello", "world", '', '', '', "1234", '']
96+
97+
sl.append("\t")
98+
sl.blankline(ensure_single=True)
99+
assert sl == ["", '', "hello", "world", '', '', '', "1234", '']
100+
101+
sl.append(" ")
102+
sl.blankline(ensure_single=True)
103+
104+
assert sl == ["", '', "hello", "world", '', '', '', "1234", '']
105+
106+
sl.append(" ")
107+
sl.blankline(ensure_single=True)
108+
sl.blankline()
109+
assert sl == ["", '', "hello", "world", '', '', '', "1234", '', '']
110+
111+
def test_slicing(self):
112+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
113+
assert sl[:-3] == ["", '', "hello", "world", '']
114+
assert sl[-3:] == ['', '', "1234"]
115+
116+
def test_start_of_line_indents(self):
117+
assert StringList("Hello\n World") == ["Hello", " World"]
118+
assert StringList("Hello\n World", convert_indents=True) == ["Hello", "\tWorld"]
119+
94120
def test_indent_size(self):
95121
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
96122

@@ -392,3 +418,64 @@ def test_eq(self):
392418
assert Indent(2, "\t") == '\t\t'
393419

394420
assert not Indent() == 1
421+
422+
def test_extend(self):
423+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
424+
sl.extend(["\nfoo\nbar\n baz"])
425+
426+
assert sl == ["", '', "hello", "world", '', '', '', "1234", '', "foo", "bar", " baz"]
427+
428+
def test_clear(self):
429+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
430+
sl.clear()
431+
432+
assert sl == []
433+
434+
def test_copy(self):
435+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
436+
sl2 = sl.copy()
437+
438+
assert sl == sl2
439+
assert sl2 == ["", '', "hello", "world", '', '', '', "1234"]
440+
assert isinstance(sl2, StringList)
441+
442+
def test_count(self):
443+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
444+
assert sl.count("hello") == 1
445+
446+
def test_count_blanklines(self):
447+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
448+
assert sl.count_blanklines() == 5
449+
450+
def test_index(self):
451+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
452+
assert sl.index("hello") == 2
453+
454+
def test_pop(self):
455+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
456+
assert sl.pop(2) == "hello"
457+
assert sl == ["", '', "world", '', '', '', "1234"]
458+
assert isinstance(sl, StringList)
459+
460+
def test_remove(self):
461+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
462+
sl.remove("hello")
463+
assert sl == ["", '', "world", '', '', '', "1234"]
464+
assert isinstance(sl, StringList)
465+
466+
def test_reverse(self):
467+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
468+
sl.reverse()
469+
assert sl == ["1234", '', '', '', "world", "hello", '', '']
470+
assert isinstance(sl, StringList)
471+
472+
def test_sort(self):
473+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
474+
sl.sort()
475+
assert sl == ['', '', '', '', '', "1234", "hello", "world"]
476+
assert isinstance(sl, StringList)
477+
478+
sl = StringList(["", '', "hello", "world", '', '', '', "1234"])
479+
sl.sort(reverse=True)
480+
assert sl == ["world", "hello", "1234", '', '', '', '', '']
481+
assert isinstance(sl, StringList)

0 commit comments

Comments
 (0)