1"""
2This module is imported from the pandas package __init__.py file
3in order to ensure that the core.config options registered here will
4be available as soon as the user loads the package. if register_option
5is invoked inside specific modules, they will not be registered until that
6module is imported, which may or may not be a problem.
7
8If you need to make sure options are available even before a certain
9module is imported, register them here rather than in the module.
10
11"""
12
13from __future__ import annotations
14
15from collections.abc import Callable
16import os
17from typing import Any
18
19import pandas._config.config as cf
20from pandas._config.config import (
21 is_bool,
22 is_callable,
23 is_instance_factory,
24 is_int,
25 is_nonnegative_int,
26 is_one_of_factory,
27 is_str,
28 is_text,
29)
30
31from pandas.errors import Pandas4Warning
32
33# compute
34
35use_bottleneck_doc = """
36: bool
37 Use the bottleneck library to accelerate if it is installed,
38 the default is True
39 Valid values: False,True
40"""
41
42
43def use_bottleneck_cb(key: str) -> None:
44 from pandas.core import nanops
45
46 nanops.set_use_bottleneck(cf.get_option(key))
47
48
49use_numexpr_doc = """
50: bool
51 Use the numexpr library to accelerate computation if it is installed,
52 the default is True
53 Valid values: False,True
54"""
55
56
57def use_numexpr_cb(key: str) -> None:
58 from pandas.core.computation import expressions
59
60 expressions.set_use_numexpr(cf.get_option(key))
61
62
63use_numba_doc = """
64: bool
65 Use the numba engine option for select operations if it is installed,
66 the default is False
67 Valid values: False,True
68"""
69
70
71def use_numba_cb(key: str) -> None:
72 from pandas.core.util import numba_
73
74 numba_.set_use_numba(cf.get_option(key))
75
76
77with cf.config_prefix("compute"):
78 cf.register_option(
79 "use_bottleneck",
80 True,
81 use_bottleneck_doc,
82 validator=is_bool,
83 cb=use_bottleneck_cb,
84 )
85 cf.register_option(
86 "use_numexpr", True, use_numexpr_doc, validator=is_bool, cb=use_numexpr_cb
87 )
88 cf.register_option(
89 "use_numba", False, use_numba_doc, validator=is_bool, cb=use_numba_cb
90 )
91#
92# options from the "display" namespace
93
94pc_precision_doc = """
95: int
96 Floating point output precision in terms of number of places after the
97 decimal, for regular formatting as well as scientific notation. Similar
98 to ``precision`` in :meth:`numpy.set_printoptions`.
99"""
100
101pc_max_rows_doc = """
102: int
103 If max_rows is exceeded, switch to truncate view. Depending on
104 `large_repr`, objects are either centrally truncated or printed as
105 a summary view.
106
107 'None' value means unlimited. Beware that printing a large number of rows
108 could cause your rendering environment (the browser, etc.) to crash.
109
110 In case python/IPython is running in a terminal and `large_repr`
111 equals 'truncate' this can be set to 0 and pandas will auto-detect
112 the height of the terminal and print a truncated object which fits
113 the screen height. The IPython notebook, IPython qtconsole, or
114 IDLE do not run in a terminal and hence it is not possible to do
115 correct auto-detection.
116"""
117
118pc_min_rows_doc = """
119: int
120 The numbers of rows to show in a truncated view (when `max_rows` is
121 exceeded). Ignored when `max_rows` is set to None or 0. When set to
122 None, follows the value of `max_rows`.
123"""
124
125pc_max_cols_doc = """
126: int
127 If max_cols is exceeded, switch to truncate view. Depending on
128 `large_repr`, objects are either centrally truncated or printed as
129 a summary view.
130
131 'None' value means unlimited. Beware that printing a large number of
132 columns could cause your rendering environment (the browser, etc.) to
133 crash.
134
135 In case python/IPython is running in a terminal and `large_repr`
136 equals 'truncate' this can be set to 0 or None and pandas will auto-detect
137 the width of the terminal and print a truncated object which fits
138 the screen width. The IPython notebook, IPython qtconsole, or IDLE
139 do not run in a terminal and hence it is not possible to do
140 correct auto-detection and defaults to 20.
141"""
142
143pc_max_categories_doc = """
144: int
145 This sets the maximum number of categories pandas should output when
146 printing out a `Categorical` or a Series of dtype "category".
147"""
148
149pc_max_info_cols_doc = """
150: int
151 max_info_columns is used in DataFrame.info method to decide if
152 per column information will be printed.
153"""
154
155pc_nb_repr_h_doc = """
156: boolean
157 When True, IPython notebook will use html representation for
158 pandas objects (if it is available).
159"""
160
161pc_pprint_nest_depth = """
162: int
163 Controls the number of nested levels to process when pretty-printing
164"""
165
166pc_multi_sparse_doc = """
167: boolean
168 "sparsify" MultiIndex display (don't display repeated
169 elements in outer levels within groups)
170"""
171
172float_format_doc = """
173: callable
174 The callable should accept a floating point number and return
175 a string with the desired format of the number. This is used
176 in some places like SeriesFormatter.
177 See formats.format.EngFormatter for an example.
178"""
179
180max_colwidth_doc = """
181: int or None
182 The maximum width in characters of a column in the repr of
183 a pandas data structure. When the column overflows, a "..."
184 placeholder is embedded in the output. A 'None' value means unlimited.
185"""
186
187colheader_justify_doc = """
188: 'left'/'right'
189 Controls the justification of column headers. used by DataFrameFormatter.
190"""
191
192pc_expand_repr_doc = """
193: boolean
194 Whether to print out the full DataFrame repr for wide DataFrames across
195 multiple lines, `max_columns` is still respected, but the output will
196 wrap-around across multiple "pages" if its width exceeds `display.width`.
197"""
198
199pc_show_dimensions_doc = """
200: boolean or 'truncate'
201 Whether to print out dimensions at the end of DataFrame repr.
202 If 'truncate' is specified, only print out the dimensions if the
203 frame is truncated (e.g. not display all rows and/or columns)
204"""
205
206pc_east_asian_width_doc = """
207: boolean
208 Whether to use the Unicode East Asian Width to calculate the display text
209 width.
210 Enabling this may affect to the performance (default: False)
211"""
212
213
214pc_table_schema_doc = """
215: boolean
216 Whether to publish a Table Schema representation for frontends
217 that support it.
218 (default: False)
219"""
220
221pc_html_border_doc = """
222: int
223 A ``border=value`` attribute is inserted in the ``<table>`` tag
224 for the DataFrame HTML repr.
225"""
226
227pc_html_use_mathjax_doc = """\
228: boolean
229 When True, Jupyter notebook will process table contents using MathJax,
230 rendering mathematical expressions enclosed by the dollar symbol.
231 (default: True)
232"""
233
234pc_max_dir_items = """\
235: int
236 The number of items that will be added to `dir(...)`. 'None' value means
237 unlimited. Because dir is cached, changing this option will not immediately
238 affect already existing dataframes until a column is deleted or added.
239
240 This is for instance used to suggest columns from a dataframe to tab
241 completion.
242"""
243
244pc_width_doc = """
245: int
246 Width of the display in characters. In case python/IPython is running in
247 a terminal this can be set to None and pandas will correctly auto-detect
248 the width.
249 Note that the IPython notebook, IPython qtconsole, or IDLE do not run in a
250 terminal and hence it is not possible to correctly detect the width.
251"""
252
253pc_chop_threshold_doc = """
254: float or None
255 if set to a float value, all float values smaller than the given threshold
256 will be displayed as exactly 0 by repr and friends.
257"""
258
259pc_max_seq_items = """
260: int or None
261 When pretty-printing a long sequence, no more then `max_seq_items`
262 will be printed. If items are omitted, they will be denoted by the
263 addition of "..." to the resulting string.
264
265 If set to None, the number of items to be printed is unlimited.
266"""
267
268pc_max_info_rows_doc = """
269: int
270 df.info() will usually show null-counts for each column.
271 For large frames this can be quite slow. max_info_rows and max_info_cols
272 limit this null check only to frames with smaller dimensions than
273 specified.
274"""
275
276pc_large_repr_doc = """
277: 'truncate'/'info'
278 For DataFrames exceeding max_rows/max_cols, the repr (and HTML repr) can
279 show a truncated table, or switch to the view from
280 df.info() (the behaviour in earlier versions of pandas).
281"""
282
283pc_memory_usage_doc = """
284: bool, string or None
285 This specifies if the memory usage of a DataFrame should be displayed when
286 df.info() is called. Valid values True,False,'deep'
287"""
288
289
290def table_schema_cb(key: str) -> None:
291 from pandas.io.formats.printing import enable_data_resource_formatter
292
293 enable_data_resource_formatter(cf.get_option(key))
294
295
296def is_terminal() -> bool:
297 """
298 Detect if Python is running in a terminal.
299
300 Returns True if Python is running in a terminal or False if not.
301 """
302 try:
303 # error: Name 'get_ipython' is not defined
304 ip = get_ipython() # type: ignore[name-defined]
305 except NameError: # assume standard Python interpreter in a terminal
306 return True
307 else:
308 if hasattr(ip, "kernel"): # IPython as a Jupyter kernel
309 return False
310 else: # IPython in a terminal
311 return True
312
313
314with cf.config_prefix("display"):
315 cf.register_option("precision", 6, pc_precision_doc, validator=is_nonnegative_int)
316 cf.register_option(
317 "float_format",
318 None,
319 float_format_doc,
320 validator=is_one_of_factory([None, is_callable]),
321 )
322 cf.register_option(
323 "max_info_rows",
324 1690785,
325 pc_max_info_rows_doc,
326 validator=is_int,
327 )
328 cf.register_option("max_rows", 60, pc_max_rows_doc, validator=is_nonnegative_int)
329 cf.register_option(
330 "min_rows",
331 10,
332 pc_min_rows_doc,
333 validator=is_instance_factory((type(None), int)),
334 )
335 cf.register_option("max_categories", 8, pc_max_categories_doc, validator=is_int)
336
337 cf.register_option(
338 "max_colwidth",
339 50,
340 max_colwidth_doc,
341 validator=is_nonnegative_int,
342 )
343 if is_terminal():
344 max_cols = 0 # automatically determine optimal number of columns
345 else:
346 max_cols = 20 # cannot determine optimal number of columns
347 cf.register_option(
348 "max_columns", max_cols, pc_max_cols_doc, validator=is_nonnegative_int
349 )
350 cf.register_option(
351 "large_repr",
352 "truncate",
353 pc_large_repr_doc,
354 validator=is_one_of_factory(["truncate", "info"]),
355 )
356 cf.register_option("max_info_columns", 100, pc_max_info_cols_doc, validator=is_int)
357 cf.register_option(
358 "colheader_justify", "right", colheader_justify_doc, validator=is_text
359 )
360 cf.register_option("notebook_repr_html", True, pc_nb_repr_h_doc, validator=is_bool)
361 cf.register_option("pprint_nest_depth", 3, pc_pprint_nest_depth, validator=is_int)
362 cf.register_option("multi_sparse", True, pc_multi_sparse_doc, validator=is_bool)
363 cf.register_option("expand_frame_repr", True, pc_expand_repr_doc)
364 cf.register_option(
365 "show_dimensions",
366 "truncate",
367 pc_show_dimensions_doc,
368 validator=is_one_of_factory([True, False, "truncate"]),
369 )
370 cf.register_option("chop_threshold", None, pc_chop_threshold_doc)
371 cf.register_option("max_seq_items", 100, pc_max_seq_items)
372 cf.register_option(
373 "width", 80, pc_width_doc, validator=is_instance_factory((type(None), int))
374 )
375 cf.register_option(
376 "memory_usage",
377 True,
378 pc_memory_usage_doc,
379 validator=is_one_of_factory([None, True, False, "deep"]),
380 )
381 cf.register_option(
382 "unicode.east_asian_width", False, pc_east_asian_width_doc, validator=is_bool
383 )
384 cf.register_option(
385 "unicode.ambiguous_as_wide", False, pc_east_asian_width_doc, validator=is_bool
386 )
387 cf.register_option(
388 "html.table_schema",
389 False,
390 pc_table_schema_doc,
391 validator=is_bool,
392 cb=table_schema_cb,
393 )
394 cf.register_option("html.border", 1, pc_html_border_doc, validator=is_int)
395 cf.register_option(
396 "html.use_mathjax", True, pc_html_use_mathjax_doc, validator=is_bool
397 )
398 cf.register_option(
399 "max_dir_items", 100, pc_max_dir_items, validator=is_nonnegative_int
400 )
401
402tc_sim_interactive_doc = """
403: boolean
404 Whether to simulate interactive mode for purposes of testing
405"""
406
407with cf.config_prefix("mode"):
408 cf.register_option("sim_interactive", False, tc_sim_interactive_doc)
409
410
411copy_on_write_doc = """
412: bool
413 Use new copy-view behaviour using Copy-on-Write. No longer used,
414 pandas now always uses Copy-on-Write behavior. This option will
415 be removed in pandas 4.0.
416"""
417
418
419with cf.config_prefix("mode"):
420 cf.register_option(
421 "copy_on_write",
422 # Get the default from an environment variable, if set, otherwise defaults
423 # to False. This environment variable can be set for testing.
424 "warn"
425 if os.environ.get("PANDAS_COPY_ON_WRITE", "0") == "warn"
426 else os.environ.get("PANDAS_COPY_ON_WRITE", "1") == "1",
427 copy_on_write_doc,
428 validator=is_one_of_factory([True, False, "warn"]),
429 )
430
431
432# user warnings
433chained_assignment = """
434: string
435 Raise an exception, warn, or no action if trying to use chained assignment,
436 The default is warn
437"""
438
439with cf.config_prefix("mode"):
440 cf.register_option(
441 "chained_assignment",
442 "warn",
443 chained_assignment,
444 validator=is_one_of_factory([None, "warn", "raise"]),
445 )
446
447performance_warnings = """
448: boolean
449 Whether to show or hide PerformanceWarnings.
450"""
451
452with cf.config_prefix("mode"):
453 cf.register_option(
454 "performance_warnings",
455 True,
456 performance_warnings,
457 validator=is_bool,
458 )
459
460
461string_storage_doc = """
462: string
463 The default storage for StringDtype.
464"""
465
466
467def is_valid_string_storage(value: Any) -> None:
468 legal_values = ["auto", "python", "pyarrow"]
469 if value not in legal_values:
470 msg = "Value must be one of python|pyarrow"
471 raise ValueError(msg)
472
473
474with cf.config_prefix("mode"):
475 cf.register_option(
476 "string_storage",
477 "auto",
478 string_storage_doc,
479 # validator=is_one_of_factory(["python", "pyarrow"]),
480 validator=is_valid_string_storage,
481 )
482
483
484# Set up the io.excel specific reader configuration.
485reader_engine_doc = """
486: string
487 The default Excel reader engine for '{ext}' files. Available options:
488 auto, {others}.
489"""
490
491_xls_options = ["xlrd", "calamine"]
492_xlsm_options = ["xlrd", "openpyxl", "calamine"]
493_xlsx_options = ["xlrd", "openpyxl", "calamine"]
494_ods_options = ["odf", "calamine"]
495_xlsb_options = ["pyxlsb", "calamine"]
496
497
498with cf.config_prefix("io.excel.xls"):
499 cf.register_option(
500 "reader",
501 "auto",
502 reader_engine_doc.format(ext="xls", others=", ".join(_xls_options)),
503 validator=is_one_of_factory([*_xls_options, "auto"]),
504 )
505
506with cf.config_prefix("io.excel.xlsm"):
507 cf.register_option(
508 "reader",
509 "auto",
510 reader_engine_doc.format(ext="xlsm", others=", ".join(_xlsm_options)),
511 validator=is_one_of_factory([*_xlsm_options, "auto"]),
512 )
513
514
515with cf.config_prefix("io.excel.xlsx"):
516 cf.register_option(
517 "reader",
518 "auto",
519 reader_engine_doc.format(ext="xlsx", others=", ".join(_xlsx_options)),
520 validator=is_one_of_factory([*_xlsx_options, "auto"]),
521 )
522
523
524with cf.config_prefix("io.excel.ods"):
525 cf.register_option(
526 "reader",
527 "auto",
528 reader_engine_doc.format(ext="ods", others=", ".join(_ods_options)),
529 validator=is_one_of_factory([*_ods_options, "auto"]),
530 )
531
532with cf.config_prefix("io.excel.xlsb"):
533 cf.register_option(
534 "reader",
535 "auto",
536 reader_engine_doc.format(ext="xlsb", others=", ".join(_xlsb_options)),
537 validator=is_one_of_factory([*_xlsb_options, "auto"]),
538 )
539
540# Set up the io.excel specific writer configuration.
541writer_engine_doc = """
542: string
543 The default Excel writer engine for '{ext}' files. Available options:
544 auto, {others}.
545"""
546
547_xlsm_options = ["openpyxl"]
548_xlsx_options = ["openpyxl", "xlsxwriter"]
549_ods_options = ["odf"]
550
551
552with cf.config_prefix("io.excel.xlsm"):
553 cf.register_option(
554 "writer",
555 "auto",
556 writer_engine_doc.format(ext="xlsm", others=", ".join(_xlsm_options)),
557 validator=str,
558 )
559
560
561with cf.config_prefix("io.excel.xlsx"):
562 cf.register_option(
563 "writer",
564 "auto",
565 writer_engine_doc.format(ext="xlsx", others=", ".join(_xlsx_options)),
566 validator=str,
567 )
568
569
570with cf.config_prefix("io.excel.ods"):
571 cf.register_option(
572 "writer",
573 "auto",
574 writer_engine_doc.format(ext="ods", others=", ".join(_ods_options)),
575 validator=str,
576 )
577
578
579# Set up the io.parquet specific configuration.
580parquet_engine_doc = """
581: string
582 The default parquet reader/writer engine. Available options:
583 'auto', 'pyarrow', 'fastparquet', the default is 'auto'
584"""
585
586with cf.config_prefix("io.parquet"):
587 cf.register_option(
588 "engine",
589 "auto",
590 parquet_engine_doc,
591 validator=is_one_of_factory(["auto", "pyarrow", "fastparquet"]),
592 )
593
594
595# Set up the io.sql specific configuration.
596sql_engine_doc = """
597: string
598 The default sql reader/writer engine. Available options:
599 'auto', 'sqlalchemy', the default is 'auto'
600"""
601
602with cf.config_prefix("io.sql"):
603 cf.register_option(
604 "engine",
605 "auto",
606 sql_engine_doc,
607 validator=is_one_of_factory(["auto", "sqlalchemy"]),
608 )
609
610# --------
611# Plotting
612# ---------
613
614plotting_backend_doc = """
615: str
616 The plotting backend to use. The default value is "matplotlib", the
617 backend provided with pandas. Other backends can be specified by
618 providing the name of the module that implements the backend.
619"""
620
621
622def register_plotting_backend_cb(key: str | None) -> None:
623 if key == "matplotlib":
624 # We defer matplotlib validation, since it's the default
625 return
626 from pandas.plotting._core import _get_plot_backend
627
628 _get_plot_backend(key)
629
630
631with cf.config_prefix("plotting"):
632 cf.register_option(
633 "backend",
634 defval="matplotlib",
635 doc=plotting_backend_doc,
636 validator=register_plotting_backend_cb, # type: ignore[arg-type]
637 )
638
639
640register_converter_doc = """
641: bool or 'auto'.
642 Whether to register converters with matplotlib's units registry for
643 dates, times, datetimes, and Periods. Toggling to False will remove
644 the converters, restoring any converters that pandas overwrote.
645"""
646
647
648def register_converter_cb(key: str) -> None:
649 from pandas.plotting import (
650 deregister_matplotlib_converters,
651 register_matplotlib_converters,
652 )
653
654 if cf.get_option(key):
655 register_matplotlib_converters()
656 else:
657 deregister_matplotlib_converters()
658
659
660with cf.config_prefix("plotting.matplotlib"):
661 cf.register_option(
662 "register_converters",
663 "auto",
664 register_converter_doc,
665 validator=is_one_of_factory(["auto", True, False]),
666 cb=register_converter_cb,
667 )
668
669# ------
670# Styler
671# ------
672
673styler_sparse_index_doc = """
674: bool
675 Whether to sparsify the display of a hierarchical index. Setting to False will
676 display each explicit level element in a hierarchical key for each row.
677"""
678
679styler_sparse_columns_doc = """
680: bool
681 Whether to sparsify the display of hierarchical columns. Setting to False will
682 display each explicit level element in a hierarchical key for each column.
683"""
684
685styler_render_repr = """
686: str
687 Determine which output to use in Jupyter Notebook in {"html", "latex"}.
688"""
689
690styler_max_elements = """
691: int
692 The maximum number of data-cell (<td>) elements that will be rendered before
693 trimming will occur over columns, rows or both if needed.
694"""
695
696styler_max_rows = """
697: int, optional
698 The maximum number of rows that will be rendered. May still be reduced to
699 satisfy ``max_elements``, which takes precedence.
700"""
701
702styler_max_columns = """
703: int, optional
704 The maximum number of columns that will be rendered. May still be reduced to
705 satisfy ``max_elements``, which takes precedence.
706"""
707
708styler_precision = """
709: int
710 The precision for floats and complex numbers.
711"""
712
713styler_decimal = """
714: str
715 The character representation for the decimal separator for floats and complex.
716"""
717
718styler_thousands = """
719: str, optional
720 The character representation for thousands separator for floats, int and complex.
721"""
722
723styler_na_rep = """
724: str, optional
725 The string representation for values identified as missing.
726"""
727
728styler_escape = """
729: str, optional
730 Whether to escape certain characters according to the given context; html or latex.
731"""
732
733styler_formatter = """
734: str, callable, dict, optional
735 A formatter object to be used as default within ``Styler.format``.
736"""
737
738styler_multirow_align = """
739: {"c", "t", "b"}
740 The specifier for vertical alignment of sparsified LaTeX multirows.
741"""
742
743styler_multicol_align = r"""
744: {"r", "c", "l", "naive-l", "naive-r"}
745 The specifier for horizontal alignment of sparsified LaTeX multicolumns. Pipe
746 decorators can also be added to non-naive values to draw vertical
747 rules, e.g. "\|r" will draw a rule on the left side of right aligned merged cells.
748"""
749
750styler_hrules = """
751: bool
752 Whether to add horizontal rules on top and bottom and below the headers.
753"""
754
755styler_environment = """
756: str
757 The environment to replace ``\\begin{table}``. If "longtable" is used results
758 in a specific longtable environment format.
759"""
760
761styler_encoding = """
762: str
763 The encoding used for output HTML and LaTeX files.
764"""
765
766styler_mathjax = """
767: bool
768 If False will render special CSS classes to table attributes that indicate Mathjax
769 will not be used in Jupyter Notebook.
770"""
771
772with cf.config_prefix("styler"):
773 cf.register_option("sparse.index", True, styler_sparse_index_doc, validator=is_bool)
774
775 cf.register_option(
776 "sparse.columns", True, styler_sparse_columns_doc, validator=is_bool
777 )
778
779 cf.register_option(
780 "render.repr",
781 "html",
782 styler_render_repr,
783 validator=is_one_of_factory(["html", "latex"]),
784 )
785
786 cf.register_option(
787 "render.max_elements",
788 2**18,
789 styler_max_elements,
790 validator=is_nonnegative_int,
791 )
792
793 cf.register_option(
794 "render.max_rows",
795 None,
796 styler_max_rows,
797 validator=is_nonnegative_int,
798 )
799
800 cf.register_option(
801 "render.max_columns",
802 None,
803 styler_max_columns,
804 validator=is_nonnegative_int,
805 )
806
807 cf.register_option("render.encoding", "utf-8", styler_encoding, validator=is_str)
808
809 cf.register_option("format.decimal", ".", styler_decimal, validator=is_str)
810
811 cf.register_option(
812 "format.precision", 6, styler_precision, validator=is_nonnegative_int
813 )
814
815 cf.register_option(
816 "format.thousands",
817 None,
818 styler_thousands,
819 validator=is_instance_factory((type(None), str)),
820 )
821
822 cf.register_option(
823 "format.na_rep",
824 None,
825 styler_na_rep,
826 validator=is_instance_factory((type(None), str)),
827 )
828
829 cf.register_option(
830 "format.escape",
831 None,
832 styler_escape,
833 validator=is_one_of_factory([None, "html", "latex", "latex-math"]),
834 )
835
836 # error: Argument 1 to "is_instance_factory" has incompatible type "tuple[
837 # ..., <typing special form>, ...]"; expected "type | tuple[type, ...]"
838 cf.register_option(
839 "format.formatter",
840 None,
841 styler_formatter,
842 validator=is_instance_factory(
843 (type(None), dict, Callable, str) # type: ignore[arg-type]
844 ),
845 )
846
847 cf.register_option("html.mathjax", True, styler_mathjax, validator=is_bool)
848
849 cf.register_option(
850 "latex.multirow_align",
851 "c",
852 styler_multirow_align,
853 validator=is_one_of_factory(["c", "t", "b", "naive"]),
854 )
855
856 val_mca = ["r", "|r|", "|r", "r|", "c", "|c|", "|c", "c|", "l", "|l|", "|l", "l|"]
857 val_mca += ["naive-l", "naive-r"]
858 cf.register_option(
859 "latex.multicol_align",
860 "r",
861 styler_multicol_align,
862 validator=is_one_of_factory(val_mca),
863 )
864
865 cf.register_option("latex.hrules", False, styler_hrules, validator=is_bool)
866
867 cf.register_option(
868 "latex.environment",
869 None,
870 styler_environment,
871 validator=is_instance_factory((type(None), str)),
872 )
873
874
875with cf.config_prefix("future"):
876 cf.register_option(
877 "infer_string",
878 False if os.environ.get("PANDAS_FUTURE_INFER_STRING", "1") == "0" else True,
879 "Whether to infer sequence of str objects as pyarrow string "
880 "dtype, which will be the default in pandas 3.0 "
881 "(at which point this option will be deprecated).",
882 validator=is_one_of_factory([True, False]),
883 )
884
885 cf.register_option(
886 "no_silent_downcasting",
887 False,
888 "This option is deprecated and will be removed in a future version. "
889 "It has no effect.",
890 validator=is_one_of_factory([True, False]),
891 )
892
893 cf.register_option(
894 "distinguish_nan_and_na",
895 os.environ.get("PANDAS_FUTURE_DISTINGUISH_NAN_AND_NA", "0") == "1",
896 "Whether to treat NaN entries as distinct from pd.NA in "
897 "numpy-nullable and pyarrow float dtypes. By default treats both "
898 "interchangeable as missing values (NaN will be coerced to NA). "
899 "See discussion in "
900 "https://github.com/pandas-dev/pandas/issues/32265",
901 validator=is_one_of_factory([True, False]),
902 )
903
904 cf.register_option(
905 "python_scalars",
906 False if os.environ.get("PANDAS_FUTURE_PYTHON_SCALARS", "0") == "0" else True,
907 "Whether to return Python scalars instead of NumPy or PyArrow scalars. "
908 "Currently experimental, setting to True is not recommended for end users.",
909 validator=is_one_of_factory([True, False]),
910 )
911
912
913# GH#59502
914cf.deprecate_option("future.no_silent_downcasting", Pandas4Warning)
915cf.deprecate_option(
916 "mode.copy_on_write",
917 Pandas4Warning,
918 msg=(
919 "The 'mode.copy_on_write' option is deprecated. Copy-on-Write can no longer "
920 "be disabled (it is always enabled with pandas >= 3.0), and setting the option "
921 "has no impact. This option will be removed in pandas 4.0."
922 ),
923)