Skip to content

[Bug] Self is not evaluating correclty in some cases #123

@iliyasone

Description

@iliyasone

I am trying to make the real pydantic work using new types introduced into the PEP 827. I think the BaseModel.model_dump is a good start. It is always nice to have fully typed dictionary as a return, especially when unpacking with exclude or include params into another function.

But the problem is that this is not working. I tried fixing Attrs look up, so it is not evaluating broken if TYPE_CHECKING methods, see #122, but it is just opened a problem with a self.

I am guessing that the Self is not substituted with actual type at the right moment... I want to solve this issue, but it would require much deeper understanding of the repository and type system implementation. I would really appreciate any advice on which part of the system I should dive into to fix this.

from typing import Any, Literal, Self, cast
from typemap.type_eval import eval_call_with_types
import typemap_extensions as typing
from pydantic import BaseModel as _BaseModel


type ModelDump[T] = typing.NewTypedDict[
    *[
        typing.Member[field.name, field.type]
        for field in typing.Iter[typing.Attrs[T]]
        if typing.IsAssignable[field.definer, _BaseModel]
        and not typing.IsEquivalent[field.definer, _BaseModel]
        and not typing.IsEquivalent[
            typing.Slice[field.name, Literal[0], Literal[2]], Literal["__"]
        ]
    ]
]


class BaseModel(_BaseModel):
    def model_dump(self, **kwargs: Any) -> ModelDump[Self]:  # type: ignore[override]
        return cast(ModelDump[Self], super().model_dump(**kwargs))
    

class User(BaseModel):
    id: int
    name: str
    age: int

print(format_helper.format_class(eval_call_with_types(User.model_dump, User)))

Full error stack:

(metatypes) iliyasone@iliyasone:~/repositories/innopolis-courses/thesis/metatypes$ uv run test_self.py 
Traceback (most recent call last):
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/test_self.py", line 30, in <module>
    print(format_helper.format_class(eval_call_with_types(User.model_dump, User)),)
                                     ~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_call.py", line 159, in eval_call_with_types
    return eval_func_with_type_vars(func, vars)
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_call.py", line 188, in eval_func_with_type_vars
    return _eval_call_with_type_vars(func, vars, ctx)
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_call.py", line 202, in _eval_call_with_type_vars
    return _eval_typing.eval_typing(rr["return"])
           ~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_typing.py", line 193, in eval_typing
    result = _eval_types(obj, ctx)
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_typing.py", line 232, in _eval_types
    evaled = _eval_types_impl(obj, child_ctx)
  File "/usr/lib/python3.14/functools.py", line 982, in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_typing.py", line 389, in _eval_applied_type_alias
    unpacked = _apply_generic.get_annotations(
        obj, named_args, key='evaluate_value'
    )
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_apply_generic.py", line 245, in get_annotations
    rr = ff(annotationlib.Format.VALUE)
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/test_self.py", line 10, in ModelDump
    for field in typing.Iter[typing.Attrs[T]]
                 ~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/typing.py", line 348, in __iter__
    return evaluator(self)
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_typing.py", line 138, in <lambda>
    lambda t: _eval_types(t, _current_context.get())  # type: ignore[arg-type]
              ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_typing.py", line 234, in _eval_types
    evaled = _eval_types_impl(obj, ctx)
  File "/usr/lib/python3.14/functools.py", line 982, in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_typing.py", line 430, in _eval_applied_class
    new_args = _eval_args(typing.get_args(obj), ctx)
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_typing.py", line 339, in _eval_args
    ev = _eval_types(arg, ctx)
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_typing.py", line 234, in _eval_types
    evaled = _eval_types_impl(obj, ctx)
  File "/usr/lib/python3.14/functools.py", line 982, in wrapper
    return dispatch(args[0].__class__)(*args, **kw)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_typing.py", line 440, in _eval_applied_class
    ret = func(*new_args, ctx=ctx)
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_operators.py", line 429, in wrapper
    func(*[_unwrap_anno(x) for x in xs], ctx=ctx)
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_operators.py", line 884, in _eval_Attrs
    hints = get_annotated_type_hints(
        tp, include_extras=True, attrs_only=True, ctx=ctx
    )
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_operators.py", line 112, in get_annotated_type_hints
    box = cached_box(cls, ctx=ctx)
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_eval_operators.py", line 95, in cached_box
    ctx.box_cache[cls] = box = _apply_generic.box(cls)
                               ~~~~~~~~~~~~~~~~~~^^^^^
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_apply_generic.py", line 141, in box
    return _box(cls, args)
  File "/home/iliyasone/repositories/innopolis-courses/thesis/metatypes/.venv/lib/python3.14/site-packages/typemap/type_eval/_apply_generic.py", line 100, in _box
    orig_bases = cls.__dict__.get("__orig_bases__")
                 ^^^^^^^^^^^^
  File "/usr/lib/python3.14/typing.py", line 538, in __getattr__
    raise AttributeError(item)
AttributeError: __dict__. Did you mean: '__dir__'?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions