dtype=None,             accept_sparse="csr",             force_all_finite=not _safe_tags(self, key="allow_nan"),<ins>            cast_to_ndarray=not preserve_X,</ins>             reset=False,         )         return self._transform(X)


" too noisy or the selection test too strict.",                 UserWarning,             )            if hasattr(X, "iloc"):                return X.iloc[:, :0]             return np.empty(0, dtype=X.dtype).reshape((X.shape[0], 0))        if len(mask) != X.shape[1]:            raise ValueError("X has a different shape than during fitting.")        return X[:, safe_mask(X, mask)]        return _safe_indexing(X, mask, axis=1)      def inverse_transform(self, X):         """Reverse the transformation operation.


Which strategy to use to initialize the missing values. Same as the         `strategy` parameter in :class:`~sklearn.impute.SimpleImputer`. <ins>    fill_value : str or numerical value, default=None        When `strategy="constant"`, `fill_value` is used to replace all        occurrences of missing_values. For string or object data types,        `fill_value` must be a string.        If `None`, `fill_value` will be 0 when imputing numerical        data and "missing_value" for strings or object data types.        .. versionadded:: 1.3</ins>     imputation_order : {'ascending', 'descending', 'roman', 'arabic', \             'random'}, default='ascending'         The order in which the features will be imputed. Possible values:


"initial_strategy": [             StrOptions({"mean", "median", "most_frequent", "constant"})         ],<ins>        "fill_value": "no_validation",  # any object is valid</ins>         "imputation_order": [             StrOptions({"ascending", "descending", "roman", "arabic", "random"})         ],


tol=1e-3,         n_nearest_features=None,         initial_strategy="mean",<ins>        fill_value=None,</ins>         imputation_order="ascending",         skip_complete=False,         min_value=-np.inf,


self.tol = tol         self.n_nearest_features = n_nearest_features         self.initial_strategy = initial_strategy<ins>        self.fill_value = fill_value</ins>         self.imputation_order = imputation_order         self.skip_complete = skip_complete         self.min_value = min_value


self.initial_imputer_ = SimpleImputer(                 missing_values=self.missing_values,                 strategy=self.initial_strategy,<ins>                fill_value=self.fill_value,</ins>                 keep_empty_features=self.keep_empty_features,             )             X_filled = self.initial_imputer_.fit_transform(X)


The default value changed from `1e-15` to `"auto"` that is            equivalent to `np.finfo(y_pred.dtype).eps`. <ins>        .. deprecated:: 1.3           `eps` is deprecated in 1.3 and will be removed in 1.5.</ins>     normalize : bool, default=True         If true, return the mean loss per sample.         Otherwise, return the sum of the per-sample losses.


y_pred = check_array(         y_pred, ensure_2d=False, dtype=[np.float64, np.float32, np.float16]     )    eps = np.finfo(y_pred.dtype).eps if eps == "auto" else eps    if eps == "auto":        eps = np.finfo(y_pred.dtype).eps    else:        # TODO: Remove user defined eps in 1.5        warnings.warn(            "Setting the eps parameter is deprecated and will "            "be removed in 1.5. Instead eps will always have"            "a default value of `np.finfo(y_pred.dtype).eps`.",            FutureWarning,        )      check_consistent_length(y_pred, y_true, sample_weight)     lb = LabelBinarizer()


# Renormalize     y_pred_sum = y_pred.sum(axis=1)<ins>    if not np.isclose(y_pred_sum, 1, rtol=1e-15, atol=5 * eps).all():        warnings.warn(            "The y_pred values do not sum to one. Starting from 1.5 this"            "will result in an error.",            UserWarning,        )</ins>     y_pred = y_pred / y_pred_sum[:, np.newaxis]     loss = -xlogy(transformed_labels, y_pred).sum(axis=1)


safe_sqr, ) from ..utils._tags import _safe_tagsfrom ..utils.validation import _check_feature_names_infrom ..utils.validation import _check_feature_names_in, check_is_fitted   class SelectorMixin(TransformerMixin, metaclass=ABCMeta):


feature_names_out : ndarray of str objects             Transformed feature names.         """        check_is_fitted(self)         input_features = _check_feature_names_in(self, input_features)         return input_features[self.get_support()] diff --git a/sklearn/random_projection.py b/sklearn/random_projection.py-- a/sklearn/random_projection.py++ b/sklearn/random_projection.py


if self.compute_inverse_components:             self.inverse_components_ = self._compute_inverse_components()         return self    @property    def _n_features_out(self):        """Number of transformed output features.        # Required by ClassNamePrefixFeaturesOutMixin.get_feature_names_out.        self._n_features_out = self.n_components         Used by ClassNamePrefixFeaturesOutMixin.get_feature_names_out.        """        return self.n_components        return self      def inverse_transform(self, X):         """Project data back to its original space.


svd_solver="randomized",                 random_state=random_state,             )<ins>            # Always output a numpy array, no matter what is configured globally            pca.set_output(transform="default")</ins>             X_embedded = pca.fit_transform(X).astype(np.float32, copy=False)             # PCA is rescaled so that PC1 has standard deviation 1e-4 which is             # the default value for random initialization. See issue #18018.


batch_size = np.clip(self.batch_size, 1, n_samples)          try:<ins>            self.n_iter_ = 0</ins>             for it in range(self.max_iter):                 if self.shuffle:                     # Only shuffle the sample indices instead of X and y to


self._build_f(X, y)         return self     def transform(self, T):        """Transform new data by linear interpolation.        Parameters        ----------        T : array-like of shape (n_samples,) or (n_samples, 1)            Data to transform.    def _transform(self, T):        """`_transform` is called by both `transform` and `predict` methods.             .. versionchanged:: 0.24               Also accepts 2d array with 1 feature.        Since `transform` is wrapped to output arrays of specific types (e.g.        NumPy arrays, pandas DataFrame), we cannot make `predict` call `transform`        directly.         Returns        -------        y_pred : ndarray of shape (n_samples,)            The transformed data.        The above behaviour could be changed in the future, if we decide to output        other type of arrays when calling `predict`.         """         if hasattr(self, "X_thresholds_"):             dtype = self.X_thresholds_.dtype         else:


return res <ins>    def transform(self, T):        """Transform new data by linear interpolation.        Parameters        ----------        T : array-like of shape (n_samples,) or (n_samples, 1)            Data to transform.            .. versionchanged:: 0.24               Also accepts 2d array with 1 feature.        Returns        -------        y_pred : ndarray of shape (n_samples,)            The transformed data.        """        return self._transform(T)</ins>     def predict(self, T):         """Predict new data by linear interpolation.


y_pred : ndarray of shape (n_samples,)             Transformed data.         """        return self.transform(T)        return self._transform(T)      # We implement get_feature_names_out here instead of using     # `ClassNamePrefixFeaturesOutMixin`` because `input_features` are ignored.


transformer_names = [                     t[0] for t in self._iter(fitted=True, replace_strings=True)                 ]                feature_names_outs = [X.columns for X in Xs]                # Selection of columns might be empty.                # Hence feature names are filtered for non-emptiness.                feature_names_outs = [X.columns for X in Xs if X.shape[1] != 0]                 names_out = self._add_prefix_for_feature_names_out(                     list(zip(transformer_names, feature_names_outs))                 )


return max_samples      if isinstance(max_samples, Real):        return round(n_samples * max_samples)        return max(round(n_samples * max_samples), 1)   def _generate_sample_indices(random_state, n_samples, n_samples_bootstrap):


- If None (default), then draw `X.shape[0]` samples.         - If int, then draw `max_samples` samples.        - If float, then draw `max_samples * X.shape[0]` samples. Thus,        - If float, then draw `max(round(n_samples * max_samples), 1)` samples. Thus,           `max_samples` should be in the interval `(0.0, 1.0]`.          .. versionadded:: 0.22


if hasattr(y, "__array__") or isinstance(y, Sequence) or is_array_api:         # DeprecationWarning will be replaced by ValueError, see NEP 34         # https://numpy.org/neps/nep-0034-infer-dtype-is-object.html        check_y_kwargs = dict(            accept_sparse=True,            allow_nd=True,            force_all_finite=False,            ensure_2d=False,            ensure_min_samples=0,            ensure_min_features=0,        )         with warnings.catch_warnings():             warnings.simplefilter("error", np.VisibleDeprecationWarning)             try:                y = xp.asarray(y)            except (np.VisibleDeprecationWarning, ValueError):                y = check_array(y, dtype=None, **check_y_kwargs)            except (np.VisibleDeprecationWarning, ValueError) as e:                if str(e).startswith("Complex data not supported"):                    raise                 # dtype=object should be provided explicitly for ragged arrays,                 # see NEP 34                y = xp.asarray(y, dtype=object)                y = check_array(y, dtype=object, **check_y_kwargs)      if not (hasattr(y, "shape") and y.ndim == 2 and y.shape[1] > 1):         return False


# https://numpy.org/neps/nep-0034-infer-dtype-is-object.html     # We therefore catch both deprecation (NumPy < 1.24) warning and     # value error (NumPy >= 1.24).    check_y_kwargs = dict(        accept_sparse=True,        allow_nd=True,        force_all_finite=False,        ensure_2d=False,        ensure_min_samples=0,        ensure_min_features=0,    )     with warnings.catch_warnings():         warnings.simplefilter("error", np.VisibleDeprecationWarning)         if not issparse(y):             try:                y = xp.asarray(y)            except (np.VisibleDeprecationWarning, ValueError):                y = check_array(y, dtype=None, **check_y_kwargs)            except (np.VisibleDeprecationWarning, ValueError) as e:                if str(e).startswith("Complex data not supported"):                    raise                 # dtype=object should be provided explicitly for ragged arrays,                 # see NEP 34                y = xp.asarray(y, dtype=object)                y = check_array(y, dtype=object, **check_y_kwargs)      # The old sequence of sequences format     try:


if y_true.min() < 0:         # TODO(1.4): Replace warning w/ ValueError         warnings.warn(            "ndcg_score should not be used on negative y_true values. ndcg_score will"            " raise a ValueError on negative y_true values starting from version 1.4.",            "ndcg_score should not be used on negative y_true values. ndcg_score"            " will raise a ValueError on negative y_true values starting from"            " version 1.4.",             FutureWarning,         )    if y_true.ndim > 1 and y_true.shape[1] <= 1:        raise ValueError(            "Computing NDCG is only meaningful when there is more than 1 document. "            f"Got {y_true.shape[1]} instead."        )     _check_dcg_target_type(y_true)     gain = _ndcg_sample_scores(y_true, y_score, k=k, ignore_ties=ignore_ties)     return np.average(gain, weights=sample_weight)


)          # early_stopping in partial_fit doesn't make sense        early_stopping = self.early_stopping and not incremental        if self.early_stopping and incremental:            raise ValueError("partial_fit does not support early_stopping=True")        early_stopping = self.early_stopping         if early_stopping:             # don't stratify in multilabel classification             should_stratify = is_classifier(self) and self.n_outputs_ == 1


