ronantakizawa/codereview-bench huggingface dataset:
Repository: apache/arrow
File: ci/scripts/python_wheel_validate_contents.py (Python)

Code before:
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

import argparse
from pathlib import Path
import re
import zipfile


def validate_wheel(path):
    p = Path(path)
    wheels = list(p.glob('*.whl'))
    error_msg = f"{len(wheels)} wheels found but only 1 expected ({wheels})"
    assert len(wheels) == 1, error_msg
    f = zipfile.ZipFile(wheels[0])
    outliers = [
        info.filename for info in f.filelist if not re.match(
            r'(pyarrow/|pyarrow-[-.\w\d]+\.dist-info/|pyarrow\.libs/)', info.filename
        )
    ]
    assert not outliers, f"Unexpected contents in wheel: {sorted(outliers)}"
    print(f"The wheel: {wheels[0]} seems valid.")

    candidates = [info for info in f.filelist if info.filename.endswith('compute.pyi')]
    assert candidates, "compute.pyi not found in wheel"
    content = f.read(candidates[0]).decode('utf-8', errors='replace')
    assert '"""' in content, "compute.pyi missing docstrings (no triple quotes found)"


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--path", type=str, required=True,
                        help="Directory where wheel is located")
    args = parser.parse_args()
    validate_wheel(args.path)


if __name__ == '__main__':
    main()


Review comment (bug):
Won't this fail also? I don't think we are able to generate those, see the other comment about the missing `dev/update_stub_docstrings.py`
```suggestion
    # Validate at least one typing stub has been generated.
    candidates = [info for info in f.filelist if info.filename.endswith('compute.pyi')]
```

Code after:
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

import argparse
from pathlib import Path
import re
import zipfile


def validate_wheel(path):
    p = Path(path)
    wheels = list(p.glob('*.whl'))
    error_msg = f"{len(wheels)} wheels found but only 1 expected ({wheels})"
    assert len(wheels) == 1, error_msg
    f = zipfile.ZipFile(wheels[0])
    outliers = [
        info.filename for info in f.filelist if not re.match(
            r'(pyarrow/|pyarrow-[-.\w\d]+\.dist-info/|pyarrow\.libs/)', info.filename
        )
    ]
    assert not outliers, f"Unexpected contents in wheel: {sorted(outliers)}"
    for filename in ('LICENSE.txt', 'NOTICE.txt'):
        assert any(info.filename.split("/")[-1] == filename
                   for info in f.filelist), \
            f"{filename} is missing from the wheel."
    print(f"The wheel: {wheels[0]} seems valid.")
    # TODO(GH-32609): Validate some docstrings were generated and added.

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--path", type=str, required=True,
                        help="Directory where wheel is located")
    args = parser.parse_args()
    validate_wheel(args.path)


if __name__ == '__main__':
    main()
Repository: apache/arrow
File: python/pyarrow-stubs/pyarrow/__init__.pyi (Python)

Code before:
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

"""Type stubs for PyArrow.

This is a placeholder stub file.
Complete type annotations will be added in subsequent PRs.
"""

from typing import Any

def __getattr__(name: str) -> Any: ...


Review comment (suggestion):
IIUC this isn't intended to be permanent.
But I thought you *might* want to consider adding a note/opening an issue to remove it before release.

Here's some examples of how it can mask runtime errors:

- https://github.com/narwhals-dev/narwhals/pull/3333
- https://github.com/pola-rs/polars/issues/24334

Code after:
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

"""Type stubs for PyArrow.

This is a placeholder stub file.
Complete type annotations will be added in subsequent PRs.
"""

from typing import Any

# TODO(GH-48970): remove __getattr__ before release as this
# will annotate non-existing attributes as Any.
# https://github.com/apache/arrow/issues/48970
def __getattr__(name: str) -> Any: ...
Repository: apache/arrow
File: ci/scripts/python_test_type_annotations.sh (Shell)

Code before:
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

set -ex
pyarrow_dir=${1}

