Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/backports/configparser/__init__.py: 48%

683 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-25 07:17 +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 

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

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

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

26 

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

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

29 for the default values. 

30 

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

32 that divide keys from values. 

33 

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

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

36 indented. 

37 

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

39 substrings that prefix comments in non-empty lines. 

40 

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

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

43 dictionary). Default is True. 

44 

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

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

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

48 

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

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

51 

52 When `default_section` is given, the name of the special section is 

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

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

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

56 attribute and may be modified at runtime. 

57 

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

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

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

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

62 BasicInterpolation. The library also provides a ``zc.buildout`` 

63 inspired ExtendedInterpolation implementation. 

64 

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

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

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

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

69 section proxies. 

70 

71 sections() 

72 Return all the configuration section names, sans DEFAULT. 

73 

74 has_section(section) 

75 Return whether the given section exists. 

76 

77 has_option(section, option) 

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

79 

80 options(section) 

81 Return list of configuration options for the named section. 

82 

83 read(filenames, encoding=None) 

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

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

86 are ignored. Return list of successfully read files. 

87 

88 read_file(f, filename=None) 

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

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

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

92 

93 read_string(string) 

94 Read configuration from a given string. 

95 

96 read_dict(dictionary) 

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

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

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

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

101 converted to strings. 

102 

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

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

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

106 constructor and the DEFAULT section. Additional substitutions may be 

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

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

109 `vars`, the value from `vars` is used. 

110 

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

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

113 

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

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

116 

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

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

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

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

121 

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

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

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

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

126 

127 remove_section(section) 

128 Remove the given file section and all its options. 

129 

130 remove_option(section, option) 

131 Remove the given option from the given section. 

132 

133 set(section, option, value) 

134 Set the given option. 

135 

136 write(fp, space_around_delimiters=True) 

137 Write the configuration state in .ini format. If 

138 `space_around_delimiters` is True (the default), delimiters 

139 between keys and values are surrounded by spaces. 

140""" 

141 

142from collections.abc import MutableMapping 

143from collections import ChainMap as _ChainMap 

144import functools 

145from .compat import io 

146import itertools 

147import os 

148import re 

149import sys 

150import warnings 

151 

152 

153__all__ = ( 

154 "NoSectionError", 

155 "DuplicateOptionError", 

156 "DuplicateSectionError", 

157 "NoOptionError", 

158 "InterpolationError", 

159 "InterpolationDepthError", 

160 "InterpolationMissingOptionError", 

161 "InterpolationSyntaxError", 

162 "ParsingError", 

163 "MissingSectionHeaderError", 

164 "ConfigParser", 

165 "RawConfigParser", 

166 "Interpolation", 

167 "BasicInterpolation", 

168 "ExtendedInterpolation", 

169 "LegacyInterpolation", 

170 "SectionProxy", 

171 "ConverterMapping", 

172 "DEFAULTSECT", 

173 "MAX_INTERPOLATION_DEPTH", 

174) 

175 

176_default_dict = dict 

177DEFAULTSECT = "DEFAULT" 

178 

179MAX_INTERPOLATION_DEPTH = 10 

180 

181 

182# exception classes 

183class Error(Exception): 

184 """Base class for ConfigParser exceptions.""" 

185 

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

187 self.message = msg 

188 Exception.__init__(self, msg) 

189 

190 def __repr__(self): 

191 return self.message 

192 

193 __str__ = __repr__ 

194 

195 

196class NoSectionError(Error): 

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

198 

199 def __init__(self, section): 

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

201 self.section = section 

202 self.args = (section,) 

203 

204 

205class DuplicateSectionError(Error): 

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

207 

208 Possible repetitions that raise this exception are: multiple creation 

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

210 in a single input file, string or dictionary. 

211 """ 

212 

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

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

215 if source is not None: 

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

217 if lineno is not None: 

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

219 message.append(": section ") 

220 message.extend(msg) 

221 msg = message 

222 else: 

