Repository: pandas-dev/pandas-stubs (language: python)

Issue:
Removed na_sentinel argument from factorize(), Index.factorize(), and ExtensionArray.factorize()
Related to migration to 2.0


Discussion / hints:

Fix patch:
diff --git a/pandas-stubs/core/algorithms.pyi b/pandas-stubs/core/algorithms.pyi
index 83d99b7c..49f922a1 100644
--- a/pandas-stubs/core/algorithms.pyi
+++ b/pandas-stubs/core/algorithms.pyi
@@ -52,8 +52,6 @@ def factorize(
 def factorize(
     values: Index | Series,
     sort: bool = ...,
-    # Not actually positional-only, used to handle deprecations in 1.5.0
-    *,
     use_na_sentinel: bool = ...,
     size_hint: int | None = ...,
 ) -> tuple[np.ndarray, Index]: ...
@@ -61,8 +59,6 @@ def factorize(
 def factorize(
     values: Categorical,
     sort: bool = ...,
-    # Not actually positional-only, used to handle deprecations in 1.5.0
-    *,
     use_na_sentinel: bool = ...,
     size_hint: int | None = ...,
 ) -> tuple[np.ndarray, Categorical]: ...
diff --git a/pandas-stubs/core/arrays/base.pyi b/pandas-stubs/core/arrays/base.pyi
index 9a632700..d60fba4d 100644
--- a/pandas-stubs/core/arrays/base.pyi
+++ b/pandas-stubs/core/arrays/base.pyi
@@ -42,8 +42,7 @@ class ExtensionArray:
     def shift(self, periods: int = ..., fill_value: object = ...) -> Self: ...
     def unique(self): ...
     def searchsorted(self, value, side: str = ..., sorter=...): ...
-    # TODO: remove keyword-only when pandas removed na_sentinel
-    def factorize(self, *, use_na_sentinel: bool = ...) -> tuple[np.ndarray, Self]: ...
+    def factorize(self, use_na_sentinel: bool = ...) -> tuple[np.ndarray, Self]: ...
     def repeat(self, repeats, axis=...): ...
     def take(
         self,
diff --git a/pandas-stubs/core/base.pyi b/pandas-stubs/core/base.pyi
index 744228c7..1cd75252 100644
--- a/pandas-stubs/core/base.pyi
+++ b/pandas-stubs/core/base.pyi
@@ -106,7 +106,7 @@ class IndexOpsMixin(OpsMixin, Generic[S1]):
     @property
     def is_monotonic_increasing(self) -> bool: ...
     def factorize(
-        self, sort: bool = ...
+        self, sort: bool = ..., use_na_sentinel: bool = ...
     ) -> tuple[np.ndarray, np.ndarray | Index | Categorical]: ...
     def searchsorted(
         self, value, side: Literal["left", "right"] = ..., sorter=...


Test patch:
diff --git a/tests/test_indexes.py b/tests/test_indexes.py
index 75c9fc11..aab49c40 100644
--- a/tests/test_indexes.py
+++ b/tests/test_indexes.py
@@ -6,6 +6,8 @@
 import numpy as np
 from numpy import typing as npt
 import pandas as pd
+from pandas.core.arrays.categorical import Categorical
+from pandas.core.indexes.base import Index
 from typing_extensions import (
     Never,
     assert_type,
@@ -1160,3 +1162,16 @@ def test_value_counts() -> None:
         pd.Series,
         float,
     )
+
+
+def test_index_factorize() -> None:
+    """Test Index.factorize method."""
+    codes, idx_uniques = pd.Index(["b", "b", "a", "c", "b"]).factorize()
+    check(assert_type(codes, np.ndarray), np.ndarray)
+    check(assert_type(idx_uniques, np.ndarray | Index | Categorical), pd.Index)
+
+    codes, idx_uniques = pd.Index(["b", "b", "a", "c", "b"]).factorize(
+        use_na_sentinel=False
+    )
+    check(assert_type(codes, np.ndarray), np.ndarray)
+    check(assert_type(idx_uniques, np.ndarray | Index | Categorical), pd.Index)