if [ "${PYARROW_TEST_ANNOTATIONS}" == "ON" ]; then
  if [ -n "${ARROW_PYTHON_VENV:-}" ]; then
    . "${ARROW_PYTHON_VENV}/bin/activate"
  fi

  # Install library stubs. Note some libraries contain their own type hints so they need to be installed.
  pip install fsspec pandas-stubs scipy-stubs types-cffi types-psutil types-requests types-python-dateutil

  # Install type checkers
  pip install mypy pyright ty

  # Run type checkers
  pushd ${pyarrow_dir}
  mypy
  pyright
  ty check;
  popd
else
  echo "Skipping type annotation tests";
fi


Review comment (suggestion):
```suggestion
  echo "Skipping type annotation tests"
```

Code after:
#!/usr/bin/env bash
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

set -ex
pyarrow_dir=${1}

if [ -n "${ARROW_PYTHON_VENV:-}" ]; then
  # shellcheck source=/dev/null
  . "${ARROW_PYTHON_VENV}/bin/activate"
fi

# Install library stubs. Note some libraries contain their own type hints so they need to be installed.
pip install fsspec pandas-stubs scipy-stubs types-cffi types-psutil types-requests types-python-dateutil

# Install type checkers
pip install mypy pyright ty

# Run type checkers
cd "${pyarrow_dir}"
mypy
pyright
ty check
Repository: apache/arrow
File: python/pyarrow/src/arrow/python/inference.cc (C++)

Code before:
    return Status::OK();
  }

  bool dtype_was_observed() const { return current_type_num_ != -1; }

  PyArray_Descr* current_dtype() const { return current_dtype_; }

  int current_type_num() const { return current_type_num_; }

 private:
  static const char* DatetimeUnitName(NPY_DATETIMEUNIT unit) {
    switch (unit) {
      case NPY_FR_s:
        return "s";
      case NPY_FR_ms:
        return "ms";
      case NPY_FR_us:
        return "us";
      case NPY_FR_ns:
        return "ns";
      case NPY_FR_D:
        return "D";
      case NPY_FR_GENERIC:
        return "generic";
      default:
        return "unknown";
    }
  }

  int current_type_num_;
  PyArray_Descr* current_dtype_;
};

class TypeInferrer {
  // A type inference visitor for Python values
 public:
  // \param validate_interval the number of elements to observe before checking
  // whether the data is mixed type or has other problems. This helps avoid
  // excess computation for each element while also making sure we "bail out"
  // early with long sequences that may have problems up front
  // \param make_unions permit mixed-type data by creating union types (not yet
  // implemented)
  explicit TypeInferrer(bool pandas_null_sentinels = false,
                        int64_t validate_interval = 100, bool make_unions = false)
      : pandas_null_sentinels_(pandas_null_sentinels),
        validate_interval_(validate_interval),
        make_unions_(make_unions),
        total_count_(0),
        none_count_(0),
        bool_count_(0),
        int_count_(0),

Review comment (suggestion):
Numpy has other [time units](https://numpy.org/devdocs/reference/arrays.datetime.html#datetime-units). Could we perhaps print which was used in case this is hit instead of unknown? I don't know if this is practical, just asking.

Code after:
    return Status::OK();
  }

  bool dtype_was_observed() const { return current_type_num_ != -1; }

  PyArray_Descr* current_dtype() const { return current_dtype_; }

  int current_type_num() const { return current_type_num_; }

 private:
  static std::string DatetimeUnitName(NPY_DATETIMEUNIT unit) {
    switch (unit) {
      case NPY_FR_Y:
        return "Y";
      case NPY_FR_M:
        return "M";
      case NPY_FR_W:
        return "W";
      case NPY_FR_D:
        return "D";
      case NPY_FR_h:
        return "h";
      case NPY_FR_m:
        return "m";
      case NPY_FR_s:
        return "s";
      case NPY_FR_ms:
        return "ms";
      case NPY_FR_us:
        return "us";
      case NPY_FR_ns:
        return "ns";
      case NPY_FR_ps:
        return "ps";
      case NPY_FR_fs:
        return "fs";
      case NPY_FR_as:
        return "as";
      case NPY_FR_GENERIC:
        return "generic";
      default:
        return "unknown (" + std::to_string(static_cast<int>(unit)) + ")";
    }
  }

  int current_type_num_;
  PyArray_Descr* current_dtype_;
};

class TypeInferrer {
  // A type inference visitor for Python values
Repository: apache/arrow
File: r/tests/testthat/test-dplyr-join.R (R)

Code before:
      collect(),
    left
  )
})

test_that("full_join", {
  compare_dplyr_binding(
    .input |>
      full_join(to_join, by = "some_grouping", keep = TRUE) |>
      collect(),
    left
  )

  compare_dplyr_binding(
    .input |>
      full_join(to_join, by = "some_grouping", keep = FALSE) |>
      collect(),
    left
  )
})

test_that("semi_join", {
  compare_dplyr_binding(
    .input |>
      semi_join(to_join, by = "some_grouping") |>
      collect(),
    left
  )
})

test_that("anti_join", {
  compare_dplyr_binding(
    .input |>
      # Factor levels when there are no rows in the data don't match
      # TODO: use better anti_join test data
      select(-fct) |>
      anti_join(to_join, by = "some_grouping") |>
      collect(),
    left
  )
})

test_that("arrow dplyr query correctly mutates then joins", {
  left <- Table$create(
    one = c("a", "b"),
    two = 1:2
  )
  right <- Table$create(
    three = TRUE,
    dos = 2L
  )

Review comment (refactor):
This test especially is effectively duplicated by https://github.com/apache/arrow/blob/744f0ec2cf9f8716fcea408d67ede9c14a7e6954/r/tests/testthat/test-dplyr-join.R#L320-L338

Though I will admit that the tests there do not follow the established pattern you follow here. Would you mind updating merging these two tests together? You can use your fixture for that purpose if you like, but if you do, would you mind adding a column with floats and also making the key column more obvious (e.g. by naming it `key` or `to_join` or something like that?

I'm happy to help describe in more detail if that's helpful!

Code after:
    "shared_float_right",
    "right_unique"
  )
  expect_equal(expected_col_names, res_col_names)
})

test_that("joins with incompatible types for join keys", {
  # Test that joining on columns with incompatible types (int vs float) fails
  # Arrow requires join keys to have compatible types - type casting is not
  # automatically performed for join keys
  left_int <- Table$create(
    x = c(1L, 2L),
    shared = c(10L, 20L)
  )
  right_float <- Table$create(
    x = c(1.0, 2.0),
    shared = c(10.1, 20.2)
  )

  expect_error(
    left_int |>
      left_join(right_float, by = "x") |>
      collect(),
    "Incompatible data types for corresponding join field keys"
  )
})

test_that("right_join", {
  compare_dplyr_binding(
    .input |>
      right_join(to_join, by = "some_grouping", keep = TRUE) |>
      collect(),
    left
  )

  compare_dplyr_binding(
    .input |>
      right_join(to_join, by = "some_grouping", keep = FALSE) |>
      collect(),
    left
  )
})

test_that("inner_join", {
  compare_dplyr_binding(
    .input |>
      inner_join(to_join, by = "some_grouping", keep = TRUE) |>
      collect(),
    left
  )
Repository: apache/arrow
File: python/pyarrow/_compute_docstrings.py (Python)

Code before:
    ]
    """

function_doc_additions["mode"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> modes = pc.mode(arr, 2)
    >>> modes[0]
    <pyarrow.StructScalar: [('mode', 2), ('count', 5)]>
    >>> modes[1]
    <pyarrow.StructScalar: [('mode', 1), ('count', 2)]>
    """

function_doc_additions["min"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr1 = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> pc.min(arr1)
    <pyarrow.Int64Scalar: 1>

    Using `skip_nulls` to handle null values.

    >>> arr2 = pa.array([1.0, None, 2.0, 3.0])
    >>> pc.min(arr2)
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr2, skip_nulls=False)
    <pyarrow.DoubleScalar: None>

    Using `ScalarAggregateOptions` to control minimum number of non-null values.

    >>> arr3 = pa.array([1.0, None, float("nan"), 3.0])
    >>> pc.min(arr3)
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr3, options=pc.ScalarAggregateOptions(min_count=3))
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr3, options=pc.ScalarAggregateOptions(min_count=4))
    <pyarrow.DoubleScalar: None>

    This function also works with string values.

    >>> arr4 = pa.array(["z", None, "y", "x"])
    >>> pc.min(arr4)
    <pyarrow.StringScalar: 'x'>
    """

function_doc_additions["max"] = """

