Skip to content

Commit

Permalink
feat(api): add catalog and database kwargs to ibis.table (ibis-…
Browse files Browse the repository at this point in the history
  • Loading branch information
gforsyth authored Mar 28, 2024
1 parent f59f423 commit 7d593c4
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 2 deletions.
31 changes: 30 additions & 1 deletion ibis/expr/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,15 +313,25 @@ def schema(
def table(
schema: SchemaLike | None = None,
name: str | None = None,
catalog: str | None = None,
database: str | None = None,
) -> ir.Table:
"""Create a table literal or an abstract table without data.
Ibis uses the word database to refer to a collection of tables, and the word
catalog to refer to a collection of databases. You can use a combination of
`catalog` and `database` to specify a hierarchical location for table.
Parameters
----------
schema
A schema for the table
name
Name for the table. One is generated if this value is `None`.
catalog
A collection of database.
database
A collection of tables. Required if catalog is not `None`.
Returns
-------
Expand All @@ -340,13 +350,32 @@ def table(
a int64
b string
Create a table with no data backing it in a specific location
>>> import ibis
>>> ibis.options.interactive = False
>>> t = ibis.table(schema=dict(a="int"), name="t", catalog="cat", database="db")
>>> t
UnboundTable: cat.db.t
a int64
"""
if name is None:
if isinstance(schema, type):
name = schema.__name__
else:
name = next(_table_names)
return ops.UnboundTable(name=name, schema=schema).to_expr()
if catalog is not None and database is None:
raise ValueError(
"A catalog-only namespace is invalid in Ibis, "
"please specify a database as well."
)

return ops.UnboundTable(
name=name,
schema=schema,
namespace=ops.Namespace(catalog=catalog, database=database),
).to_expr()


def memtable(
Expand Down
8 changes: 8 additions & 0 deletions ibis/expr/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@ def _physical_table(op, name, **kwargs):
return f"{op.__class__.__name__}: {name}\n{schema}"


@fmt.register(ops.UnboundTable)
@fmt.register(ops.DatabaseTable)
def _unbound_table(op, name, **kwargs):
schema = render_schema(op.schema, indent_level=1)
name = ".".join(filter(None, op.namespace.args + (name,)))
return f"{op.__class__.__name__}: {name}\n{schema}"


@fmt.register(ops.InMemoryTable)
def _in_memory_table(op, data, **kwargs):
import rich.pretty
Expand Down
2 changes: 1 addition & 1 deletion ibis/expr/operations/relations.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,8 @@ class PhysicalTable(Relation):

@public
class Namespace(Concrete):
database: Optional[str] = None
catalog: Optional[str] = None
database: Optional[str] = None


@public
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
UnboundTable: bork
a int64
b int64
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
UnboundTable: ork.bork.bork
a int64
b int64
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
UnboundTable: bork.bork
a int64
b int64
15 changes: 15 additions & 0 deletions ibis/expr/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,18 @@ def test_nested_name_property():
x = x + 1

assert x.op().name.count("Add") == n


def test_unbound_table_namespace():
t = ibis.table(name="bork", schema=(("a", "int"), ("b", "int")), database="bork")

assert t.op().namespace == ops.Namespace(database="bork")

t = ibis.table(
name="bork", schema=(("a", "int"), ("b", "int")), database="bork", catalog="ork"
)

assert t.op().namespace == ops.Namespace(catalog="ork", database="bork")

with pytest.raises(ValueError, match="A catalog-only namespace is invalid in Ibis"):
ibis.table(name="bork", schema=(("a", "int"), ("b", "int")), catalog="bork")
19 changes: 19 additions & 0 deletions ibis/expr/tests/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,25 @@ def test_format_in_memory_table(snapshot):
snapshot.assert_match(result, "repr.txt")


def test_format_unbound_table_namespace(snapshot):
t = ibis.table(name="bork", schema=(("a", "int"), ("b", "int")))

result = fmt(t)
snapshot.assert_match(result, "repr.txt")

t = ibis.table(name="bork", schema=(("a", "int"), ("b", "int")), database="bork")

result = fmt(t)
snapshot.assert_match(result, "reprdb.txt")

t = ibis.table(
name="bork", schema=(("a", "int"), ("b", "int")), catalog="ork", database="bork"
)

result = fmt(t)
snapshot.assert_match(result, "reprcatdb.txt")


def test_format_new_relational_operation(alltypes, snapshot):
class MyRelation(ops.Relation):
parent: ops.Relation
Expand Down

0 comments on commit 7d593c4

Please sign in to comment.