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

AttributeError: 'CPUDispatcher' object has no attribute '__globals__' with numba.njit decorated function #277

Closed
gatoniel opened this issue Nov 8, 2022 · 9 comments
Labels
needs more info Development cannot proceed before requested information has been provided

Comments

@gatoniel
Copy link

gatoniel commented Nov 8, 2022

Describe the bug
I am using the numba.njit decorator to decorate a function. When I execute pytest with typeguard, I get an error when this decorated function is called: AttributeError: 'CPUDispatcher' object has no attribute '__globals__'. When trying to narrow down the error and trying to reproduce with a minimal working example, I found out that the error only occurs when the decorated function is imported absolutely from a module. When the same function is imported with a relative import there is no error.

To Reproduce
I have three different files: two source files (one for absolute and one for relative import) and one pytest file:
src/my_module/numba_typeguard.py (absolute import)

from typing import TypeVar

import numpy as np
import numpy.typing as npt
from numba import njit

T = TypeVar("T", bound=np.generic)


@njit
def numba_sum(
    array: npt.NDArray[T],
) -> T:
    return np.sum(array)

tests/numba_typeguard.py (relative import) same function as above but in tests directory.

from typing import TypeVar

import numpy as np
import numpy.typing as npt
from numba import njit

T = TypeVar("T", bound=np.generic)


@njit
def numba_sum_local(
    array: npt.NDArray[T],
) -> T:
    return np.sum(array)

tests/test_numba_typeguard.py

import numpy as np
from my_module.numba_typeguard import numba_sum
from .numba_typeguard import numba_sum_local


def test_numba_sum_njit() -> None:
    x = np.arange(4)
    s = numba_sum(x)
    assert s == np.sum(x)


def test_numba_sum() -> None:
    x = np.arange(4)
    s = numba_sum.py_func(x)
    assert s == np.sum(x)


def test_numba_sum_local_njit() -> None:
    x = np.arange(4)
    s = numba_sum_local(x)
    assert s == np.sum(x)


def test_numba_sum_local() -> None:
    x = np.arange(4)
    s = numba_sum_local.py_func(x)
    assert s == np.sum(x)

The following is the error I get:

======================================================================================================================================= FAILURES =======================================================================================================================================
_________________________________________________________________________________________________________________________________ test_numba_sum_njit __________________________________________________________________________________________________________________________________

    def test_numba_sum_njit() -> None:
        x = np.arange(4)
>       s = numba_sum(x)

tests/test_numba_typeguard.py:8:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
.nox/typeguard-3-9/lib/python3.9/site-packages/typeguard/__init__.py:1031: in wrapper
    memo = _CallMemo(python_func, _localns, args=args, kwargs=kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <typeguard._CallMemo object at 0x7f9db523c880>, func = CPUDispatcher(<function numba_sum at 0x7f9db52fa5e0>)
frame_locals = {'T': ~T, 'TypeVar': <class 'typing.TypeVar'>, '__builtins__': {'ArithmeticError': <class 'ArithmeticError'>, 'Asserti...s/.nox/typeguard-3-9/lib/python3.9/site-packages/my_module/__pycache__/numba_typeguard.cpython-39.pyc', ...}
args = (array([0, 1, 2, 3]),), kwargs = {}, forward_refs_policy = <ForwardRefPolicy.ERROR: 1>

    def __init__(self, func: Callable, frame_locals: Optional[Dict[str, Any]] = None,
                 args: tuple = None, kwargs: Dict[str, Any] = None,
                 forward_refs_policy=ForwardRefPolicy.ERROR):
>       super().__init__(func.__globals__, frame_locals)
E       AttributeError: 'CPUDispatcher' object has no attribute '__globals__'

.nox/typeguard-3-9/lib/python3.9/site-packages/typeguard/__init__.py:191: AttributeError

Expected behavior
I expect the error not to depend on relative vs absolute import.

Additional context
As I do not know if this is related to typeguard alone or something else and as I am using the hypermodern python template, I raised also an issue there: cjolowicz/cookiecutter-hypermodern-python#1271

I tried to remove the py.typed file in the src/my_module directory, but this did not resolve the error.

@agronholm
Copy link
Owner

agronholm commented Jan 10, 2023

I was not able to reproduce the problem on latest master with this code:

from typing import TypeVar

import numpy as np
import numpy.typing as npt
from numba import njit
from typeguard import typechecked

T = TypeVar("T", bound=np.generic)


@typechecked
@njit
def numba_sum(
    array: npt.NDArray[T],
) -> T:
    return np.sum(array)

x = np.arange(4)
s = numba_sum.py_func(x)

Did I do something wrong, or is this no longer an issue?

@agronholm agronholm added the needs more info Development cannot proceed before requested information has been provided label Jan 15, 2023
@agronholm
Copy link
Owner

Closing due to a lack of replies.

@agronholm agronholm closed this as not planned Won't fix, can't repro, duplicate, stale Jan 24, 2023
@gatoniel
Copy link
Author

Sorry for the late response. I installed your latest tag 3.0.0b2 from github and ran the following code:

from typing import TypeVar

import numpy as np
import numpy.typing as npt
from numba import njit
from typeguard import typechecked

T = TypeVar("T", bound=np.generic)


@typechecked
@njit
def numba_sum(
    array: npt.NDArray[T],
) -> T:
    return np.sum(array)

x = np.arange(4)
s = numba_sum.py_func(x)
s = numba_sum(x)

It gives me the following error message:

Traceback (most recent call last):
  File "/home/niklas/drescherlab/merge-stardist-masks/test.py", line 21, in <module>
    s = numba_sum(x)
  File "/home/niklas/.cache/pypoetry/virtualenvs/merge-stardist-masks-Mk5qjuGF-py3.9/lib/python3.9/site-packages/typeguard/__init__.py", line 286, in wrapper
    memo = CallMemo(python_func, _localns, args=args, kwargs=kwargs)
  File "/home/niklas/.cache/pypoetry/virtualenvs/merge-stardist-masks-Mk5qjuGF-py3.9/lib/python3.9/site-packages/typeguard/_memo.py", line 54, in __init__
    super().__init__(func.__globals__, frame_locals, config)
AttributeError: 'CPUDispatcher' object has no attribute '__globals__'

The problem is not with the .py_func but with the real njitted function.

@agronholm
Copy link
Owner

Not sure what I did before, but I can reproduce this locally now.

@agronholm
Copy link
Owner

I am currently in the process of heavily refactoring @typechecked now. I'll try this again when that's done.

@gatoniel
Copy link
Author

Thank you so much for looking into this...

Before, you only executed numba_sum.py_func(x) not numba_sum(x)...

@agronholm
Copy link
Owner

Thank you so much for looking into this...

Before, you only executed numba_sum.py_func(x) not numba_sum(x)...

That would explain it 😄

@agronholm
Copy link
Owner

The underlying problem is that inspect.unwrap() stops at the CPUDispatcher object. If I fix that, I get: typeguard.TypeCheckError: the return value is not an instance of numpy.generic. Is this what you expected?

@agronholm
Copy link
Owner

Oh and BTW, it didn't work at all on Pythons older than 3.9.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs more info Development cannot proceed before requested information has been provided
Projects
None yet
Development

No branches or pull requests

2 participants