if self.extra:             msg += "; %s" % self.extra         # FIXME: we should probably reset __new__ for full generality        init = cls.__init__        new = cls.__new__         def wrapped(*args, **kwargs):        def wrapped(cls, *args, **kwargs):             warnings.warn(msg, category=FutureWarning)            return init(*args, **kwargs)            if new is object.__new__:                return object.__new__(cls)            return new(cls, *args, **kwargs)         cls.__init__ = wrapped        cls.__new__ = wrapped         wrapped.__name__ = "__init__"        wrapped.deprecated_original = init        wrapped.__name__ = "__new__"        wrapped.deprecated_original = new          return cls


"max_depth": [Interval(Integral, 1, None, closed="left"), None],         "min_samples_split": [             Interval(Integral, 2, None, closed="left"),            Interval(Real, 0.0, 1.0, closed="right"),            Interval("real_not_int", 0.0, 1.0, closed="right"),         ],         "min_samples_leaf": [             Interval(Integral, 1, None, closed="left"),            Interval(Real, 0.0, 1.0, closed="neither"),            Interval("real_not_int", 0.0, 1.0, closed="neither"),         ],         "min_weight_fraction_leaf": [Interval(Real, 0.0, 0.5, closed="both")],         "max_features": [             Interval(Integral, 1, None, closed="left"),            Interval(Real, 0.0, 1.0, closed="right"),            Interval("real_not_int", 0.0, 1.0, closed="right"),             StrOptions({"auto", "sqrt", "log2"}, deprecated={"auto"}),             None,         ],diff --git a/sklearn/utils/_param_validation.py b/sklearn/utils/_param_validation.py-- a/sklearn/utils/_param_validation.py++ b/sklearn/utils/_param_validation.py


Parameters     ----------    type : {numbers.Integral, numbers.Real}    type : {numbers.Integral, numbers.Real, "real_not_int"}         The set of numbers in which to set the interval.         If "real_not_int", only reals that don't have the integer type        are allowed. For example 1.0 is allowed but 1 is not.     left : float or int or None         The left bound of the interval. None means left bound is -∞.


`[0, +∞) U {+∞}`.     """ <del>    @validate_params(        {            "type": [type],            "left": [Integral, Real, None],            "right": [Integral, Real, None],            "closed": [StrOptions({"left", "right", "both", "neither"})],        }    )</del>     def __init__(self, type, left, right, *, closed):         super().__init__()         self.type = type


self._check_params()      def _check_params(self):<ins>        if self.type not in (Integral, Real, "real_not_int"):            raise ValueError(                "type must be either numbers.Integral, numbers.Real or 'real_not_int'."                f" Got {self.type} instead."            )        if self.closed not in ("left", "right", "both", "neither"):            raise ValueError(                "closed must be either 'left', 'right', 'both' or 'neither'. "                f"Got {self.closed} instead."            )</ins>         if self.type is Integral:             suffix = "for an interval over the integers."             if self.left is not None and not isinstance(self.left, Integral):


raise ValueError(                     f"right can't be None when closed == {self.closed} {suffix}"                 )<ins>        else:            if self.left is not None and not isinstance(self.left, Real):                raise TypeError("Expecting left to be a real number.")            if self.right is not None and not isinstance(self.right, Real):                raise TypeError("Expecting right to be a real number.")</ins>          if self.right is not None and self.left is not None and self.right <= self.left:             raise ValueError(


return False         return True     def _has_valid_type(self, val):        if self.type == "real_not_int":            return isinstance(val, Real) and not isinstance(val, Integral)        return isinstance(val, self.type)     def is_satisfied_by(self, val):        if not isinstance(val, self.type):        if not self._has_valid_type(val):             return False          return val in self


`range(n_features)`.      index : array-like, default=None        Index for data.        Index for data. `index` is ignored if `data_to_wrap` is already a DataFrame.      Returns     -------


if isinstance(data_to_wrap, pd.DataFrame):         if columns is not None:             data_to_wrap.columns = columns<del>        if index is not None:            data_to_wrap.index = index</del>         return data_to_wrap      return pd.DataFrame(data_to_wrap, index=index, columns=columns)


raise ValueError("'grid_resolution' must be strictly greater than 1.")      values = []    # TODO: we should handle missing values (i.e. `np.nan`) specifically and store them    # in a different Bunch attribute.     for feature, is_cat in enumerate(is_categorical):        uniques = np.unique(_safe_indexing(X, feature, axis=1))        try:            uniques = np.unique(_safe_indexing(X, feature, axis=1))        except TypeError as exc:            # `np.unique` will fail in the presence of `np.nan` and `str` categories            # due to sorting. Temporary, we reraise an error explaining the problem.            raise ValueError(                f"The column #{feature} contains mixed data types. Finding unique "                "categories fail due to sorting. It usually means that the column "                "contains `np.nan` values together with `str` categories. Such use "                "case is not yet supported in scikit-learn."            ) from exc         if is_cat or uniques.shape[0] < grid_resolution:             # Use the unique values either because:             # - feature has low resolution use unique values


if sample_weight is not None:             sample_weight = _check_sample_weight(sample_weight, X) <del>        for sample_aligned_params in fit_params.values():            check_consistent_length(y, sample_aligned_params)</del>         # TODO(1.4): Remove when base_estimator is removed         if self.base_estimator != "deprecated":             if self.estimator is not None:


self.offset_ = -0.5             return self         # else, define offset_ wrt contamination parameter        self.offset_ = np.percentile(self.score_samples(X), 100.0 * self.contamination)        # Else, define offset_ wrt contamination parameter        # To avoid performing input validation a second time we call        # _score_samples rather than score_samples        self.offset_ = np.percentile(self._score_samples(X), 100.0 * self.contamination)          return self


The anomaly score of the input samples.             The lower, the more abnormal.         """        # code structure from ForestClassifier/predict_proba        check_is_fitted(self)         # Check data         X = self._validate_data(X, accept_sparse="csr", dtype=np.float32, reset=False)         # Take the opposite of the scores as bigger is better (here less        # abnormal)        return self._score_samples(X)    def _score_samples(self, X):        """Private version of score_samples without input validation.        Input validation would remove feature names, so we disable it.        """        # Code structure from ForestClassifier/predict_proba        check_is_fitted(self)        # Take the opposite of the scores as bigger is better (here less abnormal)         return -self._compute_chunked_score_samples(X)      def _compute_chunked_score_samples(self, X):


import warnings  from ._base import SelectorMixinfrom ..base import BaseEstimator, MetaEstimatorMixin, clonefrom ..base import BaseEstimator, MetaEstimatorMixin, clone, is_classifier from ..utils._param_validation import HasMethods, Hidden, Interval, StrOptions from ..utils._param_validation import RealNotInt from ..utils._tags import _safe_tags from ..utils.validation import check_is_fittedfrom ..model_selection import cross_val_scorefrom ..model_selection import cross_val_score, check_cv from ..metrics import get_scorer_names


if self.tol is not None and self.tol < 0 and self.direction == "forward":             raise ValueError("tol must be positive when doing forward selection") <ins>        cv = check_cv(self.cv, y, classifier=is_classifier(self.estimator))</ins>         cloned_estimator = clone(self.estimator)          # the current mask corresponds to the set of features:


is_auto_select = self.tol is not None and self.n_features_to_select == "auto"         for _ in range(n_iterations):             new_feature_idx, new_score = self._get_best_new_feature_score(                cloned_estimator, X, y, current_mask                cloned_estimator, X, y, cv, current_mask             )             if is_auto_select and ((new_score - old_score) < self.tol):                 break


return self     def _get_best_new_feature_score(self, estimator, X, y, current_mask):    def _get_best_new_feature_score(self, estimator, X, y, cv, current_mask):         # Return the best new feature and its score to add to the current_mask,         # i.e. return the best new feature and its score to add (resp. remove)         # when doing forward selection (resp. backward selection).


estimator,                 X_new,                 y,                cv=self.cv,                cv=cv,                 scoring=self.scoring,                 n_jobs=self.n_jobs,             ).mean()


Increasing true positive rates such that element `i` is the true         positive rate of predictions with score >= `thresholds[i]`.     thresholds : ndarray of shape = (n_thresholds,)    thresholds : ndarray of shape (n_thresholds,)         Decreasing thresholds on the decision function used to compute         fpr and tpr. `thresholds[0]` represents no instances being predicted        and is arbitrarily set to `max(y_score) + 1`.        and is arbitrarily set to `np.inf`.      See Also     --------


