diff options
-rw-r--r-- | Doc/library/sys.rst | 29 | ||||
-rw-r--r-- | Lib/test/test_profilehooks.py | 17 | ||||
-rw-r--r-- | Lib/test/test_trace.py | 14 | ||||
-rw-r--r-- | Misc/NEWS | 2 | ||||
-rw-r--r-- | Python/sysmodule.c | 42 |
5 files changed, 104 insertions, 0 deletions
diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index c6fe2fa..4b2ff4a 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -392,6 +392,35 @@ always available. This function should be used for internal and specialized purposes only. +.. function:: getprofile() + + .. index:: + single: profile function + single: profiler + + Get the profiler function as set by :func:`setprofile`. + + .. versionadded:: 2.6 + + +.. function:: gettrace() + + .. index:: + single: trace function + single: debugger + + Get the trace function as set by :func:`settrace`. + + .. note:: + + The :func:`gettrace` function is intended only for implementing debuggers, + profilers, coverage tools and the like. Its behavior is part of the + implementation platform, rather than part of the language definition, + and thus may not be available in all Python implementations. + + .. versionadded:: 2.6 + + .. function:: getwindowsversion() Return a tuple containing five components, describing the Windows version diff --git a/Lib/test/test_profilehooks.py b/Lib/test/test_profilehooks.py index 53f882a..2eedfd9 100644 --- a/Lib/test/test_profilehooks.py +++ b/Lib/test/test_profilehooks.py @@ -4,6 +4,22 @@ import unittest from test import test_support +class TestGetProfile(unittest.TestCase): + def setUp(self): + sys.setprofile(None) + + def tearDown(self): + sys.setprofile(None) + + def test_empty(self): + assert sys.getprofile() == None + + def test_setget(self): + def fn(*args): + pass + + sys.setprofile(fn) + assert sys.getprofile() == fn class HookWatcher: def __init__(self): @@ -359,6 +375,7 @@ def show_events(callable): def test_main(): test_support.run_unittest( + TestGetProfile, ProfileHookTestCase, ProfileSimulatorTestCase ) diff --git a/Lib/test/test_trace.py b/Lib/test/test_trace.py index 230f7bb..144fc66 100644 --- a/Lib/test/test_trace.py +++ b/Lib/test/test_trace.py @@ -268,6 +268,20 @@ class TraceTestCase(unittest.TestCase): self.compare_events(func.func_code.co_firstlineno, tracer.events, func.events) + def set_and_retrieve_none(self): + sys.settrace(None) + assert sys.gettrace() is None + + def set_and_retrieve_func(self): + def fn(*args): + pass + + sys.settrace(fn) + try: + assert sys.gettrace() is fn + finally: + sys.settrace(None) + def test_01_basic(self): self.run_test(basic) def test_02_arigo(self): @@ -1042,6 +1042,8 @@ Library Extension Modules ----------------- +- Patch #1648: added ``sys.getprofile()`` and ``sys.gettrace()``. + - Patch #1663329: added ``os.closerange()`` function to quickly close a range of file descriptors without considering errors. diff --git a/Python/sysmodule.c b/Python/sysmodule.c index bbcd957..12ad828 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -398,6 +398,25 @@ function call. See the debugger chapter in the library manual." ); static PyObject * +sys_gettrace(PyObject *self, PyObject *args) +{ + PyThreadState *tstate = PyThreadState_GET(); + PyObject *temp = tstate->c_traceobj; + + if (temp == NULL) + temp = Py_None; + Py_INCREF(temp); + return temp; +} + +PyDoc_STRVAR(gettrace_doc, +"gettrace()\n\ +\n\ +Return the global debug tracing function set with sys.settrace.\n\ +See the debugger chapter in the library manual." +); + +static PyObject * sys_setprofile(PyObject *self, PyObject *args) { if (trace_init() == -1) @@ -418,6 +437,25 @@ and return. See the profiler chapter in the library manual." ); static PyObject * +sys_getprofile(PyObject *self, PyObject *args) +{ + PyThreadState *tstate = PyThreadState_GET(); + PyObject *temp = tstate->c_profileobj; + + if (temp == NULL) + temp = Py_None; + Py_INCREF(temp); + return temp; +} + +PyDoc_STRVAR(getprofile_doc, +"getprofile()\n\ +\n\ +Return the profiling function set with sys.setprofile.\n\ +See the profiler chapter in the library manual." +); + +static PyObject * sys_setcheckinterval(PyObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, "i:setcheckinterval", &_Py_CheckInterval)) @@ -793,12 +831,14 @@ static PyMethodDef sys_methods[] = { setdlopenflags_doc}, #endif {"setprofile", sys_setprofile, METH_O, setprofile_doc}, + {"getprofile", sys_getprofile, METH_NOARGS, getprofile_doc}, {"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS, setrecursionlimit_doc}, #ifdef WITH_TSC {"settscdump", sys_settscdump, METH_VARARGS, settscdump_doc}, #endif {"settrace", sys_settrace, METH_O, settrace_doc}, + {"gettrace", sys_gettrace, METH_NOARGS, gettrace_doc}, {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc}, {NULL, NULL} /* sentinel */ }; @@ -941,8 +981,10 @@ exc_info() -- return thread-safe information about the current exception\n\ exc_clear() -- clear the exception state for the current thread\n\ exit() -- exit the interpreter by raising SystemExit\n\ getdlopenflags() -- returns flags to be used for dlopen() calls\n\ +getprofile() -- get the global profiling function\n\ getrefcount() -- return the reference count for an object (plus one :-)\n\ getrecursionlimit() -- return the max recursion depth for the interpreter\n\ +gettrace() -- get the global debug tracing function\n\ setcheckinterval() -- control how often the interpreter checks for events\n\ setdlopenflags() -- set the flags to be used for dlopen() calls\n\ setprofile() -- set the global profiling function\n\ |