Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/configparser.py: 22%

696 statements  

« prev     ^ index     » next       coverage.py v7.0.1, created at 2022-12-25 06:11 +0000

1"""Configuration file parser. 

2 

3A configuration file consists of sections, lead by a "[section]" header, 

4and followed by "name: value" entries, with continuations and such in 

5the style of RFC 822. 

6 

7Intrinsic defaults can be specified by passing them into the 

8ConfigParser constructor as a dictionary. 

9 

10class: 

11 

12ConfigParser -- responsible for parsing a list of 

13 configuration files, and managing the parsed database. 

14 

15 methods: 

16 

17 __init__(defaults=None, dict_type=_default_dict, allow_no_value=False, 

18 delimiters=('=', ':'), comment_prefixes=('#', ';'), 

19 inline_comment_prefixes=None, strict=True, 

20 empty_lines_in_values=True, default_section='DEFAULT', 

21 interpolation=<unset>, converters=<unset>): 

22 Create the parser. When `defaults' is given, it is initialized into the 

23 dictionary or intrinsic defaults. The keys must be strings, the values 

24 must be appropriate for %()s string interpolation. 

25 

26 When `dict_type' is given, it will be used to create the dictionary 

27 objects for the list of sections, for the options within a section, and 

28 for the default values. 

29 

30 When `delimiters' is given, it will be used as the set of substrings 

31 that divide keys from values. 

32 

33 When `comment_prefixes' is given, it will be used as the set of 

34 substrings that prefix comments in empty lines. Comments can be 

35 indented. 

36 

37 When `inline_comment_prefixes' is given, it will be used as the set of 

38 substrings that prefix comments in non-empty lines. 

39 

40 When `strict` is True, the parser won't allow for any section or option 

41 duplicates while reading from a single source (file, string or 

42 dictionary). Default is True. 

43 

44 When `empty_lines_in_values' is False (default: True), each empty line 

45 marks the end of an option. Otherwise, internal empty lines of 

46 a multiline option are kept as part of the value. 

47 

48 When `allow_no_value' is True (default: False), options without 

49 values are accepted; the value presented for these is None. 

50 

51 When `default_section' is given, the name of the special section is 

52 named accordingly. By default it is called ``"DEFAULT"`` but this can 

53 be customized to point to any other valid section name. Its current 

54 value can be retrieved using the ``parser_instance.default_section`` 

55 attribute and may be modified at runtime. 

56 

57 When `interpolation` is given, it should be an Interpolation subclass 

58 instance. It will be used as the handler for option value 

59 pre-processing when using getters. RawConfigParser objects don't do 

60 any sort of interpolation, whereas ConfigParser uses an instance of 

61 BasicInterpolation. The library also provides a ``zc.buildbot`` 

62 inspired ExtendedInterpolation implementation. 

63 

64 When `converters` is given, it should be a dictionary where each key 

65 represents the name of a type converter and each value is a callable 

66 implementing the conversion from string to the desired datatype. Every 

67 converter gets its corresponding get*() method on the parser object and 

68 section proxies. 

69 

70 sections() 

71 Return all the configuration section names, sans DEFAULT. 

72 

73 has_section(section) 

74 Return whether the given section exists. 

75 

76 has_option(section, option) 

77 Return whether the given option exists in the given section. 

78 

79 options(section) 

80 Return list of configuration options for the named section. 

81 

82 read(filenames, encoding=None) 

83 Read and parse the iterable of named configuration files, given by 

84 name. A single filename is also allowed. Non-existing files 

85 are ignored. Return list of successfully read files. 

86 

87 read_file(f, filename=None) 

88 Read and parse one configuration file, given as a file object. 

89 The filename defaults to f.name; it is only used in error 

90 messages (if f has no `name' attribute, the string `<???>' is used). 

91 

92 read_string(string) 

93 Read configuration from a given string. 

94 

95 read_dict(dictionary) 

96 Read configuration from a dictionary. Keys are section names, 

97 values are dictionaries with keys and values that should be present 

98 in the section. If the used dictionary type preserves order, sections 

99 and their keys will be added in order. Values are automatically 

100 converted to strings. 

101 

102 get(section, option, raw=False, vars=None, fallback=_UNSET) 

103 Return a string value for the named option. All % interpolations are 

104 expanded in the return values, based on the defaults passed into the 

105 constructor and the DEFAULT section. Additional substitutions may be 

106 provided using the `vars' argument, which must be a dictionary whose 

107 contents override any pre-existing defaults. If `option' is a key in 

108 `vars', the value from `vars' is used. 

109 

110 getint(section, options, raw=False, vars=None, fallback=_UNSET) 

111 Like get(), but convert value to an integer. 

112 

113 getfloat(section, options, raw=False, vars=None, fallback=_UNSET) 

114 Like get(), but convert value to a float. 

115 

116 getboolean(section, options, raw=False, vars=None, fallback=_UNSET) 

117 Like get(), but convert value to a boolean (currently case 

118 insensitively defined as 0, false, no, off for False, and 1, true, 

119 yes, on for True). Returns False or True. 

120 

121 items(section=_UNSET, raw=False, vars=None) 

122 If section is given, return a list of tuples with (name, value) for 

123 each option in the section. Otherwise, return a list of tuples with 

124 (section_name, section_proxy) for each section, including DEFAULTSECT. 

125 

126 remove_section(section) 

127 Remove the given file section and all its options. 

128 

129 remove_option(section, option) 

130 Remove the given option from the given section. 

131 

132 set(section, option, value) 

133 Set the given option. 

134 

135 write(fp, space_around_delimiters=True) 

136 Write the configuration state in .ini format. If 

137 `space_around_delimiters' is True (the default), delimiters 

138 between keys and values are surrounded by spaces. 

139""" 

140 

141from collections.abc import MutableMapping 

142from collections import ChainMap as _ChainMap 

143import functools 

144import io 

145import itertools 

146import os 

147import re 

148import sys 

149import warnings 

150 

151__all__ = ["NoSectionError", "DuplicateOptionError", "DuplicateSectionError", 

152 "NoOptionError", "InterpolationError", "InterpolationDepthError", 

153 "InterpolationMissingOptionError", "InterpolationSyntaxError", 

154 "ParsingError", "MissingSectionHeaderError", 

155 "ConfigParser", "SafeConfigParser", "RawConfigParser", 

156 "Interpolation", "BasicInterpolation", "ExtendedInterpolation", 

157 "LegacyInterpolation", "SectionProxy", "ConverterMapping", 

158 "DEFAULTSECT", "MAX_INTERPOLATION_DEPTH"] 

159 

160_default_dict = dict 

161DEFAULTSECT = "DEFAULT" 

162 

163MAX_INTERPOLATION_DEPTH = 10 

164 

165 

166 

167# exception classes 

168class Error(Exception): 

169 """Base class for ConfigParser exceptions.""" 

170 

171 def __init__(self, msg=''): 

172 self.message = msg 

173 Exception.__init__(self, msg) 

174 

175 def __repr__(self): 

176 return self.message 

177 

178 __str__ = __repr__ 

179 

180 

181class NoSectionError(Error): 

182 """Raised when no section matches a requested option.""" 

183 

184 def __init__(self, section): 

185 Error.__init__(self, 'No section: %r' % (section,)) 

186 self.section = section 

187 self.args = (section, ) 

188 

189 

190class DuplicateSectionError(Error): 

191 """Raised when a section is repeated in an input source. 

192 

193 Possible repetitions that raise this exception are: multiple creation 

194 using the API or in strict parsers when a section is found more than once 

195 in a single input file, string or dictionary. 

196 """ 

197 

198 def __init__(self, section, source=None, lineno=None): 

199 msg = [repr(section), " already exists"] 

200 if source is not None: 

201 message = ["While reading from ", repr(source)] 

202 if lineno is not None: 

203 message.append(" [line {0:2d}]".format(lineno)) 

204 message.append(": section ") 

205 message.extend(msg) 

206 msg = message 

207 else: 

208 msg.insert(0, "Section ") 

209 Error.__init__(self, "".join(msg)) 

210 self.section = section 

211 self.source = source 

212 self.lineno = lineno 

213 self.args = (section, source, lineno) 

214 

215 

216class DuplicateOptionError(Error): 

217 """Raised by strict parsers when an option is repeated in an input source. 

218 

219 Current implementation raises this exception only when an option is found 

220 more than once in a single file, string or dictionary. 

221 """ 

222 

223 def __init__(self, section, option, source=None, lineno=None): 

224 msg = [repr(option), " in section ", repr(section), 

225 " already exists"] 

226 if source is not None: 

227 message = ["While reading from ", repr(source)] 

228 if lineno is not None: 

229 message.append(" [line {0:2d}]".format(lineno)) 

230 message.append(": option ") 

231 message.extend(msg) 

232 msg = message 

233 else: 

234 msg.insert(0, "Option ") 

235 Error.__init__(self, "".join(msg)) 

236 self.section = section 

237 self.option = option 

238 self.source = source 

239 self.lineno = lineno 

240 self.args = (section, option, source, lineno) 

241 

242 

243class NoOptionError(Error): 

244 """A requested option was not found.""" 

245 

246 def __init__(self, option, section): 

247 Error.__init__(self, "No option %r in section: %r" % 

248 (option, section)) 

249 self.option = option 

250 self.section = section 

251 self.args = (option, section) 

252 

253 

254class InterpolationError(Error): 

255 """Base class for interpolation-related exceptions.""" 

256 

257 def __init__(self, option, section, msg): 

258 Error.__init__(self, msg) 

259 self.option = option 

260 self.section = section 

261 self.args = (option, section, msg) 

262 

263 

264class InterpolationMissingOptionError(InterpolationError): 

265 """A string substitution required a setting which was not available.""" 

266 

267 def __init__(self, option, section, rawval, reference): 

268 msg = ("Bad value substitution: option {!r} in section {!r} contains " 

269 "an interpolation key {!r} which is not a valid option name. " 

270 "Raw value: {!r}".format(option, section, reference, rawval)) 

271 InterpolationError.__init__(self, option, section, msg) 

272 self.reference = reference 

273 self.args = (option, section, rawval, reference) 

274 

275 

276class InterpolationSyntaxError(InterpolationError): 

277 """Raised when the source text contains invalid syntax. 

278 

279 Current implementation raises this exception when the source text into 

280 which substitutions are made does not conform to the required syntax. 

281 """ 

282 

283 

284class InterpolationDepthError(InterpolationError): 

285 """Raised when substitutions are nested too deeply.""" 

286 

287 def __init__(self, option, section, rawval): 

288 msg = ("Recursion limit exceeded in value substitution: option {!r} " 

289 "in section {!r} contains an interpolation key which " 

290 "cannot be substituted in {} steps. Raw value: {!r}" 

291 "".format(option, section, MAX_INTERPOLATION_DEPTH, 

292 rawval)) 

293 InterpolationError.__init__(self, option, section, msg) 

294 self.args = (option, section, rawval) 

295 

296 

297class ParsingError(Error): 

298 """Raised when a configuration file does not follow legal syntax.""" 

299 

300 def __init__(self, source=None, filename=None): 

301 # Exactly one of `source'/`filename' arguments has to be given. 

302 # `filename' kept for compatibility. 

303 if filename and source: 

304 raise ValueError("Cannot specify both `filename' and `source'. " 

305 "Use `source'.") 

306 elif not filename and not source: 

307 raise ValueError("Required argument `source' not given.") 

308 elif filename: 

309 source = filename 

310 Error.__init__(self, 'Source contains parsing errors: %r' % source) 

311 self.source = source 

312 self.errors = [] 

313 self.args = (source, ) 

314 

315 @property 

316 def filename(self): 

317 """Deprecated, use `source'.""" 

318 warnings.warn( 

319 "The 'filename' attribute will be removed in future versions. " 

320 "Use 'source' instead.", 

321 DeprecationWarning, stacklevel=2 

322 ) 

323 return self.source 

324 

325 @filename.setter 

326 def filename(self, value): 

327 """Deprecated, user `source'.""" 

328 warnings.warn( 

329 "The 'filename' attribute will be removed in future versions. " 

330 "Use 'source' instead.", 

331 DeprecationWarning, stacklevel=2 

332 ) 

333 self.source = value 

334 

335 def append(self, lineno, line): 

336 self.errors.append((lineno, line)) 

337 self.message += '\n\t[line %2d]: %s' % (lineno, line) 

338 

339 

340class MissingSectionHeaderError(ParsingError): 

341 """Raised when a key-value pair is found before any section header.""" 

342 

