import pathlib import _io from .pini_exception import pini_exception from .pini_exception import pini_syntax from .pini import pini from .key import key from .section import section class parser(): def __init__(self, target: str | pathlib.Path): if target isinstance str: target = pathlib.Path(target) if not target.is_file(): raise pini_exception("File " + str(target) + " not exists.") self.__current = None self.__path = target self.__config = pini() self.__process() def __get_section(self) -> section: if self.__current is None: self.__current = section() return self.__get_section() return self.__current def __new_section(self, name: str) -> section: if type(name) is not str: raise TypeError("New section name must be str.") name = name.strip() if len(name) == 0: raise pini_syntax("New section name can not be empty.") if self.__current is not None: self.__config.add(self.__current) self.__current = section() self.__current.name = name def __process(self) -> None: with self.__path.open() as file: for line in file: self.__parse_line(line) def __parse_line(self, line: str) -> None: line = line.lstrip() if len(line) == 0: return first = line[0] if first == "[": self.__parse_section(line) return if first == "#": if len(line) >= 3 and line[0:3] == "###": self.__parse_unactive_key(line) return self.__parse_comment(line) return self.__parse_key(line) def __split_comment(self, line: str) -> [str | None , str | None]: position = line.find("#") if position == -1: return line.strip(), None content = line[:position].strip() comment = line[position + 1:] if len(comment) > 0 and comment[0] == " ": comment = comment[1:] if len(content) == 0: content = None if len(comment) == 0: comment = None return content, comment def __parse_unactive_key(self, line: str) -> None: line = line[3:] if line[0] == " ": line = line[1:] content, comment = self.__split_comment(line) if content is None: if comment is None: return self.__get_section().add_comment(comment) position = content.find("=") target = key() target.value = None target.name = content.strip() target.comment = comment def __parse_key(self, line: str) -> None: content, comment = self.__split_comment(line) if content is None and comment is not None: self.__parse_comment("#" + comment) return if content.count("=") != 1: raise pini_syntax("" def __parse_section(self, line: str) -> None: content, comment = self.__split_comment(line) if content.count("[") != 1 or content.count("]") != 1: raise pini_syntax("Section name must start with [ and end with ].") start = content.find("[") + 1 end = content.find("]") name = content[start:end].strip() if len(name) == 0: raise pini_syntax("Section name can not be empty.") if name.count(" ") > 0 or name.count("\t") > 0: raise pini_syntax("Section name can not contain white chars.") self.__new_section(name) if comment is not None: self.__get_section().add_comment(comment) def __parse_comment(self, line: str) -> None: if line[0] != "#": return line = line[1:] if len(line) == 0: self.__get_section().add_comment("") return if line[0] == " ": line = line[1:] self.__get_section().add_comment(line)