# Copyright 2021 The casbin Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from io import StringIO class Config: """represents an implementation of the ConfigInterface""" # DEFAULT_SECTION specifies the name of a section if no name provided DEFAULT_SECTION = "default" # DEFAULT_COMMENT defines what character(s) indicate a comment `#` DEFAULT_COMMENT = "#" # DEFAULT_COMMENT_SEM defines what alternate character(s) indicate a comment `;` DEFAULT_COMMENT_SEM = ";" # DEFAULT_MULTI_LINE_SEPARATOR defines what character indicates a multi-line content DEFAULT_MULTI_LINE_SEPARATOR = "\\" _data = dict() def __init__(self): self._data = dict() @staticmethod def new_config(conf_name): c = Config() c._parse(conf_name) return c @staticmethod def new_config_from_text(text): c = Config() f = StringIO(text) c._parse_buffer(f) return c def add_config(self, section, option, value): if section == "": section = self.DEFAULT_SECTION if section not in self._data.keys(): self._data[section] = {} self._data[section][option] = value def _parse(self, fname): with open(fname, "r", encoding="utf-8") as f: self._parse_buffer(f) def _parse_buffer(self, f): section = "" line_num = 0 buf = [] can_write = False while True: if can_write: self._write(section, line_num, buf) can_write = False line_num = line_num + 1 line = f.readline() if not line: if len(buf) > 0: self._write(section, line_num, buf) break line = line.strip() if ( "" == line or self.DEFAULT_COMMENT == line[0:1] or self.DEFAULT_COMMENT_SEM == line[0:1] ): can_write = True continue elif "[" == line[0:1] and "]" == line[-1]: if len(buf) > 0: self._write(section, line_num, buf) can_write = False section = line[1:-1] else: p = "" if self.DEFAULT_MULTI_LINE_SEPARATOR == line[-1]: p = line[0:-1].strip() p = p + " " else: p = line can_write = True buf.append(p) def _write(self, section, line_num, b): buf = "".join(b) if len(buf) <= 0: return option_val = buf.split("=", 1) if len(option_val) != 2: raise RuntimeError( "parse the content error : line {} , {} = ?".format( line_num, option_val[0] ) ) option = option_val[0].strip() value = option_val[1].strip() self.add_config(section, option, value) del b[:] def get_bool(self, key): """lookups up the value using the provided key and converts the value to a bool.""" return self.get(key).capitalize() == "True" def get_int(self, key): """lookups up the value using the provided key and converts the value to a int""" return int(self.get(key)) def get_float(self, key): """lookups up the value using the provided key and converts the value to a float""" return float(self.get(key)) def get_string(self, key): """lookups up the value using the provided key and converts the value to a string""" return self.get(key) def get_strings(self, key): """lookups up the value using the provided key and converts the value to an array of string""" value = self.get(key) if value == "": return None return value.split(",") def set(self, key, value): if len(key) == 0: raise RuntimeError("key is empty") keys = key.lower().split("::") if len(keys) >= 2: section = keys[0] option = keys[1] else: section = "" option = keys[0] self.add_config(section, option, value) def get(self, key): """section.key or key""" keys = key.lower().split("::") if len(keys) >= 2: section = keys[0] option = keys[1] else: section = self.DEFAULT_SECTION option = keys[0] if section in self._data.keys(): if option in self._data[section].keys(): return self._data[section][option] return ""