@@ -77,6 +77,10 @@ def pytest_addoption(parser):
7777 dest = "sparse_ordering" ,
7878 help = "If there are gaps between ordinals they are filled "
7979 "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." )
8084
8185
8286class OrderingPlugin (object ):
@@ -88,14 +92,50 @@ class OrderingPlugin(object):
8892 """
8993
9094
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+
91115def get_filename (item ):
92116 name = item .location [0 ]
93117 if os .sep in name :
94118 name = item .location [0 ].rsplit (os .sep , 1 )[1 ]
95119 return name [:- 3 ]
96120
97121
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+
99139 if "order" in keys :
100140 mark = item .get_closest_marker ("order" )
101141 order = mark .args [0 ] if mark .args else None
@@ -156,22 +196,22 @@ def insert_after(name, items, sort):
156196 return False
157197
158198
159- def do_modify_items (items , sparse_ordering ):
199+ def do_modify_items (items ):
160200 before_item = {}
161201 after_item = {}
162202 start_item = {}
163203 end_item = {}
164204 unordered_list = []
205+ alias_names = {}
165206
166207 for item in items :
167208 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 )
169210
170211 start_item = sorted (start_item .items ())
171212 end_item = sorted (end_item .items ())
172213
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 )
175215
176216 still_left = 0
177217 length = len (before_item ) + len (after_item )
@@ -187,7 +227,8 @@ def do_modify_items(items, sparse_ordering):
187227
188228 remove_labels = []
189229 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 ):
191232 remove_labels .append (label )
192233 for label in remove_labels :
193234 del after_item [label ]
@@ -207,11 +248,11 @@ def do_modify_items(items, sparse_ordering):
207248 return sorted_list
208249
209250
210- def sort_numbered_items (start_item , end_item , unordered_list , sparse_ordering ):
251+ def sort_numbered_items (start_item , end_item , unordered_list ):
211252 sorted_list = []
212253 index = 0
213254 for entries in start_item :
214- if sparse_ordering :
255+ if Settings . sparse_ordering :
215256 while entries [0 ] > index and unordered_list :
216257 sorted_list .append (unordered_list .pop (0 ))
217258 index += 1
@@ -220,38 +261,28 @@ def sort_numbered_items(start_item, end_item, unordered_list, sparse_ordering):
220261 mid_index = len (sorted_list )
221262 index = - 1
222263 for entries in reversed (end_item ):
223- if sparse_ordering :
264+ if Settings . sparse_ordering :
224265 while entries [0 ] < index and unordered_list :
225266 sorted_list .insert (mid_index , unordered_list .pop ())
226267 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
232271 return sorted_list
233272
234273
235274def 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" :
247279 module_items = OrderedDict ()
248280 for item in items :
249281 module_path = item .nodeid [:item .nodeid .index ("::" )]
250282 module_items .setdefault (module_path , []).append (item )
251283 sorted_list = []
252284 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 ))
255286 else : # class scope
256287 class_items = OrderedDict ()
257288 for item in items :
@@ -262,7 +293,6 @@ def modify_items(session, config, items):
262293 class_items .setdefault (class_path , []).append (item )
263294 sorted_list = []
264295 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 ))
267297
268298 items [:] = sorted_list
0 commit comments