343 def __init__(self, filename, lineno, line): 

344 Error.__init__( 

345 self, 

346 'File contains no section headers.\nfile: %r, line: %d\n%r' % 

347 (filename, lineno, line)) 

348 self.source = filename 

349 self.lineno = lineno 

350 self.line = line 

351 self.args = (filename, lineno, line) 

352 

353 

354# Used in parser getters to indicate the default behaviour when a specific 

355# option is not found it to raise an exception. Created to enable `None' as 

356# a valid fallback value. 

357_UNSET = object() 

358 

359 

360class Interpolation: 

361 """Dummy interpolation that passes the value through with no changes.""" 

362 

363 def before_get(self, parser, section, option, value, defaults): 

364 return value 

365 

366 def before_set(self, parser, section, option, value): 

367 return value 

368 

369 def before_read(self, parser, section, option, value): 

370 return value 

371 

372 def before_write(self, parser, section, option, value): 

373 return value 

374 

375 

376class BasicInterpolation(Interpolation): 

377 """Interpolation as implemented in the classic ConfigParser. 

378 

379 The option values can contain format strings which refer to other values in 

380 the same section, or values in the special default section. 

381 

382 For example: 

383 

384 something: %(dir)s/whatever 

385 

386 would resolve the "%(dir)s" to the value of dir. All reference 

387 expansions are done late, on demand. If a user needs to use a bare % in 

388 a configuration file, she can escape it by writing %%. Other % usage 

389 is considered a user error and raises `InterpolationSyntaxError'.""" 

390 

391 _KEYCRE = re.compile(r"%\(([^)]+)\)s") 

392 

393 def before_get(self, parser, section, option, value, defaults): 

394 L = [] 

395 self._interpolate_some(parser, option, L, value, section, defaults, 1) 

396 return ''.join(L) 

397 

398 def before_set(self, parser, section, option, value): 

399 tmp_value = value.replace('%%', '') # escaped percent signs 

400 tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax 

401 if '%' in tmp_value: 

402 raise ValueError("invalid interpolation syntax in %r at " 

403 "position %d" % (value, tmp_value.find('%'))) 

404 return value 

405 

406 def _interpolate_some(self, parser, option, accum, rest, section, map, 

407 depth): 

408 rawval = parser.get(section, option, raw=True, fallback=rest) 

409 if depth > MAX_INTERPOLATION_DEPTH: 

410 raise InterpolationDepthError(option, section, rawval) 

411 while rest: 

412 p = rest.find("%") 

413 if p < 0: 

414 accum.append(rest) 

415 return 

416 if p > 0: 

417 accum.append(rest[:p]) 

418 rest = rest[p:] 

419 # p is no longer used 

420 c = rest[1:2] 

421 if c == "%": 

422 accum.append("%") 

423 rest = rest[2:] 

424 elif c == "(": 

425 m = self._KEYCRE.match(rest) 

426 if m is None: 

427 raise InterpolationSyntaxError(option, section, 

428 "bad interpolation variable reference %r" % rest) 

429 var = parser.optionxform(m.group(1)) 

430 rest = rest[m.end():] 

431 try: 

432 v = map[var] 

433 except KeyError: 

434 raise InterpolationMissingOptionError( 

435 option, section, rawval, var) from None 

436 if "%" in v: 

437 self._interpolate_some(parser, option, accum, v, 

438 section, map, depth + 1) 

439 else: 

440 accum.append(v) 

441 else: 

442 raise InterpolationSyntaxError( 

443 option, section, 

444 "'%%' must be followed by '%%' or '(', " 

445 "found: %r" % (rest,)) 

446 

447 

448class ExtendedInterpolation(Interpolation): 

449 """Advanced variant of interpolation, supports the syntax used by 

450 `zc.buildout'. Enables interpolation between sections.""" 

451 

452 _KEYCRE = re.compile(r"\$\{([^}]+)\}") 

453 

454 def before_get(self, parser, section, option, value, defaults): 

455 L = [] 

456 self._interpolate_some(parser, option, L, value, section, defaults, 1) 

457 return ''.join(L) 

458 

459 def before_set(self, parser, section, option, value): 

460 tmp_value = value.replace('$$', '') # escaped dollar signs 

461 tmp_value = self._KEYCRE.sub('', tmp_value) # valid syntax 

462 if '$' in tmp_value: 

463 raise ValueError("invalid interpolation syntax in %r at " 

464 "position %d" % (value, tmp_value.find('$'))) 

465 return value 

466 

467 def _interpolate_some(self, parser, option, accum, rest, section, map, 

468 depth): 

469 rawval = parser.get(section, option, raw=True, fallback=rest) 

470 if depth > MAX_INTERPOLATION_DEPTH: 

471 raise InterpolationDepthError(option, section, rawval) 

472 while rest: 

473 p = rest.find("$") 

474 if p < 0: 

475 accum.append(rest) 

476 return 

477 if p > 0: 

478 accum.append(rest[:p]) 

479 rest = rest[p:] 

480 # p is no longer used 

481 c = rest[1:2] 

482 if c == "$": 

483 accum.append("$") 

484 rest = rest[2:] 

485 elif c == "{": 

486 m = self._KEYCRE.match(rest) 

487 if m is None: 

488 raise InterpolationSyntaxError(option, section, 

489 "bad interpolation variable reference %r" % rest) 

490 path = m.group(1).split(':') 

491 rest = rest[m.end():] 

492 sect = section 

493 opt = option 

494 try: 

495 if len(path) == 1: 

496 opt = parser.optionxform(path[0]) 

497 v = map[opt] 

498 elif len(path) == 2: 

499 sect = path[0] 

500 opt = parser.optionxform(path[1]) 

501 v = parser.get(sect, opt, raw=True) 

502 else: 

503 raise InterpolationSyntaxError( 

504 option, section, 

505 "More than one ':' found: %r" % (rest,)) 

506 except (KeyError, NoSectionError, NoOptionError): 

507 raise InterpolationMissingOptionError( 

508 option, section, rawval, ":".join(path)) from None 

509 if "$" in v: 

510 self._interpolate_some(parser, opt, accum, v, sect, 

511 dict(parser.items(sect, raw=True)), 

512 depth + 1) 

513 else: 

514 accum.append(v) 

515 else: 

516 raise InterpolationSyntaxError( 

517 option, section, 

518 "'$' must be followed by '$' or '{', " 

519 "found: %r" % (rest,)) 

