Skip to content

Commit d2fc51a

Browse files
authored
docs: add columns for "requires ordering/index" to supported APIs summary (#892)
1 parent d9b8ef5 commit d2fc51a

File tree

5 files changed

+69
-55
lines changed

5 files changed

+69
-55
lines changed

bigframes/core/validations.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,16 @@
1717
from __future__ import annotations
1818

1919
import functools
20-
from typing import Optional, Protocol, TYPE_CHECKING
20+
from typing import Optional, Protocol, TYPE_CHECKING, Union
2121

2222
import bigframes.constants
2323
import bigframes.exceptions
2424

2525
if TYPE_CHECKING:
2626
from bigframes import Session
2727
from bigframes.core.blocks import Block
28+
from bigframes.dataframe import DataFrame
29+
from bigframes.operations.base import SeriesMethods
2830

2931

3032
class HasSession(Protocol):
@@ -37,13 +39,24 @@ def _block(self) -> Block:
3739
...
3840

3941

42+
def requires_index(meth):
43+
@functools.wraps(meth)
44+
def guarded_meth(df: Union[DataFrame, SeriesMethods], *args, **kwargs):
45+
df._throw_if_null_index(meth.__name__)
46+
return meth(df, *args, **kwargs)
47+
48+
guarded_meth._validations_requires_index = True # type: ignore
49+
return guarded_meth
50+
51+
4052
def requires_ordering(suggestion: Optional[str] = None):
4153
def decorator(meth):
4254
@functools.wraps(meth)
4355
def guarded_meth(object: HasSession, *args, **kwargs):
4456
enforce_ordered(object, meth.__name__, suggestion)
4557
return meth(object, *args, **kwargs)
4658

59+
guarded_meth._validations_requires_ordering = True # type: ignore
4760
return guarded_meth
4861

4962
return decorator

bigframes/dataframe.py

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from __future__ import annotations
1818

1919
import datetime
20-
import functools
2120
import inspect
2221
import re
2322
import sys
@@ -92,15 +91,6 @@
9291
)
9392

9493

