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._global_config["compute"]["use_bottleneck"])
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._global_config["compute"]["use_numexpr"])
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._global_config["compute"]["use_numba"])
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, so that double-width characters such as CJK characters and most
210 emoji are aligned correctly.
211 Enabling this may affect performance (default: False)
212"""
213
214pc_ambiguous_as_wide_doc = """
215: boolean
216 Whether to treat characters whose Unicode East Asian Width is ambiguous
217 as double-width. Only used when ``display.unicode.east_asian_width`` is
218 True (default: False)
219"""
220
221
222pc_table_schema_doc = """
223: boolean
224 Whether to publish a Table Schema representation for frontends
225 that support it.
226 (default: False)
227"""
228
229pc_html_border_doc = """
230: int
231 A ``border=value`` attribute is inserted in the ``<table>`` tag
232 for the DataFrame HTML repr.
233"""
234
235pc_html_use_mathjax_doc = """\
236: boolean
237 When True, Jupyter notebook will process table contents using MathJax,
238 rendering mathematical expressions enclosed by the dollar symbol.
239 (default: True)
240"""
241
242pc_max_dir_items = """\
243: int
244 The number of items that will be added to `dir(...)`. 'None' value means
245 unlimited. Because dir is cached, changing this option will not immediately
246 affect already existing dataframes until a column is deleted or added.
247
248 This is for instance used to suggest columns from a dataframe to tab
249 completion.
250"""
251
252pc_width_doc = """
253: int
254 Width of the display in characters. In case python/IPython is running in
255 a terminal this can be set to None and pandas will correctly auto-detect
256 the width.
257 Note that the IPython notebook, IPython qtconsole, or IDLE do not run in a
258 terminal and hence it is not possible to correctly detect the width.
259"""
260
261pc_chop_threshold_doc = """
262: float or None
263 if set to a float value, all float values smaller than the given threshold
264 will be displayed as exactly 0 by repr and friends.
265"""
266
267pc_max_seq_items = """
268: int or None
269 When pretty-printing a long sequence, no more than `max_seq_items`
270 will be printed. If items are omitted, they will be denoted by the
271 addition of "..." to the resulting string.
272
273 If set to None, the number of items to be printed is unlimited.
274"""
275
276pc_max_info_rows_doc = """
277: int
278 df.info() will usually show null-counts for each column.
279 For large frames this can be quite slow. max_info_rows and max_info_cols
280 limit this null check only to frames with smaller dimensions than
281 specified.
282"""
283
284pc_large_repr_doc = """
285: 'truncate'/'info'
286 For DataFrames exceeding max_rows/max_cols, the repr (and HTML repr) can
287 show a truncated table, or switch to the view from
288 df.info() (the behaviour in earlier versions of pandas).
289"""
290
291pc_memory_usage_doc = """
292: bool, string or None
293 This specifies if the memory usage of a DataFrame should be displayed when
294 df.info() is called. Valid values True,False,'deep'
295"""
296
297
298def table_schema_cb(key: str) -> None:
299 from pandas.io.formats.printing import enable_data_resource_formatter
300
301 enable_data_resource_formatter(cf._global_config["display"]["html"]["table_schema"])
302
303
304def is_terminal() -> bool:
305 """
306 Detect if Python is running in a terminal.
307
308 Returns True if Python is running in a terminal or False if not.
309 """
310 try:
311 # error: Name 'get_ipython' is not defined
312 ip = get_ipython() # type: ignore[name-defined]
313 except NameError: # assume standard Python interpreter in a terminal
314 return True
315 else:
316 if hasattr(ip, "kernel"): # IPython as a Jupyter kernel
317 return False
318 else: # IPython in a terminal
319 return True
320
321
322with cf.config_prefix("display"):
323 cf.register_option("precision", 6, pc_precision_doc, validator=is_nonnegative_int)
324 cf.register_option(
325 "float_format",
326 None,
327 float_format_doc,
328 validator=is_one_of_factory([None, is_callable]),
329 )
330 cf.register_option(
331 "max_info_rows",
332 1690785,
333 pc_max_info_rows_doc,
334 validator=is_int,
335 )
336 cf.register_option("max_rows", 60, pc_max_rows_doc, validator=is_nonnegative_int)
337 cf.register_option(
338 "min_rows",
339 10,
340 pc_min_rows_doc,
341 validator=is_instance_factory((type(None), int)),
342 )
343 cf.register_option("max_categories", 8, pc_max_categories_doc, validator=is_int)
344
345 cf.register_option(
346 "max_colwidth",
347 50,
348 max_colwidth_doc,
349 validator=is_nonnegative_int,
350 )
351 if is_terminal():
352 max_cols = 0 # automatically determine optimal number of columns
353 else:
354 max_cols = 20 # cannot determine optimal number of columns
355 cf.register_option(
356 "max_columns", max_cols, pc_max_cols_doc, validator=is_nonnegative_int
357 )
358 cf.register_option(
359 "large_repr",
360 "truncate",
361 pc_large_repr_doc,
362 validator=is_one_of_factory(["truncate", "info"]),
363 )
364 cf.register_option("max_info_columns", 100, pc_max_info_cols_doc, validator=is_int)
365 cf.register_option(
366 "colheader_justify", "right", colheader_justify_doc, validator=is_text
367 )
368 cf.register_option("notebook_repr_html", True, pc_nb_repr_h_doc, validator=is_bool)
369 cf.register_option("pprint_nest_depth", 3, pc_pprint_nest_depth, validator=is_int)
370 cf.register_option("multi_sparse", True, pc_multi_sparse_doc, validator=is_bool)
371 cf.register_option("expand_frame_repr", True, pc_expand_repr_doc)
372 cf.register_option(
373 "show_dimensions",
374 "truncate",
375 pc_show_dimensions_doc,
376 validator=is_one_of_factory([True, False, "truncate"]),
377 )
378 cf.register_option("chop_threshold", None, pc_chop_threshold_doc)
379 cf.register_option("max_seq_items", 100, pc_max_seq_items)
380 cf.register_option(
381 "width", 80, pc_width_doc, validator=is_instance_factory((type(None), int))
382 )
383 cf.register_option(
384 "memory_usage",
385 True,
386 pc_memory_usage_doc,
387 validator=is_one_of_factory([None, True, False, "deep"]),
388 )
389 cf.register_option(
390 "unicode.east_asian_width", False, pc_east_asian_width_doc, validator=is_bool
391 )
392 cf.register_option(
393 "unicode.ambiguous_as_wide", False, pc_ambiguous_as_wide_doc, validator=is_bool
394 )
395 cf.register_option(
396 "html.table_schema",
397 False,
398 pc_table_schema_doc,
399 validator=is_bool,
400 cb=table_schema_cb,
401 )
402 cf.register_option("html.border", 1, pc_html_border_doc, validator=is_int)
403 cf.register_option(
404 "html.use_mathjax", True, pc_html_use_mathjax_doc, validator=is_bool
405 )
406 cf.register_option(
407 "max_dir_items", 100, pc_max_dir_items, validator=is_nonnegative_int
408 )
409
410tc_sim_interactive_doc = """
411: boolean
412 Whether to simulate interactive mode for purposes of testing
413"""
414
415with cf.config_prefix("mode"):
416 cf.register_option("sim_interactive", False, tc_sim_interactive_doc)
417
418
419copy_on_write_doc = """
420: bool
421 Use new copy-view behaviour using Copy-on-Write. No longer used,
422 pandas now always uses Copy-on-Write behavior. This option will
423 be removed in pandas 4.0.
424"""
425
426
427with cf.config_prefix("mode"):
428 cf.register_option(
429 "copy_on_write",
430 # Get the default from an environment variable, if set, otherwise defaults
431 # to False. This environment variable can be set for testing.
432 "warn"
433 if os.environ.get("PANDAS_COPY_ON_WRITE", "0") == "warn"
434 else os.environ.get("PANDAS_COPY_ON_WRITE", "1") == "1",
435 copy_on_write_doc,
436 validator=is_one_of_factory([True, False, "warn"]),
437 )
438
439
440# user warnings
441chained_assignment = """
442: string
443 No longer used. This option has had no effect since SettingWithCopyWarning
444 was removed in pandas 3.0. This option will be removed in pandas 4.0.
445"""
446
447with cf.config_prefix("mode"):
448 cf.register_option(
449 "chained_assignment",
450 "warn",
451 chained_assignment,
452 validator=is_one_of_factory([None, "warn", "raise"]),
453 )
454
455performance_warnings = """
456: boolean
457 Whether to show or hide PerformanceWarnings.
458"""
459
460with cf.config_prefix("mode"):
461 cf.register_option(
462 "performance_warnings",
463 True,
464 performance_warnings,
465 validator=is_bool,
466 )
467
468
469max_threads_doc = """
470: int or None
471 Maximum number of worker threads for parallel operations (e.g. ``read_csv``
472 for large files). ``None`` (the default) means use ``min(os.cpu_count(), 6)``,
473 further limited to the CPUs available to the process (CPU affinity and cgroup
474 limits). Set to ``1`` to disable parallel execution, or to a fixed number to
475 raise the cap or to limit thread usage when pandas is embedded in a larger
476 parallel workflow. Ignored on Emscripten/Pyodide, which cannot spawn threads.
477"""
478
479
480def _is_positive_int_or_none(value: Any) -> None:
481 if value is None:
482 return
483 if isinstance(value, int) and value >= 1:
484 return
485 raise ValueError("Value must be a positive integer or None")
486
487
488with cf.config_prefix("mode"):
489 cf.register_option(
490 "max_threads",
491 None,
492 max_threads_doc,
493 validator=_is_positive_int_or_none,
494 )
495
496
497string_storage_doc = """
498: string
499 The default storage for StringDtype.
500"""
501
502
503def is_valid_string_storage(value: Any) -> None:
504 legal_values = ["auto", "python", "pyarrow"]
505 if value not in legal_values:
506 msg = "Value must be one of python|pyarrow"
507 raise ValueError(msg)
508
509
510with cf.config_prefix("mode"):
511 cf.register_option(
512 "string_storage",
513 "auto",
514 string_storage_doc,
515 # validator=is_one_of_factory(["python", "pyarrow"]),
516 validator=is_valid_string_storage,
517 )
518
519
520# Set up the io.excel specific reader configuration.
521reader_engine_doc = """
522: string
523 The default Excel reader engine for '{ext}' files. Available options:
524 auto, {others}.
525"""
526
527_xls_options = ["xlrd", "calamine"]
528_xlsm_options = ["xlrd", "openpyxl", "calamine"]
529_xlsx_options = ["xlrd", "openpyxl", "calamine"]
530_ods_options = ["odf", "calamine"]
531_xlsb_options = ["pyxlsb", "calamine"]
532
533
534with cf.config_prefix("io.excel.xls"):
535 cf.register_option(
536 "reader",
537 "auto",
538 reader_engine_doc.format(ext="xls", others=", ".join(_xls_options)),
539 validator=is_one_of_factory([*_xls_options, "auto"]),
540 )
541
542with cf.config_prefix("io.excel.xlsm"):
543 cf.register_option(
544 "reader",
545 "auto",
546 reader_engine_doc.format(ext="xlsm", others=", ".join(_xlsm_options)),
547 validator=is_one_of_factory([*_xlsm_options, "auto"]),
548 )
549
550
551with cf.config_prefix("io.excel.xlsx"):
552 cf.register_option(
553 "reader",
554 "auto",
555 reader_engine_doc.format(ext="xlsx", others=", ".join(_xlsx_options)),
556 validator=is_one_of_factory([*_xlsx_options, "auto"]),
557 )
558
559
560with cf.config_prefix("io.excel.ods"):
561 cf.register_option(
562 "reader",
563 "auto",
564 reader_engine_doc.format(ext="ods", others=", ".join(_ods_options)),
565 validator=is_one_of_factory([*_ods_options, "auto"]),
566 )
567
568with cf.config_prefix("io.excel.xlsb"):
569 cf.register_option(
570 "reader",
571 "auto",
572 reader_engine_doc.format(ext="xlsb", others=", ".join(_xlsb_options)),
573 validator=is_one_of_factory([*_xlsb_options, "auto"]),
574 )
575
576# Set up the io.excel specific writer configuration.
577writer_engine_doc = """
578: string
579 The default Excel writer engine for '{ext}' files. Available options:
580 auto, {others}.
581"""
582
583_xlsm_options = ["openpyxl"]
584_xlsx_options = ["openpyxl", "xlsxwriter"]
585_ods_options = ["odf"]
586
587
588with cf.config_prefix("io.excel.xlsm"):
589 cf.register_option(
590 "writer",
591 "auto",
592 writer_engine_doc.format(ext="xlsm", others=", ".join(_xlsm_options)),
593 validator=str,
594 )
595
596
597with cf.config_prefix("io.excel.xlsx"):
598 cf.register_option(
599 "writer",
600 "auto",
601 writer_engine_doc.format(ext="xlsx", others=", ".join(_xlsx_options)),
602 validator=str,
603 )
604
605
606with cf.config_prefix("io.excel.ods"):
607 cf.register_option(
608 "writer",
609 "auto",
610 writer_engine_doc.format(ext="ods", others=", ".join(_ods_options)),
611 validator=str,
612 )
613
614
615# Set up the io.parquet specific configuration.
616parquet_engine_doc = """
617: string
618 The default parquet reader/writer engine. Available options:
619 'auto', 'pyarrow', 'fastparquet', the default is 'auto'
620"""
621
622with cf.config_prefix("io.parquet"):
623 cf.register_option(
624 "engine",
625 "auto",
626 parquet_engine_doc,
627 validator=is_one_of_factory(["auto", "pyarrow", "fastparquet"]),
628 )
629
630
631# Set up the io.sql specific configuration.
632sql_engine_doc = """
633: string
634 The default sql reader/writer engine. Available options:
635 'auto', 'sqlalchemy', the default is 'auto'
636"""
637
638with cf.config_prefix("io.sql"):
639 cf.register_option(
640 "engine",
641 "auto",
642 sql_engine_doc,
643 validator=is_one_of_factory(["auto", "sqlalchemy"]),
644 )
645
646# --------
647# Plotting
648# ---------
649
650plotting_backend_doc = """
651: str
652 The plotting backend to use. The default value is "matplotlib", the
653 backend provided with pandas. Other backends can be specified by
654 providing the name of the module that implements the backend.
655"""
656
657
658def register_plotting_backend_cb(key: str | None) -> None:
659 if key == "matplotlib":
660 # We defer matplotlib validation, since it's the default
661 return
662 from pandas.plotting._core import _get_plot_backend
663
664 _get_plot_backend(key)
665
666
667with cf.config_prefix("plotting"):
668 cf.register_option(
669 "backend",
670 defval="matplotlib",
671 doc=plotting_backend_doc,
672 validator=register_plotting_backend_cb, # type: ignore[arg-type]
673 )
674
675
676register_converter_doc = """
677: bool or 'auto'.
678 Whether to register converters with matplotlib's units registry for
679 dates, times, datetimes, and Periods. Toggling to False will remove
680 the converters, restoring any converters that pandas overwrote.
681"""
682
683
684def register_converter_cb(key: str) -> None:
685 from pandas.plotting import (
686 deregister_matplotlib_converters,
687 register_matplotlib_converters,
688 )
689
690 if cf._global_config["plotting"]["matplotlib"]["register_converters"]:
691 register_matplotlib_converters()
692 else:
693 deregister_matplotlib_converters()
694
695
696with cf.config_prefix("plotting.matplotlib"):
697 cf.register_option(
698 "register_converters",
699 "auto",
700 register_converter_doc,
701 validator=is_one_of_factory(["auto", True, False]),
702 cb=register_converter_cb,
703 )
704
705# ------
706# Styler
707# ------
708
709styler_sparse_index_doc = """
710: bool
711 Whether to sparsify the display of a hierarchical index. Setting to False will
712 display each explicit level element in a hierarchical key for each row.
713"""
714
715styler_sparse_columns_doc = """
716: bool
717 Whether to sparsify the display of hierarchical columns. Setting to False will
718 display each explicit level element in a hierarchical key for each column.
719"""
720
721styler_render_repr = """
722: str
723 Determine which output to use in Jupyter Notebook in {"html", "latex"}.
724"""
725
726styler_max_elements = """
727: int
728 The maximum number of data-cell (<td>) elements that will be rendered before
729 trimming will occur over columns, rows or both if needed. Not applied to LaTeX.
730"""
731
732styler_max_rows = """
733: int, optional
734 The maximum number of rows that will be rendered. May still be reduced to
735 satisfy ``max_elements``, which takes precedence. Not applied to LaTeX.
736"""
737
738styler_max_columns = """
739: int, optional
740 The maximum number of columns that will be rendered. May still be reduced to
741 satisfy ``max_elements``, which takes precedence. Not applied to LaTeX.
742"""
743
744styler_precision = """
745: int
746 The precision for floats and complex numbers.
747 This option affects only ``Styler`` rendering (e.g. ``DataFrame.style``), not
748 the default Series/DataFrame repr, which is controlled by the ``display.*``
749 options.
750"""
751
752styler_decimal = """
753: str
754 The character representation for the decimal separator for floats and complex.
755 This option affects only ``Styler`` rendering (e.g. ``DataFrame.style``), not
756 the default Series/DataFrame repr, which is controlled by the ``display.*``
757 options.
758"""
759
760styler_thousands = """
761: str, optional
762 The character representation for thousands separator for floats, int and complex.
763 This option affects only ``Styler`` rendering (e.g. ``DataFrame.style``), not
764 the default Series/DataFrame repr, which is controlled by the ``display.*``
765 options.
766"""
767
768styler_na_rep = """
769: str, optional
770 The string representation for values identified as missing.
771 This option affects only ``Styler`` rendering (e.g. ``DataFrame.style``), not
772 the default Series/DataFrame repr, which is controlled by the ``display.*``
773 options.
774"""
775
776styler_escape = """
777: str, optional
778 Whether to escape certain characters according to the given context; html or latex.
779 This option affects only ``Styler`` rendering (e.g. ``DataFrame.style``), not
780 the default Series/DataFrame repr, which is controlled by the ``display.*``
781 options.
782"""
783
784styler_formatter = """
785: str, callable, dict, optional
786 A formatter object to be used as default within ``Styler.format``.
787"""
788
789styler_multirow_align = """
790: {"c", "t", "b"}
791 The specifier for vertical alignment of sparsified LaTeX multirows.
792"""
793
794styler_multicol_align = r"""
795: {"r", "c", "l", "naive-l", "naive-r"}
796 The specifier for horizontal alignment of sparsified LaTeX multicolumns. Pipe
797 decorators can also be added to non-naive values to draw vertical
798 rules, e.g. "\|r" will draw a rule on the left side of right aligned merged cells.
799"""
800
801styler_hrules = """
802: bool
803 Whether to add horizontal rules on top and bottom and below the headers.
804"""
805
806styler_environment = """
807: str
808 The environment to replace ``\\begin{table}``. If "longtable" is used results
809 in a specific longtable environment format.
810"""
811
812styler_encoding = """
813: str
814 The encoding used for output HTML and LaTeX files.
815"""
816
817styler_mathjax = """
818: bool
819 If False will render special CSS classes to table attributes that indicate Mathjax
820 will not be used in Jupyter Notebook.
821"""
822
823with cf.config_prefix("styler"):
824 cf.register_option("sparse.index", True, styler_sparse_index_doc, validator=is_bool)
825
826 cf.register_option(
827 "sparse.columns", True, styler_sparse_columns_doc, validator=is_bool
828 )
829
830 cf.register_option(
831 "render.repr",
832 "html",
833 styler_render_repr,
834 validator=is_one_of_factory(["html", "latex"]),
835 )
836
837 cf.register_option(
838 "render.max_elements",
839 2**18,
840 styler_max_elements,
841 validator=is_nonnegative_int,
842 )
843
844 cf.register_option(
845 "render.max_rows",
846 None,
847 styler_max_rows,
848 validator=is_nonnegative_int,
849 )
850
851 cf.register_option(
852 "render.max_columns",
853 None,
854 styler_max_columns,
855 validator=is_nonnegative_int,
856 )
857
858 cf.register_option("render.encoding", "utf-8", styler_encoding, validator=is_str)
859
860 cf.register_option("format.decimal", ".", styler_decimal, validator=is_str)
861
862 cf.register_option(
863 "format.precision", 6, styler_precision, validator=is_nonnegative_int
864 )
865
866 cf.register_option(
867 "format.thousands",
868 None,
869 styler_thousands,
870 validator=is_instance_factory((type(None), str)),
871 )
872
873 cf.register_option(
874 "format.na_rep",
875 None,
876 styler_na_rep,
877 validator=is_instance_factory((type(None), str)),
878 )
879
880 cf.register_option(
881 "format.escape",
882 None,
883 styler_escape,
884 validator=is_one_of_factory([None, "html", "latex", "latex-math"]),
885 )
886
887 # error: Argument 1 to "is_instance_factory" has incompatible type "tuple[
888 # ..., <typing special form>, ...]"; expected "type | tuple[type, ...]"
889 cf.register_option(
890 "format.formatter",
891 None,
892 styler_formatter,
893 validator=is_instance_factory(
894 (type(None), dict, Callable, str) # type: ignore[arg-type]
895 ),
896 )
897
898 cf.register_option("html.mathjax", True, styler_mathjax, validator=is_bool)
899
900 cf.register_option(
901 "latex.multirow_align",
902 "c",
903 styler_multirow_align,
904 validator=is_one_of_factory(["c", "t", "b", "naive"]),
905 )
906
907 val_mca = ["r", "|r|", "|r", "r|", "c", "|c|", "|c", "c|", "l", "|l|", "|l", "l|"]
908 val_mca += ["naive-l", "naive-r"]
909 cf.register_option(
910 "latex.multicol_align",
911 "r",
912 styler_multicol_align,
913 validator=is_one_of_factory(val_mca),
914 )
915
916 cf.register_option("latex.hrules", False, styler_hrules, validator=is_bool)
917
918 cf.register_option(
919 "latex.environment",
920 None,
921 styler_environment,
922 validator=is_instance_factory((type(None), str)),
923 )
924
925
926# Used by CI to run the test suite with every enrolled future
927# option set to its old ("legacy") or future ("upcoming") value.
928_FUTURE_MODE = os.environ.get("PANDAS_FUTURE", "default")
929if _FUTURE_MODE not in ("legacy", "default", "upcoming"):
930 raise ValueError(
931 "PANDAS_FUTURE environment variable must be one of 'legacy', "
932 f"'default', or 'upcoming', got {_FUTURE_MODE!r}"
933 )
934
935_future_option_behaviors: dict[str, dict[str, Any]] = {}
936
937
938def _register_future_option(
939 name: str,
940 *,
941 legacy: Any,
942 default: Any,
943 upcoming: Any,
944 doc: str,
945 validator: Callable[[object], Any],
946 enrolled: bool = True,
947) -> None:
948 """
949 Register an option under the "future" prefix.
950
951 The option's value is determined by, in order of precedence:
952
953 1. The PANDAS_FUTURE_<NAME> environment variable, if set: "0" means
954 False and "1" means True; any other value raises.
955 2. The PANDAS_FUTURE environment variable ("legacy", "default", or
956 "upcoming"), if the option is enrolled.
957 3. The ``default`` value.
958
959 ``enrolled=False`` registers the option but exempts it from
960 PANDAS_FUTURE, for options whose non-default values do not yet pass the
961 test suite.
962 """
963 env_override = os.environ.get(f"PANDAS_FUTURE_{name.upper()}")
964 if env_override is not None:
965 if env_override not in ("0", "1"):
966 raise ValueError(
967 f"PANDAS_FUTURE_{name.upper()} environment variable must be "
968 f"'0' or '1', got {env_override!r}"
969 )
970 value = env_override == "1"
971 elif enrolled:
972 value = {"legacy": legacy, "default": default, "upcoming": upcoming}[
973 _FUTURE_MODE
974 ]
975 else:
976 value = default
977 _future_option_behaviors[name] = {
978 "legacy": legacy,
979 "default": default,
980 "upcoming": upcoming,
981 "enrolled": enrolled,
982 }
983 cf.register_option(name, value, doc, validator=validator)
984
985
986with cf.config_prefix("future"):
987 _register_future_option(
988 "infer_string",
989 legacy=False,
990 default=True,
991 upcoming=True,
992 doc="Whether to infer a sequence of str objects as str dtype rather "
993 "than object dtype. This has been the default since pandas 3.0. This "
994 "option is deprecated and will be removed in pandas 4.0, at which "
995 "point str dtype will always be inferred.",
996 validator=is_one_of_factory([True, False]),
997 )
998
999 cf.register_option(
1000 "no_silent_downcasting",
1001 False,
1002 "This option is deprecated and will be removed in a future version. "
1003 "It has no effect.",
1004 validator=is_one_of_factory([True, False]),
1005 )
1006
1007 _register_future_option(
1008 "distinguish_nan_and_na",
1009 legacy=False,
1010 default=False,
1011 upcoming=True,
1012 # the test suite does not yet pass with the upcoming value
1013 enrolled=False,
1014 doc="Whether to treat NaN entries as distinct from pd.NA in "
1015 "numpy-nullable and pyarrow float dtypes. By default treats both "
1016 "interchangeable as missing values (NaN will be coerced to NA). "
1017 "See discussion in "
1018 "https://github.com/pandas-dev/pandas/issues/32265",
1019 validator=is_one_of_factory([True, False]),
1020 )
1021
1022 _register_future_option(
1023 "python_scalars",
1024 legacy=False,
1025 default=False,
1026 upcoming=True,
1027 doc="Whether to return Python scalars instead of NumPy or PyArrow "
1028 "scalars. "
1029 "Values from object dtype data where the operation coerces them to NumPy "
1030 "floats remain NumPy scalars. "
1031 "Currently experimental, setting to True is not recommended for end users.",
1032 validator=is_one_of_factory([True, False]),
1033 )
1034
1035 _register_future_option(
1036 "infer_freq_returns_offset",
1037 legacy=False,
1038 default=None,
1039 upcoming=True,
1040 # the test suite does not yet pass with the legacy or upcoming values
1041 enrolled=False,
1042 doc="Whether pd.infer_freq and .inferred_freq return a BaseOffset object "
1043 "instead of a string, which will be the default in a future version of "
1044 "pandas. Set to True to opt in to the future behavior, or False to "
1045 "keep the old behavior and silence the warning.",
1046 validator=is_one_of_factory([True, False, None]),
1047 )
1048
1049
1050# GH#59502
1051cf.deprecate_option("future.no_silent_downcasting", Pandas4Warning)
1052# GH#68436
1053cf.deprecate_option(
1054 "future.infer_string",
1055 Pandas4Warning,
1056 msg=(
1057 "The 'future.infer_string' option is deprecated and will be removed in "
1058 "pandas 4.0. Inferring str dtype for string data has been the default "
1059 "since pandas 3.0, and it will no longer be possible to disable it."
1060 ),
1061)
1062cf.deprecate_option(
1063 "mode.copy_on_write",
1064 Pandas4Warning,
1065 msg=(
1066 "The 'mode.copy_on_write' option is deprecated. Copy-on-Write can no longer "
1067 "be disabled (it is always enabled with pandas >= 3.0), and setting the option "
1068 "has no impact. This option will be removed in pandas 4.0."
1069 ),
1070)
1071cf.deprecate_option(
1072 "mode.chained_assignment",
1073 Pandas4Warning,
1074 msg=(
1075 "The 'mode.chained_assignment' option is deprecated. It has had no effect "
1076 "since pandas 3.0, which removed the SettingWithCopyWarning it controlled. "
1077 "Chained assignment now emits a ChainedAssignmentError warning instead; use "
1078 "warnings.filterwarnings with category=ChainedAssignmentError to silence or "
1079 "escalate it. This option will be removed in pandas 4.0."
1080 ),
1081)