520 

521 

522class LegacyInterpolation(Interpolation): 

523 """Deprecated interpolation used in old versions of ConfigParser. 

524 Use BasicInterpolation or ExtendedInterpolation instead.""" 

525 

526 _KEYCRE = re.compile(r"%\(([^)]*)\)s|.") 

527 

528 def before_get(self, parser, section, option, value, vars): 

529 rawval = value 

530 depth = MAX_INTERPOLATION_DEPTH 

531 while depth: # Loop through this until it's done 

532 depth -= 1 

533 if value and "%(" in value: 

534 replace = functools.partial(self._interpolation_replace, 

535 parser=parser) 

536 value = self._KEYCRE.sub(replace, value) 

537 try: 

538 value = value % vars 

539 except KeyError as e: 

540 raise InterpolationMissingOptionError( 

541 option, section, rawval, e.args[0]) from None 

542 else: 

543 break 

544 if value and "%(" in value: 

545 raise InterpolationDepthError(option, section, rawval) 

546 return value 

547 

548 def before_set(self, parser, section, option, value): 

549 return value 

550 

551 @staticmethod 

552 def _interpolation_replace(match, parser): 

553 s = match.group(1) 

554 if s is None: 

555 return match.group() 

556 else: 

557 return "%%(%s)s" % parser.optionxform(s) 

558 

559 

560class RawConfigParser(MutableMapping): 

561 """ConfigParser that does not do interpolation.""" 

562 

563 # Regular expressions for parsing section headers and options 

564 _SECT_TMPL = r""" 

565 \[ # [ 

566 (?P<header>[^]]+) # very permissive! 

567 \] # ] 

568 """ 

569 _OPT_TMPL = r""" 

570 (?P<option>.*?) # very permissive! 

571 \s*(?P<vi>{delim})\s* # any number of space/tab, 

572 # followed by any of the 

573 # allowed delimiters, 

574 # followed by any space/tab 

575 (?P<value>.*)$ # everything up to eol 

576 """ 

577 _OPT_NV_TMPL = r""" 

578 (?P<option>.*?) # very permissive! 

579 \s*(?: # any number of space/tab, 

580 (?P<vi>{delim})\s* # optionally followed by 

581 # any of the allowed 

582 # delimiters, followed by any 

583 # space/tab 

584 (?P<value>.*))?$ # everything up to eol 

585 """ 

586 # Interpolation algorithm to be used if the user does not specify another 

587 _DEFAULT_INTERPOLATION = Interpolation() 

588 # Compiled regular expression for matching sections 

589 SECTCRE = re.compile(_SECT_TMPL, re.VERBOSE) 

590 # Compiled regular expression for matching options with typical separators 

591 OPTCRE = re.compile(_OPT_TMPL.format(delim="=|:"), re.VERBOSE) 

592 # Compiled regular expression for matching options with optional values 

593 # delimited using typical separators 

594 OPTCRE_NV = re.compile(_OPT_NV_TMPL.format(delim="=|:"), re.VERBOSE) 

595 # Compiled regular expression for matching leading whitespace in a line 

596 NONSPACECRE = re.compile(r"\S") 

597 # Possible boolean values in the configuration. 

598 BOOLEAN_STATES = {'1': True, 'yes': True, 'true': True, 'on': True, 

599 '0': False, 'no': False, 'false': False, 'off': False} 

600 

601 def __init__(self, defaults=None, dict_type=_default_dict, 

602 allow_no_value=False, *, delimiters=('=', ':'), 

603 comment_prefixes=('#', ';'), inline_comment_prefixes=None, 

604 strict=True, empty_lines_in_values=True, 

605 default_section=DEFAULTSECT, 

606 interpolation=_UNSET, converters=_UNSET): 

607 

608 self._dict = dict_type 

609 self._sections = self._dict() 

610 self._defaults = self._dict() 

611 self._converters = ConverterMapping(self) 

612 self._proxies = self._dict() 

613 self._proxies[default_section] = SectionProxy(self, default_section) 

614 self._delimiters = tuple(delimiters) 

615 if delimiters == ('=', ':'): 

616 self._optcre = self.OPTCRE_NV if allow_no_value else self.OPTCRE 

617 else: 

618 d = "|".join(re.escape(d) for d in delimiters) 

619 if allow_no_value: 

620 self._optcre = re.compile(self._OPT_NV_TMPL.format(delim=d), 

621 re.VERBOSE) 

622 else: 

623 self._optcre = re.compile(self._OPT_TMPL.format(delim=d), 

624 re.VERBOSE) 

625 self._comment_prefixes = tuple(comment_prefixes or ()) 

626 self._inline_comment_prefixes = tuple(inline_comment_prefixes or ()) 

627 self._strict = strict 

628 self._allow_no_value = allow_no_value 

629 self._empty_lines_in_values = empty_lines_in_values 

630 self.default_section=default_section 

631 self._interpolation = interpolation 

632 if self._interpolation is _UNSET: 

633 self._interpolation = self._DEFAULT_INTERPOLATION 

634 if self._interpolation is None: 

635 self._interpolation = Interpolation() 

636 if converters is not _UNSET: 

637 self._converters.update(converters) 

638 if defaults: 

639 self._read_defaults(defaults) 

640 

641 def defaults(self): 

642 return self._defaults 

643 

644 def sections(self): 

645 """Return a list of section names, excluding [DEFAULT]""" 

646 # self._sections will never have [DEFAULT] in it 

647 return list(self._sections.keys()) 

648 

649 def add_section(self, section): 

650 """Create a new section in the configuration. 

651 

652 Raise DuplicateSectionError if a section by the specified name 

653 already exists. Raise ValueError if name is DEFAULT. 

654 """ 

655 if section == self.default_section: 

656 raise ValueError('Invalid section name: %r' % section) 

657 

658 if section in self._sections: 

659 raise DuplicateSectionError(section) 

660 self._sections[section] = self._dict() 

661 self._proxies[section] = SectionProxy(self, section) 

662 

663 def has_section(self, section): 

664 """Indicate whether the named section is present in the configuration. 

665 

666 The DEFAULT section is not acknowledged. 

667 """ 

668 return section in self._sections 

669 

670 def options(self, section): 

671 """Return a list of option names for the given section name.""" 

672 try: 

