beartype / plum

Multiple dispatch in Python
https://beartype.github.io/plum
MIT License
497 stars 22 forks source link

`process` function getting the arguments for `Bundle`'s `__new__` method? #141

Open sylvorg opened 1 month ago

sylvorg commented 1 month ago

Hello!

As in the title; if you test out the repository here, for some reason, the combination of these files:

__init__.py:

import rich.traceback as RichTraceback

RichTraceback.install(show_locals=True)

import rich.pretty as RichPretty

RichPretty.install()

from beartype.claw import beartype_this_package

beartype_this_package()

from plum_off.bundle import *

bundle.py:

from .python import plumeta, process

class Bundle(plumeta, metaclass=plumeta):
    def __new__(cls, name, bases, ns):
        pass

class bundle(metaclass=Bundle):
    pass

python.py:

from plum import dispatch, Dispatcher

# Adapted From: https://github.com/coady/multimethod/blob/main/multimethod/__init__.py#L488-L498
class plumeta(type):
    """Convert all callables in namespace to Dispatchers."""

    class __prepare__(dict):
        def __init__(self, *args):
            self.__dispatcher__ = Dispatcher()
            super().__setitem__("__dispatcher__", self.__dispatcher__)

        def __setitem__(self, key, value):
            if callable(value):
                args, kwargs = getattr(value, "__plume__", (tuple(), dict()))
                if not kwargs.get("disabled", False):
                    value = getattr(self.get(key), "dispatch", self.__dispatcher__)(
                        value, *args, **kwargs
                    )
            super().__setitem__(key, value)

@dispatch
def process(_: type):
    pass

Cause the following traceback:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ in <module>:1                                                                                    │
│                                                                                                  │
│ /mnt/wsl/sylvorg/tests/plum-off/plum_off/__init__.py:13 in <module>                              │
│                                                                                                  │
│   10                                                                                             │
│   11 beartype_this_package()                                                                     │
│   12                                                                                             │
│ ❱ 13 from plum_off.bundle import *                                                               │
│   14                                                                                             │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ beartype_this_package = <function beartype_this_package at 0x7fa88f3814e0>                   │ │
│ │                python = <module 'plum_off.python' from                                       │ │
│ │                         '/mnt/wsl/sylvorg/tests/plum-off/plum_off/python.py'>                │ │
│ │            RichPretty = <module 'rich.pretty' from                                           │ │
│ │                         '/nix/store/m3ww19ir18vfggdpjwmglar2rs6fg627-python3.11-rich-13.5.2… │ │
│ │         RichTraceback = <module 'rich.traceback' from                                        │ │
│ │                         '/nix/store/m3ww19ir18vfggdpjwmglar2rs6fg627-python3.11-rich-13.5.2… │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /mnt/wsl/sylvorg/tests/plum-off/plum_off/bundle.py:9 in <module>                                 │
│                                                                                                  │
│    6 │   │   pass                                                                                │
│    7                                                                                             │
│    8                                                                                             │
│ ❱  9 class bundle(metaclass=Bundle):                                                             │
│   10 │   pass                                                                                    │
│   11                                                                                             │
│                                                                                                  │
│ ╭────────────────────────────────────────── locals ──────────────────────────────────────────╮   │
│ │  Bundle = <class 'plum_off.bundle.Bundle'>                                                 │   │
│ │ plumeta = <class 'plum_off.python.plumeta'>                                                │   │
│ │ process = <multiple-dispatch function process (with 1 registered and 0 pending method(s))> │   │
│ ╰────────────────────────────────────────────────────────────────────────────────────────────╯   │
│                                                                                                  │
│ /nix/store/brnivi65vfq079xakl2lcs2kpaq2464a-python3.11-plum_dispatch-2.3.2/lib/python3.11/site-p │
│ ackages/plum/function.py:367 in __call__                                                         │
│                                                                                                  │
│   364 │                                                                                          │
│   365 │   def __call__(self, *args, **kw_args):                                                  │
│   366 │   │   __tracebackhide__ = True                                                           │
│ ❱ 367 │   │   method, return_type = self._resolve_method_with_cache(args=args)                   │
│   368 │   │   return _convert(method(*args, **kw_args), return_type)                             │
│   369 │                                                                                          │
│   370 │   def _resolve_method_with_cache(                                                        │
│                                                                                                  │
│ ╭────────────────────────────────────────── locals ──────────────────────────────────────────╮   │
│ │    args = (                                                                                │   │
│ │           │   <class 'plum_off.bundle.Bundle'>,                                            │   │
│ │           │   'bundle',                                                                    │   │
│ │           │   (),                                                                          │   │
│ │           │   {                                                                            │   │
│ │           │   │   '__dispatcher__': <plum.dispatcher.Dispatcher object at 0x7fa88f398990>, │   │
│ │           │   │   '__module__': 'plum_off.bundle',                                         │   │
│ │           │   │   '__qualname__': 'bundle'                                                 │   │
│ │           │   }                                                                            │   │
│ │           )                                                                                │   │
│ │ kw_args = {}                                                                               │   │
│ │    self = <multiple-dispatch function process (with 1 registered and 0 pending method(s))> │   │
│ ╰────────────────────────────────────────────────────────────────────────────────────────────╯   │
│                                                                                                  │
│ /nix/store/brnivi65vfq079xakl2lcs2kpaq2464a-python3.11-plum_dispatch-2.3.2/lib/python3.11/site-p │
│ ackages/plum/function.py:398 in _resolve_method_with_cache                                       │
│                                                                                                  │
│   395 │   │   │   │   args = Signature(*(resolve_type_hint(t) for t in types))                   │
│   396 │   │   │                                                                                  │
│   397 │   │   │   # Cache miss. Run the resolver based on the arguments.                         │
│ ❱ 398 │   │   │   method, return_type = self.resolve_method(args)                                │
│   399 │   │   │   # If the resolver is faithful, then we can perform caching using the types     │
│   400 │   │   │   # of the arguments. If the resolver is not faithful, then we cannot.           │
│   401 │   │   │   if self._resolver.is_faithful:                                                 │
│                                                                                                  │
│ ╭───────────────────────────────────────── locals ─────────────────────────────────────────╮     │
│ │  args = (                                                                                │     │
│ │         │   <class 'plum_off.bundle.Bundle'>,                                            │     │
│ │         │   'bundle',                                                                    │     │
│ │         │   (),                                                                          │     │
│ │         │   {                                                                            │     │
│ │         │   │   '__dispatcher__': <plum.dispatcher.Dispatcher object at 0x7fa88f398990>, │     │
│ │         │   │   '__module__': 'plum_off.bundle',                                         │     │
│ │         │   │   '__qualname__': 'bundle'                                                 │     │
│ │         │   }                                                                            │     │
│ │         )                                                                                │     │
│ │  self = <multiple-dispatch function process (with 1 registered and 0 pending method(s))> │     │
│ │ types = (                                                                                │     │
│ │         │   <class 'plum_off.python.plumeta'>,                                           │     │
│ │         │   <class 'str'>,                                                               │     │
│ │         │   <class 'tuple'>,                                                             │     │
│ │         │   <class 'plum_off.python.plumeta.__prepare__'>                                │     │
│ │         )                                                                                │     │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────╯     │
│                                                                                                  │
│ /nix/store/brnivi65vfq079xakl2lcs2kpaq2464a-python3.11-plum_dispatch-2.3.2/lib/python3.11/site-p │
│ ackages/plum/function.py:318 in resolve_method                                                   │
│                                                                                                  │
│   315 │   │   │   # Change the function name if this is a method.                                │
│   316 │   │   │   if self.owner:                                                                 │
│   317 │   │   │   │   e.f_name = self.__qualname__                                               │
│ ❱ 318 │   │   │   impl, return_type = self._handle_not_found_lookup_error(e)                     │
│   319 │   │                                                                                      │
│   320 │   │   return impl, return_type                                                           │
│   321                                                                                            │
│                                                                                                  │
│ ╭───────────────────────────────────────── locals ──────────────────────────────────────────╮    │
│ │   self = <multiple-dispatch function process (with 1 registered and 0 pending method(s))> │    │
│ │ target = (                                                                                │    │
│ │          │   <class 'plum_off.bundle.Bundle'>,                                            │    │
│ │          │   'bundle',                                                                    │    │
│ │          │   (),                                                                          │    │
│ │          │   {                                                                            │    │
│ │          │   │   '__dispatcher__': <plum.dispatcher.Dispatcher object at 0x7fa88f398990>, │    │
│ │          │   │   '__module__': 'plum_off.bundle',                                         │    │
│ │          │   │   '__qualname__': 'bundle'                                                 │    │
│ │          │   }                                                                            │    │
│ │          )                                                                                │    │
│ ╰───────────────────────────────────────────────────────────────────────────────────────────╯    │
│                                                                                                  │
│ /nix/store/brnivi65vfq079xakl2lcs2kpaq2464a-python3.11-plum_dispatch-2.3.2/lib/python3.11/site-p │
│ ackages/plum/function.py:327 in _handle_not_found_lookup_error                                   │
│                                                                                                  │
│   324 │   ) -> Tuple[Callable, TypeHint]:                                                        │
│   325 │   │   if not self.owner:                                                                 │
│   326 │   │   │   # Not in a class. Nothing we can do.                                           │
│ ❱ 327 │   │   │   raise ex from None                                                             │
│   328 │   │                                                                                      │
│   329 │   │   # In a class. Walk through the classes in the class's MRO, except for this         │
│   330 │   │   # class, and try to get the method.                                                │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │   ex = `process(<class 'plum_off.bundle.Bundle'>, 'bundle', (), {'__dispatcher__':           │ │
│ │        <plum.dispatcher.Dispatcher object at 0x7fa88f398990>, '__module__':                  │ │
│ │        'plum_off.bundle',                                                                    │ │
│ │        '__qualname__': 'bundle'})` could not be resolved.                                    │ │
│ │                                                                                              │ │
│ │        Closest candidates are the following:                                                 │ │
│ │        │   process(_: type)                                                                  │ │
│ │        │   │   <function process at 0x7fa88f286f20> @ ~/tests/plum-off/plum_off/python.py:24 │ │
│ │ self = <multiple-dispatch function process (with 1 registered and 0 pending method(s))>      │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /nix/store/brnivi65vfq079xakl2lcs2kpaq2464a-python3.11-plum_dispatch-2.3.2/lib/python3.11/site-p │
│ ackages/plum/function.py:300 in resolve_method                                                   │
│                                                                                                  │
│   297 │   │                                                                                      │
│   298 │   │   try:                                                                               │
│   299 │   │   │   # Attempt to find the method using the resolver.                               │
│ ❱ 300 │   │   │   method = self._resolver.resolve(target)                                        │
│   301 │   │   │   impl = method.implementation                                                   │
│   302 │   │   │   return_type = method.return_type                                               │
│   303                                                                                            │
│                                                                                                  │
│ ╭───────────────────────────────────────── locals ──────────────────────────────────────────╮    │
│ │   self = <multiple-dispatch function process (with 1 registered and 0 pending method(s))> │    │
│ │ target = (                                                                                │    │
│ │          │   <class 'plum_off.bundle.Bundle'>,                                            │    │
│ │          │   'bundle',                                                                    │    │
│ │          │   (),                                                                          │    │
│ │          │   {                                                                            │    │
│ │          │   │   '__dispatcher__': <plum.dispatcher.Dispatcher object at 0x7fa88f398990>, │    │
│ │          │   │   '__module__': 'plum_off.bundle',                                         │    │
│ │          │   │   '__qualname__': 'bundle'                                                 │    │
│ │          │   }                                                                            │    │
│ │          )                                                                                │    │
│ ╰───────────────────────────────────────────────────────────────────────────────────────────╯    │
│                                                                                                  │
│ /nix/store/brnivi65vfq079xakl2lcs2kpaq2464a-python3.11-plum_dispatch-2.3.2/lib/python3.11/site-p │
│ ackages/plum/resolver.py:320 in resolve                                                          │
│                                                                                                  │
│   317 │   │                                                                                      │
│   318 │   │   if len(candidates) == 0:                                                           │
│   319 │   │   │   # There is no matching signature.                                              │
│ ❱ 320 │   │   │   raise NotFoundLookupError(self.function_name, target, self.methods)            │
│   321 │   │                                                                                      │
│   322 │   │   elif len(candidates) == 1:                                                         │
│   323 │   │   │   # There is exactly one matching signature. Success!                            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ candidates = []                                                                              │ │
│ │      check = <function Resolver.resolve.<locals>.check at 0x7fa88f287240>                    │ │
│ │       self = <plum.resolver.Resolver object at 0x7fa88f28eb80>                               │ │
│ │     target = (                                                                               │ │
│ │              │   <class 'plum_off.bundle.Bundle'>,                                           │ │
│ │              │   'bundle',                                                                   │ │
│ │              │   (),                                                                         │ │
│ │              │   {                                                                           │ │
│ │              │   │   '__dispatcher__': <plum.dispatcher.Dispatcher object at                 │ │
│ │              0x7fa88f398990>,                                                                │ │
│ │              │   │   '__module__': 'plum_off.bundle',                                        │ │
│ │              │   │   '__qualname__': 'bundle'                                                │ │
│ │              │   }                                                                           │ │
│ │              )                                                                               │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
NotFoundLookupError: `process(<class 'plum_off.bundle.Bundle'>, 'bundle', (), {'__dispatcher__': <plum.dispatcher.Dispatcher object at 0x7fa88f398990>, '__module__':
'plum_off.bundle',
'__qualname__': 'bundle'})` could not be resolved.

Closest candidates are the following:
    process(_: [1mtype[0m)
        <function process at 0x7fa88f286f20> @
]8;id=869878;file:///mnt/wsl/sylvorg/tests/plum-off/plum_off/python.py#24[37m~/tests/plum-off/plum_off/[0m]8;;]8;id=380415;file:///mnt/wsl/sylvorg/tests/plum-off/p
lum_off/python.py#24[1;4;37mpython.py[0m]8;;]8;id=869878;file:///mnt/wsl/sylvorg/tests/plum-off/plum_off/python.py#24[37m:24[0m]8;;

If the signatures are too difficult to read:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/mnt/wsl/sylvorg/tests/plum-off/plum_off/__init__.py", line 13, in <module>
    from plum_off.bundle import *
  File "/mnt/wsl/sylvorg/tests/plum-off/plum_off/bundle.py", line 9, in <module>
    class bundle(metaclass=Bundle):
  File "/mnt/wsl/sylvorg/tests/plum-off/lib/python3.11/site-packages/plum/function.py", line 367, in __call__
    method, return_type = self._resolve_method_with_cache(args=args)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/wsl/sylvorg/tests/plum-off/lib/python3.11/site-packages/plum/function.py", line 398, in _resolve_method_with_cache
    method, return_type = self.resolve_method(args)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/wsl/sylvorg/tests/plum-off/lib/python3.11/site-packages/plum/function.py", line 318, in resolve_method
    impl, return_type = self._handle_not_found_lookup_error(e)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/wsl/sylvorg/tests/plum-off/lib/python3.11/site-packages/plum/function.py", line 327, in _handle_not_found_lookup_error
    raise ex from None
  File "/mnt/wsl/sylvorg/tests/plum-off/lib/python3.11/site-packages/plum/function.py", line 300, in resolve_method
    method = self._resolver.resolve(target)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/mnt/wsl/sylvorg/tests/plum-off/lib/python3.11/site-packages/plum/resolver.py", line 320, in resolve
    raise NotFoundLookupError(self.function_name, target, self.methods)
plum.resolver.NotFoundLookupError: `process(<class 'plum_off.bundle.Bundle'>, 'bundle', (), {'__dispatcher__': <plum.dispatcher.Dispatcher object at 0x7f833a6fcd50>, '__module__': 'plum_off.bundle',
'__qualname__': 'bundle'})` could not be resolved.

Closest candidates are the following:
    process(_: type)
        <function process at 0x7f833a5e3ce0> @ ~/tests/plum-off/plum_off/python.py:24

Since the problem seems to go away when beartype_this_package is removed or commented out, I'm pinging @leycec as well!

Sorry for all the issues recently, and thank you kindly for the help!

wesselb commented 1 month ago

Hey @sylvorg! Hmmm, this looks pretty complicated.

Concretely, the error comes up because process is called with more arguments than defined. Could you try changing the definition to this, to see if that works?

@dispatch
def process(_: type, *args):
    pass
sylvorg commented 1 month ago

Nope:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /nix/store/a1zmsz063k8fl5c6xvmzfnmw8bri0g36-python3.11-beartype-0.16.4/lib/python3.11/site-packa │
│ ges/beartype/_decor/decorcore.py:214 in _beartype_object_nonfatal                                │
│                                                                                                  │
│   211 │                                                                                          │
│   212 │   # Attempt to decorate the passed beartypeable.                                         │
│   213 │   try:                                                                                   │
│ ❱ 214 │   │   return _beartype_object_fatal(obj, conf=conf, **kwargs)                            │
│   215 │   # If doing so unexpectedly raises an exception, coerce that fatal exception            │
│   216 │   # into a non-fatal warning for nebulous safety.                                        │
│   217 │   except Exception as exception:                                                         │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │             conf = BeartypeConf(warning_cls_on_decorator_exception=<class                    │ │
│ │                    'beartype.roar._roarwarn.BeartypeClawDecorWarning'>)                      │ │
│ │    error_message = '\n    beartype.roar.BeartypeDecorWrappeeException: Uncallable None not   │ │
│ │                    decoratabl'+15                                                            │ │
│ │           kwargs = {}                                                                        │ │
│ │              obj = None                                                                      │ │
│ │ warning_category = <class 'beartype.roar._roarwarn.BeartypeClawDecorWarning'>                │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /nix/store/a1zmsz063k8fl5c6xvmzfnmw8bri0g36-python3.11-beartype-0.16.4/lib/python3.11/site-packa │
│ ges/beartype/_decor/decorcore.py:136 in _beartype_object_fatal                                   │
│                                                                                                  │
│   133 │   │   if isinstance(obj, type) else                                                      │
│   134 │   │   # Else, this object is a non-class. In this case, this non-class                   │
│   135 │   │   # decorated with type-checking.                                                    │
│ ❱ 136 │   │   beartype_nontype(obj, **kwargs)  # type: ignore[return-value]                      │
│   137 │   )                                                                                      │
│   138                                                                                            │
│   139                                                                                            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ kwargs = {                                                                                   │ │
│ │          │   'conf': BeartypeConf(warning_cls_on_decorator_exception=<class                  │ │
│ │          'beartype.roar._roarwarn.BeartypeClawDecorWarning'>)                                │ │
│ │          }                                                                                   │ │
│ │    obj = None                                                                                │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /nix/store/a1zmsz063k8fl5c6xvmzfnmw8bri0g36-python3.11-beartype-0.16.4/lib/python3.11/site-packa │
│ ges/beartype/_decor/_decornontype.py:122 in beartype_nontype                                     │
│                                                                                                  │
│   119 │   #                                                                                      │
│   120 │   # If this object is uncallable, raise an exception.                                    │
│   121 │   elif not callable(obj):                                                                │
│ ❱ 122 │   │   raise BeartypeDecorWrappeeException(                                               │
│   123 │   │   │   f'Uncallable {repr(obj)} not decoratable by @beartype.')                       │
│   124 │   # Else, this object is callable.                                                       │
│   125 │   #                                                                                      │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │   kwargs = {                                                                                 │ │
│ │            │   'conf': BeartypeConf(warning_cls_on_decorator_exception=<class                │ │
│ │            'beartype.roar._roarwarn.BeartypeClawDecorWarning'>)                              │ │
│ │            }                                                                                 │ │
│ │      obj = None                                                                              │ │
│ │ obj_type = <class 'NoneType'>                                                                │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
BeartypeDecorWrappeeException: Uncallable None not decoratable by @beartype.

During handling of the above exception, another exception occurred:

╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ in <module>:1                                                                                    │
│                                                                                                  │
│ /mnt/wsl/sylvorg/tests/plum-off/plum_off/__init__.py:13 in <module>                              │
│                                                                                                  │
│   10                                                                                             │
│   11 beartype_this_package()                                                                     │
│   12                                                                                             │
│ ❱ 13 from plum_off.bundle import *                                                               │
│   14                                                                                             │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ beartype_this_package = <function beartype_this_package at 0x7fac2998d4e0>                   │ │
│ │                python = <module 'plum_off.python' from                                       │ │
│ │                         '/mnt/wsl/sylvorg/tests/plum-off/plum_off/python.py'>                │ │
│ │            RichPretty = <module 'rich.pretty' from                                           │ │
│ │                         '/nix/store/m3ww19ir18vfggdpjwmglar2rs6fg627-python3.11-rich-13.5.2… │ │
│ │         RichTraceback = <module 'rich.traceback' from                                        │ │
│ │                         '/nix/store/m3ww19ir18vfggdpjwmglar2rs6fg627-python3.11-rich-13.5.2… │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /mnt/wsl/sylvorg/tests/plum-off/plum_off/bundle.py:9 in <module>                                 │
│                                                                                                  │
│    6 │   │   pass                                                                                │
│    7                                                                                             │
│    8                                                                                             │
│ ❱  9 class bundle(metaclass=Bundle):                                                             │
│   10 │   pass                                                                                    │
│   11                                                                                             │
│                                                                                                  │
│ ╭────────────────────────────────────────── locals ──────────────────────────────────────────╮   │
│ │  Bundle = <class 'plum_off.bundle.Bundle'>                                                 │   │
│ │ plumeta = <class 'plum_off.python.plumeta'>                                                │   │
│ │ process = <multiple-dispatch function process (with 1 registered and 0 pending method(s))> │   │
│ ╰────────────────────────────────────────────────────────────────────────────────────────────╯   │
│                                                                                                  │
│ /nix/store/a1zmsz063k8fl5c6xvmzfnmw8bri0g36-python3.11-beartype-0.16.4/lib/python3.11/site-packa │
│ ges/beartype/_decor/decorcache.py:130 in beartype_confed                                         │
│                                                                                                  │
│   127 │   │                                                                                      │
│   128 │   │   # Decorate this object with type-checking configured by this                       │
│   129 │   │   # configuration.                                                                   │
│ ❱ 130 │   │   return beartype_object(obj, conf)                                                  │
│   131 │                                                                                          │
│   132 │   # Cache this private decorator against this configuration.                             │
│   133 │   _bear_conf_to_decor[conf] = beartype_confed                                            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │ conf = BeartypeConf(warning_cls_on_decorator_exception=<class                                │ │
│ │        'beartype.roar._roarwarn.BeartypeClawDecorWarning'>)                                  │ │
│ │  obj = None                                                                                  │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /nix/store/a1zmsz063k8fl5c6xvmzfnmw8bri0g36-python3.11-beartype-0.16.4/lib/python3.11/site-packa │
│ ges/beartype/_decor/decorcore.py:95 in beartype_object                                           │
│                                                                                                  │
│    92 │   │   # Else, this beartype configuration requests that this decorator emit              │
│    93 │   │   # fatal warnings at decoration time. In this case, defer to the                    │
│    94 │   │   # lower-level decorator doing so.                                                  │
│ ❱  95 │   │   _beartype_object_nonfatal(obj, conf=conf, **kwargs)                                │
│    96 │   )                                                                                      │
│    97                                                                                            │
│    98 # ....................{ PRIVATE ~ decorators               }....................           │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │   conf = BeartypeConf(warning_cls_on_decorator_exception=<class                              │ │
│ │          'beartype.roar._roarwarn.BeartypeClawDecorWarning'>)                                │ │
│ │ kwargs = {}                                                                                  │ │
│ │    obj = None                                                                                │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /nix/store/a1zmsz063k8fl5c6xvmzfnmw8bri0g36-python3.11-beartype-0.16.4/lib/python3.11/site-packa │
│ ges/beartype/_decor/decorcore.py:253 in _beartype_object_nonfatal                                │
│                                                                                                  │
│   250 │   │   #   capitalized such that the first character is uppercase.                        │
│   251 │   │   # * This indented exception message.                                               │
│   252 │   │   warning_message = uppercase_str_char_first(                                        │
│ ❱ 253 │   │   │   f'{prefix_beartypeable(obj)}{label_object_context(obj)}:'                      │
│   254 │   │   │   f'{error_message}'                                                             │
│   255 │   │   )                                                                                  │
│   256                                                                                            │
│                                                                                                  │
│ ╭─────────────────────────────────────────── locals ───────────────────────────────────────────╮ │
│ │             conf = BeartypeConf(warning_cls_on_decorator_exception=<class                    │ │
│ │                    'beartype.roar._roarwarn.BeartypeClawDecorWarning'>)                      │ │
│ │    error_message = '\n    beartype.roar.BeartypeDecorWrappeeException: Uncallable None not   │ │
│ │                    decoratabl'+15                                                            │ │
│ │           kwargs = {}                                                                        │ │
│ │              obj = None                                                                      │ │
│ │ warning_category = <class 'beartype.roar._roarwarn.BeartypeClawDecorWarning'>                │ │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                  │
│ /nix/store/a1zmsz063k8fl5c6xvmzfnmw8bri0g36-python3.11-beartype-0.16.4/lib/python3.11/site-packa │
│ ges/beartype/_util/text/utiltextprefix.py:63 in prefix_beartypeable                              │
│                                                                                                  │
│    60 │   │   if isinstance(obj, type) else                                                      │
│    61 │   │   # Else, this beartypeable is a callable. In this case, a label                     │
│    62 │   │   # describing this callable.                                                        │
│ ❱  63 │   │   f'{label_callable(func=obj, is_color=is_color)} '  # type: ignore[arg-type]        │
│    64 │   )                                                                                      │
│    65                                                                                            │
│    66                                                                                            │
│                                                                                                  │
│ ╭───── locals ─────╮                                                                             │
│ │ is_color = False │                                                                             │
│ │      obj = None  │                                                                             │
│ ╰──────────────────╯                                                                             │
│                                                                                                  │
│ /nix/store/a1zmsz063k8fl5c6xvmzfnmw8bri0g36-python3.11-beartype-0.16.4/lib/python3.11/site-packa │
│ ges/beartype/_util/text/utiltextlabel.py:179 in label_callable                                   │
│                                                                                                  │
│   176 │   str                                                                                    │
│   177 │   │   Human-readable label describing this callable.                                     │
│   178 │   '''                                                                                    │
│ ❱ 179 │   assert callable(func), f'{repr(func)} uncallable.'                                     │
│   180 │   assert isinstance(is_context, bool) or is_context is None, (  # <-- "NoneTypeOr" is    │
│   181 │   │   f'{repr(is_context)} not tri-state boolean.')                                      │
│   182                                                                                            │
│                                                                                                  │
│ ╭────── locals ──────╮                                                                           │
│ │       func = None  │                                                                           │
│ │   is_color = False │                                                                           │
│ │ is_context = None  │                                                                           │
│ ╰────────────────────╯                                                                           │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
AssertionError: None uncallable.
wesselb commented 1 month ago

@sylvorg Oof, I'm really not sure what is happening here. Are you sure that the issue here is on Plum's side?

@dispatch
def process(_: type, *args):
    pass

Is this implementation correct? I'm not sure what process is supposed to do.

Should it be something like this?

@dispatch
def process(x: type, *args):
    return x

I'm not sure.

sylvorg commented 1 month ago

Oof, I'm really not sure what is happening here. Are you sure that the issue here is on Plum's side?

Unlikely; pinging @leycec again, as this seems to only be happening when beartype_this_package() is used. 😅 Sorry about this, old friend!