Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pandas/_config/config.py: 45%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

291 statements  

1""" 

2The config module holds package-wide configurables and provides 

3a uniform API for working with them. 

4 

5Overview 

6======== 

7 

8This module supports the following requirements: 

9- options are referenced using keys in dot.notation, e.g. "x.y.option - z". 

10- keys are case-insensitive. 

11- functions should accept partial/regex keys, when unambiguous. 

12- options can be registered by modules at import time. 

13- options can be registered at init-time (via core.config_init) 

14- options have a default value, and (optionally) a description and 

15 validation function associated with them. 

16- options can be deprecated, in which case referencing them 

17 should produce a warning. 

18- deprecated options can optionally be rerouted to a replacement 

19 so that accessing a deprecated option reroutes to a differently 

20 named option. 

21- options can be reset to their default value. 

22- all option can be reset to their default value at once. 

23- all options in a certain sub - namespace can be reset at once. 

24- the user can set / get / reset or ask for the description of an option. 

25- a developer can register and mark an option as deprecated. 

26- you can register a callback to be invoked when the option value 

27 is set or reset. Changing the stored value is considered misuse, but 

28 is not verboten. 

29 

30Implementation 

31============== 

32 

33- Data is stored using nested dictionaries, and should be accessed 

34 through the provided API. 

35 

36- "Registered options" and "Deprecated options" have metadata associated 

37 with them, which are stored in auxiliary dictionaries keyed on the 

38 fully-qualified key, e.g. "x.y.z.option". 

39 

40- the config_init module is imported by the package's __init__.py file. 

41 placing any register_option() calls there will ensure those options 

42 are available as soon as pandas is loaded. If you use register_option 

43 in a module, it will only be available after that module is imported, 

44 which you should be aware of. 

45 

46- `config_prefix` is a context_manager (for use with the `with` keyword) 

47 which can save developers some typing, see the docstring. 

48 

49""" 

50 

51from __future__ import annotations 

52 

53from contextlib import contextmanager 

54import re 

55from typing import ( 

56 TYPE_CHECKING, 

57 Any, 

58 NamedTuple, 

59 cast, 

60) 

61import warnings 

62 

63from pandas.util._exceptions import find_stack_level 

64 

65if TYPE_CHECKING: 

66 from collections.abc import ( 

67 Callable, 

68 Generator, 

69 Sequence, 

70 ) 

71 

72 from pandas._typing import F 

73 

74 

75class DeprecatedOption(NamedTuple): 

76 key: str 

77 category: type[Warning] 

78 msg: str | None 

79 rkey: str | None 

80 removal_ver: str | None 

81 

82 

83class RegisteredOption(NamedTuple): 

84 key: str 

85 defval: Any 

86 doc: str 

87 validator: Callable[[object], Any] | None 

88 cb: Callable[[str], Any] | None 

89 

90 

91# holds deprecated option metadata 

92_deprecated_options: dict[str, DeprecatedOption] = {} 

93 

94# holds registered option metadata 

95_registered_options: dict[str, RegisteredOption] = {} 

96 

97# holds the current values for registered options 

98_global_config: dict[str, Any] = {} 

99 

100# keys which have a special meaning 

101_reserved_keys: list[str] = ["all"] 

102 

103 

104class OptionError(AttributeError, KeyError): 

105 """ 

106 Exception raised for pandas.options. 

107 

108 Backwards compatible with KeyError checks. 

109 

110 See Also 

111 -------- 

112 options : Access and modify global pandas settings. 

113 

114 Examples 

115 -------- 

116 >>> pd.options.context 

117 Traceback (most recent call last): 

118 OptionError: No such option 

119 """ 

120 

121 __module__ = "pandas.errors" 

122 

123 

124# 

125# User API 

126 

127 

128def _get_single_key(pat: str, warn: bool = True, extra_stacklevel: int = 0) -> str: 

129 keys = _select_options(pat) 

130 if len(keys) == 0: 

131 if warn: 

132 _warn_if_deprecated(pat, extra_stacklevel=extra_stacklevel) 

133 raise OptionError(f"No such keys(s): {pat!r}") 

134 if len(keys) > 1: 

135 raise OptionError("Pattern matched multiple keys") 

136 key = keys[0] 

137 

138 if warn: 

139 _warn_if_deprecated(key, extra_stacklevel=extra_stacklevel) 

140 

141 key = _translate_key(key) 

142 

143 return key 

144 

145 

146def get_option(pat: str) -> Any: 

147 """ 

148 Retrieve the value of the specified option. 

149 

150 This method allows users to query the current value of a given option 

151 in the pandas configuration system. Options control various display, 

152 performance, and behavior-related settings within pandas. 

153 

154 Parameters 

155 ---------- 

156 pat : str 

157 Regexp which should match a single option. 

158 

159 .. warning:: 

160 

161 Partial matches are supported for convenience, but unless you use the 

162 full option name (e.g. x.y.z.option_name), your code may break in future 

163 versions if new options with similar names are introduced. 

164 

165 Returns 

166 ------- 

167 Any 

168 The value of the option. 

169 

170 Raises 

171 ------ 

172 OptionError : if no such option exists 

173 

174 See Also 

175 -------- 

176 set_option : Set the value of the specified option or options. 

177 reset_option : Reset one or more options to their default value. 

178 describe_option : Print the description for one or more registered options. 

179 

180 Notes 

181 ----- 

182 For all available options, please view the :ref:`User Guide <options.available>` 

183 or use ``pandas.describe_option()``. 

184 

185 Examples 

186 -------- 

187 >>> pd.get_option("display.max_columns") # doctest: +SKIP 

188 4 

189 """ 

190 return _get_option_impl(pat) 

191 

192 

193def _get_option_impl(pat: str, warn: bool = True) -> Any: 

194 key = _get_single_key(pat, warn=warn) 

195 

196 # walk the nested dict 

197 root, k = _get_root(key) 

198 return root[k] 

199 

200 

201def _set_option_impl(*args: Any, warn: bool = True, extra_stacklevel: int = 0) -> None: 

202 # GH#63235: `warn` and `extra_stacklevel` let option_context warn exactly 

203 # once, aimed at the caller rather than at contextlib. 

204 # Handle dictionary input 

205 if len(args) == 1 and isinstance(args[0], dict): 

206 args = tuple(kv for item in args[0].items() for kv in item) 

207 

208 nargs = len(args) 

209 if not nargs or nargs % 2 != 0: 

210 raise ValueError("Must provide an even number of non-keyword arguments") 

211 

212 for k, v in zip(args[::2], args[1::2], strict=True): 

213 key = _get_single_key(k, warn=warn, extra_stacklevel=extra_stacklevel) 

214 

215 opt = _get_registered_option(key) 

216 if opt and opt.validator: 

217 opt.validator(v) 

218 

219 # walk the nested dict 

220 root, k_root = _get_root(key) 

221 root[k_root] = v 

222 

223 if opt is not None and opt.cb: 

224 opt.cb(key) 

225 

226 

227def set_option(*args: Any) -> None: 

