Skip to content

Commit

Permalink
refactor(api): use as_* for type coercion methods
Browse files Browse the repository at this point in the history
  • Loading branch information
ncclementi committed Aug 14, 2024
1 parent 1d64e58 commit 5500e75
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 77 deletions.
41 changes: 30 additions & 11 deletions ibis/backends/tests/test_temporal.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ def test_date_truncate(backend, alltypes, df, unit):
def test_integer_to_interval_timestamp(
backend, con, alltypes, df, unit, displacement_type
):
interval = alltypes.int_col.to_interval(unit=unit)
interval = alltypes.int_col.as_interval(unit=unit)
expr = (alltypes.timestamp_col + interval).name("tmp")

def convert_to_offset(offset, displacement_type=displacement_type):
Expand Down Expand Up @@ -663,7 +663,7 @@ def convert_to_offset(offset, displacement_type=displacement_type):
@pytest.mark.notimpl(["datafusion", "druid"], raises=com.OperationNotDefinedError)
@pytest.mark.notimpl(["exasol"], raises=com.OperationNotDefinedError)
def test_integer_to_interval_date(backend, con, alltypes, df, unit):
interval = alltypes.int_col.to_interval(unit=unit)
interval = alltypes.int_col.as_interval(unit=unit)
month = alltypes.date_string_col[:2]
day = alltypes.date_string_col[3:5]
year = alltypes.date_string_col[6:8]
Expand Down Expand Up @@ -1182,11 +1182,18 @@ def test_integer_to_timestamp(backend, con, unit):

# convert the timestamp to the input unit being tested
int_expr = ibis.literal(pandas_ts // factor)
expr = int_expr.to_timestamp(unit).name("tmp")
result = con.execute(expr)
expr_as = int_expr.as_timestamp(unit).name("tmp")
result_as = con.execute(expr_as)

with pytest.warns(FutureWarning, match="v10.0"):
expr_to = int_expr.to_timestamp(unit).name("tmp")

result_to = con.execute(expr_to)

expected = pd.Timestamp(pandas_ts, unit="ns").floor(backend_unit)

assert result == expected
assert result_as == expected
assert result_to == expected


@pytest.mark.parametrize(
Expand Down Expand Up @@ -1260,12 +1267,18 @@ def test_integer_to_timestamp(backend, con, unit):
@pytest.mark.notimpl(["exasol"], raises=com.OperationNotDefinedError)
def test_string_to_timestamp(alltypes, fmt):
table = alltypes
result = table.mutate(date=table.date_string_col.to_timestamp(fmt)).execute()
result_as = table.mutate(date=table.date_string_col.as_timestamp(fmt)).execute()

with pytest.warns(FutureWarning, match="v10.0"):
result_to = table.mutate(date=table.date_string_col.to_timestamp(fmt)).execute()

# TEST: do we get the same date out, that we put in?
# format string assumes that we are using pandas' strftime
for i, val in enumerate(result["date"]):
assert val.strftime("%m/%d/%y") == result["date_string_col"][i]
for i, val in enumerate(result_as["date"]):
assert val.strftime("%m/%d/%y") == result_as["date_string_col"][i]

for i, val in enumerate(result_to["date"]):
assert val.strftime("%m/%d/%y") == result_to["date_string_col"][i]


@pytest.mark.parametrize(
Expand Down Expand Up @@ -1339,12 +1352,18 @@ def test_string_to_timestamp(alltypes, fmt):
@pytest.mark.notimpl(["exasol"], raises=com.OperationNotDefinedError)
def test_string_to_date(alltypes, fmt):
table = alltypes
result = table.mutate(date=table.date_string_col.to_date(fmt)).execute()
result_as = table.mutate(date=table.date_string_col.as_date(fmt)).execute()

with pytest.warns(FutureWarning, match="v10.0"):
result_to = table.mutate(date=table.date_string_col.to_date(fmt)).execute()

# TEST: do we get the same date out, that we put in?
# format string assumes that we are using pandas' strftime
for i, val in enumerate(result["date"]):
assert val.strftime("%m/%d/%y") == result["date_string_col"][i]
for i, val in enumerate(result_as["date"]):
assert val.strftime("%m/%d/%y") == result_as["date_string_col"][i]

for i, val in enumerate(result_as["date"]):
assert val.strftime("%m/%d/%y") == result_to["date_string_col"][i]


@pytest.mark.parametrize(
Expand Down
19 changes: 17 additions & 2 deletions ibis/expr/types/numeric.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from ibis.common.exceptions import IbisTypeError
from ibis.expr.types.core import _binop
from ibis.expr.types.generic import Column, Scalar, Value
from ibis.util import deprecated

if TYPE_CHECKING:
from collections.abc import Iterable, Sequence
Expand Down Expand Up @@ -1013,7 +1014,7 @@ def histogram(

@public
class IntegerValue(NumericValue):
def to_timestamp(
def as_timestamp(
self,
unit: Literal["s", "ms", "us"] = "s",
) -> ir.TimestampValue:
Expand All @@ -1031,7 +1032,7 @@ def to_timestamp(
"""
return ops.TimestampFromUNIX(self, unit).to_expr()

def to_interval(
def as_interval(
self,
unit: Literal["Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns"] = "s",
) -> ir.IntervalValue:
Expand All @@ -1049,6 +1050,20 @@ def to_interval(
"""
return ops.IntervalFromInteger(self, unit).to_expr()

@deprecated(as_of="10.0", instead="use as_timestamp() instead")
def to_timestamp(
self,
unit: Literal["s", "ms", "us"] = "s",
) -> ir.TimestampValue:
return self.as_timestamp(unit=unit)

@deprecated(as_of="10.0", instead="use as_interval() instead")
def to_interval(
self,
unit: Literal["Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns"] = "s",
) -> ir.IntervalValue:
return self.as_interval(unit=unit)

def convert_base(
self,
from_base: IntegerValue,
Expand Down
17 changes: 13 additions & 4 deletions ibis/expr/types/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from ibis import util
from ibis.expr.types.core import _binop
from ibis.expr.types.generic import Column, Scalar, Value
from ibis.util import deprecated

if TYPE_CHECKING:
from collections.abc import Iterable, Sequence
Expand Down Expand Up @@ -1269,7 +1270,7 @@ def replace(
"""
return ops.StringReplace(self, pattern, replacement).to_expr()

def to_timestamp(self, format_str: str) -> ir.TimestampValue:
def as_timestamp(self, format_str: str) -> ir.TimestampValue:
"""Parse a string and return a timestamp.
Parameters
Expand All @@ -1287,7 +1288,7 @@ def to_timestamp(self, format_str: str) -> ir.TimestampValue:
>>> import ibis
>>> ibis.options.interactive = True
>>> t = ibis.memtable({"ts": ["20170206"]})
>>> t.ts.to_timestamp("%Y%m%d")
>>> t.ts.as_timestamp("%Y%m%d")
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ StringToTimestamp(ts, '%Y%m%d') ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
Expand All @@ -1298,7 +1299,11 @@ def to_timestamp(self, format_str: str) -> ir.TimestampValue:
"""
return ops.StringToTimestamp(self, format_str).to_expr()

def to_date(self, format_str: str) -> ir.DateValue:
@deprecated(as_of="10.0", instead="use as_timestamp() instead")
def to_timestamp(self, format_str: str) -> ir.TimestampValue:
return self.as_timestamp(format_str=format_str)

def as_date(self, format_str: str) -> ir.DateValue:
"""Parse a string and return a date.
Parameters
Expand All @@ -1316,7 +1321,7 @@ def to_date(self, format_str: str) -> ir.DateValue:
>>> import ibis
>>> ibis.options.interactive = True
>>> t = ibis.memtable({"ts": ["20170206"]})
>>> t.ts.to_date("%Y%m%d")
>>> t.ts.as_date("%Y%m%d")
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ StringToDate(ts, '%Y%m%d') ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
Expand All @@ -1327,6 +1332,10 @@ def to_date(self, format_str: str) -> ir.DateValue:
"""
return ops.StringToDate(self, format_str).to_expr()

@deprecated(as_of="10.0", instead="use as_timestamp() instead")
def to_date(self, format_str: str) -> ir.DateValue:
return self.as_date(format_str=format_str)

def protocol(self):
"""Parse a URL and extract protocol.
Expand Down
31 changes: 18 additions & 13 deletions ibis/expr/types/temporal.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from ibis.common.temporal import IntervalUnit
from ibis.expr.types.core import _binop
from ibis.expr.types.generic import Column, Scalar, Value
from ibis.util import deprecated

if TYPE_CHECKING:
import datetime
Expand Down Expand Up @@ -822,7 +823,7 @@ class TimestampColumn(Column, TimestampValue):

@public
class IntervalValue(Value):
def to_unit(self, target_unit: str) -> IntervalValue:
def as_unit(self, target_unit: str) -> IntervalValue:
"""Convert this interval to units of `target_unit`."""
# TODO(kszucs): should use a separate operation for unit conversion
# which we can rewrite/simplify to integer multiplication/division
Expand All @@ -839,62 +840,66 @@ def to_unit(self, target_unit: str) -> IntervalValue:
value = util.convert_unit(
self.cast(dt.int64), current_unit.short, target_unit.short
)
return value.to_interval(target_unit)
return value.as_interval(target_unit)

@deprecated(as_of="10.0", instead="use as_unit() instead")
def to_unit(self, target_unit: str) -> IntervalValue:
return self.as_unit(target_unit=target_unit)

@property
def years(self) -> ir.IntegerValue:
"""The number of years (IntegerValue)."""
return self.to_unit("Y")
return self.as_unit("Y")

@property
def quarters(self) -> ir.IntegerValue:
"""The number of quarters (IntegerValue)."""
return self.to_unit("Q")
return self.as_unit("Q")

@property
def months(self) -> ir.IntegerValue:
"""The number of months (IntegerValue)."""
return self.to_unit("M")
return self.as_unit("M")

@property
def weeks(self) -> ir.IntegerValue:
"""The number of weeks (IntegerValue)."""
return self.to_unit("W")
return self.as_unit("W")

@property
def days(self) -> ir.IntegerValue:
"""The number of days (IntegerValue)."""
return self.to_unit("D")
return self.as_unit("D")

@property
def hours(self) -> ir.IntegerValue:
"""The number of hours (IntegerValue)."""
return self.to_unit("h")
return self.as_unit("h")

@property
def minutes(self) -> ir.IntegerValue:
"""The number of minutes (IntegerValue)."""
return self.to_unit("m")
return self.as_unit("m")

@property
def seconds(self) -> ir.IntegerValue:
"""The number of seconds (IntegerValue)."""
return self.to_unit("s")
return self.as_unit("s")

@property
def milliseconds(self) -> ir.IntegerValue:
"""The number of milliseconds (IntegerValue)."""
return self.to_unit("ms")
return self.as_unit("ms")

@property
def microseconds(self) -> ir.IntegerValue:
"""The number of microseconds (IntegerValue)."""
return self.to_unit("us")
return self.as_unit("us")

@property
def nanoseconds(self) -> ir.IntegerValue:
"""The number of nanoseconds (IntegerValue)."""
return self.to_unit("ns")
return self.as_unit("ns")

def __add__(
self,
Expand Down
Loading

0 comments on commit 5500e75

Please sign in to comment.