"""
|
Tests for the private NumPy argument parsing functionality.
|
They mainly exists to ensure good test coverage without having to try the
|
weirder cases on actual numpy functions but test them in one place.
|
|
The test function is defined in C to be equivalent to (errors may not always
|
match exactly, and could be adjusted):
|
|
def func(arg1, /, arg2, *, arg3):
|
i = integer(arg1) # reproducing the 'i' parsing in Python.
|
return None
|
"""
|
|
import threading
|
|
import pytest
|
from numpy._core._multiarray_tests import (
|
argparse_example_function as func,
|
)
|
from numpy._core._multiarray_tests import (
|
threaded_argparse_example_function as thread_func,
|
)
|
|
import numpy as np
|
from numpy.testing import IS_WASM
|
|
|
@pytest.mark.skipif(IS_WASM, reason="wasm doesn't have support for threads")
|
def test_thread_safe_argparse_cache():
|
b = threading.Barrier(8)
|
|
def call_thread_func():
|
b.wait()
|
thread_func(arg1=3, arg2=None)
|
|
tasks = [threading.Thread(target=call_thread_func) for _ in range(8)]
|
[t.start() for t in tasks]
|
[t.join() for t in tasks]
|
|
|
def test_invalid_integers():
|
with pytest.raises(TypeError,
|
match="integer argument expected, got float"):
|
func(1.)
|
with pytest.raises(OverflowError):
|
func(2**100)
|
|
|
def test_missing_arguments():
|
with pytest.raises(TypeError,
|
match="missing required positional argument 0"):
|
func()
|
with pytest.raises(TypeError,
|
match="missing required positional argument 0"):
|
func(arg2=1, arg3=4)
|
with pytest.raises(TypeError,
|
match=r"missing required argument \'arg2\' \(pos 1\)"):
|
func(1, arg3=5)
|
|
|
def test_too_many_positional():
|
# the second argument is positional but can be passed as keyword.
|
with pytest.raises(TypeError,
|
match="takes from 2 to 3 positional arguments but 4 were given"):
|
func(1, 2, 3, 4)
|
|
|
def test_multiple_values():
|
with pytest.raises(TypeError,
|
match=r"given by name \('arg2'\) and position \(position 1\)"):
|
func(1, 2, arg2=3)
|
|
|
def test_string_fallbacks():
|
# We can (currently?) use numpy strings to test the "slow" fallbacks
|
# that should normally not be taken due to string interning.
|
arg2 = np.str_("arg2")
|
missing_arg = np.str_("missing_arg")
|
func(1, **{arg2: 3})
|
with pytest.raises(TypeError,
|
match="got an unexpected keyword argument 'missing_arg'"):
|
func(2, **{missing_arg: 3})
|
|
|
def test_too_many_arguments_method_forwarding():
|
# Not directly related to the standard argument parsing, but we sometimes
|
# forward methods to Python: arr.mean() calls np._core._methods._mean()
|
# This adds code coverage for this `npy_forward_method`.
|
arr = np.arange(3)
|
args = range(1000)
|
with pytest.raises(TypeError):
|
arr.mean(*args)
|