228 """ 

229 Set the value of the specified option or options. 

230 

231 This method allows fine-grained control over the behavior and display settings 

232 of pandas. Options affect various functionalities such as output formatting, 

233 display limits, and operational behavior. Settings can be modified at runtime 

234 without requiring changes to global configurations or environment variables. 

235 

236 Parameters 

237 ---------- 

238 *args : str | object | dict 

239 Arguments provided in pairs, which will be interpreted as (pattern, value), 

240 or as a single dictionary containing multiple option-value pairs. 

241 pattern: str 

242 Regexp which should match a single option 

243 value: object 

244 New value of option 

245 

246 .. warning:: 

247 

248 Partial pattern matches are supported for convenience, but unless you 

249 use the full option name (e.g. x.y.z.option_name), your code may break in 

250 future versions if new options with similar names are introduced. 

251 

252 Returns 

253 ------- 

254 None 

255 No return value. 

256 

257 Raises 

258 ------ 

259 ValueError if odd numbers of non-keyword arguments are provided 

260 TypeError if keyword arguments are provided 

261 OptionError if no such option exists 

262 

263 See Also 

264 -------- 

265 get_option : Retrieve the value of the specified option. 

266 reset_option : Reset one or more options to their default value. 

267 describe_option : Print the description for one or more registered options. 

268 option_context : Context manager to temporarily set options in a ``with`` 

269 statement. 

270 

271 Notes 

272 ----- 

273 For all available options, please view the :ref:`User Guide <options.available>` 

274 or use ``pandas.describe_option()``. 

275 

276 Examples 

277 -------- 

278 Option-Value Pair Input: 

279 

280 >>> pd.set_option("display.max_columns", 4) 

281 >>> df = pd.DataFrame([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]) 

282 >>> df 

283 0 1 ... 3 4 

284 0 1 2 ... 4 5 

285 1 6 7 ... 9 10 

286 [2 rows x 5 columns] 

287 >>> pd.reset_option("display.max_columns") 

288 

289 Dictionary Input: 

290 

291 >>> pd.set_option({"display.max_columns": 4, "display.precision": 1}) 

292 >>> df = pd.DataFrame([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]) 

293 >>> df 

294 0 1 ... 3 4 

295 0 1 2 ... 4 5 

296 1 6 7 ... 9 10 

297 [2 rows x 5 columns] 

298 >>> pd.reset_option("display.max_columns") 

299 >>> pd.reset_option("display.precision") 

300 """ 

301 _set_option_impl(*args) 

302 

303 

304def describe_option(pat: str = "", _print_desc: bool = True) -> str | None: 

305 """ 

306 Print the description for one or more registered options. 

307 

308 Call with no arguments to get a listing for all registered options. 

309 

310 Parameters 

311 ---------- 

312 pat : str, default "" 

313 String or string regexp pattern. 

314 Empty string will return all options. 

315 For regexp strings, all matching keys will have their description displayed. 

316 _print_desc : bool, default True 

317 If True (default) the description(s) will be printed to stdout. 

318 Otherwise, the description(s) will be returned as a string 

319 (for testing). 

320 

321 Returns 

322 ------- 

323 None 

324 If ``_print_desc=True``. 

325 str 

326 If the description(s) as a string if ``_print_desc=False``. 

327 

328 See Also 

329 -------- 

330 get_option : Retrieve the value of the specified option. 

331 set_option : Set the value of the specified option or options. 

332 reset_option : Reset one or more options to their default value. 

333 

334 Notes 

335 ----- 

336 For all available options, please view the 

337 :ref:`User Guide <options.available>`. 

338 

339 Examples 

340 -------- 

341 >>> pd.describe_option("display.max_columns") # doctest: +SKIP 

342 display.max_columns : int 

343 If max_cols is exceeded, switch to truncate view... 

344 """ 

345 keys = _select_options(pat) 

346 if len(keys) == 0: 

347 raise OptionError(f"No such keys(s) for {pat=}") 

348 

349 s = "\n".join([_build_option_description(k) for k in keys]) 

350 

351 if _print_desc: 

352 print(s) 

353 return None 

354 return s 

355 

356 

357def reset_option(pat: str) -> None: 

358 """ 

359 Reset one or more options to their default value. 

360 

361 This method resets the specified pandas option(s) back to their default 

362 values. It allows partial string matching for convenience, but users should 

363 exercise caution to avoid unintended resets due to changes in option names 

364 in future versions. 

365 

366 Parameters 

367 ---------- 

368 pat : str/regex 

369 If specified only options matching ``pat*`` will be reset. 

370 Pass ``"all"`` as argument to reset all options. 

371 

372 .. warning:: 

373 

374 Partial matches are supported for convenience, but unless you 

375 use the full option name (e.g. x.y.z.option_name), your code may break 

376 in future versions if new options with similar names are introduced. 

377 

378 Returns 

379 ------- 

380 None 

381 No return value. 

382 

383 See Also 

384 -------- 

385 get_option : Retrieve the value of the specified option. 

386 set_option : Set the value of the specified option or options. 

387 describe_option : Print the description for one or more registered options. 

388 

389 Notes 

390 ----- 

391 For all available options, please view the 

392 :ref:`User Guide <options.available>`. 

393 

394 Examples 

395 -------- 

396 >>> pd.reset_option("display.max_columns") # doctest: +SKIP 

397 """ 

398 keys = _select_options(pat) 

399 

400 if len(keys) == 0: 

401 raise OptionError(f"No such keys(s) for {pat=}") 

402 

403 if len(keys) > 1 and len(pat) < 4 and pat != "all": 

404 raise ValueError( 

405 "You must specify at least 4 characters when " 

406 "resetting multiple keys, use the special keyword " 

407 '"all" to reset all the options to their default value' 

408 ) 

409 

410 for k in keys: 

411 set_option(k, _registered_options[k].defval) 

412 

413 

414def get_default_val(pat: str) -> Any: 

415 key = _get_single_key(pat) 

416 opt = _get_registered_option(key) 

417 assert opt is not None 

418 return opt.defval 

419 

420 

421class DictWrapper: 

422 """provide attribute-style access to a nested dict""" 

423 

424 d: dict[str, Any] 

425 

426 def __init__(self, d: dict[str, Any], prefix: str = "") -> None: 

427 object.__setattr__(self, "d", d) 

428 object.__setattr__(self, "prefix", prefix) 

429 

430 def __setattr__(self, key: str, val: Any) -> None: 

431 prefix = object.__getattribute__(self, "prefix") 

432 if prefix: 

433 prefix += "." 

434 prefix += key 

435 # you can't set new keys 

436 # can you can't overwrite subtrees 

437 if key in self.d and not isinstance(self.d[key], dict): 

438 set_option(prefix, val) 

439 else: 

440 raise OptionError("You can only set the value of existing options") 

441 

442 def __getattr__(self, key: str) -> Any: 

443 prefix = object.__getattribute__(self, "prefix") 

444 if prefix: 

445 prefix += "." 

446 prefix += key 

447 try: 

448 v = object.__getattribute__(self, "d")[key] 

449 except KeyError as err: 

450 raise OptionError("No such option") from err 

451 if isinstance(v, dict): 

452 return DictWrapper(v, prefix) 

453 else: 

454 return get_option(prefix) 

455 

456 def __dir__(self) -> list[str]: 

457 return list(self.d.keys()) 

458 

459 

460options = DictWrapper(_global_config) 

461# DictWrapper defines a custom setattr 

462object.__setattr__(options, "__module__", "pandas") 

463 

464# 

465# Functions for use by pandas developers, in addition to User - api 

466 

467 

468@contextmanager 

469def option_context(*args: Any) -> Generator[None]: 

