optimize fixtures.reorder_items
This commit is contained in:
parent
b0032ba2b3
commit
ee6c9f50a2
|
@ -4,7 +4,7 @@ import functools
|
||||||
import inspect
|
import inspect
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict, deque, defaultdict
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
import py
|
import py
|
||||||
|
@ -163,62 +163,56 @@ def get_parametrized_fixture_keys(item, scopenum):
|
||||||
|
|
||||||
def reorder_items(items):
|
def reorder_items(items):
|
||||||
argkeys_cache = {}
|
argkeys_cache = {}
|
||||||
|
items_by_argkey = {}
|
||||||
for scopenum in range(0, scopenum_function):
|
for scopenum in range(0, scopenum_function):
|
||||||
argkeys_cache[scopenum] = d = {}
|
argkeys_cache[scopenum] = d = {}
|
||||||
|
items_by_argkey[scopenum] = item_d = defaultdict(list)
|
||||||
for item in items:
|
for item in items:
|
||||||
keys = OrderedDict.fromkeys(get_parametrized_fixture_keys(item, scopenum))
|
keys = OrderedDict.fromkeys(get_parametrized_fixture_keys(item, scopenum))
|
||||||
if keys:
|
if keys:
|
||||||
d[item] = keys
|
d[item] = keys
|
||||||
return reorder_items_atscope(items, set(), argkeys_cache, 0)
|
for key in keys:
|
||||||
|
item_d[key].append(item)
|
||||||
|
|
||||||
|
return list(reorder_items_atscope(items, set(), argkeys_cache, items_by_argkey, 0))
|
||||||
|
|
||||||
|
|
||||||
def reorder_items_atscope(items, ignore, argkeys_cache, scopenum):
|
def reorder_items_atscope(items, ignore, argkeys_cache, items_by_argkey, scopenum):
|
||||||
if scopenum >= scopenum_function or len(items) < 3:
|
if scopenum >= scopenum_function or len(items) < 3:
|
||||||
return items
|
return items
|
||||||
items_done = []
|
items = deque(items)
|
||||||
while 1:
|
items_done = OrderedDict()
|
||||||
items_before, items_same, items_other, newignore = \
|
scoped_items_by_argkey = items_by_argkey[scopenum]
|
||||||
slice_items(items, ignore, argkeys_cache[scopenum])
|
scoped_argkeys_cache = argkeys_cache[scopenum]
|
||||||
items_before = reorder_items_atscope(
|
while items:
|
||||||
items_before, ignore, argkeys_cache, scopenum + 1)
|
|
||||||
if items_same is None:
|
|
||||||
# nothing to reorder in this scope
|
|
||||||
assert items_other is None
|
|
||||||
return items_done + items_before
|
|
||||||
items_done.extend(items_before)
|
|
||||||
items = items_same + items_other
|
|
||||||
ignore = newignore
|
|
||||||
|
|
||||||
|
no_argkey_group = OrderedDict()
|
||||||
|
slicing_argkey = None
|
||||||
|
|
||||||
|
while items:
|
||||||
|
item = items.popleft()
|
||||||
|
if item in items_done:
|
||||||
|
continue
|
||||||
|
|
||||||
|
argkeys = OrderedDict.fromkeys(k for k in scoped_argkeys_cache.get(item, ()) if k not in ignore)
|
||||||
|
if not argkeys:
|
||||||
|
no_argkey_group[item] = None
|
||||||
|
|
||||||
def slice_items(items, ignore, scoped_argkeys_cache):
|
|
||||||
# we pick the first item which uses a fixture instance in the
|
|
||||||
# requested scope and which we haven't seen yet. We slice the input
|
|
||||||
# items list into a list of items_nomatch, items_same and
|
|
||||||
# items_other
|
|
||||||
if scoped_argkeys_cache: # do we need to do work at all?
|
|
||||||
it = iter(items)
|
|
||||||
# first find a slicing key
|
|
||||||
for i, item in enumerate(it):
|
|
||||||
argkeys = scoped_argkeys_cache.get(item)
|
|
||||||
if argkeys is not None:
|
|
||||||
newargkeys = OrderedDict.fromkeys(k for k in argkeys if k not in ignore)
|
|
||||||
if newargkeys: # found a slicing key
|
|
||||||
slicing_argkey, _ = newargkeys.popitem()
|
|
||||||
items_before = items[:i]
|
|
||||||
items_same = [item]
|
|
||||||
items_other = []
|
|
||||||
# now slice the remainder of the list
|
|
||||||
for item in it:
|
|
||||||
argkeys = scoped_argkeys_cache.get(item)
|
|
||||||
if argkeys and slicing_argkey in argkeys and \
|
|
||||||
slicing_argkey not in ignore:
|
|
||||||
items_same.append(item)
|
|
||||||
else:
|
else:
|
||||||
items_other.append(item)
|
slicing_argkey, _ = argkeys.popitem()
|
||||||
newignore = ignore.copy()
|
#we don't have to remove relevant items from later in the deque because they'll just be ignored
|
||||||
newignore.add(slicing_argkey)
|
items.extendleft(reversed(scoped_items_by_argkey[slicing_argkey]))
|
||||||
return (items_before, items_same, items_other, newignore)
|
break
|
||||||
return items, None, None, None
|
|
||||||
|
if no_argkey_group:
|
||||||
|
no_argkey_group = reorder_items_atscope(
|
||||||
|
no_argkey_group, set(), argkeys_cache, items_by_argkey, scopenum + 1)
|
||||||
|
for item in no_argkey_group:
|
||||||
|
items_done[item] = None
|
||||||
|
|
||||||
|
ignore.add(slicing_argkey)
|
||||||
|
|
||||||
|
return items_done
|
||||||
|
|
||||||
|
|
||||||
def fillfixtures(function):
|
def fillfixtures(function):
|
||||||
|
|
Loading…
Reference in New Issue