1616from typemap .typing import (
1717 Attrs ,
1818 Bool ,
19+ Cls ,
1920 Length ,
2021 GetArg ,
2122 GetMemberType ,
2930 Matches ,
3031 Member ,
3132 NewProtocol ,
33+ PropName ,
3234 Slice ,
3335)
3436
@@ -137,13 +139,15 @@ class Table[name: str]:
137139 pass
138140
139141
140- class Field [Table , Name , PyType ]:
142+ class FieldType [Table , Name , PyType ]:
141143 def __lt__ (self , other : Any ) -> Filter [Table ]: ...
142144
143145
144- type FieldTable [T ] = GetArg [T , Field , Literal [0 ]]
145- type FieldName [T ] = GetArg [T , Field , Literal [1 ]]
146- type FieldPyType [T ] = GetArg [T , Field , Literal [2 ]]
146+ type Field [T ] = FieldType [Cls , PropName , T ]
147+
148+ type FieldTable [T : FieldType ] = GetArg [T , FieldType , Literal [0 ]]
149+ type FieldName [T : FieldType ] = GetArg [T , FieldType , Literal [1 ]]
150+ type FieldPyType [T : FieldType ] = GetArg [T , FieldType , Literal [2 ]]
147151
148152
149153class ColumnArgs (TypedDict , total = False ):
@@ -230,7 +234,9 @@ class DbLinkSource[Args: DbLinkSourceArgs](InitField[Args]):
230234
231235type MakeQueryEntryAllFields [T : Table ] = QueryEntry [
232236 T ,
233- tuple [* [GetName [m ] for m in Iter [Attrs [T ]] if IsSub [GetType [m ], Field ]],],
237+ tuple [
238+ * [GetName [m ] for m in Iter [Attrs [T ]] if IsSub [GetType [m ], FieldType ]],
239+ ],
234240]
235241type MakeQueryEntryNamedFields [
236242 T : Table ,
@@ -241,7 +247,7 @@ class DbLinkSource[Args: DbLinkSourceArgs](InitField[Args]):
241247 * [
242248 GetName [m ]
243249 for m in Iter [Attrs [T ]]
244- if IsSub [GetType [m ], Field ]
250+ if IsSub [GetType [m ], FieldType ]
245251 and any (IsSub [FieldName [GetType [m ]], f ] for f in Iter [FieldNames ])
246252 ],
247253 ],
@@ -258,7 +264,7 @@ class DbLinkSource[Args: DbLinkSourceArgs](InitField[Args]):
258264 else [MakeQueryEntryAllFields [New ]]
259265 ),
260266]
261- type AddField [Entries , New : Field ] = tuple [
267+ type AddField [Entries , New : FieldType ] = tuple [
262268 * [ # Existing entries
263269 (
264270 e # Non-matching entry
@@ -276,7 +282,7 @@ class DbLinkSource[Args: DbLinkSourceArgs](InitField[Args]):
276282 if not Bool [EntriesHasTable [Entries , FieldTable [New ]]]
277283 ),
278284]
279- type AddEntries [Entries , News : tuple [Table | Field , ...]] = (
285+ type AddEntries [Entries , News : tuple [Table | FieldType , ...]] = (
280286 Entries
281287 if IsSub [Length [News ], Literal [0 ]]
282288 else AddEntries [
@@ -341,50 +347,44 @@ def execute[Es: tuple[type[Table], ...]](
341347
342348
343349class User (Table [Literal ["users" ]]):
344- id : Field [User , Literal [ "id" ], int ] = column (
350+ id : Field [int ] = column (
345351 db_type = DbInteger (), primary_key = True , autoincrement = True
346352 )
347- name : Field [User , Literal ["name" ], str ] = column (
348- db_type = DbString (length = 150 ), nullable = False
349- )
350- email : Field [User , Literal ["email" ], str ] = column (
353+ name : Field [str ] = column (db_type = DbString (length = 150 ), nullable = False )
354+ email : Field [str ] = column (
351355 db_type = DbString (length = 100 ), unique = True , nullable = False
352356 )
353- age : Field [User , Literal [ "age" ], int | None ] = column (db_type = DbInteger ())
354- active : Field [User , Literal [ "active" ], bool ] = column (
357+ age : Field [int | None ] = column (db_type = DbInteger ())
358+ active : Field [bool ] = column (
355359 db_type = DbBoolean (), default = True , nullable = False
356360 )
357- posts : Field [User , Literal [ "posts" ], list [Post ]] = column (
361+ posts : Field [list [Post ]] = column (
358362 db_type = DbLinkSource (source = "Post" , cardinality = Cardinality .MANY )
359363 )
360364
361365
362366class Post (Table [Literal ["posts" ]]):
363- id : Field [Post , Literal [ "id" ], int ] = column (
367+ id : Field [int ] = column (
364368 db_type = DbInteger (), primary_key = True , autoincrement = True
365369 )
366- content : Field [Post , Literal ["content" ], str ] = column (
367- db_type = DbString (length = 1000 ), nullable = False
368- )
369- author : Field [Post , Literal ["author" ], User ] = column (
370+ content : Field [str ] = column (db_type = DbString (length = 1000 ), nullable = False )
371+ author : Field [User ] = column (
370372 db_type = DbLinkTarget (target = User ), nullable = False
371373 )
372- comments : Field [Post , Literal [ "comments" ], list [Comment ]] = column (
374+ comments : Field [list [Comment ]] = column (
373375 db_type = DbLinkSource (source = "Comment" , cardinality = Cardinality .MANY )
374376 )
375377
376378
377379class Comment (Table [Literal ["comments" ]]):
378- id : Field [Comment , Literal [ "id" ], int ] = column (
380+ id : Field [int ] = column (
379381 db_type = DbInteger (), primary_key = True , autoincrement = True
380382 )
381- content : Field [Comment , Literal ["content" ], str ] = column (
382- db_type = DbString (length = 1000 ), nullable = False
383- )
384- author : Field [Comment , Literal ["author" ], User ] = column (
383+ content : Field [str ] = column (db_type = DbString (length = 1000 ), nullable = False )
384+ author : Field [User ] = column (
385385 db_type = DbLinkTarget (target = User ), nullable = False
386386 )
387- post : Field [Comment , Literal [ "post" ], Post ] = column (
387+ post : Field [Post ] = column (
388388 db_type = DbLinkTarget (target = Post ), nullable = False
389389 )
390390
@@ -573,3 +573,84 @@ class Select[tests.test_qblike_3.User, tuple[typing.Literal['name']]]:
573573 class Select[tests.test_qblike_3.Post, tuple[typing.Literal['content']]]:
574574 content: str
575575 """ )
576+
577+
578+ def test_qblike_3_select_08 ():
579+ class UserAlias (User ):
580+ pass
581+
582+ query = eval_call_with_types (select , UserAlias )
583+ fmt = format_helper .format_class (query )
584+ assert fmt == textwrap .dedent ("""\
585+ class Query[tuple[tuple[tests.test_qblike_3.test_qblike_3_select_08.<locals>.UserAlias, tuple[typing.Literal['id'], typing.Literal['name'], typing.Literal['email'], typing.Literal['age'], typing.Literal['active'], typing.Literal['posts']]]]]:
586+ """ )
587+
588+ results = eval_call_with_types (Session .execute , Session , query )
589+ result = eval_typing (GetArg [results , list , Literal [0 ]])
590+
591+ fmt = format_helper .format_class (result )
592+ assert fmt == textwrap .dedent ("""\
593+ class Select[tests.test_qblike_3.test_qblike_3_select_08.<locals>.UserAlias, tuple[typing.Literal['id'], typing.Literal['name'], typing.Literal['email'], typing.Literal['age'], typing.Literal['active'], typing.Literal['posts']]]:
594+ id: int
595+ name: str
596+ email: str
597+ age: int | None
598+ active: bool
599+ posts: list[tests.test_qblike_3.Post]
600+ """ )
601+
602+
603+ def test_qblike_3_select_09 ():
604+ class UserAlias (User ):
605+ pass
606+
607+ user_alias_name = eval_typing (GetMemberType [UserAlias , Literal ["name" ]])
608+ user_alias_email = eval_typing (GetMemberType [UserAlias , Literal ["email" ]])
609+ query = eval_call_with_types (select , user_alias_name , user_alias_email )
610+ fmt = format_helper .format_class (query )
611+ assert fmt == textwrap .dedent ("""\
612+ class Query[tuple[tuple[tests.test_qblike_3.test_qblike_3_select_09.<locals>.UserAlias, tuple[typing.Literal['name'], typing.Literal['email']]]]]:
613+ """ )
614+
615+ results = eval_call_with_types (Session .execute , Session , query )
616+ result = eval_typing (GetArg [results , list , Literal [0 ]])
617+
618+ fmt = format_helper .format_class (result )
619+ assert fmt == textwrap .dedent ("""\
620+ class Select[tests.test_qblike_3.test_qblike_3_select_09.<locals>.UserAlias, tuple[typing.Literal['name'], typing.Literal['email']]]:
621+ name: str
622+ email: str
623+ """ )
624+
625+
626+ def test_qblike_3_select_10 ():
627+ class UserAlias (User ):
628+ pass
629+
630+ user_name = eval_typing (GetMemberType [User , Literal ["name" ]])
631+ user_alias_name = eval_typing (GetMemberType [UserAlias , Literal ["name" ]])
632+ query = eval_call_with_types (select , user_name , user_alias_name )
633+ fmt = format_helper .format_class (query )
634+ assert fmt == textwrap .dedent ("""\
635+ class Query[tuple[tuple[tests.test_qblike_3.User, tuple[typing.Literal['name']]], tuple[tests.test_qblike_3.test_qblike_3_select_10.<locals>.UserAlias, tuple[typing.Literal['name']]]]]:
636+ """ )
637+
638+ results = eval_call_with_types (Session .execute , Session , query )
639+ result = eval_typing (GetArg [results , list , Literal [0 ]])
640+
641+ result_names = eval_typing (AttrNames [result ])
642+ assert result_names == tuple [Literal ["User" ], Literal ["UserAlias" ]]
643+
644+ result_user = eval_typing (GetMemberType [result , Literal ["User" ]])
645+ fmt = format_helper .format_class (result_user )
646+ assert fmt == textwrap .dedent ("""\
647+ class Select[tests.test_qblike_3.User, tuple[typing.Literal['name']]]:
648+ name: str
649+ """ )
650+
651+ result_user_alias = eval_typing (GetMemberType [result , Literal ["UserAlias" ]])
652+ fmt = format_helper .format_class (result_user_alias )
653+ assert fmt == textwrap .dedent ("""\
654+ class Select[tests.test_qblike_3.test_qblike_3_select_10.<locals>.UserAlias, tuple[typing.Literal['name']]]:
655+ name: str
656+ """ )
0 commit comments