Skip to content

API: no_default #30788

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion doc/source/reference/extensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ behaves correctly.
api.indexers.check_bool_array_indexer


The sentinel ``pandas.api.extensions._no_default`` is used as the default
The sentinel ``pandas.api.extensions.no_default`` is used as the default
value in some methods. Use an ``is`` comparison to check if the user
provides a non-default value.
8 changes: 4 additions & 4 deletions pandas/_libs/lib.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2232,14 +2232,14 @@ def maybe_convert_objects(ndarray[object] objects, bint try_float=0,
return objects


# Note: _no_default is exported to the public API in pandas.api.extensions
_no_default = object() #: Sentinel indicating the default value.
# Note: no_default is exported to the public API in pandas.api.extensions
no_default = object() #: Sentinel indicating the default value.


@cython.boundscheck(False)
@cython.wraparound(False)
def map_infer_mask(ndarray arr, object f, const uint8_t[:] mask, bint convert=1,
object na_value=_no_default, object dtype=object):
object na_value=no_default, object dtype=object):
"""
Substitute for np.vectorize with pandas-friendly dtype inference.

Expand Down Expand Up @@ -2270,7 +2270,7 @@ def map_infer_mask(ndarray arr, object f, const uint8_t[:] mask, bint convert=1,
result = np.empty(n, dtype=dtype)
for i in range(n):
if mask[i]:
if na_value is _no_default:
if na_value is no_default:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having a cdef version (kind of like we have for NaT) would help perf here (not necessary for this PR)

val = arr[i]
else:
val = na_value
Expand Down
2 changes: 1 addition & 1 deletion pandas/api/extensions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Public API for extending pandas objects."""
from pandas._libs.lib import _no_default # noqa: F401
from pandas._libs.lib import no_default # noqa: F401
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we want this available to library authors, but we never want users to use this, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be fine for users. I can imagine people working with the signature of functions that use no_default.


from pandas.core.dtypes.dtypes import ( # noqa: F401
ExtensionDtype,
Expand Down
6 changes: 3 additions & 3 deletions pandas/core/arrays/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ def __iter__(self):
for i in range(len(self)):
yield self[i]

def to_numpy(self, dtype=None, copy=False, na_value=lib._no_default):
def to_numpy(self, dtype=None, copy=False, na_value=lib.no_default):
"""
Convert to a NumPy ndarray.

Expand All @@ -378,9 +378,9 @@ def to_numpy(self, dtype=None, copy=False, na_value=lib._no_default):
numpy.ndarray
"""
result = np.asarray(self, dtype=dtype)
if copy or na_value is not lib._no_default:
if copy or na_value is not lib.no_default:
result = result.copy()
if na_value is not lib._no_default:
if na_value is not lib.no_default:
result[self.isna()] = na_value
return result

Expand Down
4 changes: 2 additions & 2 deletions pandas/core/arrays/boolean.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def __getitem__(self, item):
return type(self)(self._data[item], self._mask[item])

def to_numpy(
self, dtype=None, copy=False, na_value: "Scalar" = lib._no_default,
self, dtype=None, copy=False, na_value: "Scalar" = lib.no_default,
):
"""
Convert to a NumPy Array.
Expand Down Expand Up @@ -377,7 +377,7 @@ def to_numpy(
>>> a.to_numpy(dtype="bool", na_value=False)
array([ True, False, False])
"""
if na_value is lib._no_default:
if na_value is lib.no_default:
na_value = libmissing.NA
if dtype is None:
dtype = object
Expand Down
6 changes: 3 additions & 3 deletions pandas/core/arrays/integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,16 +376,16 @@ def __getitem__(self, item):

return type(self)(self._data[item], self._mask[item])

def _coerce_to_ndarray(self, dtype=None, na_value=lib._no_default):
def _coerce_to_ndarray(self, dtype=None, na_value=lib.no_default):
"""
coerce to an ndarary of object dtype
"""
if dtype is None:
dtype = object

if na_value is lib._no_default and is_float_dtype(dtype):
if na_value is lib.no_default and is_float_dtype(dtype):
na_value = np.nan
elif na_value is lib._no_default:
elif na_value is lib.no_default:
na_value = libmissing.NA

if is_integer_dtype(dtype):
Expand Down
6 changes: 3 additions & 3 deletions pandas/core/arrays/numpy_.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,13 +421,13 @@ def skew(self, axis=None, dtype=None, out=None, keepdims=False, skipna=True):

# ------------------------------------------------------------------------
# Additional Methods
def to_numpy(self, dtype=None, copy=False, na_value=lib._no_default):
def to_numpy(self, dtype=None, copy=False, na_value=lib.no_default):
result = np.asarray(self._ndarray, dtype=dtype)

if (copy or na_value is not lib._no_default) and result is self._ndarray:
if (copy or na_value is not lib.no_default) and result is self._ndarray:
result = result.copy()

if na_value is not lib._no_default:
if na_value is not lib.no_default:
result[self.isna()] = na_value

return result
Expand Down
6 changes: 3 additions & 3 deletions pandas/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ def array(self) -> ExtensionArray:

return result

def to_numpy(self, dtype=None, copy=False, na_value=lib._no_default, **kwargs):
def to_numpy(self, dtype=None, copy=False, na_value=lib.no_default, **kwargs):
"""
A NumPy ndarray representing the values in this Series or Index.

Expand Down Expand Up @@ -874,9 +874,9 @@ def to_numpy(self, dtype=None, copy=False, na_value=lib._no_default, **kwargs):

result = np.asarray(self._values, dtype=dtype)
# TODO(GH-24345): Avoid potential double copy
if copy or na_value is not lib._no_default:
if copy or na_value is not lib.no_default:
result = result.copy()
if na_value is not lib._no_default:
if na_value is not lib.no_default:
result[self.isna()] = na_value
return result

Expand Down
6 changes: 3 additions & 3 deletions pandas/core/computation/eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Optional
import warnings

from pandas._libs.lib import _no_default
from pandas._libs.lib import no_default
from pandas.util._validators import validate_bool_kwarg

from pandas.core.computation.engines import _engines
Expand Down Expand Up @@ -171,7 +171,7 @@ def eval(
expr,
parser="pandas",
engine: Optional[str] = None,
truediv=_no_default,
truediv=no_default,
local_dict=None,
global_dict=None,
resolvers=(),
Expand Down Expand Up @@ -288,7 +288,7 @@ def eval(

inplace = validate_bool_kwarg(inplace, "inplace")

if truediv is not _no_default:
if truediv is not no_default:
warnings.warn(
"The `truediv` parameter in pd.eval is deprecated and will be "
"removed in a future version.",
Expand Down
12 changes: 4 additions & 8 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,6 @@
Name or list of names to sort by""",
)

