Beispiel #1
0
    def read(self, fobj, filename=''):
        encoding = None
        
        if isinstance(fobj, (str, text_type)):
            f = open(fobj, 'rb')
            text = f.read()
            f.close()
        else:
            text = fobj.read()
            
        text = text + b'\n'
        begin = 0
        if text.startswith(codecs.BOM_UTF8):
            begin = 3
            encoding = 'UTF-8'
        elif text.startswith(codecs.BOM_UTF16):
            begin = 2
            encoding = 'UTF-16'
            
        if not encoding:
            try:
                text_type(text, 'UTF-8')
                encoding = 'UTF-8'
            except:
                encoding = defaultencoding
                
        self._encoding = encoding
        
        f = StringIO(text_type(text, 'utf-8'))
        f.seek(begin)
        lineno = 0
        comments = []
        section = None
        while 1:
            lastpos = f.tell()
            line = f.readline()
            lineno += 1
            if not line:
                break
            line = line.strip()
            if line:
                if line.startswith(self._commentchar):
                    if lineno == 1: #first comment line
                        b = r_encoding.search(line[1:])
                        if b:
                            self._encoding = b.groups()[0]
                            continue
                    comments.append(line)
                elif line.startswith('[') and line.endswith(']'):
                    sec_name = line[1:-1].strip()
                    #process include notation
                    if sec_name.startswith('include:'):
                        _filename = sec_name[8:].strip()
                        _filename = os.path.abspath(_filename)
                        if os.path.exists(_filename):
                            old_encoding = self._encoding
                            self.read(_filename)
                            self._encoding = old_encoding
                        else:
                            import warnings
                            warnings.warn(Warning("Can't find the file [%s], so just skip it" % _filename), stacklevel=2)
                        continue
                    info = RawValue(self._inifile, lineno, sec_name)
                    section = self.add(sec_name, comments, info=info)
                    comments = []
                elif '=' in line:
                    if section is None:
                        raise Exception("No section found, please define it first in %s file" % self.filename)

                    #if find <=, then it'll replace the old value for mutable variables
                    #because the default behavior will merge list and dict
                    pos = line.find('<=')
                    if pos != -1:
                        begin, end = pos, pos+2
                        replace_flag = True
                    else:
                        pos = line.find('=')
                        begin, end = pos, pos+1
                        replace_flag = False
                        
                    keyname = line[:begin].strip()
                    #check keyname
                    if keyname in self._env:
                        raise KeyError("Settings key %s is alread defined in env, please change it's name" % keyname)
                    
                    rest = line[end:].strip()
                    #if key= then value will be set ''
                    if rest == '':
                        v = None
                    else:
                        f.seek(lastpos+end)
                        try:
                            value, iden_existed = self.__read_line(f)
                        except Exception as e:
                            print_exc()
                            raise Exception("Parsing ini file error in %s:%d:%s" % (filename or self._inifile, lineno, line))
                        if self._lazy:
                            if iden_existed:
                                v = EvalValue(value, filename or self._inifile, lineno, line)
                            else:
                                v = value
                        else:
                            if self._raw:
                                v = RawValue(self._inifile, lineno, value, replace_flag)
                            else:
                                try:
                                    v = eval_value(value, self.env(), self[sec_name], self._encoding)
                                except Exception as e:
                                    print(e)
                                    print_exc()
                                    print_(dict(self))
                                    raise Exception("Converting value (%s) error in %s:%d:%s" % (value, filename or self._inifile, lineno, line))
                    section.add(keyname, v, comments, replace=replace_flag)
                    comments = []
            else:
                comments.append(line)