1
1
# -*- coding: utf-8 -*-
2
- from . _version import __version__
3
-
4
- import operator
2
+ import os
3
+ import re
4
+ import sys
5
5
6
- import pytest
6
+ from . _version import __version__
7
7
8
8
orders_map = {
9
9
'first' : 0 ,
21
21
'fifth_to_last' : - 5 ,
22
22
'sixth_to_last' : - 6 ,
23
23
'seventh_to_last' : - 7 ,
24
- 'eighth_to_last' : - 8 ,
24
+ 'eighth_to_last' : - 8
25
25
}
26
26
27
27
@@ -34,8 +34,8 @@ def pytest_configure(config):
34
34
)
35
35
36
36
config_line = (
37
- 'run: specify ordering information for when tests should run '
38
- 'in relation to one another. ' + provided_by_pytest_ordering
37
+ 'run: specify ordering information for when tests should run '
38
+ 'in relation to one another. ' + provided_by_pytest_ordering
39
39
)
40
40
config .addinivalue_line ('markers' , config_line )
41
41
@@ -46,37 +46,150 @@ def pytest_configure(config):
46
46
config .addinivalue_line ('markers' , config_line )
47
47
48
48
49
- def pytest_collection_modifyitems (session , config , items ):
50
- grouped_items = {}
51
-
52
- for item in items :
53
-
54
- for mark_name , order in orders_map .items ():
55
- mark = item .get_closest_marker (mark_name )
49
+ def get_filename (item ):
50
+ name = item .location [0 ]
51
+ if os .sep in name :
52
+ name = item .location [0 ].rsplit (os .sep , 1 )[1 ]
53
+ return name [:- 3 ]
56
54
57
- if mark :
58
- item .add_marker (pytest .mark .run (order = order ))
59
- break
60
55
56
+ def mark_binning (item , keys , start , end , before , after , unordered ):
57
+ match_order = re .compile (r"order(\d+)(:?,|$)" )
58
+ find_order = match_order .search ("," .join (keys ))
59
+ if find_order :
60
+ order = int (find_order .group (1 ))
61
+ start .setdefault (order , []).append (item )
62
+ return True
63
+ elif "run" in keys :
61
64
mark = item .get_closest_marker ('run' )
62
-
63
- if mark :
64
- order = mark .kwargs .get ('order' )
65
+ order = mark .kwargs .get ('order' )
66
+ before_mark = mark .kwargs .get ('before' )
67
+ after_mark = mark .kwargs .get ('after' )
68
+ if order is not None :
69
+ order = int (order )
70
+ if order < 0 :
71
+ end .setdefault (order , []).append (item )
72
+ else :
73
+ start .setdefault (order , []).append (item )
74
+ elif before_mark :
75
+ if "." not in before_mark :
76
+ prefix = get_filename (item )
77
+ before_mark = prefix + "." + before_mark
78
+ before .setdefault (before_mark , []).append (item )
79
+ elif after_mark :
80
+ if "." not in after_mark :
81
+ prefix = get_filename (item )
82
+ after_mark = prefix + "." + after_mark
83
+
84
+ after .setdefault (after_mark , []).append (item )
65
85
else :
66
- order = None
67
-
68
- grouped_items .setdefault (order , []).append (item )
69
-
70
- sorted_items = []
71
- unordered_items = [grouped_items .pop (None , [])]
86
+ for ordinal , position in orders_map .items ():
87
+ if ordinal in mark .args :
88
+ if position < 0 :
89
+ end .setdefault (position , []).append (item )
90
+ else :
91
+ start .setdefault (position , []).append (item )
92
+ break
93
+ return True
94
+ for mark_name , order in orders_map .items ():
95
+ mark = item .get_closest_marker (mark_name )
96
+ if mark :
97
+ order = int (order )
98
+ if order < 0 :
99
+ end .setdefault (order , []).append (item )
100
+ else :
101
+ start .setdefault (order , []).append (item )
102
+ return True
103
+ unordered .append (item )
104
+ return False
105
+
106
+
107
+ def insert (items , sort ):
108
+ list_items = []
109
+ if isinstance (items , tuple ):
110
+ list_items = items [1 ]
111
+ else :
112
+ list_items = items
113
+ sort += list_items
114
+
115
+
116
+ def insert_before (name , items , sort ):
117
+ regex_name = re .escape (name ) + r"(:?\.\w+)?$"
118
+ for pos , item in enumerate (sort ):
119
+ prefix = get_filename (item )
120
+ item_name = prefix + "." + item .location [2 ]
121
+ if re .match (regex_name , item_name ):
122
+ if pos == 0 :
123
+ sort [:] = items + sort
124
+ else :
125
+ sort [pos :1 ] = items
126
+ return True
127
+ return False
128
+
129
+
130
+ def insert_after (name , items , sort ):
131
+ regex_name = re .escape (name ) + r"(:?\.\w+)?$"
132
+ for pos , item in reversed (list (enumerate (sort ))):
133
+ prefix = get_filename (item )
134
+ item_name = prefix + "." + item .location [2 ]
135
+ if re .match (regex_name , item_name ):
136
+ sort [pos + 1 :1 ] = items
137
+ return True
138
+
139
+ return False
72
140
73
- start_list = sorted ((i for i in grouped_items .items () if i [0 ] >= 0 ),
74
- key = operator .itemgetter (0 ))
75
- end_list = sorted ((i for i in grouped_items .items () if i [0 ] < 0 ),
76
- key = operator .itemgetter (0 ))
77
141
78
- sorted_items .extend ([i [1 ] for i in start_list ])
79
- sorted_items .extend (unordered_items )
80
- sorted_items .extend ([i [1 ] for i in end_list ])
142
+ def pytest_collection_modifyitems (session , config , items ):
143
+ before_item = {}
144
+ after_item = {}
145
+ start_item = {}
146
+ end_item = {}
147
+ unordered_list = []
81
148
82
- items [:] = [item for sublist in sorted_items for item in sublist ]
149
+ for item in items :
150
+ mark_binning (item , item .keywords .keys (), start_item , end_item ,
151
+ before_item , after_item , unordered_list )
152
+
153
+ start_item = sorted (start_item .items ())
154
+ end_item = sorted (end_item .items ())
155
+
156
+ sorted_list = []
157
+
158
+ for entries in start_item :
159
+ insert (entries , sorted_list )
160
+ insert (unordered_list , sorted_list )
161
+ for entries in end_item :
162
+ insert (entries , sorted_list )
163
+
164
+ still_left = 0
165
+ length = len (before_item ) + len (after_item )
166
+
167
+ while still_left != length :
168
+ still_left = length
169
+ remove_labels = []
170
+ for label , before in before_item .items ():
171
+ if insert_before (label , before , sorted_list ):
172
+ remove_labels .append (label )
173
+ for label in remove_labels :
174
+ del before_item [label ]
175
+
176
+ remove_labels = []
177
+ for label , after in after_item .items ():
178
+ if insert_after (label , after , sorted_list ):
179
+ remove_labels .append (label )
180
+ for label in remove_labels :
181
+ del after_item [label ]
182
+
183
+ length = len (before_item ) + len (after_item )
184
+ if length :
185
+ sys .stdout .write ("WARNING: can not execute test relative to others: " )
186
+ for label , entry in before_item .items ():
187
+ sys .stdout .write (label + " " )
188
+ sorted_list += entry
189
+ for label , entry in after_item .items ():
190
+ sys .stdout .write (label + " " )
191
+ sorted_list += entry
192
+ sys .stdout .flush ()
193
+ print ("enqueue them behind the others" )
194
+
195
+ items [:] = sorted_list
0 commit comments