Skip to content

[FEATURE] Implement AdjustLink helper type #31

@AliiiBenn

Description

@AliiiBenn

Description

Implement the AdjustLink helper type as mentioned in PEP 827.

Problem

AdjustLink is a helper type referenced in PEP 827 for handling ORM-style relations. It wraps a type in list if the link is a MultiLink (one-to-many), otherwise returns the type as-is.

Usage Examples

# One-to-one relationship (Link) - returns the type directly
type UserProfile = AdjustLink[Profile, Link[Profile]]
# Results in: Profile

# One-to-many relationship (MultiLink) - wraps in list
type UserPosts = AdjustLink[Post, MultiLink[Post]]
# Results in: list[Post]

Real-world context

This is designed for Prisma-style ORMs where fields can be:

  • Property[int] → raw Python type (int)
  • Link[User] → related model (User)
  • MultiLink[Post] → list of related models (list[Post])

AdjustLink automatically handles the distinction between:

  • Link (one-to-one): returns T
  • MultiLink (one-to-many): returns list[T]

Proposed Implementation

Step 1: Define operator class in typing.py

class AdjustLink[Tgt, LinkTy]:
    pass

Step 2: Implement evaluator in _eval_operators.py

@type_eval.register_evaluator(AdjustLink)
def _eval_AdjustLink(tgt, link_ty, *, ctx):
    # 1. Evaluate both arguments
    tgt = _eval_types(tgt, ctx)
    link_ty = _eval_types(link_ty, ctx)
    
    # 2. Check if LinkTy is a MultiLink
    is_multilink = _eval_types(IsAssignable[link_ty, MultiLink], ctx)
    
    # 3. Return list[tgt] if MultiLink, otherwise tgt
    if is_multilink:
        return list[tgt]
    return tgt

Step 3: Export in typemap_extensions/init.py

from typemap.typing import AdjustLink

Dependencies

  • Uses existing IsAssignable for type checking
  • Uses existing MultiLink class (from tests or needs to be added)

Implementation Order

AdjustLink is the simplest and can be implemented first. It is also used by ConvertField, so implementing it enables testing ConvertField.

Priority

  • priority:critical
  • priority:high
  • priority:medium
  • priority:low

Estimated Effort

  • effort:xs - Simple conditional logic
  • effort:s
  • effort:m
  • effort:l
  • effort:xl

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions