Skip to content

Commit

Permalink
Render API docstrings in .py files as html (#98)
Browse files Browse the repository at this point in the history
This does the following:

- Ensure the package in `spec/API_specification/dataframe_api/` is importable
- Ensure all docstrings for objects/methods are rendered in the html docs via `autodoc`
- Add a description for operators supported by the dataframe object (and a few TODOs)
- Adds Sphinx templates for styling the html rendered versions of methods and attributes
  properly (taken over from the array-api repo). The Sphinx templates help with better
  styling of methods/attrs
- Adds some infrastructure for static typing that we may need. So far only the `Scalar`
  class needed a `TypeVar`, but there should be more to do there.
  • Loading branch information
rgommers authored Jan 18, 2023
1 parent 17ddbbd commit 60775db
Show file tree
Hide file tree
Showing 16 changed files with 387 additions and 54 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
*.swp
_build
__pycache__
spec/API_specification/generated/
23 changes: 23 additions & 0 deletions spec/API_specification/column_object.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.. _column-object:

Column object
=============

A conforming implementation of the dataframe API standard must provide and
support a column object having the following attributes and methods.

-------------------------------------------------

Methods
-------
TODO

..
NOTE: please keep the methods in alphabetical order
.. currentmodule:: dataframe_api

.. autosummary::
:toctree: generated
:template: property.rst

1 change: 0 additions & 1 deletion spec/API_specification/column_selection.md

This file was deleted.

5 changes: 5 additions & 0 deletions spec/API_specification/dataframe_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
Function stubs and API documentation for the DataFrame API standard.
"""

from .column_object import *
from .dataframe_object import *
from .groupby_object import *


__dataframe_api_version__: str = "YYYY.MM"
"""
String representing the version of the DataFrame API specification to which the
Expand Down
63 changes: 63 additions & 0 deletions spec/API_specification/dataframe_api/_types.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
"""
Types for type annotations used in the dataframe API standard.
The type variables should be replaced with the actual types for a given
library, e.g., for Pandas TypeVar('DataFrame') would be replaced with pd.DataFrame.
"""
from __future__ import annotations

from dataclasses import dataclass
from typing import (
Any,
List,
Literal,
Optional,
Sequence,
Tuple,
TypeVar,
Union,
Protocol,
)
from enum import Enum

array = TypeVar("array")
Scalar = TypeVar("Scalar")
device = TypeVar("device")
dtype = TypeVar("dtype")
SupportsDLPack = TypeVar("SupportsDLPack")
SupportsBufferProtocol = TypeVar("SupportsBufferProtocol")
PyCapsule = TypeVar("PyCapsule")
# ellipsis cannot actually be imported from anywhere, so include a dummy here
# to keep pyflakes happy. https://github.com/python/typeshed/issues/3556
ellipsis = TypeVar("ellipsis")

_T_co = TypeVar("_T_co", covariant=True)


class NestedSequence(Protocol[_T_co]):
def __getitem__(self, key: int, /) -> Union[_T_co, NestedSequence[_T_co]]:
...

def __len__(self, /) -> int:
...


__all__ = [
"Any",
"DataFrame",
"List",
"Literal",
"NestedSequence",
"Optional",
"PyCapsule",
"SupportsBufferProtocol",
"SupportsDLPack",
"Tuple",
"Union",
"Sequence",
"array",
"device",
"dtype",
"ellipsis",
"Enum",
]
82 changes: 56 additions & 26 deletions spec/API_specification/dataframe_api/dataframe_object.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
__all__ = ["DataFrame"]

from typing import Sequence, TYPE_CHECKING
from __future__ import annotations
from typing import Sequence, Union, TYPE_CHECKING

if TYPE_CHECKING:
from .column_object import Column
from .groupby_object import GroupBy
from ._types import Scalar


__all__ = ["DataFrame"]


class DataFrame:
Expand Down Expand Up @@ -33,7 +36,7 @@ def get_column_by_name(self, name: str, /) -> Column:
"""
...

def get_columns_by_name(self, names: Sequence[str], /) -> "DataFrame":
def get_columns_by_name(self, names: Sequence[str], /) -> DataFrame:
"""
Select multiple columns by name.
Expand All @@ -52,7 +55,7 @@ def get_columns_by_name(self, names: Sequence[str], /) -> "DataFrame":
"""
...

def get_rows(self, indices: Sequence[int]) -> "DataFrame":
def get_rows(self, indices: Sequence[int]) -> DataFrame:
"""
Select a subset of rows, similar to `ndarray.take`.
Expand All @@ -75,7 +78,7 @@ def get_rows(self, indices: Sequence[int]) -> "DataFrame":

def slice_rows(
self, start: int | None, stop: int | None, step: int | None
) -> "DataFrame":
) -> DataFrame:
"""
Select a subset of rows corresponding to a slice.
Expand All @@ -91,7 +94,7 @@ def slice_rows(
"""
...