Review comment (suggestion):
```suggestion
    Using ``skip_nulls`` to handle null values.
```

Code after:
    ]
    """

function_doc_additions["mode"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> modes = pc.mode(arr, 2)
    >>> modes[0]
    <pyarrow.StructScalar: [('mode', 2), ('count', 5)]>
    >>> modes[1]
    <pyarrow.StructScalar: [('mode', 1), ('count', 2)]>
    """

function_doc_additions["min"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr1 = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> pc.min(arr1)
    <pyarrow.Int64Scalar: 1>

    Using ``skip_nulls`` to handle null values.

    >>> arr2 = pa.array([1.0, None, 2.0, 3.0])
    >>> pc.min(arr2)
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr2, skip_nulls=False)
    <pyarrow.DoubleScalar: None>

    Using ``ScalarAggregateOptions`` to control minimum number of non-null values.

    >>> arr3 = pa.array([1.0, None, float("nan"), 3.0])
    >>> pc.min(arr3)
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr3, options=pc.ScalarAggregateOptions(min_count=3))
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr3, options=pc.ScalarAggregateOptions(min_count=4))
    <pyarrow.DoubleScalar: None>

    This function also works with string values.

    >>> arr4 = pa.array(["z", None, "y", "x"])
    >>> pc.min(arr4)
    <pyarrow.StringScalar: 'x'>
    """

function_doc_additions["max"] = """
Repository: apache/arrow
File: python/pyarrow/_compute_docstrings.py (Python)

Code before:
    >>> arr = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> modes = pc.mode(arr, 2)
    >>> modes[0]
    <pyarrow.StructScalar: [('mode', 2), ('count', 5)]>
    >>> modes[1]
    <pyarrow.StructScalar: [('mode', 1), ('count', 2)]>
    """

function_doc_additions["min"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr1 = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> pc.min(arr1)
    <pyarrow.Int64Scalar: 1>

    Using `skip_nulls` to handle null values.

    >>> arr2 = pa.array([1.0, None, 2.0, 3.0])
    >>> pc.min(arr2)
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr2, skip_nulls=False)
    <pyarrow.DoubleScalar: None>

    Using `ScalarAggregateOptions` to control minimum number of non-null values.

    >>> arr3 = pa.array([1.0, None, float("nan"), 3.0])
    >>> pc.min(arr3)
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr3, options=pc.ScalarAggregateOptions(min_count=3))
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr3, options=pc.ScalarAggregateOptions(min_count=4))
    <pyarrow.DoubleScalar: None>

    This function also works with string values.

    >>> arr4 = pa.array(["z", None, "y", "x"])
    >>> pc.min(arr4)
    <pyarrow.StringScalar: 'x'>
    """