are reversed upon returning them to ensure they correspond to both ``fpr``     and ``tpr``, which are sorted in reversed order during their calculation. <ins>    An arbritrary threshold is added for the case `tpr=0` and `fpr=0` to    ensure that the curve starts at `(0, 0)`. This threshold corresponds to the    `np.inf`.</ins>     References     ----------     .. [1] `Wikipedia entry for the Receiver operating characteristic


>>> tpr     array([0. , 0.5, 0.5, 1. , 1. ])     >>> thresholds    array([1.8 , 0.8 , 0.4 , 0.35, 0.1 ])    array([ inf, 0.8 , 0.4 , 0.35, 0.1 ])     """     fps, tps, thresholds = _binary_clf_curve(         y_true, y_score, pos_label=pos_label, sample_weight=sample_weight


# to make sure that the curve starts at (0, 0)     tps = np.r_[0, tps]     fps = np.r_[0, fps]    thresholds = np.r_[thresholds[0] + 1, thresholds]    # get dtype of `y_score` even if it is an array-like    thresholds = np.r_[np.inf, thresholds]      if fps[-1] <= 0:         warnings.warn(


if self.estimator is not None:             self.estimator_ = self.estimator        elif self.base_estimator not in [None, "deprecated"]:        elif self.base_estimator != "deprecated":             warnings.warn(                 (                     "`base_estimator` was renamed to `estimator` in version 1.2 and "


),                 FutureWarning,             )            self.estimator_ = self.base_estimator            if self.base_estimator is not None:                self.estimator_ = self.base_estimator            else:                self.estimator_ = default         else:             self.estimator_ = default diff --git a/sklearn/ensemble/_weight_boosting.py b/sklearn/ensemble/_weight_boosting.py-- a/sklearn/ensemble/_weight_boosting.py++ b/sklearn/ensemble/_weight_boosting.py


"n_estimators": [Interval(Integral, 1, None, closed="left")],         "learning_rate": [Interval(Real, 0, None, closed="neither")],         "random_state": ["random_state"],        "base_estimator": [HasMethods(["fit", "predict"]), StrOptions({"deprecated"})],        "base_estimator": [            HasMethods(["fit", "predict"]),            StrOptions({"deprecated"}),            None,        ],     }      @abstractmethod


import numpy as np from ..utils.validation import check_is_fittedfrom ..utils.validation import check_is_fitted, check_array from ..utils._param_validation import Interval, validate_params, StrOptions  from ..base import is_classifier


The maximum depth of the representation. If None, the tree is fully         generated.     feature_names : list of str, default=None        Names of each of the features.    feature_names : array-like of shape (n_features,), default=None        An array containing the feature names.         If None, generic names will be used ("x[0]", "x[1]", ...).     class_names : list of str or bool, default=None    class_names : array-like of shape (n_classes,) or bool, default=None         Names of each of the target classes in ascending numerical order.         Only relevant for classification and not supported for multi-output.         If ``True``, shows a symbolic representation of the class name.


>>> tree.export_graphviz(clf)     'digraph Tree {...     """<ins>    if feature_names is not None:        feature_names = check_array(            feature_names, ensure_2d=False, dtype=None, ensure_min_samples=0        )    if class_names is not None and not isinstance(class_names, bool):        class_names = check_array(            class_names, ensure_2d=False, dtype=None, ensure_min_samples=0        )</ins>      check_is_fitted(decision_tree)     own_file = False


@validate_params(     {         "decision_tree": [DecisionTreeClassifier, DecisionTreeRegressor],        "feature_names": [list, None],        "class_names": [list, None],        "feature_names": ["array-like", None],        "class_names": ["array-like", None],         "max_depth": [Interval(Integral, 0, None, closed="left"), None],         "spacing": [Interval(Integral, 1, None, closed="left"), None],         "decimals": [Interval(Integral, 0, None, closed="left"), None],


It can be an instance of         DecisionTreeClassifier or DecisionTreeRegressor.     feature_names : list of str, default=None        A list of length n_features containing the feature names.    feature_names : array-like of shape (n_features,), default=None        An array containing the feature names.         If None generic names will be used ("feature_0", "feature_1", ...).     class_names : list or None, default=None    class_names : array-like of shape (n_classes,), default=None         Names of each of the target classes in ascending numerical order.         Only relevant for classification and not supported for multi-output.          - if `None`, the class names are delegated to `decision_tree.classes_`;        - if a list, then `class_names` will be used as class names instead          of `decision_tree.classes_`. The length of `class_names` must match        - otherwise, `class_names` will be used as class names instead of          `decision_tree.classes_`. The length of `class_names` must match           the length of `decision_tree.classes_`.          .. versionadded:: 1.3


|   |--- petal width (cm) >  1.75     |   |   |--- class: 2     """<ins>    if feature_names is not None:        feature_names = check_array(            feature_names, ensure_2d=False, dtype=None, ensure_min_samples=0        )    if class_names is not None:        class_names = check_array(            class_names, ensure_2d=False, dtype=None, ensure_min_samples=0        )</ins>     check_is_fitted(decision_tree)     tree_ = decision_tree.tree_     if is_classifier(decision_tree):


class_names = decision_tree.classes_         elif len(class_names) != len(decision_tree.classes_):             raise ValueError(                "When `class_names` is a list, it should contain as"                "When `class_names` is an array, it should contain as"                 " many items as `decision_tree.classes_`. Got"                 f" {len(class_names)} while the tree was fitted with"                 f" {len(decision_tree.classes_)} classes."


else:         value_fmt = "{}{} value: {}\n"     if feature_names:    if feature_names is not None:         feature_names_ = [             feature_names[i] if i != _tree.TREE_UNDEFINED else None             for i in tree_.feature


# Collect newly grown trees             self.estimators_.extend(trees)         if self.oob_score:        if self.oob_score and (            n_more_estimators > 0 or not hasattr(self, "oob_score_")        ):             y_type = type_of_target(y)             if y_type in ("multiclass-multioutput", "unknown"):                 # FIXME: we could consider to support multiclass-multioutput if


Estimator instance.         """         super().set_output(transform=transform)<ins></ins>         transformers = (             trans             for _, trans, _ in chain(


for trans in transformers:             _safe_set_output(trans, transform=transform) <ins>        if self.remainder not in {"passthrough", "drop"}:            _safe_set_output(self.remainder, transform=transform)</ins>         return self      def get_params(self, deep=True):


We here use scipy builtins which uses the brent optimizer.         """        mask = np.isnan(x)        if np.all(mask):            raise ValueError("Column must not be all nan.")         # the computation of lambda is influenced by NaNs so we need to         # get rid of them        _, lmbda = stats.boxcox(x[~np.isnan(x)], lmbda=None)        _, lmbda = stats.boxcox(x[~mask], lmbda=None)          return lmbda


.. note::            The fast ``method='recursion'`` option is only available for           ``kind='average'``. Plotting individual dependencies requires using           the slower ``method='brute'`` option.           `kind='average'` and `sample_weights=None`. Computing individual           dependencies and doing weighted averages requires using the slower           `method='brute'`.          .. versionadded:: 0.24            Add `kind` parameter with `'average'`, `'individual'`, and `'both'`


X,         features,         *,<ins>        sample_weight=None,</ins>         categorical_features=None,         feature_names=None,         target=None,


with `kind='average'`). Each tuple must be of size 2.             If any entry is a string, then it must be in ``feature_names``. <ins>        sample_weight : array-like of shape (n_samples,), default=None            Sample weights are used to calculate weighted means when averaging the            model output. If `None`, then samples are equally weighted. If            `sample_weight` is not `None`, then `method` will be set to `'brute'`.            Note that `sample_weight` is ignored for `kind='individual'`.            .. versionadded:: 1.3</ins>         categorical_features : array-like of shape (n_features,) or shape \                 (n_categorical_features,), dtype={bool, int, str}, default=None             Indicates the categorical features.


computationally intensive.              - `'auto'`: the `'recursion'` is used for estimators that support it,              and `'brute'` is used otherwise.              and `'brute'` is used otherwise. If `sample_weight` is not `None`,              then `'brute'` is used regardless of the estimator.              Please see :ref:`this note <pdp_method_differences>` for             differences between the `'brute'` and `'recursion'` method.


- ``kind='average'`` results in the traditional PD plot;             - ``kind='individual'`` results in the ICE plot.            Note that the fast ``method='recursion'`` option is only available for           ``kind='average'``. Plotting individual dependencies requires using the           slower ``method='brute'`` option.           Note that the fast `method='recursion'` option is only available for           `kind='average'` and `sample_weights=None`. Computing individual           dependencies and doing weighted averages requires using the slower           `method='brute'`.          centered : bool, default=False             If `True`, the ICE and PD lines will start at the origin of the


estimator,                 X,                 fxs,<ins>                sample_weight=sample_weight,</ins>                 feature_names=feature_names,                 categorical_features=categorical_features,                 response_method=response_method,


sample_weight=sample_weight)  def roc_auc_score(y_true, y_score, average="macro", sample_weight=None):def roc_auc_score(y_true, y_score, average="macro", sample_weight=None,                  max_fpr=None):     """Compute Area Under the Receiver Operating Characteristic Curve (ROC AUC)     from prediction scores.


sample_weight : array-like of shape = [n_samples], optional         Sample weights. <ins>    max_fpr : float > 0 and <= 1, optional        If not ``None``, the standardized partial AUC [3]_ over the range        [0, max_fpr] is returned.</ins>     Returns     -------     auc : float


.. [2] Fawcett T. An introduction to ROC analysis[J]. Pattern Recognition            Letters, 2006, 27(8):861-874. <ins>    .. [3] `Analyzing a portion of the ROC curve. McClish, 1989            <http://www.ncbi.nlm.nih.gov/pubmed/2668680>`_</ins>     See also     --------     average_precision_score : Area under the precision-recall curve


fpr, tpr, tresholds = roc_curve(y_true, y_score,                                         sample_weight=sample_weight)        return auc(fpr, tpr)        if max_fpr is None or max_fpr == 1:            return auc(fpr, tpr)        if max_fpr <= 0 or max_fpr > 1:            raise ValueError("Expected max_frp in range ]0, 1], got: %r"                             % max_fpr)        # Add a single point at max_fpr by linear interpolation        stop = np.searchsorted(fpr, max_fpr, 'right')        x_interp = [fpr[stop - 1], fpr[stop]]        y_interp = [tpr[stop - 1], tpr[stop]]        tpr = np.append(tpr[:stop], np.interp(max_fpr, x_interp, y_interp))        fpr = np.append(fpr[:stop], max_fpr)        partial_auc = auc(fpr, tpr)        # McClish correction: standardize result to be 0.5 if non-discriminant        # and 1 if maximal        min_area = 0.5 * max_fpr**2        max_area = max_fpr        return 0.5 * (1 + (partial_auc - min_area) / (max_area - min_area))      y_type = type_of_target(y_true)     if y_type == "binary":


class TestCase(unittest.TestCase):    longMessage = False    longMessage = True     failureException = AssertionError      def _formatMessage(self, msg, standardMsg):diff --git a/sklearn/utils/estimator_checks.py b/sklearn/utils/estimator_checks.py-- a/sklearn/utils/estimator_checks.py++ b/sklearn/utils/estimator_checks.py


yield check_fit2d_1feature     yield check_fit1d     yield check_get_params_invariance<ins>    yield check_set_params</ins>     yield check_dict_unchanged     yield check_dont_overwrite_parameters


shallow_params.items()))  <ins>@ignore_warnings(category=(DeprecationWarning, FutureWarning))def check_set_params(name, estimator_orig):    # Check that get_params() returns the same thing    # before and after set_params() with some fuzz    estimator = clone(estimator_orig)    orig_params = estimator.get_params(deep=False)    msg = ("get_params result does not match what was passed to set_params")    estimator.set_params(**orig_params)    curr_params = estimator.get_params(deep=False)    assert_equal(set(orig_params.keys()), set(curr_params.keys()), msg)    for k, v in curr_params.items():        assert orig_params[k] is v, msg    # some fuzz values    test_values = [-np.inf, np.inf, None]    test_params = deepcopy(orig_params)    for param_name in orig_params.keys():        default_value = orig_params[param_name]        for value in test_values:            test_params[param_name] = value            try:                estimator.set_params(**test_params)            except (TypeError, ValueError) as e:                e_type = e.__class__.__name__                # Exception occurred, possibly parameter validation                warnings.warn("{} occurred during set_params. "                              "It is recommended to delay parameter "                              "validation until fit.".format(e_type))                change_warning_msg = "Estimator's parameters changed after " \                                     "set_params raised {}".format(e_type)                params_before_exception = curr_params                curr_params = estimator.get_params(deep=False)                try:                    assert_equal(set(params_before_exception.keys()),                                 set(curr_params.keys()))                    for k, v in curr_params.items():                        assert params_before_exception[k] is v                except AssertionError:                    warnings.warn(change_warning_msg)            else:                curr_params = estimator.get_params(deep=False)                assert_equal(set(test_params.keys()),                             set(curr_params.keys()),                             msg)                for k, v in curr_params.items():                    assert test_params[k] is v, msg        test_params[param_name] = default_value</ins> @ignore_warnings(category=(DeprecationWarning, FutureWarning)) def check_classifiers_regression_target(name, estimator_orig):     # Check if classifier throws an exception when fed regression targets


self.n_jobs = n_jobs      def _fit_transform(self, X):        X = check_array(X)        X = check_array(X, accept_sparse='csr')         self.nbrs_ = NearestNeighbors(n_neighbors=self.n_neighbors,                                       algorithm=self.neighbors_algorithm,                                       n_jobs=self.n_jobs)diff --git a/sklearn/manifold/locally_linear.py b/sklearn/manifold/locally_linear.py-- a/sklearn/manifold/locally_linear.py++ b/sklearn/manifold/locally_linear.py


Parameters     ----------    X : {array-like, sparse matrix, BallTree, KDTree, NearestNeighbors}    X : {array-like, NearestNeighbors}         Sample data, shape = (n_samples, n_features), in the form of a        numpy array, sparse array, precomputed tree, or NearestNeighbors        object.        numpy array or a NearestNeighbors object.      n_neighbors : int         Number of neighbors for each sample.


Parameters     ----------    X : {array-like, sparse matrix, BallTree, KDTree, NearestNeighbors}    X : {array-like, NearestNeighbors}         Sample data, shape = (n_samples, n_features), in the form of a        numpy array, sparse array, precomputed tree, or NearestNeighbors        object.        numpy array or a NearestNeighbors object.      n_neighbors : integer         number of neighbors to consider for each point.


else:         raise ValueError("Algorithm must be 'auto', 'full' or 'elkan', got"                          " %s" % str(algorithm))    seeds = random_state.randint(np.iinfo(np.int32).max, size=n_init)     if effective_n_jobs(n_jobs) == 1:         # For a single thread, less memory is needed if we just store one set         # of the best results (as opposed to one set per run per thread).        for it in range(n_init):        for seed in seeds:             # run a k-means once             labels, inertia, centers, n_iter_ = kmeans_single(                 X, sample_weight, n_clusters, max_iter=max_iter, init=init,                 verbose=verbose, precompute_distances=precompute_distances,                 tol=tol, x_squared_norms=x_squared_norms,                random_state=random_state)                random_state=seed)             # determine if these results are the best so far             if best_inertia is None or inertia < best_inertia:                 best_labels = labels.copy()


best_n_iter = n_iter_     else:         # parallelisation of k-means runs<del>        seeds = random_state.randint(np.iinfo(np.int32).max, size=n_init)</del>         results = Parallel(n_jobs=n_jobs, verbose=0)(             delayed(kmeans_single)(X, sample_weight, n_clusters,                                    max_iter=max_iter, init=init,


return last_step.fit(Xt, y, **fit_params).transform(Xt)      @if_delegate_has_method(delegate='_final_estimator')    def predict(self, X):    def predict(self, X, **predict_params):         """Apply transforms to the data, and predict with the final estimator          Parameters


Data to predict on. Must fulfill input requirements of first step             of the pipeline. <ins>        **predict_params : dict of string -> object            Parameters to the ``predict`` called at the end of all            transformations in the pipeline. Note that while this may be            used to return uncertainties from some models with return_std            or return_cov, uncertainties that are generated by the            transformations in the pipeline are not propagated to the            final estimator.</ins>         Returns         -------         y_pred : array-like


for name, transform in self.steps[:-1]:             if transform is not None:                 Xt = transform.transform(Xt)        return self.steps[-1][-1].predict(Xt)        return self.steps[-1][-1].predict(Xt, **predict_params)      @if_delegate_has_method(delegate='_final_estimator')     def fit_predict(self, X, y=None, **fit_params):


#   http://cseweb.ucsd.edu/~lvdmaaten/workshops/nips2010/papers/vandermaaten.pdf from __future__ import division <ins>import warnings</ins> from time import time import numpy as np from scipy import linalg


return p, error, i  def trustworthiness(X, X_embedded, n_neighbors=5, precomputed=False):def trustworthiness(X, X_embedded, n_neighbors=5,                    precomputed=False, metric='euclidean'):     r"""Expresses to what extent the local structure is retained.      The trustworthiness is within [0, 1]. It is defined as


precomputed : bool, optional (default: False)         Set this flag if X is a precomputed square distance matrix.         ..deprecated:: 0.20            ``precomputed`` has been deprecated in version 0.20 and will be            removed in version 0.22. Use ``metric`` instead.    metric : string, or callable, optional, default 'euclidean'        Which metric to use for computing pairwise distances between samples        from the original input space. If metric is 'precomputed', X must be a        matrix of pairwise distances or squared distances. Otherwise, see the        documentation of argument metric in sklearn.pairwise.pairwise_distances        for a list of available metrics.     Returns     -------     trustworthiness : float         Trustworthiness of the low-dimensional embedding.     """     if precomputed:        dist_X = X    else:        dist_X = pairwise_distances(X, squared=True)        warnings.warn("The flag 'precomputed' has been deprecated in version "                      "0.20 and will be removed in 0.22. See 'metric' "                      "parameter instead.", DeprecationWarning)        metric = 'precomputed'    dist_X = pairwise_distances(X, metric=metric)     ind_X = np.argsort(dist_X, axis=1)     ind_X_embedded = NearestNeighbors(n_neighbors).fit(X_embedded).kneighbors(         return_distance=False)


coef_ : array, shape (1, n_features) or (n_classes, n_features)         Coefficient of the features in the decision function.         `coef_` is of shape (1, n_features) when the given problem        is binary.        `coef_` is of shape (1, n_features) when the given problem is binary.        In particular, when `multi_class='multinomial'`, `coef_` corresponds        to outcome 1 (True) and `-coef_` corresponds to outcome 0 (False).      intercept_ : array, shape (1,) or (n_classes,)         Intercept (a.k.a. bias) added to the decision function.          If `fit_intercept` is set to False, the intercept is set to zero.        `intercept_` is of shape(1,) when the problem is binary.        `intercept_` is of shape (1,) when the given problem is binary.        In particular, when `multi_class='multinomial'`, `intercept_`        corresponds to outcome 1 (True) and `-intercept_` corresponds to        outcome 0 (False).      n_iter_ : array, shape (n_classes,) or (1, )         Actual number of iterations for all classes. If binary or multinomial,


"""         if not hasattr(self, "coef_"):             raise NotFittedError("Call fit before prediction")        calculate_ovr = self.coef_.shape[0] == 1 or self.multi_class == "ovr"        if calculate_ovr:        if self.multi_class == "ovr":             return super(LogisticRegression, self)._predict_proba_lr(X)         else:            return softmax(self.decision_function(X), copy=False)            decision = self.decision_function(X)            if decision.ndim == 1:                # Workaround for multi_class="multinomial" and binary outcomes                # which requires softmax prediction with only a 1D decision.                decision_2d = np.c_[-decision, decision]            else:                decision_2d = decision            return softmax(decision_2d, copy=False)      def predict_log_proba(self, X):         """Log of probability estimates.


deprecated: bool  def type_to_xref(target: str, env: BuildEnvironment = None, suppress_prefix: bool = False                 ) -> addnodes.pending_xref:    """Convert a type string to a cross reference node."""    if target == 'None' or target.startswith('typing.'):def parse_reftarget(reftarget: str, suppress_prefix: bool = False                    ) -> Tuple[str, str, str, bool]:    """Parse a type string and return (reftype, reftarget, title, refspecific flag)"""    refspecific = False    if reftarget.startswith('.'):        reftarget = reftarget[1:]        title = reftarget        refspecific = True    elif reftarget.startswith('~'):        reftarget = reftarget[1:]        title = reftarget.split('.')[-1]    elif suppress_prefix:        title = reftarget.split('.')[-1]    elif reftarget.startswith('typing.'):        title = reftarget[7:]    else:        title = reftarget    if reftarget == 'None' or reftarget.startswith('typing.'):         # typing module provides non-class types.  Obj reference is good to refer them.         reftype = 'obj'     else:         reftype = 'class'     return reftype, reftarget, title, refspecificdef type_to_xref(target: str, env: BuildEnvironment = None, suppress_prefix: bool = False                 ) -> addnodes.pending_xref:    """Convert a type string to a cross reference node."""     if env:         kwargs = {'py:module': env.ref_context.get('py:module'),                   'py:class': env.ref_context.get('py:class')}     else:         kwargs = {}     refspecific = False    if target.startswith('.'):        target = target[1:]        text = target        refspecific = True    elif target.startswith('~'):        target = target[1:]        text = target.split('.')[-1]    elif suppress_prefix:        text = target.split('.')[-1]    elif target.startswith('typing.'):        text = target[7:]    else:        text = target    reftype, target, title, refspecific = parse_reftarget(target, suppress_prefix)      if env.config.python_use_unqualified_type_names:         # Note: It would be better to use qualname to describe the object to support support         # nested classes.  But python domain can't access the real python object because this         # module should work not-dynamically.        shortname = text.split('.')[-1]        shortname = title.split('.')[-1]         contnodes: List[Node] = [pending_xref_condition('', shortname, condition='resolved'),                                 pending_xref_condition('', text, condition='*')]                                 pending_xref_condition('', title, condition='*')]     else:        contnodes = [nodes.Text(text)]        contnodes = [nodes.Text(title)]      return pending_xref('', *contnodes,                         refdomain='py', reftype=reftype, reftarget=target,


result = super().make_xref(rolename, domain, target,  # type: ignore                                    innernode, contnode,                                    env, inliner=None, location=None)        result['refspecific'] = True        result['py:module'] = env.ref_context.get('py:module')        result['py:class'] = env.ref_context.get('py:class')        if target.startswith(('.', '~')):            prefix, result['reftarget'] = target[0], target[1:]            if prefix == '.':                text = target[1:]            elif prefix == '~':                text = target.split('.')[-1]            for node in list(result.traverse(nodes.Text)):                node.parent[node.parent.index(node)] = nodes.Text(text)                break        elif isinstance(result, pending_xref) and env.config.python_use_unqualified_type_names:            children = result.children            result.clear()            shortname = target.split('.')[-1]            textnode = innernode('', shortname)            contnodes = [pending_xref_condition('', '', textnode, condition='resolved'),                         pending_xref_condition('', '', *children, condition='*')]            result.extend(contnodes)        if isinstance(result, pending_xref):            result['refspecific'] = True            result['py:module'] = env.ref_context.get('py:module')            result['py:class'] = env.ref_context.get('py:class')            reftype, reftarget, reftitle, _ = parse_reftarget(target)            if reftarget != reftitle:                result['reftype'] = reftype                result['reftarget'] = reftarget                result.clear()                result += innernode(reftitle, reftitle)            elif env.config.python_use_unqualified_type_names:                children = result.children                result.clear()                shortname = target.split('.')[-1]                textnode = innernode('', shortname)                contnodes = [pending_xref_condition('', '', textnode, condition='resolved'),                             pending_xref_condition('', '', *children, condition='*')]                result.extend(contnodes)          return result


class PyField(PyXrefMixin, Field):    def make_xref(self, rolename: str, domain: str, target: str,                  innernode: Type[TextlikeNode] = nodes.emphasis,                  contnode: Node = None, env: BuildEnvironment = None,                  inliner: Inliner = None, location: Node = None) -> Node:        if rolename == 'class' and target == 'None':            # None is not a type, so use obj role instead.            rolename = 'obj'        return super().make_xref(rolename, domain, target, innernode, contnode,                                 env, inliner, location)    pass   class PyGroupedField(PyXrefMixin, GroupedField):


class PyTypedField(PyXrefMixin, TypedField):    def make_xref(self, rolename: str, domain: str, target: str,                  innernode: Type[TextlikeNode] = nodes.emphasis,                  contnode: Node = None, env: BuildEnvironment = None,                  inliner: Inliner = None, location: Node = None) -> Node:        if rolename == 'class' and target == 'None':            # None is not a type, so use obj role instead.            rolename = 'obj'        return super().make_xref(rolename, domain, target, innernode, contnode,                                 env, inliner, location)    pass   class PyObject(ObjectDescription[Tuple[str, str]]):diff --git a/sphinx/ext/autodoc/typehints.py b/sphinx/ext/autodoc/typehints.py-- a/sphinx/ext/autodoc/typehints.py++ b/sphinx/ext/autodoc/typehints.py


def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any,                      options: Dict, args: str, retann: str) -> None:     """Record type hints to env object."""<ins>    if app.config.autodoc_typehints_format == 'short':        mode = 'smart'    else:        mode = 'fully-qualified'</ins>     try:         if callable(obj):             annotations = app.env.temp_data.setdefault('annotations', {})


sig = inspect.signature(obj, type_aliases=app.config.autodoc_type_aliases)             for param in sig.parameters.values():                 if param.annotation is not param.empty:                    annotation[param.name] = typing.stringify(param.annotation)                    annotation[param.name] = typing.stringify(param.annotation, mode)             if sig.return_annotation is not sig.empty:                annotation['return'] = typing.stringify(sig.return_annotation)                annotation['return'] = typing.stringify(sig.return_annotation, mode)     except (TypeError, ValueError):         pass


node.parent.hasattr('ids') and node.parent['ids']):             # add permalink anchor             if close_tag.startswith('</h'):                self.add_permalink_ref(node.parent, _('Permalink to this headline'))                self.add_permalink_ref(node.parent, _('Permalink to this heading'))             elif close_tag.startswith('</h'):                 self.body.append('%s' % (                                     _('Permalink to this headline'),                                     _('Permalink to this heading'),                                      self.config.html_permalinks_icon))             elif isinstance(node.parent, nodes.table):                 self.body.append('')diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py-- a/sphinx/writers/html5.py++ b/sphinx/writers/html5.py


node.parent.hasattr('ids') and node.parent['ids']):             # add permalink anchor             if close_tag.startswith('</h'):                self.add_permalink_ref(node.parent, _('Permalink to this headline'))                self.add_permalink_ref(node.parent, _('Permalink to this heading'))             elif close_tag.startswith('</h'):                 self.body.append('%s' % (                                     _('Permalink to this headline'),                                     _('Permalink to this heading'),                                      self.config.html_permalinks_icon))             elif isinstance(node.parent, nodes.table):                 self.body.append('')


descr = _('%s command line option') % currprogram         else:             descr = _('command line option')        for option in sig.split(', '):        for option in signode.get('allnames', []):             entry = '; '.join([descr, option])             self.indexnode['entries'].append(('pair', entry, signode['ids'][0], '', None))


uri_pattern = re.compile(re.escape(base_uri).replace('%s', '(?P<value>.+)'))              match = uri_pattern.match(uri)            if match and match.groupdict().get('value'):            if (                match and                match.groupdict().get('value') and                '/' not in match.groupdict()['value']            ):                 # build a replacement suggestion                 msg = __('hardcoded link %r could be replaced by an extlink '                          '(try using %r instead)')


def visit_footnote(self, node: Element) -> None:         self.in_footnote += 1         label = cast(nodes.label, node[0])        if 'referred' in node:            self.body.append(r'\sphinxstepexplicit ')         if self.in_parsed_literal:             self.body.append(r'\begin{footnote}[%s]' % label.astext())         else:             self.body.append('%' + CR)             self.body.append(r'\begin{footnote}[%s]' % label.astext())         if 'referred' in node:            self.body.append(r'\phantomsection'                             r'\label{\thesphinxscope.%s}%%' % label.astext() + CR)            # TODO: in future maybe output a latex macro with backrefs here            pass         self.body.append(r'\sphinxAtStartFootnote' + CR)      def depart_footnote(self, node: Element) -> None:


def visit_footnotetext(self, node: Element) -> None:         label = cast(nodes.label, node[0])         self.body.append('%' + CR)        self.body.append(r'\begin{footnotetext}[%s]'                         r'\phantomsection\label{\thesphinxscope.%s}%%'                         % (label.astext(), label.astext()) + CR)        self.body.append(r'\begin{footnotetext}[%s]' % label.astext())         self.body.append(r'\sphinxAtStartFootnote' + CR)      def depart_footnotetext(self, node: Element) -> None:


return stringify_signature(sig, show_return_annotation=False, **kwargs) <ins>    def _find_signature(self) -> Tuple[str, str]:        result = super()._find_signature()        if result is not None:            # Strip a return value from signature of constructor in docstring (first entry)            result = (result[0], None)        for i, sig in enumerate(self._signatures):            if sig.endswith(' -> None'):                # Strip a return value from signatures of constructor in docstring (subsequent                # entries)                self._signatures[i] = sig[:-8]        return result</ins>     def format_signature(self, **kwargs: Any) -> str:         if self.doc_as_attr:             return ''


kw_defaults = list(function.args.kw_defaults)             parameters = list(sig.parameters.values())             for i, param in enumerate(parameters):                if param.default is not param.empty:                if param.default is param.empty:                    if param.kind == param.KEYWORD_ONLY:                        # Consume kw_defaults for kwonly args                        kw_defaults.pop(0)                else:                     if param.kind in (param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD):                         default = defaults.pop(0)                         value = get_default_value(lines, default)


self.start_filter,                        self.end_filter,                        self.lines_filter,                       self.dedent_filter,                        self.prepend_filter,                       self.append_filter,                       self.dedent_filter]                       self.append_filter]             lines = self.read_file(self.filename, location=location)             for func in filters:                 lines = func(lines, location=location)


return {x.strip() for x in arg.split(',') if x.strip()}  def inherited_members_option(arg: Any) -> Union[object, Set[str]]:def inherited_members_option(arg: Any) -> Set[str]:     """Used to convert the :members: option to auto directives."""     if arg in (None, True):        return 'object'        return {'object'}    elif arg:        return set(x.strip() for x in arg.split(','))     else:        return arg        return set()   def member_order_option(arg: Any) -> Optional[str]:


``autodoc-skip-member`` event.         """         def is_filtered_inherited_member(name: str, obj: Any) -> bool:            inherited_members = self.options.inherited_members or set()             if inspect.isclass(self.object):                 for cls in self.object.__mro__:                    if cls.__name__ == self.options.inherited_members and cls != self.object:                    if cls.__name__ in inherited_members and cls != self.object:                         # given member is a member of specified *super class*                         return True                     elif name in cls.__dict__:


def __eq__(self, other: Any) -> bool:         return self.name == other <ins>    def __hash__(self) -> int:        return hash(self.name)    def __repr__(self) -> str:        return self.name</ins>  class TypeAliasModule:     """Pseudo module class for autodoc_type_aliases."""


import ast import inspect import sys<ins>from inspect import Parameter</ins> from typing import Any, Dict, List, Optional  from sphinx.application import Sphinx


if value is None:                             value = ast_unparse(default)  # type: ignore                         parameters[i] = param.replace(default=DefaultValue(value))            if bound_method and inspect.ismethod(obj):                # classmethods                cls = inspect.Parameter('cls', Parameter.POSITIONAL_OR_KEYWORD)                parameters.insert(0, cls)             sig = sig.replace(parameters=parameters)            obj.__signature__ = sig            if bound_method and inspect.ismethod(obj):                # classmethods can't be assigned __signature__ attribute.                obj.__dict__['__signature__'] = sig            else:                obj.__signature__ = sig     except (AttributeError, TypeError):         # failed to update signature (ex. built-in or extension types)         pass


# TODO: Use nowrap option once LaTeX formatter supports it         # https://github.com/pygments/pygments/pull/1343         hlcode = hlcode.replace(r'\begin{Verbatim}[commandchars=\\\{\}]',                                r'\sphinxcode{\sphinxupquote{')                                r'\sphinxcode{\sphinxupquote{%')         # get consistent trailer        hlcode = hlcode.rstrip()[:-14]  # strip \end{Verbatim}        hlcode = hlcode.rstrip()[:-15]  # strip \n\end{Verbatim}         self.body.append(hlcode)        self.body.append('}}')        self.body.append('%' + CR + '}}')         raise nodes.SkipNode      def depart_literal(self, node: Element) -> None:


for field_list in field_lists:             if app.config.autodoc_typehints_description_target == "all":                modify_field_list(field_list, annotations[fullname])                if objtype == 'class':                    modify_field_list(field_list, annotations[fullname], suppress_rtype=True)                else:                    modify_field_list(field_list, annotations[fullname])             elif app.config.autodoc_typehints_description_target == "documented_params":                 augment_descriptions_with_types(                     field_list, annotations[fullname], force_rtype=True


return field_list  def modify_field_list(node: nodes.field_list, annotations: Dict[str, str]) -> None:def modify_field_list(node: nodes.field_list, annotations: Dict[str, str],                      suppress_rtype: bool = False) -> None:     arguments: Dict[str, Dict[str, bool]] = {}     fields = cast(Iterable[nodes.field], node)     for field in fields:


node += field      if 'return' in annotations and 'return' not in arguments:<ins>        annotation = annotations['return']        if annotation == 'None' and suppress_rtype:            return</ins>         field = nodes.field()         field += nodes.field_name('', 'rtype')         field += nodes.field_body('', nodes.paragraph('', annotation))


if name == 'return':             continue         arg = arguments.get(name, {})        if '*' + name in arguments:            name = '*' + name            arguments.get(name)        elif '**' + name in arguments:            name = '**' + name            arguments.get(name)        else:            arg = arguments.get(name, {})         if not arg.get('type'):             field = nodes.field()             field += nodes.field_name('', 'type ' + name)


has_type.add('return')      # Add 'type' for parameters with a description but no declared type.    for name in annotations:    for name, annotation in annotations.items():         if name in ('return', 'returns'):             continue        if '*' + name in has_description:            name = '*' + name        elif '**' + name in has_description:            name = '**' + name         if name in has_description and name not in has_type:             field = nodes.field()             field += nodes.field_name('', 'type ' + name)            field += nodes.field_body('', nodes.paragraph('', annotations[name]))            field += nodes.field_body('', nodes.paragraph('', annotation))             node += field      # Add 'rtype' if 'return' is present and 'rtype' isn't.


for node in content:         if isinstance(node, nodes.field_list):             fields = cast(List[nodes.field], node)            for field in fields:            # removing list items while iterating the list needs reversed()            for field in reversed(fields):                 field_name = cast(nodes.field_body, field[0]).astext().strip()                 if field_name == 'meta' or field_name.startswith('meta '):                     node.remove(field)                    break   class PythonModuleIndex(Index):


def __iter__(self) -> Generator[Message, None, None]:         for message in self.messages:            positions = [(source, line) for source, line, uuid in self.metadata[message]]            positions = sorted(set((source, line) for source, line, uuid                                   in self.metadata[message]))             uuids = [uuid for source, line, uuid in self.metadata[message]]             yield Message(message, positions, uuids)


raise ConfigError(__("config directory doesn't contain a conf.py file (%s)") %                               confdir)         namespace = eval_config_file(filename, tags)<ins>        # Note: Old sphinx projects have been configured as "langugae = None" because        #       sphinx-quickstart previously generated this by default.        #       To keep compatibility, they should be fallback to 'en' for a while        #       (This conversion should not be removed before 2025-01-01).        if namespace.get("language", ...) is None:            logger.warning(__("Invalid configuration value found: 'language = None'. "                              "Update your configuration to a valid langauge code. "                              "Falling back to 'en' (English)."))            namespace["language"] = "en"</ins>         return cls(namespace, overrides or {})      def convert_overrides(self, name: str, value: Any) -> Any:


confdir)         namespace = eval_config_file(filename, tags)         # Note: Old sphinx projects have been configured as "langugae = None" because        # Note: Old sphinx projects have been configured as "language = None" because         #       sphinx-quickstart previously generated this by default.         #       To keep compatibility, they should be fallback to 'en' for a while         #       (This conversion should not be removed before 2025-01-01).         if namespace.get("language", ...) is None:             logger.warning(__("Invalid configuration value found: 'language = None'. "                              "Update your configuration to a valid langauge code. "                              "Update your configuration to a valid language code. "                               "Falling back to 'en' (English)."))             namespace["language"] = "en"


def run(self, **kwargs: Any) -> None:         matcher = NodeMatcher(nodes.literal, classes=["kbd"])        for node in self.document.findall(matcher):  # type: nodes.literal        # this list must be pre-created as during iteration new nodes        # are added which match the condition in the NodeMatcher.        for node in list(self.document.findall(matcher)):  # type: nodes.literal             parts = self.pattern.split(node[-1].astext())             if len(parts) == 1 or self.is_multiwords_key(parts):                 continue


return "%s.%s" % (self.visit(node.value), node.attr)      def visit_BinOp(self, node: ast.BinOp) -> str:<ins>        # Special case ``**`` to not have surrounding spaces.        if isinstance(node.op, ast.Pow):            return "".join(map(self.visit, (node.left, node.op, node.right)))</ins>         return " ".join(self.visit(e) for e in [node.left, node.op, node.right])      def visit_BoolOp(self, node: ast.BoolOp) -> str:


return "%s[%s]" % (self.visit(node.value), self.visit(node.slice))      def visit_UnaryOp(self, node: ast.UnaryOp) -> str:        return "%s %s" % (self.visit(node.op), self.visit(node.operand))        # UnaryOp is one of {UAdd, USub, Invert, Not}, which refer to ``+x``,        # ``-x``, ``~x``, and ``not x``. Only Not needs a space.        if isinstance(node.op, ast.Not):            return "%s %s" % (self.visit(node.op), self.visit(node.operand))        return "%s%s" % (self.visit(node.op), self.visit(node.operand))      def visit_Tuple(self, node: ast.Tuple) -> str:         if len(node.elts) == 0:


pending_xrefs = cast(Iterable[addnodes.pending_xref], node)     for child in pending_xrefs:         if child.get('refuri') is not None:            if graphviz_output_format == 'SVG':                urls[child['reftitle']] = "../" + child.get('refuri')            # Construct the name from the URI if the reference is external via intersphinx            if not child.get('internal', True):                refname = child['refuri'].rsplit('#', 1)[-1]             else:                urls[child['reftitle']] = child.get('refuri')                refname = child['reftitle']            urls[refname] = child.get('refuri')         elif child.get('refid') is not None:             if graphviz_output_format == 'SVG':                urls[child['reftitle']] = '../' + current_filename + '#' + child.get('refid')                urls[child['reftitle']] = current_filename + '#' + child.get('refid')             else:                 urls[child['reftitle']] = '#' + child.get('refid')


return ret      def parse_content(self, toctree: addnodes.toctree) -> List[Node]:        generated_docnames = frozenset(self.env.domains['std'].initial_data['labels'].keys())         suffixes = self.config.source_suffix          # glob target documents        all_docnames = self.env.found_docs.copy()        all_docnames = self.env.found_docs.copy() | generated_docnames         all_docnames.remove(self.env.docname)  # remove current document          ret: List[Node] = []


patname = docname_join(self.env.docname, entry)                 docnames = sorted(patfilter(all_docnames, patname))                 for docname in docnames:<ins>                    if docname in generated_docnames:                        # don't include generated documents in globs                        continue</ins>                     all_docnames.remove(docname)  # don't include it again                     toctree['entries'].append((None, docname))                     toctree['includefiles'].append(docname)


docname = docname_join(self.env.docname, docname)                 if url_re.match(ref) or ref == 'self':                     toctree['entries'].append((title, ref))                elif docname not in self.env.found_docs:                elif docname not in self.env.found_docs | generated_docnames:                     if excluded(self.env.doc2path(docname, False)):                         message = __('toctree contains reference to excluded document %r')                         subtype = 'excluded'diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py-- a/sphinx/environment/adapters/toctree.py++ b/sphinx/environment/adapters/toctree.py


"""Toctree adapter for sphinx.environment.""" from typing import TYPE_CHECKING, Any, Iterable, List, Optional, castfrom typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple, cast  from docutils import nodes from docutils.nodes import Element, Node


"""         if toctree.get('hidden', False) and not includehidden:             return None<ins>        generated_docnames: Dict[str, Tuple[str, str, str]] = self.env.domains['std'].initial_data['labels'].copy()  # NoQA: E501</ins>          # For reading the following two helper function, it is useful to keep         # in mind the node structure of a toctree (using HTML-like node names


item = nodes.list_item('', para)                         # don't show subitems                         toc = nodes.bullet_list('', item)                    elif ref in generated_docnames:                        docname, _, sectionname = generated_docnames[ref]                        if not title:                            title = sectionname                        reference = nodes.reference('', title, internal=True,                                                    refuri=docname, anchorname='')                        para = addnodes.compact_paragraph('', '', reference)                        item = nodes.list_item('', para)                        # don't show subitems                        toc = nodes.bullet_list('', item)                     else:                         if ref in parents:                             logger.warning(__('circular toctree references 'diff --git a/sphinx/environment/collectors/toctree.py b/sphinx/environment/collectors/toctree.py-- a/sphinx/environment/collectors/toctree.py++ b/sphinx/environment/collectors/toctree.py


def assign_figure_numbers(self, env: BuildEnvironment) -> List[str]:         """Assign a figure number to each figure under a numbered toctree."""<ins>        generated_docnames = frozenset(env.domains['std'].initial_data['labels'].keys())</ins>          rewrite_needed = []


fignumbers[figure_id] = get_next_fignumber(figtype, secnum)          def _walk_doctree(docname: str, doctree: Element, secnum: Tuple[int, ...]) -> None:<ins>            nonlocal generated_docnames</ins>             for subnode in doctree.children:                 if isinstance(subnode, nodes.section):                     next_secnum = get_section_number(docname, subnode)


if url_re.match(subdocname) or subdocname == 'self':                             # don't mess with those                             continue<ins>                        if subdocname in generated_docnames:                            # or these                            continue</ins>                          _walk_doc(subdocname, secnum)                 elif isinstance(subnode, nodes.Element):


builder = cast(CheckExternalLinksBuilder, self.app.builder)         hyperlinks = builder.hyperlinks         # reference nodes        for refnode in self.document.findall(nodes.reference):            if 'refuri' not in refnode:                continue            uri = refnode['refuri']        def add_uri(uri: str, node: nodes.Element) -> None:             newuri = self.app.emit_firstresult('linkcheck-process-uri', uri)             if newuri:                 uri = newuri             lineno = get_node_line(refnode)            lineno = get_node_line(node)             uri_info = Hyperlink(uri, self.env.docname, lineno)             if uri not in hyperlinks:                 hyperlinks[uri] = uri_info         # reference nodes        for refnode in self.document.findall(nodes.reference):            if 'refuri' not in refnode:                continue            uri = refnode['refuri']            add_uri(uri, refnode)         # image nodes         for imgnode in self.document.findall(nodes.image):             uri = imgnode['candidates'].get('?')             if uri and '://' in uri:                newuri = self.app.emit_firstresult('linkcheck-process-uri', uri)                if newuri:                    uri = newuri                lineno = get_node_line(imgnode)                uri_info = Hyperlink(uri, self.env.docname, lineno)                if uri not in hyperlinks:                    hyperlinks[uri] = uri_info                add_uri(uri, imgnode)        # raw nodes        for rawnode in self.document.findall(nodes.raw):            uri = rawnode.get('source')            if uri and '://' in uri:                add_uri(uri, rawnode)   def rewrite_github_anchor(app: Sphinx, uri: str) -> Optional[str]:


from sphinx import addnodes, package_dir from sphinx.deprecation import RemovedInSphinx70Warning from sphinx.environment import BuildEnvironment<ins>from sphinx.util import split_into</ins>   class SearchLanguage:


# stemmed words in titles -> set(docname)         self._title_mapping: Dict[str, Set[str]] = {}         self._all_titles: Dict[str, List[Tuple[str, str]]] = {}  # docname -> all titles<ins>        self._index_entries: Dict[str, List[Tuple[str, str, str]]] = {}  # docname -> index entry</ins>         self._stem_cache: Dict[str, str] = {}       # word -> stemmed word         self._objtypes: Dict[Tuple[str, str], int] = {}     # objtype -> index         # objtype index -> (domain, type, objname (localized))


