Use dict instead of OrderedDict on Python 3.7

OrderedDict is quite a bit heavier than just a dict.
This commit is contained in:
Ran Benita 2020-04-30 15:49:20 +03:00
parent 4787fd64a4
commit fcc473ab1c
4 changed files with 27 additions and 15 deletions

View File

@ -6,7 +6,6 @@ ignores the external pytest-cache
""" """
import json import json
import os import os
from collections import OrderedDict
from typing import Dict from typing import Dict
from typing import Generator from typing import Generator
from typing import List from typing import List
@ -23,6 +22,7 @@ from .pathlib import rm_rf
from .reports import CollectReport from .reports import CollectReport
from _pytest import nodes from _pytest import nodes
from _pytest._io import TerminalWriter from _pytest._io import TerminalWriter
from _pytest.compat import order_preserving_dict
from _pytest.config import Config from _pytest.config import Config
from _pytest.main import Session from _pytest.main import Session
from _pytest.python import Module from _pytest.python import Module
@ -338,8 +338,8 @@ class NFPlugin:
self, session: Session, config: Config, items: List[nodes.Item] self, session: Session, config: Config, items: List[nodes.Item]
) -> None: ) -> None:
if self.active: if self.active:
new_items = OrderedDict() # type: OrderedDict[str, nodes.Item] new_items = order_preserving_dict() # type: Dict[str, nodes.Item]
other_items = OrderedDict() # type: OrderedDict[str, nodes.Item] other_items = order_preserving_dict() # type: Dict[str, nodes.Item]
for item in items: for item in items:
if item.nodeid not in self.cached_nodeids: if item.nodeid not in self.cached_nodeids:
new_items[item.nodeid] = item new_items[item.nodeid] = item

View File

@ -381,3 +381,15 @@ else:
return self return self
value = instance.__dict__[self.func.__name__] = self.func(instance) value = instance.__dict__[self.func.__name__] = self.func(instance)
return value return value
# Sometimes an algorithm needs a dict which yields items in the order in which
# they were inserted when iterated. Since Python 3.7, `dict` preserves
# insertion order. Since `dict` is faster and uses less memory than
# `OrderedDict`, prefer to use it if possible.
if sys.version_info >= (3, 7):
order_preserving_dict = dict
else:
from collections import OrderedDict
order_preserving_dict = OrderedDict

View File

@ -4,7 +4,6 @@ import sys
import warnings import warnings
from collections import defaultdict from collections import defaultdict
from collections import deque from collections import deque
from collections import OrderedDict
from typing import Dict from typing import Dict
from typing import List from typing import List
from typing import Tuple from typing import Tuple
@ -26,6 +25,7 @@ from _pytest.compat import getimfunc
from _pytest.compat import getlocation from _pytest.compat import getlocation
from _pytest.compat import is_generator from _pytest.compat import is_generator
from _pytest.compat import NOTSET from _pytest.compat import NOTSET
from _pytest.compat import order_preserving_dict
from _pytest.compat import safe_getattr from _pytest.compat import safe_getattr
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
from _pytest.deprecated import FILLFUNCARGS from _pytest.deprecated import FILLFUNCARGS
@ -220,12 +220,14 @@ def reorder_items(items):
argkeys_cache[scopenum] = d = {} argkeys_cache[scopenum] = d = {}
items_by_argkey[scopenum] = item_d = defaultdict(deque) items_by_argkey[scopenum] = item_d = defaultdict(deque)
for item in items: for item in items:
keys = OrderedDict.fromkeys(get_parametrized_fixture_keys(item, scopenum)) keys = order_preserving_dict.fromkeys(
get_parametrized_fixture_keys(item, scopenum)
)
if keys: if keys:
d[item] = keys d[item] = keys
for key in keys: for key in keys:
item_d[key].append(item) item_d[key].append(item)
items = OrderedDict.fromkeys(items) items = order_preserving_dict.fromkeys(items)
return list(reorder_items_atscope(items, argkeys_cache, items_by_argkey, 0)) return list(reorder_items_atscope(items, argkeys_cache, items_by_argkey, 0))
@ -240,17 +242,17 @@ def reorder_items_atscope(items, argkeys_cache, items_by_argkey, scopenum):
return items return items
ignore = set() ignore = set()
items_deque = deque(items) items_deque = deque(items)
items_done = OrderedDict() items_done = order_preserving_dict()
scoped_items_by_argkey = items_by_argkey[scopenum] scoped_items_by_argkey = items_by_argkey[scopenum]
scoped_argkeys_cache = argkeys_cache[scopenum] scoped_argkeys_cache = argkeys_cache[scopenum]
while items_deque: while items_deque:
no_argkey_group = OrderedDict() no_argkey_group = order_preserving_dict()
slicing_argkey = None slicing_argkey = None
while items_deque: while items_deque:
item = items_deque.popleft() item = items_deque.popleft()
if item in items_done or item in no_argkey_group: if item in items_done or item in no_argkey_group:
continue continue
argkeys = OrderedDict.fromkeys( argkeys = order_preserving_dict.fromkeys(
k for k in scoped_argkeys_cache.get(item, []) if k not in ignore k for k in scoped_argkeys_cache.get(item, []) if k not in ignore
) )
if not argkeys: if not argkeys:

View File

@ -3,7 +3,6 @@
This is a good source for looking at the various reporting hooks. This is a good source for looking at the various reporting hooks.
""" """
import argparse import argparse
import collections
import datetime import datetime
import inspect import inspect
import platform import platform
@ -28,6 +27,7 @@ from more_itertools import collapse
import pytest import pytest
from _pytest import nodes from _pytest import nodes
from _pytest._io import TerminalWriter from _pytest._io import TerminalWriter
from _pytest.compat import order_preserving_dict
from _pytest.config import Config from _pytest.config import Config
from _pytest.config import ExitCode from _pytest.config import ExitCode
from _pytest.deprecated import TERMINALWRITER_WRITER from _pytest.deprecated import TERMINALWRITER_WRITER
@ -839,8 +839,8 @@ class TerminalReporter:
return return
reports_grouped_by_message = ( reports_grouped_by_message = (
collections.OrderedDict() order_preserving_dict()
) # type: collections.OrderedDict[str, List[WarningReport]] ) # type: Dict[str, List[WarningReport]]
for wr in warning_reports: for wr in warning_reports:
reports_grouped_by_message.setdefault(wr.message, []).append(wr) reports_grouped_by_message.setdefault(wr.message, []).append(wr)
@ -854,9 +854,7 @@ class TerminalReporter:
if len(locations) < 10: if len(locations) < 10:
return "\n".join(map(str, locations)) return "\n".join(map(str, locations))
counts_by_filename = ( counts_by_filename = order_preserving_dict() # type: Dict[str, int]
collections.OrderedDict()
) # type: collections.OrderedDict[str, int]
for loc in locations: for loc in locations:
key = str(loc).split("::", 1)[0] key = str(loc).split("::", 1)[0]
counts_by_filename[key] = counts_by_filename.get(key, 0) + 1 counts_by_filename[key] = counts_by_filename.get(key, 0) + 1