function_doc_additions["max"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr1 = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> pc.max(arr1)
    <pyarrow.Int64Scalar: 3>


Review comment (suggestion):
```suggestion
    Using ``ScalarAggregateOptions`` to control minimum number of non-null values.
```

Code after:
    >>> arr = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> modes = pc.mode(arr, 2)
    >>> modes[0]
    <pyarrow.StructScalar: [('mode', 2), ('count', 5)]>
    >>> modes[1]
    <pyarrow.StructScalar: [('mode', 1), ('count', 2)]>
    """

function_doc_additions["min"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr1 = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> pc.min(arr1)
    <pyarrow.Int64Scalar: 1>

    Using ``skip_nulls`` to handle null values.

    >>> arr2 = pa.array([1.0, None, 2.0, 3.0])
    >>> pc.min(arr2)
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr2, skip_nulls=False)
    <pyarrow.DoubleScalar: None>

    Using ``ScalarAggregateOptions`` to control minimum number of non-null values.

    >>> arr3 = pa.array([1.0, None, float("nan"), 3.0])
    >>> pc.min(arr3)
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr3, options=pc.ScalarAggregateOptions(min_count=3))
    <pyarrow.DoubleScalar: 1.0>
    >>> pc.min(arr3, options=pc.ScalarAggregateOptions(min_count=4))
    <pyarrow.DoubleScalar: None>

    This function also works with string values.

    >>> arr4 = pa.array(["z", None, "y", "x"])
    >>> pc.min(arr4)
    <pyarrow.StringScalar: 'x'>
    """

function_doc_additions["max"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr1 = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> pc.max(arr1)
    <pyarrow.Int64Scalar: 3>
Repository: apache/arrow
File: python/pyarrow/_compute_docstrings.py (Python)

Code before:

    This function also works with string values.

    >>> arr4 = pa.array(["z", None, "y", "x"])
    >>> pc.min(arr4)
    <pyarrow.StringScalar: 'x'>
    """

function_doc_additions["max"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr1 = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> pc.max(arr1)
    <pyarrow.Int64Scalar: 3>

    Using `skip_nulls` to handle null values.

    >>> arr2 = pa.array([1.0, None, 2.0, 3.0])
    >>> pc.max(arr2)
    <pyarrow.DoubleScalar: 3.0>
    >>> pc.max(arr2, skip_nulls=False)
    <pyarrow.DoubleScalar: None>

    Using `ScalarAggregateOptions` to control minimum number of non-null values.

    >>> arr3 = pa.array([1.0, None, float("nan"), 3.0])
    >>> pc.max(arr3)
    <pyarrow.DoubleScalar: 3.0>
    >>> pc.max(arr3, options=pc.ScalarAggregateOptions(min_count=3))
    <pyarrow.DoubleScalar: 3.0>
    >>> pc.max(arr3, options=pc.ScalarAggregateOptions(min_count=4))
    <pyarrow.DoubleScalar: None>

    This function also works with string values.

    >>> arr4 = pa.array(["z", None, "y", "x"])
    >>> pc.max(arr4)
    <pyarrow.StringScalar: 'z'>
    """

function_doc_additions["min_max"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr1 = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> pc.min_max(arr1)
    <pyarrow.StructScalar: [('min', 1), ('max', 3)]>


Review comment (suggestion):
```suggestion
    Using ``ScalarAggregateOptions`` to control minimum number of non-null values.
```

Code after:

    This function also works with string values.

    >>> arr4 = pa.array(["z", None, "y", "x"])
    >>> pc.min(arr4)
    <pyarrow.StringScalar: 'x'>
    """

function_doc_additions["max"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr1 = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> pc.max(arr1)
    <pyarrow.Int64Scalar: 3>

    Using ``skip_nulls`` to handle null values.

    >>> arr2 = pa.array([1.0, None, 2.0, 3.0])
    >>> pc.max(arr2)
    <pyarrow.DoubleScalar: 3.0>
    >>> pc.max(arr2, skip_nulls=False)
    <pyarrow.DoubleScalar: None>

    Using ``ScalarAggregateOptions`` to control minimum number of non-null values.

    >>> arr3 = pa.array([1.0, None, float("nan"), 3.0])
    >>> pc.max(arr3)
    <pyarrow.DoubleScalar: 3.0>
    >>> pc.max(arr3, options=pc.ScalarAggregateOptions(min_count=3))
    <pyarrow.DoubleScalar: 3.0>
    >>> pc.max(arr3, options=pc.ScalarAggregateOptions(min_count=4))
    <pyarrow.DoubleScalar: None>

    This function also works with string values.

    >>> arr4 = pa.array(["z", None, "y", "x"])
    >>> pc.max(arr4)
    <pyarrow.StringScalar: 'z'>
    """

function_doc_additions["min_max"] = """
    Examples
    --------
    >>> import pyarrow as pa
    >>> import pyarrow.compute as pc
    >>> arr1 = pa.array([1, 1, 2, 2, 3, 2, 2, 2])
    >>> pc.min_max(arr1)
    <pyarrow.StructScalar: [('min', 1), ('max', 3)]>