Skip to content

Commit

Permalink
Merge pull request #542 from pfackeldey/feat/align_array_behavior_of_…
Browse files Browse the repository at this point in the history
…_bool_nonzero_long_int_float_complex_index__with_dask

[feat] Explicitly raise `TracerConversionError` when a tracer is used in a context that requires a concrete value
  • Loading branch information
martindurant authored Sep 11, 2024
2 parents fdb03f6 + 235c7c6 commit dba2d37
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 4 deletions.
23 changes: 23 additions & 0 deletions docs/api/utils.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Errors
------

Utilities to implement array behaviors for dask-awkward arrays.


.. currentmodule:: dask_awkward


.. autosummary::
:toctree: generated/

utils.IncompatiblePartitions

.. autosummary::
:toctree: generated/

utils.ConcretizationTypeError

.. raw:: html

<script data-goatcounter="https://dask-awkward.goatcounter.com/count"
async src="//gc.zgo.at/count.js"></script>
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Table of Contents
api/reducers.rst
api/structure.rst
api/behavior.rst
api/utils.rst

.. toctree::
:maxdepth: 1
Expand Down
18 changes: 18 additions & 0 deletions src/dask_awkward/lib/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from dask_awkward.layers import AwkwardBlockwiseLayer, AwkwardMaterializedLayer
from dask_awkward.lib.optimize import all_optimizations
from dask_awkward.utils import (
ConcretizationTypeError,
DaskAwkwardNotImplemented,
IncompatiblePartitions,
field_access_to_front,
Expand Down Expand Up @@ -921,6 +922,23 @@ def __dask_postpersist__(self):

__dask_scheduler__ = staticmethod(threaded_get)

def __bool__(self):
raise ConcretizationTypeError(f"The __bool__() method was called on {self!r}.")

def __int__(self):
raise ConcretizationTypeError(f"The __int__() method was called on {self!r}.")

def __float__(self):
raise ConcretizationTypeError(f"The __float__() method was called on {self!r}.")

def __complex__(self):
raise ConcretizationTypeError(
f"The __complex__() method was called on {self!r}."
)

def __index__(self):
raise ConcretizationTypeError(f"The __index__() method was called on {self!r}.")

def __setitem__(self, where: Any, what: Any) -> None:
if not (
isinstance(where, str)
Expand Down
46 changes: 45 additions & 1 deletion src/dask_awkward/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
if TYPE_CHECKING:
from dask_awkward.lib.core import Array


T = TypeVar("T")
P = ParamSpec("P")

Expand Down Expand Up @@ -38,6 +37,51 @@ def divisions_msg(name: str, *args: Array) -> str:
return msg


class ConcretizationTypeError(TypeError):
"""
This error occurs when a ``dask_awkward.Array`` is used in a context that requires a concrete
value.
There are several reasons why this error might occur:
Examples
--------
- When a ``dask_awkward.Array`` is used in a conditional statement:
>>> import dask_awkward as dak
>>> import awkward as ak
>>> dask_arr = dak.from_awkward(ak.Array([1]), npartitions=1)
>>> if dask_arr > 2:
>>> dask_arr += 1
Traceback (most recent call last): ...
dask_awkward.utils.ConcretizationTypeError: A dask_awkward.Array is encountered in a computation where a concrete value is expected. If you intend to convert the dask_awkward.Array to a concrete value, use the `.compute()` method. The __bool__() method was called on dask.awkward<greater, npartitions=1>.
- When a ``dask_awkward.Array`` is cast to a Python type:
>>> import dask_awkward as dak
>>> import awkward as ak
>>> dask_arr = dak.from_awkward(ak.Array([1]), npartitions=1)
>>> int(dask_arr)
Traceback (most recent call last): ...
dask_awkward.utils.ConcretizationTypeError: A dask_awkward.Array is encountered in a computation where a concrete value is expected. If you intend to convert the dask_awkward.Array to a concrete value, use the `.compute()` method. The __int__() method was called on dask.awkward<from-awkward, npartitions=1>.
These errors can be resolved by explicitely converting the tracer to a concrete value:
>>> import dask_awkward as dak
>>> dask_arr = dak.from_awkward(ak.Array([1]), npartitions=1)
>>> bool(dask_arr.compute())
True
"""

def __init__(self, msg: str):
self.message = "A dask_awkward.Array is encountered in a computation where a concrete value is expected. "
self.message += "If you intend to convert the dask_awkward.Array to a concrete value, use the `.compute()` method. "
self.message += msg
super().__init__(self.message)


class LazyInputsDict(Mapping):
"""Dictionary with lazy key value pairs
Expand Down
15 changes: 14 additions & 1 deletion tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
typetracer_array,
)
from dask_awkward.lib.testutils import assert_eq
from dask_awkward.utils import IncompatiblePartitions
from dask_awkward.utils import ConcretizationTypeError, IncompatiblePartitions

if TYPE_CHECKING:
from dask_awkward.lib.core import Array
Expand Down Expand Up @@ -968,3 +968,16 @@ def test_map_partitions_bad_arguments():
array2,
meta=empty_typetracer(),
)


def test_array__bool_nonzero_long_int_float_complex_index():
import operator

dask_arr = dak.from_awkward(ak.Array([1]), npartitions=1)

for fun in bool, int, float, complex, operator.index:
with pytest.raises(
ConcretizationTypeError,
match=r"A dask_awkward.Array is encountered in a computation where a concrete value is expected. If you intend to convert the dask_awkward.Array to a concrete value, use the `.compute\(\)` method. The .+ method was called on .+.",
):
fun(dask_arr)
4 changes: 2 additions & 2 deletions tests/test_io_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ def test_json_sanity(json_data_dir: Path, concrete_data: ak.Array) -> None:
", use `\\.eager_compute_divisions\\(\\)` on the collection."
),
):
assert ds
assert len(ds)
ds.eager_compute_divisions()
assert ds
assert len(ds)

assert_eq(ds, concrete_data)

Expand Down

0 comments on commit dba2d37

Please sign in to comment.