Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Improve speed of Generic.__new__. Both PY2 and PY3. Fixes #196.
  • Loading branch information
Guido van Rossum committed Apr 2, 2016
commit e0d1c5dc659db9734c10a1b3c678df9df75fcda0
39 changes: 27 additions & 12 deletions python2/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,20 @@ def _geqv(a, b):
return _gorg(a) is _gorg(b)


def _next_in_mro(cls):
"""Helper for Generic.__new__.

Returns the class after the last occurrence of Generic or
Generic[...] in cls.__mro__.
"""
next_in_mro = object
# Look for the last occurrence of Generic or Generic[...].
for i, c in enumerate(cls.__mro__[:-1]):
if isinstance(c, GenericMeta) and _gorg(c) is Generic:
next_in_mro = cls.__mro__[i+1]
return next_in_mro


class GenericMeta(TypingMeta, abc.ABCMeta):
"""Metaclass for generic types."""

Expand Down Expand Up @@ -919,9 +933,6 @@ def __new__(cls, name, bases, namespace,
# and reject multiple Generic[...].
gvars = None
for base in bases:
if base is object:
# Avoid checking for Generic in its own definition.
continue
if base is Generic:
raise TypeError("Cannot inherit from plain Generic")
if (isinstance(base, GenericMeta) and
Expand Down Expand Up @@ -950,6 +961,8 @@ def __new__(cls, name, bases, namespace,
self.__extra__ = extra
# Else __extra__ is inherited, eventually from the
# (meta-)class default above.
# Speed hack (https://github.com/python/typing/issues/196).
self.__next_in_mro__ = _next_in_mro(self)
return self

def _get_type_vars(self, tvars):
Expand Down Expand Up @@ -1077,6 +1090,10 @@ def __subclasscheck__(self, cls):
return issubclass(cls, self.__extra__)


# Prevent checks for Generic to crash when defining Generic.
Generic = None


class Generic(object):
"""Abstract base class for generic types.

Expand All @@ -1102,16 +1119,13 @@ def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
__slots__ = ()

def __new__(cls, *args, **kwds):
next_in_mro = object
# Look for the last occurrence of Generic or Generic[...].
for i, c in enumerate(cls.__mro__[:-1]):
if isinstance(c, GenericMeta) and _gorg(c) is Generic:
next_in_mro = cls.__mro__[i+1]
origin = _gorg(cls)
obj = next_in_mro.__new__(origin)
if origin is not cls:
if cls.__origin__ is None:
return cls.__next_in_mro__.__new__(cls)
else:
origin = _gorg(cls)
obj = cls.__next_in_mro__.__new__(origin)
obj.__init__(*args, **kwds)
return obj
return obj


def cast(typ, val):
Expand Down Expand Up @@ -1305,6 +1319,7 @@ def _get_protocol_attrs(self):
attr != '__args__' and
attr != '__slots__' and
attr != '_get_protocol_attrs' and
attr != '__next_in_mro__' and
attr != '__parameters__' and
attr != '__origin__' and
attr != '__module__'):
Expand Down
36 changes: 27 additions & 9 deletions src/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,20 @@ def _geqv(a, b):
return _gorg(a) is _gorg(b)


def _next_in_mro(cls):
"""Helper for Generic.__new__.

Returns the class after the last occurrence of Generic or
Generic[...] in cls.__mro__.
"""
next_in_mro = object
# Look for the last occurrence of Generic or Generic[...].
for i, c in enumerate(cls.__mro__[:-1]):
if isinstance(c, GenericMeta) and _gorg(c) is Generic:
next_in_mro = cls.__mro__[i+1]
return next_in_mro


class GenericMeta(TypingMeta, abc.ABCMeta):
"""Metaclass for generic types."""

Expand Down Expand Up @@ -929,6 +943,8 @@ def __new__(cls, name, bases, namespace,
self.__extra__ = extra
# Else __extra__ is inherited, eventually from the
# (meta-)class default above.
# Speed hack (https://github.com/python/typing/issues/196).
self.__next_in_mro__ = _next_in_mro(self)
return self

def _get_type_vars(self, tvars):
Expand Down Expand Up @@ -1056,6 +1072,10 @@ def __subclasscheck__(self, cls):
return issubclass(cls, self.__extra__)


# Prevent checks for Generic to crash when defining Generic.
Generic = None


class Generic(metaclass=GenericMeta):
"""Abstract base class for generic types.

Expand All @@ -1080,16 +1100,13 @@ def lookup_name(mapping: Mapping[KT, VT], key: KT, default: VT) -> VT:
__slots__ = ()

def __new__(cls, *args, **kwds):
next_in_mro = object
# Look for the last occurrence of Generic or Generic[...].
for i, c in enumerate(cls.__mro__[:-1]):
if isinstance(c, GenericMeta) and _gorg(c) is Generic:
next_in_mro = cls.__mro__[i+1]
origin = _gorg(cls)
obj = next_in_mro.__new__(origin)
if origin is not cls:
if cls.__origin__ is None:
return cls.__next_in_mro__.__new__(cls)
else:
origin = _gorg(cls)
obj = cls.__next_in_mro__.__new__(origin)
obj.__init__(*args, **kwds)
return obj
return obj


def cast(typ, val):
Expand Down Expand Up @@ -1283,6 +1300,7 @@ def _get_protocol_attrs(self):
attr != '__args__' and
attr != '__slots__' and
attr != '_get_protocol_attrs' and
attr != '__next_in_mro__' and
attr != '__parameters__' and
attr != '__origin__' and
attr != '__module__'):
Expand Down