for title, titleid in titlelist:                 alltitles.setdefault(title, []).append((fn2index[docname],  titleid))         index_entries: Dict[str, List[Tuple[int, str]]] = {}        for docname, entries in self._index_entries.items():            for entry, entry_id, main_entry in entries:                index_entries.setdefault(entry.lower(), []).append((fn2index[docname],  entry_id))         return dict(docnames=docnames, filenames=filenames, titles=titles, terms=terms,                     objects=objects, objtypes=objtypes, objnames=objnames,                     titleterms=title_terms, envversion=self.env.version,                    alltitles=alltitles)                    alltitles=alltitles, indexentries=index_entries)      def label(self) -> str:         return "%s (code: %s)" % (self.lang.language_name, self.lang.lang)


if _filter(stemmed_word) and not already_indexed:                 self._mapping.setdefault(stemmed_word, set()).add(docname) <ins>        # find explicit entries within index directives        _index_entries: Set[Tuple[str, str, str]] = set()        for node in doctree.findall(addnodes.index):            for entry_type, value, tid, main, *index_key in node['entries']:                tid = tid or ''                try:                    if entry_type == 'single':                        try:                            entry, subentry = split_into(2, 'single', value)                        except ValueError:                            entry, = split_into(1, 'single', value)                            subentry = ''                        _index_entries.add((entry, tid, main))                        if subentry:                            _index_entries.add((subentry, tid, main))                    elif entry_type == 'pair':                        first, second = split_into(2, 'pair', value)                        _index_entries.add((first, tid, main))                        _index_entries.add((second, tid, main))                    elif entry_type == 'triple':                        first, second, third = split_into(3, 'triple', value)                        _index_entries.add((first, tid, main))                        _index_entries.add((second, tid, main))                        _index_entries.add((third, tid, main))                    elif entry_type in {'see', 'seealso'}:                        first, second = split_into(2, 'see', value)                        _index_entries.add((first, tid, main))                except ValueError:                    pass        self._index_entries[docname] = sorted(_index_entries)</ins>     def context_for_searchtool(self) -> Dict[str, Any]:         if self.lang.js_splitter_code:             js_splitter_code = self.lang.js_splitter_code


def _parse_annotation(annotation: str, env: BuildEnvironment | None) -> list[Node]:     """Parse type annotation."""<ins>    short_literals = env.config.python_display_short_literal_types</ins>     def unparse(node: ast.AST) -> list[Node]:         if isinstance(node, ast.Attribute):             return [nodes.Text(f"{unparse(node.value)[0]}.{node.attr}")]


if isinstance(node, ast.Subscript):             if getattr(node.value, 'id', '') in {'Optional', 'Union'}:                 return _unparse_pep_604_annotation(node)<ins>            if short_literals and getattr(node.value, 'id', '') == 'Literal':                return _unparse_pep_604_annotation(node)</ins>             result = unparse(node.value)             result.append(addnodes.desc_sig_punctuation('', '['))             result.extend(unparse(node.slice))


app.add_domain(PythonDomain)     app.add_config_value('python_use_unqualified_type_names', False, 'env')<ins>    app.add_config_value('python_display_short_literal_types', False, 'env')</ins>     app.connect('object-description-transform', filter_meta_fields)     app.connect('missing-reference', builtin_resolver, priority=900)


}      def write_doc(self, docname: str, doctree: nodes.document) -> None:<del>        title_node = self.env.longtitles.get(docname)        title = self.render_partial(title_node)['title'] if title_node else ''        self.index_page(docname, doctree, title)</del>         destination = StringOutput(encoding='utf-8')         doctree.settings = self.docsettings


def write_doc_serialized(self, docname: str, doctree: nodes.document) -> None:         self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir)         self.post_process_images(doctree)<ins>        title_node = self.env.longtitles.get(docname)        title = self.render_partial(title_node)['title'] if title_node else ''        self.index_page(docname, doctree, title)</ins>      def finish(self) -> None:         self.finish_tasks.add_task(self.gen_indices)


def visit_seealso(self, node: Element) -> None:         self.body.append(BLANKLINE)        self.body.append(r'\begin{sphinxseealso}{%s}' % admonitionlabels['seealso'] + CR)        self.body.append(r'\begin{sphinxseealso}{%s:}' % admonitionlabels['seealso'] + CR)      def depart_seealso(self, node: Element) -> None:         self.body.append(BLANKLINE)


# Leaf nodes for markup of text fragments ######################################### #: A set of classes inheriting :class:`desc_sig_element`. Each node class#: is expected to be handled by the builder's translator class if the latter#: does not inherit from SphinxTranslator.#:#: This set can be extended manually by third-party extensions or#: by subclassing :class:`desc_sig_element` and using the class#: keyword argument `_sig_element=True`.SIG_ELEMENTS: set[type[desc_sig_element]] = set() # Signature text elements, generally translated to node.inline # in SigElementFallbackTransform.# When adding a new one, add it to SIG_ELEMENTS.# When adding a new one, add it to SIG_ELEMENTS via the class# keyword argument `_sig_element=True` (e.g., see `desc_sig_space`).  class desc_sig_element(nodes.inline, _desc_classes_injector):     """Common parent class of nodes for inline text of a signature."""


super().__init__(rawsource, text, *children, **attributes)         self['classes'].extend(self.classes)     def __init_subclass__(cls, *, _sig_element=False, **kwargs):        super().__init_subclass__(**kwargs)        if _sig_element:            # add the class to the SIG_ELEMENTS set if asked            SIG_ELEMENTS.add(cls)  # to not reinvent the wheel, the classes in the following desc_sig classes # are based on those used in Pygments class desc_sig_space(desc_sig_element):class desc_sig_space(desc_sig_element, _sig_element=True):     """Node for a space in a signature."""     classes = ["w"]


super().__init__(rawsource, text, *children, **attributes)  class desc_sig_name(desc_sig_element):class desc_sig_name(desc_sig_element, _sig_element=True):     """Node for an identifier in a signature."""     classes = ["n"]  class desc_sig_operator(desc_sig_element):class desc_sig_operator(desc_sig_element, _sig_element=True):     """Node for an operator in a signature."""     classes = ["o"]  class desc_sig_punctuation(desc_sig_element):class desc_sig_punctuation(desc_sig_element, _sig_element=True):     """Node for punctuation in a signature."""     classes = ["p"]  class desc_sig_keyword(desc_sig_element):class desc_sig_keyword(desc_sig_element, _sig_element=True):     """Node for a general keyword in a signature."""     classes = ["k"]  class desc_sig_keyword_type(desc_sig_element):class desc_sig_keyword_type(desc_sig_element, _sig_element=True):     """Node for a keyword which is a built-in type in a signature."""     classes = ["kt"]  class desc_sig_literal_number(desc_sig_element):class desc_sig_literal_number(desc_sig_element, _sig_element=True):     """Node for a numeric literal in a signature."""     classes = ["m"]  class desc_sig_literal_string(desc_sig_element):class desc_sig_literal_string(desc_sig_element, _sig_element=True):     """Node for a string literal in a signature."""     classes = ["s"]  class desc_sig_literal_char(desc_sig_element):class desc_sig_literal_char(desc_sig_element, _sig_element=True):     """Node for a character literal in a signature."""     classes = ["sc"]  SIG_ELEMENTS = [desc_sig_space,                desc_sig_name,                desc_sig_operator,                desc_sig_punctuation,                desc_sig_keyword, desc_sig_keyword_type,                desc_sig_literal_number, desc_sig_literal_string, desc_sig_literal_char] ############################################################### # new admonition-like constructs diff --git a/sphinx/transforms/post_transforms/__init__.py b/sphinx/transforms/post_transforms/__init__.py-- a/sphinx/transforms/post_transforms/__init__.py++ b/sphinx/transforms/post_transforms/__init__.py


# subclass of SphinxTranslator supports desc_sig_element nodes automatically.             return         # for the leaf elements (desc_sig_element), the translator should support _all_        if not all(has_visitor(translator, node) for node in addnodes.SIG_ELEMENTS):        # for the leaf elements (desc_sig_element), the translator should support _all_,        # unless there exists a generic visit_desc_sig_element default visitor        if (not all(has_visitor(translator, node) for node in addnodes.SIG_ELEMENTS)                and not has_visitor(translator, addnodes.desc_sig_element)):             self.fallback(addnodes.desc_sig_element)          if not has_visitor(translator, addnodes.desc_inline):             self.fallback(addnodes.desc_inline)     def fallback(self, nodeType: Any) -> None:        for node in self.document.findall(nodeType):    def fallback(self, node_type: Any) -> None:        """Translate nodes of type *node_type* to docutils inline nodes.        The original node type name is stored as a string in a private        ``_sig_node_type`` attribute if the latter did not exist.        """        for node in self.document.findall(node_type):             newnode = nodes.inline()             newnode.update_all_atts(node)             newnode.extend(node)            # Only set _sig_node_type if not defined by the user            newnode.setdefault('_sig_node_type', node.tagname)             node.replace_self(newnode)


raise AttributeError(name) from exc  def object_description(object: Any) -> str:    """A repr() implementation that returns text safe to use in reST context."""    if isinstance(object, dict):def object_description(obj: Any, *, _seen: frozenset = frozenset()) -> str:    """A repr() implementation that returns text safe to use in reST context.    Maintains a set of 'seen' object IDs to detect and avoid infinite recursion.    """    seen = _seen    if isinstance(obj, dict):        if id(obj) in seen:            return 'dict(...)'        seen |= {id(obj)}         try:            sorted_keys = sorted(object)        except Exception:            pass  # Cannot sort dict keys, fall back to generic repr        else:            items = ("%s: %s" %                     (object_description(key), object_description(object[key]))                     for key in sorted_keys)            return "{%s}" % ", ".join(items)    elif isinstance(object, set):            sorted_keys = sorted(obj)        except TypeError:            # Cannot sort dict keys, fall back to using descriptions as a sort key            sorted_keys = sorted(obj, key=lambda k: object_description(k, _seen=seen))        items = ((object_description(key, _seen=seen),                  object_description(obj[key], _seen=seen)) for key in sorted_keys)        return '{%s}' % ', '.join(f'{key}: {value}' for (key, value) in items)    elif isinstance(obj, set):        if id(obj) in seen:            return 'set(...)'        seen |= {id(obj)}         try:            sorted_values = sorted(object)            sorted_values = sorted(obj)         except TypeError:            pass  # Cannot sort set values, fall back to generic repr        else:            return "{%s}" % ", ".join(object_description(x) for x in sorted_values)    elif isinstance(object, frozenset):            # Cannot sort set values, fall back to using descriptions as a sort key            sorted_values = sorted(obj, key=lambda x: object_description(x, _seen=seen))        return '{%s}' % ', '.join(object_description(x, _seen=seen) for x in sorted_values)    elif isinstance(obj, frozenset):        if id(obj) in seen:            return 'frozenset(...)'        seen |= {id(obj)}         try:            sorted_values = sorted(object)            sorted_values = sorted(obj)         except TypeError:            pass  # Cannot sort frozenset values, fall back to generic repr        else:            return "frozenset({%s})" % ", ".join(object_description(x)                                                 for x in sorted_values)    elif isinstance(object, enum.Enum):        return f"{object.__class__.__name__}.{object.name}"            # Cannot sort frozenset values, fall back to using descriptions as a sort key            sorted_values = sorted(obj, key=lambda x: object_description(x, _seen=seen))        return 'frozenset({%s})' % ', '.join(object_description(x, _seen=seen)                                             for x in sorted_values)    elif isinstance(obj, enum.Enum):        return f'{obj.__class__.__name__}.{obj.name}'    elif isinstance(obj, tuple):        if id(obj) in seen:            return 'tuple(...)'        seen |= frozenset([id(obj)])        return '(%s%s)' % (            ', '.join(object_description(x, _seen=seen) for x in obj),            ',' * (len(obj) == 1),        )    elif isinstance(obj, list):        if id(obj) in seen:            return 'list(...)'        seen |= {id(obj)}        return '[%s]' % ', '.join(object_description(x, _seen=seen) for x in obj)      try:        s = repr(object)        s = repr(obj)     except Exception as exc:         raise ValueError from exc     # Strip non-deterministic memory addresses such as