673 opts = self._sections[section].copy() 

674 except KeyError: 

675 raise NoSectionError(section) from None 

676 opts.update(self._defaults) 

677 return list(opts.keys()) 

678 

679 def read(self, filenames, encoding=None): 

680 """Read and parse a filename or an iterable of filenames. 

681 

682 Files that cannot be opened are silently ignored; this is 

683 designed so that you can specify an iterable of potential 

684 configuration file locations (e.g. current directory, user's 

685 home directory, systemwide directory), and all existing 

686 configuration files in the iterable will be read. A single 

687 filename may also be given. 

688 

689 Return list of successfully read files. 

690 """ 

691 if isinstance(filenames, (str, bytes, os.PathLike)): 

692 filenames = [filenames] 

693 read_ok = [] 

694 for filename in filenames: 

695 try: 

696 with open(filename, encoding=encoding) as fp: 

697 self._read(fp, filename) 

698 except OSError: 

699 continue 

700 if isinstance(filename, os.PathLike): 

701 filename = os.fspath(filename) 

702 read_ok.append(filename) 

703 return read_ok 

704 

705 def read_file(self, f, source=None): 

706 """Like read() but the argument must be a file-like object. 

707 

708 The `f' argument must be iterable, returning one line at a time. 

709 Optional second argument is the `source' specifying the name of the 

710 file being read. If not given, it is taken from f.name. If `f' has no 

711 `name' attribute, `<???>' is used. 

712 """ 

713 if source is None: 

714 try: 

715 source = f.name 

716 except AttributeError: 

717 source = '<???>' 

718 self._read(f, source) 

719 

720 def read_string(self, string, source='<string>'): 

721 """Read configuration from a given string.""" 

722 sfile = io.StringIO(string) 

723 self.read_file(sfile, source) 

724 

725 def read_dict(self, dictionary, source='<dict>'): 

726 """Read configuration from a dictionary. 

727 

728 Keys are section names, values are dictionaries with keys and values 

729 that should be present in the section. If the used dictionary type 

730 preserves order, sections and their keys will be added in order. 

731 

732 All types held in the dictionary are converted to strings during 

733 reading, including section names, option names and keys. 

734 

735 Optional second argument is the `source' specifying the name of the 

736 dictionary being read. 

737 """ 

738 elements_added = set() 

739 for section, keys in dictionary.items(): 

740 section = str(section) 

741 try: 

742 self.add_section(section) 

743 except (DuplicateSectionError, ValueError): 

744 if self._strict and section in elements_added: 

745 raise 

746 elements_added.add(section) 

747 for key, value in keys.items(): 

748 key = self.optionxform(str(key)) 

749 if value is not None: 

750 value = str(value) 

751 if self._strict and (section, key) in elements_added: 

752 raise DuplicateOptionError(section, key, source) 

753 elements_added.add((section, key)) 

754 self.set(section, key, value) 

755 

756 def readfp(self, fp, filename=None): 

757 """Deprecated, use read_file instead.""" 

758 warnings.warn( 

759 "This method will be removed in future versions. " 

760 "Use 'parser.read_file()' instead.", 

761 DeprecationWarning, stacklevel=2 

762 ) 

763 self.read_file(fp, source=filename) 

764 

765 def get(self, section, option, *, raw=False, vars=None, fallback=_UNSET): 

766 """Get an option value for a given section. 

767 

768 If `vars' is provided, it must be a dictionary. The option is looked up 

769 in `vars' (if provided), `section', and in `DEFAULTSECT' in that order. 

770 If the key is not found and `fallback' is provided, it is used as 

771 a fallback value. `None' can be provided as a `fallback' value. 

772 

773 If interpolation is enabled and the optional argument `raw' is False, 

774 all interpolations are expanded in the return values. 

775 

776 Arguments `raw', `vars', and `fallback' are keyword only. 

777 

778 The section DEFAULT is special. 

779 """ 

780 try: 

781 d = self._unify_values(section, vars) 

782 except NoSectionError: 

783 if fallback is _UNSET: 

784 raise 

785 else: 

786 return fallback 

787 option = self.optionxform(option) 

788 try: 

789 value = d[option] 

790 except KeyError: 

791 if fallback is _UNSET: 

792 raise NoOptionError(option, section) 

793 else: 

794 return fallback 

795 

796 if raw or value is None: 

797 return value 

798 else: 

799 return self._interpolation.before_get(self, section, option, value, 

800 d) 

801 

802 def _get(self, section, conv, option, **kwargs): 

803 return conv(self.get(section, option, **kwargs)) 

804 

805 def _get_conv(self, section, option, conv, *, raw=False, vars=None, 

806 fallback=_UNSET, **kwargs): 

807 try: 

808 return self._get(section, conv, option, raw=raw, vars=vars, 

809 **kwargs) 

810 except (NoSectionError, NoOptionError): 

811 if fallback is _UNSET: 

812 raise 

813 return fallback 

814 

815 # getint, getfloat and getboolean provided directly for backwards compat 

816 def getint(self, section, option, *, raw=False, vars=None, 

817 fallback=_UNSET, **kwargs): 

818 return self._get_conv(section, option, int, raw=raw, vars=vars, 

819 fallback=fallback, **kwargs) 

820 

821 def getfloat(self, section, option, *, raw=False, vars=None, 

822 fallback=_UNSET, **kwargs): 

823 return self._get_conv(section, option, float, raw=raw, vars=vars, 

824 fallback=fallback, **kwargs) 

825 

826 def getboolean(self, section, option, *, raw=False, vars=None, 

827 fallback=_UNSET, **kwargs): 

828 return self._get_conv(section, option, self._convert_to_boolean, 

829 raw=raw, vars=vars, fallback=fallback, **kwargs) 

830 

831 def items(self, section=_UNSET, raw=False, vars=None): 

832 """Return a list of (name, value) tuples for each option in a section. 

833 

834 All % interpolations are expanded in the return values, based on the 

835 defaults passed into the constructor, unless the optional argument 

836 `raw' is true. Additional substitutions may be provided using the 

837 `vars' argument, which must be a dictionary whose contents overrides 

838 any pre-existing defaults. 

839 

840 The section DEFAULT is special. 

841 """ 

842 if section is _UNSET: 

843 return super().items() 

844 d = self._defaults.copy() 

845 try: 

846 d.update(self._sections[section]) 

847 except KeyError: 