223 msg.insert(0, "Section ") 

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

225 self.section = section 

226 self.source = source 

227 self.lineno = lineno 

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

229 

230 

231class DuplicateOptionError(Error): 

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

233 

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

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

236 """ 

237 

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

239 msg = [repr(option), " in section ", repr(section), " already exists"] 

240 if source is not None: 

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

242 if lineno is not None: 

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

244 message.append(": option ") 

245 message.extend(msg) 

246 msg = message 

247 else: 

248 msg.insert(0, "Option ") 

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

250 self.section = section 

251 self.option = option 

252 self.source = source 

253 self.lineno = lineno 

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

255 

256 

257class NoOptionError(Error): 

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

259 

260 def __init__(self, option, section): 

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

262 self.option = option 

263 self.section = section 

264 self.args = (option, section) 

265 

266 

267class InterpolationError(Error): 

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

269 

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

271 Error.__init__(self, msg) 

272 self.option = option 

273 self.section = section 

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

275 

276 

277class InterpolationMissingOptionError(InterpolationError): 

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

279 

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

281 msg = ( 

282 "Bad value substitution: option {!r} in section {!r} contains " 

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

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

285 ) 

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

287 self.reference = reference 

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

289 

290 

291class InterpolationSyntaxError(InterpolationError): 

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

293 

294 Current implementation raises this exception when the source text into 

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

296 """ 

297 

298 

299class InterpolationDepthError(InterpolationError): 

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

301 

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

303 msg = ( 

304 "Recursion limit exceeded in value substitution: option {!r} " 

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

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

307 "".format(option, section, MAX_INTERPOLATION_DEPTH, rawval) 

308 ) 

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

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

311 

312 

313class ParsingError(Error): 

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

315 

316 def __init__(self, source): 

317 super().__init__(f'Source contains parsing errors: {source!r}') 

318 self.source = source 

319 self.errors = [] 

320 self.args = (source,) 

321 

322 def append(self, lineno, line): 

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

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

325 

326 

327class MissingSectionHeaderError(ParsingError): 

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

329 

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

331 Error.__init__( 

332 self, 

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

334 % (filename, lineno, line), 

335 ) 

336 self.source = filename 

337 self.lineno = lineno 

338 self.line = line 

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

340 

341 

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

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

344# a valid fallback value. 

345_UNSET = object() 

346 

347 

348class Interpolation: 

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

350 

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

352 return value 

353 

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

355 return value 

356 

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

358 return value 

359 

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

361 return value 

362 

363 

364class BasicInterpolation(Interpolation): 

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

366 

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

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

369 

370 For example: 

371 

372 something: %(dir)s/whatever 

373 

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

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

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

377 is considered a user error and raises `InterpolationSyntaxError`.""" 

378 

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

380 

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

382 L = [] 

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

384 return ''.join(L) 

385 

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

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

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

389 if '%' in tmp_value: 

390 raise ValueError( 

391 "invalid interpolation syntax in %r at " 

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

393 ) 

394 return value 

395 

396 def _interpolate_some( # noqa: C901 

397 self, parser, option, accum, rest, section, map, depth 

398 ): 

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

400 if depth > MAX_INTERPOLATION_DEPTH: 

401 raise InterpolationDepthError(option, section, rawval) 

402 while rest: 

403 p = rest.find("%") 

404 if p < 0: 

405 accum.append(rest) 

406 return 

407 if p > 0: 

408 accum.append(rest[:p]) 

409 rest = rest[p:] 

410 # p is no longer used 

411 c = rest[1:2] 

412 if c == "%": 

413 accum.append("%") 

414 rest = rest[2:] 

415 elif c == "(": 

416 m = self._KEYCRE.match(rest) 

417 if m is None: 

418 raise InterpolationSyntaxError( 

419 option, 

420 section, 

421 "bad interpolation variable reference %r" % rest, 

422 ) 

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

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

425 try: 

426 v = map[var] 

427 except KeyError: 

428 raise InterpolationMissingOptionError( 

429 option, section, rawval, var 

430 ) from None 

431 if "%" in v: 

432 self._interpolate_some( 

433 parser, option, accum, v, section, map, depth + 1 

434 ) 

435 else: 

436 accum.append(v) 

437 else: 

438 raise InterpolationSyntaxError( 

439 option, 

440 section, 

441 "'%%' must be followed by '%%' or '(', " "found: %r" % (rest,), 

442 ) 

443 

444 

445class ExtendedInterpolation(Interpolation): 

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

447 `zc.buildout`. Enables interpolation between sections.""" 

448 

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

450 

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

452 L = [] 

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

454 return ''.join(L) 

455 

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

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

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

459 if '$' in tmp_value: 

460 raise ValueError( 

461 "invalid interpolation syntax in %r at " 

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

463 ) 

464 return value 

465 

466 def _interpolate_some( # noqa: C901 

467 self, parser, option, accum, rest, section, map, depth 

468 ): 

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( 

489 option, 

490 section, 

491 "bad interpolation variable reference %r" % rest, 

492 ) 

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

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

495 sect = section 

496 opt = option 

497 try: 

498 if len(path) == 1: 

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

500 v = map[opt] 

501 elif len(path) == 2: 

502 sect = path[0] 

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

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

505 else: 

506 raise InterpolationSyntaxError( 

507 option, section, "More than one ':' found: %r" % (rest,) 

508 ) 

509 except (KeyError, NoSectionError, NoOptionError): 

510 raise InterpolationMissingOptionError( 

511 option, section, rawval, ":".join(path) 

512 ) from None 

513 if "$" in v: 

514 self._interpolate_some( 

515 parser, 

516 opt, 

517 accum, 

518 v, 

519 sect, 

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

521 depth + 1, 

522 ) 

523 else: 

524 accum.append(v) 

525 else: 

526 raise InterpolationSyntaxError( 

527 option, 

528 section, 

529 "'$' must be followed by '$' or '{', " "found: %r" % (rest,), 

530 ) 

531 

532 

533class LegacyInterpolation(Interpolation): 

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

535 Use BasicInterpolation or ExtendedInterpolation instead.""" 

536 

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

538 

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

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

541 warnings.warn( 

542 "LegacyInterpolation has been deprecated since Python 3.2 " 

543 "and will be removed from the configparser module in Python 3.13. " 

544 "Use BasicInterpolation or ExtendedInterpolation instead.", 

545 DeprecationWarning, 

546 stacklevel=2, 

547 ) 

548 

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

550 rawval = value 

551 depth = MAX_INTERPOLATION_DEPTH 

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

553 depth -= 1 

554 if value and "%(" in value: 

555 replace = functools.partial(self._interpolation_replace, parser=parser) 

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

557 try: 

558 value = value % vars 

559 except KeyError as e: 

560 raise InterpolationMissingOptionError( 

561 option, section, rawval, e.args[0] 

562 ) from None 

563 else: 

564 break 

565 if value and "%(" in value: 

566 raise InterpolationDepthError(option, section, rawval) 

567 return value 

568 

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

570 return value 

571 

572 @staticmethod 

573 def _interpolation_replace(match, parser): 

574 s = match.group(1) 

575 if s is None: 

576 return match.group() 

577 else: 

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

579 

580 

581class RawConfigParser(MutableMapping): 

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

583 

584 # Regular expressions for parsing section headers and options 

585 _SECT_TMPL = r""" 

586 \[ # [ 

587 (?P<header>.+) # very permissive! 

588 \] # ] 

589 """ 

590 _OPT_TMPL = r""" 

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

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

593 # followed by any of the 

594 # allowed delimiters, 

595 # followed by any space/tab 

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

597 """ 

598 _OPT_NV_TMPL = r""" 

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

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

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

602 # any of the allowed 

603 # delimiters, followed by any 

604 # space/tab 

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

606 """ 

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

608 _DEFAULT_INTERPOLATION = Interpolation() 

609 # Compiled regular expression for matching sections 

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

611 # Compiled regular expression for matching options with typical separators 

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

613 # Compiled regular expression for matching options with optional values 

614 # delimited using typical separators 

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

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

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

618 # Possible boolean values in the configuration. 

619 BOOLEAN_STATES = { 

620 '1': True, 

621 'yes': True, 

622 'true': True, 

623 'on': True, 

624 '0': False, 

625 'no': False, 

626 'false': False, 

627 'off': False, 

628 } 

629 

630 def __init__( 

631 self, 

632 defaults=None, 

633 dict_type=_default_dict, 

634 allow_no_value=False, 

635 *, 

636 delimiters=('=', ':'), 

637 comment_prefixes=('#', ';'), 

638 inline_comment_prefixes=None, 

639 strict=True, 

640 empty_lines_in_values=True, 

641 default_section=DEFAULTSECT, 

642 interpolation=_UNSET, 

643 converters=_UNSET, 

644 ): 

645 self._dict = dict_type 

646 self._sections = self._dict() 

647 self._defaults = self._dict() 

648 self._converters = ConverterMapping(self) 

649 self._proxies = self._dict() 

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

651 self._delimiters = tuple(delimiters) 

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

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

654 else: 

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

656 if allow_no_value: 

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

658 else: 

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

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

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

662 self._strict = strict 

663 self._allow_no_value = allow_no_value 

664 self._empty_lines_in_values = empty_lines_in_values 

665 self.default_section = default_section 

666 self._interpolation = interpolation 

667 if self._interpolation is _UNSET: 

668 self._interpolation = self._DEFAULT_INTERPOLATION 

669 if self._interpolation is None: 

670 self._interpolation = Interpolation() 

671 if not isinstance(self._interpolation, Interpolation): 

672 raise TypeError( 

673 f"interpolation= must be None or an instance of Interpolation;" 

674 f" got an object of type {type(self._interpolation)}" 

675 ) 

676 if converters is not _UNSET: 

677 self._converters.update(converters) 

678 if defaults: 

679 self._read_defaults(defaults) 

680 

681 def defaults(self): 

682 return self._defaults 

683 

684 def sections(self): 

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

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

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

688 

689 def add_section(self, section): 

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

691 

692 Raise DuplicateSectionError if a section by the specified name 

693 already exists. Raise ValueError if name is DEFAULT. 

694 """ 

695 if section == self.default_section: 

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

697 

698 if section in self._sections: 

699 raise DuplicateSectionError(section) 

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

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

702 

703 def has_section(self, section): 

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

705 

706 The DEFAULT section is not acknowledged. 

707 """ 

708 return section in self._sections 

709 

710 def options(self, section): 

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

712 try: 

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

714 except KeyError: 

715 raise NoSectionError(section) from None 

716 opts.update(self._defaults) 

717 return list(opts.keys()) 

718 

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

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

721 

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

723 designed so that you can specify an iterable of potential 

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

725 home directory, systemwide directory), and all existing 

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

727 filename may also be given. 

728 

729 Return list of successfully read files. 

730 """ 

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

732 filenames = [filenames] 

733 encoding = io.text_encoding(encoding) 

734 read_ok = [] 

735 for filename in filenames: 

736 try: 

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

738 self._read(fp, filename) 

739 except OSError: 

740 continue 

741 if isinstance(filename, os.PathLike): 

742 filename = os.fspath(filename) 

743 read_ok.append(filename) 

744 return read_ok 

745 

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

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

748 

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

750 Optional second argument is the `source` specifying the name of the 

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

752 `name` attribute, `<???>` is used. 

753 """ 

754 if source is None: 

755 try: 

756 source = f.name 

757 except AttributeError: 

758 source = '<???>' 

759 self._read(f, source) 

760 

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

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

763 sfile = io.StringIO(string) 

764 self.read_file(sfile, source) 

765 

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

767 """Read configuration from a dictionary. 

768 

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

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

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

772 

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

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

775 

776 Optional second argument is the `source` specifying the name of the 

777 dictionary being read. 

778 """ 

779 elements_added = set() 

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

781 section = str(section) 

782 try: 

783 self.add_section(section) 

784 except (DuplicateSectionError, ValueError): 

785 if self._strict and section in elements_added: 

786 raise 

787 elements_added.add(section) 

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

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

790 if value is not None: 

791 value = str(value) 

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

793 raise DuplicateOptionError(section, key, source) 

794 elements_added.add((section, key)) 

795 self.set(section, key, value) 

796 

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

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

799 

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

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

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

803 a fallback value. `None` can be provided as a `fallback` value. 

804 

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

806 all interpolations are expanded in the return values. 

807 

808 Arguments `raw`, `vars`, and `fallback` are keyword only. 

809 

810 The section DEFAULT is special. 

811 """ 

812 try: 

813 d = self._unify_values(section, vars) 

814 except NoSectionError: 

815 if fallback is _UNSET: 

816 raise 

817 else: 

818 return fallback 

819 option = self.optionxform(option) 

820 try: 

821 value = d[option] 

822 except KeyError: 

823 if fallback is _UNSET: 

824 raise NoOptionError(option, section) 

825 else: 

826 return fallback 

827 

828 if raw or value is None: 

829 return value 

830 else: 

831 return self._interpolation.before_get(self, section, option, value, d) 

832 

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

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

835 

836 def _get_conv( 

837 self, section, option, conv, *, raw=False, vars=None, fallback=_UNSET, **kwargs 

838 ): 

839 try: 

840 return self._get(section, conv, option, raw=raw, vars=vars, **kwargs) 

841 except (NoSectionError, NoOptionError): 

842 if fallback is _UNSET: 

843 raise 

844 return fallback 

845 

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

847 def getint( 

848 self, section, option, *, raw=False, vars=None, fallback=_UNSET, **kwargs 

849 ): 

850 return self._get_conv( 

851 section, option, int, raw=raw, vars=vars, fallback=fallback, **kwargs 

852 ) 

853 

854 def getfloat( 

855 self, section, option, *, raw=False, vars=None, fallback=_UNSET, **kwargs 

856 ): 

857 return self._get_conv( 

858 section, option, float, raw=raw, vars=vars, fallback=fallback, **kwargs 

859 ) 

860 

861 def getboolean( 

862 self, section, option, *, raw=False, vars=None, fallback=_UNSET, **kwargs 

863 ): 

864 return self._get_conv( 

865 section, 

866 option, 

867 self._convert_to_boolean, 

868 raw=raw, 

869 vars=vars, 

870 fallback=fallback, 

871 **kwargs, 

872 ) 

873 

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

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

876 

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

878 defaults passed into the constructor, unless the optional argument 

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

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

881 any pre-existing defaults. 

882 

883 The section DEFAULT is special. 

884 """ 

885 if section is _UNSET: 

886 return super(RawConfigParser, self).items() 

887 d = self._defaults.copy() 

888 try: 

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

890 except KeyError: 

891 if section != self.default_section: 

892 raise NoSectionError(section) 

893 orig_keys = list(d.keys()) 

894 # Update with the entry specific variables 

895 if vars: 

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

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

898 

899 def value_getter_interp(option): 

900 return self._interpolation.before_get(self, section, option, d[option], d) 

901 

902 def value_getter_raw(option): 

903 return d[option] 

904 

905 value_getter = value_getter_raw if raw else value_getter_interp 

906 

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

908 

909 def popitem(self): 

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

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

912 KeyError. 

913 

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

915 """ 

916 for key in self.sections(): 

917 value = self[key] 

918 del self[key] 

919 return key, value 

920 raise KeyError 

921 

922 def optionxform(self, optionstr): 

923 return optionstr.lower() 

924 

925 def has_option(self, section, option): 

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

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

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

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

930 option = self.optionxform(option) 

931 return option in self._defaults 

932 elif section not in self._sections: 

933 return False 

934 else: 

935 option = self.optionxform(option) 

936 return option in self._sections[section] or option in self._defaults 

937 

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

939 """Set an option.""" 

940 if value: 

941 value = self._interpolation.before_set(self, section, option, value) 

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

943 sectdict = self._defaults 

944 else: 

945 try: 

946 sectdict = self._sections[section] 

947 except KeyError: 

948 raise NoSectionError(section) from None 

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

950 

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

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

953 

954 If `space_around_delimiters` is True (the default), delimiters 

955 between keys and values are surrounded by spaces. 

956 

957 Please note that comments in the original configuration file are not 

958 preserved when writing the configuration back. 

959 """ 

960 if space_around_delimiters: 

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

962 else: 

963 d = self._delimiters[0] 

964 if self._defaults: 

965 self._write_section(fp, self.default_section, self._defaults.items(), d) 

966 for section in self._sections: 

967 self._write_section(fp, section, self._sections[section].items(), d) 

968 

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

970 """Write a single section to the specified `fp`.""" 

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

972 for key, value in section_items: 

973 value = self._interpolation.before_write(self, section_name, key, value) 

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

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

976 else: 

977 value = "" 

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

979 fp.write("\n") 

980 

981 def remove_option(self, section, option): 

982 """Remove an option.""" 

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

984 sectdict = self._defaults 

985 else: 

986 try: 

987 sectdict = self._sections[section] 

988 except KeyError: 

989 raise NoSectionError(section) from None 

990 option = self.optionxform(option) 

991 existed = option in sectdict 

992 if existed: 

993 del sectdict[option] 

994 return existed 

995 

996 def remove_section(self, section): 

997 """Remove a file section.""" 

998 existed = section in self._sections 

999 if existed: 

1000 del self._sections[section] 

1001 del self._proxies[section] 

1002 return existed 

1003 

1004 def __getitem__(self, key): 

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

1006 raise KeyError(key) 

1007 return self._proxies[key] 

1008 

1009 def __setitem__(self, key, value): 

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

1011 # the section. 

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

1013 return 

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

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

1016 if key == self.default_section: 

1017 self._defaults.clear() 

1018 elif key in self._sections: 

1019 self._sections[key].clear() 

1020 self.read_dict({key: value}) 

1021 

1022 def __delitem__(self, key): 

1023 if key == self.default_section: 

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

1025 if not self.has_section(key): 

1026 raise KeyError(key) 

1027 self.remove_section(key) 

1028 

1029 def __contains__(self, key): 

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

1031 

1032 def __len__(self): 

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

1034 

1035 def __iter__(self): 

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

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

1038 

1039 def _read(self, fp, fpname): # noqa: C901 

1040 """Parse a sectioned configuration file. 

1041 

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

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

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

1045 default). 

1046 

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

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

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

1050 

1051 Configuration files may include comments, prefixed by specific 

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

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

1054 section names. Please note that comments get stripped off when reading 

1055 configuration files. 

