Skip to content

Conversation

@NickCrews
Copy link
Contributor

This allows for pleasant UX such as

  • ibis.dtype(ibis.ir.StringValue)
  • ibis.dtype(ibis.ir.IntegerValue["!uint32"])
class Users(ibis.Table):
    name: ibis.ir.StringColumn
    age: ibis.ir.IntegerColumn["uint8"]

def my_api(users: Users):
    # Runtime coercion of types works as expected!
    users = ibis.cast(users, Users)
    # IDE type hints work too!
    reveal_type(users.age) # Its an IntegerColumn!

I also adjusted the ibis.dtype() function so that the nullable kwarg defaults to None, which means "Don't mess with the nullability of something that is already a dtype". I can put this into a separate PR if desired, but I think this is a good change to make anyways.
The current behavior of dtype(nonnullable_dtype, nullable=True) returning the original input, still nonnullable, is a footgun.

@github-actions github-actions bot added tests Issues or PRs related to tests datatypes Issues relating to ibis's datatypes (under `ibis.expr.datatypes`) labels Sep 10, 2025
@NickCrews NickCrews force-pushed the paramaterized-expr-types branch from 9cb1ca7 to 6381b1b Compare October 16, 2025 19:43
@NickCrews
Copy link
Contributor Author

This is effectively adding a Protocol to ibis, where anything that has a .__dtype__ attribute, ibis will prefer to get the datatype from that attribute. I think this is in general a good idea. I am thinking we could do this for other ibis APIs as well, eg ibis.schema() will first look for a .__schema__ attribute and prefer that if it exists. Not sure if there are other places where this would make sense.

It might be a good idea to make these attributes to be better namespaced, eg __ibis_dtype__ and __ibis_schema__.

@NickCrews
Copy link
Contributor Author

@deepyaman Do you have any thoughts here?

This allows for pleasant UX such as
- ibis.dtype(ibis.ir.StringValue)
- ibis.dtype(ibis.ir.IntegerValue["!uint32"])

```python
class Users(ibis.Table):
    name: ibis.ir.StringColumn
    age: ibis.ir.IntegerColumn["uint8"]

def my_api(users: Users):
    # Runtime coercion of types works as expected!
    users = ibis.cast(users, Users)
    # IDE type hints work too!
    reveal_type(users.age) # Its an IntegerColumn!
```

I also adjusted the ibis.dtype() function so that the nullable kwarg defaults to None, which means "Don't mess with the nullability of something that is already a dtype". I can put this into a separate PR if desired, but I think this is a good change to make anyways.
The current behavior of `dtype(nonnullable_dtype, nullable=True)` returning the original input, still nonnullable, is a footgun.
@NickCrews NickCrews force-pushed the paramaterized-expr-types branch from 6381b1b to f5be1d0 Compare October 17, 2025 03:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

datatypes Issues relating to ibis's datatypes (under `ibis.expr.datatypes`) tests Issues or PRs related to tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant