vercel-labs / vercel-labs/python-typemap

[Bug] `Self` is not evaluating correclty in some cases

Open
#123 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
25
Forks
3
PR merge metrics
No merged PRs in 30d

Description

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__'?

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the failure in test_self.py, then trace the stack through typemap/type_eval/_eval_call.py, _eval_typing.py, _apply_generic.py, and _eval_operators.py, especially the Attrs evaluation and generic boxing path. Done means the example evaluates User.model_dump without the AttributeError and produces the expected type for Self.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.