from __future__ import annotations from typing import TYPE_CHECKING import weakref from pandas.util._decorators import set_module if TYPE_CHECKING: from pandas.core.generic import NDFrame @set_module("pandas") class Flags: """ Flags that apply to pandas objects. “Flags” differ from “metadata”. Flags reflect properties of the pandas object (the Series or DataFrame). Metadata refer to properties of the dataset, and should be stored in DataFrame.attrs. Parameters ---------- obj : Series or DataFrame The object these flags are associated with. allows_duplicate_labels : bool, default True Whether to allow duplicate labels in this object. By default, duplicate labels are permitted. Setting this to ``False`` will cause an :class:`errors.DuplicateLabelError` to be raised when `index` (or columns for DataFrame) is not unique, or any subsequent operation on introduces duplicates. See :ref:`duplicates.disallow` for more. .. warning:: This is an experimental feature. Currently, many methods fail to propagate the ``allows_duplicate_labels`` value. In future versions it is expected that every method taking or returning one or more DataFrame or Series objects will propagate ``allows_duplicate_labels``. See Also -------- DataFrame.attrs : Dictionary of global attributes of this dataset. Series.attrs : Dictionary of global attributes of this dataset. Examples -------- Attributes can be set in two ways: >>> df = pd.DataFrame() >>> df.flags >>> df.flags.allows_duplicate_labels = False >>> df.flags >>> df.flags["allows_duplicate_labels"] = True >>> df.flags """ _keys: set[str] = {"allows_duplicate_labels"} def __init__(self, obj: NDFrame, *, allows_duplicate_labels: bool) -> None: self._allows_duplicate_labels = allows_duplicate_labels self._obj = weakref.ref(obj) @property def allows_duplicate_labels(self) -> bool: """ Whether this object allows duplicate labels. Setting ``allows_duplicate_labels=False`` ensures that the index (and columns of a DataFrame) are unique. Most methods that accept and return a Series or DataFrame will propagate the value of ``allows_duplicate_labels``. See :ref:`duplicates` for more. See Also -------- DataFrame.attrs : Set global metadata on this object. DataFrame.set_flags : Set global flags on this object. Examples -------- >>> df = pd.DataFrame({"A": [1, 2]}, index=["a", "a"]) >>> df.flags.allows_duplicate_labels True >>> df.flags.allows_duplicate_labels = False Traceback (most recent call last): ... pandas.errors.DuplicateLabelError: Index has duplicates. positions label a [0, 1] """ return self._allows_duplicate_labels @allows_duplicate_labels.setter def allows_duplicate_labels(self, value: bool) -> None: value = bool(value) obj = self._obj() if obj is None: raise ValueError("This flag's object has been deleted.") if not value: for ax in obj.axes: ax._maybe_check_unique() self._allows_duplicate_labels = value def __getitem__(self, key: str): if key not in self._keys: raise KeyError(key) return getattr(self, key) def __setitem__(self, key: str, value) -> None: if key not in self._keys: raise ValueError(f"Unknown flag {key}. Must be one of {self._keys}") setattr(self, key, value) def __repr__(self) -> str: return f"" def __eq__(self, other: object) -> bool: if isinstance(other, type(self)): return self.allows_duplicate_labels == other.allows_duplicate_labels return False