UPDATE: das kann „unmöglich“ sein sauber zu tun, weil Sphinx der Code des Objekts Funktion verwendet die Funktion Signatur zu erzeugen. Aber da Sie Sphinx verwenden, gibt es einen hacky Workaround, der funktioniert.
Es ist hacky, weil es den Dekorateur effektiv deaktiviert, während sphinx läuft, aber es funktioniert, also ist es eine praktische Lösung.
Zuerst ging ich den Weg der Konstruktion eines neuen types.CodeType
Objekts, um das func_code
Code-Objekt-Mitglied des Wrappers zu ersetzen, was Sphinx verwendet, wenn die Signaturen erzeugt werden.
konnte ich Python segfault durch die Strecke gehen oder versuchen, in den co_varnames
, co_nlocals
usw. Mitglieder des Codeobjekts aus der ursprünglichen Funktion zu tauschen, und während ansprechend, es war zu kompliziert.
Die folgende Lösung, während es ein Hacky schwerer Hammer ist, ist auch sehr einfach =)
Der Ansatz ist wie folgt: Wenn innerhalb Sphinx ausgeführt wird, eine Umgebungsvariable festgelegt, dass der Dekorateur überprüfen. Im Inneren des Dekorators, wenn Sphinx erkannt wird, verziere keine Dekoration und gebe stattdessen die ursprüngliche Funktion zurück.
In Ihrem Sphinx conf.py:
import os
os.environ['SPHINX_BUILD'] = '1'
Und dann ist hier ein Beispiel-Modul mit einem Testfall, der zeigt, wie es aussehen könnte:
import functools
import os
import types
import unittest
SPHINX_BUILD = bool(os.environ.get('SPHINX_BUILD', ''))
class StaleError(StandardError):
"""Custom exception for staleness"""
pass
def check_stale(f):
"""Raise StaleError when the object has gone stale"""
if SPHINX_BUILD:
# sphinx hack: use the original function when sphinx is running so that the
# documentation ends up with the correct function signatures.
# See 'SPHINX_BUILD' in conf.py.
return f
@functools.wraps(f)
def wrapper(self, *args, **kwargs):
if self.stale:
raise StaleError('stale')
return f(self, *args, **kwargs)
return wrapper
class Example(object):
def __init__(self):
self.stale = False
self.value = 0
@check_stale
def get(self):
"""docstring"""
return self.value
@check_stale
def calculate(self, a, b, c):
"""docstring"""
return self.value + a + b + c
class TestCase(unittest.TestCase):
def test_example(self):
example = Example()
self.assertEqual(example.get(), 0)
example.value = 1
example.stale = True
self.assertRaises(StaleError, example.get)
example.stale = False
self.assertEqual(example.calculate(1, 1, 1), 4)
if __name__ == '__main__':
unittest.main()
Die Dokumentation in der stdlib und in Sphinx beide scheinen zu implizieren dass du alles richtig machst. :( –
Haben Sie versucht, mit dem [Decorator-Paket] (http://pypi.python.org/pypi/decorator) und '@ Decorator' auf' checkStale' zu setzen? Ich hatte ein ähnliches Problem mit 'epydoc' mit einem dekoriert Funktion – bstpierre
@bstpierre Ich nehme an, dass das Dekorator-Paket nicht Teil einer normalen Python-Distribution ist? Ich frage mich, ob es möglich ist, es wo verfügbar zu verwenden, und sonst Fallback zu dem, was ich habe? –