Merge pull request #7172 from bluetech/micro-optimizations-1
Some easy micro optimizations to collection
This commit is contained in:
commit
8c2c297e1e
|
@ -6,7 +6,6 @@ ignores the external pytest-cache
|
|||
"""
|
||||
import json
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
from typing import Dict
|
||||
from typing import Generator
|
||||
from typing import List
|
||||
|
@ -23,6 +22,7 @@ from .pathlib import rm_rf
|
|||
from .reports import CollectReport
|
||||
from _pytest import nodes
|
||||
from _pytest._io import TerminalWriter
|
||||
from _pytest.compat import order_preserving_dict
|
||||
from _pytest.config import Config
|
||||
from _pytest.main import Session
|
||||
from _pytest.python import Module
|
||||
|
@ -338,8 +338,8 @@ class NFPlugin:
|
|||
self, session: Session, config: Config, items: List[nodes.Item]
|
||||
) -> None:
|
||||
if self.active:
|
||||
new_items = OrderedDict() # type: OrderedDict[str, nodes.Item]
|
||||
other_items = OrderedDict() # type: OrderedDict[str, nodes.Item]
|
||||
new_items = order_preserving_dict() # type: Dict[str, nodes.Item]
|
||||
other_items = order_preserving_dict() # type: Dict[str, nodes.Item]
|
||||
for item in items:
|
||||
if item.nodeid not in self.cached_nodeids:
|
||||
new_items[item.nodeid] = item
|
||||
|
|
|
@ -381,3 +381,15 @@ else:
|
|||
return self
|
||||
value = instance.__dict__[self.func.__name__] = self.func(instance)
|
||||
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
|
||||
|
|
|
@ -4,7 +4,6 @@ import sys
|
|||
import warnings
|
||||
from collections import defaultdict
|
||||
from collections import deque
|
||||
from collections import OrderedDict
|
||||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Tuple
|
||||
|
@ -26,6 +25,7 @@ from _pytest.compat import getimfunc
|
|||
from _pytest.compat import getlocation
|
||||
from _pytest.compat import is_generator
|
||||
from _pytest.compat import NOTSET
|
||||
from _pytest.compat import order_preserving_dict
|
||||
from _pytest.compat import safe_getattr
|
||||
from _pytest.compat import TYPE_CHECKING
|
||||
from _pytest.deprecated import FILLFUNCARGS
|
||||
|
@ -220,12 +220,14 @@ def reorder_items(items):
|
|||
argkeys_cache[scopenum] = d = {}
|
||||
items_by_argkey[scopenum] = item_d = defaultdict(deque)
|
||||
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:
|
||||
d[item] = keys
|
||||
for key in keys:
|
||||
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))
|
||||
|
||||
|
||||
|
@ -240,17 +242,17 @@ def reorder_items_atscope(items, argkeys_cache, items_by_argkey, scopenum):
|
|||
return items
|
||||
ignore = set()
|
||||
items_deque = deque(items)
|
||||
items_done = OrderedDict()
|
||||
items_done = order_preserving_dict()
|
||||
scoped_items_by_argkey = items_by_argkey[scopenum]
|
||||
scoped_argkeys_cache = argkeys_cache[scopenum]
|
||||
while items_deque:
|
||||
no_argkey_group = OrderedDict()
|
||||
no_argkey_group = order_preserving_dict()
|
||||
slicing_argkey = None
|
||||
while items_deque:
|
||||
item = items_deque.popleft()
|
||||
if item in items_done or item in no_argkey_group:
|
||||
continue
|
||||
argkeys = OrderedDict.fromkeys(
|
||||
argkeys = order_preserving_dict.fromkeys(
|
||||
k for k in scoped_argkeys_cache.get(item, []) if k not in ignore
|
||||
)
|
||||
if not argkeys:
|
||||
|
|
|
@ -91,6 +91,19 @@ class Node(metaclass=NodeMeta):
|
|||
""" base class for Collector and Item the test collection tree.
|
||||
Collector subclasses have children, Items are terminal nodes."""
|
||||
|
||||
# Use __slots__ to make attribute access faster.
|
||||
# Note that __dict__ is still available.
|
||||
__slots__ = (
|
||||
"name",
|
||||
"parent",
|
||||
"config",
|
||||
"session",
|
||||
"fspath",
|
||||
"_nodeid",
|
||||
"_store",
|
||||
"__dict__",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
name: str,
|
||||
|
@ -216,7 +229,7 @@ class Node(metaclass=NodeMeta):
|
|||
return self._nodeid
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.nodeid)
|
||||
return hash(self._nodeid)
|
||||
|
||||
def setup(self):
|
||||
pass
|
||||
|
|
|
@ -365,15 +365,17 @@ class PyCollector(PyobjMixin, nodes.Collector):
|
|||
# NB. we avoid random getattrs and peek in the __dict__ instead
|
||||
# (XXX originally introduced from a PyPy need, still true?)
|
||||
dicts = [getattr(self.obj, "__dict__", {})]
|
||||
for basecls in inspect.getmro(self.obj.__class__):
|
||||
for basecls in self.obj.__class__.__mro__:
|
||||
dicts.append(basecls.__dict__)
|
||||
seen = {}
|
||||
seen = set()
|
||||
values = []
|
||||
for dic in dicts:
|
||||
# Note: seems like the dict can change during iteration -
|
||||
# be careful not to remove the list() without consideration.
|
||||
for name, obj in list(dic.items()):
|
||||
if name in seen:
|
||||
continue
|
||||
seen[name] = True
|
||||
seen.add(name)
|
||||
res = self._makeitem(name, obj)
|
||||
if res is None:
|
||||
continue
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
This is a good source for looking at the various reporting hooks.
|
||||
"""
|
||||
import argparse
|
||||
import collections
|
||||
import datetime
|
||||
import inspect
|
||||
import platform
|
||||
|
@ -28,6 +27,7 @@ from more_itertools import collapse
|
|||
import pytest
|
||||
from _pytest import nodes
|
||||
from _pytest._io import TerminalWriter
|
||||
from _pytest.compat import order_preserving_dict
|
||||
from _pytest.config import Config
|
||||
from _pytest.config import ExitCode
|
||||
from _pytest.deprecated import TERMINALWRITER_WRITER
|
||||
|
@ -839,8 +839,8 @@ class TerminalReporter:
|
|||
return
|
||||
|
||||
reports_grouped_by_message = (
|
||||
collections.OrderedDict()
|
||||
) # type: collections.OrderedDict[str, List[WarningReport]]
|
||||
order_preserving_dict()
|
||||
) # type: Dict[str, List[WarningReport]]
|
||||
for wr in warning_reports:
|
||||
reports_grouped_by_message.setdefault(wr.message, []).append(wr)
|
||||
|
||||
|
@ -854,9 +854,7 @@ class TerminalReporter:
|
|||
if len(locations) < 10:
|
||||
return "\n".join(map(str, locations))
|
||||
|
||||
counts_by_filename = (
|
||||
collections.OrderedDict()
|
||||
) # type: collections.OrderedDict[str, int]
|
||||
counts_by_filename = order_preserving_dict() # type: Dict[str, int]
|
||||
for loc in locations:
|
||||
key = str(loc).split("::", 1)[0]
|
||||
counts_by_filename[key] = counts_by_filename.get(key, 0) + 1
|
||||
|
|
Loading…
Reference in New Issue