207 changes: 0 additions & 207 deletions docs/about/license.md

This file was deleted.

118 changes: 0 additions & 118 deletions docs/about/roadmap.md

This file was deleted.

24 changes: 0 additions & 24 deletions docs/about/team.md

This file was deleted.

2 changes: 1 addition & 1 deletion docs/api/backends/base.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

<!-- prettier-ignore-start -->
::: ibis.backends.base.BaseBackend
selection:
options:
inherited_members: true
<!-- prettier-ignore-end -->
2 changes: 1 addition & 1 deletion docs/api/backends/pandas.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ These base classes underlie the pandas-based backends.

<!-- prettier-ignore-start -->
::: ibis.backends.pandas.BasePandasBackend
selection:
options:
inherited_members: true
<!-- prettier-ignore-end -->
2 changes: 1 addition & 1 deletion docs/api/backends/sql.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

<!-- prettier-ignore-start -->
::: ibis.backends.base.sql.BaseSQLBackend
selection:
options:
inherited_members: true
<!-- prettier-ignore-end -->
2 changes: 1 addition & 1 deletion docs/api/backends/sqlalchemy.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

<!-- prettier-ignore-start -->
::: ibis.backends.base.sql.alchemy.BaseAlchemyBackend
selection:
options:
inherited_members: true
<!-- prettier-ignore-end -->
15 changes: 14 additions & 1 deletion docs/api/config.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# Configuration Options

::: ibis.config
<!-- prettier-ignore-start -->
::: ibis.config.Options
options:
show_bases: false
::: ibis.config.Repr
options:
show_bases: false
::: ibis.config.SQL
options:
show_bases: false
::: ibis.config.ContextAdjustment
options:
show_bases: false
<!-- prettier-ignore-end -->
2 changes: 2 additions & 0 deletions docs/api/expressions/top_level.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ These methods and objects are available directly in the `ibis` module.
::: ibis.to_sql
::: ibis.random
::: ibis.range_window
::: ibis.read_csv
::: ibis.read_parquet
::: ibis.row_number
::: ibis.schema
::: ibis.struct
Expand Down
1 change: 0 additions & 1 deletion docs/backends/Dask.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ backend_name: Dask
backend_url: https://dask.org
backend_module: dask
backend_param_style: a dictionary of paths
is_experimental: true
---

{% include 'backends/template.md' %}
1 change: 0 additions & 1 deletion docs/backends/Datafusion.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ backend_name: Datafusion
backend_url: https://arrow.apache.org/datafusion/
backend_module: datafusion
backend_param_style: a dictionary of paths
is_experimental: true
version_added: "2.1"
---

Expand Down
2 changes: 1 addition & 1 deletion docs/backends/DuckDB.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ backend_url: https://duckdb.org/
backend_module: duckdb
backend_param_style: a path to a DuckDB database
backend_connection_example: ibis.duckdb.connect("path/to/my.duckdb")
development_only: false
version_added: "3.0"
intro: |
!!! danger "`duckdb` >= 0.5.0 requires `duckdb-engine` >= 0.6.2"
Expand Down
74 changes: 31 additions & 43 deletions docs/backends/Impala.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ backend.

<!-- prettier-ignore-start -->
::: ibis.backends.impala.Backend
rendering:
options:
heading_level: 3
selection:
members:
- set_database
- create_database
Expand All @@ -45,9 +44,8 @@ find the most methods on `ImpalaTable`.

<!-- prettier-ignore-start -->
::: ibis.backends.impala.Backend
rendering:
options:
heading_level: 3
selection:
members:
- table
- sql
Expand All @@ -73,9 +71,8 @@ The best way to interact with a single table is through the

<!-- prettier-ignore-start -->
::: ibis.backends.impala.client.ImpalaTable
rendering:
options:
heading_level: 3
selection:
members:
- add_partition
- alter
Expand Down Expand Up @@ -104,9 +101,8 @@ The best way to interact with a single table is through the

<!-- prettier-ignore-start -->
::: ibis.backends.impala.Backend
rendering:
options:
heading_level: 3
selection:
members:
- drop_table_or_view
- create_view
Expand All @@ -117,9 +113,8 @@ The best way to interact with a single table is through the

<!-- prettier-ignore-start -->
::: ibis.backends.impala.Backend
rendering:
options:
heading_level: 3
selection:
members:
- delimited_file
- parquet_file
Expand Down Expand Up @@ -161,10 +156,9 @@ table or database.
## Table objects

<!-- prettier-ignore-start -->
::: ibis.backends.impala.Backend.table
rendering:
::: ibis.backends.base.sql.BaseSQLBackend.table
options:
heading_level: 3

<!-- prettier-ignore-end -->

The client's `table` method allows you to create an Ibis table
Expand All @@ -183,9 +177,8 @@ you can use to examine its schema:

<!-- prettier-ignore-start -->
::: ibis.backends.impala.client.ImpalaTable
rendering:
options:
heading_level: 3
selection:
members:
- schema

Expand Down Expand Up @@ -228,9 +221,8 @@ top-level client connection or a database object.

<!-- prettier-ignore-start -->
::: ibis.backends.impala.Backend.create_table
rendering:
options:
heading_level: 3

<!-- prettier-ignore-end -->

### Creating tables from a table expression
Expand Down Expand Up @@ -349,9 +341,8 @@ partition data:

<!-- prettier-ignore-start -->
::: ibis.backends.impala.client.ImpalaTable
rendering:
options:
heading_level: 3
selection:
members:
- add_partition
- drop_partition
Expand Down Expand Up @@ -434,9 +425,8 @@ To get a handy wrangled version of `DESCRIBE FORMATTED` use the

<!-- prettier-ignore-start -->
::: ibis.backends.impala.client.ImpalaTable.metadata
rendering:
options:
heading_level: 3

<!-- prettier-ignore-end -->

```python
Expand Down Expand Up @@ -493,9 +483,8 @@ data files backing a table:

<!-- prettier-ignore-start -->
::: ibis.backends.impala.client.ImpalaTable
rendering:
options:
heading_level: 3
selection:
members:
- files

Expand Down Expand Up @@ -528,9 +517,8 @@ change partition-specific metadata use `alter_partition`.

<!-- prettier-ignore-start -->
::: ibis.backends.impala.client.ImpalaTable
rendering:
options:
heading_level: 3
selection:
members:
- alter
- alter_partition
Expand Down Expand Up @@ -570,9 +558,8 @@ table.alter_partition(

<!-- prettier-ignore-start -->
::: ibis.backends.impala.client.ImpalaTable
rendering:
options:
heading_level: 3
selection:
members:
- compute_stats

Expand All @@ -598,9 +585,8 @@ table.compute_stats(incremental=True)

<!-- prettier-ignore-start -->
::: ibis.backends.impala.client.ImpalaTable
rendering:
options:
heading_level: 3
selection:
members:
- column_stats
- stats
Expand Down Expand Up @@ -672,19 +658,17 @@ methods:

<!-- prettier-ignore-start -->
::: ibis.backends.impala.Backend
rendering:
options:
heading_level: 3
selection:
members:
- invalidate_metadata

<!-- prettier-ignore-end -->

<!-- prettier-ignore-start -->
::: ibis.backends.impala.client.ImpalaTable
rendering:
options:
heading_level: 3
selection:
members:
- invalidate_metadata
- refresh
Expand Down Expand Up @@ -719,19 +703,17 @@ also deals with file name conflicts so data is not lost in such cases.

<!-- prettier-ignore-start -->
::: ibis.backends.impala.Backend
rendering:
options:
heading_level: 3
selection:
members:
- load_data

<!-- prettier-ignore-end -->

<!-- prettier-ignore-start -->
::: ibis.backends.impala.client.ImpalaTable
rendering:
options:
heading_level: 3
selection:
members:
- load_data

Expand Down Expand Up @@ -761,9 +743,8 @@ query execution:

<!-- prettier-ignore-start -->
::: ibis.backends.impala.Backend
rendering:
options:
heading_level: 3
selection:
members:
- disable_codegen
- get_options
Expand Down Expand Up @@ -1345,10 +1326,17 @@ your Ibis session to plug in all your own functions.
## Working with secure clusters (Kerberos)

Ibis is compatible with Hadoop clusters that are secured with Kerberos (as well
as SSL and LDAP). Just like the Impala shell and ODBC/JDBC connectors, Ibis
connects to Impala through the HiveServer2 interface (using the impyla client).
Therefore, the connection semantics are similar to the other access methods for
working with secure clusters.
as SSL and LDAP). Note that to enable this support, you'll also need to install
the `kerberos` package.

```sh
$ pip install kerberos
```

Just like the Impala shell and ODBC/JDBC connectors, Ibis connects to Impala
through the HiveServer2 interface (using the impyla client). Therefore, the
connection semantics are similar to the other access methods for working with
secure clusters.

Specifically, after authenticating yourself against Kerberos (e.g., by issuing
the appropriate `kinit` commmand), simply pass `auth_mechanism='GSSAPI'` or
Expand Down
9 changes: 9 additions & 0 deletions docs/backends/MSSQL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
backend_name: MS SQL Server
backend_url: https://www.microsoft.com/en-us/evalcenter/evaluate-sql-server-2022
backend_module: mssql
backend_param_style: connection parameters
version_added: "4.0"
---

{% include 'backends/template.md' %}
10 changes: 5 additions & 5 deletions docs/backends/Pandas.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Here's how to define an element-wise function:

```python
import ibis.expr.datatypes as dt
from ibis.backends.pandas import udf
from ibis.backends.pandas.udf import udf

@udf.elementwise(input_type=[dt.int64], output_type=dt.double)
def add_one(x):
Expand All @@ -44,7 +44,7 @@ Here's how to define a reduction function:

```python
import ibis.expr.datatypes as dt
from ibis.backends.pandas import udf
from ibis.backends.pandas.udf import udf

@udf.reduction(input_type=[dt.double], output_type=dt.double)
def double_mean(series):
Expand All @@ -62,7 +62,7 @@ Here's how to define an analytic function:

```python
import ibis.expr.datatypes as dt
from ibis.backends.pandas import udf
from ibis.backends.pandas.udf import udf

@udf.analytic(input_type=[dt.double], output_type=dt.double)
def zscore(series):
Expand Down Expand Up @@ -114,7 +114,7 @@ in your function:

```python
import ibis.expr.datatypes as dt
from ibis.backends.pandas import udf
from ibis.backends.pandas.udf import udf

@udf.elementwise([dt.int64], dt.double)
def add_two(x, **kwargs): # do stuff with kwargs
Expand All @@ -128,7 +128,7 @@ For example:

```python
import ibis.expr.datatypes as dt
from ibis.backends.pandas import udf
from ibis.backends.pandas.udf import udf

@udf.elementwise([dt.int64], dt.double)
def add_two_with_none(x, y=None):
Expand Down
10 changes: 10 additions & 0 deletions docs/backends/Polars.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
backend_name: Polars
backend_url: https://pola-rs.github.io/polars-book/user-guide/index.html
backend_module: polars
backend_param_style: connection parameters
is_experimental: true
version_added: "4.0"
---

{% include 'backends/template.md' %}
3 changes: 1 addition & 2 deletions docs/backends/SQLite.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ exclude_backend_api: true

<!-- prettier-ignore-start -->
::: ibis.backends.sqlite.Backend
rendering:
options:
heading_level: 3
selection:
inherited_members: true
members:
- add_operation
Expand Down
11 changes: 11 additions & 0 deletions docs/backends/Snowflake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
backend_name: Snowflake
backend_url: https://snowflake.com/
backend_module: snowflake
backend_param_style: a SQLAlchemy connection string
backend_connection_example: ibis.connect("snowflake://user:pass@locator/database/schema")
is_experimental: true
version_added: "4.0"
---

