Respect explicit return type of __new__()#21441
Respect explicit return type of __new__()#21441ilevkivskyi wants to merge 7 commits intopython:masterfrom
Conversation
|
Diff from mypy_primer, showing the effect of this PR on open source code: zope.interface (https://github.com/zopefoundation/zope.interface)
- src/zope/interface/common/tests/test_collections.py:88: error: Incompatible types in assignment (expression has type "set[type[array[int]]]", base class "VerifyClassMixin" defined the type as "tuple[()]") [assignment]
+ src/zope/interface/common/tests/test_collections.py:88: error: Incompatible types in assignment (expression has type "set[type[array[_T]]]", base class "VerifyClassMixin" defined the type as "tuple[()]") [assignment]
comtypes (https://github.com/enthought/comtypes)
- comtypes/server/register.py:226: error: Incompatible types in assignment (expression has type "reversed[tuple[int, str]]", variable has type "list[tuple[int, str]]") [assignment]
+ comtypes/server/register.py:226: error: Incompatible types in assignment (expression has type "Iterator[tuple[int, str]]", variable has type "list[tuple[int, str]]") [assignment]
discord.py (https://github.com/Rapptz/discord.py)
- discord/abc.py:1815: error: Incompatible types in assignment (expression has type "reversed[MessagePin]", variable has type "list[MessagePin]") [assignment]
+ discord/abc.py:1815: error: Incompatible types in assignment (expression has type "Iterator[MessagePin]", variable has type "list[MessagePin]") [assignment]
pandera (https://github.com/pandera-dev/pandera)
+ tests/pandas/test_model.py:1797: error: Argument 1 to "from_records" of "DataFrame" has incompatible type "type[Schema]"; expected "type[DataFrameBase[Schema]]" [arg-type]
pandas-stubs (https://github.com/pandas-dev/pandas-stubs)
+ tests/arrays/test_numpy_.py:60: error: Expression is of type "Any", not "NumpyExtensionArray" [assert-type]
sympy (https://github.com/sympy/sympy)
+ sympy/core/evalf.py:997: error: Argument 1 to "evalf_add" has incompatible type "Expr"; expected "Add" [arg-type]
+ sympy/core/function.py:449: error: Unused "type: ignore" comment [unused-ignore]
+ sympy/core/function.py:959: error: Argument 1 to "pickle" has incompatible type "type[UndefinedFunction]"; expected "type[type[AppliedUndef]]" [arg-type]
+ sympy/solvers/ode/single.py:1985: error: "Expr" has no attribute "name" [attr-defined]
+ sympy/printing/smtlib.py:188: error: Argument 1 to "_print_Unequality" of "SMTLibPrinter" has incompatible type "Unequality | BooleanFalse | BooleanTrue"; expected "Unequality" [arg-type]
+ sympy/printing/smtlib.py:567: error: Item "BooleanFalse" of "Equality | BooleanFalse | BooleanTrue" has no attribute "lhs" [union-attr]
+ sympy/printing/smtlib.py:567: error: Item "BooleanTrue" of "Equality | BooleanFalse | BooleanTrue" has no attribute "lhs" [union-attr]
+ sympy/printing/smtlib.py:567: error: Item "BooleanFalse" of "Equality | BooleanFalse | BooleanTrue" has no attribute "rhs" [union-attr]
+ sympy/printing/smtlib.py:567: error: Item "BooleanTrue" of "Equality | BooleanFalse | BooleanTrue" has no attribute "rhs" [union-attr]
+ sympy/printing/smtlib.py:569: error: Item "BooleanFalse" of "Equality | BooleanFalse | BooleanTrue" has no attribute "rhs" [union-attr]
+ sympy/printing/smtlib.py:569: error: Item "BooleanTrue" of "Equality | BooleanFalse | BooleanTrue" has no attribute "rhs" [union-attr]
+ sympy/printing/smtlib.py:569: error: Item "BooleanFalse" of "Equality | BooleanFalse | BooleanTrue" has no attribute "lhs" [union-attr]
+ sympy/printing/smtlib.py:569: error: Item "BooleanTrue" of "Equality | BooleanFalse | BooleanTrue" has no attribute "lhs" [union-attr]
pandas (https://github.com/pandas-dev/pandas)
+ pandas/tseries/frequencies.py:298: error: Incompatible return value type (got "Timestamp | NaTType", expected "Timestamp") [return-value]
- pandas/core/dtypes/cast.py:698: error: Non-overlapping identity check (left operand type: "Timestamp", right operand type: "NaTType") [comparison-overlap]
- pandas/core/dtypes/cast.py:711: error: Non-overlapping identity check (left operand type: "Timedelta", right operand type: "NaTType") [comparison-overlap]
+ pandas/core/dtypes/cast.py:159: error: Incompatible types in assignment (expression has type "Timestamp | NaTType", variable has type "str | bytes | date | datetime | timedelta | <7 more items> | Interval[Any] | complex | integer[Any] | floating[Any] | complexfloating[Any, Any]") [assignment]
+ pandas/core/dtypes/cast.py:161: error: Incompatible types in assignment (expression has type "Timedelta | NaTType", variable has type "str | bytes | date | datetime | timedelta | <7 more items> | Interval[Any] | complex | integer[Any] | floating[Any] | complexfloating[Any, Any]") [assignment]
+ pandas/core/arrays/_ranges.py:147: error: Incompatible types in assignment (expression has type "Timestamp | NaTType", variable has type "Timestamp | None") [assignment]
+ pandas/core/arrays/datetimes.py:832: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "unit" [union-attr]
+ pandas/core/arrays/datetimes.py:3174: error: Incompatible types in assignment (expression has type "Timestamp | NaTType", variable has type "Timestamp | None") [assignment]
+ pandas/core/arrays/datetimes.py:3174: note: Error code "assignment" not covered by "type: ignore[arg-type]" comment
- pandas/core/arrays/datetimes.py:3175: error: Non-overlapping identity check (left operand type: "Timestamp", right operand type: "NaTType") [comparison-overlap]
+ pandas/core/arrays/datetimes.py:3175: error: Non-overlapping identity check (left operand type: "Timestamp | None", right operand type: "NaTType") [comparison-overlap]
+ pandas/core/arrays/datetimes.py:3176: error: Item "None" of "Timestamp | None" has no attribute "as_unit" [union-attr]
+ pandas/core/arrays/datetimes.py:3182: error: Incompatible types in assignment (expression has type "Timestamp | NaTType", variable has type "Timestamp | None") [assignment]
+ pandas/core/arrays/datetimes.py:3182: note: Error code "assignment" not covered by "type: ignore[arg-type]" comment
- pandas/core/arrays/datetimes.py:3183: error: Non-overlapping identity check (left operand type: "Timestamp", right operand type: "NaTType") [comparison-overlap]
+ pandas/core/arrays/datetimes.py:3183: error: Non-overlapping identity check (left operand type: "Timestamp | None", right operand type: "NaTType") [comparison-overlap]
+ pandas/core/arrays/datetimes.py:3184: error: Item "None" of "Timestamp | None" has no attribute "as_unit" [union-attr]
+ pandas/core/arrays/period.py:385: error: Incompatible return value type (got "Period | NaTType", expected "Period") [return-value]
+ pandas/core/arrays/period.py:1227: error: Argument 1 to "_add_timedelta_arraylike" of "PeriodArray" has incompatible type "ndarray[tuple[Any, ...], dtype[generic[date | int | timedelta | None]]]"; expected "TimedeltaArray | ndarray[tuple[Any, ...], dtype[timedelta64[timedelta | int | None]]]" [arg-type]
+ pandas/core/arrays/period.py:1342: error: Argument 1 to "delta_to_tick" has incompatible type "Timedelta | NaTType"; expected "timedelta" [arg-type]
+ pandas/core/window/rolling.py:2023: error: Incompatible types in assignment (expression has type "int | signedinteger[_64Bit]", variable has type "int | None") [assignment]
+ pandas/core/tools/datetimes.py:608: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_julian_date" [union-attr]
+ pandas/core/tools/datetimes.py:654: error: No overload variant of "__floordiv__" of "Timedelta" matches argument type "NaTType" [operator]
+ pandas/core/tools/datetimes.py:654: note: Possible overload variants:
+ pandas/core/tools/datetimes.py:654: note: def __floordiv__(self, timedelta, /) -> int
+ pandas/core/tools/datetimes.py:654: note: def __floordiv__(self, float, /) -> Timedelta
+ pandas/core/tools/datetimes.py:654: note: def __floordiv__(self, ndarray[tuple[Any, ...], dtype[timedelta64[timedelta | int | None]]], /) -> ndarray[tuple[Any, ...], dtype[signedinteger[_32Bit | _64Bit]]]
+ pandas/core/tools/datetimes.py:654: note: def __floordiv__(self, ndarray[tuple[Any, ...], dtype[number[Any, int | float | complex]]], /) -> ndarray[tuple[Any, ...], dtype[timedelta64[timedelta | int | None]]] | Timedelta
+ pandas/core/tools/datetimes.py:654: note: Both left and right operands are unions
+ pandas/core/indexes/timedeltas.py:324: error: Argument 1 to "to_offset" has incompatible type "Timedelta | NaTType"; expected "timedelta | str | PeriodDtypeBase" [arg-type]
+ pandas/core/indexes/timedeltas.py:324: note: Error code "arg-type" not covered by "type: ignore[operator]" comment
+ pandas/core/indexes/period.py:673: error: Incompatible return value type (got "Period | NaTType", expected "Period") [return-value]
+ pandas/core/indexes/period.py:700: error: Item "NaTType" of "Period | NaTType" has no attribute "asfreq" [union-attr]
+ pandas/core/indexes/datetimes.py:943: error: Unsupported left operand type for % ("NaTType") [operator]
+ pandas/core/indexes/datetimes.py:943: note: Left operand is of type "Timedelta | NaTType"
+ pandas/core/indexes/datetimes.py:1120: error: Item "NaTType" of "Period | NaTType" has no attribute "start_time" [union-attr]
+ pandas/core/indexes/datetimes.py:1123: error: Unsupported operand types for + ("NaTType" and "int") [operator]
+ pandas/core/indexes/datetimes.py:1123: note: Left operand is of type "Period | NaTType"
+ pandas/core/indexes/datetimes.py:1148: error: Incompatible types in assignment (expression has type "Timestamp | NaTType", variable has type "datetime") [assignment]
+ pandas/core/indexes/datetimes.py:1154: error: "datetime" has no attribute "tz_localize" [attr-defined]
+ pandas/core/indexes/datetimes.py:1156: error: Incompatible return value type (got "tuple[datetime, Resolution]", expected "tuple[Timestamp, Resolution]") [return-value]
+ pandas/core/indexes/datetimes.py:1735: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "unit" [union-attr]
+ pandas/core/indexes/datetimes.py:1736: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "unit" [union-attr]
+ pandas/core/indexes/datetimelike.py:1107: error: Argument 1 to "to_offset" has incompatible type "Timedelta | NaTType"; expected "timedelta | str | PeriodDtypeBase" [arg-type]
+ pandas/core/resample.py:2524: error: Incompatible types in assignment (expression has type "Timestamp | NaTType", variable has type "Literal['epoch', 'start', 'start_day', 'end', 'end_day'] | Timestamp") [assignment]
+ pandas/core/resample.py:2648: error: Argument "offset" to "_get_timestamp_range_edges" has incompatible type "Timedelta | NaTType | None"; expected "Timedelta | None" [arg-type]
+ pandas/core/resample.py:2840: error: Argument "offset" to "_get_period_range_edges" has incompatible type "Timedelta | NaTType | None"; expected "Timedelta | None" [arg-type]
+ pandas/core/resample.py:2959: error: Incompatible types in assignment (expression has type "Timestamp | NaTType", variable has type "Literal['epoch', 'start', 'start_day', 'end', 'end_day'] | Timestamp") [assignment]
+ pandas/core/resample.py:2975: error: Incompatible types in assignment (expression has type "Timestamp | NaTType", variable has type "Timestamp") [assignment]
+ pandas/core/resample.py:2977: error: Incompatible types in assignment (expression has type "Timestamp | NaTType", variable has type "Timestamp") [assignment]
+ pandas/core/resample.py:2979: error: Incompatible types in assignment (expression has type "Timestamp | NaTType", variable has type "Timestamp") [assignment]
+ pandas/core/resample.py:3091: error: No overload variant of "__mul__" of "signedinteger" matches argument type "Tick" [operator]
+ pandas/core/resample.py:3091: note: Possible overload variants:
+ pandas/core/resample.py:3091: note: def __mul__(self, int | signedinteger[_8Bit] | numpy.bool[builtins.bool] | signedinteger[_64Bit], /) -> signedinteger[_64Bit]
+ pandas/core/resample.py:3091: note: def __mul__(self, float, /) -> float64
+ pandas/core/resample.py:3091: note: def __mul__(self, complex, /) -> complex128
+ pandas/core/resample.py:3091: note: def __mul__(self, signedinteger[Any], /) -> signedinteger[Any]
+ pandas/core/resample.py:3091: note: def __mul__(self, integer[Any], /) -> Any
+ pandas/core/resample.py:3091: note: Left operand is of type "int | signedinteger[_64Bit]"
+ pandas/core/resample.py:3139: error: Incompatible return value type (got "tuple[Timestamp | NaTType, Timestamp | NaTType]", expected "tuple[Timestamp, Timestamp]") [return-value]
+ pandas/io/excel/_odfreader.py:220: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "time" [union-attr]
+ pandas/tseries/holiday.py:262: error: Incompatible types in assignment (expression has type "Timestamp | NaTType | None", variable has type "Timestamp | None") [assignment]
+ pandas/tseries/holiday.py:264: error: Incompatible types in assignment (expression has type "Timestamp | NaTType | None", variable has type "Timestamp | None") [assignment]
+ pandas/tests/tslibs/test_timedeltas.py:24: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_pytimedelta" [union-attr]
+ pandas/tests/tseries/offsets/test_custom_business_hour.py:277: error: Unsupported operand types for - ("NaTType" and "Nano") [operator]
+ pandas/tests/tseries/offsets/test_custom_business_hour.py:277: note: Left operand is of type "Timestamp | NaTType"
+ pandas/tests/tseries/offsets/test_custom_business_hour.py:278: error: Unsupported operand types for - ("NaTType" and "Nano") [operator]
+ pandas/tests/tseries/offsets/test_custom_business_hour.py:278: note: Left operand is of type "Timestamp | NaTType"
+ pandas/tests/tseries/offsets/test_custom_business_hour.py:288: error: Unsupported operand types for - ("NaTType" and "Nano") [operator]
+ pandas/tests/tseries/offsets/test_custom_business_hour.py:288: note: Left operand is of type "Timestamp | NaTType"
+ pandas/tests/tseries/offsets/test_custom_business_hour.py:289: error: Unsupported operand types for - ("NaTType" and "Nano") [operator]
+ pandas/tests/tseries/offsets/test_custom_business_hour.py:289: note: Left operand is of type "Timestamp | NaTType"
+ pandas/tests/tseries/offsets/test_business_day.py:78: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_pytimedelta" [union-attr]
+ pandas/tests/tseries/offsets/test_business_day.py:79: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_timedelta64" [union-attr]
+ pandas/tests/series/indexing/test_setitem.py:512: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_timedelta64" [union-attr]
+ pandas/tests/series/indexing/test_setitem.py:513: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_pytimedelta" [union-attr]
+ pandas/tests/scalar/test_nat.py:557: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_pytimedelta" [union-attr]
+ pandas/tests/scalar/test_nat.py:558: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_timedelta64" [union-attr]
+ pandas/tests/scalar/timedelta/test_timedelta.py:266: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "max" [union-attr]
+ pandas/tests/scalar/interval/test_arithmetic.py:116: error: Value of type variable "_OrderableT" of "Interval" cannot be "Timestamp | NaTType" [type-var]
+ pandas/tests/scalar/interval/test_arithmetic.py:119: error: Value of type variable "_OrderableT" of "Interval" cannot be "Timedelta | NaTType" [type-var]
+ pandas/tests/indexes/test_engines.py:62: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_pytimedelta" [union-attr]
+ pandas/tests/indexes/test_engines.py:63: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_timedelta64" [union-attr]
+ pandas/tests/groupby/methods/test_rank.py:72: error: List item 0 has incompatible type "list[Timestamp | NaTType]"; expected "ndarray[tuple[Any, ...], dtype[Any]]" [list-item]
+ pandas/tests/groupby/methods/test_rank.py:79: error: List item 1 has incompatible type "list[Timestamp | NaTType]"; expected "ndarray[tuple[Any, ...], dtype[Any]]" [list-item]
+ pandas/tests/groupby/methods/test_rank.py:86: error: List item 2 has incompatible type "list[Timedelta | NaTType]"; expected "ndarray[tuple[Any, ...], dtype[Any]]" [list-item]
+ pandas/tests/groupby/methods/test_rank.py:93: error: List item 3 has incompatible type "list[Period | Any]"; expected "ndarray[tuple[Any, ...], dtype[Any]]" [list-item]
+ pandas/tests/groupby/methods/test_rank.py:94: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/groupby/methods/test_rank.py:95: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/groupby/methods/test_rank.py:96: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/groupby/methods/test_rank.py:97: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/groupby/methods/test_rank.py:98: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/groupby/methods/test_rank.py:202: error: List item 0 has incompatible type "list[float | Timestamp | NaTType]"; expected "ndarray[tuple[Any, ...], dtype[Any]]" [list-item]
+ pandas/tests/groupby/methods/test_rank.py:212: error: List item 1 has incompatible type "list[float | Timestamp | NaTType]"; expected "ndarray[tuple[Any, ...], dtype[Any]]" [list-item]
+ pandas/tests/groupby/methods/test_rank.py:222: error: List item 2 has incompatible type "list[float | Timedelta | NaTType]"; expected "ndarray[tuple[Any, ...], dtype[Any]]" [list-item]
+ pandas/tests/groupby/methods/test_rank.py:232: error: List item 3 has incompatible type "list[float | Period | Any]"; expected "ndarray[tuple[Any, ...], dtype[Any]]" [list-item]
+ pandas/tests/groupby/methods/test_rank.py:233: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/groupby/methods/test_rank.py:234: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/groupby/methods/test_rank.py:236: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/groupby/methods/test_rank.py:237: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/groupby/methods/test_rank.py:238: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/arrays/test_timedeltas.py:215: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_timedelta64" [union-attr]
+ pandas/tests/arrays/test_timedeltas.py:216: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_pytimedelta" [union-attr]
+ pandas/tests/arrays/test_timedeltas.py:238: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/arrays/test_datetimes.py:669: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "to_period" [union-attr]
+ pandas/tests/arrays/test_datetimelike.py:187: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "time" [union-attr]
+ pandas/tests/arithmetic/conftest.py:70: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_pytimedelta" [union-attr]
+ pandas/tests/arithmetic/conftest.py:72: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_timedelta64" [union-attr]
+ pandas/tests/arithmetic/conftest.py:87: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_pytimedelta" [union-attr]
+ pandas/tests/arithmetic/conftest.py:106: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_pytimedelta" [union-attr]
+ pandas/tests/arithmetic/conftest.py:131: error: Item "NaTType" of "Timedelta | NaTType" has no attribute "to_pytimedelta" [union-attr]
+ pandas/plotting/_matplotlib/converter.py:153: error: Item "NaTType" of "Timestamp | NaTType" has no attribute "time" [union-attr]
... (truncated 15 lines) ...
starlette (https://github.com/encode/starlette)
+ starlette/testclient.py:129: error: Incompatible types in assignment (expression has type "tuple[MemoryObjectSendStream[MutableMapping[str, Any]], MemoryObjectReceiveStream[MutableMapping[str, Any]]]", variable has type "create_memory_object_stream[MutableMapping[str, Any]]") [assignment]
+ starlette/testclient.py:131: error: Incompatible types in assignment (expression has type "tuple[MemoryObjectSendStream[MutableMapping[str, Any]], MemoryObjectReceiveStream[MutableMapping[str, Any]]]", variable has type "create_memory_object_stream[MutableMapping[str, Any]]") [assignment]
+ starlette/testclient.py:678: error: Incompatible types in assignment (expression has type "tuple[MemoryObjectSendStream[MutableMapping[str, Any] | None], MemoryObjectReceiveStream[MutableMapping[str, Any] | None]]", variable has type "create_memory_object_stream[MutableMapping[str, Any] | None]") [assignment]
+ starlette/testclient.py:680: error: Incompatible types in assignment (expression has type "tuple[MemoryObjectSendStream[MutableMapping[str, Any]], MemoryObjectReceiveStream[MutableMapping[str, Any]]]", variable has type "create_memory_object_stream[MutableMapping[str, Any]]") [assignment]
+ starlette/middleware/base.py:189: error: Incompatible types in assignment (expression has type "tuple[MemoryObjectSendStream[MutableMapping[str, Any]], MemoryObjectReceiveStream[MutableMapping[str, Any]]]", variable has type "create_memory_object_stream[MutableMapping[str, Any]]") [assignment]
|
|
cc @Dr-Irv for all the new errors in class Timestamp(datetime):
...
def __new__( # type: ignore[misc]
cls: type[Self],
# ...
) -> Self | NaTType: ... |
Yes, I agree that is suspicious.
We should probably copy the PYI for I have on my TODO list to first make the pandas source compatible with the latest release of |
Would the following alternatives also preserve backwards compatibility just as well, but reflect explicit intention better?
|
With this PR will still give an error if the explicit return
__new__()is not a subtype of current class, but now we will actually use it. There are two exceptions (to preserve backwards compatibility):Anywith still use current class as the return type.This uses a more principled implementation than some earlier attempts: adding a new dedicated attribute to
CallableTypefor this purpose. Some comments:CallableType.type_guardandCallableType.type_iswere not handled in dependency visitors (neither coarse-grained nor fine-grained). IMO they definitely should be handled there, so I now handle them.CallableTypea bit to compensate for new attribute by removing (rarely used)min_argsattribute. I also use compact flags serialization.CallableType.ret_typefor various type object edge cases.instance_typeis set whenis_type_obj()returnsTrue. This is mostly to avoid breaking 3rd party plugins.