1056 """ 

1057 elements_added = set() 

1058 cursect = None # None, or a dictionary 

1059 sectname = None 

1060 optname = None 

1061 lineno = 0 

1062 indent_level = 0 

1063 e = None # None, or an exception 

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

1065 comment_start = sys.maxsize 

1066 # strip inline comments 

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

1068 while comment_start == sys.maxsize and inline_prefixes: 

1069 next_prefixes = {} 

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

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

1072 if index == -1: 

1073 continue 

1074 next_prefixes[prefix] = index 

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

1076 comment_start = min(comment_start, index) 

1077 inline_prefixes = next_prefixes 

1078 # strip full line comments 

1079 for prefix in self._comment_prefixes: 

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

1081 comment_start = 0 

1082 break 

1083 if comment_start == sys.maxsize: 

1084 comment_start = None 

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

1086 if not value: 

1087 if self._empty_lines_in_values: 

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

1089 # comment on the line 

1090 if ( 

1091 comment_start is None 

1092 and cursect is not None 

1093 and optname 

1094 and cursect[optname] is not None 

1095 ): 

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

1097 else: 

1098 # empty line marks end of value 

1099 indent_level = sys.maxsize 

1100 continue 

1101 # continuation line? 

1102 first_nonspace = self.NONSPACECRE.search(line) 

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

1104 if cursect is not None and optname and cur_indent_level > indent_level: 

1105 cursect[optname].append(value) 

1106 # a section header or option header? 

1107 else: 

1108 indent_level = cur_indent_level 

1109 # is it a section header? 

1110 mo = self.SECTCRE.match(value) 

1111 if mo: 

1112 sectname = mo.group('header') 

1113 if sectname in self._sections: 

1114 if self._strict and sectname in elements_added: 

1115 raise DuplicateSectionError(sectname, fpname, lineno) 

1116 cursect = self._sections[sectname] 

1117 elements_added.add(sectname) 

1118 elif sectname == self.default_section: 

1119 cursect = self._defaults 

1120 else: 

1121 cursect = self._dict() 

1122 self._sections[sectname] = cursect 

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

1124 elements_added.add(sectname) 

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

1126 optname = None 

1127 # no section header in the file? 

1128 elif cursect is None: 

1129 raise MissingSectionHeaderError(fpname, lineno, line) 

1130 # an option line? 

1131 else: 

1132 mo = self._optcre.match(value) 

1133 if mo: 

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

1135 if not optname: 

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

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

1138 if self._strict and (sectname, optname) in elements_added: 

1139 raise DuplicateOptionError( 

1140 sectname, optname, fpname, lineno 

1141 ) 

1142 elements_added.add((sectname, optname)) 

1143 # This check is fine because the OPTCRE cannot 

1144 # match if it would set optval to None 

1145 if optval is not None: 

1146 optval = optval.strip() 

1147 cursect[optname] = [optval] 

1148 else: 

1149 # valueless option handling 

1150 cursect[optname] = None 

1151 else: 

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

1153 # exception but keep going. the exception will be 

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

1155 # list of all bogus lines 

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

1157 self._join_multiline_values() 

1158 # if any parsing errors occurred, raise an exception 

1159 if e: 

1160 raise e 

1161 

1162 def _join_multiline_values(self): 

1163 defaults = self.default_section, self._defaults 

1164 all_sections = itertools.chain((defaults,), self._sections.items()) 

1165 for section, options in all_sections: 

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

1167 if isinstance(val, list): 

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

1169 options[name] = self._interpolation.before_read( 

1170 self, section, name, val 

1171 ) 

1172 

1173 def _read_defaults(self, defaults): 

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

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

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

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

1178 

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

1180 if not exc: 

1181 exc = ParsingError(fpname) 

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

1183 return exc 

1184 

1185 def _unify_values(self, section, vars): 

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

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

1188 

1189 """ 

1190 sectiondict = {} 

1191 try: 

1192 sectiondict = self._sections[section] 

1193 except KeyError: 

1194 if section != self.default_section: 

1195 raise NoSectionError(section) 

1196 # Update with the entry specific variables 

1197 vardict = {} 

1198 if vars: 

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

1200 if value is not None: 

1201 value = str(value) 

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

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

1204 

1205 def _convert_to_boolean(self, value): 

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

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

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

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

1210 

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

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

1213 

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

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

1216 string if: 

1217 - we do not allow valueless options, or 

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

1219 

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

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

1222 access and in ConfigParser.set(). 

