|
|
@@ -1,205 +1,68 @@
|
|
|
-from .exception import pini_exception
|
|
|
-from .exception import pini_type_exception
|
|
|
from .exception import pini_syntax
|
|
|
-from .line import line
|
|
|
|
|
|
-class key(line):
|
|
|
- def __init__(self):
|
|
|
- super().__init__()
|
|
|
- self.__value: str | int | float | None = None
|
|
|
+class key:
|
|
|
+ def __init__(
|
|
|
+ self,
|
|
|
+ name: str,
|
|
|
+ content: str | int | float | bool | None = None,
|
|
|
+ comment: str | None = None
|
|
|
+ ):
|
|
|
+ self.name = name
|
|
|
+ self.content = content
|
|
|
+ self.comment = comment
|
|
|
|
|
|
@property
|
|
|
- def value(self) -> str | int | float | None:
|
|
|
- return self.__value
|
|
|
+ def name(self) -> str:
|
|
|
+ return self.__name
|
|
|
|
|
|
@property
|
|
|
- def value_type(self) -> str:
|
|
|
- if self.__value is None:
|
|
|
- return "None"
|
|
|
-
|
|
|
- return type(self.__value).__name__
|
|
|
-
|
|
|
- @value.setter
|
|
|
- def value(self, target: str | int | float | None) -> None:
|
|
|
- if type(target) is str:
|
|
|
- self.__value = target.strip()
|
|
|
- return
|
|
|
-
|
|
|
- if type(target) is int or type(target) is float or target is None:
|
|
|
- self.__value = target
|
|
|
- return
|
|
|
-
|
|
|
- raise TypeError("Value must be str, int, float or None.")
|
|
|
-
|
|
|
- def get(self, empty: str | int | float | None) -> str | int | float | None:
|
|
|
- checked = type(empty) is str
|
|
|
- checked = checked or type(empty) is int
|
|
|
- checked = checked or type(empty) is float
|
|
|
- checked = checked or empty is None
|
|
|
-
|
|
|
- if not checked:
|
|
|
- raise TypeError("Default value for empty key type is not valid.")
|
|
|
-
|
|
|
- if self.__value is None:
|
|
|
- return empty
|
|
|
-
|
|
|
- if type(empty) is not type(self.__value):
|
|
|
- error = "Type of the " + self.name + " is not valid. "
|
|
|
- error = error + "It must be in " + type(empty).__name__ + ". "
|
|
|
- error = error + "It is " + type(self.__value).__name__ + "."
|
|
|
-
|
|
|
- raise pini_type_exception(error)
|
|
|
-
|
|
|
- return self.__value
|
|
|
-
|
|
|
- def render(self) -> str:
|
|
|
- comment = ""
|
|
|
-
|
|
|
- if self.comment is not None:
|
|
|
- comment = "# " + self.comment
|
|
|
-
|
|
|
- if self.name is None:
|
|
|
- return comment
|
|
|
-
|
|
|
- content = self.name + " = "
|
|
|
-
|
|
|
- if self.__value is not None:
|
|
|
- content = content + str(self.__value)
|
|
|
-
|
|
|
- if self.__value is None:
|
|
|
- content = "### " + content
|
|
|
-
|
|
|
- if len(comment) > 0:
|
|
|
- content = content + (" " * (4 - (len(content) % 4)))
|
|
|
- content = content + comment
|
|
|
-
|
|
|
- return content
|
|
|
-
|
|
|
- def clone(self):
|
|
|
- copy = key()
|
|
|
- copy.name = self.name
|
|
|
- copy.value = self.value
|
|
|
- copy.comment = self.comment
|
|
|
-
|
|
|
- return copy
|
|
|
-
|
|
|
-class parse_key():
|
|
|
- def __new__(cls, line: str) -> key:
|
|
|
- target = key()
|
|
|
-
|
|
|
- if type(line) is not str:
|
|
|
- raise TypeError("Line must be in str type.")
|
|
|
-
|
|
|
- cls.__init__(target, cls, line)
|
|
|
-
|
|
|
- return target
|
|
|
+ def content(self) -> str | int | float | bool | None:
|
|
|
+ return self.__content
|
|
|
|
|
|
- def __init__(self, cls, line: str) -> None:
|
|
|
- line = line.lstrip()
|
|
|
-
|
|
|
- if len(line) == 0:
|
|
|
- return
|
|
|
-
|
|
|
- if line[0:3] == "###":
|
|
|
- cls.__parse_blank(self, cls, line[3:])
|
|
|
- return
|
|
|
-
|
|
|
- cls.__parse_normal(self, cls, line)
|
|
|
-
|
|
|
- def __split_comment(line: str) -> [str | None, str | None]:
|
|
|
- line = line.lstrip()
|
|
|
-
|
|
|
- if len(line) == 0:
|
|
|
- return None, None
|
|
|
-
|
|
|
- comment = None
|
|
|
- content = line.rsplit()
|
|
|
- comment_position = line.find("#")
|
|
|
-
|
|
|
- if comment_position != -1:
|
|
|
- comment = line[comment_position + 1:]
|
|
|
-
|
|
|
- if comment[0] == " ":
|
|
|
- comment = comment[1:]
|
|
|
-
|
|
|
- if len(comment) == 0:
|
|
|
- comment = None
|
|
|
-
|
|
|
- content = line[:comment_position].rsplit()
|
|
|
-
|
|
|
- if len(content) == 0:
|
|
|
- content = None
|
|
|
-
|
|
|
- return content, comment
|
|
|
-
|
|
|
- def __parse_blank(self, cls, line: str) -> None:
|
|
|
- content, comment = cls.__split_comment(line)
|
|
|
-
|
|
|
- where = content.find("=")
|
|
|
-
|
|
|
- if where != -1:
|
|
|
- content = content[:where].rsplit()
|
|
|
-
|
|
|
- self.name = content
|
|
|
- self.value = None
|
|
|
- self.comment = comment
|
|
|
-
|
|
|
- def __split_comment(cls, line: str) -> [str | None, str | None]:
|
|
|
- name = line
|
|
|
- value = None
|
|
|
- value_position = line.find("=")
|
|
|
+ @property
|
|
|
+ def comment(self) -> str | None:
|
|
|
+ return self.__comment
|
|
|
|
|
|
- if value_position == -1:
|
|
|
- return name, value
|
|
|
+ @name.setter
|
|
|
+ def name(self, target: str) -> None:
|
|
|
+ target = target.strip()
|
|
|
|
|
|
- name = line[:value_position].rsplit()
|
|
|
- value = line[value_position + 1:].lstrip()
|
|
|
- value = cls.__parse_value(cls, value)
|
|
|
-
|
|
|
- return name, value
|
|
|
+ if len(target) == 0:
|
|
|
+ raise pini_syntax("Key name lenght could not be blank.")
|
|
|
|
|
|
- def __parse_value(cls, line: str) -> str | None:
|
|
|
- line = line.strip()
|
|
|
+ self.__name = target
|
|
|
|
|
|
- if len(line) == 0:
|
|
|
- return None
|
|
|
+ @content.setter
|
|
|
+ def content(self, target: str | int | float | bool | None) -> None:
|
|
|
+ self.__content = target
|
|
|
|
|
|
- if cls.is_number(line):
|
|
|
- as_float = float(line)
|
|
|
- as_integer = int(line)
|
|
|
+ @comment.setter
|
|
|
+ def comment(self, target: str) -> None:
|
|
|
+ self.__comment = target
|
|
|
|
|
|
- if as_float == as_integer:
|
|
|
- return as_integer
|
|
|
+ def __render_content(self) -> str:
|
|
|
+ if type(self.content) is int or type(self.content) is float:
|
|
|
+ return str(self.content)
|
|
|
|
|
|
- return as_float
|
|
|
+ if type(self.content) is str:
|
|
|
+ return "\"" + self.content + "\""
|
|
|
|
|
|
- if line[0] == "'" or line[0] == "\"":
|
|
|
- start = line[0]
|
|
|
+ if type(self.content) is bool:
|
|
|
+ return "True" if self.content else "False"
|
|
|
|
|
|
- if line[-1] != start:
|
|
|
- raise pini_syntax("String without stop.")
|
|
|
-
|
|
|
- line = line[1:-1]
|
|
|
- where = 0
|
|
|
-
|
|
|
- while True:
|
|
|
- where = line.find(start, where)
|
|
|
-
|
|
|
- if where == -1:
|
|
|
- break
|
|
|
+ if self.content is None:
|
|
|
+ return "None"
|
|
|
|
|
|
- if line[where - 1] != "\\":
|
|
|
- raise pini_syntax("String stopper not expected.")
|
|
|
+ raise TypeError("Key content must be int, float, string or None.")
|
|
|
|
|
|
- return line
|
|
|
+ def render(self) -> str:
|
|
|
+ result = self.name + " = "
|
|
|
+ result = result + self.__render_content()
|
|
|
|
|
|
- def is_number(value: str) -> bool:
|
|
|
- if value[0] == "-":
|
|
|
- value = value[1:]
|
|
|
+ if self.comment is not None:
|
|
|
+ result = result + " # " + self.__comment
|
|
|
|
|
|
- value = value.replace(".", "")
|
|
|
- return value.isnumeric()
|
|
|
+ return result
|
|
|
|
|
|
- def __parse_normal(self, cls, line: str) -> None:
|
|
|
- content, comment = cls.__split_comment(line)
|
|
|
- name, value = cls.__split_content(cls, content)
|
|
|
+ def __str__(self) -> str:
|
|
|
+ return self.render()
|