@@ -77,6 +77,10 @@ def pytest_addoption(parser):
77
77
dest = "sparse_ordering" ,
78
78
help = "If there are gaps between ordinals they are filled "
79
79
"with unordered tests." )
80
+ group .addoption ("--order-dependencies" , action = "store_true" ,
81
+ dest = "order_dependencies" ,
82
+ help = "If set, dependencies added by pytest-dependency will"
83
+ "be ordered if needed." )
80
84
81
85
82
86
class OrderingPlugin (object ):
@@ -88,14 +92,50 @@ class OrderingPlugin(object):
88
92
"""
89
93
90
94
95
+ class Settings :
96
+ sparse_ordering = False
97
+ order_dependencies = False
98
+ scope = "session"
99
+
100
+ @classmethod
101
+ def initialize (cls , config ):
102
+ cls .sparse_ordering = config .getoption ("sparse_ordering" )
103
+ cls .order_dependencies = config .getoption ("order_dependencies" )
104
+ scope = config .getoption ("order_scope" )
105
+ if scope in ("session" , "module" , "class" ):
106
+ cls .scope = scope
107
+ else :
108
+ if scope is not None :
109
+ warn ("Unknown order scope '{}', ignoring it. "
110
+ "Valid scopes are 'session', 'module' and 'class'."
111
+ .format (scope ))
112
+ cls .scope = "session"
113
+
114
+
91
115
def get_filename (item ):
92
116
name = item .location [0 ]
93
117
if os .sep in name :
94
118
name = item .location [0 ].rsplit (os .sep , 1 )[1 ]
95
119
return name [:- 3 ]
96
120
97
121
98
- def mark_binning (item , keys , start , end , before , after , unordered ):
122
+ def mark_binning (item , keys , start , end , before , after , unordered , alias ):
123
+ if ("dependency" in keys and
124
+ (Settings .order_dependencies or "order" in keys )):
125
+ # always order dependencies if an order mark is present
126
+ # otherwise only if order-dependencies is set
127
+ mark = item .get_closest_marker ("dependency" )
128
+ prefix = get_filename (item ) + "."
129
+ dependent_mark = mark .kwargs .get ("depends" )
130
+ if dependent_mark :
131
+ for name in dependent_mark :
132
+ if "." not in name :
133
+ name = prefix + name
134
+ after .setdefault (name , []).append (item )
135
+ name_mark = mark .kwargs .get ("name" )
136
+ if name_mark :
137
+ alias [prefix + name_mark ] = prefix + item .name
138
+
99
139
if "order" in keys :
100
140
mark = item .get_closest_marker ("order" )
101
141
order = mark .args [0 ] if mark .args else None
@@ -156,22 +196,22 @@ def insert_after(name, items, sort):
156
196
return False
157
197
158
198
159
- def do_modify_items (items , sparse_ordering ):
199
+ def do_modify_items (items ):
160
200
before_item = {}
161
201
after_item = {}
162
202
start_item = {}
163
203
end_item = {}
164
204
unordered_list = []
205
+ alias_names = {}
165
206
166
207
for item in items :
167
208
mark_binning (item , item .keywords .keys (), start_item , end_item ,
168
- before_item , after_item , unordered_list )
209
+ before_item , after_item , unordered_list , alias_names )
169
210
170
211
start_item = sorted (start_item .items ())
171
212
end_item = sorted (end_item .items ())
172
213
173
- sorted_list = sort_numbered_items (start_item , end_item , unordered_list ,
174
- sparse_ordering )
214
+ sorted_list = sort_numbered_items (start_item , end_item , unordered_list )
175
215
176
216
still_left = 0
177
217
length = len (before_item ) + len (after_item )
@@ -187,7 +227,8 @@ def do_modify_items(items, sparse_ordering):
187
227
188
228
remove_labels = []
189
229
for label , after in after_item .items ():
190
- if insert_after (label , after , sorted_list ):
230
+ name = alias_names [label ] if label in alias_names else label
231
+ if insert_after (name , after , sorted_list ):
191
232
remove_labels .append (label )
192
233
for label in remove_labels :
193
234
del after_item [label ]
@@ -207,11 +248,11 @@ def do_modify_items(items, sparse_ordering):
207
248
return sorted_list
208
249
209
250
210
- def sort_numbered_items (start_item , end_item , unordered_list , sparse_ordering ):
251
+ def sort_numbered_items (start_item , end_item , unordered_list ):
211
252
sorted_list = []
212
253
index = 0
213
254
for entries in start_item :
214
- if sparse_ordering :
255
+ if Settings . sparse_ordering :
215
256
while entries [0 ] > index and unordered_list :
216
257
sorted_list .append (unordered_list .pop (0 ))
217
258
index += 1
@@ -220,38 +261,28 @@ def sort_numbered_items(start_item, end_item, unordered_list, sparse_ordering):
220
261
mid_index = len (sorted_list )
221
262
index = - 1
222
263
for entries in reversed (end_item ):
223
- if sparse_ordering :
264
+ if Settings . sparse_ordering :
224
265
while entries [0 ] < index and unordered_list :
225
266
sorted_list .insert (mid_index , unordered_list .pop ())
226
267
index -= 1
227
- for item in reversed (entries [1 ]):
228
- sorted_list .insert (mid_index , item )
229
- index += len (entries [1 ])
230
- for unordered_item in reversed (unordered_list ):
231
- sorted_list .insert (mid_index , unordered_item )
268
+ sorted_list [mid_index :mid_index ] = entries [1 ]
269
+ index -= len (entries [1 ])
270
+ sorted_list [mid_index :mid_index ] = unordered_list
232
271
return sorted_list
233
272
234
273
235
274
def modify_items (session , config , items ):
236
- sparse_ordering = config .getoption ("sparse_ordering" )
237
- scope = config .getoption ("order_scope" )
238
- if scope not in ("session" , "module" , "class" ):
239
- if scope is not None :
240
- warn ("Unknown order scope '{}', ignoring it. "
241
- "Valid scopes are 'session', 'module' and 'class'."
242
- .format (scope ))
243
- scope = "session"
244
- if scope == "session" :
245
- sorted_list = do_modify_items (items , sparse_ordering )
246
- elif scope == "module" :
275
+ Settings .initialize (config )
276
+ if Settings .scope == "session" :
277
+ sorted_list = do_modify_items (items )
278
+ elif Settings .scope == "module" :
247
279
module_items = OrderedDict ()
248
280
for item in items :
249
281
module_path = item .nodeid [:item .nodeid .index ("::" )]
250
282
module_items .setdefault (module_path , []).append (item )
251
283
sorted_list = []
252
284
for module_item_list in module_items .values ():
253
- sorted_list .extend (do_modify_items (
254
- module_item_list , sparse_ordering ))
285
+ sorted_list .extend (do_modify_items (module_item_list ))
255
286
else : # class scope
256
287
class_items = OrderedDict ()
257
288
for item in items :
@@ -262,7 +293,6 @@ def modify_items(session, config, items):
262
293
class_items .setdefault (class_path , []).append (item )
263
294
sorted_list = []
264
295
for class_item_list in class_items .values ():
265
- sorted_list .extend (do_modify_items (
266
- class_item_list , sparse_ordering ))
296
+ sorted_list .extend (do_modify_items (class_item_list ))
267
297
268
298
items [:] = sorted_list
0 commit comments