470 """ 

471 Context manager to temporarily set options in a ``with`` statement. 

472 

473 This method allows users to set one or more pandas options temporarily 

474 within a controlled block. The previous options' values are restored 

475 once the block is exited. This is useful when making temporary adjustments 

476 to pandas' behavior without affecting the global state. 

477 

478 Parameters 

479 ---------- 

480 *args : str | object | dict 

481 An even amount of arguments provided in pairs which will be 

482 interpreted as (pattern, value) pairs. Alternatively, a single 

483 dictionary of {pattern: value} may be provided. 

484 

485 Returns 

486 ------- 

487 None 

488 No return value. 

489 

490 Yields 

491 ------ 

492 None 

493 No yield value. 

494 

495 See Also 

496 -------- 

497 get_option : Retrieve the value of the specified option. 

498 set_option : Set the value of the specified option. 

499 reset_option : Reset one or more options to their default value. 

500 describe_option : Print the description for one or more registered options. 

501 

502 Notes 

503 ----- 

504 For all available options, please view the :ref:`User Guide <options.available>` 

505 or use ``pandas.describe_option()``. 

506 

507 Examples 

508 -------- 

509 >>> from pandas import option_context 

510 >>> with option_context("display.max_rows", 10, "display.max_columns", 5): 

511 ... pass 

512 >>> with option_context({"display.max_rows": 10, "display.max_columns": 5}): 

513 ... pass 

514 """ 

515 if len(args) == 1 and isinstance(args[0], dict): 

516 args = tuple(kv for item in args[0].items() for kv in item) 

517 

518 if len(args) % 2 != 0 or len(args) < 2: 

519 raise ValueError( 

520 "Provide an even amount of arguments as " 

521 "option_context(pat, val, pat, val...)." 

522 ) 

523 

524 ops = tuple(zip(args[::2], args[1::2], strict=True)) 

525 undo: tuple[tuple[Any, Any], ...] = () 

526 try: 

527 # GH#63235: a deprecated option must warn exactly once per option_context, 

528 # so only the entry below warns; reading the old value and restoring it are 

529 # bookkeeping the user did not ask for. extra_stacklevel=1 skips the 

530 # contextlib.__enter__ frame so the warning lands on the ``with`` statement. 

531 undo = tuple((pat, _get_option_impl(pat, warn=False)) for pat, val in ops) 

532 for pat, val in ops: 

533 _set_option_impl(pat, val, extra_stacklevel=1) 

534 yield 

535 finally: 

536 for pat, val in undo: 

537 _set_option_impl(pat, val, warn=False) 

538 

539 

540def register_option( 

541 key: str, 

542 defval: object, 

543 doc: str = "", 

544 validator: Callable[[object], Any] | None = None, 

545 cb: Callable[[str], Any] | None = None, 

546) -> None: 

547 """ 

548 Register an option in the package-wide pandas config object 

549 

550 Parameters 

551 ---------- 

552 key : str 

553 Fully-qualified key, e.g. "x.y.option - z". 

554 defval : object 

555 Default value of the option. 

556 doc : str 

557 Description of the option. 

558 validator : Callable, optional 

559 Function of a single argument, should raise `ValueError` if 

560 called with a value which is not a legal value for the option. 

561 cb 

562 a function of a single argument "key", which is called 

563 immediately after an option value is set/reset. key is 

564 the full name of the option. 

565 

566 Raises 

567 ------ 

568 ValueError if `validator` is specified and `defval` is not a valid value. 

569 

570 """ 

571 import keyword 

572 import tokenize 

573 

574 key = key.lower() 

575 

576 if key in _registered_options: 

577 raise OptionError(f"Option '{key}' has already been registered") 

578 if key in _reserved_keys: 

579 raise OptionError(f"Option '{key}' is a reserved key") 

580 

581 # the default value should be legal 

582 if validator: 

583 validator(defval) 

584 

585 # walk the nested dict, creating dicts as needed along the path 

586 path = key.split(".") 

587 

588 for k in path: 

589 if not re.match("^" + tokenize.Name + "$", k): 

590 raise ValueError(f"{k} is not a valid identifier") 

591 if keyword.iskeyword(k): 

592 raise ValueError(f"{k} is a python keyword") 

593 

594 cursor = _global_config 

595 msg = "Path prefix to option '{option}' is already an option" 

596 

597 for i, p in enumerate(path[:-1]): 

598 if not isinstance(cursor, dict): 

599 raise OptionError(msg.format(option=".".join(path[:i]))) 

600 if p not in cursor: 

601 cursor[p] = {} 

602 cursor = cursor[p] 

603 

604 if not isinstance(cursor, dict): 

605 raise OptionError(msg.format(option=".".join(path[:-1]))) 

606 

607 # a namespace already lives here, i.e. `key` is a path prefix to one or 

608 # more already-registered options; registering it would clobber them 

609 # (GH#29242) 

610 if isinstance(cursor.get(path[-1]), dict): 

611 raise OptionError(f"Option '{key}' is a prefix of an already-registered option") 

612 

613 cursor[path[-1]] = defval # initialize 

614 

615 # save the option metadata 

616 _registered_options[key] = RegisteredOption( 

617 key=key, defval=defval, doc=doc, validator=validator, cb=cb 

618 ) 

619 

620 

621def deprecate_option( 

622 key: str, 

623 category: type[Warning], 

624 msg: str | None = None, 

625 rkey: str | None = None, 

626 removal_ver: str | None = None, 

627) -> None: 

628 """ 

629 Mark option `key` as deprecated, if code attempts to access this option, 

630 a warning will be produced, using `msg` if given, or a default message 

631 if not. 

632 if `rkey` is given, any access to the key will be re-routed to `rkey`. 

633 

634 Neither the existence of `key` nor that if `rkey` is checked. If they 

635 do not exist, any subsequence access will fail as usual, after the 

636 deprecation warning is given. 

637 

638 Parameters 

639 ---------- 

640 key : str 

641 Name of the option to be deprecated. 

642 must be a fully-qualified option name (e.g "x.y.z.rkey"). 

643 category : Warning 

644 Warning class for the deprecation. 

645 msg : str, optional 

646 Warning message to output when the key is referenced. 

647 if no message is given a default message will be emitted. 

648 rkey : str, optional 

649 Name of an option to reroute access to. 

650 If specified, any referenced `key` will be 

651 re-routed to `rkey` including set/get/reset. 

652 rkey must be a fully-qualified option name (e.g "x.y.z.rkey"). 

653 used by the default message if no `msg` is specified. 

654 removal_ver : str, optional 

655 Specifies the version in which this option will 

656 be removed. used by the default message if no `msg` is specified. 

657 

658 Raises 

659 ------ 

660 OptionError 

661 If the specified key has already been deprecated. 

662 """ 

663 key = key.lower() 

664 

665 if key in _deprecated_options: 

666 raise OptionError(f"Option '{key}' has already been defined as deprecated.") 

667 

668 _deprecated_options[key] = DeprecatedOption(key, category, msg, rkey, removal_ver) 

669 

670 

671# 

672# functions internal to the module 

673 

674 

675def _select_options(pat: str) -> list[str]: 

676 """ 

677 returns a list of keys matching `pat` 

678 

679 if pat=="all", returns all registered options 

680 """ 

681 # short-circuit for exact key 

682 if pat in _registered_options: 

683 return [pat] 

684 

685 # else look through all of them 

686 keys = sorted(_registered_options.keys()) 

687 if pat == "all": # reserved key 

688 return keys 

689 

690 return [k for k in keys if re.search(pat, k, re.I)] 

691 

692 

693def _get_root(key: str) -> tuple[dict[str, Any], str]: 

694 path = key.split(".") 

695 cursor = _global_config 

696 for p in path[:-1]: 

697 cursor = cursor[p] 

698 return cursor, path[-1] 

699 

700 

701def _get_deprecated_option(key: str) -> DeprecatedOption | None: 

702 """ 

703 Retrieves the metadata for a deprecated option, if `key` is deprecated. 

704 

705 Returns 

706 ------- 

707 DeprecatedOption (namedtuple) if key is deprecated, None otherwise 

708 """ 

709 try: 

710 d = _deprecated_options[key] 

711 except KeyError: 

712 return None 

713 else: 

714 return d 

715 

716 

717def _get_registered_option(key: str) -> RegisteredOption | None: 

718 """ 

719 Retrieves the option metadata if `key` is a registered option. 

720 

721 Returns 

722 ------- 

723 RegisteredOption (namedtuple) if key is deprecated, None otherwise 

724 """ 

725 return _registered_options.get(key) 

726 

727 

728def _translate_key(key: str) -> str: 

729 """ 

730 if `key` is deprecated and a replacement key defined, will return the 

731 replacement key, otherwise returns `key` as-is 

732 """ 

733 d = _get_deprecated_option(key) 

734 if d: 

735 return d.rkey or key 

736 else: 

737 return key 

738 

739 

740def _warn_if_deprecated(key: str, extra_stacklevel: int = 0) -> bool: 

741 """ 

742 Checks if `key` is a deprecated option and if so, prints a warning. 

743 

744 Returns 

745 ------- 

746 bool - True if `key` is deprecated, False otherwise. 

747 """ 

748 d = _get_deprecated_option(key) 

749 if d: 

750 stacklevel = find_stack_level() + extra_stacklevel 

751 if d.msg: 

752 warnings.warn( 

753 d.msg, 

754 d.category, 

755 stacklevel=stacklevel, 

756 ) 

757 else: 

758 msg = f"'{key}' is deprecated" 

759 if d.removal_ver: 

760 msg += f" and will be removed in {d.removal_ver}" 

761 if d.rkey: 

762 msg += f", please use '{d.rkey}' instead." 

763 else: 

764 msg += ", please refrain from using it." 

765 

766 warnings.warn( 

767 msg, 

768 d.category, 

769 stacklevel=stacklevel, 

770 ) 

771 return True 

772 return False 

773 

774 

775def _build_option_description(k: str) -> str: 

776 """Builds a formatted description of a registered option and prints it""" 

777 o = _get_registered_option(k) 

778 d = _get_deprecated_option(k) 

779 assert o is not None 

780 

781 s = f"{k} " 

782 

783 if o.doc: 

784 s += "\n".join(o.doc.strip().split("\n")) 

785 else: 

786 s += "No description available." 

787 

788 if o: 

789 with warnings.catch_warnings(): 

790 warnings.simplefilter("ignore", FutureWarning) 

791 warnings.simplefilter("ignore", DeprecationWarning) 

792 s += f"\n [default: {o.defval}] [currently: {get_option(k)}]" 

793 

794 if d: 

795 rkey = d.rkey or "" 

796 s += "\n (Deprecated" 

797 s += f", use `{rkey}` instead." 

798 s += ")" 

799 

800 return s 

801 

802 

803# helpers 

804 

805 

806@contextmanager 

807def config_prefix(prefix: str) -> Generator[None]: 

808 """ 

809 contextmanager for multiple invocations of API with a common prefix 

810 

811 supported API functions: (register / get / set )__option 

812 

813 Warning: This is not thread - safe, and won't work properly if you import 

814 the API functions into your module using the "from x import y" construct. 

815 

816 Example 

817 ------- 

818 import pandas._config.config as cf 

819 with cf.config_prefix("display.font"): 

820 cf.register_option("color", "red") 

821 cf.register_option("size", " 5 pt") 

822 cf.set_option(size, " 6 pt") 

823 cf.get_option(size) 

824 ... 

825 

826 etc' 

827 

828 will register options "display.font.color", "display.font.size", set the 

829 value of "display.font.size"... and so on. 

830 """ 

831 # Note: reset_option relies on set_option, and on key directly 

832 # it does not fit in to this monkey-patching scheme 

833 

834 global register_option, get_option, set_option 

835 

836 def wrap(func: F) -> F: 

837 def inner(key: str, *args: object, **kwds: object) -> object: 

838 pkey = f"{prefix}.{key}" 

839 return func(pkey, *args, **kwds) 

840 

841 return cast("F", inner) 

842 

843 _register_option = register_option 

844 _get_option = get_option 