{% include 'backends/template.md' %}
10 changes: 10 additions & 0 deletions docs/backends/Trino.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
backend_name: Trino
backend_url: https://trino.io
backend_module: trino
backend_param_style: a SQLAlchemy connection string
is_experimental: true
version_added: "4.0"
---

{% include 'backends/template.md' %}
5 changes: 5 additions & 0 deletions docs/backends/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ another kind of expression and typically have high-level APIs for execution.

- [Dask](Dask.md)
- [Datafusion](Datafusion.md)
- [DuckDB](DuckDB.md)
- [MySQL](MySQL.md)
- [MS SQL Server](MSSQL.md)
- [Polars](Polars.md)
- [PostgreSQL](PostgreSQL.md)
- [PySpark](PySpark.md)
- [SQLite](SQLite.md)
- [Snowflake](Snowflake.md)
- [Trino](Trino.md)

## Direct Execution Backends

Expand Down
15 changes: 14 additions & 1 deletion docs/backends/support_matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,17 @@ hide:

Backends are shown in descending order of the number of supported operations.

{{ read_csv("docs/backends/support_matrix.csv") }}
!!! tip "The Snowflake backend coverage is an overestimate"

The Snowflake backend translation functions are reused from the PostgreSQL backend
and some operations that claim coverage may not work.

The Snowflake backend is a good place to start contributing!

## Core Operations

{{ read_csv("docs/backends/core_support_matrix.csv") }}

## Geospatial Operations

{{ read_csv("docs/backends/geospatial_support_matrix.csv") }}
19 changes: 10 additions & 9 deletions docs/backends/template.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
# [{{ backend_name }}]({{ backend_url }})

{% if is_experimental %}
!!! experimental "{% if version_added %}New in v{{ version_added }}{% else %}Experimental{% endif %}"
!!! experimental "{% if version_added %}Introduced in v{{ version_added }}{% else %}Experimental{% endif %}"

The {{ backend_name }} backend is experimental and is subject to backwards incompatible changes.

{% elif version_added %}
!!! tip "Introduced in v{{ version_added }}"
{% endif %}

{% if intro %}{{ intro }}{% endif %}

{% if not development_only %}
{% if not (development_only | default(False)) %}

## Install

Expand All @@ -33,7 +35,7 @@ Install ibis and dependencies for the {{ backend_name }} backend:
{% else %}
!!! info "The {{ backend_name }} backend isn't released yet!"

[Set up a development environment](../contribute/01_environment.md) to use this backend.
[Set up a development environment](../community/contribute/01_environment.md) to use this backend.

{% endif %}

Expand All @@ -44,19 +46,19 @@ Install ibis and dependencies for the {{ backend_name }} backend:
Create a client by passing in {{ backend_param_style }} to `ibis.{{ backend_module }}.connect`.

<!-- prettier-ignore-start -->
See [`ibis.backends.{{ backend_module }}.Backend.do_connect`][ibis.backends.{{ backend_module }}.Backend.do_connect]
See [`ibis.backends.{{ backend_module }}.Backend.do_connect`][ibis.backends.{{ backend_module }}.{{ do_connect_base | default('Backend') }}.do_connect]
for connection parameter information.
<!-- prettier-ignore-end -->

<!-- prettier-ignore-start -->
!!! info "`ibis.{{ backend_module }}.connect` is a thin wrapper around [`ibis.backends.{{ backend_module }}.Backend.do_connect`][ibis.backends.{{ backend_module }}.Backend.do_connect]."
!!! info "`ibis.{{ backend_module }}.connect` is a thin wrapper around [`ibis.backends.{{ backend_module }}.Backend.do_connect`][ibis.backends.{{ backend_module }}.{{ do_connect_base | default('Backend') }}.do_connect]."
<!-- prettier-ignore-end -->

### Connection Parameters

<!-- prettier-ignore-start -->
::: ibis.backends.{{ backend_module }}.Backend.do_connect
rendering:
::: ibis.backends.{{ backend_module }}.{{ do_connect_base | default('Backend') }}.do_connect
options:
heading_level: 4
<!-- prettier-ignore-end -->

Expand All @@ -66,9 +68,8 @@ for connection parameter information.

<!-- prettier-ignore-start -->
::: ibis.backends.{{ backend_module }}.Backend
rendering:
options:
heading_level: 3
selection:
inherited_members: true
<!-- prettier-ignore-end -->

Expand Down
41 changes: 41 additions & 0 deletions docs/blog/ibis-version-4.0.0-release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Ibis v4.0.0

**by Patrick Clarke**

09 January 2023

## Introduction

Ibis 4.0 has officially been released as the latest version of the package.
This release includes several new backends, improved functionality, and some major internal refactors.
A full list of the changes can be found in the [project release notes](../release_notes.md).
Let’s talk about some of the new changes 4.0 brings for Ibis users.

## Backends

