def confparse(): global RPICFG rpicfg = configparser.ConfigParser() try: rpicfg.read(RPICFG) # Verify Section if rpicfg.sections() != ["HOST", "TELEBOT"]: raise configparser.ParsingError("RPICFG Section Error") # Verify Section Keys if list(rpicfg["HOST"].keys()) != [ "rootca", "certificate", "privatekey", "hostname", "rpi" ]: raise configparser.ParsingError("RPICFG Section Key Error") elif list(rpicfg["TELEBOT"].keys()) != ["bottok", "phoneid"]: raise configparser.ParsingError("RPICFG Section Key Error") # Set ConfigParser Object RPICFG = { "HOST": dict(rpicfg["HOST"]), "TELEBOT": dict(rpicfg["TELEBOT"]) } RPICFG["TELEBOT"]["phoneid"] = int(rpicfg["TELEBOT"]["phoneid"]) except configparser.ParsingError: # Reset RPICFG """ python3 builtin print but outputs to sys.stderr """ print("Rewriting to Default Host") rpicfg.clear() rpicfg["HOST"] = { "rootca": "AWSCert/rootca.pem", "certificate": "AWSCert/certificate.pem.crt", "privatekey": "AWSCert/private.pem.key", "hostname": "a2jmdmmdzxnqz9-ats.iot.us-east-1.amazonaws.com", "rpi": "YLRasp" } rpicfg["TELEBOT"] = { "bottok": "1487998228:AAEeVn6LyRfF1HpcicSlHljt9hidMdJ5rSs", "phoneid": "903351528" } RPICFG = { "HOST": dict(rpicfg["HOST"]), "TELEBOT": dict(rpicfg["TELEBOT"]) } RPICFG["TELEBOT"]["phoneid"] = int(rpicfg["TELEBOT"]["phoneid"])
def getjson(self, section, option, fallback=None): """Load JSON object from value. Args: section (str): section name. option (str): option name. Kwargs: fallback: Dict or List. Returns dict or list. """ try: val = self.get(section, option) if val.strip() == '' and fallback is not None: return fallback elif val.strip() == '': raise configparser.NoSectionError(section) from None except configparser.NoSectionError as e: if fallback is not None: return fallback else: raise configparser.NoSectionError(section) from None except configparser.NoOptionError as e: if fallback is not None: return fallback else: raise configparser.NoOptionError(section, option) from None try: return js.loads(val) except json.decoder.JSONDecodeError as e: raise configparser.ParsingError("section '%s'" % section + " option '%s'" % option + " (JSON %s)" % e) from None
def test_read_config_file_raises(mocker, monkeypatch): """Handle exceptions while reading pyproject.toml/setup.cfg, if any.""" toml_error = toml.TomlDecodeError("toml error", doc="foo", pos=0) os_error = OSError("os error") mock_parse_pyproject_toml = mocker.Mock() mock_parse_pyproject_toml.side_effect = (toml_error, os_error) monkeypatch.setattr(config, "parse_pyproject_toml", mock_parse_pyproject_toml) cfg_error = configparser.ParsingError("cfg parsing error") mock_parse_setup_cfg = mocker.Mock() mock_parse_setup_cfg.side_effect = (cfg_error, ) monkeypatch.setattr(config, "parse_setup_cfg", mock_parse_setup_cfg) error_msg = "Error reading configuration file: toml error" with pytest.raises(click.FileError, match=error_msg): config.read_config_file({}, "foo", "pyproject.toml") error_msg = "Error reading configuration file: os error" with pytest.raises(click.FileError, match=error_msg): config.read_config_file({}, "foo", "pyproject.toml") error_msg = ( "Error reading configuration file: Source contains parsing errors: " "'cfg parsing error'") with pytest.raises(click.FileError, match=error_msg): config.read_config_file({}, "foo", "setup.cfg")
def test_load_config_3(self): """ Scenario 3: - the config file exists - os.path.isfile: True - the config file reading failed, - the dafault values are loaded to the View, - logger writes one messages to the log file. """ typeof = 'Spam0' controller.os.path.isfile = mock.Mock(return_value=True) self.c.config.read = mock.Mock(side_effect=configparser.ParsingError('None')) tabwidget0 = mock.Mock(typeof=typeof) tablist = [tabwidget0] self.c.view.get_tablist = mock.Mock(return_value=tablist) self.c.load_config() assert self.c.config.read.call_count == 1 calls = [mock.call.warning(self.c.configerr['parse']), mock.call.warning(self.c.configerr['keyerr'].format(typeof))] with self.assertRaises(KeyError): self.c.config['Spam3'] with self.assertRaises(configparser.ParsingError): self.c.config.read() tabwidget0.set_srcdir.assert_called_once_with([''], fill='') tabwidget0.set_dstdir.assert_called_once_with([''], fill='') tabwidget0.set_active_direc.assert_called_once_with(['False'], fill=False) tabwidget0.set_tosend.set_active_direc(False) self.c.logger.warning.assert_has_calls(calls) assert self.c.logger.warning.call_count == 2
def __init__(self, root="/", config_file=None): defaults = copy.deepcopy(os.environ) defaults["HOSTNAME"] = gcmu.public_name() if "SHORT_HOSTNAME" not in defaults: defaults["SHORT_HOSTNAME"] = defaults["HOSTNAME"].split(".")[0] if "USER" in defaults: del defaults["USER"] if "GLOBUS_USER" not in defaults: defaults["GLOBUS_USER"] = "" if "GLOBUS_PASSWORD" not in defaults: defaults["GLOBUS_PASSWORD"] = "" configparser.ConfigParser.__init__(self, defaults) self.root = root self.cilogon_dn_prefix = CILOGON_DN_PREFIX self.cilogon_org_name = None if config_file is None: config_file = os.path.join("/", ConfigFile.DEFAULT_CONFIG_FILE) config_fp = open(config_file, "r") try: if self.readfp(config_fp) == []: raise configparser.ParsingError(config_file) finally: config_fp.close() self.validate(config_file) self.validate_cilogon_identity_provider()
def qualtrics_check(config_dict: dict): """ Perform Qualtrics checks on config file :param config_dict: Dictionary containing all LD-Cool-P configuration """ qualtrics_err = 0 qualtrics_err_source = [] if 'qualtrics' in config_dict: if isinstance(config_dict['qualtrics']['survey_id'], list): ref_size = len(config_dict['qualtrics']['survey_id']) for key in ['survey_shortname', 'survey_email']: if len(config_dict['qualtrics'][key]) != ref_size: qualtrics_err += 1 qualtrics_err_source.append(key) else: print("survey_id in not a list") else: print("No qualtrics settings in config file") if qualtrics_err != 0: str_join = ', '.join(qualtrics_err_source) print(f"ERROR: Number of items incorrect in: {str_join}") raise configparser.ParsingError(source=str_join)
def getlist(self, section, option, fallback=None): """Get list from option value. Example: .. code:: [Bar] files_to_check = /path/to/file1, /path/to/file2, /path/to/another file with space in the name Args: section (str): section name. option (str): option name. Kwargs: fallback (list): List of default values. Returns list. """ try: val = self.get(section, option) if val.strip() == '': return [] val = val.replace('\n', '').replace('\r', '').split(',') except configparser.NoSectionError as e: if fallback is not None: val = fallback else: raise configparser.NoSectionError(section) from None except configparser.NoOptionError as e: if fallback is not None: val = fallback else: raise configparser.NoOptionError(section, option) from None if isinstance(val, list): return val else: raise configparser.ParsingError("section '%s'" % section + " option '%s'" % option + " expected list") from None
def test_load_config_2(self): """ Scenario 2: - the config file exists - os.path.isfile: True, - parsing config file failed, - set_top loads default value, - logger writes two messages to the log file. """ self.c.config.read = mock.Mock( side_effect=configparser.ParsingError('None')) DirMaker.os.path.isfile = mock.Mock(return_value=True) with self.assertRaises(configparser.ParsingError): self.c.config.read() self.c.config.read_dict({'': {'': ''}}) self.c.load_config() self.c.set_top.assert_called_once_with(self.c.userdir) calls = [ mock.call.warning(self.c.configerr['parse']), mock.call.warning(self.c.configerr['keyerr']) ] assert self.c.logger.warning.call_count == 2 self.c.logger.assert_has_calls(calls)
def parse_slack_config_file(slack_config_file): """Parse slack configuration file Args: slack_config_file: Path to slack configuration file Returns: Dictionary with slack configurations """ config = configparser.ConfigParser() slack_config_dict = {} try: config.read(slack_config_file) slack_config_dict = { "slack_token": config["SLACK_PROPERTIES"]["SLACK_TOKEN"], "slack_username": config["SLACK_PROPERTIES"]["SLACK_USERNAME"], "slack_icon_url": config["SLACK_PROPERTIES"]["SLACK_ICON_URL"], "topic_channel_mapping": {}, "default_channel": config["GENERAL"]["DEFAULT_CHANNEL"], } slack_config_dict["topic_channel_mapping"] = config.items( "TOPIC_CHANNEL_MAPPING" ) with open("config.txt", "w") as f: f.write(str(slack_config_dict)) except IOError: raise IOError("Error: Slack configuration file does not appear to exist.") except configparser.NoSectionError: raise configparser.NoSectionError("Error: A section is missing") except configparser.DuplicateSectionError: raise configparser.DuplicateSectionError("Error: Section duplication error") except configparser.ParsingError: raise configparser.ParsingError("Error: Slack configuration file parsing error") except: raise Exception("Error: Error in Slack configuration file.") return slack_config_dict
def load_config(path): configuration = Config(False) configFile = configparser.ConfigParser() try: configFile.read(path) with open(path) as f: configFile.read_file(f) except IOError as error: print("File at \"", path, "\" not found.", sep="") raise error try: # Main ratio = float(configFile.get("Main", "LeftToRightRatio")) if not 0 <= ratio <= 2: raise configparser.ParsingError("LeftToRightRatio out of bounds ({:.3f} OOR [0,2])".format(ratio)) if ratio <= 1: configuration.MotorLeftRatio = ratio configuration.MotorRightRatio = 1 else: configuration.MotorLeftRatio = 1 configuration.MotorRightRatio = 1 / ratio configuration.PiCamEnabled = configFile.get("Main", "CamEnabled").lower() == "true" configuration.I2CBus = int(configFile.get("Main", "i2cBus")) if not 0 <= configuration.I2CBus <= 2: raise configparser.ParsingError("Bus out of bounds ({:d} OOR [0,2])".format(configuration.I2CBus)) configuration.MotorDriverFrequency = int(configFile.get("Main", "MotorDriverFrequency")) if not 1 <= configuration.MotorDriverFrequency <= 10000: raise configparser.ParsingError( "Frequency out of bounds ({:d} OOR [1,10000])".format(configuration.MotorDriverFrequency)) configuration.Handshake = configFile.get("Main", "Handshake").lower() == "true" # Sensors configuration.UltraSonicState = int(configFile.get("Sensors", "USMode")) configuration.UltraSonicInterruptPinEnabled = configFile.get("Sensors", "USInterruptPin").lower() == "true" configuration.UltraSonicMode = int(configFile.get("Sensors", "USPollingMethod")) if not 0 <= configuration.UltraSonicMode <= 4: raise configparser.ParsingError("Method {:d} not recognized".format(configuration.UltraSonicMode)) configuration.UltraSonicLock = configFile.get("Sensors", "USLock").lower() == "true" if configuration.UltraSonicLock and configuration.UltraSonicMode == 0: raise configparser.ParsingError("US Lock is enabled but there is no polling method") configuration.UltraSonicThreshold = int(configFile.get("Sensors", "USDistanceInterrupt")) if configuration.UltraSonicThreshold < 0: raise configparser.ParsingError( "Distance cannot be negative ({:d} < 0)".format(configuration.UltraSonicThreshold)) if configuration.UltraSonicMode == 2 and configuration.UltraSonicThreshold > 29: raise configparser.ParsingError( "Threshold out of bounds ({:d} OOR [0,29])".format(configuration.UltraSonicThreshold)) configuration.UltraSonicPollingRate = int(configFile.get("Sensors", "USPollingRate")) if configuration.UltraSonicMode != 3 and not 1 <= configuration.UltraSonicPollingRate <= 100: raise configparser.ParsingError( "Polling rate out of bounds ({:d} OOR [1,100])".format(configuration.UltraSonicPollingRate)) configuration.UltraSonicPollingDelay = float(configFile.get("Sensors", "USDelay")) if configuration.UltraSonicMode != 3 and configuration.UltraSonicPollingDelay <= 0: raise configparser.ParsingError( "Delay must be positive number ({:.2f} <= 0)".format(configuration.UltraSonicPollingDelay)) # Pins configuration.UltraSonicInterruptPin = int(configFile.get("Pins", "InterruptPin")) configuration.MotorDriverLeftPWM = int(configFile.get("Pins", "MotorDriverLeftPWM")) configuration.MotorDriverRightPWM = int(configFile.get("Pins", "MotorDriverRightPWM")) configuration.MotorDriverLeftForwards = int(configFile.get("Pins", "MotorDriverLeftForwards")) configuration.MotorDriverLeftBackwards = int(configFile.get("Pins", "MotorDriverLeftBackwards")) configuration.MotorDriverRightForwards = int(configFile.get("Pins", "MotorDriverRightForwards")) configuration.MotorDriverRightBackwards = int(configFile.get("Pins", "MotorDriverRightBackwards")) except configparser.Error as error: print("Config file {} contains errors.".format(path)) raise error return configuration
bot_token = config['telegram']['token'] chat_id = config['telegram']['chatid'] bitrix24_token = config['bitrix24']['token'] bitrix24_domain = str(config['bitrix24']['domain']).rstrip('/').split('//')[-1] logfile = config['basic']['logfile'] telno_split_regex = config['basic']['regex'] save_path = str(config['basic']['save_path']).rstrip('/') + '/' audio_url = str(config['basic']['audio_url']).rstrip('/') + '/' number_position = int(config['basic']['number_position']) if number_position > 0: number_position -= 1 elif number_position == 0: raise configparser.ParsingError( '\nЗначение индекса номера телефона в файле (number_position) ' 'должно быть отличным от нуля!\n') split_re = re.compile(r'\w+') accepted_extensions = [v for v in split_re.findall( config['basic']['accepted_extensions'])] except configparser.Error as pe: print('\n\nОшибка чтения конфигурационного файла!\n' 'Или неверно задана конфигурация или ошибка возникла при присвоении значений!\n' 'Здесь объяснений нет, попробуйте посмотреть в логе ошибки ниже.\n\n') print(pe, '\n') exit(1) except Exception as e: print('\nНепредвиденная ошибка в обработке конфигурационного файла!\n\n') print(e, '\n') exit(1)
def init_config(path): config = {} configFile = configparser.ConfigParser() try: configFile.read(path) with open(path) as f: configFile.read_file(f) except IOError: print("File at \"", path, "\" not found.", sep="") exit(404) try: ratio = float(configFile.get("Main", "LeftToRightRatio")) config['C_Enabled'] = configFile.get("Main", "CamEnabled") == "true" config['MOT_DRF'] = int(configFile.get("Main", "ServoDriverFrequency")) if not 1 <= config['MOT_DRF'] <= 10000: raise configparser.ParsingError( "Frequency out of bounds ({:d} OOR [1,10000])".format( config['MOT_DRF'])) config['BUS'] = int(configFile.get("Main", "i2cBus")) if not 0 <= config['BUS'] <= 2: raise configparser.ParsingError( "Bus out of bounds ({:d} OOR [0,2])".format(config['BUS'])) config['US_Enabled'] = configFile.get("Sensors", "USEnabled") == "true" config['US_Rem_Dis'] = configFile.get("Sensors", "USRemoteDisable") == "true" config['US_Rem_IP'] = configFile.get("Sensors", "USRemoteInterruptPin") == "true" config['US_Method'] = int( configFile.get("Sensors", "USInterruptMethod")) if not 0 <= config['US_Method'] <= 3: raise configparser.ParsingError( "Method {:d} not recognized".format(config['US_Method'])) config['US_Lock'] = configFile.get("Sensors", "USLock") == "true" config['US_Distance'] = int( configFile.get("Sensors", "USDistanceInterrupt")) if config['US_Distance'] < 0: raise configparser.ParsingError( "Distance cannot be negative ({:d} < 0)".format( config['US_Distance'])) if config['US_Method'] == 2 and config['US_Distance'] > 29: raise configparser.ParsingError( "Threshold out of bounds ({:d} OOR [0,29])".format( config['US_Distance'])) config['US_Rate'] = int(configFile.get("Sensors", "USPollingRate")) if config['US_Method'] != 3 and not 1 <= config['US_Rate'] <= 100: raise configparser.ParsingError( "Polling rate out of bounds ({:d} OOR [1,100])".format( config['US_Rate'])) config['US_Delay'] = float(configFile.get("Sensors", "USDelay")) if config['US_Method'] != 3 and config['US_Delay'] <= 0: raise configparser.ParsingError( "Delay must be positive number ({:d} <= 0)".format( config['US_Delay'])) config['Interrupt'] = int(configFile.get("Pins", "InterruptPin")) config['MOT_LBF'], config['MOT_LBB'] = configFile.get( "Pins", "LeftBack").split(",") config['MOT_RBF'], config['MOT_RBB'] = configFile.get( "Pins", "RightBack").split(",") config['US_LE'] = int(configFile.get("Pins", "USLeftEcho")) config['US_RE'] = int(configFile.get("Pins", "USRightEcho")) config['US_FE'] = int(configFile.get("Pins", "USFrontEcho")) config['US_LT'] = int(configFile.get("Pins", "USLeftTrigger")) config['US_RT'] = int(configFile.get("Pins", "USRightTrigger")) config['US_FT'] = int(configFile.get("Pins", "USFrontTrigger")) config['MOT_DRL'] = int(configFile.get("Pins", "ServoDriverLeft")) config['MOT_DRR'] = int(configFile.get("Pins", "ServoDriverRight")) config['MOT_LBF'] = int(config['MOT_LBF']) config['MOT_LBB'] = int(config['MOT_LBB']) config['MOT_RBF'] = int(config['MOT_RBF']) config['MOT_RBB'] = int(config['MOT_RBB']) if ratio <= 1: config['MOT_LBR'] = ratio config['MOT_RBR'] = 1 else: config['MOT_LBR'] = 1 config['MOT_RBR'] = 1 / ratio except configparser.Error as error: print("Config file {} contains errors.".format(path)) print(error) exit(408) return config
def test_try_to_configure_logging_ParsingError(self, m_handle_parsing_error, m_configure_logging): m_configure_logging.side_effect = configparser.ParsingError(source='abcd') try_to_configure_logging('conf.conf') m_handle_parsing_error.called_once_with()
def test_try_to_parse_config_file_ParsingError(self, m_handle_parsing_error, m_parse_config_file): m_parse_config_file.side_effect = configparser.ParsingError(source='abcd') try_to_parse_config_file('conf.conf') m_handle_parsing_error.called_once_with()
def _read(self, fp: Union[BufferedReader, IO[bytes]], fpname: str) -> None: """A direct copy of the py2.4 version of the super class's _read method to assure it uses ordered dicts. Had to change one line to make it work. Future versions have this fixed, but in fact its quite embarrassing for the guys not to have done it right in the first place ! Removed big comments to make it more compact. Made sure it ignores initial whitespace as git uses tabs""" cursect = None # None, or a dictionary optname = None lineno = 0 is_multi_line = False e = None # None, or an exception def string_decode(v: str) -> str: if v[-1] == '\\': v = v[:-1] # end cut trailing escapes to prevent decode error return v.encode(defenc).decode('unicode_escape') # end # end while True: # we assume to read binary ! line = fp.readline().decode(defenc) if not line: break lineno = lineno + 1 # comment or blank line? if line.strip() == '' or self.re_comment.match(line): continue if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR": # no leading whitespace continue # is it a section header? mo = self.SECTCRE.match(line.strip()) if not is_multi_line and mo: sectname: str = mo.group('header').strip() if sectname in self._sections: cursect = self._sections[sectname] elif sectname == cp.DEFAULTSECT: cursect = self._defaults else: cursect = self._dict((('__name__', sectname), )) self._sections[sectname] = cursect self._proxies[sectname] = None # So sections can't start with a continuation line optname = None # no section header in the file? elif cursect is None: raise cp.MissingSectionHeaderError(fpname, lineno, line) # an option line? elif not is_multi_line: mo = self.OPTCRE.match(line) if mo: # We might just have handled the last line, which could contain a quotation we want to remove optname, vi, optval = mo.group('option', 'vi', 'value') if vi in ('=', ':') and ';' in optval and not optval.strip( ).startswith('"'): pos = optval.find(';') if pos != -1 and optval[pos - 1].isspace(): optval = optval[:pos] optval = optval.strip() if optval == '""': optval = '' # end handle empty string optname = self.optionxform(optname.rstrip()) if len(optval ) > 1 and optval[0] == '"' and optval[-1] != '"': is_multi_line = True optval = string_decode(optval[1:]) # end handle multi-line # preserves multiple values for duplicate optnames cursect.add(optname, optval) else: # check if it's an option with no value - it's just ignored by git if not self.OPTVALUEONLY.match(line): if not e: e = cp.ParsingError(fpname) e.append(lineno, repr(line)) continue else: line = line.rstrip() if line.endswith('"'): is_multi_line = False line = line[:-1] # end handle quotations optval = cursect.getlast(optname) cursect.setlast(optname, optval + string_decode(line)) # END parse section or option # END while reading # if any parsing errors occurred, raise an exception if e: raise e
def _read(self, fp, fpname): cursect = None optname = None lineno = 0 is_multi_line = False e = None def string_decode(v): if v[-1] == '\\': v = v[:-1] # end cut trailing escapes to prevent decode error if PY3: return v.encode(defenc).decode('unicode_escape') else: return v.decode('string_escape') # end # end while True: # we assume to read binary ! line = fp.readline().decode(defenc) if not line: break lineno = lineno + 1 # comment or blank line? if line.strip() == '' or self.re_comment.match(line): continue if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR": # no leading whitespace continue # is it a section header? mo = self.SECTCRE.match(line.strip()) if not is_multi_line and mo: sectname = mo.group('header').strip() if sectname in self._sections: cursect = self._sections[sectname] elif sectname == cp.DEFAULTSECT: cursect = self._defaults else: cursect = self._dict((('__name__', sectname), )) self._sections[sectname] = cursect self._proxies[sectname] = None # So sections can't start with a continuation line optname = None # no section header in the file? elif cursect is None: raise cp.MissingSectionHeaderError(fpname, lineno, line) # an option line? elif not is_multi_line: mo = self.OPTCRE.match(line) if mo: # We might just have handled the last line, which could # contain a quotation we want to remove optname, vi, optval = mo.group('option', 'vi', 'value') if vi in ('=', ':') and ';' in optval and not optval.strip( ).startswith('"'): pos = optval.find(';') if pos != -1 and optval[pos - 1].isspace(): optval = optval[:pos] optval = optval.strip() if optval == '""': optval = '' # end handle empty string optname = self.optionxform(optname.rstrip()) if len(optval ) > 1 and optval[0] == '"' and optval[-1] != '"': is_multi_line = True optval = string_decode(optval[1:]) # end handle multi-line cursect[optname] = optval else: if not self.OPTVALUEONLY.match(line): if not e: e = cp.ParsingError(fpname) e.append(lineno, repr(line)) continue else: line = line.rstrip() if line.endswith('"'): is_multi_line = False line = line[:-1] # end handle quotations cursect[optname] += string_decode(line) # END parse section or option # END while reading # if any parsing errors occurred, raise an exception if e: raise e
def _read(self, fp, fpname): """Parse a sectioned setup file. The sections in setup file contains a title line at the top, indicated by a name in square brackets (`[]'), plus key/value options lines, indicated by `name: value' format lines. Continuations are represented by an embedded newline then leading whitespace. Blank lines, lines beginning with a '#', and just about everything else are ignored. """ cursect = None # None, or a dictionary optname = None lineno = 0 e = None # None, or an exception while True: line = fp.readline() if not line: break lineno = lineno + 1 # comment or blank line? if line.strip() == '' or line[0] in '#;': continue if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR": # no leading whitespace continue # continuation line? if line[0].isspace() and cursect is not None and optname: value = line.strip() if value: cursect[optname].append(value) # a section header or option header? else: # is it a section header? mo = self.SECTCRE.match(line) if mo: sectname = mo.group('header') if sectname in self._sections: cursect = self._sections[sectname] elif sectname == 'DEFAULT': cursect = self._defaults else: cursect = self._dict() cursect['__name__'] = sectname self._sections[sectname] = cursect # So sections can't start with a continuation line optname = None # no section header in the file? elif cursect is None: raise configparser.MissingSectionHeaderError( fpname, lineno, line) # an option line? else: mo = self._optcre.match(line) if mo: optname, vi, optval = mo.group('option', 'vi', 'value') optname = self.optionxform(optname.rstrip()) # This check is fine because the OPTCRE cannot # match if it would set optval to None if optval is not None: # XXX Added support for '#' inline comments if vi in ('=', ':') and (';' in optval or '#' in optval): # strip comments optval = re.split(r'\s+(;|#)', optval)[0] # if what is left is comment as a value, fallback to an empty string # that is: `foo = ;` would mean `foo` is '', which brings parity with # what ceph-conf tool does if optval in [';', '#']: optval = '' optval = optval.strip() # allow empty values if optval == '""': optval = '' cursect[optname] = [optval] else: # valueless option handling cursect[optname] = optval else: # a non-fatal parsing error occurred. set up the # exception but keep going. the exception will be # raised at the end of the file and will contain a # list of all bogus lines if not e: e = configparser.ParsingError(fpname) e.append(lineno, repr(line)) # if any parsing errors occurred, raise an exception if e: raise e # join the multi-line values collected while reading all_sections = [self._defaults] all_sections.extend(self._sections.values()) for options in all_sections: for name, val in options.items(): if isinstance(val, list): options[name] = '\n'.join(val)
def _read(self, fp, fpname): """Parse a sectioned setup file. The sections in setup file contains a title line at the top, indicated by a name in square brackets (`[]'), plus key/value options lines, indicated by `name: value' format lines. Continuations are represented by an embedded newline then leading whitespace. Blank lines, lines beginning with a '#', and just about everything else are ignored. """ cursect = None # None, or a dictionary optname = None lineno = 0 e = None # None, or an exception while True: line = fp.readline() if not line: break lineno = lineno + 1 # comment or blank line? if line.strip() == '' or line[0] in '#;': self._sections.add_other(cursect, line) continue if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR": # no leading whitespace continue # continuation line? if line[0].isspace() and cursect is not None and optname: value = line.strip() if value: #cursect[optname] = "%s\n%s" % (cursect[optname], value) #self.set(cursect, optname, "%s\n%s" % (self.get(cursect, optname), value)) if cursect == configparser.DEFAULTSECT: self._defaults[optname] = "%s\n%s" % ( self._defaults[optname], value) else: # use the raw value here (original version uses raw=False) self._sections[cursect]._find( optname).value = '%s\n%s' % (self.get( cursect, optname, raw=True), value) # a section header or option header? else: # is it a section header? mo = self.SECTCRE.match(line) if mo: sectname = mo.group('header') if sectname in self._sections: cursect = self._sections[sectname] elif sectname == configparser.DEFAULTSECT: cursect = self._defaults else: #cursect = {'__name__': sectname} #self._sections[sectname] = cursect self.add_section(sectname) self.set(sectname, '__name__', sectname) # So sections can't start with a continuation line cursect = sectname optname = None # no section header in the file? elif cursect is None: raise configparser.MissingSectionHeaderError( fpname, lineno, line) # an option line? else: mo = self.OPTCRE.match(line) if mo: optname, vi, optval = mo.group('option', 'vi', 'value') if vi in ('=', ':') and ';' in optval: # ';' is a comment delimiter only if it follows # a spacing character pos = optval.find(';') if pos != -1 and optval[pos - 1].isspace(): optval = optval[:pos] optval = optval.strip() # allow empty values if optval == '""': optval = '' optname = self.optionxform(optname.rstrip()) if cursect == configparser.DEFAULTSECT: self._defaults[optname] = optval else: self._sections[cursect]._add_option(optname, line=line) else: # a non-fatal parsing error occurred. set up the # exception but keep going. the exception will be # raised at the end of the file and will contain a # list of all bogus lines if not e: e = configparser.ParsingError(fpname) e.append(lineno, repr(line)) # if any parsing errors occurred, raise an exception if e: raise e # pylint: disable-msg=E0702
def _configparser_convert_str(x): result = literal_eval(x) if not isinstance(result, str): raise configparser.ParsingError(f"Needs to be a string type: {x}") return result
def _read(self, fp, fpname): u"""Parse a sectioned setup file. The sections in setup file contains a title line at the top, indicated by a name in square brackets (`[]'), plus key/value options lines, indicated by `name: value' format lines. Continuations are represented by an embedded newline then leading whitespace. Blank lines, lines beginning with a '#', and just about everything else are ignored. """ cursect = None # None, or a dictionary optname = None lineno = 0 e = None # None, or an exception while True: line = fp.readline() if not line: break lineno = lineno + 1 # comment or blank line? if line.strip() == '' or line[0] in '#;': continue if line.split(None, 1)[0].lower() == 'rem' and line[0] in "rR": # no leading whitespace continue # continuation line? if line[0].isspace() and cursect is not None and optname: value = line.strip() if value: cursect[optname].append(value) # a section header or option header? else: #JAZ add environment variable expansion if not getattr(self, 'no_expand_vars', False): line = os.path.expandvars(line) # is it a section header? mo = self.SECTCRE.match(line) if mo: sectname = mo.group('header') if sectname in self._sections: cursect = self._sections[sectname] elif sectname == configparser.DEFAULTSECT: cursect = self._defaults else: cursect = self._dict() self._sections[sectname] = cursect # So sections can't start with a continuation line optname = None # no section header in the file? elif line.lower().startswith('%include'): if not getattr(self, 'no_expand_includes', False): include_statement, filename = line.split() filename = filename.strip('"').strip("'") sys.stdout.write("Reading included ini file: `" + filename + "'\n") if not os.path.exists(filename): # TODO: remove direct sys.stderr writes raise ValueError("Tried to include non-existent " "ini file: `" + filename + "'\n") self.read(filename) cursect = None elif cursect is None: raise configparser.MissingSectionHeaderError( fpname, lineno, line) # an option line? else: mo = self._optcre.match(line) if mo: optname, vi, optval = mo.group('option', 'vi', 'value') optname = self.optionxform(optname.rstrip()) # This check is fine because the OPTCRE cannot # match if it would set optval to None if optval is not None: if vi in ('=', ':') and ';' in optval: # ';' is a comment delimiter only if it # follows a spacing character pos = optval.find(';') if pos != -1 and optval[pos - 1].isspace(): optval = optval[:pos] optval = optval.strip() # allow empty values if optval == '""': optval = '' cursect[optname] = [optval] else: # valueless option handling cursect[optname] = optval else: # a non-fatal parsing error occurred. set up the # exception but keep going. the exception will be # raised at the end of the file and will contain # a list of all bogus lines if not e: e = configparser.ParsingError(fpname) e.append(lineno, repr(line)) # if any parsing errors occurred, raise an exception if e: raise e # join the multi-line values collected while reading all_sections = [self._defaults] all_sections.extend(list(self._sections.values())) for options in all_sections: for name, val in list(options.items()): if isinstance(val, list): options[name] = '\n'.join(val)
def __init__(self, config_file_list): self.log = log.getChild(self.__class__.__name__) try: parser = configparser.SafeConfigParser() # Enable Extended Interpolation - allow values from one section # to be referenced from another section. parser._interpolation = configparser.ExtendedInterpolation() # Attempt to read and parse a list of filenames, returning a list # of filenames which were successfully parsed. If none of the # filenames exist, the configparser instance will contain an empty # dataset. processed_files = parser.read(config_file_list) self.log.debug("CONFIG: Config files processed: %s", processed_files) # FIXME: We can either pass a verified list of files to the parser # OR we can verify the number of processed files is 1 or greater. if len(processed_files) < 1: # Just raise the standard parsing error exception instead # of trying to handle a missing file differently than one # with parsing errors. We may change this later if found # to be too confusing. raise configparser.ParsingError(config_file_list) except configparser.ParsingError as error: self.log.exception("Unable to parse config file: %s", error) sys.exit(1) # Begin building object by creating dictionary member attributes # from config file sections/values. self.flags = {} self.mysqldb_config = {} self.queries = {} # Likely will be removed at some point self.notification_servers = {} # Not directly referenced yet, but exposing for future use self.email = {} try: # Grab all values from section as tuple pairs and convert # to dictionaries for easy reference # Not directly referenced yet, but exposing for future use self.email = dict(parser.items('email')) self.flags = dict(parser.items('flags')) self.mysqldb_config = dict(parser.items('mysqldb_config')) self.queries = dict(parser.items('queries')) # FIXME: This name will likely need adjusting later # to match whatever new section name is chosen for the config file self.notification_servers = dict(parser.items('notification_servers')) # FIXME: Is there a better to handle this? # This is a one-off boolean flag from a separate section self.mysqldb_config['raise_on_warnings'] = \ parser.getboolean('mysqldb_config', 'raise_on_warnings') # Convert text "boolean" flag values to true boolean values for key in self.flags: self.flags[key] = parser.getboolean('flags', key) self.log.debug("%s has a value of %s and a type of %s", key, self.flags[key], type(self.flags[key])) except configparser.NoSectionError as error: self.log.exception("Unable to parse config file: %s", error) sys.exit(1)