Repository: pandas-dev/pandas
Pull request #60449 (2024-11-29 05:01:33)

DOC: fix SA01,ES01 for pandas.io.stata.StataWriter.write_file
fixes

```
pandas.io.stata.StataWriter.write_file SA01, ES01
```


Patch:
diff --git a/ci/code_checks.sh b/ci/code_checks.sh
index 9faa2a2496..3948f654f9 100755
--- a/ci/code_checks.sh
+++ b/ci/code_checks.sh
@@ -89,16 +89,13 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
         -i "pandas.arrays.TimedeltaArray PR07,SA01" \
         -i "pandas.core.groupby.DataFrameGroupBy.boxplot PR07,RT03,SA01" \
         -i "pandas.core.groupby.DataFrameGroupBy.get_group RT03,SA01" \
-        -i "pandas.core.groupby.DataFrameGroupBy.indices SA01" \
         -i "pandas.core.groupby.DataFrameGroupBy.nunique SA01" \
         -i "pandas.core.groupby.DataFrameGroupBy.plot PR02" \
         -i "pandas.core.groupby.DataFrameGroupBy.sem SA01" \
         -i "pandas.core.groupby.SeriesGroupBy.get_group RT03,SA01" \
-        -i "pandas.core.groupby.SeriesGroupBy.indices SA01" \
         -i "pandas.core.groupby.SeriesGroupBy.plot PR02" \
         -i "pandas.core.groupby.SeriesGroupBy.sem SA01" \
         -i "pandas.core.resample.Resampler.get_group RT03,SA01" \
-        -i "pandas.core.resample.Resampler.indices SA01" \
         -i "pandas.core.resample.Resampler.max PR01,RT03,SA01" \
         -i "pandas.core.resample.Resampler.mean SA01" \
         -i "pandas.core.resample.Resampler.min PR01,RT03,SA01" \
@@ -116,7 +113,6 @@ if [[ -z "$CHECK" || "$CHECK" == "docstrings" ]]; then
         -i "pandas.errors.ValueLabelTypeMismatch SA01" \
         -i "pandas.infer_freq SA01" \
         -i "pandas.io.json.build_table_schema PR07,RT03,SA01" \
-        -i "pandas.io.stata.StataWriter.write_file SA01" \
         -i "pandas.plotting.andrews_curves RT03,SA01" \
         -i "pandas.plotting.scatter_matrix PR07,SA01" \
         -i "pandas.tseries.offsets.BDay PR02,SA01" \
diff --git a/doc/source/whatsnew/v3.0.0.rst b/doc/source/whatsnew/v3.0.0.rst
index 4bd31de185..e74bd2f745 100644
--- a/doc/source/whatsnew/v3.0.0.rst
+++ b/doc/source/whatsnew/v3.0.0.rst
@@ -667,7 +667,7 @@ Indexing
 ^^^^^^^^
 - Bug in :meth:`DataFrame.__getitem__` returning modified columns when called with ``slice`` in Python 3.12 (:issue:`57500`)
 - Bug in :meth:`DataFrame.from_records` throwing a ``ValueError`` when passed an empty list in ``index`` (:issue:`58594`)
--
+- Bug in printing :attr:`Index.names` and :attr:`MultiIndex.levels` would not escape single quotes (:issue:`60190`)
 
 Missing
 ^^^^^^^
diff --git a/pandas/_config/config.py b/pandas/_config/config.py
index 1d57aa806e..35139979f9 100644
--- a/pandas/_config/config.py
+++ b/pandas/_config/config.py
@@ -188,6 +188,11 @@ def set_option(*args) -> None:
     """
     Set the value of the specified option or options.
 
+    This method allows fine-grained control over the behavior and display settings
+    of pandas. Options affect various functionalities such as output formatting,
+    display limits, and operational behavior. Settings can be modified at runtime
+    without requiring changes to global configurations or environment variables.
+
     Parameters
     ----------
     *args : str | object
diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py
index ad23127ad4..48d4e0456d 100644
--- a/pandas/core/groupby/groupby.py
+++ b/pandas/core/groupby/groupby.py
@@ -515,6 +515,15 @@ class BaseGroupBy(PandasObject, SelectionMixin[NDFrameT], GroupByIndexingMixin):
         """
         Dict {group name -> group indices}.
 
