Title: API for excluding methods from unittest stack traces
Type: enhancement Stage: needs patch
Components: Library (Lib) Versions: Python 3.11
Status: open Resolution:
Dependencies: Superseder:
Assigned To: michael.foord Nosy List: Julian, amaury.forgeotdarc, dmalcolm, michael.foord, purcell, rbcollins, rhettinger, serhiy.storchaka
Priority: normal Keywords:

Created on 2007-04-23 03:56 by rbcollins, last changed 2021-09-05 17:45 by serhiy.storchaka.

Messages (9)
msg55078 - (view) Author: Robert Collins (rbcollins) * (Python committer) Date: 2007-04-23 03:56
pyunit looks for __unittest = 1 in the globals of functions in an assertion stacktrace. This is used to trim the trace so that unittest implementation methods do  not show up.

It would be great if it looked in the locals of the frame as well, as this would allow subclasses of TestCase that add new assertFOO methods to have them filtered in the same manner.

e.g. (bad example :))
def assertComplexState(self, inputs):
    __unittest = 1
    self.assertEqual('42', inputs[0], 'the input %s is not the right answer' % inputs)

msg61493 - (view) Author: Steve Purcell (purcell) (Python triager) Date: 2008-01-22 10:16
This is a good idea, but slightly messy.

A better solution would be for unittest to provide a decorator that 
could be used to mark assertion functions.  Internally, that decorator 
may well work the way you describe.

Given a corresponding patch, someone with more time than myself may well 
be willing to commit it.
msg116666 - (view) Author: Mark Lawrence (BreamoreBoy) * Date: 2010-09-17 14:11
is this still relevant?
msg116667 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-09-17 14:14
It is relevant and would be *possible* to implement. I'm not 100% convinced it is a good *enough* idea to make it worth adding though. I'd like to leave the issue open for the moment in case other people want to comment.
msg122753 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-11-29 01:02
__unittest needs to die (with appropriate deprecation).

I agree that a nicer API for marking functions and methods as needing to be excluded from unittest stacktraces would be useful. A decorator is a good way to expose that API to developers. Internally unittest could use the new API and __unittest can go away.

Introspecting stack frames is a bad way to implement this, as it doesn't play well with other implementations (like IronPython which doesn't have introspectable Python stack frames by default).
msg123620 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-12-08 16:21
So from the stackframe you can only get to the code object not to the function object and although the code object is also reachable from a decorator it isn't mutable so we can't "mark it" in any way. We could in theory 're-build' the function and create a new code object (__code__ is assignable) by copying the original but adding a non-existent name to one of the code attributes. This is pretty horrible though.

So a *real* local variable (as suggested by Robert) would work, but the functionality wouldn't work on IronPython and would cause tools like pyflakes to complain about an unused name.

Another alternative is to use the docstring. This is available via code_object.co_consts[0], so we could use a marker in the docstring to indicate that this frame should be omitted from tracebacks. Unless we can make the marker either invisible (magic whitespace anyone?) or non-invasive this is also a not so pleasant idea. (And wouldn't work with -OO.)

Alternative suggestions welcomed.
msg123634 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2010-12-08 19:14
Maybe a global registry... implemented with a WeakKeyDictionary?
msg123635 - (view) Author: Michael Foord (michael.foord) * (Python committer) Date: 2010-12-08 19:18
Global registry of code objects, hmmm... Could work. I'll prototype it and test it with IronPython / Jython / pypy.
msg401099 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-09-05 17:45
What to do with comprehensions and classes? Corresponding code objects are not easily accessible and they do not have corresponding function. It would be difficult to use the locals of the frame with comprehensions.

Maybe use per-module registries of qualnames?

class MyAssertions:
    def assertComplexState(self, inputs):
        self.assertEqual('42', inputs[0], 'the input %s is not the right answer' % inputs)

__unittests = {'MyAssertions.assertComplexState'}

The frame is skipped if f_globals['__unittests'] contains co_qualname or any parents of co_qualname.

We can even add a decorator:

def assertion(func):
    mod = sys.modules[func.__module__]
    mod.__dict__.setdefault('__unittests', set())
    return func
Date User Action Args
2021-09-05 17:45:39serhiy.storchakasetnosy: + serhiy.storchaka

messages: + msg401099
versions: + Python 3.11, - Python 3.4
2014-02-03 19:08:59BreamoreBoysetnosy: - BreamoreBoy
2012-09-09 19:36:44r.david.murraysetnosy: + Julian
stage: test needed -> needs patch

versions: + Python 3.4, - Python 3.2
2012-09-09 19:36:08r.david.murraylinkissue15891 superseder
2010-12-08 19:18:02michael.foordsetmessages: + msg123635
2010-12-08 19:14:31amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg123634
2010-12-08 16:21:47michael.foordsetnosy: + rhettinger
messages: + msg123620
2010-12-08 14:56:40dmalcolmsetnosy: + dmalcolm
2010-11-29 01:02:08michael.foordsetassignee: purcell -> michael.foord
messages: + msg122753
title: pyunit should allow __unittest in locals to trim stackframes -> API for excluding methods from unittest stack traces
2010-09-17 14:14:06michael.foordsetmessages: + msg116667
2010-09-17 14:11:26BreamoreBoysetnosy: + BreamoreBoy

messages: + msg116666
versions: - Python 2.7
2009-05-12 14:32:41ajaksu2setnosy: + michael.foord
versions: + Python 2.7, Python 3.2, - Python 2.6

stage: test needed
2008-01-22 10:16:14purcellsetmessages: + msg61493
2007-04-23 03:56:38rbcollinscreate