parser.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import pathlib
  2. import _io
  3. from .pini_exception import pini_exception
  4. from .pini_exception import pini_syntax
  5. from .pini import pini
  6. from .key import key
  7. from .section import section
  8. class parser():
  9. def __init__(self, target: str | pathlib.Path):
  10. if target isinstance str:
  11. target = pathlib.Path(target)
  12. if not target.is_file():
  13. raise pini_exception("File " + str(target) + " not exists.")
  14. self.__current = None
  15. self.__path = target
  16. self.__config = pini()
  17. self.__process()
  18. def __get_section(self) -> section:
  19. if self.__current is None:
  20. self.__current = section()
  21. return self.__get_section()
  22. return self.__current
  23. def __new_section(self, name: str) -> section:
  24. if type(name) is not str:
  25. raise TypeError("New section name must be str.")
  26. name = name.strip()
  27. if len(name) == 0:
  28. raise pini_syntax("New section name can not be empty.")
  29. if self.__current is not None:
  30. self.__config.add(self.__current)
  31. self.__current = section()
  32. self.__current.name = name
  33. def __process(self) -> None:
  34. with self.__path.open() as file:
  35. for line in file:
  36. self.__parse_line(line)
  37. def __parse_line(self, line: str) -> None:
  38. line = line.lstrip()
  39. if len(line) == 0:
  40. return
  41. first = line[0]
  42. if first == "[":
  43. self.__parse_section(line)
  44. return
  45. if first == "#":
  46. if len(line) >= 3 and line[0:3] == "###":
  47. self.__parse_unactive_key(line)
  48. return
  49. self.__parse_comment(line)
  50. return
  51. self.__parse_key(line)
  52. def __split_comment(self, line: str) -> [str | None , str | None]:
  53. position = line.find("#")
  54. if position == -1:
  55. return line.strip(), None
  56. content = line[:position].strip()
  57. comment = line[position + 1:]
  58. if len(comment) > 0 and comment[0] == " ":
  59. comment = comment[1:]
  60. if len(content) == 0:
  61. content = None
  62. if len(comment) == 0:
  63. comment = None
  64. return content, comment
  65. def __parse_unactive_key(self, line: str) -> None:
  66. line = line[3:]
  67. if line[0] == " ":
  68. line = line[1:]
  69. content, comment = self.__split_comment(line)
  70. if content is None:
  71. if comment is None:
  72. return
  73. self.__get_section().add_comment(comment)
  74. position = content.find("=")
  75. target = key()
  76. target.value = None
  77. target.name = content.strip()
  78. target.comment = comment
  79. def __parse_key(self, line: str) -> None:
  80. content, comment = self.__split_comment(line)
  81. if content is None and comment is not None:
  82. self.__parse_comment("#" + comment)
  83. return
  84. if content.count("=") != 1:
  85. raise pini_syntax(""
  86. def __parse_section(self, line: str) -> None:
  87. content, comment = self.__split_comment(line)
  88. if content.count("[") != 1 or content.count("]") != 1:
  89. raise pini_syntax("Section name must start with [ and end with ].")
  90. start = content.find("[") + 1
  91. end = content.find("]")
  92. name = content[start:end].strip()
  93. if len(name) == 0:
  94. raise pini_syntax("Section name can not be empty.")
  95. if name.count(" ") > 0 or name.count("\t") > 0:
  96. raise pini_syntax("Section name can not contain white chars.")
  97. self.__new_section(name)
  98. if comment is not None:
  99. self.__get_section().add_comment(comment)
  100. def __parse_comment(self, line: str) -> None:
  101. if line[0] != "#":
  102. return
  103. line = line[1:]
  104. if len(line) == 0:
  105. self.__get_section().add_comment("")
  106. return
  107. if line[0] == " ":
  108. line = line[1:]
  109. self.__get_section().add_comment(line)