diff options
| author | Michele Simionato <michele.simionato@gmail.com> | 2015-07-23 14:40:09 +0200 |
|---|---|---|
| committer | Michele Simionato <michele.simionato@gmail.com> | 2015-07-23 14:40:09 +0200 |
| commit | bf1748df8d229bbfe40de6944c48349228e5b5bc (patch) | |
| tree | faf5fb5db86e2bed6a7de4ca528b479979bffea5 /src | |
| parent | 6d099d1b69144e5bd491e457ec493b8f100480a1 (diff) | |
| download | python-decorator-git-bf1748df8d229bbfe40de6944c48349228e5b5bc.tar.gz | |
More algorithmic fixes
Diffstat (limited to 'src')
| -rw-r--r-- | src/decorator.py | 8 | ||||
| -rw-r--r-- | src/tests/documentation.py | 24 | ||||
| -rw-r--r-- | src/tests/test.py | 3 |
3 files changed, 19 insertions, 16 deletions
diff --git a/src/decorator.py b/src/decorator.py index 2a96b4a..bab05b4 100644 --- a/src/decorator.py +++ b/src/decorator.py @@ -285,13 +285,15 @@ def append(a, vancestors): Append ``a`` to the list of the virtual ancestors, unless it is already included. """ + add = True for j, va in enumerate(vancestors): if issubclass(va, a): + add = False break if issubclass(a, va): vancestors[j] = a - break - else: + add = False + if add: vancestors.append(a) @@ -330,7 +332,7 @@ def dispatch_on(*dispatch_args): for t, type_, ra in zip(types, types_, ras): if issubclass(t, type_) and type_ not in t.__mro__: append(type_, ra) - return map(set, ras) + return [set(ra) for ra in ras] def mros(*types): """ diff --git a/src/tests/documentation.py b/src/tests/documentation.py index 4591611..c5f8c7d 100644 --- a/src/tests/documentation.py +++ b/src/tests/documentation.py @@ -821,30 +821,30 @@ implementation for ``Set`` is taken: >>> get_length(SomeSet()) 1 - -The implementation of generic functions in the decorator module is -still experimental. In this initial phase implicity was preferred -over perfect consistency with the way ``functools.singledispatch`` works in -the standard library. So there are some subtle differences in special -cases. - -Considered a class ``C`` registered both as ``collections.Iterable`` -and ``collections.Sized`` and define a generic function ``g`` with +Some times it is not clear how to dispatch. For instance, consider a +class ``C`` registered both as ``collections.Iterable`` and +``collections.Sized`` and define a generic function ``g`` with implementations both for ``collections.Iterable`` and ``collections.Sized``. It is impossible to decide which implementation -to use, and the following code will fail with a RuntimeError: +to use, since the ancestors are independent, and the following code +will fail with a RuntimeError: $$singledispatch_example This is consistent with the "refuse the temptation to guess" -philosophy. ``functools.singledispatch`` will raise a similar error. +philosophy. ``functools.singledispatch`` would raise a similar error. + It would be easy to rely on the order of registration to decide the precedence order. This is reasonable, but also fragile: if during some refactoring you change the registration order by mistake, a different implementation could be taken. If implementations of the generic functions are distributed across modules, and you change the import order, a different implementation could be taken. So the decorator -module is using the same approach of the standard library. +module prefers to raise an error in the face of ambiguity. This is the +same approach taken by the standard library. Notice that the dispatch +algorithm used by the decorator module is different from the one used +by ``functools.singledispatch``, so there are cases where you will get +different answers. Finally let me notice that the decorator module implementation does not use any cache, whereas the one in ``singledispatch`` has a cache. diff --git a/src/tests/test.py b/src/tests/test.py index 8413a58..2de144e 100644 --- a/src/tests/test.py +++ b/src/tests/test.py @@ -320,7 +320,8 @@ class TestSingleDispatch(unittest.TestCase): def i_sequence(arg): return "sequence" r = R() - #self.assertEqual(i(r), "mapping") # was sequence + with doc.assertRaises(RuntimeError): + self.assertEqual(i(r), "mapping") class S(object): pass |