_single_colon_regex = re.compile(r'(?<!:):(?!:)') _xref_or_code_regex = re.compile(     r'((?::(?:[a-zA-Z0-9]+[\-_+:.])*[a-zA-Z0-9]+:`.+?`)|'    r'(?:``.+?``))')    r'(?:``.+?``)|'    r'(?::meta .+:.*)|'    r'(?:`.+?\s*(?<!\x00)<.*?>`))') _xref_regex = re.compile(     r'(?:(?::(?:[a-zA-Z0-9]+[\-_+:.])*[a-zA-Z0-9]+:)?`.+?`)', )


from docutils.parsers.rst import roles from docutils.parsers.rst.languages import en as englishfrom docutils.parsers.rst.states import Body from docutils.statemachine import StringList from docutils.utils import Reporterfrom jinja2 import Environmentfrom jinja2 import Environment, pass_environment  from sphinx.locale import __ from sphinx.util import docutils, logging try:    from jinja2.utils import pass_environmentexcept ImportError:    from jinja2 import environmentfilter as pass_environment logger = logging.getLogger(__name__) docinfo_re = re.compile(':\\w+:.*?')FIELD_NAME_RE = re.compile(Body.patterns['field_marker']) symbols_re = re.compile(r'([!-\-/:-@\[-`{-~])')  # symbols without dot(0x2e) SECTIONING_CHARS = ['=', '-', '~']


if prolog:         pos = 0         for line in content:            if docinfo_re.match(line):            if FIELD_NAME_RE.match(line):                 pos += 1             else:                 break


pos += 1          # insert prolog (after docinfo if exists)<ins>        lineno = 0</ins>         for lineno, line in enumerate(prolog.splitlines()):             content.insert(pos + lineno, line, '<rst_prolog>', lineno)


self.anchors_ignore: list[re.Pattern[str]] = list(             map(re.compile, config.linkcheck_anchors_ignore))<ins>        self.anchors_ignore_for_url: list[re.Pattern[str]] = list(            map(re.compile, config.linkcheck_anchors_ignore_for_url))</ins>         self.documents_exclude: list[re.Pattern[str]] = list(             map(re.compile, config.linkcheck_exclude_documents))         self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info


def _check_uri(self, uri: str, hyperlink: Hyperlink) -> tuple[str, str, int]:         req_url, delimiter, anchor = uri.partition('#')        for rex in self.anchors_ignore if delimiter and anchor else []:            if rex.match(anchor):                anchor = ''                break        if delimiter and anchor:            for rex in self.anchors_ignore:                if rex.match(anchor):                    anchor = ''                    break            else:                for rex in self.anchors_ignore_for_url:                    if rex.match(req_url):                        anchor = ''                        break          # handle non-ASCII URIs         try:


# Anchors starting with ! are ignored since they are     # commonly used for dynamic pages     app.add_config_value('linkcheck_anchors_ignore', ['^!'], False)<ins>    app.add_config_value('linkcheck_anchors_ignore_for_url', (), False, (tuple, list))</ins>     app.add_config_value('linkcheck_rate_limit_timeout', 300.0, False)      app.add_event('linkcheck-process-uri')


node['raw_entries'] = entries                 node['entries'] = new_entries <del>        # remove translated attribute that is used for avoiding double translation.        matcher = NodeMatcher(translated=Any)        for translated in self.document.findall(matcher):  # type: nodes.Element            translated.delattr('translated')</del>  class RemoveTranslatableInline(SphinxTransform):     """


self.tls_verify = config.tls_verify         self.tls_cacerts = config.tls_cacerts         self._session = requests._Session()         super().__init__(daemon=True)      def run(self) -> None:         while True:             next_check, hyperlink = self.wqueue.get()             if hyperlink is None:                # An empty hyperlink is a signal to shutdown the worker; cleanup resources here                self._session.close()                 break              uri, docname, _docpath, lineno = hyperlink


return status, info, code <ins>    def _retrieval_methods(self,                           check_anchors: bool,                           anchor: str) -> Iterator[tuple[Callable, dict]]:        if not check_anchors or not anchor:            yield self._session.head, {'allow_redirects': True}        yield self._session.get, {'stream': True}</ins>     def _check_uri(self, uri: str, hyperlink: Hyperlink) -> tuple[str, str, int]:         req_url, delimiter, anchor = uri.partition('#')         for rex in self.anchors_ignore if delimiter and anchor else []:


error_message = None         status_code = -1         response_url = retry_after = ''        for retrieval_method, kwargs in _retrieval_methods(self.check_anchors, anchor):        for retrieval_method, kwargs in self._retrieval_methods(self.check_anchors, anchor):             try:                 with retrieval_method(                     url=req_url, auth=auth_info,


return {}  def _retrieval_methods(check_anchors: bool, anchor: str) -> Iterator[tuple[Callable, dict]]:    if not check_anchors or not anchor:        yield requests.head, {'allow_redirects': True}    yield requests.get, {'stream': True} def contains_anchor(response: Response, anchor: str) -> bool:     """Determine if an anchor is contained within an HTTP response.""" diff --git a/sphinx/util/requests.py b/sphinx/util/requests.py-- a/sphinx/util/requests.py++ b/sphinx/util/requests.py


from __future__ import annotations  import warningsfrom contextlib import contextmanagerfrom typing import Any, Iteratorfrom typing import Any from urllib.parse import urlsplit  import requests


f'Sphinx/{sphinx.__version__}')  <del>@contextmanagerdef ignore_insecure_warning(verify: bool) -> Iterator[None]:    with warnings.catch_warnings():        if not verify:            # ignore InsecureRequestWarning if verify=False            warnings.filterwarnings("ignore", category=InsecureRequestWarning)        yield</del> def _get_tls_cacert(url: str, certs: str | dict[str, str] | None) -> str | bool:     """Get additional CA cert for a specific URL."""     if not certs:


return certs.get(hostname, True)  def get(url: str,        _user_agent: str = '',        _tls_info: tuple[bool, str | dict[str, str] | None] = (),  # type: ignore[assignment]        **kwargs: Any) -> requests.Response:    """Sends a HEAD request like requests.head().def get(url: str, **kwargs: Any) -> requests.Response:    """Sends a GET request like requests.get().      This sets up User-Agent header and TLS verification automatically."""    headers = kwargs.setdefault('headers', {})    headers.setdefault('User-Agent', _user_agent or _USER_AGENT)    if _tls_info:        tls_verify, tls_cacerts = _tls_info        verify = bool(kwargs.get('verify', tls_verify))        kwargs.setdefault('verify', verify and _get_tls_cacert(url, tls_cacerts))    else:        verify = kwargs.get('verify', True)    with _Session() as session:        return session.get(url, **kwargs)     with ignore_insecure_warning(verify):        return requests.get(url, **kwargs) def head(url: str,         _user_agent: str = '',         _tls_info: tuple[bool, str | dict[str, str] | None] = (),  # type: ignore[assignment]         **kwargs: Any) -> requests.Response:def head(url: str, **kwargs: Any) -> requests.Response:     """Sends a HEAD request like requests.head().      This sets up User-Agent header and TLS verification automatically."""    headers = kwargs.setdefault('headers', {})    headers.setdefault('User-Agent', _user_agent or _USER_AGENT)    if _tls_info:        tls_verify, tls_cacerts = _tls_info        verify = bool(kwargs.get('verify', tls_verify))        kwargs.setdefault('verify', verify and _get_tls_cacert(url, tls_cacerts))    else:        verify = kwargs.get('verify', True)    with _Session() as session:        return session.head(url, **kwargs)     with ignore_insecure_warning(verify):        return requests.head(url, **kwargs)class _Session(requests.Session):    def request(  # type: ignore[override]        self, method: str, url: str,        _user_agent: str = '',        _tls_info: tuple[bool, str | dict[str, str] | None] = (),  # type: ignore[assignment]        **kwargs: Any,    ) -> requests.Response:        """Sends a request with an HTTP verb and url.        This sets up User-Agent header and TLS verification automatically."""        headers = kwargs.setdefault('headers', {})        headers.setdefault('User-Agent', _user_agent or _USER_AGENT)        if _tls_info:            tls_verify, tls_cacerts = _tls_info            verify = bool(kwargs.get('verify', tls_verify))            kwargs.setdefault('verify', verify and _get_tls_cacert(url, tls_cacerts))        else:            verify = kwargs.get('verify', True)        if verify:            return super().request(method, url, **kwargs)        with warnings.catch_warnings():            # ignore InsecureRequestWarning if verify=False            warnings.filterwarnings("ignore", category=InsecureRequestWarning)            return super().request(method, url, **kwargs)


from docutils.parsers.rst.directives.admonitions import BaseAdmonition from docutils.parsers.rst.directives.misc import Class from docutils.parsers.rst.directives.misc import Include as BaseInclude<ins>from docutils.statemachine import StateMachine</ins>  from sphinx import addnodes from sphinx.domains.changeset import VersionChange  # noqa: F401  # for compatibility


from sphinx.util.docutils import SphinxDirective from sphinx.util.matching import Matcher, patfilter from sphinx.util.nodes import explicit_title_re<ins>from sphinx.util.osutil import os_path</ins>  if TYPE_CHECKING:     from docutils.nodes import Element, Node