Ibis 4.0 brings [Polars](https://ibis-project.org/docs/latest/backends/Polars/), [Snowflake](https://ibis-project.org/docs/dev/backends/Snowflake/), and [Trino](https://ibis-project.org/docs/dev/backends/Trino/) into an already-impressive stock of supported backends.
The [Polars](https://www.pola.rs/) backend adds another way for users to work locally with DataFrames.
The [Snowflake](https://www.snowflake.com/en/) and [Trino](https://trino.io/) backends add a free and familiar python API to popular data warehouses.

Alongside these new backends, Google BigQuery and Microsoft SQL have been moved to the main repo and have been updated.

## Functionality

There are a lot of improvements incoming, but some notable changes include:

- [read API](https://github.com/ibis-project/ibis/pull/5005)): allows users to read various file formats directly into their [configured `default_backend`](https://ibis-project.org/docs/dev/api/config/?h=default#ibis.config.Options) (default DuckDB) through `read_*` functions, which makes working with local files easier than ever.
- [to_pyarrow and to_pyarrow_batches](https://github.com/ibis-project/ibis/pull/4454#issuecomment-1262640204): users can now return PyArrow objects (Tables, Arrays, Scalars, RecordBatchReader) and therefore grants all of the functionality that PyArrow provides
- [JSON getitem](https://github.com/ibis-project/ibis/pull/4525): users can now run getitem on a JSON field using Ibis expressions with some backends
- [Plotting support through `__array__`](https://github.com/ibis-project/ibis/pull/4547): allows users to plot Ibis expressions out of the box

## Refactors

This won't be visible to most users, but the project underwent a series of refactors that spans [multiple PRs](https://github.com/ibis-project/ibis/pulls?q=is%3Apr+is%3Amerged+%22refactor%3A%22+milestone%3A4.0.0).
Notable changes include removing intermediate expressions, improving the testing framework, and UX updates.

## Additional Changes

As mentioned previously, additional functionality, bugfixes, and more have been included in the latest 4.0 release.
To stay up to date and learn more about recent changes: check out the project's homepage at [ibis-project.org](https://ibis-project.org/docs/latest/), follow [@IbisData](https://twitter.com/IbisData) on Twitter, find the source code and community on [GitHub](https://github.com/ibis-project/ibis), and join the discussion on [Gitter](https://gitter.im/ibis-dev/Lobby).

As always, try Ibis by [installing](https://ibis-project.org/docs/latest/install/) it today.
1,606 changes: 1,606 additions & 0 deletions docs/blog/rendered/ci-analysis.ipynb

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,12 @@ hide:
nix-shell
```

This may take awhile due to artifact download from the cache.
This may take a while due to artifact download from the cache.

=== "Conda"

!!! info "Some optional dependencies for Windows are not available through `conda`/`mamba`"

1. `python-duckdb` and `duckdb-engine`. Required for the DuckDB backend.
1. `clickhouse-cityhash`. Required for compression support in the ClickHouse backend.

#### Support Matrix
Expand Down Expand Up @@ -151,6 +150,7 @@ hide:
1. Install development dependencies

```sh
pip install 'poetry>=1.2'
pip install -r requirements.txt
```

Expand All @@ -160,7 +160,11 @@ hide:
pip install -e .
```

Once you've set up an environment, try building the documentation:
## Building the Docs

!!! warning "You **must** set up an environment with Nix as above to build the website and docs."

Then, run:

```sh
mkdocs serve
Expand Down
81 changes: 81 additions & 0 deletions docs/community/contribute/02_workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Contribute to the Ibis Codebase

## Getting started

First, set up a [development environment](01_environment.md).

## Taking Issues

If you find an issue you want to work on, write a comment with the text
`/take` on the issue. GitHub will then assign the issue to you.

## Running the test suite

To run tests that do not require a backend:

```sh
pytest -m core
```

### Backend Test Suites

!!! info "You may be able to skip this section"

If you haven't made changes to the core of ibis (e.g., `ibis/expr`)
or any specific backends (`ibis/backends`) this material isn't necessary to
follow to make a pull request.

To run the tests for a specific backend (e.g. sqlite):

```sh
pytest -m sqlite
```

## Setting up non-trivial backends

These client-server backends need to be started before testing them.
They can be started with `docker-compose` directly, or using the `just` tool.

- ClickHouse: `just up clickhouse`
- PostgreSQL: `just up postgres`
- MySQL: `just up mysql`
- impala: `just up impala`

### Test the backend locally

If anything seems amiss with a backend, you can of course test it locally:

```sh
export PGPASSWORD=postgres
psql -t -A -h localhost -U postgres -d ibis_testing -c "select 'success'"
```

## Download Test Data

Backends need to be populated with test data to run the tests successfully:

```sh
just download-data
```

## Writing the commit

Ibis follows the [Conventional Commits](https://www.conventionalcommits.org/) structure.
In brief, the commit summary should look like:

fix(types): make all floats doubles

The type (e.g. `fix`) can be:

- `fix`: A bug fix. Correlates with PATCH in SemVer
- `feat`: A new feature. Correlates with MINOR in SemVer
- `docs`: Documentation only changes
- `style`: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
`
If the commit fixes a Github issue, add something like this to the bottom of the description:

fixes #4242

## Submit a PR

Ibis follows the standard Git Pull Request process. The team will review the PR and merge when it's ready.
17 changes: 17 additions & 0 deletions docs/community/contribute/03_style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Style and Formatting

## Code Style

- [`black`](https://github.com/psf/black): Formatting Python code
- [`ruff`](https://github.com/charliermarsh/ruff): Formatting and sorting `import` statements
- [`shellcheck`](https://github.com/koalaman/shellcheck): Linting shell scripts
- [`shfmt`](https://github.com/mvdan/sh): Formatting shell scripts
- [`statix`](https://github.com/nerdypepper/statix): Linting nix files
- [`nixpkgs-fmt`](https://github.com/nix-community/nixpkgs-fmt): Formatting nix files

!!! tip

If you use `nix-shell`, all of these are already setup for you and ready to use, and you don't need to do anything to install these tools.

We use [numpydoc](https://numpydoc.readthedocs.io/en/latest/format.html) as our
standard format for docstrings.
39 changes: 39 additions & 0 deletions docs/community/contribute/05_maintainers_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Maintaining the Codebase

Ibis maintainers are expected to handle the following tasks as they arise:

- Reviewing and merging pull requests
- Triaging new issues

## Dependencies

A number of tasks that are typically associated with maintenance are partially or fully automated.

- [WhiteSource Renovate](https://www.whitesourcesoftware.com/free-developer-tools/renovate/) (Python library dependencies and GitHub Actions)
- [Custom GitHub Action](https://github.com/ibis-project/ibis/actions/workflows/update-deps.yml) (Nix dependencies)

### poetry

Occasionally you may need to lock [`poetry`](https://python-poetry.org) dependencies. Edit `pyproject.toml` as needed, then run:

```sh
poetry lock --no-update
```

## Release

Ibis is released on [PyPI](https://pypi.org/project/ibis-framework/) and [Conda Forge](https://github.com/conda-forge/ibis-framework-feedstock).

=== "PyPI"

Releases to PyPI are handled automatically using [semantic
release](https://egghead.io/lessons/javascript-automating-releases-with-semantic-release).

To trigger a release use the [Release GitHub Action](https://github.com/ibis-project/ibis/actions/workflows/release.yml).

=== "`conda-forge`"

The conda-forge package is maintained as a [conda-forge feedstock](https://github.com/conda-forge/ibis-framework-feedstock).

After a release to PyPI, the conda-forge bot automatically updates the ibis
package.
15 changes: 15 additions & 0 deletions docs/community/contribute/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Contribute to Ibis

{{ config.extra.project_name }} is developed and maintained by a [community of
volunteer contributors]({{ config.repo_url }}/graphs/contributors).

{% for group in config.extra.team %}

## {{ group.name }}

{% for person in group.members %}

- https://github.com/{{ person }}
{% endfor %}

{% endfor %}
99 changes: 0 additions & 99 deletions docs/community/ecosystem.md

This file was deleted.

6 changes: 6 additions & 0 deletions docs/community/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Community

Ibis aims to be a welcoming, friendly, diverse and
inclusive community. Everybody is welcome, regardless of gender, sexual
orientation, gender identity, and expression, disability, physical appearance,
body size, race, or religion.
208 changes: 0 additions & 208 deletions docs/contribute/02_workflow.md

This file was deleted.

33 changes: 0 additions & 33 deletions docs/contribute/03_style.md

This file was deleted.

95 changes: 0 additions & 95 deletions docs/contribute/04_backend_tests.md

This file was deleted.

99 changes: 0 additions & 99 deletions docs/contribute/05_maintainers_guide.md

This file was deleted.

9 changes: 9 additions & 0 deletions docs/docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Ibis Documentation

Welcome to the ibis documentation!

- **Coming from Pandas?**: Check out [ibis for pandas users](../ibis-for-pandas-users.ipynb)!
- **Coming from SQL?**: Take a look at [ibis for SQL programmers](../ibis-for-sql-programmers.ipynb)!
- **Want to see some more examples?**: We've got [a set of tutorial notebooks](../tutorial/index.md) for that!
- **Looking for API docs?**: Start [here](../api/expressions/top_level.md)!
- **Interested in contributing?**: Our [contribution section](../community/contribute/index.md) has what you need!
8 changes: 4 additions & 4 deletions docs/example.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import ibis

con = ibis.sqlite.connect("crunchbase.db")
Expand All @@ -11,11 +13,9 @@
.aggregate(
num_investments=c.permalink.nunique(),
acq_ipos=(
c.status.isin(("ipo", "acquired"))
.ifelse(c.permalink, ibis.NA)
.nunique()
c.status.isin(("ipo", "acquired")).ifelse(c.permalink, ibis.NA).nunique()
),
)
.mutate(acq_rate=lambda t: t.acq_ipos / t.num_investments)
.sort_by(ibis.desc(2))
.order_by(ibis.desc(2))
)
68 changes: 68 additions & 0 deletions docs/how_to/chain-expressions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# How to Chain Expressions with Underscore

Expressions can easily be chained using the deferred expression API, also known as the Underscore (`_`) API.

In this guide, we use the `_` API to concisely create column expressions and then chain table expressions.

## Setup

To get started, import `_` from ibis:

```python
import ibis
from ibis import _

import pandas as pd
```

Let's create two in-memory tables using [`ibis.memtable`](memtable-join.md), an API introduced in 3.2:

```python
t1 = ibis.memtable(pd.DataFrame({'x': range(5), 'y': list('ab')*2 + list('e')}))
t2 = ibis.memtable(pd.DataFrame({'x': range(10), 'z': list(reversed(list('ab')*2 + list('e')))*2}))
```

## Creating ColumnExpressions

We can use `_` to create new column expressions without explicit reference to the previous table expression:

```python
# We can pass a deferred expression into a function:
def modf(t):
return t.x % 3

xmod = modf(_)

# We can create ColumnExprs like aggregate expressions:
ymax = _.y.max()
zmax = _.z.max()
zct = _.z.count()
```

## Chaining Ibis Expressions

We can also use it to chain Ibis expressions in one Python expression:

```python
join = (
t1
# _ is t1
.join(t2, _.x == t2.x)
# _ is the join result:
.mutate(xmod=xmod)
# _ is the TableExpression after mutate:
.group_by(_.xmod)
# `ct` is a ColumnExpression derived from a deferred expression:
.aggregate(ymax=ymax, zmax=zmax)
# _ is the aggregation result:
.filter(_.ymax == _.zmax)
# _ is the filtered result, and re-create xmod in t2 using modf:
.join(t2, _.xmod == modf(t2))
# _ is the second join result:
.join(t1, _.xmod == modf(t1), suffixes=('', '_x'))
# _ is the third join result:
.select(_.x, _.y, _.z)
# Finally, _ is the selection result:
.order_by(_.x)
)
```
2 changes: 1 addition & 1 deletion docs/how_to/duckdb_register.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Use `register` to load external data files with the DuckDB backend
# How to Use `register` to load external data files with the DuckDB backend

<!-- prettier-ignore-start -->
Here we use the [`register`][ibis.backends.duckdb.Backend.register] method to load external data files and join them.
Expand Down
110 changes: 110 additions & 0 deletions docs/how_to/memtable-join.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# How to join an in-memory DataFrame to a TableExpression

You might have an in-memory DataFrame that you want to join to a TableExpression.
For example, you might have a file on your local machine that you don't want to upload to
your backend, but you need to join it to a table in that backend.

You can perform joins on local data to TableExpressions from your backend easily with Ibis MemTables.

In this guide, you will learn how to join a pandas DataFrame to a TableExpression.

## Data Setup:

In this example, we will create two DataFrames: one containing events and one containing event names.
We will save the events to a parquet file and read that as a TableExpression in the DuckDB backend.
We will then convert the event names DataFrame to a PandasInMemoryTable (MemTable), which is
a pandas DataFrame as a TableExpression and join the two expressions together as we would
two TableExpressions in a backend.

```python
In [1]: import ibis

In [2]: import pandas as pd
...: from datetime import date

In [3]: # create a pandas DataFrame that we will convert to a
...: # PandasInMemoryTable (Ibis MemTable)
...: events = pd.DataFrame(
...: {
...: 'event_id': range(4),
...: 'event_name': [f'e{k}' for k in range(4)],
...: }
...: )

In [4]: # Create a parquet file that we will read in using the DuckDB backend
...: # as a TableExpression
...: measures = pd.DataFrame({
...: "event_id": [0] * 2 + [1] * 3 + [2] * 5 + [3] * 2
...: ,"measured_on": map(
...: date
...: ,[2021] * 12, [6] * 4 + [5] * 6 + [7] * 2
...: ,range(1, 13)
...: )
...: ,"measurement": None
...: })

In [5]: measures.at[1, "measurement"] = 5.
...: measures.at[4, "measurement"] = 42.
...: measures.at[5, "measurement"] = 42.
...: measures.at[7, "measurement"] = 11.

In [6]: # Save measures to parquet:
...: measures.to_parquet('measures.parquet')

In [7]: # connect to a DuckDB backend
...: conn = ibis.connect('duckdb://:memory:')
...: measures = conn.register('measures.parquet', 'measures')

In [8]: # `measures` is a TableExpression in a DuckDB backend connection:
...: measures
Out[8]:
AlchemyTable: measures
event_id int64
measured_on date
measurement float64
```

Converting a pandas DataFrame to a MemTable is as simple as feeding it to `ibis.memtable`:

```python
In [9]: # To join, convert your DataFrame to a memtable
...: mem_events = ibis.memtable(events)

In [10]: mem_events
Out[10]:
PandasInMemoryTable
data:
DataFrameProxy:
event_id event_name
0 0 e0
1 1 e1
2 2 e2
3 3 e3
```

and joining is the same as joining any two TableExpressions:

```python
In [11]: # Join as you would two table expressions
...: measures.join(
...: mem_events
...: ,measures['event_id'] == mem_events['event_id']
...: ,suffixes=('', '__x')
...: ).execute()
Out[11]:
event_id measured_on measurement event_id__x event_name
0 0 2021-06-01 NaN 0 e0
1 0 2021-06-02 5.0 0 e0
2 1 2021-06-03 NaN 1 e1
3 1 2021-06-04 NaN 1 e1
4 1 2021-05-05 42.0 1 e1
5 2 2021-05-06 42.0 2 e2
6 2 2021-05-07 NaN 2 e2
7 2 2021-05-08 11.0 2 e2
8 2 2021-05-09 NaN 2 e2
9 2 2021-05-10 NaN 2 e2
10 3 2021-07-11 NaN 3 e3
11 3 2021-07-12 NaN 3 e3
```

Note that the return result of the `join` is a TableExpression and that `execute` returns a pandas DataFrame.
74 changes: 74 additions & 0 deletions docs/how_to/sessionize.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# How to Sessionize a Log of Events

Suppose you have entities (users, objects, actions, etc) that have event logs through polling or event triggers.

You might be interested in partitioning these logs by something called **sessions**, which can be defined as the duration of an event.

In the case of a user portal, it might be the time spent completing a task or navigating an app.
For games, it might be a time spent playing the game or remaining logged in.
For retail, it might be checking out or walking the premises.

This guide on sessionization is inspired by [_The Expressions API in Polars is Amazing_](https://www.pola.rs/posts/the-expressions-api-in-polars-is-amazing/),
a blog post in the [Polars](https://www.pola.rs/) community demonstrating the strength of polars expressions.

## Sessionizing Logs on a Cadence

For this example, we have a dataset that contains entities polled on a cadence.
The data used here can be found at `https://storage.googleapis.com/ibis-tutorial-data/wowah_data/wowah_data.csv`.
You can use `ibis.read("https://storage.googleapis.com/ibis-tutorial-data/wowah_data/wowah_data.csv")` to quickly get it into a table expression.

Our data contains the following:

- `char` : a unique identifier for a character (or a player). This is our entity column
- `timestamp`: a timestamp denoting when a `char` was polled. This occurs every ~10 minutes

We can take this information, along with a definition of what separates two sessions for an entity, and break our dataset up into sessions **without using any joins**:

```python
# Imports
import ibis
from ibis import _ as c

# Read files into table expressions with ibis.read:
data = ibis.read("https://storage.googleapis.com/ibis-tutorial-data/wowah_data/wowah_data_raw.parquet")

# integer delay in seconds noting if a row should be included in the previous session for an entity
session_boundary_threshold = 30 * 60

# Window for finding session ids per character
entity_window = ibis.cumulative_window(group_by=c.char, order_by=c.timestamp)

# Take the previous timestamp within a window (by character ordered by timestamp):
# Note: the first value in a window will be null
ts_lag = c.timestamp.lag().over(entity_window)

# Subtract the lag from the current timestamp to get a timedelta
ts_delta = c.timestamp - ts_lag

# Compare timedelta to our session delay in seconds to determine if the
# current timestamp falls outside of the session.
# Cast as int for aggregation
is_new_session = (ts_delta > ibis.interval(seconds=session_boundary_threshold))

# Window for finding session min/max
session_window = ibis.window(group_by=[c.char, c.session_id])

# Generate all of the data we need to analyze sessions:
sessionized = (
data
# Create a session id for each character by using a cumulative sum
# over the `new_session` column
.mutate(new_session=is_new_session.fillna(True))
# Create a session id for each character by using a cumulative sum
# over the `new_session` column
.mutate(session_id=c.new_session.sum().over(entity_window))
# Drop `new_session` because it is no longer needed
.drop("new_session")
.mutate(
# Get session duration using max(timestamp) - min(timestamp) over our window
session_duration=c.timestamp.max().over(session_window) - c.timestamp.min().over(session_window)
)
# Sort for convenience
.order_by([c.char, c.timestamp])
)
```
70 changes: 51 additions & 19 deletions docs/how_to/topk.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Compute the Top K Records
# How to Compute the Top K Records

<!-- prettier-ignore-start -->
Here we use the [`topk`][ibis.expr.types.Column.topk] method to compute the top
Expand All @@ -10,28 +10,60 @@ Here we use the [`topk`][ibis.expr.types.Column.topk] method to compute the top

```python
>>> import ibis

>>> ibis.options.interactive = True

>>> con = ibis.duckdb.connect() # in-memory duckdb

>>> con.raw_sql("CALL dbgen(sf=0.1)")

>>> orders = con.table("orders")

>>> orders.o_custkey.topk(5) # top 5 most frequent customers
o_custkey count
0 11998 36
1 8761 36
2 3151 35
3 388 35
4 8362 35
┏━━━━━━━━━━━┳━━━━━━━┓
┃ o_custkey ┃ count ┃
┡━━━━━━━━━━━╇━━━━━━━┩
!int32 │ int64 │
├───────────┼───────┤
876136
1199836
315135
836235
38835
└───────────┴───────┘
>>> topk = orders.o_custkey.topk(5, by=orders.o_totalprice.sum()) # top 5 largest spending customers
>>> topk
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┓
┃ o_custkey ┃ sum
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━┩
!int32 │ decimal(38, 2) │
├───────────┼────────────────┤
83625793605.05
69585370682.19
94545354381.81
3465323350.43
103545227957.24
└───────────┴────────────────┘
```

>>> orders.o_custkey.topk(5, by=orders.o_totalprice.sum()) # top 5 largest spending customers
o_custkey sum
0 8362 5793605.05
1 6958 5370682.19
2 9454 5354381.81
3 346 5323350.43
4 10354 5227957.24
<!-- prettier-ignore-start -->
You can also use [`topk`][ibis.expr.types.Column.topk] to retrieve the rows
from the original table that match the key used, in this case `o_custkey`. This
is done with a left semi join:
<!-- prettier-ignore-end -->

```python
>>> orders.semi_join(topk, "o_custkey")
┏━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ o_orderkey ┃ o_custkey ┃ o_orderstatus ┃ o_totalprice ┃ o_orderdate ┃ o_orderpriority ┃ o_clerk ┃ o_shippriority ┃ o_comment ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
!int32 │ !int32 │ !string │ !decimal(15, 2) │ !date │ !string │ !string │ !int32 │ !string │
├────────────┼───────────┼───────────────┼─────────────────┼─────────────┼─────────────────┼─────────────────┼────────────────┼──────────────────────────────────────────────────────────────┤
40006958 │ F │ 115722.851992-01-045-LOW │ Clerk#000000339 │ 0 │ le carefully closely even pinto beans. regular, ironic foxe… │
144028362 │ F │ 131557.791993-10-153-MEDIUM │ Clerk#000000672 │ 0 │ azzle slyly. carefully regular instructions affix carefully… │
1478410354 │ F │ 216307.341992-03-153-MEDIUM │ Clerk#000000479 │ 0 │ lyly final theodoli │
1741510354 │ O │ 110427.401996-09-182-HIGH │ Clerk#000000148 │ 0 │ . furiously even asymptotes wake carefully according to t │
177609454 │ F │ 167249.601992-06-054-NOT SPECIFIED │ Clerk#000000093 │ 0 │ uriously final pinto beans wake furiously │
188539454 │ F │ 163677.191993-01-181-URGENT │ Clerk#000000046 │ 0 │ sts. courts haggle furiously. even, enticing depo │
213178362 │ P │ 267386.981995-04-105-LOW │ Clerk#000000737 │ 0 │ Tiresias. accounts a │
231388362 │ O │ 174882.011997-07-231-URGENT │ Clerk#000000253 │ 0 │ uctions integrate carefully regular pinto beans. silent acc… │
2397210354 │ F │ 129646.661993-08-174-NOT SPECIFIED │ Clerk#000001000 │ 0 │ s. blithely final packages sleep quickly idle pearls. even,… │
24064346 │ F │ 147095.221993-07-263-MEDIUM │ Clerk#000000020 │ 0 │ ithely final foxes. furiously final instructi │
│ … │ … │ … │ … │ … │ … │ … │ … │ … │
└────────────┴───────────┴───────────────┴─────────────────┴─────────────┴─────────────────┴─────────────────┴────────────────┴──────────────────────────────────────────────────────────────┘
```
4,332 changes: 4,332 additions & 0 deletions docs/ibis-for-pandas-users.ipynb

Large diffs are not rendered by default.

45 changes: 3 additions & 42 deletions docs/ibis-for-sql-programmers.ipynb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

232 changes: 37 additions & 195 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,215 +1,57 @@
---
hide:
- toc
- navigation
- footer
---

# :ibis-logo: Ibis
# <span style="font-size: 1.5em; margin: 0">:ibis-logo: The Ibis Project</span>

## Expressive analytics in Python at any scale.
## The flexibility of Python analytics with the scale and performance of modern SQL.

<script
src="https://asciinema.org/a/yp5Ww4XKyjJsUCXkEz5or9rPq.js"
data-autoplay="true"
data-preload="true"
data-loop="true"
data-i="4"
data-rows="20"
id="asciicast-yp5Ww4XKyjJsUCXkEz5or9rPq"
async>
</script>

## Installation

=== "pip"

```sh
pip install ibis-framework
```

{% for mgr in ["conda", "mamba"] %}
=== "{{ mgr }}"

```sh
{{ mgr }} install -c conda-forge ibis-framework
```

{% endfor %}

Try it out!

```python
python -c 'import ibis; print(ibis.__version__)'
```

## Features

### SQL Coverage

#### Anything you can write in a `SELECT` statement you can write in Ibis.

=== "Group By"

##### SQL

```sql
SELECT f, sum(a + b) AS d
FROM t
GROUP BY f
```

##### Ibis

```python
t.group_by("f").aggregate(d=t.a + t.b.sum())
```

=== "Join"

##### SQL

```sql
SELECT exp(t.a) AS d
FROM t
LEFT SEMI JOIN s
ON t.x = t.y
```

##### Ibis

```python
t.semi_join(s, t.x == t.y).select([lambda t: t.a.exp().name("d")])
```

=== "Window Functions"

##### SQL

```sql
SELECT *, avg(x) OVER (PARTITION BY y) as z
FROM t
```

##### Ibis

```python
t.group_by("y").mutate(z=t.x.avg())
```

!!! tip "Coming from SQL?"

Check out [Ibis for SQL Programmers](ibis-for-sql-programmers)

### Abstract Over SQL Dialects

#### No more rewrites when scaling up or down.

=== "SQLite"

```python
con = ibis.sqlite.connect("my_sqlite.db")
```

=== "PostgreSQL"

```python
con = ibis.postgres.connect(user="me", host="my_computer", port=9090)
```
---

=== "BigQuery"
<div class="install-tutorial-button" markdown>
[Install](./install.md){ .md-button .md-button--primary }
[Tutorial](./tutorial/index.md){ .md-button }
</div>

```python
con = ibis.bigquery.connect(project_id="my_project_id", dataset_id="my_dataset_id")
```
---

```python
t = con.table("t")
t.group_by("y").mutate(z=t.x.avg())
```python title="Write high-level Python code"
>>> import ibis
>>> con = ibis.connect('movielens.sqlite')
>>> movies = con.tables.movies
>>> rating_by_year = movies.group_by('year').avg_rating.mean()
>>> q = rating_by_year.order_by(rating_by_year.year.desc())
```

### Ecosystem

#### Ibis builds on top of and works with existing Python tools.
```py title="Compile to SQL"
>>> con.compile(q)

```python
t.semi_join(s, t.x == t.y).select([lambda t: t.a.exp().name("d")]).head(2)
df = expr.execute() # a pandas DataFrame!
SELECT year, avg(avg_rating)
FROM movies t1
GROUP BY t1.year
ORDER BY t1.year DESC
```

## Example
```py title="Execute on multiple backends"
>>> con.execute(q)

Let's compute the number of citizens per squared kilometer in Asia:

```python
>>> import ibis
>>> db = ibis.sqlite.connect("geography.db")
>>> countries = db.table("countries")
>>> asian_countries = countries.filter(countries.continent == "AS")
>>> density_in_asia = asian_countries.population.sum() / asian_countries.area_km2.sum()
>>> density_in_asia.execute()
130.7019141926602
year mean(avg_rating)
0 2021 2.586362
1 2020 2.719994
2 2019 2.932275
3 2018 3.005046
4 2017 3.071669
```

!!! tip "Learn more!"

Learn more about Ibis in [our tutorial](tutorial/01-Introduction-to-Ibis).

## Comparison to other tools

=== "SQL"

!!! tip "Coming from SQL?"

Check out [Ibis for SQL Programmers](ibis-for-sql-programmers)!

Ibis gives you the benefit of a programming language. You don't need to
sacrifice maintainability to get to those insights!

=== "Ibis"

``` py title="docs/example.py" linenums="1"
--8<-- "docs/example.py"
```

=== "SQL"

``` sql title="docs/example.sql" linenums="1"
--8<-- "docs/example.sql"
```

=== "SQLAlchemy"

Ibis aims to be more concise and composable than
[SQLAlchemy](https://www.sqlalchemy.org/) when writing interactive
analytics code.

!!! success "Ibis :heart:'s SQLAlchemy"

Ibis generates SQLAlchemy expressions for some of our backends
including the [PostgreSQL](./backends/PostgreSQL.md) and
[SQLite](./backends/SQLite.md) backends!

=== "Ibis"

``` py title="docs/example.py" linenums="1"
--8<-- "docs/example.py"
```

=== "SQLAlchemy"

``` py title="docs/sqlalchemy_example.py" "linenums="1"
--8<-- "docs/sqlalchemy_example.py"
```

<div class="download-button" markdown>
[:fontawesome-solid-cloud-arrow-down: Download the example data](https://storage.googleapis.com/ibis-testing-data/crunchbase.db){ .md-button .md-button--primary }
</div>

## What's Next?

!!! question "Need a specific backend?"

Take a look at the [backends](./backends/index.md) documentation!
---

!!! tip "Interested in contributing?"
## Features

Get started by [setting up a development environment](./contribute/01_environment.md)!
- **Consistent syntax across backends**: Enjoy a uniform Python API, whether using [DuckDB](https://duckdb.org), [PostgreSQL](https://postgresql.org), [PySpark](https://spark.apache.org/docs/latest/api/python/index.html), [BigQuery](https://cloud.google.com/bigquery/), or [any other supported backend](./backends/index.md).
- **Performant**: Execute queries as fast as the database engine itself.
- **Interactive**: Explore data in a notebook or REPL.
- **Extensible**: Add new operations, optimizations, and custom APIs.
- **Free and open-source**: licensed under Apache 2.0, [available on Github](https://github.com/ibis-project/ibis/blob/master/README.md)
44 changes: 44 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
hide:
- toc
- navigation
- footer
---

# Install Ibis

=== "pip"

```sh
pip install ibis-framework # (1)
```

1. Note that the `ibis-framework` package is *not* the same as the `ibis` package in PyPI. These two libraries cannot coexist in the same Python environment, as they are both imported with the `ibis` module name.

{% for mgr in ["conda", "mamba"] %}
=== "{{ mgr }}"

```sh
{{ mgr }} install -c conda-forge ibis-framework
```

{% endfor %}

## Install backend dependencies

{% for backend in sorted(ibis.backends.base._get_backend_names()) %}
=== "{{ backend }}"

```sh
pip install 'ibis-framework[{{ backend }}]'
```

{% endfor %}

---

After you've successfully installed Ibis, try going through the tutorial:

<div class="install-tutorial-button" markdown>
[Go to the Tutorial](./tutorial/index.md){ .md-button .md-button--primary }
</div>
Loading