848 if section != self.default_section: 

849 raise NoSectionError(section) 

850 orig_keys = list(d.keys()) 

851 # Update with the entry specific variables 

852 if vars: 

853 for key, value in vars.items(): 

854 d[self.optionxform(key)] = value 

855 value_getter = lambda option: self._interpolation.before_get(self, 

856 section, option, d[option], d) 

857 if raw: 

858 value_getter = lambda option: d[option] 

859 return [(option, value_getter(option)) for option in orig_keys] 

860 

861 def popitem(self): 

862 """Remove a section from the parser and return it as 

863 a (section_name, section_proxy) tuple. If no section is present, raise 

864 KeyError. 

865 

866 The section DEFAULT is never returned because it cannot be removed. 

867 """ 

868 for key in self.sections(): 

869 value = self[key] 

870 del self[key] 

871 return key, value 

872 raise KeyError 

873 

874 def optionxform(self, optionstr): 

875 return optionstr.lower() 

876 

877 def has_option(self, section, option): 

878 """Check for the existence of a given option in a given section. 

879 If the specified `section' is None or an empty string, DEFAULT is 

880 assumed. If the specified `section' does not exist, returns False.""" 

881 if not section or section == self.default_section: 

882 option = self.optionxform(option) 

883 return option in self._defaults 

884 elif section not in self._sections: 

885 return False 

886 else: 

887 option = self.optionxform(option) 

888 return (option in self._sections[section] 

889 or option in self._defaults) 

890 

891 def set(self, section, option, value=None): 

892 """Set an option.""" 

893 if value: 

894 value = self._interpolation.before_set(self, section, option, 

895 value) 

896 if not section or section == self.default_section: 

897 sectdict = self._defaults 

898 else: 

899 try: 

900 sectdict = self._sections[section] 

901 except KeyError: 

902 raise NoSectionError(section) from None 

903 sectdict[self.optionxform(option)] = value 

904 

905 def write(self, fp, space_around_delimiters=True): 

906 """Write an .ini-format representation of the configuration state. 

907 

908 If `space_around_delimiters' is True (the default), delimiters 

909 between keys and values are surrounded by spaces. 

910 """ 

911 if space_around_delimiters: 

912 d = " {} ".format(self._delimiters[0]) 

913 else: 

914 d = self._delimiters[0] 

915 if self._defaults: 

916 self._write_section(fp, self.default_section, 

917 self._defaults.items(), d) 

918 for section in self._sections: 

919 self._write_section(fp, section, 

920 self._sections[section].items(), d) 

921 

922 def _write_section(self, fp, section_name, section_items, delimiter): 

923 """Write a single section to the specified `fp'.""" 

924 fp.write("[{}]\n".format(section_name)) 

925 for key, value in section_items: 

926 value = self._interpolation.before_write(self, section_name, key, 

927 value) 

928 if value is not None or not self._allow_no_value: 

929 value = delimiter + str(value).replace('\n', '\n\t') 

930 else: 

931 value = "" 

932 fp.write("{}{}\n".format(key, value)) 

933 fp.write("\n") 

934 

935 def remove_option(self, section, option): 

936 """Remove an option.""" 

937 if not section or section == self.default_section: 

938 sectdict = self._defaults 

939 else: 

940 try: 

941 sectdict = self._sections[section] 

942 except KeyError: 

943 raise NoSectionError(section) from None 

944 option = self.optionxform(option) 

945 existed = option in sectdict 

946 if existed: 

947 del sectdict[option] 

948 return existed 

949 

950 def remove_section(self, section): 

951 """Remove a file section.""" 

952 existed = section in self._sections 

953 if existed: 

954 del self._sections[section] 

955 del self._proxies[section] 

956 return existed 

957 

958 def __getitem__(self, key): 

959 if key != self.default_section and not self.has_section(key): 

960 raise KeyError(key) 

961 return self._proxies[key] 

962 

963 def __setitem__(self, key, value): 

964 # To conform with the mapping protocol, overwrites existing values in 

965 # the section. 

966 if key in self and self[key] is value: 

967 return 

968 # XXX this is not atomic if read_dict fails at any point. Then again, 

969 # no update method in configparser is atomic in this implementation. 

970 if key == self.default_section: 

971 self._defaults.clear() 

972 elif key in self._sections: 

973 self._sections[key].clear() 

974 self.read_dict({key: value}) 

975 

976 def __delitem__(self, key): 

977 if key == self.default_section: 

978 raise ValueError("Cannot remove the default section.") 

979 if not self.has_section(key): 

980 raise KeyError(key) 

981 self.remove_section(key) 

982 

983 def __contains__(self, key): 

984 return key == self.default_section or self.has_section(key) 

985 

986 def __len__(self): 

987 return len(self._sections) + 1 # the default section 

988 

989 def __iter__(self): 

990 # XXX does it break when underlying container state changed? 

991 return itertools.chain((self.default_section,), self._sections.keys()) 

992 

993 def _read(self, fp, fpname): 

994 """Parse a sectioned configuration file. 

995 

996 Each section in a configuration file contains a header, indicated by 

997 a name in square brackets (`[]'), plus key/value options, indicated by 

998 `name' and `value' delimited with a specific substring (`=' or `:' by 

999 default). 

1000 

1001 Values can span multiple lines, as long as they are indented deeper 

1002 than the first line of the value. Depending on the parser's mode, blank 

1003 lines may be treated as parts of multiline values or ignored. 

1004 

1005 Configuration files may include comments, prefixed by specific 

1006 characters (`#' and `;' by default). Comments may appear on their own 

1007 in an otherwise empty line or may be entered in lines holding values or 

1008 section names. 

1009 """ 

1010 elements_added = set() 

1011 cursect = None # None, or a dictionary 

1012 sectname = None 

1013 optname = None 

1014 lineno = 0 

1015 indent_level = 0 

1016 e = None # None, or an exception 

1017 for lineno, line in enumerate(fp, start=1): 

1018 comment_start = sys.maxsize 

1019 # strip inline comments 

1020 inline_prefixes = {p: -1 for p in self._inline_comment_prefixes} 

1021 while comment_start == sys.maxsize and inline_prefixes: 

1022 next_prefixes = {} 

1023 for prefix, index in inline_prefixes.items(): 

1024 index = line.find(prefix, index+1) 

1025 if index == -1: 

1026 continue 