+        See Also
+        --------
+        core.groupby.DataFrameGroupBy.indices : Provides a mapping of group rows to
+            positions of the elements.
+        core.groupby.SeriesGroupBy.indices : Provides a mapping of group rows to
+            positions of the elements.
+        core.resample.Resampler.indices : Provides a mapping of group rows to
+            positions of the elements.
+
         Examples
         --------
 
diff --git a/pandas/core/indexes/frozen.py b/pandas/core/indexes/frozen.py
index c559c52958..254bd71ade 100644
--- a/pandas/core/indexes/frozen.py
+++ b/pandas/core/indexes/frozen.py
@@ -110,7 +110,9 @@ class FrozenList(PandasObject, list):
         raise TypeError(f"'{type(self).__name__}' does not support mutable operations.")
 
     def __str__(self) -> str:
-        return pprint_thing(self, quote_strings=True, escape_chars=("\t", "\r", "\n"))
+        return pprint_thing(
+            self, quote_strings=True, escape_chars=("\t", "\r", "\n", "'")
+        )
 
     def __repr__(self) -> str:
         return f"{type(self).__name__}({self!s})"
diff --git a/pandas/io/formats/printing.py b/pandas/io/formats/printing.py
index 67b5eb6f5e..a9936ba8c8 100644
--- a/pandas/io/formats/printing.py
+++ b/pandas/io/formats/printing.py
@@ -203,7 +203,7 @@ def pprint_thing(
     def as_escaped_string(
         thing: Any, escape_chars: EscapeChars | None = escape_chars
     ) -> str:
-        translate = {"\t": r"\t", "\n": r"\n", "\r": r"\r"}
+        translate = {"\t": r"\t", "\n": r"\n", "\r": r"\r", "'": r"\'"}
         if isinstance(escape_chars, Mapping):
             if default_escapes:
                 translate.update(escape_chars)
diff --git a/pandas/io/stata.py b/pandas/io/stata.py
index ed89d5766c..63f729c834 100644
--- a/pandas/io/stata.py
+++ b/pandas/io/stata.py
@@ -2748,6 +2748,18 @@ supported types."""
         """
         Export DataFrame object to Stata dta format.
 
+        This method writes the contents of a pandas DataFrame to a `.dta` file
+        compatible with Stata. It includes features for handling value labels,
+        variable types, and metadata like timestamps and data labels. The output
+        file can then be read and used in Stata or other compatible statistical
+        tools.
+
+        See Also
+        --------
+        read_stata : Read Stata file into DataFrame.
+        DataFrame.to_stata : Export DataFrame object to Stata dta format.
+        io.stata.StataWriter : A class for writing Stata binary dta files.
+
         Examples
         --------
         >>> df = pd.DataFrame(


Test patch:
diff --git a/pandas/tests/io/formats/test_printing.py b/pandas/tests/io/formats/test_printing.py
index 1009dfec53..3b63011bf8 100644
--- a/pandas/tests/io/formats/test_printing.py
+++ b/pandas/tests/io/formats/test_printing.py
@@ -3,11 +3,33 @@
 from collections.abc import Mapping
 import string
 
+import pytest
+
 import pandas._config.config as cf
 
+import pandas as pd
+
 from pandas.io.formats import printing
 
 
+@pytest.mark.parametrize(
+    "input_names, expected_names",
+    [
+        (["'a b"], "['\\'a b']"),  # Escape leading quote
+        (["test's b"], "['test\\'s b']"),  # Escape apostrophe
+        (["'test' b"], "['\\'test\\' b']"),  # Escape surrounding quotes
+        (["test b'"], "['test b\\'']"),  # Escape single quote
+        (["test\n' b"], "['test\\n\\' b']"),  # Escape quotes, preserve newline
+    ],
+)
+def test_formatted_index_names(input_names, expected_names):
+    # GH#60190
+    df = pd.DataFrame({name: [1, 2, 3] for name in input_names}).set_index(input_names)
+    formatted_names = str(df.index.names)
+
+    assert formatted_names == expected_names
+
+
 def test_adjoin():
     data = [["a", "b", "c"], ["dd", "ee", "ff"], ["ggg", "hhh", "iii"]]
     expected = "a  dd  ggg\nb  ee  hhh\nc  ff  iii"