diff --git a/.travis.yml b/.travis.yml index 47510df..892fbeb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,9 +11,21 @@ matrix: - ALLOW_DEPLOY=false - AIO_AVAILABLE=false - COVERAGERC=".coveragerc-py34" - - python: "3.5.2" + - python: "3.5" env: - - ALLOW_DEPLOY=true + - ALLOW_DEPLOY=false + - AIO_AVAILABLE=false + - COVERAGERC=".coveragerc" + - python: "3.6" + env: + - ALLOW_DEPLOY=false + - AIO_AVAILABLE=true + - COVERAGERC=".coveragerc" + - python: "3.7" + dist: xenial + sudo: required + env: + - ALLOW_DEPLOY=false - AIO_AVAILABLE=true - COVERAGERC=".coveragerc" install: @@ -32,7 +44,7 @@ deploy: provider: pypi distributions: sdist bdist_wheel on: - python: "3.5.2" + python: "3.6" tags: true user: nocarryr password: diff --git a/pydispatch/dispatch.py b/pydispatch/dispatch.py index bb8e141..84174e1 100644 --- a/pydispatch/dispatch.py +++ b/pydispatch/dispatch.py @@ -84,12 +84,11 @@ class Foo(Dispatcher): __skip_initialized = True def __new__(cls, *args, **kwargs): def iter_bases(_cls): - if _cls is object: - raise StopIteration - yield _cls - for b in _cls.__bases__: - for _cls_ in iter_bases(b): - yield _cls_ + if _cls is not object: + yield _cls + for b in _cls.__bases__: + for _cls_ in iter_bases(b): + yield _cls_ skip_initialized = Dispatcher._Dispatcher__skip_initialized if not skip_initialized or cls not in Dispatcher._Dispatcher__initialized_subclasses: props = {} diff --git a/tests/test_subclass_init.py b/tests/test_subclass_init.py index d791bdf..3604713 100644 --- a/tests/test_subclass_init.py +++ b/tests/test_subclass_init.py @@ -1,5 +1,47 @@ import math import time +import warnings + +def test_dispatcher_construction(): + from pydispatch import Dispatcher, Property + + class A(Dispatcher): + foo = Property() + bar = Property() + baz = Property() + _events_ = [ + 'on_stuff', 'on_more_stuff', + ] + class B(A): + a = Property() + b = Property() + c = Property() + _events_ = [ + 'on_even_more_stuff', 'on_one_more_thing' + ] + + with warnings.catch_warnings(record=True) as w_list: + warnings.simplefilter("always") + a = A() + b = B() + for w in w_list: + # Check for PEP-0479 (StopIteration) issues + assert not issubclass(w.category, DeprecationWarning) + assert not issubclass(w.category, PendingDeprecationWarning) + assert len(w_list) == 0 + + a_prop_names = {'foo', 'bar', 'baz'} + a_event_names = {'on_stuff', 'on_more_stuff'} + assert a_prop_names == set(a._Dispatcher__property_events.keys()) + assert a_event_names == set(a._Dispatcher__events.keys()) + + b_prop_names = {'a', 'b', 'c'} + b_prop_names |= a_prop_names + b_event_names = {'on_even_more_stuff', 'on_one_more_thing'} + b_event_names |= a_event_names + + assert b_prop_names == set(b._Dispatcher__property_events.keys()) + assert b_event_names == set(b._Dispatcher__events.keys()) def test_subclass_new_timing(): from pydispatch import Dispatcher, Property