Skip to content

Commit

Permalink
feat(api): add toplevel ibis.connect()
Browse files Browse the repository at this point in the history
  • Loading branch information
Saul Pwanson authored and cpcloud committed Jul 5, 2022
1 parent 75bded1 commit e13946b
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 1 deletion.
95 changes: 94 additions & 1 deletion ibis/backends/base/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from __future__ import annotations

import abc
import functools
import re
from pathlib import Path
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Iterable, Mapping

if TYPE_CHECKING:
Expand All @@ -15,10 +17,11 @@
import ibis.expr.operations as ops
import ibis.expr.schema as sch
import ibis.expr.types as ir
from ibis.common.dispatch import RegexDispatcher
from ibis.common.exceptions import TranslationError
from ibis.util import deprecated

__all__ = ('BaseBackend', 'Database')
__all__ = ('BaseBackend', 'Database', 'connect')


class Database:
Expand Down Expand Up @@ -593,3 +596,93 @@ def has_operation(cls, operation: type[ops.Value]) -> bool:
raise NotImplementedError(
f"{cls.name} backend has not implemented `has_operation` API"
)


_connect = RegexDispatcher("_connect")


@_connect.register(r"(?P<backend>.+)://(?P<path>.*)", priority=10)
def _(_: str, *, backend: str, path: str, **kwargs: Any) -> BaseBackend:
"""Connect to given `backend` with `path`.
Examples
--------
>>> con = ibis.connect("duckdb://relative/path/to/data.db")
>>> con = ibis.connect("postgres://user:pass@hostname:port/database")
"""
instance = getattr(ibis, backend)
backend += (backend == "postgres") * "ql"
try:
return instance.connect(url=f"{backend}://{path}", **kwargs)
except TypeError:
return instance.connect(path, **kwargs)


@_connect.register(r"file://(?P<path>.*)", priority=10)
def _(_: str, *, path: str, **kwargs: Any) -> BaseBackend:
"""Connect to file located at `path`."""
return _connect(path, **kwargs)


@_connect.register(r".+\.(?P<backend>.+)", priority=1)
def _(path: str, *, backend: str, **kwargs: Any) -> BaseBackend:
"""Connect to given path.
The extension is assumed to be the name of an ibis backend.
Examples
--------
>>> con = ibis.connect("file://relative/path/to/data.duckdb")
"""
return getattr(ibis, backend).connect(path, **kwargs)


@functools.singledispatch
def connect(resource: Path | str, **_: Any) -> BaseBackend:
"""Connect to `resource`.
`resource` can be a `pathlib.Path` or a `str` specifying a URL or path.
Examples
--------
>>> con = ibis.connect("duckdb://relative/path/to/data.db")
>>> con = ibis.connect("relative/path/to/data.duckdb")
"""
raise NotImplementedError(type(resource))


@connect.register
def _(path: Path, **kwargs: Any) -> BaseBackend:
return _connect(str(path), **kwargs)


@connect.register
def _(url: str, **kwargs: Any) -> BaseBackend:
return _connect(url, **kwargs)


@_connect.register(
r"(?P<backend>.+)://(?P<filename>.+\.(?P<extension>.+))",
priority=11,
)
def _(
_: str,
*,
backend: str,
filename: str,
extension: str,
**kwargs: Any,
) -> BaseBackend:
"""Connect to `backend` and register a file.
The extension of the file will be used to register the file with
the backend.
Examples
--------
>>> con = ibis.connect("duckdb://relative/path/to/data.csv")
>>> con = ibis.connect("duckdb://relative/path/to/more/data.parquet")
"""
con = getattr(ibis, backend).connect(**kwargs)
con.register(f"{extension}://{filename}")
return con
2 changes: 2 additions & 0 deletions ibis/expr/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import ibis.expr.operations as ops
import ibis.expr.schema as sch
import ibis.expr.types as ir
from ibis.backends.base import connect
from ibis.expr.deferred import Deferred
from ibis.expr.random import random
from ibis.expr.schema import Schema
Expand Down Expand Up @@ -115,6 +116,7 @@
'array',
'case',
'coalesce',
'connect',
'cross_join',
'cumulative_window',
'date',
Expand Down

0 comments on commit e13946b

Please sign in to comment.