Skip to content

Commit

Permalink
docs: fill out table API with working examples
Browse files Browse the repository at this point in the history
  • Loading branch information
cpcloud authored and gforsyth committed Mar 2, 2023
1 parent b7d4e02 commit 16fc8be
Show file tree
Hide file tree
Showing 32 changed files with 1,604 additions and 492 deletions.
49 changes: 49 additions & 0 deletions .github/workflows/ibis-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,52 @@ jobs:

- name: check shapely and duckdb imports
run: poetry run python -c 'import shapely.geometry, duckdb'

test_doctests:
name: Doctests
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
python-version:
- "3.11"
steps:
- name: install system dependencies
run: |
set -euo pipefail
sudo apt-get update -y -q
sudo apt-get install -y -q build-essential graphviz libgeos-dev libkrb5-dev
- name: checkout
uses: actions/checkout@v3

- name: install python
uses: actions/setup-python@v4
id: install_python
with:
python-version: ${{ matrix.python-version }}

- uses: syphar/restore-pip-download-cache@v1
with:
requirement_files: poetry.lock
custom_cache_key_element: doctests-${{ steps.install_python.outputs.python-version }}

- run: python -m pip install --upgrade pip 'poetry<1.4'

- uses: syphar/restore-virtualenv@v1
with:
requirement_files: poetry.lock
custom_cache_key_element: doctests-${{ steps.install_python.outputs.python-version }}

- name: install ibis with all extras
run: poetry install --without dev --without docs --extras all