95-
def requires_index(meth):
96-
@functools.wraps(meth)
97-
def guarded_meth(df: DataFrame, *args, **kwargs):
98-
df._throw_if_null_index(meth.__name__)
99-
return meth(df, *args, **kwargs)
100-
101-
return guarded_meth
102-
103-
10494
# Inherits from pandas DataFrame so that we can use the same docstrings.
10595
@log_adapter.class_logger
10696
class DataFrame(vendored_pandas_frame.DataFrame):
@@ -261,7 +251,7 @@ def _sql_names(
261251
return results
262252

263253
@property
264-
@requires_index
254+
@validations.requires_index
265255
def index(
266256
self,
267257
) -> indexes.Index:
@@ -277,7 +267,7 @@ def index(self, value):
277267
self.index.name = value.name if hasattr(value, "name") else None
278268

279269
@property
280-
@requires_index
270+
@validations.requires_index
281271
def loc(self) -> indexers.LocDataFrameIndexer:
282272
return indexers.LocDataFrameIndexer(self)
283273

@@ -292,7 +282,7 @@ def iat(self) -> indexers.IatDataFrameIndexer:
292282
return indexers.IatDataFrameIndexer(self)
293283

294284
@property
295-
@requires_index
285+
@validations.requires_index
296286
def at(self) -> indexers.AtDataFrameIndexer:
297287
return indexers.AtDataFrameIndexer(self)
298288

@@ -348,7 +338,7 @@ def _has_index(self) -> bool:
348338
def T(self) -> DataFrame:
349339
return DataFrame(self._get_block().transpose())
350340

351-
@requires_index
341+
@validations.requires_index
352342
@validations.requires_ordering()
353343
def transpose(self) -> DataFrame:
354344
return self.T
@@ -417,7 +407,7 @@ def memory_usage(self, index: bool = True):
417407
column_sizes = pandas.concat([index_size, column_sizes])
418408
return column_sizes
419409

420-
@requires_index
410+
@validations.requires_index
421411
def info(
422412
self,
423413
verbose: Optional[bool] = None,
@@ -1682,7 +1672,7 @@ def set_index(
16821672
col_ids_strs: List[str] = [col_id for col_id in col_ids if col_id is not None]
16831673
return DataFrame(self._block.set_index(col_ids_strs, append=append, drop=drop))
16841674

1685-
@requires_index
1675+
@validations.requires_index
16861676
def sort_index(
16871677
self, ascending: bool = True, na_position: Literal["first", "last"] = "last"
16881678
) -> DataFrame:
@@ -1884,7 +1874,7 @@ def reindex(
18841874
if columns is not None:
18851875
return self._reindex_columns(columns)
18861876

1887-
@requires_index
1877+
@validations.requires_index
18881878
def _reindex_rows(
18891879
self,
18901880
index,
@@ -1931,12 +1921,12 @@ def _reindex_columns(self, columns):
19311921
result_df.columns = new_column_index
19321922
return result_df
19331923

1934-
@requires_index
1924+
@validations.requires_index
19351925
def reindex_like(self, other: DataFrame, *, validate: typing.Optional[bool] = None):
19361926
return self.reindex(index=other.index, columns=other.columns, validate=validate)
19371927

19381928
@validations.requires_ordering()
1939-
@requires_index
1929+
@validations.requires_index
19401930
def interpolate(self, method: str = "linear") -> DataFrame:
19411931
if method == "pad":
19421932
return self.ffill()
@@ -2231,12 +2221,12 @@ def agg(
22312221
aggregate = agg
22322222
aggregate.__doc__ = inspect.getdoc(vendored_pandas_frame.DataFrame.agg)
22332223

2234-
@requires_index
2224+
@validations.requires_index
22352225
@validations.requires_ordering()
22362226
def idxmin(self) -> bigframes.series.Series:
22372227
return bigframes.series.Series(block_ops.idxmin(self._block))
22382228

2239-
@requires_index
2229+
@validations.requires_index
22402230
@validations.requires_ordering()
22412231
def idxmax(self) -> bigframes.series.Series:
22422232
return bigframes.series.Series(block_ops.idxmax(self._block))
@@ -2345,7 +2335,7 @@ def _pivot(
23452335
)
23462336
return DataFrame(pivot_block)
23472337

2348-
@requires_index
2338+
@validations.requires_index
23492339
@validations.requires_ordering()
23502340
def pivot(
23512341
self,
@@ -2360,7 +2350,7 @@ def pivot(
23602350
) -> DataFrame:
23612351
return self._pivot(columns=columns, index=index, values=values)
23622352

2363-
@requires_index
2353+
@validations.requires_index
23642354
@validations.requires_ordering()
23652355
def pivot_table(
23662356
self,
@@ -2460,7 +2450,7 @@ def _stack_multi(self, level: LevelsType = -1):
24602450
block = block.stack(levels=len(level))
24612451
return DataFrame(block)
24622452

2463-
@requires_index
2453+
@validations.requires_index
24642454
@validations.requires_ordering()
24652455
def unstack(self, level: LevelsType = -1):
24662456
if not utils.is_list_like(level):
@@ -2711,7 +2701,7 @@ def groupby(
27112701
else:
27122702
raise TypeError("You have to supply one of 'by' and 'level'")
27132703

2714-
@requires_index
2704+
@validations.requires_index
27152705
def _groupby_level(
27162706
self,
27172707
level: LevelsType,

bigframes/operations/base.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
from __future__ import annotations
1616

17-
import functools
1817
import typing
1918
from typing import List, Sequence
2019

@@ -35,15 +34,6 @@
3534
import bigframes.session
3635

3736

38-
def requires_index(meth):
39-
@functools.wraps(meth)
40-
def guarded_meth(df: SeriesMethods, *args, **kwargs):
41-
df._throw_if_null_index(meth.__name__)
42-
return meth(df, *args, **kwargs)
43-
44-
return guarded_meth
45-
46-
4737
class SeriesMethods:
4838
def __init__(
4939
self,

bigframes/series.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import bigframes.operations as ops
5353
import bigframes.operations.aggregations as agg_ops
5454
import bigframes.operations.base
55-
from bigframes.operations.base import requires_index
5655
import bigframes.operations.datetimes as dt
5756
import bigframes.operations.plotting as plotting
5857
import bigframes.operations.strings as strings
@@ -88,7 +87,7 @@ def dtypes(self):
8887
return self._dtype
8988

9089
@property
91-
@requires_index
90+
@validations.requires_index
9291
def loc(self) -> bigframes.core.indexers.LocSeriesIndexer:
9392
return bigframes.core.indexers.LocSeriesIndexer(self)
9493

@@ -103,7 +102,7 @@ def iat(self) -> bigframes.core.indexers.IatSeriesIndexer:
103102
return bigframes.core.indexers.IatSeriesIndexer(self)
104103

105104
@property
106-
@requires_index
105+
@validations.requires_index
107106
def at(self) -> bigframes.core.indexers.AtSeriesIndexer:
108107
return bigframes.core.indexers.AtSeriesIndexer(self)
109108

@@ -142,7 +141,7 @@ def values(self) -> numpy.ndarray:
142141
return self.to_numpy()
143142

144143
@property
145-
@requires_index
144+
@validations.requires_index
146145
def index(self) -> indexes.Index:
147146
return indexes.Index.from_frame(self)
148147

@@ -245,7 +244,7 @@ def rename(
245244

246245
raise ValueError(f"Unsupported type of parameter index: {type(index)}")
247246

248-
@requires_index
247+
@validations.requires_index
249248
def rename_axis(
250249
self,
251250
mapper: typing.Union[blocks.Label, typing.Sequence[blocks.Label]],
@@ -404,12 +403,12 @@ def drop(
404403
block = block.drop_columns([condition_id])
405404
return Series(block.select_column(self._value_column))
406405

407-
@requires_index
406+
@validations.requires_index
408407
def droplevel(self, level: LevelsType, axis: int | str = 0):
409408
resolved_level_ids = self._resolve_levels(level)
410409
return Series(self._block.drop_levels(resolved_level_ids))
411410

412-
@requires_index
411+
@validations.requires_index
413412
def swaplevel(self, i: int = -2, j: int = -1):
414413
level_i = self._block.index_columns[i]
415414
level_j = self._block.index_columns[j]
@@ -419,7 +418,7 @@ def swaplevel(self, i: int = -2, j: int = -1):
419418
]
420419
return Series(self._block.reorder_levels(reordering))
421420

422-
@requires_index
421+
@validations.requires_index
423422
def reorder_levels(self, order: LevelsType, axis: int | str = 0):
424423
resolved_level_ids = self._resolve_levels(order)
425424
return Series(self._block.reorder_levels(resolved_level_ids))
@@ -609,7 +608,7 @@ def _mapping_replace(self, mapping: dict[typing.Hashable, typing.Hashable]):
609608
return Series(block.select_column(result))
610609

611610
@validations.requires_ordering()
612-
@requires_index
611+
@validations.requires_index
613612
def interpolate(self, method: str = "linear") -> Series:
614613
if method == "pad":
615614
return self.ffill()
@@ -1162,7 +1161,7 @@ def argmin(self) -> int:
11621161
scalars.Scalar, Series(block.select_column(row_nums)).iloc[0]
11631162
)
11641163

1165-
@requires_index
1164+
@validations.requires_index
11661165
def unstack(self, level: LevelsType = -1):
11671166
if isinstance(level, int) or isinstance(level, str):
11681167
level = [level]
@@ -1186,7 +1185,7 @@ def unstack(self, level: LevelsType = -1):
11861185
)
11871186
return bigframes.dataframe.DataFrame(pivot_block)
11881187

1189-
@requires_index
1188+
@validations.requires_index
11901189
def idxmax(self) -> blocks.Label:
11911190
block = self._block.order_by(
11921191
[
@@ -1200,7 +1199,7 @@ def idxmax(self) -> blocks.Label:
12001199
block = block.slice(0, 1)
12011200
return indexes.Index(block).to_pandas()[0]
12021201

1203-
@requires_index
1202+
@validations.requires_index
12041203
def idxmin(self) -> blocks.Label:
12051204
block = self._block.order_by(
12061205
[
@@ -1314,7 +1313,7 @@ def sort_values(
13141313
)
13151314
return Series(block)
13161315

1317-
@requires_index
1316+
@validations.requires_index
13181317
def sort_index(self, *, axis=0, ascending=True, na_position="last") -> Series:
13191318
# TODO(tbergeron): Support level parameter once multi-index introduced.
13201319
if na_position not in ["first", "last"]:
@@ -1377,7 +1376,7 @@ def groupby(
13771376
else:
13781377
raise TypeError("You have to supply one of 'by' and 'level'")
13791378

1380-
@requires_index
1379+
@validations.requires_index
13811380
def _groupby_level(
13821381
self,
13831382
level: int | str | typing.Sequence[int] | typing.Sequence[str],
@@ -1518,11 +1517,11 @@ def combine(
15181517
materialized_series = result_series._cached()
15191518
return materialized_series
15201519

1521-
@requires_index
1520+
@validations.requires_index
15221521
def add_prefix(self, prefix: str, axis: int | str | None = None) -> Series:
15231522
return Series(self._get_block().add_prefix(prefix))
15241523

1525-
@requires_index
1524+
@validations.requires_index
15261525
def add_suffix(self, suffix: str, axis: int | str | None = None) -> Series:
15271526
return Series(self._get_block().add_suffix(suffix))
15281527

@@ -1574,7 +1573,7 @@ def filter(
15741573
else:
15751574
raise ValueError("Need to provide 'items', 'like', or 'regex'")
15761575

1577-
@requires_index
1576+
@validations.requires_index
15781577
def reindex(self, index=None, *, validate: typing.Optional[bool] = None):
15791578
if validate and not self.index.is_unique:
15801579
raise ValueError("Original index must be unique to reindex")
@@ -1603,7 +1602,7 @@ def reindex(self, index=None, *, validate: typing.Optional[bool] = None):
16031602
)._block
16041603
return Series(result_block)
16051604

1606-
@requires_index
1605+
@validations.requires_index
16071606
def reindex_like(self, other: Series, *, validate: typing.Optional[bool] = None):
16081607
return self.reindex(other.index, validate=validate)
16091608

0 commit comments

Comments
 (0)