# sentinel value to use as kwarg in place of None when None has special meaning
# and needs to be distinguished from a user explicitly passing None.
sentinel = object()


def _single_replace(self, to_replace, method, inplace, limit):
"""
Expand Down Expand Up @@ -1086,7 +1082,7 @@ def rename(self, *args, **kwargs):
return result.__finalize__(self)

@rewrite_axis_style_signature("mapper", [("copy", True), ("inplace", False)])
def rename_axis(self, mapper=sentinel, **kwargs):
def rename_axis(self, mapper=lib.no_default, **kwargs):
"""
Set the name of the axis for the index or columns.

Expand Down Expand Up @@ -1211,7 +1207,7 @@ class name
monkey 2 2
"""
axes, kwargs = self._construct_axes_from_arguments(
(), kwargs, sentinel=sentinel
(), kwargs, sentinel=lib.no_default
)
copy = kwargs.pop("copy", True)
inplace = kwargs.pop("inplace", False)
Expand All @@ -1227,7 +1223,7 @@ class name

inplace = validate_bool_kwarg(inplace, "inplace")

if mapper is not sentinel:
if mapper is not lib.no_default:
# Use v0.23 behavior if a scalar or list
non_mapper = is_scalar(mapper) or (
is_list_like(mapper) and not is_dict_like(mapper)
Expand All @@ -1243,7 +1239,7 @@ class name

for axis in range(self._AXIS_LEN):
v = axes.get(self._AXIS_NAMES[axis])
if v is sentinel:
if v is lib.no_default:
continue
non_mapper = is_scalar(v) or (is_list_like(v) and not is_dict_like(v))
if non_mapper:
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/indexes/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ def _get_time_micros(self):
values = self._data._local_timestamps()
return fields.get_time_micros(values)

def to_series(self, keep_tz=lib._no_default, index=None, name=None):
def to_series(self, keep_tz=lib.no_default, index=None, name=None):
"""
Create a Series with both index and values equal to the index keys
useful with map for returning an indexer based on an index.
Expand Down Expand Up @@ -466,7 +466,7 @@ def to_series(self, keep_tz=lib._no_default, index=None, name=None):
if name is None:
name = self.name

if keep_tz is not lib._no_default:
if keep_tz is not lib.no_default:
if keep_tz:
warnings.warn(
"The 'keep_tz' keyword in DatetimeIndex.to_series "
Expand Down
10 changes: 4 additions & 6 deletions pandas/core/indexes/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@
dict(klass="MultiIndex", target_klass="MultiIndex or list of tuples")
)

_no_default_names = object()


class MultiIndexUIntEngine(libindex.BaseMultiIndexCodesEngine, libindex.UInt64Engine):
"""
Expand Down Expand Up @@ -373,7 +371,7 @@ def _verify_integrity(
return new_codes

@classmethod
def from_arrays(cls, arrays, sortorder=None, names=_no_default_names):
def from_arrays(cls, arrays, sortorder=None, names=lib.no_default):
"""
Convert arrays to MultiIndex.

Expand Down Expand Up @@ -427,7 +425,7 @@ def from_arrays(cls, arrays, sortorder=None, names=_no_default_names):
raise ValueError("all arrays must be same length")

codes, levels = factorize_from_iterables(arrays)
if names is _no_default_names:
if names is lib.no_default:
names = [getattr(arr, "name", None) for arr in arrays]

return MultiIndex(
Expand Down Expand Up @@ -497,7 +495,7 @@ def from_tuples(cls, tuples, sortorder=None, names=None):
return MultiIndex.from_arrays(arrays, sortorder=sortorder, names=names)

@classmethod
def from_product(cls, iterables, sortorder=None, names=_no_default_names):
def from_product(cls, iterables, sortorder=None, names=lib.no_default):
"""
Make a MultiIndex from the cartesian product of multiple iterables.

Expand Down Expand Up @@ -548,7 +546,7 @@ def from_product(cls, iterables, sortorder=None, names=_no_default_names):
iterables = list(iterables)

codes, levels = factorize_from_iterables(iterables)
if names is _no_default_names:
if names is lib.no_default:
names = [getattr(it, "name", None) for it in iterables]

codes = cartesian_product(codes)
Expand Down
6 changes: 4 additions & 2 deletions pandas/io/formats/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

from pandas._config import get_option

from pandas._libs import lib

from pandas.core.dtypes.generic import ABCMultiIndex

from pandas import option_context
Expand Down Expand Up @@ -245,7 +247,7 @@ def _write_col_header(self, indent: int) -> None:

if self.fmt.sparsify:
# GH3547
sentinel = object()
sentinel = lib.no_default
else:
sentinel = False
levels = self.columns.format(sparsify=sentinel, adjoin=False, names=False)
Expand Down Expand Up @@ -451,7 +453,7 @@ def _write_hierarchical_rows(

if self.fmt.sparsify:
# GH3547
sentinel = object()
sentinel = lib.no_default
levels = frame.index.format(sparsify=sentinel, adjoin=False, names=False)

level_lengths = get_level_lengths(levels, sentinel)
Expand Down
8 changes: 4 additions & 4 deletions pandas/io/formats/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from pandas._config import get_option

from pandas._libs import lib
from pandas.compat._optional import import_optional_dependency
from pandas.util._decorators import Appender

Expand Down Expand Up @@ -1475,8 +1476,7 @@ def _get_level_lengths(index, hidden_elements=None):

Result is a dictionary of (level, initial_position): span
"""
sentinel = object()
levels = index.format(sparsify=sentinel, adjoin=False, names=False)
levels = index.format(sparsify=lib.no_default, adjoin=False, names=False)

if hidden_elements is None:
hidden_elements = []
Expand All @@ -1492,10 +1492,10 @@ def _get_level_lengths(index, hidden_elements=None):
for j, row in enumerate(lvl):
if not get_option("display.multi_sparse"):
lengths[(i, j)] = 1
elif (row != sentinel) and (j not in hidden_elements):
elif (row is not lib.no_default) and (j not in hidden_elements):
last_label = j
lengths[(i, last_label)] = 1
elif row != sentinel:
elif row is not lib.no_default:
# even if its hidden, keep track of it in case
# length >1 and later elements are visible
last_label = j
Expand Down
6 changes: 2 additions & 4 deletions pandas/tests/extension/decimal/array.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@

import numpy as np

from pandas._libs import lib

from pandas.core.dtypes.base import ExtensionDtype

import pandas as pd
from pandas.api.extensions import register_extension_dtype
from pandas.api.extensions import no_default, register_extension_dtype
from pandas.core.arrays import ExtensionArray, ExtensionScalarOpsMixin


Expand Down Expand Up @@ -86,7 +84,7 @@ def _from_factorized(cls, values, original):

_HANDLED_TYPES = (decimal.Decimal, numbers.Number, np.ndarray)

def to_numpy(self, dtype=None, copy=False, na_value=lib._no_default, decimals=None):
def to_numpy(self, dtype=None, copy=False, na_value=no_default, decimals=None):
result = np.asarray(self, dtype=dtype)
if decimals is not None:
result = np.asarray([round(x, decimals) for x in result])
Expand Down