845 _set_option = set_option 

846 set_option = wrap(set_option) 

847 get_option = wrap(get_option) 

848 register_option = wrap(register_option) 

849 try: 

850 yield 

851 finally: 

852 set_option = _set_option 

853 get_option = _get_option 

854 register_option = _register_option 

855 

856 

857# These factories and methods are handy for use as the validator 

858# arg in register_option 

859 

860 

861def is_type_factory(_type: type[Any]) -> Callable[[Any], None]: 

862 """ 

863 

864 Parameters 

865 ---------- 

866 `_type` - a type to be compared against (e.g. type(x) == `_type`) 

867 

868 Returns 

869 ------- 

870 validator - a function of a single argument x , which raises 

871 ValueError if type(x) is not equal to `_type` 

872 

873 """ 

874 

875 def inner(x: object) -> None: 

876 if type(x) != _type: 

877 raise ValueError(f"Value must have type '{_type}'") 

878 

879 return inner 

880 

881 

882def is_instance_factory(_type: type | tuple[type, ...]) -> Callable[[Any], None]: 

883 """ 

884 

885 Parameters 

886 ---------- 

887 `_type` - the type to be checked against 

888 

889 Returns 

890 ------- 

891 validator - a function of a single argument x , which raises 

892 ValueError if x is not an instance of `_type` 

893 

894 """ 

895 if isinstance(_type, tuple): 

896 type_repr = "|".join(map(str, _type)) 

897 else: 

898 type_repr = f"'{_type}'" 

899 

900 def inner(x: object) -> None: 

901 if not isinstance(x, _type): 

902 raise ValueError(f"Value must be an instance of {type_repr}") 

903 

904 return inner 

905 

906 

907def is_one_of_factory(legal_values: Sequence[Any]) -> Callable[[Any], None]: 

908 callables = [c for c in legal_values if callable(c)] 

909 legal_values = [c for c in legal_values if not callable(c)] 

910 

911 def inner(x: object) -> None: 

912 if x not in legal_values: 

913 if not any(c(x) for c in callables): 

914 uvals = [str(lval) for lval in legal_values] 

915 pp_values = "|".join(uvals) 

916 msg = f"Value must be one of {pp_values}" 

917 if len(callables): 

918 msg += " or a callable" 

919 raise ValueError(msg) 

920 

921 return inner 

922 

923 

924def is_nonnegative_int(value: object) -> None: 

925 """ 

926 Verify that value is None or a positive int. 

927 

928 Parameters 

929 ---------- 

930 value : None or int 

931 The `value` to be checked. 

932 

933 Raises 

934 ------ 

935 ValueError 

936 When the value is not None or is a negative integer 

937 """ 

938 if value is None: 

939 return 

940 

941 elif isinstance(value, int): 

942 if value >= 0: 

943 return 

944 

945 msg = "Value must be a nonnegative integer or None" 

946 raise ValueError(msg) 

947 

948 

949# common type validators, for convenience 

950# usage: register_option(... , validator = is_int) 

951is_int = is_type_factory(int) 

952is_bool = is_type_factory(bool) 

953is_float = is_type_factory(float) 

954is_str = is_type_factory(str) 

955is_text = is_instance_factory((str, bytes)) 

956 

957 

958def is_callable(obj: object) -> bool: 

959 """ 

960 

961 Parameters 

962 ---------- 

963 `obj` - the object to be checked 

964 

965 Returns 

966 ------- 

967 validator - returns True if object is callable 

968 raises ValueError otherwise. 

969 

970 """ 

971 if not callable(obj): 

972 raise ValueError("Value must be a callable") 

973 return True 

974 

975 

976# import set_module here would cause circular import 

977get_option.__module__ = "pandas" 

978set_option.__module__ = "pandas" 

979describe_option.__module__ = "pandas" 

980reset_option.__module__ = "pandas" 

981option_context.__module__ = "pandas"