Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing behaviour in ak._v2 functions #1415

Merged
merged 6 commits into from
Apr 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/awkward/_v2/operations/convert/ak_from_iter.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,5 @@ def _impl(iterable, highlevel, behavior, allow_record, initial, resize):
form = ak._v2.forms.from_json(formstr)

return ak._v2.operations.convert.from_buffers(
form, length, buffers, highlevel=highlevel
form, length, buffers, highlevel=highlevel, behavior=behavior
)
4 changes: 3 additions & 1 deletion src/awkward/_v2/operations/convert/ak_from_json_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ def _impl(
else:
length = 1

out = ak._v2.operations.convert.from_buffers(form, length, container)
out = ak._v2.operations.convert.from_buffers(
form, length, container, highlevel=highlevel, behavior=behavior
)

if schema.get("type") == "array":
return out
Expand Down
7 changes: 6 additions & 1 deletion src/awkward/_v2/operations/structure/ak_argcartesian.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,12 @@ def _impl(arrays, axis, nested, parameters, with_name, highlevel, behavior):
parameters["__record__"] = with_name

result = ak._v2.operations.structure.cartesian(
layouts, axis=axis, nested=nested, parameters=parameters, highlevel=False
layouts,
axis=axis,
nested=nested,
parameters=parameters,
highlevel=False,
behavior=behavior,
)

return ak._v2._util.wrap(result, behavior, highlevel)
13 changes: 11 additions & 2 deletions src/awkward/_v2/operations/structure/ak_broadcast_arrays.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def broadcast_arrays(*arrays, **kwargs):
right-broadcasting, as described below.
highlevel (bool, default is True): If True, return an #ak.Array;
otherwise, return a low-level #ak.layout.Content subclass.
behavior (None or dict): Custom #ak.behavior for the output array, if
high-level.
depth_limit (None or int, default is None): If None, attempt to fully
broadcast the `arrays` to all levels. If an int, limit the number
of dimensions that get broadcasted. The minimum value is `1`,
Expand Down Expand Up @@ -138,11 +140,18 @@ def broadcast_arrays(*arrays, **kwargs):


def _impl(arrays, kwargs):
(highlevel, depth_limit, left_broadcast, right_broadcast) = ak._v2._util.extra(
(
highlevel,
behavior,
depth_limit,
left_broadcast,
right_broadcast,
) = ak._v2._util.extra(
(),
kwargs,
[
("highlevel", True),
("behavior", None),
("depth_limit", None),
("left_broadcast", True),
("right_broadcast", True),
Expand All @@ -165,7 +174,7 @@ def action(inputs, depth, **kwargs):
else:
return None

behavior = ak._v2._util.behavior_of(*arrays)
behavior = ak._v2._util.behavior_of(*arrays, behavior=behavior)
out = ak._v2._broadcasting.broadcast_and_apply(
inputs,
action,
Expand Down
2 changes: 1 addition & 1 deletion src/awkward/_v2/operations/structure/ak_cartesian.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ def getfunction3(inputs, depth, **kwargs):
while len(toflatten) != 0:
flatten_axis = toflatten.pop()
result = ak._v2.operations.structure.flatten(
result, axis=flatten_axis, highlevel=False
result, axis=flatten_axis, highlevel=False, behavior=behavior
)

return ak._v2._util.wrap(result, behavior, highlevel)
4 changes: 2 additions & 2 deletions src/awkward/_v2/operations/structure/ak_strings_astype.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ def action(layout, **kwargs):
or layout.parameter("__array__") == "bytestring"
):
layout = ak._v2.operations.structure.without_parameters(
layout, highlevel=False
layout, highlevel=False, behavior=behavior
)
max_length = ak._v2.operations.reducers.max(
ak._v2.operations.structure.num(layout)
ak._v2.operations.structure.num(layout, behavior=behavior)
)
regulararray = layout.rpad(max_length, 1)
maskedarray = ak._v2.operations.convert.to_numpy(
Expand Down
2 changes: 1 addition & 1 deletion src/awkward/_v2/operations/structure/ak_unzip.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def check_for_union(layout, **kwargs):

elif isinstance(layout, ak._v2.contents.UnionArray):
for content in layout.contents:
if set(ak.operations.describe.fields(content)) != set(fields):
if set(ak._v2.operations.describe.fields(content)) != set(fields):
raise ak._v2._util.error(
ValueError("union of different sets of fields, cannot ak.unzip")
)
Expand Down
19 changes: 11 additions & 8 deletions src/awkward/_v2/operations/structure/ak_where.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ def where(condition, *args, **kwargs):
buffers with distinct types (using an #ak.layout.UnionArray8_64).
highlevel (bool, default is True): If True, return an #ak.Array;
otherwise, return a low-level #ak.layout.Content subclass.
behavior (None or dict): Custom #ak.behavior for the output array, if
high-level.

This function has a one-argument form, `condition` without `x` or `y`, and
a three-argument form, `condition`, `x`, and `y`. In the one-argument form,
Expand All @@ -36,16 +38,16 @@ def where(condition, *args, **kwargs):
for all `i`. The structure of `x` and `y` do not need to be the same; if
they are incompatible types, the output will have #ak.type.UnionType.
"""
mergebool, highlevel = ak._v2._util.extra(
(), kwargs, [("mergebool", True), ("highlevel", True)]
mergebool, highlevel, behavior = ak._v2._util.extra(
(), kwargs, [("mergebool", True), ("highlevel", True), ("behavior", None)]
)

if len(args) == 0:
with ak._v2._util.OperationErrorContext(
"ak._v2.where",
dict(condition=condition, mergebool=mergebool, highlevel=highlevel),
):
return _impl1(condition, mergebool, highlevel)
return _impl1(condition, mergebool, highlevel, behavior)

elif len(args) == 1:
raise ak._v2._util.error(
Expand All @@ -60,7 +62,7 @@ def where(condition, *args, **kwargs):
condition=condition, x=x, y=y, mergebool=mergebool, highlevel=highlevel
),
):
return _impl3(condition, x, y, mergebool, highlevel)
return _impl3(condition, x, y, mergebool, highlevel, behavior)

else:
raise ak._v2._util.error(
Expand All @@ -71,7 +73,7 @@ def where(condition, *args, **kwargs):
)


def _impl1(condition, mergebool, highlevel):
def _impl1(condition, mergebool, highlevel, behavior):
akcondition = ak._v2.operations.convert.to_layout(
condition, allow_record=False, allow_other=False
)
Expand All @@ -84,15 +86,16 @@ def _impl1(condition, mergebool, highlevel):
if highlevel:
return tuple(
ak._v2._util.wrap(
ak._v2.contents.NumpyArray(x), ak._v2._util.behavior_of(condition)
ak._v2.contents.NumpyArray(x),
ak._v2._util.behavior_of(condition, behavior=behavior),
)
for x in out
)
else:
return tuple(ak._v2.contents.NumpyArray(x) for x in out)


def _impl3(condition, x, y, mergebool, highlevel):
def _impl3(condition, x, y, mergebool, highlevel, behavior):
akcondition = ak._v2.operations.convert.to_layout(
condition, allow_record=False, allow_other=False
)
Expand Down Expand Up @@ -122,7 +125,7 @@ def action(inputs, **kwargs):
else:
return None

behavior = ak._v2._util.behavior_of(condition, x, y)
behavior = ak._v2._util.behavior_of(condition, x, y, behavior=behavior)
out = ak._v2._broadcasting.broadcast_and_apply(
[akcondition, left, right],
action,
Expand Down
1 change: 1 addition & 0 deletions src/awkward/_v2/operations/structure/ak_with_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def with_parameter(array, parameter, value, highlevel=True, behavior=None):


def _impl(array, parameter, value, highlevel, behavior):
behavior = ak._v2._util.behavior_of(array, behavior=behavior)
layout = ak._v2.operations.convert.to_layout(
array, allow_record=True, allow_other=False
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def without_parameters(array, highlevel=True, behavior=None):


def _impl(array, highlevel, behavior):
behavior = ak._v2._util.behavior_of(array, behavior=behavior)
layout = ak._v2.operations.convert.to_layout(
array, allow_record=True, allow_other=False
)
Expand Down
145 changes: 145 additions & 0 deletions tests/v2/test_1415-behaviour-forwarding.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE

import pytest # noqa: F401
import awkward as ak # noqa: F401
import numpy as np

one = ak._v2.Array([[0.0, 1.1, 2.2, None], [], [3.3, 4.4]])
two = ak._v2.Array([[100, 200, 300, 400], [300], [400, 500]])


def test_behavior_forwarding_structure():
three = ak._v2.operations.convert.from_iter(
[[0.99999], [6], [2.99999]], highlevel=True
)
four = ak._v2.operations.convert.from_iter(
[[1.00001], [6], [3.00001]], highlevel=True
)
mask1 = ak._v2.highlevel.Array([[True, True, False, False], [True], [True, False]])
five = ak._v2.Array(["1.1", "2.2", " 3.3 ", "00004.4", "-5.5"])

six = ak._v2.Array(
[{"x": 1}, {"x": 2}, {"x": 3}, {"x": 3}, {"x": 3}], check_valid=True
)
seven = ak._v2.Array([1.1, 2.2, 3.3, 4.4, 5.5], check_valid=True)

assert (
ak._v2.operations.structure.argcartesian([one, two], behavior={})[0].behavior
== {}
)
assert (
ak._v2.operations.structure.argcombinations(one, 2, behavior={})[0].behavior
== {}
)
assert ak._v2.operations.structure.argsort(one, behavior={})[0].behavior == {}

assert (
ak._v2.operations.structure.broadcast_arrays(
5, ak._v2.Array([[0.0, 1.1, 2.2], [], [3.3, 4.4]], behavior={})
)[0].behavior
== {}
)

assert ak._v2.operations.structure.cartesian([one], behavior={})[0].behavior == {}
assert (
ak._v2.operations.structure.combinations(one, 2, behavior={})[0].behavior == {}
)
assert (
ak._v2.operations.structure.concatenate([one, two], behavior={})[0].behavior
== {}
)

assert ak._v2.operations.structure.fill_none(one, 42, behavior={})[0].behavior == {}
assert ak._v2.operations.structure.flatten(one, behavior={}).behavior == {}
assert ak._v2.operations.structure.from_regular(one, behavior={})[0].behavior == {}
assert ak._v2.operations.structure.full_like(one, 6, behavior={})[0].behavior == {}

assert ak._v2.operations.structure.is_none(one, behavior={}).behavior == {}
assert ak._v2.operations.structure.isclose(three, four, behavior={}).behavior == {}

assert ak._v2.operations.structure.local_index(one, behavior={})[0].behavior == {}

assert ak._v2.operations.structure.mask(two, mask1, behavior={})[0].behavior == {}

assert ak._v2.operations.structure.nan_to_num(one, behavior={})[0].behavior == {}
assert ak._v2.operations.structure.num(one, behavior={}).behavior == {}

assert ak._v2.operations.structure.ones_like(one, behavior={})[0].behavior == {}

assert ak._v2.operations.structure.packed(one, behavior={})[0].behavior == {}
assert ak._v2.operations.structure.pad_none(one, 6, behavior={})[0].behavior == {}

assert ak._v2.operations.structure.ravel(one, behavior={}).behavior == {}
assert ak._v2.operations.structure.run_lengths(one, behavior={})[0].behavior == {}

assert ak._v2.operations.structure.sort(one, behavior={})[0].behavior == {}
assert (
ak._v2.operations.structure.strings_astype(
five, np.float64, behavior={}
).behavior
== {}
)

assert ak._v2.operations.structure.to_regular(three, behavior={})[0].behavior == {}

assert ak._v2.operations.structure.unflatten(five, 2, behavior={})[0].behavior == {}
assert (
ak._v2.operations.structure.unzip(ak._v2.Array([{"x": 1}], behavior={}))[
0
].behavior
== {}
)

assert (
ak._v2.operations.structure.values_astype(one, "float32", behavior={})[
0
].behavior
== {}
)

assert (
ak._v2.operations.structure.where(
ak._v2.highlevel.Array(
[[True, True], [True, False], [True, False]], behavior={}
)
)[0].behavior
== {}
)
assert (
ak._v2.operations.structure.with_field(six, seven, where="y", behavior={})[
0
].behavior
== {}
)
assert (
ak._v2.operations.structure.with_name(six, "cloud", behavior={})[0].behavior
== {}
)
assert (
ak._v2.operations.structure.without_parameters(
ak._v2.operations.structure.with_parameter(
one, "__array__", "cloud", behavior={}
)
)[0].behavior
== {}
)

assert ak._v2.operations.structure.zeros_like(one, behavior={})[0].behavior == {}
assert ak._v2.operations.structure.zip([five, seven], behavior={})[0].behavior == {}


def test_behavior_forwarding_convert():
assert (
ak._v2.operations.convert.from_json_schema(
" [ 1 ,2 ,3.0, 4, 5] \n ",
{"type": "array", "items": {"type": "integer"}},
behavior={},
).behavior
== {}
)


@pytest.mark.skip(reason="FIXME: v2 highlevel implemented yet")
def test_behaviour_notimplemented():
assert ak._v2.operations.structure.firsts([one, two], behavior={})[0].behavior == {}
assert ak._v2.operations.structure.singletons(one, behavior={})[0].behavior == {}