1
1
import sys
2
- from typing import List , Optional , Union , Dict , Tuple
2
+ from typing import Optional , List , Dict , Tuple , Generic , TypeVar
3
3
4
4
from _pytest .python import Function
5
5
6
6
from .settings import Scope , Settings
7
7
8
8
9
+ _ItemType = TypeVar ("_ItemType" , "Item" , "ItemGroup" )
10
+
11
+
9
12
class Item :
10
13
"""Represents a single test item."""
11
14
@@ -46,8 +49,8 @@ def __init__(
46
49
items : List [Item ],
47
50
settings : Settings ,
48
51
scope : Scope ,
49
- rel_marks : List ["RelativeMark" ],
50
- dep_marks : List ["RelativeMark" ],
52
+ rel_marks : List ["RelativeMark[Item] " ],
53
+ dep_marks : List ["RelativeMark[Item] " ],
51
54
) -> None :
52
55
self .items = items
53
56
self .settings = settings
@@ -63,16 +66,16 @@ def __init__(
63
66
self .dep_marks = filter_marks (dep_marks , items )
64
67
65
68
def collect_markers (self , item : Item ) -> None :
66
- if item .order is not None :
67
- self .handle_order_mark (item )
69
+ self .handle_order_mark (item )
68
70
if item .nr_rel_items or item .order is None :
69
71
self .unordered_items .append (item )
70
72
71
73
def handle_order_mark (self , item : Item ) -> None :
72
- if item .order < 0 :
73
- self ._end_items .setdefault (item .order , []).append (item )
74
- else :
75
- self ._start_items .setdefault (item .order , []).append (item )
74
+ if item .order is not None :
75
+ if item .order < 0 :
76
+ self ._end_items .setdefault (item .order , []).append (item )
77
+ else :
78
+ self ._start_items .setdefault (item .order , []).append (item )
76
79
77
80
def sort_numbered_items (self ) -> List [Item ]:
78
81
self .start_items = sorted (self ._start_items .items ())
@@ -114,22 +117,26 @@ def print_unhandled_items(self) -> None:
114
117
def number_of_rel_groups (self ) -> int :
115
118
return len (self .rel_marks ) + len (self .dep_marks )
116
119
117
- def handle_rel_marks (self , sorted_list : List [Item ]) -> None :
120
+ def handle_rel_marks (
121
+ self , sorted_list : List [Item ]
122
+ ) -> None :
118
123
self .handle_relative_marks (
119
124
self .rel_marks , sorted_list , self .all_rel_marks
120
125
)
121
126
122
- def handle_dep_marks (self , sorted_list : List [Item ]) -> None :
127
+ def handle_dep_marks (
128
+ self , sorted_list : List [Item ]
129
+ ) -> None :
123
130
self .handle_relative_marks (
124
131
self .dep_marks , sorted_list , self .all_dep_marks
125
132
)
126
133
127
134
@staticmethod
128
135
def handle_relative_marks (
129
- marks : List ["RelativeMark" ],
136
+ marks : List ["RelativeMark[Item] " ],
130
137
sorted_list : List [Item ],
131
- all_marks : List ["RelativeMark" ],
132
- ):
138
+ all_marks : List ["RelativeMark[Item] " ],
139
+ ) -> None :
133
140
for mark in reversed (marks ):
134
141
if move_item (mark , sorted_list ):
135
142
marks .remove (mark )
@@ -138,19 +145,21 @@ def handle_relative_marks(
138
145
def group_order (self ) -> Optional [int ]:
139
146
if self .start_items :
140
147
return self .start_items [0 ][0 ]
141
- if self .end_items :
148
+ elif self .end_items :
142
149
return self .end_items [- 1 ][0 ]
150
+ return None
143
151
144
152
145
153
class ItemGroup :
146
- """Holds a group of sorted items with the same group order scope.
154
+ """
155
+ Holds a group of sorted items with the same group order scope.
147
156
Used for sorting groups similar to Item for sorting items.
148
157
"""
149
158
150
159
def __init__ (
151
160
self , items : Optional [List [Item ]] = None , order : Optional [int ] = None
152
161
) -> None :
153
- self .items = items or []
162
+ self .items : List [ Item ] = items or []
154
163
self .order = order
155
164
self .nr_rel_items = 0
156
165
@@ -168,25 +177,26 @@ def extend(self, groups: List["ItemGroup"], order: Optional[int]) -> None:
168
177
self .order = order
169
178
170
179
171
- class RelativeMark :
172
- """Represents a marker for an item or an item group.
180
+ class RelativeMark (Generic [_ItemType ]):
181
+ """
182
+ Represents a marker for an item or an item group.
173
183
Holds two related items or groups and their relationship.
174
184
"""
175
185
176
186
def __init__ (
177
187
self ,
178
- item : Union [ Item , ItemGroup ] ,
179
- item_to_move : Union [ Item , ItemGroup ] ,
188
+ item : _ItemType ,
189
+ item_to_move : _ItemType ,
180
190
move_after : bool ,
181
191
) -> None :
182
- self .item : Item = item
183
- self .item_to_move : Item = item_to_move
192
+ self .item : _ItemType = item
193
+ self .item_to_move : _ItemType = item_to_move
184
194
self .move_after : bool = move_after
185
195
186
196
187
197
def filter_marks (
188
- marks : List [RelativeMark ], all_items : List [Item ]
189
- ) -> List [RelativeMark ]:
198
+ marks : List [RelativeMark [ _ItemType ] ], all_items : List [Item ]
199
+ ) -> List [RelativeMark [ _ItemType ] ]:
190
200
result = []
191
201
for mark in marks :
192
202
if mark .item in all_items and mark .item_to_move in all_items :
@@ -197,7 +207,7 @@ def filter_marks(
197
207
198
208
199
209
def move_item (
200
- mark : RelativeMark , sorted_items : List [Union [ Item , ItemGroup ] ]
210
+ mark : RelativeMark [ _ItemType ] , sorted_items : List [_ItemType ]
201
211
) -> bool :
202
212
if (
203
213
mark .item not in sorted_items
0 commit comments