1223 """ 

1224 if not isinstance(section, str): 

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

1226 if not isinstance(option, str): 

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

1228 if not self._allow_no_value or value: 

1229 if not isinstance(value, str): 

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

1231 

1232 @property 

1233 def converters(self): 

1234 return self._converters 

1235 

1236 

1237class ConfigParser(RawConfigParser): 

1238 """ConfigParser implementing interpolation.""" 

1239 

1240 _DEFAULT_INTERPOLATION = BasicInterpolation() 

1241 

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

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

1244 interpolation syntax on the value.""" 

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

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

1247 

1248 def add_section(self, section): 

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

1250 RawConfigParser.add_section by validating if the section name is 

1251 a string.""" 

1252 self._validate_value_types(section=section) 

1253 super().add_section(section) 

1254 

1255 def _read_defaults(self, defaults): 

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

1257 values to strings like the rest of the API. 

1258 

1259 Does not perform interpolation for backwards compatibility. 

1260 """ 

1261 try: 

1262 hold_interpolation = self._interpolation 

1263 self._interpolation = Interpolation() 

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

1265 finally: 

1266 self._interpolation = hold_interpolation 

1267 

1268 

1269class SectionProxy(MutableMapping): 

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

1271 

1272 def __init__(self, parser, name): 

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

1274 self._parser = parser 

1275 self._name = name 

1276 for conv in parser.converters: 

1277 key = 'get' + conv 

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

1279 setattr(self, key, getter) 

1280 

1281 def __repr__(self): 

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

1283 

1284 def __getitem__(self, key): 

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

1286 raise KeyError(key) 

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

1288 

1289 def __setitem__(self, key, value): 

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

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

1292 

1293 def __delitem__(self, key): 

1294 if not ( 

1295 self._parser.has_option(self._name, key) 

1296 and self._parser.remove_option(self._name, key) 

1297 ): 

1298 raise KeyError(key) 

1299 

1300 def __contains__(self, key): 

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

1302 

1303 def __len__(self): 

1304 return len(self._options()) 

1305 

1306 def __iter__(self): 

1307 return self._options().__iter__() 

1308 

1309 def _options(self): 

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

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

1312 else: 

1313 return self._parser.defaults() 

1314 

1315 @property 

1316 def parser(self): 

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

1318 return self._parser 

1319 

1320 @property 

1321 def name(self): 

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

1323 return self._name 

1324 

1325 def get(self, option, fallback=None, *, raw=False, vars=None, _impl=None, **kwargs): 

1326 """Get an option value. 

1327 

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

1329 is not found. 

1330 

1331 """ 

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

1333 # object that provides the desired type conversion. 

1334 if not _impl: 

1335 _impl = self._parser.get 

1336 return _impl( 

1337 self._name, option, raw=raw, vars=vars, fallback=fallback, **kwargs 

1338 ) 

1339 

1340 

1341class ConverterMapping(MutableMapping): 

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

1343 

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

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

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

1347 """ 

1348 

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

1350 

1351 def __init__(self, parser): 

1352 self._parser = parser 

1353 self._data = {} 

1354 for getter in dir(self._parser): 

1355 m = self.GETTERCRE.match(getter) 

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

1357 continue 

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

1359 

1360 def __getitem__(self, key): 

1361 return self._data[key] 

1362 

1363 def __setitem__(self, key, value): 

1364 try: 

1365 k = 'get' + key 

1366 except TypeError: 

1367 raise ValueError( 

1368 'Incompatible key: {} (type: {})' ''.format(key, type(key)) 

1369 ) 

1370 if k == 'get': 

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

1372 self._data[key] = value 

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

1374 func.converter = value 

1375 setattr(self._parser, k, func) 

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

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

1378 setattr(proxy, k, getter) 

1379 

1380 def __delitem__(self, key): 

1381 try: 

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

1383 except TypeError: 

1384 raise KeyError(key) 

1385 del self._data[key] 

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

1387 try: 

1388 delattr(inst, k) 

1389 except AttributeError: 

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

1391 # clean up 

1392 continue 

1393 

1394 def __iter__(self): 

1395 return iter(self._data) 

1396 

1397 def __len__(self): 

1398 return len(self._data)