1027 next_prefixes[prefix] = index 

1028 if index == 0 or (index > 0 and line[index-1].isspace()): 

1029 comment_start = min(comment_start, index) 

1030 inline_prefixes = next_prefixes 

1031 # strip full line comments 

1032 for prefix in self._comment_prefixes: 

1033 if line.strip().startswith(prefix): 

1034 comment_start = 0 

1035 break 

1036 if comment_start == sys.maxsize: 

1037 comment_start = None 

1038 value = line[:comment_start].strip() 

1039 if not value: 

1040 if self._empty_lines_in_values: 

1041 # add empty line to the value, but only if there was no 

1042 # comment on the line 

1043 if (comment_start is None and 

1044 cursect is not None and 

1045 optname and 

1046 cursect[optname] is not None): 

1047 cursect[optname].append('') # newlines added at join 

1048 else: 

1049 # empty line marks end of value 

1050 indent_level = sys.maxsize 

1051 continue 

1052 # continuation line? 

1053 first_nonspace = self.NONSPACECRE.search(line) 

1054 cur_indent_level = first_nonspace.start() if first_nonspace else 0 

1055 if (cursect is not None and optname and 

1056 cur_indent_level > indent_level): 

1057 cursect[optname].append(value) 

1058 # a section header or option header? 

1059 else: 

1060 indent_level = cur_indent_level 

1061 # is it a section header? 

1062 mo = self.SECTCRE.match(value) 

1063 if mo: 

1064 sectname = mo.group('header') 

1065 if sectname in self._sections: 

1066 if self._strict and sectname in elements_added: 

1067 raise DuplicateSectionError(sectname, fpname, 

1068 lineno) 

1069 cursect = self._sections[sectname] 

1070 elements_added.add(sectname) 

1071 elif sectname == self.default_section: 

1072 cursect = self._defaults 

1073 else: 

1074 cursect = self._dict() 

1075 self._sections[sectname] = cursect 

1076 self._proxies[sectname] = SectionProxy(self, sectname) 

1077 elements_added.add(sectname) 

1078 # So sections can't start with a continuation line 

1079 optname = None 

1080 # no section header in the file? 

1081 elif cursect is None: 

1082 raise MissingSectionHeaderError(fpname, lineno, line) 

1083 # an option line? 

1084 else: 

1085 mo = self._optcre.match(value) 

1086 if mo: 

1087 optname, vi, optval = mo.group('option', 'vi', 'value') 

1088 if not optname: 

1089 e = self._handle_error(e, fpname, lineno, line) 

1090 optname = self.optionxform(optname.rstrip()) 

1091 if (self._strict and 

1092 (sectname, optname) in elements_added): 

1093 raise DuplicateOptionError(sectname, optname, 

1094 fpname, lineno) 

1095 elements_added.add((sectname, optname)) 

1096 # This check is fine because the OPTCRE cannot 

1097 # match if it would set optval to None 

1098 if optval is not None: 

1099 optval = optval.strip() 

1100 cursect[optname] = [optval] 

1101 else: 

1102 # valueless option handling 

1103 cursect[optname] = None 

1104 else: 

1105 # a non-fatal parsing error occurred. set up the 

1106 # exception but keep going. the exception will be 

1107 # raised at the end of the file and will contain a 

1108 # list of all bogus lines 

1109 e = self._handle_error(e, fpname, lineno, line) 

1110 self._join_multiline_values() 

1111 # if any parsing errors occurred, raise an exception 

1112 if e: 

1113 raise e 

1114 

1115 def _join_multiline_values(self): 

1116 defaults = self.default_section, self._defaults 

1117 all_sections = itertools.chain((defaults,), 

1118 self._sections.items()) 

1119 for section, options in all_sections: 

1120 for name, val in options.items(): 

1121 if isinstance(val, list): 

1122 val = '\n'.join(val).rstrip() 

1123 options[name] = self._interpolation.before_read(self, 

1124 section, 

1125 name, val) 

1126 

1127 def _read_defaults(self, defaults): 

1128 """Read the defaults passed in the initializer. 

1129 Note: values can be non-string.""" 

1130 for key, value in defaults.items(): 

1131 self._defaults[self.optionxform(key)] = value 

1132 

1133 def _handle_error(self, exc, fpname, lineno, line): 

1134 if not exc: 

1135 exc = ParsingError(fpname) 

1136 exc.append(lineno, repr(line)) 

1137 return exc 

1138 

1139 def _unify_values(self, section, vars): 

1140 """Create a sequence of lookups with 'vars' taking priority over 

1141 the 'section' which takes priority over the DEFAULTSECT. 

1142 

1143 """ 

1144 sectiondict = {} 

1145 try: 

1146 sectiondict = self._sections[section] 

1147 except KeyError: 

1148 if section != self.default_section: 

1149 raise NoSectionError(section) from None 

1150 # Update with the entry specific variables 

1151 vardict = {} 

1152 if vars: 

1153 for key, value in vars.items(): 

1154 if value is not None: 

1155 value = str(value) 

1156 vardict[self.optionxform(key)] = value 

1157 return _ChainMap(vardict, sectiondict, self._defaults) 

1158 

1159 def _convert_to_boolean(self, value): 

1160 """Return a boolean value translating from other types if necessary. 

1161 """ 

1162 if value.lower() not in self.BOOLEAN_STATES: 

1163 raise ValueError('Not a boolean: %s' % value) 

1164 return self.BOOLEAN_STATES[value.lower()] 

1165 

1166 def _validate_value_types(self, *, section="", option="", value=""): 

1167 """Raises a TypeError for non-string values. 

1168 

1169 The only legal non-string value if we allow valueless 

1170 options is None, so we need to check if the value is a 

1171 string if: 

1172 - we do not allow valueless options, or 

1173 - we allow valueless options but the value is not None 

1174 

1175 For compatibility reasons this method is not used in classic set() 

1176 for RawConfigParsers. It is invoked in every case for mapping protocol 

1177 access and in ConfigParser.set(). 

1178 """ 

1179 if not isinstance(section, str): 

1180 raise TypeError("section names must be strings") 

1181 if not isinstance(option, str): 

1182 raise TypeError("option keys must be strings") 

1183 if not self._allow_no_value or value: 

1184 if not isinstance(value, str): 

1185 raise TypeError("option values must be strings") 

1186 

1187 @property 

