Source code for python2verilog.utils.lines
"""Utility Classes"""
from __future__ import annotations
[docs]
class Lines:
"""
A list of str that can be serialized to string with provided indents
"""
[docs]
@staticmethod
def assert_no_newline(string: str):
"""
Asserts no newline character in string
"""
assert string.find("\n") == -1, "Newline in Lines: " + string
def __init__(self, data: list[str] | str | None = None):
if data is None:
self.lines: list[str] = []
elif isinstance(data, str):
self.lines = []
for line in data.splitlines():
self.lines.append(line)
elif isinstance(data, list):
for line in data:
assert isinstance(line, str), "Input must be a list of strings"
self.assert_no_newline(line)
self.lines = data
else:
assert False, "Invalid input type: " + str(type(data))
def __add__(self, other: str):
return self.add(other)
def __str__(self):
return self.to_string()
def __repr__(self):
return self.to_string()
def __len__(self):
return len(self.lines)
def __getitem__(self, key: int):
return self.lines[key]
def __setitem__(self, key: int, value: str):
self.lines[key] = value
def __delitem__(self, key: int):
del self.lines[key]
def __rshift__(self, indent: int):
self.indent(indent)
@staticmethod
def __indent(indent_amount: int, text: str):
"""
Indent non-empty lines
"""
if len(text.strip()) > 0:
return Indent(indent_amount) + text
return text
[docs]
def indent(self, indent_amount: int):
"""
Indent all lines by amount
"""
self.lines = [self.__indent(indent_amount, line) for line in self.lines]
return self
[docs]
def to_string(self, indent: int = 0):
"""
Converts all lines into a string with lines
"""
output = ""
for buffer in self.lines:
output += self.__indent(indent, buffer) + "\n"
return output
[docs]
def add(self, other: str):
"""
Adds a new line
"""
assert isinstance(other, str)
self.assert_no_newline(other)
self.lines.append(other)
return self
[docs]
def blank(self):
"""
Adds a blank line
"""
self.lines.append("")
return self
[docs]
def concat(self, other: Lines, indent: int = 0):
"""
Concats two Lines
"""
assert isinstance(other, Lines), f"got {type(other)} instead"
for line in other.lines:
self.lines.append(self.__indent(indent, line))
return self
[docs]
@staticmethod
def nestify(buffers: list[tuple[Lines, Lines]], indent: int = 0):
"""
pair[0][0]
pair[1][0]
pair[2][0]
pair[2][1]
pair[1][0]
pair[0][1]
"""
assert isinstance(indent, int)
for pair in buffers:
assert isinstance(pair[0], Lines), f"{type(pair[0])} {pair[0]}"
assert isinstance(pair[1], Lines), f"{type(pair[1])} {pair[1]}"
assert len(pair) == 2
lines = Lines()
for i, buffer in enumerate(buffers):
lines.concat(buffer[0], indent + i)
for i, buffer in enumerate(reversed(buffers)):
lines.concat(buffer[1], indent + len(buffers) - i - 1)
return lines
[docs]
class Indent:
"""
Creates str instances of indentation
"""
indentor = " " * 4
[docs]
def indentify(self, indent: int = 0) -> str:
"""
Creates indentation
"""
return self.indentor * indent
def __init__(self, indent: int = 0):
self.indent = indent
def __add__(self, other: str):
assert isinstance(other, str)
return self.indentify(self.indent) + other
def __radd__(self, other: str):
assert isinstance(other, str)
return other + self.indentify(self.indent)
def __str__(self):
return self.indentify(self.indent)
[docs]
class ImplementsToLines:
"""
A base class defining an interface for classes that need to provide a 'to_lines' method
"""
[docs]
def to_lines(self):
"""
To Lines
"""
raise NotImplementedError("Derived class must implement to_lines")
[docs]
def to_string(self):
"""
To string
"""
return str(self.to_lines())
def __str__(self):
return self.to_string()