- uses: extractions/setup-just@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: run doctests
run: just doctest
7 changes: 4 additions & 3 deletions ibis/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""Initialize Ibis module."""
from __future__ import annotations

from ibis import util
__version__ = "4.1.0"

from ibis import examples, util
from ibis.backends.base import BaseBackend
from ibis.common.exceptions import IbisError
from ibis.config import options
Expand All @@ -11,6 +13,7 @@

__all__ = [ # noqa: PLE0604
'api',
'examples',
'ir',
'util',
'BaseBackend',
Expand All @@ -19,8 +22,6 @@
*api.__all__,
]

__version__ = "4.1.0"

_KNOWN_BACKENDS = ['heavyai']


Expand Down
2 changes: 1 addition & 1 deletion ibis/backends/base/df/timecontext.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ def construct_time_context_aware_series(
Examples
--------
>>> import pandas as pd
>>> from ibis.expr.timecontext import construct_time_context_aware_series
>>> from ibis.backends.base.df.timecontext import construct_time_context_aware_series
>>> df = pd.DataFrame(
... {
... 'time': pd.Series(
Expand Down
4 changes: 1 addition & 3 deletions ibis/backends/bigquery/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,13 +260,11 @@ def parse_project_and_dataset(project: str, dataset: str = "") -> tuple[str, str
'ibis-gbq'
>>> dataset
'my_dataset'
>>> data_project, billing_project, dataset = parse_project_and_dataset(
>>> data_project, billing_project, _ = parse_project_and_dataset(
... 'ibis-gbq'
... )
>>> data_project
'ibis-gbq'
>>> print(dataset)
None
"""
if dataset.count(".") > 1:
raise ValueError(
Expand Down
4 changes: 2 additions & 2 deletions ibis/backends/bigquery/udf/find.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ def find_names(node: ast.AST) -> list[ast.Name]:
>>> import ast
>>> node = ast.parse('a + b')
>>> names = find_names(node)
>>> names # doctest: +ELLIPSIS
[<_ast.Name object at 0x...>, <_ast.Name object at 0x...>]
>>> names
[<....Name object at 0x...>, <....Name object at 0x...>]
>>> names[0].id
'a'
>>> names[1].id
Expand Down
16 changes: 8 additions & 8 deletions ibis/backends/dask/execution/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,18 +107,18 @@ def coerce_to_output(
Examples below use pandas objects for legibility, but functionality is the
same on dask objects.
>>> coerce_to_output(pd.Series(1), expr)
>>> coerce_to_output(pd.Series(1), expr) # doctest: +SKIP
0 1
Name: result, dtype: int64
>>> coerce_to_output(1, expr)
>>> coerce_to_output(1, expr) # doctest: +SKIP
0 1
Name: result, dtype: int64
>>> coerce_to_output(1, expr, [1,2,3])
>>> coerce_to_output(1, expr, [1,2,3]) # doctest: +SKIP
1 1
2 1
3 1
Name: result, dtype: int64
>>> coerce_to_output([1,2,3], expr)
>>> coerce_to_output([1,2,3], expr) # doctest: +SKIP
0 [1, 2, 3]
Name: result, dtype: object
"""
Expand Down Expand Up @@ -288,22 +288,22 @@ def add_partitioned_sorted_column(
Examples
--------
>>> ddf = dd.from_pandas(pd.DataFrame({'a': [1, 2,3, 4]}), npartitions=2)
>>> ddf
>>> ddf # doctest: +SKIP
Dask DataFrame Structure:
a
npartitions=2
0 int64
2 ...
3 ...
Dask Name: from_pandas, 2 task
>>> ddf.compute()
>>> ddf.compute() # doctest: +SKIP
a
0 1
1 2
2 3
3 4
>>> ddf = add_partitioned_sorted_column(ddf)
>>> ddf
>>> ddf # doctest: +SKIP
Dask DataFrame Structure:
a
npartitions=2
Expand All @@ -312,7 +312,7 @@ def add_partitioned_sorted_column(
8589934592 ...
Dask Name: set_index, 8 tasks
Name: result, dtype: int64
>>> ddf.compute()
>>> ddf.compute() # doctest: +SKIP
a
_ibis_index
0 1
Expand Down
2 changes: 1 addition & 1 deletion ibis/backends/pandas/aggcontext.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@
... 'time': pd.date_range(periods=4, start='now')
... })
>>> sorter = lambda df: df.sort_values('time')
>>> gb = df.groupby('key').apply(sorter).reset_index(
>>> gb = df.groupby('key', group_keys=False).apply(sorter).reset_index(
... drop=True
... ).groupby('key')
>>> rolling = gb.value.rolling(2)
Expand Down
8 changes: 4 additions & 4 deletions ibis/backends/pandas/execution/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,18 @@ def coerce_to_output(
--------
For dataframe outputs, see ``ibis.util.coerce_to_dataframe``.
>>> coerce_to_output(pd.Series(1), node)
>>> coerce_to_output(pd.Series(1), node) # doctest: +SKIP
0 1
Name: result, dtype: int64
>>> coerce_to_output(1, node)
>>> coerce_to_output(1, node) # doctest: +SKIP
0 1
Name: result, dtype: int64
>>> coerce_to_output(1, node, [1,2,3])
>>> coerce_to_output(1, node, [1,2,3]) # doctest: +SKIP
1 1
2 1
3 1
Name: result, dtype: int64
>>> coerce_to_output([1,2,3], node)
>>> coerce_to_output([1,2,3], node) # doctest: +SKIP
0 [1, 2, 3]
Name: result, dtype: object
"""
Expand Down
5 changes: 3 additions & 2 deletions ibis/backends/pyspark/timecontext.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,16 @@ def combine_time_context(
Examples
--------
>>> import pandas as pd
>>> timecontexts = [
... (pd.Timestamp('20200102'), pd.Timestamp('20200103')),
... (pd.Timestamp('20200101'), pd.Timestamp('20200106')),
... (pd.Timestamp('20200109'), pd.Timestamp('20200110')),
... ]
>>> combine_time_context(timecontexts)
(pd.Timestamp('20200101'), pd.Timestamp('20200110'))
(Timestamp(...), Timestamp(...))
>>> timecontexts = [None]
>>> combine_time_context(timecontexts)
>>> print(combine_time_context(timecontexts))
None
"""
begin = min((t[0] for t in timecontexts if t), default=None)
Expand Down
2 changes: 1 addition & 1 deletion ibis/common/annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ def annotated(_1=None, _2=None, _3=None, **kwargs):
2. With argument validators passed as keyword arguments
>>> from ibis.common.validate import instance_of
>>> from ibis.common.validators import instance_of
>>> @annotated(x=instance_of(int), y=instance_of(str))
... def foo(x, y):
... return float(x) + float(y)
Expand Down
3 changes: 3 additions & 0 deletions ibis/common/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class MapSet(Mapping[K, V]):
... def __getitem__(self, key):
... return self._data[key]
...
... def __repr__(self):
... return f"MyMap({repr(self._data)})"
...
>>> m = MyMap(a=1, b=2)
>>> n = dict(a=1, b=2, c=3)
>>> m <= n
Expand Down
16 changes: 16 additions & 0 deletions ibis/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import os

import pytest

import ibis


@pytest.fixture(autouse=True)
@pytest.mark.usefixtures("doctest_namespace")
def add_ibis(monkeypatch):
# disable color for doctests so we don't have to include
# escape codes in docstrings
monkeypatch.setitem(os.environ, "NO_COLOR", "1")
# reset interactive mode to False for doctests that don't execute
# expressions
ibis.options.interactive = False
4 changes: 2 additions & 2 deletions ibis/examples/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ def _make_fetch_docstring(*, name: str, reader: str):
Examples
--------
>>> from ibis.interactive import *
>>> t = ex.{name}.fetch()
>>> import ibis
>>> t = ibis.examples.{name}.fetch()
"""


Expand Down
30 changes: 13 additions & 17 deletions ibis/expr/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,12 @@ def find_immediate_parent_tables(input_node, keep_input=True):
>>> import ibis, toolz
>>> t = ibis.table([('a', 'int64')], name='t')
>>> expr = t.mutate(foo=t.a + 1)
>>> result = find_immediate_parent_tables(expr)
>>> len(result)
1
>>> result[0]
r0 := UnboundTable[t]
a int64
Selection[r0]
selections:
r0
foo: r0.a + 1
>>> result, = find_immediate_parent_tables(expr.op())
>>> result.equals(expr.op())
True
>>> result, = find_immediate_parent_tables(expr.op(), keep_input=False)
>>> result.equals(t.op())
True
"""
assert all(isinstance(arg, ops.Node) for arg in util.promote_list(input_node))

Expand Down Expand Up @@ -681,19 +677,19 @@ def flatten_predicate(node):
>>> import ibis
>>> t = ibis.table([('a', 'int64'), ('b', 'string')], name='t')
>>> filt = (t.a == 1) & (t.b == 'foo')
>>> predicates = flatten_predicate(filt)
>>> predicates = flatten_predicate(filt.op())
>>> len(predicates)
2
>>> predicates[0]
r0 := UnboundTable[t]
>>> predicates[0].to_expr().name("left")
r0 := UnboundTable: t
a int64
b string
r0.a == 1
>>> predicates[1]
r0 := UnboundTable[t]
left: r0.a == 1
>>> predicates[1].to_expr().name("right")
r0 := UnboundTable: t
a int64
b string
r0.b == 'foo'
right: r0.b == 'foo'
"""

def predicate(node):
Expand Down
Loading

0 comments on commit 16fc8be

Please sign in to comment.