1188 def converters(self): 

1189 return self._converters 

1190 

1191 

1192class ConfigParser(RawConfigParser): 

1193 """ConfigParser implementing interpolation.""" 

1194 

1195 _DEFAULT_INTERPOLATION = BasicInterpolation() 

1196 

1197 def set(self, section, option, value=None): 

1198 """Set an option. Extends RawConfigParser.set by validating type and 

1199 interpolation syntax on the value.""" 

1200 self._validate_value_types(option=option, value=value) 

1201 super().set(section, option, value) 

1202 

1203 def add_section(self, section): 

1204 """Create a new section in the configuration. Extends 

1205 RawConfigParser.add_section by validating if the section name is 

1206 a string.""" 

1207 self._validate_value_types(section=section) 

1208 super().add_section(section) 

1209 

1210 def _read_defaults(self, defaults): 

1211 """Reads the defaults passed in the initializer, implicitly converting 

1212 values to strings like the rest of the API. 

1213 

1214 Does not perform interpolation for backwards compatibility. 

1215 """ 

1216 try: 

1217 hold_interpolation = self._interpolation 

1218 self._interpolation = Interpolation() 

1219 self.read_dict({self.default_section: defaults}) 

1220 finally: 

1221 self._interpolation = hold_interpolation 

1222 

1223 

1224class SafeConfigParser(ConfigParser): 

1225 """ConfigParser alias for backwards compatibility purposes.""" 

1226 

1227 def __init__(self, *args, **kwargs): 

1228 super().__init__(*args, **kwargs) 

1229 warnings.warn( 

1230 "The SafeConfigParser class has been renamed to ConfigParser " 

1231 "in Python 3.2. This alias will be removed in future versions." 

1232 " Use ConfigParser directly instead.", 

1233 DeprecationWarning, stacklevel=2 

1234 ) 

1235 

1236 

1237class SectionProxy(MutableMapping): 

1238 """A proxy for a single section from a parser.""" 

1239 

1240 def __init__(self, parser, name): 

1241 """Creates a view on a section of the specified `name` in `parser`.""" 

1242 self._parser = parser 

1243 self._name = name 

1244 for conv in parser.converters: 

1245 key = 'get' + conv 

1246 getter = functools.partial(self.get, _impl=getattr(parser, key)) 

1247 setattr(self, key, getter) 

1248 

1249 def __repr__(self): 

1250 return '<Section: {}>'.format(self._name) 

1251 

1252 def __getitem__(self, key): 

1253 if not self._parser.has_option(self._name, key): 

1254 raise KeyError(key) 

1255 return self._parser.get(self._name, key) 

1256 

1257 def __setitem__(self, key, value): 

1258 self._parser._validate_value_types(option=key, value=value) 

1259 return self._parser.set(self._name, key, value) 

1260 

1261 def __delitem__(self, key): 

1262 if not (self._parser.has_option(self._name, key) and 

1263 self._parser.remove_option(self._name, key)): 

1264 raise KeyError(key) 

1265 

1266 def __contains__(self, key): 

1267 return self._parser.has_option(self._name, key) 

1268 

1269 def __len__(self): 

1270 return len(self._options()) 

1271 

1272 def __iter__(self): 

1273 return self._options().__iter__() 

1274 

1275 def _options(self): 

1276 if self._name != self._parser.default_section: 

1277 return self._parser.options(self._name) 

1278 else: 

1279 return self._parser.defaults() 

1280 

1281 @property 

1282 def parser(self): 

1283 # The parser object of the proxy is read-only. 

1284 return self._parser 

1285 

1286 @property 

1287 def name(self): 

1288 # The name of the section on a proxy is read-only. 

1289 return self._name 

1290 

1291 def get(self, option, fallback=None, *, raw=False, vars=None, 

1292 _impl=None, **kwargs): 

1293 """Get an option value. 

1294 

1295 Unless `fallback` is provided, `None` will be returned if the option 

1296 is not found. 

1297 

1298 """ 

1299 # If `_impl` is provided, it should be a getter method on the parser 

1300 # object that provides the desired type conversion. 

1301 if not _impl: 

1302 _impl = self._parser.get 

1303 return _impl(self._name, option, raw=raw, vars=vars, 

1304 fallback=fallback, **kwargs) 

1305 

1306 

1307class ConverterMapping(MutableMapping): 

1308 """Enables reuse of get*() methods between the parser and section proxies. 

1309 

1310 If a parser class implements a getter directly, the value for the given 

1311 key will be ``None``. The presence of the converter name here enables 

1312 section proxies to find and use the implementation on the parser class. 

1313 """ 

1314 

1315 GETTERCRE = re.compile(r"^get(?P<name>.+)$") 

1316 

1317 def __init__(self, parser): 

1318 self._parser = parser 

1319 self._data = {} 

1320 for getter in dir(self._parser): 

1321 m = self.GETTERCRE.match(getter) 

1322 if not m or not callable(getattr(self._parser, getter)): 

1323 continue 

1324 self._data[m.group('name')] = None # See class docstring. 

1325 

1326 def __getitem__(self, key): 

1327 return self._data[key] 

1328 

1329 def __setitem__(self, key, value): 

1330 try: 

1331 k = 'get' + key 

1332 except TypeError: 

1333 raise ValueError('Incompatible key: {} (type: {})' 

1334 ''.format(key, type(key))) 

1335 if k == 'get': 

1336 raise ValueError('Incompatible key: cannot use "" as a name') 

1337 self._data[key] = value 

1338 func = functools.partial(self._parser._get_conv, conv=value) 

1339 func.converter = value 

1340 setattr(self._parser, k, func) 

1341 for proxy in self._parser.values(): 

1342 getter = functools.partial(proxy.get, _impl=func) 

1343 setattr(proxy, k, getter) 

1344 

1345 def __delitem__(self, key): 

1346 try: 

1347 k = 'get' + (key or None) 

1348 except TypeError: 

1349 raise KeyError(key) 

1350 del self._data[key] 

1351 for inst in itertools.chain((self._parser,), self._parser.values()): 

1352 try: 

1353 delattr(inst, k) 

1354 except AttributeError: 

1355 # don't raise since the entry was present in _data, silently 

1356 # clean up 

1357 continue 

1358 

1359 def __iter__(self): 

1360 return iter(self._data) 

1361 

1362 def __len__(self): 

1363 return len(self._data)