def get_rows_by_mask(self, mask: Column[bool]) -> "DataFrame":
def get_rows_by_mask(self, mask: "Column[bool]") -> DataFrame:
"""
Select a subset of rows corresponding to a mask.
Expand All @@ -110,7 +113,7 @@ def get_rows_by_mask(self, mask: Column[bool]) -> "DataFrame":
"""
...

def insert(self, loc: int, label: str, value: Column) -> "DataFrame":
def insert(self, loc: int, label: str, value: Column) -> DataFrame:
"""
Insert column into DataFrame at specified location.
Expand All @@ -124,7 +127,7 @@ def insert(self, loc: int, label: str, value: Column) -> "DataFrame":
"""
...

def drop_column(self, label: str) -> "DataFrame":
def drop_column(self, label: str) -> DataFrame:
"""
Drop the specified column.
Expand All @@ -143,7 +146,7 @@ def drop_column(self, label: str) -> "DataFrame":
"""
...

def set_column(self, label: str, value: Column) -> "DataFrame":
def set_column(self, label: str, value: Column) -> DataFrame:
"""
Add or replace a column.
Expand All @@ -158,8 +161,10 @@ def set_column(self, label: str, value: Column) -> "DataFrame":
"""
...

def __eq__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __eq__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Compare for equality.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -173,8 +178,10 @@ def __eq__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __ne__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __ne__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Compare for non-equality.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -188,8 +195,10 @@ def __ne__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __ge__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __ge__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Compare for "greater than or equal to" `other`.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -203,8 +212,10 @@ def __ge__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __gt__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __gt__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Compare for "greater than" `other`.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -218,8 +229,10 @@ def __gt__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __le__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __le__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Compare for "less than or equal to" `other`.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -233,8 +246,10 @@ def __le__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __lt__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __lt__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Compare for "less than" `other`.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -248,8 +263,10 @@ def __lt__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __add__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __add__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Add `other` dataframe or scalar to this dataframe.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -263,8 +280,10 @@ def __add__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __sub__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __sub__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Subtract `other` dataframe or scalar from this dataframe.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -278,8 +297,10 @@ def __sub__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __mul__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __mul__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Multiply `other` dataframe or scalar with this dataframe.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -293,8 +314,10 @@ def __mul__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __truediv__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __truediv__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Divide this dataframe by `other` dataframe or scalar. True division, returns floats.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -308,8 +331,10 @@ def __truediv__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __floordiv__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __floordiv__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Floor-divide (returns integers) this dataframe by `other` dataframe or scalar.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -323,8 +348,10 @@ def __floordiv__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __pow__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __pow__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Raise this dataframe to the power of `other`.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -338,8 +365,10 @@ def __pow__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __mod__(self, other: DataFrame | "Scalar") -> "DataFrame":
def __mod__(self, other: DataFrame | Scalar) -> DataFrame:
"""
Return modulus of this dataframe by `other` (`%` operator).
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -353,8 +382,10 @@ def __mod__(self, other: DataFrame | "Scalar") -> "DataFrame":
"""
...

def __divmod__(self, other: DataFrame | "Scalar") -> tuple["DataFrame", "DataFrame"]:
def __divmod__(self, other: DataFrame | Scalar) -> tuple[DataFrame, DataFrame]:
"""
Return quotient and remainder of integer division. See `divmod` builtin function.
Parameters
----------
other : DataFrame or Scalar
Expand All @@ -364,8 +395,7 @@ def __divmod__(self, other: DataFrame | "Scalar") -> tuple["DataFrame", "DataFra
Returns
-------
DataFrame
DataFrame
A tuple of two DataFrame's
"""
...

Expand Down
Loading

0 comments on commit 60775db

Please sign in to comment.