diff mbox series

[1/9] python3-yappi: update 1.4.0 -> 1.6.0

Message ID 20231222151108.645675-1-alex@linutronix.de
State Superseded
Headers show
Series [1/9] python3-yappi: update 1.4.0 -> 1.6.0 | expand

Commit Message

Alexander Kanavin Dec. 22, 2023, 3:11 p.m. UTC
Drop patches:
0002-add-3.11-to-the-setup.patch - issue resolved upstream
0001-Fix-imports-for-ptests.patch - unclear what the problem is, too difficult to rebase.

Signed-off-by: Alexander Kanavin <alex@linutronix.de>
---
 .../0001-Fix-imports-for-ptests.patch         | 3895 -----------------
 .../0002-add-3.11-to-the-setup.patch          |   26 -
 ...-yappi_1.4.0.bb => python3-yappi_1.6.0.bb} |    8 +-
 3 files changed, 2 insertions(+), 3927 deletions(-)
 delete mode 100644 meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
 delete mode 100644 meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch
 rename meta-python/recipes-devtools/python/{python3-yappi_1.4.0.bb => python3-yappi_1.6.0.bb} (74%)

Comments

Khem Raj Dec. 22, 2023, 3:54 p.m. UTC | #1
On Fri, Dec 22, 2023 at 7:11 AM Alexander Kanavin
<alex.kanavin@gmail.com> wrote:
>
> Drop patches:
> 0002-add-3.11-to-the-setup.patch - issue resolved upstream
> 0001-Fix-imports-for-ptests.patch - unclear what the problem is, too difficult to rebase.

Does
bitbake meta-python-image-ptest-python3-yappi

show regression ?

>
> Signed-off-by: Alexander Kanavin <alex@linutronix.de>
> ---
>  .../0001-Fix-imports-for-ptests.patch         | 3895 -----------------
>  .../0002-add-3.11-to-the-setup.patch          |   26 -
>  ...-yappi_1.4.0.bb => python3-yappi_1.6.0.bb} |    8 +-
>  3 files changed, 2 insertions(+), 3927 deletions(-)
>  delete mode 100644 meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
>  delete mode 100644 meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch
>  rename meta-python/recipes-devtools/python/{python3-yappi_1.4.0.bb => python3-yappi_1.6.0.bb} (74%)
>
> diff --git a/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch b/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
> deleted file mode 100644
> index 476db4b7d..000000000
> --- a/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
> +++ /dev/null
> @@ -1,3895 +0,0 @@
> -From 0dedc1c573ddc4e87475eb03c64555cd54a72e92 Mon Sep 17 00:00:00 2001
> -From: Trevor Gamblin <trevor.gamblin@windriver.com>
> -Date: Mon, 7 Jun 2021 09:40:20 -0400
> -Subject: [PATCH] Fix imports for tests
> -
> -Signed-off-by: Trevor Gamblin <trevor.gamblin@windriver.com>
> ----
> -Upstream-Status: Pending
> -
> - tests/test_asyncio.py              | 2 +-
> - tests/test_asyncio_context_vars.py | 2 +-
> - tests/test_functionality.py        | 2 +-
> - tests/test_hooks.py                | 2 +-
> - tests/test_tags.py                 | 2 +-
> - 5 files changed, 6 insertions(+), 6 deletions(-)
> -
> ---- a/tests/test_asyncio.py
> -+++ b/tests/test_asyncio.py
> -@@ -2,7 +2,7 @@ import unittest
> - import yappi
> - import asyncio
> - import threading
> --from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
> -+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
> -
> -
> - async def async_sleep(sec):
> ---- a/tests/test_asyncio_context_vars.py
> -+++ b/tests/test_asyncio_context_vars.py
> -@@ -5,7 +5,7 @@ import contextvars
> - import functools
> - import time
> - import os
> --import utils
> -+import tests.utils as utils
> - import yappi
> -
> - async_context_id = contextvars.ContextVar('async_context_id')
> ---- a/tests/test_functionality.py
> -+++ b/tests/test_functionality.py
> -@@ -1,1916 +1,1916 @@
> --import os
> --import sys
> --import time
> --import threading
> --import unittest
> --import yappi
> --import _yappi
> --import utils
> --import multiprocessing  # added to fix http://bugs.python.org/issue15881 for > Py2.6
> --import subprocess
> --
> --_counter = 0
> --
> --
> --class BasicUsage(utils.YappiUnitTestCase):
> --
> --    def test_callback_function_int_return_overflow(self):
> --        # this test is just here to check if any errors are generated, as the err
> --        # is printed in C side, I did not include it here. THere are ways to test
> --        # this deterministically, I did not bother
> --        import ctypes
> --
> --        def _unsigned_overflow_margin():
> --            return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1
> --
> --        def foo():
> --            pass
> --
> --        #with utils.captured_output() as (out, err):
> --        yappi.set_context_id_callback(_unsigned_overflow_margin)
> --        yappi.set_tag_callback(_unsigned_overflow_margin)
> --        yappi.start()
> --        foo()
> --
> --    def test_issue60(self):
> --
> --        def foo():
> --            buf = bytearray()
> --            buf += b't' * 200
> --            view = memoryview(buf)[10:]
> --            view = view.tobytes()
> --            del buf[:10]  # this throws exception
> --            return view
> --
> --        yappi.start(builtins=True)
> --        foo()
> --        self.assertTrue(
> --            len(
> --                yappi.get_func_stats(
> --                    filter_callback=lambda x: yappi.
> --                    func_matches(x, [memoryview.tobytes])
> --                )
> --            ) > 0
> --        )
> --        yappi.stop()
> --
> --    def test_issue54(self):
> --
> --        def _tag_cbk():
> --            global _counter
> --            _counter += 1
> --            return _counter
> --
> --        def a():
> --            pass
> --
> --        def b():
> --            pass
> --
> --        yappi.set_tag_callback(_tag_cbk)
> --        yappi.start()
> --        a()
> --        a()
> --        a()
> --        yappi.stop()
> --        stats = yappi.get_func_stats()
> --        self.assertEqual(stats.pop().ncall, 3)  # aggregated if no tag is given
> --        stats = yappi.get_func_stats(tag=1)
> --
> --        for i in range(1, 3):
> --            stats = yappi.get_func_stats(tag=i)
> --            stats = yappi.get_func_stats(
> --                tag=i, filter_callback=lambda x: yappi.func_matches(x, [a])
> --            )
> --
> --            stat = stats.pop()
> --            self.assertEqual(stat.ncall, 1)
> --
> --        yappi.set_tag_callback(None)
> --        yappi.clear_stats()
> --        yappi.start()
> --        b()
> --        b()
> --        stats = yappi.get_func_stats()
> --        self.assertEqual(len(stats), 1)
> --        stat = stats.pop()
> --        self.assertEqual(stat.ncall, 2)
> --
> --    def test_filter(self):
> --
> --        def a():
> --            pass
> --
> --        def b():
> --            a()
> --
> --        def c():
> --            b()
> --
> --        _TCOUNT = 5
> --
> --        ts = []
> --        yappi.start()
> --        for i in range(_TCOUNT):
> --            t = threading.Thread(target=c)
> --            t.start()
> --            ts.append(t)
> --
> --        for t in ts:
> --            t.join()
> --
> --        yappi.stop()
> --
> --        ctx_ids = []
> --        for tstat in yappi.get_thread_stats():
> --            if tstat.name == '_MainThread':
> --                main_ctx_id = tstat.id
> --            else:
> --                ctx_ids.append(tstat.id)
> --
> --        fstats = yappi.get_func_stats(filter={"ctx_id": 9})
> --        self.assertTrue(fstats.empty())
> --        fstats = yappi.get_func_stats(
> --            filter={
> --                "ctx_id": main_ctx_id,
> --                "name": "c"
> --            }
> --        )  # main thread
> --        self.assertTrue(fstats.empty())
> --
> --        for i in ctx_ids:
> --            fstats = yappi.get_func_stats(
> --                filter={
> --                    "ctx_id": i,
> --                    "name": "a",
> --                    "ncall": 1
> --                }
> --            )
> --            self.assertEqual(fstats.pop().ncall, 1)
> --            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"})
> --            self.assertEqual(fstats.pop().ncall, 1)
> --            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"})
> --            self.assertEqual(fstats.pop().ncall, 1)
> --
> --        yappi.clear_stats()
> --        yappi.start(builtins=True)
> --        time.sleep(0.1)
> --        yappi.stop()
> --        fstats = yappi.get_func_stats(filter={"module": "time"})
> --        self.assertEqual(len(fstats), 1)
> --
> --        # invalid filters`
> --        self.assertRaises(
> --            Exception, yappi.get_func_stats, filter={'tag': "sss"}
> --        )
> --        self.assertRaises(
> --            Exception, yappi.get_func_stats, filter={'ctx_id': "None"}
> --        )
> --
> --    def test_filter_callback(self):
> --
> --        def a():
> --            time.sleep(0.1)
> --
> --        def b():
> --            a()
> --
> --        def c():
> --            pass
> --
> --        def d():
> --            pass
> --
> --        yappi.set_clock_type("wall")
> --        yappi.start(builtins=True)
> --        a()
> --        b()
> --        c()
> --        d()
> --        stats = yappi.get_func_stats(
> --            filter_callback=lambda x: yappi.func_matches(x, [a, b])
> --        )
> --        #stats.print_all()
> --        r1 = '''
> --        tests/test_functionality.py:98 a      2      0.000000  0.200350  0.100175
> --        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.100197
> --        '''
> --        self.assert_traces_almost_equal(r1, stats)
> --        self.assertEqual(len(stats), 2)
> --        stats = yappi.get_func_stats(
> --            filter_callback=lambda x: yappi.
> --            module_matches(x, [sys.modules[__name__]])
> --        )
> --        r1 = '''
> --        tests/test_functionality.py:98 a      2      0.000000  0.230130  0.115065
> --        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.109011
> --        tests/test_functionality.py:104 c     1      0.000000  0.000002  0.000002
> --        tests/test_functionality.py:107 d     1      0.000000  0.000001  0.000001
> --        '''
> --        self.assert_traces_almost_equal(r1, stats)
> --        self.assertEqual(len(stats), 4)
> --
> --        stats = yappi.get_func_stats(
> --            filter_callback=lambda x: yappi.func_matches(x, [time.sleep])
> --        )
> --        self.assertEqual(len(stats), 1)
> --        r1 = '''
> --        time.sleep                            2      0.206804  0.220000  0.103402
> --        '''
> --        self.assert_traces_almost_equal(r1, stats)
> --
> --    def test_print_formatting(self):
> --
> --        def a():
> --            pass
> --
> --        def b():
> --            a()
> --
> --        func_cols = {
> --            1: ("name", 48),
> --            0: ("ncall", 5),
> --            2: ("tsub", 8),
> --        }
> --        thread_cols = {
> --            1: ("name", 48),
> --            0: ("ttot", 8),
> --        }
> --
> --        yappi.start()
> --        a()
> --        b()
> --        yappi.stop()
> --        fs = yappi.get_func_stats()
> --        cs = fs[1].children
> --        ts = yappi.get_thread_stats()
> --        #fs.print_all(out=sys.stderr, columns={1:("name", 70), })
> --        #cs.print_all(out=sys.stderr, columns=func_cols)
> --        #ts.print_all(out=sys.stderr, columns=thread_cols)
> --        #cs.print_all(out=sys.stderr, columns={})
> --
> --        self.assertRaises(
> --            yappi.YappiError, fs.print_all, columns={1: ("namee", 9)}
> --        )
> --        self.assertRaises(
> --            yappi.YappiError, cs.print_all, columns={1: ("dd", 0)}
> --        )
> --        self.assertRaises(
> --            yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)}
> --        )
> --
> --    def test_get_clock(self):
> --        yappi.set_clock_type('cpu')
> --        self.assertEqual('cpu', yappi.get_clock_type())
> --        clock_info = yappi.get_clock_info()
> --        self.assertTrue('api' in clock_info)
> --        self.assertTrue('resolution' in clock_info)
> --
> --        yappi.set_clock_type('wall')
> --        self.assertEqual('wall', yappi.get_clock_type())
> --
> --        t0 = yappi.get_clock_time()
> --        time.sleep(0.1)
> --        duration = yappi.get_clock_time() - t0
> --        self.assertTrue(0.05 < duration < 0.3)
> --
> --    def test_profile_decorator(self):
> --
> --        def aggregate(func, stats):
> --            fname = "tests/%s.profile" % (func.__name__)
> --            try:
> --                stats.add(fname)
> --            except IOError:
> --                pass
> --            stats.save(fname)
> --            raise Exception("messing around")
> --
> --        @yappi.profile(return_callback=aggregate)
> --        def a(x, y):
> --            if x + y == 25:
> --                raise Exception("")
> --            return x + y
> --
> --        def b():
> --            pass
> --
> --        try:
> --            os.remove(
> --                "tests/a.profile"
> --            )  # remove the one from prev test, if available
> --        except:
> --            pass
> --
> --        # global profile is on to mess things up
> --        yappi.start()
> --        b()
> --
> --        # assert functionality and call function at same time
> --        try:
> --            self.assertEqual(a(1, 2), 3)
> --        except:
> --            pass
> --        try:
> --            self.assertEqual(a(2, 5), 7)
> --        except:
> --            pass
> --        try:
> --            a(4, 21)
> --        except:
> --            pass
> --        stats = yappi.get_func_stats().add("tests/a.profile")
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        self.assertEqual(fsa.ncall, 3)
> --        self.assertEqual(len(stats), 1)  # b() should be cleared out.
> --
> --        @yappi.profile(return_callback=aggregate)
> --        def count_down_rec(n):
> --            if n == 0:
> --                return
> --            count_down_rec(n - 1)
> --
> --        try:
> --            os.remove(
> --                "tests/count_down_rec.profile"
> --            )  # remove the one from prev test, if available
> --        except:
> --            pass
> --
> --        try:
> --            count_down_rec(4)
> --        except:
> --            pass
> --        try:
> --            count_down_rec(3)
> --        except:
> --            pass
> --
> --        stats = yappi.YFuncStats("tests/count_down_rec.profile")
> --        fsrec = utils.find_stat_by_name(stats, 'count_down_rec')
> --        self.assertEqual(fsrec.ncall, 9)
> --        self.assertEqual(fsrec.nactualcall, 2)
> --
> --    def test_strip_dirs(self):
> --
> --        def a():
> --            pass
> --
> --        stats = utils.run_and_get_func_stats(a, )
> --        stats.strip_dirs()
> --        fsa = utils.find_stat_by_name(stats, "a")
> --        self.assertEqual(fsa.module, os.path.basename(fsa.module))
> --
> --    @unittest.skipIf(os.name == "nt", "do not run on Windows")
> --    def test_run_as_script(self):
> --        import re
> --        p = subprocess.Popen(
> --            ['yappi', os.path.join('./tests', 'run_as_script.py')],
> --            stdout=subprocess.PIPE
> --        )
> --        out, err = p.communicate()
> --        self.assertEqual(p.returncode, 0)
> --        func_stats, thread_stats = re.split(
> --            b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out
> --        )
> --        self.assertTrue(b'FancyThread' in thread_stats)
> --
> --    def test_yappi_overhead(self):
> --        LOOP_COUNT = 100000
> --
> --        def a():
> --            pass
> --
> --        def b():
> --            for i in range(LOOP_COUNT):
> --                a()
> --
> --        t0 = time.time()
> --        yappi.start()
> --        b()
> --        yappi.stop()
> --        time_with_yappi = time.time() - t0
> --        t0 = time.time()
> --        b()
> --        time_without_yappi = time.time() - t0
> --        if time_without_yappi == 0:
> --            time_without_yappi = 0.000001
> --
> --        # in latest v0.82, I calculated this as close to "7.0" in my machine.
> --        # however, %83 of this overhead is coming from tickcount(). The other %17
> --        # seems to have been evenly distributed to the internal bookkeeping
> --        # structures/algorithms which seems acceptable. Note that our test only
> --        # tests one function being profiled at-a-time in a short interval.
> --        # profiling high number of functions in a small time
> --        # is a different beast, (which is pretty unlikely in most applications)
> --        # So as a conclusion: I cannot see any optimization window for Yappi that
> --        # is worth implementing as we will only optimize %17 of the time.
> --        sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \
> --            (time_with_yappi / time_without_yappi))
> --
> --    def test_clear_stats_while_running(self):
> --
> --        def a():
> --            pass
> --
> --        yappi.start()
> --        a()
> --        yappi.clear_stats()
> --        a()
> --        stats = yappi.get_func_stats()
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        self.assertEqual(fsa.ncall, 1)
> --
> --    def test_generator(self):
> --
> --        def _gen(n):
> --            while (n > 0):
> --                yield n
> --                n -= 1
> --
> --        yappi.start()
> --        for x in _gen(5):
> --            pass
> --        self.assertTrue(
> --            yappi.convert2pstats(yappi.get_func_stats()) is not None
> --        )
> --
> --    def test_slice_child_stats_and_strip_dirs(self):
> --
> --        def b():
> --            for i in range(10000000):
> --                pass
> --
> --        def a():
> --            b()
> --
> --        yappi.start(builtins=True)
> --        a()
> --        stats = yappi.get_func_stats()
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        self.assertTrue(fsa.children[0:1] is not None)
> --        prev_afullname = fsa.full_name
> --        prev_bchildfullname = fsa.children[fsb].full_name
> --        stats.strip_dirs()
> --        self.assertTrue(len(prev_afullname) > len(fsa.full_name))
> --        self.assertTrue(
> --            len(prev_bchildfullname) > len(fsa.children[fsb].full_name)
> --        )
> --
> --    def test_children_stat_functions(self):
> --        _timings = {"a_1": 5, "b_1": 3, "c_1": 1}
> --        _yappi._set_test_timings(_timings)
> --
> --        def b():
> --            pass
> --
> --        def c():
> --            pass
> --
> --        def a():
> --            b()
> --            c()
> --
> --        yappi.start()
> --        a()
> --        b()  # non-child call
> --        c()  # non-child call
> --        stats = yappi.get_func_stats()
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        childs_of_a = fsa.children.get().sort("tavg", "desc")
> --        prev_item = None
> --        for item in childs_of_a:
> --            if prev_item:
> --                self.assertTrue(prev_item.tavg > item.tavg)
> --            prev_item = item
> --        childs_of_a.sort("name", "desc")
> --        prev_item = None
> --        for item in childs_of_a:
> --            if prev_item:
> --                self.assertTrue(prev_item.name > item.name)
> --            prev_item = item
> --        childs_of_a.clear()
> --        self.assertTrue(childs_of_a.empty())
> --
> --    def test_no_stats_different_clock_type_load(self):
> --
> --        def a():
> --            pass
> --
> --        yappi.start()
> --        a()
> --        yappi.stop()
> --        yappi.get_func_stats().save("tests/ystats1.ys")
> --        yappi.clear_stats()
> --        yappi.set_clock_type("WALL")
> --        yappi.start()
> --        yappi.stop()
> --        stats = yappi.get_func_stats().add("tests/ystats1.ys")
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        self.assertTrue(fsa is not None)
> --
> --    def test_subsequent_profile(self):
> --        _timings = {"a_1": 1, "b_1": 1}
> --        _yappi._set_test_timings(_timings)
> --
> --        def a():
> --            pass
> --
> --        def b():
> --            pass
> --
> --        yappi.start()
> --        a()
> --        yappi.stop()
> --        yappi.start()
> --        b()
> --        yappi.stop()
> --        stats = yappi.get_func_stats()
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        self.assertTrue(fsa is not None)
> --        self.assertTrue(fsb is not None)
> --        self.assertEqual(fsa.ttot, 1)
> --        self.assertEqual(fsb.ttot, 1)
> --
> --    def test_lambda(self):
> --        f = lambda: time.sleep(0.3)
> --        yappi.set_clock_type("wall")
> --        yappi.start()
> --        f()
> --        stats = yappi.get_func_stats()
> --        fsa = utils.find_stat_by_name(stats, '<lambda>')
> --        self.assertTrue(fsa.ttot > 0.1)
> --
> --    def test_module_stress(self):
> --        self.assertEqual(yappi.is_running(), False)
> --
> --        yappi.start()
> --        yappi.clear_stats()
> --        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
> --
> --        yappi.stop()
> --        yappi.clear_stats()
> --        yappi.set_clock_type("cpu")
> --        self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy")
> --        self.assertEqual(yappi.is_running(), False)
> --        yappi.clear_stats()
> --        yappi.clear_stats()
> --
> --    def test_stat_sorting(self):
> --        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
> --        _yappi._set_test_timings(_timings)
> --
> --        self._ncall = 1
> --
> --        def a():
> --            b()
> --
> --        def b():
> --            if self._ncall == 2:
> --                return
> --            self._ncall += 1
> --            a()
> --
> --        stats = utils.run_and_get_func_stats(a)
> --        stats = stats.sort("totaltime", "desc")
> --        prev_stat = None
> --        for stat in stats:
> --            if prev_stat:
> --                self.assertTrue(prev_stat.ttot >= stat.ttot)
> --            prev_stat = stat
> --        stats = stats.sort("totaltime", "asc")
> --        prev_stat = None
> --        for stat in stats:
> --            if prev_stat:
> --                self.assertTrue(prev_stat.ttot <= stat.ttot)
> --            prev_stat = stat
> --        stats = stats.sort("avgtime", "asc")
> --        prev_stat = None
> --        for stat in stats:
> --            if prev_stat:
> --                self.assertTrue(prev_stat.tavg <= stat.tavg)
> --            prev_stat = stat
> --        stats = stats.sort("name", "asc")
> --        prev_stat = None
> --        for stat in stats:
> --            if prev_stat:
> --                self.assertTrue(prev_stat.name <= stat.name)
> --            prev_stat = stat
> --        stats = stats.sort("subtime", "asc")
> --        prev_stat = None
> --        for stat in stats:
> --            if prev_stat:
> --                self.assertTrue(prev_stat.tsub <= stat.tsub)
> --            prev_stat = stat
> --
> --        self.assertRaises(
> --            yappi.YappiError, stats.sort, "invalid_func_sorttype_arg"
> --        )
> --        self.assertRaises(
> --            yappi.YappiError, stats.sort, "totaltime",
> --            "invalid_func_sortorder_arg"
> --        )
> --
> --    def test_start_flags(self):
> --        self.assertEqual(_yappi._get_start_flags(), None)
> --        yappi.start()
> --
> --        def a():
> --            pass
> --
> --        a()
> --        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
> --        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
> --        self.assertEqual(len(yappi.get_thread_stats()), 1)
> --
> --    def test_builtin_profiling(self):
> --
> --        def a():
> --            time.sleep(0.4)  # is a builtin function
> --
> --        yappi.set_clock_type('wall')
> --
> --        yappi.start(builtins=True)
> --        a()
> --        stats = yappi.get_func_stats()
> --        fsa = utils.find_stat_by_name(stats, 'sleep')
> --        self.assertTrue(fsa is not None)
> --        self.assertTrue(fsa.ttot > 0.3)
> --        yappi.stop()
> --        yappi.clear_stats()
> --
> --        def a():
> --            pass
> --
> --        yappi.start()
> --        t = threading.Thread(target=a)
> --        t.start()
> --        t.join()
> --        stats = yappi.get_func_stats()
> --
> --    def test_singlethread_profiling(self):
> --        yappi.set_clock_type('wall')
> --
> --        def a():
> --            time.sleep(0.2)
> --
> --        class Worker1(threading.Thread):
> --
> --            def a(self):
> --                time.sleep(0.3)
> --
> --            def run(self):
> --                self.a()
> --
> --        yappi.start(profile_threads=False)
> --
> --        c = Worker1()
> --        c.start()
> --        c.join()
> --        a()
> --        stats = yappi.get_func_stats()
> --        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
> --        fsa2 = utils.find_stat_by_name(stats, 'a')
> --        self.assertTrue(fsa1 is None)
> --        self.assertTrue(fsa2 is not None)
> --        self.assertTrue(fsa2.ttot > 0.1)
> --
> --    def test_run(self):
> --
> --        def profiled():
> --            pass
> --
> --        yappi.clear_stats()
> --        try:
> --            with yappi.run():
> --                profiled()
> --            stats = yappi.get_func_stats()
> --        finally:
> --            yappi.clear_stats()
> --
> --        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
> --
> --    def test_run_recursive(self):
> --
> --        def profiled():
> --            pass
> --
> --        def not_profiled():
> --            pass
> --
> --        yappi.clear_stats()
> --        try:
> --            with yappi.run():
> --                with yappi.run():
> --                    profiled()
> --                # Profiling stopped here
> --                not_profiled()
> --            stats = yappi.get_func_stats()
> --        finally:
> --            yappi.clear_stats()
> --
> --        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
> --        self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled'))
> --
> --
> --class StatSaveScenarios(utils.YappiUnitTestCase):
> --
> --    def test_pstats_conversion(self):
> --
> --        def pstat_id(fs):
> --            return (fs.module, fs.lineno, fs.name)
> --
> --        def a():
> --            d()
> --
> --        def b():
> --            d()
> --
> --        def c():
> --            pass
> --
> --        def d():
> --            pass
> --
> --        _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2}
> --        _yappi._set_test_timings(_timings)
> --        stats = utils.run_and_get_func_stats(a, )
> --        stats.strip_dirs()
> --        stats.save("tests/a1.pstats", type="pstat")
> --        fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a"))
> --        fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d"))
> --        yappi.clear_stats()
> --        _yappi._set_test_timings(_timings)
> --        stats = utils.run_and_get_func_stats(a, )
> --        stats.strip_dirs()
> --        stats.save("tests/a2.pstats", type="pstat")
> --        yappi.clear_stats()
> --        _yappi._set_test_timings(_timings)
> --        stats = utils.run_and_get_func_stats(b, )
> --        stats.strip_dirs()
> --        stats.save("tests/b1.pstats", type="pstat")
> --        fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b"))
> --        yappi.clear_stats()
> --        _yappi._set_test_timings(_timings)
> --        stats = utils.run_and_get_func_stats(c, )
> --        stats.strip_dirs()
> --        stats.save("tests/c1.pstats", type="pstat")
> --        fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c"))
> --
> --        # merge saved stats and check pstats values are correct
> --        import pstats
> --        p = pstats.Stats(
> --            'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats',
> --            'tests/c1.pstats'
> --        )
> --        p.strip_dirs()
> --        # ct = ttot, tt = tsub
> --        (cc, nc, tt, ct, callers) = p.stats[fsa_pid]
> --        self.assertEqual(cc, nc, 2)
> --        self.assertEqual(tt, 20)
> --        self.assertEqual(ct, 24)
> --        (cc, nc, tt, ct, callers) = p.stats[fsd_pid]
> --        self.assertEqual(cc, nc, 3)
> --        self.assertEqual(tt, 6)
> --        self.assertEqual(ct, 6)
> --        self.assertEqual(len(callers), 2)
> --        (cc, nc, tt, ct) = callers[fsa_pid]
> --        self.assertEqual(cc, nc, 2)
> --        self.assertEqual(tt, 4)
> --        self.assertEqual(ct, 4)
> --        (cc, nc, tt, ct) = callers[fsb_pid]
> --        self.assertEqual(cc, nc, 1)
> --        self.assertEqual(tt, 2)
> --        self.assertEqual(ct, 2)
> --
> --    def test_merge_stats(self):
> --        _timings = {
> --            "a_1": 15,
> --            "b_1": 14,
> --            "c_1": 12,
> --            "d_1": 10,
> --            "e_1": 9,
> --            "f_1": 7,
> --            "g_1": 6,
> --            "h_1": 5,
> --            "i_1": 1
> --        }
> --        _yappi._set_test_timings(_timings)
> --
> --        def a():
> --            b()
> --
> --        def b():
> --            c()
> --
> --        def c():
> --            d()
> --
> --        def d():
> --            e()
> --
> --        def e():
> --            f()
> --
> --        def f():
> --            g()
> --
> --        def g():
> --            h()
> --
> --        def h():
> --            i()
> --
> --        def i():
> --            pass
> --
> --        yappi.start()
> --        a()
> --        a()
> --        yappi.stop()
> --        stats = yappi.get_func_stats()
> --        self.assertRaises(
> --            NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE"
> --        )
> --        stats.save("tests/ystats2.ys")
> --        yappi.clear_stats()
> --        _yappi._set_test_timings(_timings)
> --        yappi.start()
> --        a()
> --        stats = yappi.get_func_stats().add("tests/ystats2.ys")
> --        fsa = utils.find_stat_by_name(stats, "a")
> --        fsb = utils.find_stat_by_name(stats, "b")
> --        fsc = utils.find_stat_by_name(stats, "c")
> --        fsd = utils.find_stat_by_name(stats, "d")
> --        fse = utils.find_stat_by_name(stats, "e")
> --        fsf = utils.find_stat_by_name(stats, "f")
> --        fsg = utils.find_stat_by_name(stats, "g")
> --        fsh = utils.find_stat_by_name(stats, "h")
> --        fsi = utils.find_stat_by_name(stats, "i")
> --        self.assertEqual(fsa.ttot, 45)
> --        self.assertEqual(fsa.ncall, 3)
> --        self.assertEqual(fsa.nactualcall, 3)
> --        self.assertEqual(fsa.tsub, 3)
> --        self.assertEqual(fsa.children[fsb].ttot, fsb.ttot)
> --        self.assertEqual(fsa.children[fsb].tsub, fsb.tsub)
> --        self.assertEqual(fsb.children[fsc].ttot, fsc.ttot)
> --        self.assertEqual(fsb.children[fsc].tsub, fsc.tsub)
> --        self.assertEqual(fsc.tsub, 6)
> --        self.assertEqual(fsc.children[fsd].ttot, fsd.ttot)
> --        self.assertEqual(fsc.children[fsd].tsub, fsd.tsub)
> --        self.assertEqual(fsd.children[fse].ttot, fse.ttot)
> --        self.assertEqual(fsd.children[fse].tsub, fse.tsub)
> --        self.assertEqual(fse.children[fsf].ttot, fsf.ttot)
> --        self.assertEqual(fse.children[fsf].tsub, fsf.tsub)
> --        self.assertEqual(fsf.children[fsg].ttot, fsg.ttot)
> --        self.assertEqual(fsf.children[fsg].tsub, fsg.tsub)
> --        self.assertEqual(fsg.ttot, 18)
> --        self.assertEqual(fsg.tsub, 3)
> --        self.assertEqual(fsg.children[fsh].ttot, fsh.ttot)
> --        self.assertEqual(fsg.children[fsh].tsub, fsh.tsub)
> --        self.assertEqual(fsh.ttot, 15)
> --        self.assertEqual(fsh.tsub, 12)
> --        self.assertEqual(fsh.tavg, 5)
> --        self.assertEqual(fsh.children[fsi].ttot, fsi.ttot)
> --        self.assertEqual(fsh.children[fsi].tsub, fsi.tsub)
> --        #stats.debug_print()
> --
> --    def test_merge_multithreaded_stats(self):
> --        import _yappi
> --        timings = {"a_1": 2, "b_1": 1}
> --        _yappi._set_test_timings(timings)
> --
> --        def a():
> --            pass
> --
> --        def b():
> --            pass
> --
> --        yappi.start()
> --        t = threading.Thread(target=a)
> --        t.start()
> --        t.join()
> --        t = threading.Thread(target=b)
> --        t.start()
> --        t.join()
> --        yappi.get_func_stats().save("tests/ystats1.ys")
> --        yappi.clear_stats()
> --        _yappi._set_test_timings(timings)
> --        self.assertEqual(len(yappi.get_func_stats()), 0)
> --        self.assertEqual(len(yappi.get_thread_stats()), 1)
> --        t = threading.Thread(target=a)
> --        t.start()
> --        t.join()
> --
> --        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
> --        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
> --        yappi.get_func_stats().save("tests/ystats2.ys")
> --
> --        stats = yappi.YFuncStats([
> --            "tests/ystats1.ys",
> --            "tests/ystats2.ys",
> --        ])
> --        fsa = utils.find_stat_by_name(stats, "a")
> --        fsb = utils.find_stat_by_name(stats, "b")
> --        self.assertEqual(fsa.ncall, 2)
> --        self.assertEqual(fsb.ncall, 1)
> --        self.assertEqual(fsa.tsub, fsa.ttot, 4)
> --        self.assertEqual(fsb.tsub, fsb.ttot, 1)
> --
> --    def test_merge_load_different_clock_types(self):
> --        yappi.start(builtins=True)
> --
> --        def a():
> --            b()
> --
> --        def b():
> --            c()
> --
> --        def c():
> --            pass
> --
> --        t = threading.Thread(target=a)
> --        t.start()
> --        t.join()
> --        yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys")
> --        yappi.stop()
> --        yappi.clear_stats()
> --        yappi.start(builtins=False)
> --        t = threading.Thread(target=a)
> --        t.start()
> --        t.join()
> --        yappi.get_func_stats().save("tests/ystats2.ys")
> --        yappi.stop()
> --        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
> --        yappi.clear_stats()
> --        yappi.set_clock_type("wall")
> --        yappi.start()
> --        t = threading.Thread(target=a)
> --        t.start()
> --        t.join()
> --        yappi.get_func_stats().save("tests/ystats3.ys")
> --        self.assertRaises(
> --            yappi.YappiError,
> --            yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys"
> --        )
> --        stats = yappi.YFuncStats(["tests/ystats1.ys",
> --                                  "tests/ystats2.ys"]).sort("name")
> --        fsa = utils.find_stat_by_name(stats, "a")
> --        fsb = utils.find_stat_by_name(stats, "b")
> --        fsc = utils.find_stat_by_name(stats, "c")
> --        self.assertEqual(fsa.ncall, 2)
> --        self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall)
> --
> --    def test_merge_aabab_aabbc(self):
> --        _timings = {
> --            "a_1": 15,
> --            "a_2": 14,
> --            "b_1": 12,
> --            "a_3": 10,
> --            "b_2": 9,
> --            "c_1": 4
> --        }
> --        _yappi._set_test_timings(_timings)
> --
> --        def a():
> --            if self._ncall == 1:
> --                self._ncall += 1
> --                a()
> --            elif self._ncall == 5:
> --                self._ncall += 1
> --                a()
> --            else:
> --                b()
> --
> --        def b():
> --            if self._ncall == 2:
> --                self._ncall += 1
> --                a()
> --            elif self._ncall == 6:
> --                self._ncall += 1
> --                b()
> --            elif self._ncall == 7:
> --                c()
> --            else:
> --                return
> --
> --        def c():
> --            pass
> --
> --        self._ncall = 1
> --        stats = utils.run_and_get_func_stats(a, )
> --        stats.save("tests/ystats1.ys")
> --        yappi.clear_stats()
> --        _yappi._set_test_timings(_timings)
> --        #stats.print_all()
> --
> --        self._ncall = 5
> --        stats = utils.run_and_get_func_stats(a, )
> --        stats.save("tests/ystats2.ys")
> --
> --        #stats.print_all()
> --
> --        def a():  # same name but another function(code object)
> --            pass
> --
> --        yappi.start()
> --        a()
> --        stats = yappi.get_func_stats().add(
> --            ["tests/ystats1.ys", "tests/ystats2.ys"]
> --        )
> --        #stats.print_all()
> --        self.assertEqual(len(stats), 4)
> --
> --        fsa = None
> --        for stat in stats:
> --            if stat.name == "a" and stat.ttot == 45:
> --                fsa = stat
> --                break
> --        self.assertTrue(fsa is not None)
> --
> --        self.assertEqual(fsa.ncall, 7)
> --        self.assertEqual(fsa.nactualcall, 3)
> --        self.assertEqual(fsa.ttot, 45)
> --        self.assertEqual(fsa.tsub, 10)
> --        fsb = utils.find_stat_by_name(stats, "b")
> --        fsc = utils.find_stat_by_name(stats, "c")
> --        self.assertEqual(fsb.ncall, 6)
> --        self.assertEqual(fsb.nactualcall, 3)
> --        self.assertEqual(fsb.ttot, 36)
> --        self.assertEqual(fsb.tsub, 27)
> --        self.assertEqual(fsb.tavg, 6)
> --        self.assertEqual(fsc.ttot, 8)
> --        self.assertEqual(fsc.tsub, 8)
> --        self.assertEqual(fsc.tavg, 4)
> --        self.assertEqual(fsc.nactualcall, fsc.ncall, 2)
> --
> --
> --class MultithreadedScenarios(utils.YappiUnitTestCase):
> --
> --    def test_issue_32(self):
> --        '''
> --        Start yappi from different thread and we get Internal Error(15) as
> --        the current_ctx_id() called while enumerating the threads in start()
> --        and as it does not swap to the enumerated ThreadState* the THreadState_GetDict()
> --        returns wrong object and thus sets an invalid id for the _ctx structure.
> --
> --        When this issue happens multiple Threads have same tid as the internal ts_ptr
> --        will be same for different contexts. So, let's see if that happens
> --        '''
> --
> --        def foo():
> --            time.sleep(0.2)
> --
> --        def bar():
> --            time.sleep(0.1)
> --
> --        def thread_func():
> --            yappi.set_clock_type("wall")
> --            yappi.start()
> --
> --            bar()
> --
> --        t = threading.Thread(target=thread_func)
> --        t.start()
> --        t.join()
> --
> --        foo()
> --
> --        yappi.stop()
> --
> --        thread_ids = set()
> --        for tstat in yappi.get_thread_stats():
> --            self.assertTrue(tstat.tid not in thread_ids)
> --            thread_ids.add(tstat.tid)
> --
> --    def test_subsequent_profile(self):
> --        WORKER_COUNT = 5
> --
> --        def a():
> --            pass
> --
> --        def b():
> --            pass
> --
> --        def c():
> --            pass
> --
> --        _timings = {
> --            "a_1": 3,
> --            "b_1": 2,
> --            "c_1": 1,
> --        }
> --
> --        yappi.start()
> --
> --        def g():
> --            pass
> --
> --        g()
> --        yappi.stop()
> --        yappi.clear_stats()
> --        _yappi._set_test_timings(_timings)
> --        yappi.start()
> --
> --        _dummy = []
> --        for i in range(WORKER_COUNT):
> --            t = threading.Thread(target=a)
> --            t.start()
> --            t.join()
> --        for i in range(WORKER_COUNT):
> --            t = threading.Thread(target=b)
> --            t.start()
> --            _dummy.append(t)
> --            t.join()
> --        for i in range(WORKER_COUNT):
> --            t = threading.Thread(target=a)
> --            t.start()
> --            t.join()
> --        for i in range(WORKER_COUNT):
> --            t = threading.Thread(target=c)
> --            t.start()
> --            t.join()
> --        yappi.stop()
> --        yappi.start()
> --
> --        def f():
> --            pass
> --
> --        f()
> --        stats = yappi.get_func_stats()
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        fsc = utils.find_stat_by_name(stats, 'c')
> --        self.assertEqual(fsa.ncall, 10)
> --        self.assertEqual(fsb.ncall, 5)
> --        self.assertEqual(fsc.ncall, 5)
> --        self.assertEqual(fsa.ttot, fsa.tsub, 30)
> --        self.assertEqual(fsb.ttot, fsb.tsub, 10)
> --        self.assertEqual(fsc.ttot, fsc.tsub, 5)
> --
> --        # MACOSx optimizes by only creating one worker thread
> --        self.assertTrue(len(yappi.get_thread_stats()) >= 2)
> --
> --    def test_basic(self):
> --        yappi.set_clock_type('wall')
> --
> --        def dummy():
> --            pass
> --
> --        def a():
> --            time.sleep(0.2)
> --
> --        class Worker1(threading.Thread):
> --
> --            def a(self):
> --                time.sleep(0.3)
> --
> --            def run(self):
> --                self.a()
> --
> --        yappi.start(builtins=False, profile_threads=True)
> --
> --        c = Worker1()
> --        c.start()
> --        c.join()
> --        a()
> --        stats = yappi.get_func_stats()
> --        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
> --        fsa2 = utils.find_stat_by_name(stats, 'a')
> --        self.assertTrue(fsa1 is not None)
> --        self.assertTrue(fsa2 is not None)
> --        self.assertTrue(fsa1.ttot > 0.2)
> --        self.assertTrue(fsa2.ttot > 0.1)
> --        tstats = yappi.get_thread_stats()
> --        self.assertEqual(len(tstats), 2)
> --        tsa = utils.find_stat_by_name(tstats, 'Worker1')
> --        tsm = utils.find_stat_by_name(tstats, '_MainThread')
> --        dummy()  # call dummy to force ctx name to be retrieved again.
> --        self.assertTrue(tsa is not None)
> --        # TODO: I put dummy() to fix below, remove the comments after a while.
> --        self.assertTrue( # FIX: I see this fails sometimes?
> --            tsm is not None,
> --            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(tstats))))
> --
> --    def test_ctx_stats(self):
> --        from threading import Thread
> --        DUMMY_WORKER_COUNT = 5
> --        yappi.start()
> --
> --        class DummyThread(Thread):
> --            pass
> --
> --        def dummy():
> --            pass
> --
> --        def dummy_worker():
> --            pass
> --
> --        for i in range(DUMMY_WORKER_COUNT):
> --            t = DummyThread(target=dummy_worker)
> --            t.start()
> --            t.join()
> --        yappi.stop()
> --        stats = yappi.get_thread_stats()
> --        tsa = utils.find_stat_by_name(stats, "DummyThread")
> --        self.assertTrue(tsa is not None)
> --        yappi.clear_stats()
> --        time.sleep(1.0)
> --        _timings = {
> --            "a_1": 6,
> --            "b_1": 5,
> --            "c_1": 3,
> --            "d_1": 1,
> --            "a_2": 4,
> --            "b_2": 3,
> --            "c_2": 2,
> --            "d_2": 1
> --        }
> --        _yappi._set_test_timings(_timings)
> --
> --        class Thread1(Thread):
> --            pass
> --
> --        class Thread2(Thread):
> --            pass
> --
> --        def a():
> --            b()
> --
> --        def b():
> --            c()
> --
> --        def c():
> --            d()
> --
> --        def d():
> --            time.sleep(0.6)
> --
> --        yappi.set_clock_type("wall")
> --        yappi.start()
> --        t1 = Thread1(target=a)
> --        t1.start()
> --        t2 = Thread2(target=a)
> --        t2.start()
> --        t1.join()
> --        t2.join()
> --        stats = yappi.get_thread_stats()
> --
> --        # the fist clear_stats clears the context table?
> --        tsa = utils.find_stat_by_name(stats, "DummyThread")
> --        self.assertTrue(tsa is None)
> --
> --        tst1 = utils.find_stat_by_name(stats, "Thread1")
> --        tst2 = utils.find_stat_by_name(stats, "Thread2")
> --        tsmain = utils.find_stat_by_name(stats, "_MainThread")
> --        dummy()  # call dummy to force ctx name to be retrieved again.
> --        self.assertTrue(len(stats) == 3)
> --        self.assertTrue(tst1 is not None)
> --        self.assertTrue(tst2 is not None)
> --        # TODO: I put dummy() to fix below, remove the comments after a while.
> --        self.assertTrue( # FIX: I see this fails sometimes
> --            tsmain is not None,
> --            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(stats))))
> --        self.assertTrue(1.0 > tst2.ttot >= 0.5)
> --        self.assertTrue(1.0 > tst1.ttot >= 0.5)
> --
> --        # test sorting of the ctx stats
> --        stats = stats.sort("totaltime", "desc")
> --        prev_stat = None
> --        for stat in stats:
> --            if prev_stat:
> --                self.assertTrue(prev_stat.ttot >= stat.ttot)
> --            prev_stat = stat
> --        stats = stats.sort("totaltime", "asc")
> --        prev_stat = None
> --        for stat in stats:
> --            if prev_stat:
> --                self.assertTrue(prev_stat.ttot <= stat.ttot)
> --            prev_stat = stat
> --        stats = stats.sort("schedcount", "desc")
> --        prev_stat = None
> --        for stat in stats:
> --            if prev_stat:
> --                self.assertTrue(prev_stat.sched_count >= stat.sched_count)
> --            prev_stat = stat
> --        stats = stats.sort("name", "desc")
> --        prev_stat = None
> --        for stat in stats:
> --            if prev_stat:
> --                self.assertTrue(prev_stat.name.lower() >= stat.name.lower())
> --            prev_stat = stat
> --        self.assertRaises(
> --            yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg"
> --        )
> --        self.assertRaises(
> --            yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg"
> --        )
> --
> --    def test_ctx_stats_cpu(self):
> --
> --        def get_thread_name():
> --            try:
> --                return threading.current_thread().name
> --            except AttributeError:
> --                return "Anonymous"
> --
> --        def burn_cpu(sec):
> --            t0 = yappi.get_clock_time()
> --            elapsed = 0
> --            while (elapsed < sec):
> --                for _ in range(1000):
> --                    pass
> --                elapsed = yappi.get_clock_time() - t0
> --
> --        def test():
> --
> --            ts = []
> --            for i in (0.01, 0.05, 0.1):
> --                t = threading.Thread(target=burn_cpu, args=(i, ))
> --                t.name = "burn_cpu-%s" % str(i)
> --                t.start()
> --                ts.append(t)
> --            for t in ts:
> --                t.join()
> --
> --        yappi.set_clock_type("cpu")
> --        yappi.set_context_name_callback(get_thread_name)
> --
> --        yappi.start()
> --
> --        test()
> --
> --        yappi.stop()
> --
> --        tstats = yappi.get_thread_stats()
> --        r1 = '''
> --        burn_cpu-0.1      3      123145356058624  0.100105  8
> --        burn_cpu-0.05     2      123145361313792  0.050149  8
> --        burn_cpu-0.01     1      123145356058624  0.010127  2
> --        MainThread        0      4321620864       0.001632  6
> --        '''
> --        self.assert_ctx_stats_almost_equal(r1, tstats)
> --
> --    def test_producer_consumer_with_queues(self):
> --        # we currently just stress yappi, no functionality test is done here.
> --        yappi.start()
> --        if utils.is_py3x():
> --            from queue import Queue
> --        else:
> --            from Queue import Queue
> --        from threading import Thread
> --        WORKER_THREAD_COUNT = 50
> --        WORK_ITEM_COUNT = 2000
> --
> --        def worker():
> --            while True:
> --                item = q.get()
> --                # do the work with item
> --                q.task_done()
> --
> --        q = Queue()
> --        for i in range(WORKER_THREAD_COUNT):
> --            t = Thread(target=worker)
> --            t.daemon = True
> --            t.start()
> --
> --        for item in range(WORK_ITEM_COUNT):
> --            q.put(item)
> --        q.join()  # block until all tasks are done
> --        #yappi.get_func_stats().sort("callcount").print_all()
> --        yappi.stop()
> --
> --    def test_temporary_lock_waiting(self):
> --        yappi.start()
> --        _lock = threading.Lock()
> --
> --        def worker():
> --            _lock.acquire()
> --            try:
> --                time.sleep(1.0)
> --            finally:
> --                _lock.release()
> --
> --        t1 = threading.Thread(target=worker)
> --        t2 = threading.Thread(target=worker)
> --        t1.start()
> --        t2.start()
> --        t1.join()
> --        t2.join()
> --        #yappi.get_func_stats().sort("callcount").print_all()
> --        yappi.stop()
> --
> --    @unittest.skipIf(os.name != "posix", "requires Posix compliant OS")
> --    def test_signals_with_blocking_calls(self):
> --        import signal, os, time
> --
> --        # just to verify if signal is handled correctly and stats/yappi are not corrupted.
> --        def handler(signum, frame):
> --            raise Exception("Signal handler executed!")
> --
> --        yappi.start()
> --        signal.signal(signal.SIGALRM, handler)
> --        signal.alarm(1)
> --        self.assertRaises(Exception, time.sleep, 2)
> --        stats = yappi.get_func_stats()
> --        fsh = utils.find_stat_by_name(stats, "handler")
> --        self.assertTrue(fsh is not None)
> --
> --    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
> --    def test_concurrent_futures(self):
> --        yappi.start()
> --        from concurrent.futures import ThreadPoolExecutor
> --        with ThreadPoolExecutor(max_workers=5) as executor:
> --            f = executor.submit(pow, 5, 2)
> --            self.assertEqual(f.result(), 25)
> --        time.sleep(1.0)
> --        yappi.stop()
> --
> --    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
> --    def test_barrier(self):
> --        yappi.start()
> --        b = threading.Barrier(2, timeout=1)
> --
> --        def worker():
> --            try:
> --                b.wait()
> --            except threading.BrokenBarrierError:
> --                pass
> --            except Exception:
> --                raise Exception("BrokenBarrierError not raised")
> --
> --        t1 = threading.Thread(target=worker)
> --        t1.start()
> --        #b.wait()
> --        t1.join()
> --        yappi.stop()
> --
> --
> --class NonRecursiveFunctions(utils.YappiUnitTestCase):
> --
> --    def test_abcd(self):
> --        _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1}
> --        _yappi._set_test_timings(_timings)
> --
> --        def a():
> --            b()
> --
> --        def b():
> --            c()
> --
> --        def c():
> --            d()
> --
> --        def d():
> --            pass
> --
> --        stats = utils.run_and_get_func_stats(a)
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        fsc = utils.find_stat_by_name(stats, 'c')
> --        fsd = utils.find_stat_by_name(stats, 'd')
> --        cfsab = fsa.children[fsb]
> --        cfsbc = fsb.children[fsc]
> --        cfscd = fsc.children[fsd]
> --
> --        self.assertEqual(fsa.ttot, 6)
> --        self.assertEqual(fsa.tsub, 1)
> --        self.assertEqual(fsb.ttot, 5)
> --        self.assertEqual(fsb.tsub, 2)
> --        self.assertEqual(fsc.ttot, 3)
> --        self.assertEqual(fsc.tsub, 2)
> --        self.assertEqual(fsd.ttot, 1)
> --        self.assertEqual(fsd.tsub, 1)
> --        self.assertEqual(cfsab.ttot, 5)
> --        self.assertEqual(cfsab.tsub, 2)
> --        self.assertEqual(cfsbc.ttot, 3)
> --        self.assertEqual(cfsbc.tsub, 2)
> --        self.assertEqual(cfscd.ttot, 1)
> --        self.assertEqual(cfscd.tsub, 1)
> --
> --    def test_stop_in_middle(self):
> --        _timings = {"a_1": 6, "b_1": 4}
> --        _yappi._set_test_timings(_timings)
> --
> --        def a():
> --            b()
> --            yappi.stop()
> --
> --        def b():
> --            time.sleep(0.2)
> --
> --        yappi.start()
> --        a()
> --        stats = yappi.get_func_stats()
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --
> --        self.assertEqual(fsa.ncall, 1)
> --        self.assertEqual(fsa.nactualcall, 0)
> --        self.assertEqual(fsa.ttot, 0)  # no call_leave called
> --        self.assertEqual(fsa.tsub, 0)  # no call_leave called
> --        self.assertEqual(fsb.ttot, 4)
> --
> --
> --class RecursiveFunctions(utils.YappiUnitTestCase):
> --
> --    def test_fibonacci(self):
> --
> --        def fib(n):
> --            if n > 1:
> --                return fib(n - 1) + fib(n - 2)
> --            else:
> --                return n
> --
> --        stats = utils.run_and_get_func_stats(fib, 22)
> --        fs = utils.find_stat_by_name(stats, 'fib')
> --        self.assertEqual(fs.ncall, 57313)
> --        self.assertEqual(fs.ttot, fs.tsub)
> --
> --    def test_abcadc(self):
> --        _timings = {
> --            "a_1": 20,
> --            "b_1": 19,
> --            "c_1": 17,
> --            "a_2": 13,
> --            "d_1": 12,
> --            "c_2": 10,
> --            "a_3": 5
> --        }
> --        _yappi._set_test_timings(_timings)
> --
> --        def a(n):
> --            if n == 3:
> --                return
> --            if n == 1 + 1:
> --                d(n)
> --            else:
> --                b(n)
> --
> --        def b(n):
> --            c(n)
> --
> --        def c(n):
> --            a(n + 1)
> --
> --        def d(n):
> --            c(n)
> --
> --        stats = utils.run_and_get_func_stats(a, 1)
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        fsc = utils.find_stat_by_name(stats, 'c')
> --        fsd = utils.find_stat_by_name(stats, 'd')
> --        self.assertEqual(fsa.ncall, 3)
> --        self.assertEqual(fsa.nactualcall, 1)
> --        self.assertEqual(fsa.ttot, 20)
> --        self.assertEqual(fsa.tsub, 7)
> --        self.assertEqual(fsb.ttot, 19)
> --        self.assertEqual(fsb.tsub, 2)
> --        self.assertEqual(fsc.ttot, 17)
> --        self.assertEqual(fsc.tsub, 9)
> --        self.assertEqual(fsd.ttot, 12)
> --        self.assertEqual(fsd.tsub, 2)
> --        cfsca = fsc.children[fsa]
> --        self.assertEqual(cfsca.nactualcall, 0)
> --        self.assertEqual(cfsca.ncall, 2)
> --        self.assertEqual(cfsca.ttot, 13)
> --        self.assertEqual(cfsca.tsub, 6)
> --
> --    def test_aaaa(self):
> --        _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2}
> --        _yappi._set_test_timings(_timings)
> --
> --        def d(n):
> --            if n == 3:
> --                return
> --            d(n + 1)
> --
> --        stats = utils.run_and_get_func_stats(d, 0)
> --        fsd = utils.find_stat_by_name(stats, 'd')
> --        self.assertEqual(fsd.ncall, 4)
> --        self.assertEqual(fsd.nactualcall, 1)
> --        self.assertEqual(fsd.ttot, 9)
> --        self.assertEqual(fsd.tsub, 9)
> --        cfsdd = fsd.children[fsd]
> --        self.assertEqual(cfsdd.ttot, 7)
> --        self.assertEqual(cfsdd.tsub, 7)
> --        self.assertEqual(cfsdd.ncall, 3)
> --        self.assertEqual(cfsdd.nactualcall, 0)
> --
> --    def test_abcabc(self):
> --        _timings = {
> --            "a_1": 20,
> --            "b_1": 19,
> --            "c_1": 17,
> --            "a_2": 13,
> --            "b_2": 11,
> --            "c_2": 9,
> --            "a_3": 6
> --        }
> --        _yappi._set_test_timings(_timings)
> --
> --        def a(n):
> --            if n == 3:
> --                return
> --            else:
> --                b(n)
> --
> --        def b(n):
> --            c(n)
> --
> --        def c(n):
> --            a(n + 1)
> --
> --        stats = utils.run_and_get_func_stats(a, 1)
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        fsc = utils.find_stat_by_name(stats, 'c')
> --        self.assertEqual(fsa.ncall, 3)
> --        self.assertEqual(fsa.nactualcall, 1)
> --        self.assertEqual(fsa.ttot, 20)
> --        self.assertEqual(fsa.tsub, 9)
> --        self.assertEqual(fsb.ttot, 19)
> --        self.assertEqual(fsb.tsub, 4)
> --        self.assertEqual(fsc.ttot, 17)
> --        self.assertEqual(fsc.tsub, 7)
> --        cfsab = fsa.children[fsb]
> --        cfsbc = fsb.children[fsc]
> --        cfsca = fsc.children[fsa]
> --        self.assertEqual(cfsab.ttot, 19)
> --        self.assertEqual(cfsab.tsub, 4)
> --        self.assertEqual(cfsbc.ttot, 17)
> --        self.assertEqual(cfsbc.tsub, 7)
> --        self.assertEqual(cfsca.ttot, 13)
> --        self.assertEqual(cfsca.tsub, 8)
> --
> --    def test_abcbca(self):
> --        _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1}
> --        _yappi._set_test_timings(_timings)
> --        self._ncall = 1
> --
> --        def a():
> --            if self._ncall == 1:
> --                b()
> --            else:
> --                return
> --
> --        def b():
> --            c()
> --
> --        def c():
> --            if self._ncall == 1:
> --                self._ncall += 1
> --                b()
> --            else:
> --                a()
> --
> --        stats = utils.run_and_get_func_stats(a)
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        fsc = utils.find_stat_by_name(stats, 'c')
> --        cfsab = fsa.children[fsb]
> --        cfsbc = fsb.children[fsc]
> --        cfsca = fsc.children[fsa]
> --        self.assertEqual(fsa.ttot, 10)
> --        self.assertEqual(fsa.tsub, 2)
> --        self.assertEqual(fsb.ttot, 9)
> --        self.assertEqual(fsb.tsub, 4)
> --        self.assertEqual(fsc.ttot, 7)
> --        self.assertEqual(fsc.tsub, 4)
> --        self.assertEqual(cfsab.ttot, 9)
> --        self.assertEqual(cfsab.tsub, 2)
> --        self.assertEqual(cfsbc.ttot, 7)
> --        self.assertEqual(cfsbc.tsub, 4)
> --        self.assertEqual(cfsca.ttot, 1)
> --        self.assertEqual(cfsca.tsub, 1)
> --        self.assertEqual(cfsca.ncall, 1)
> --        self.assertEqual(cfsca.nactualcall, 0)
> --
> --    def test_aabccb(self):
> --        _timings = {
> --            "a_1": 13,
> --            "a_2": 11,
> --            "b_1": 9,
> --            "c_1": 5,
> --            "c_2": 3,
> --            "b_2": 1
> --        }
> --        _yappi._set_test_timings(_timings)
> --        self._ncall = 1
> --
> --        def a():
> --            if self._ncall == 1:
> --                self._ncall += 1
> --                a()
> --            else:
> --                b()
> --
> --        def b():
> --            if self._ncall == 3:
> --                return
> --            else:
> --                c()
> --
> --        def c():
> --            if self._ncall == 2:
> --                self._ncall += 1
> --                c()
> --            else:
> --                b()
> --
> --        stats = utils.run_and_get_func_stats(a)
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        fsc = utils.find_stat_by_name(stats, 'c')
> --        cfsaa = fsa.children[fsa.index]
> --        cfsab = fsa.children[fsb]
> --        cfsbc = fsb.children[fsc.full_name]
> --        cfscc = fsc.children[fsc]
> --        cfscb = fsc.children[fsb]
> --        self.assertEqual(fsb.ttot, 9)
> --        self.assertEqual(fsb.tsub, 5)
> --        self.assertEqual(cfsbc.ttot, 5)
> --        self.assertEqual(cfsbc.tsub, 2)
> --        self.assertEqual(fsa.ttot, 13)
> --        self.assertEqual(fsa.tsub, 4)
> --        self.assertEqual(cfsab.ttot, 9)
> --        self.assertEqual(cfsab.tsub, 4)
> --        self.assertEqual(cfsaa.ttot, 11)
> --        self.assertEqual(cfsaa.tsub, 2)
> --        self.assertEqual(fsc.ttot, 5)
> --        self.assertEqual(fsc.tsub, 4)
> --
> --    def test_abaa(self):
> --        _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5}
> --        _yappi._set_test_timings(_timings)
> --
> --        self._ncall = 1
> --
> --        def a():
> --            if self._ncall == 1:
> --                b()
> --            elif self._ncall == 2:
> --                self._ncall += 1
> --                a()
> --            else:
> --                return
> --
> --        def b():
> --            self._ncall += 1
> --            a()
> --
> --        stats = utils.run_and_get_func_stats(a)
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        cfsaa = fsa.children[fsa]
> --        cfsba = fsb.children[fsa]
> --        self.assertEqual(fsb.ttot, 10)
> --        self.assertEqual(fsb.tsub, 1)
> --        self.assertEqual(fsa.ttot, 13)
> --        self.assertEqual(fsa.tsub, 12)
> --        self.assertEqual(cfsaa.ttot, 5)
> --        self.assertEqual(cfsaa.tsub, 5)
> --        self.assertEqual(cfsba.ttot, 9)
> --        self.assertEqual(cfsba.tsub, 4)
> --
> --    def test_aabb(self):
> --        _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5}
> --        _yappi._set_test_timings(_timings)
> --
> --        self._ncall = 1
> --
> --        def a():
> --            if self._ncall == 1:
> --                self._ncall += 1
> --                a()
> --            elif self._ncall == 2:
> --                b()
> --            else:
> --                return
> --
> --        def b():
> --            if self._ncall == 2:
> --                self._ncall += 1
> --                b()
> --            else:
> --                return
> --
> --        stats = utils.run_and_get_func_stats(a)
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        cfsaa = fsa.children[fsa]
> --        cfsab = fsa.children[fsb]
> --        cfsbb = fsb.children[fsb]
> --        self.assertEqual(fsa.ttot, 13)
> --        self.assertEqual(fsa.tsub, 4)
> --        self.assertEqual(fsb.ttot, 9)
> --        self.assertEqual(fsb.tsub, 9)
> --        self.assertEqual(cfsaa.ttot, 10)
> --        self.assertEqual(cfsaa.tsub, 1)
> --        self.assertEqual(cfsab.ttot, 9)
> --        self.assertEqual(cfsab.tsub, 4)
> --        self.assertEqual(cfsbb.ttot, 5)
> --        self.assertEqual(cfsbb.tsub, 5)
> --
> --    def test_abbb(self):
> --        _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1}
> --        _yappi._set_test_timings(_timings)
> --
> --        self._ncall = 1
> --
> --        def a():
> --            if self._ncall == 1:
> --                b()
> --
> --        def b():
> --            if self._ncall == 3:
> --                return
> --            self._ncall += 1
> --            b()
> --
> --        stats = utils.run_and_get_func_stats(a)
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        cfsab = fsa.children[fsb]
> --        cfsbb = fsb.children[fsb]
> --        self.assertEqual(fsa.ttot, 13)
> --        self.assertEqual(fsa.tsub, 3)
> --        self.assertEqual(fsb.ttot, 10)
> --        self.assertEqual(fsb.tsub, 10)
> --        self.assertEqual(fsb.ncall, 3)
> --        self.assertEqual(fsb.nactualcall, 1)
> --        self.assertEqual(cfsab.ttot, 10)
> --        self.assertEqual(cfsab.tsub, 4)
> --        self.assertEqual(cfsbb.ttot, 6)
> --        self.assertEqual(cfsbb.tsub, 6)
> --        self.assertEqual(cfsbb.nactualcall, 0)
> --        self.assertEqual(cfsbb.ncall, 2)
> --
> --    def test_aaab(self):
> --        _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1}
> --        _yappi._set_test_timings(_timings)
> --
> --        self._ncall = 1
> --
> --        def a():
> --            if self._ncall == 3:
> --                b()
> --                return
> --            self._ncall += 1
> --            a()
> --
> --        def b():
> --            return
> --
> --        stats = utils.run_and_get_func_stats(a)
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        cfsaa = fsa.children[fsa]
> --        cfsab = fsa.children[fsb]
> --        self.assertEqual(fsa.ttot, 13)
> --        self.assertEqual(fsa.tsub, 12)
> --        self.assertEqual(fsb.ttot, 1)
> --        self.assertEqual(fsb.tsub, 1)
> --        self.assertEqual(cfsaa.ttot, 10)
> --        self.assertEqual(cfsaa.tsub, 9)
> --        self.assertEqual(cfsab.ttot, 1)
> --        self.assertEqual(cfsab.tsub, 1)
> --
> --    def test_abab(self):
> --        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
> --        _yappi._set_test_timings(_timings)
> --
> --        self._ncall = 1
> --
> --        def a():
> --            b()
> --
> --        def b():
> --            if self._ncall == 2:
> --                return
> --            self._ncall += 1
> --            a()
> --
> --        stats = utils.run_and_get_func_stats(a)
> --        fsa = utils.find_stat_by_name(stats, 'a')
> --        fsb = utils.find_stat_by_name(stats, 'b')
> --        cfsab = fsa.children[fsb]
> --        cfsba = fsb.children[fsa]
> --        self.assertEqual(fsa.ttot, 13)
> --        self.assertEqual(fsa.tsub, 8)
> --        self.assertEqual(fsb.ttot, 10)
> --        self.assertEqual(fsb.tsub, 5)
> --        self.assertEqual(cfsab.ttot, 10)
> --        self.assertEqual(cfsab.tsub, 5)
> --        self.assertEqual(cfsab.ncall, 2)
> --        self.assertEqual(cfsab.nactualcall, 1)
> --        self.assertEqual(cfsba.ttot, 6)
> --        self.assertEqual(cfsba.tsub, 5)
> --
> --
> --if __name__ == '__main__':
> --    #     import sys;sys.argv = ['', 'BasicUsage.test_run_as_script']
> --    #     import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile']
> --    unittest.main()
> -+import os
> -+import sys
> -+import time
> -+import threading
> -+import unittest
> -+import yappi
> -+import _yappi
> -+import tests.utils as utils
> -+import multiprocessing  # added to fix http://bugs.python.org/issue15881 for > Py2.6
> -+import subprocess
> -+
> -+_counter = 0
> -+
> -+
> -+class BasicUsage(utils.YappiUnitTestCase):
> -+
> -+    def test_callback_function_int_return_overflow(self):
> -+        # this test is just here to check if any errors are generated, as the err
> -+        # is printed in C side, I did not include it here. THere are ways to test
> -+        # this deterministically, I did not bother
> -+        import ctypes
> -+
> -+        def _unsigned_overflow_margin():
> -+            return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1
> -+
> -+        def foo():
> -+            pass
> -+
> -+        #with utils.captured_output() as (out, err):
> -+        yappi.set_context_id_callback(_unsigned_overflow_margin)
> -+        yappi.set_tag_callback(_unsigned_overflow_margin)
> -+        yappi.start()
> -+        foo()
> -+
> -+    def test_issue60(self):
> -+
> -+        def foo():
> -+            buf = bytearray()
> -+            buf += b't' * 200
> -+            view = memoryview(buf)[10:]
> -+            view = view.tobytes()
> -+            del buf[:10]  # this throws exception
> -+            return view
> -+
> -+        yappi.start(builtins=True)
> -+        foo()
> -+        self.assertTrue(
> -+            len(
> -+                yappi.get_func_stats(
> -+                    filter_callback=lambda x: yappi.
> -+                    func_matches(x, [memoryview.tobytes])
> -+                )
> -+            ) > 0
> -+        )
> -+        yappi.stop()
> -+
> -+    def test_issue54(self):
> -+
> -+        def _tag_cbk():
> -+            global _counter
> -+            _counter += 1
> -+            return _counter
> -+
> -+        def a():
> -+            pass
> -+
> -+        def b():
> -+            pass
> -+
> -+        yappi.set_tag_callback(_tag_cbk)
> -+        yappi.start()
> -+        a()
> -+        a()
> -+        a()
> -+        yappi.stop()
> -+        stats = yappi.get_func_stats()
> -+        self.assertEqual(stats.pop().ncall, 3)  # aggregated if no tag is given
> -+        stats = yappi.get_func_stats(tag=1)
> -+
> -+        for i in range(1, 3):
> -+            stats = yappi.get_func_stats(tag=i)
> -+            stats = yappi.get_func_stats(
> -+                tag=i, filter_callback=lambda x: yappi.func_matches(x, [a])
> -+            )
> -+
> -+            stat = stats.pop()
> -+            self.assertEqual(stat.ncall, 1)
> -+
> -+        yappi.set_tag_callback(None)
> -+        yappi.clear_stats()
> -+        yappi.start()
> -+        b()
> -+        b()
> -+        stats = yappi.get_func_stats()
> -+        self.assertEqual(len(stats), 1)
> -+        stat = stats.pop()
> -+        self.assertEqual(stat.ncall, 2)
> -+
> -+    def test_filter(self):
> -+
> -+        def a():
> -+            pass
> -+
> -+        def b():
> -+            a()
> -+
> -+        def c():
> -+            b()
> -+
> -+        _TCOUNT = 5
> -+
> -+        ts = []
> -+        yappi.start()
> -+        for i in range(_TCOUNT):
> -+            t = threading.Thread(target=c)
> -+            t.start()
> -+            ts.append(t)
> -+
> -+        for t in ts:
> -+            t.join()
> -+
> -+        yappi.stop()
> -+
> -+        ctx_ids = []
> -+        for tstat in yappi.get_thread_stats():
> -+            if tstat.name == '_MainThread':
> -+                main_ctx_id = tstat.id
> -+            else:
> -+                ctx_ids.append(tstat.id)
> -+
> -+        fstats = yappi.get_func_stats(filter={"ctx_id": 9})
> -+        self.assertTrue(fstats.empty())
> -+        fstats = yappi.get_func_stats(
> -+            filter={
> -+                "ctx_id": main_ctx_id,
> -+                "name": "c"
> -+            }
> -+        )  # main thread
> -+        self.assertTrue(fstats.empty())
> -+
> -+        for i in ctx_ids:
> -+            fstats = yappi.get_func_stats(
> -+                filter={
> -+                    "ctx_id": i,
> -+                    "name": "a",
> -+                    "ncall": 1
> -+                }
> -+            )
> -+            self.assertEqual(fstats.pop().ncall, 1)
> -+            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"})
> -+            self.assertEqual(fstats.pop().ncall, 1)
> -+            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"})
> -+            self.assertEqual(fstats.pop().ncall, 1)
> -+
> -+        yappi.clear_stats()
> -+        yappi.start(builtins=True)
> -+        time.sleep(0.1)
> -+        yappi.stop()
> -+        fstats = yappi.get_func_stats(filter={"module": "time"})
> -+        self.assertEqual(len(fstats), 1)
> -+
> -+        # invalid filters`
> -+        self.assertRaises(
> -+            Exception, yappi.get_func_stats, filter={'tag': "sss"}
> -+        )
> -+        self.assertRaises(
> -+            Exception, yappi.get_func_stats, filter={'ctx_id': "None"}
> -+        )
> -+
> -+    def test_filter_callback(self):
> -+
> -+        def a():
> -+            time.sleep(0.1)
> -+
> -+        def b():
> -+            a()
> -+
> -+        def c():
> -+            pass
> -+
> -+        def d():
> -+            pass
> -+
> -+        yappi.set_clock_type("wall")
> -+        yappi.start(builtins=True)
> -+        a()
> -+        b()
> -+        c()
> -+        d()
> -+        stats = yappi.get_func_stats(
> -+            filter_callback=lambda x: yappi.func_matches(x, [a, b])
> -+        )
> -+        #stats.print_all()
> -+        r1 = '''
> -+        tests/test_functionality.py:98 a      2      0.000000  0.200350  0.100175
> -+        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.100197
> -+        '''
> -+        self.assert_traces_almost_equal(r1, stats)
> -+        self.assertEqual(len(stats), 2)
> -+        stats = yappi.get_func_stats(
> -+            filter_callback=lambda x: yappi.
> -+            module_matches(x, [sys.modules[__name__]])
> -+        )
> -+        r1 = '''
> -+        tests/test_functionality.py:98 a      2      0.000000  0.230130  0.115065
> -+        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.109011
> -+        tests/test_functionality.py:104 c     1      0.000000  0.000002  0.000002
> -+        tests/test_functionality.py:107 d     1      0.000000  0.000001  0.000001
> -+        '''
> -+        self.assert_traces_almost_equal(r1, stats)
> -+        self.assertEqual(len(stats), 4)
> -+
> -+        stats = yappi.get_func_stats(
> -+            filter_callback=lambda x: yappi.func_matches(x, [time.sleep])
> -+        )
> -+        self.assertEqual(len(stats), 1)
> -+        r1 = '''
> -+        time.sleep                            2      0.206804  0.220000  0.103402
> -+        '''
> -+        self.assert_traces_almost_equal(r1, stats)
> -+
> -+    def test_print_formatting(self):
> -+
> -+        def a():
> -+            pass
> -+
> -+        def b():
> -+            a()
> -+
> -+        func_cols = {
> -+            1: ("name", 48),
> -+            0: ("ncall", 5),
> -+            2: ("tsub", 8),
> -+        }
> -+        thread_cols = {
> -+            1: ("name", 48),
> -+            0: ("ttot", 8),
> -+        }
> -+
> -+        yappi.start()
> -+        a()
> -+        b()
> -+        yappi.stop()
> -+        fs = yappi.get_func_stats()
> -+        cs = fs[1].children
> -+        ts = yappi.get_thread_stats()
> -+        #fs.print_all(out=sys.stderr, columns={1:("name", 70), })
> -+        #cs.print_all(out=sys.stderr, columns=func_cols)
> -+        #ts.print_all(out=sys.stderr, columns=thread_cols)
> -+        #cs.print_all(out=sys.stderr, columns={})
> -+
> -+        self.assertRaises(
> -+            yappi.YappiError, fs.print_all, columns={1: ("namee", 9)}
> -+        )
> -+        self.assertRaises(
> -+            yappi.YappiError, cs.print_all, columns={1: ("dd", 0)}
> -+        )
> -+        self.assertRaises(
> -+            yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)}
> -+        )
> -+
> -+    def test_get_clock(self):
> -+        yappi.set_clock_type('cpu')
> -+        self.assertEqual('cpu', yappi.get_clock_type())
> -+        clock_info = yappi.get_clock_info()
> -+        self.assertTrue('api' in clock_info)
> -+        self.assertTrue('resolution' in clock_info)
> -+
> -+        yappi.set_clock_type('wall')
> -+        self.assertEqual('wall', yappi.get_clock_type())
> -+
> -+        t0 = yappi.get_clock_time()
> -+        time.sleep(0.1)
> -+        duration = yappi.get_clock_time() - t0
> -+        self.assertTrue(0.05 < duration < 0.3)
> -+
> -+    def test_profile_decorator(self):
> -+
> -+        def aggregate(func, stats):
> -+            fname = "tests/%s.profile" % (func.__name__)
> -+            try:
> -+                stats.add(fname)
> -+            except IOError:
> -+                pass
> -+            stats.save(fname)
> -+            raise Exception("messing around")
> -+
> -+        @yappi.profile(return_callback=aggregate)
> -+        def a(x, y):
> -+            if x + y == 25:
> -+                raise Exception("")
> -+            return x + y
> -+
> -+        def b():
> -+            pass
> -+
> -+        try:
> -+            os.remove(
> -+                "tests/a.profile"
> -+            )  # remove the one from prev test, if available
> -+        except:
> -+            pass
> -+
> -+        # global profile is on to mess things up
> -+        yappi.start()
> -+        b()
> -+
> -+        # assert functionality and call function at same time
> -+        try:
> -+            self.assertEqual(a(1, 2), 3)
> -+        except:
> -+            pass
> -+        try:
> -+            self.assertEqual(a(2, 5), 7)
> -+        except:
> -+            pass
> -+        try:
> -+            a(4, 21)
> -+        except:
> -+            pass
> -+        stats = yappi.get_func_stats().add("tests/a.profile")
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        self.assertEqual(fsa.ncall, 3)
> -+        self.assertEqual(len(stats), 1)  # b() should be cleared out.
> -+
> -+        @yappi.profile(return_callback=aggregate)
> -+        def count_down_rec(n):
> -+            if n == 0:
> -+                return
> -+            count_down_rec(n - 1)
> -+
> -+        try:
> -+            os.remove(
> -+                "tests/count_down_rec.profile"
> -+            )  # remove the one from prev test, if available
> -+        except:
> -+            pass
> -+
> -+        try:
> -+            count_down_rec(4)
> -+        except:
> -+            pass
> -+        try:
> -+            count_down_rec(3)
> -+        except:
> -+            pass
> -+
> -+        stats = yappi.YFuncStats("tests/count_down_rec.profile")
> -+        fsrec = utils.find_stat_by_name(stats, 'count_down_rec')
> -+        self.assertEqual(fsrec.ncall, 9)
> -+        self.assertEqual(fsrec.nactualcall, 2)
> -+
> -+    def test_strip_dirs(self):
> -+
> -+        def a():
> -+            pass
> -+
> -+        stats = utils.run_and_get_func_stats(a, )
> -+        stats.strip_dirs()
> -+        fsa = utils.find_stat_by_name(stats, "a")
> -+        self.assertEqual(fsa.module, os.path.basename(fsa.module))
> -+
> -+    @unittest.skipIf(os.name == "nt", "do not run on Windows")
> -+    def test_run_as_script(self):
> -+        import re
> -+        p = subprocess.Popen(
> -+            ['yappi', os.path.join('./tests', 'run_as_script.py')],
> -+            stdout=subprocess.PIPE
> -+        )
> -+        out, err = p.communicate()
> -+        self.assertEqual(p.returncode, 0)
> -+        func_stats, thread_stats = re.split(
> -+            b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out
> -+        )
> -+        self.assertTrue(b'FancyThread' in thread_stats)
> -+
> -+    def test_yappi_overhead(self):
> -+        LOOP_COUNT = 100000
> -+
> -+        def a():
> -+            pass
> -+
> -+        def b():
> -+            for i in range(LOOP_COUNT):
> -+                a()
> -+
> -+        t0 = time.time()
> -+        yappi.start()
> -+        b()
> -+        yappi.stop()
> -+        time_with_yappi = time.time() - t0
> -+        t0 = time.time()
> -+        b()
> -+        time_without_yappi = time.time() - t0
> -+        if time_without_yappi == 0:
> -+            time_without_yappi = 0.000001
> -+
> -+        # in latest v0.82, I calculated this as close to "7.0" in my machine.
> -+        # however, %83 of this overhead is coming from tickcount(). The other %17
> -+        # seems to have been evenly distributed to the internal bookkeeping
> -+        # structures/algorithms which seems acceptable. Note that our test only
> -+        # tests one function being profiled at-a-time in a short interval.
> -+        # profiling high number of functions in a small time
> -+        # is a different beast, (which is pretty unlikely in most applications)
> -+        # So as a conclusion: I cannot see any optimization window for Yappi that
> -+        # is worth implementing as we will only optimize %17 of the time.
> -+        sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \
> -+            (time_with_yappi / time_without_yappi))
> -+
> -+    def test_clear_stats_while_running(self):
> -+
> -+        def a():
> -+            pass
> -+
> -+        yappi.start()
> -+        a()
> -+        yappi.clear_stats()
> -+        a()
> -+        stats = yappi.get_func_stats()
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        self.assertEqual(fsa.ncall, 1)
> -+
> -+    def test_generator(self):
> -+
> -+        def _gen(n):
> -+            while (n > 0):
> -+                yield n
> -+                n -= 1
> -+
> -+        yappi.start()
> -+        for x in _gen(5):
> -+            pass
> -+        self.assertTrue(
> -+            yappi.convert2pstats(yappi.get_func_stats()) is not None
> -+        )
> -+
> -+    def test_slice_child_stats_and_strip_dirs(self):
> -+
> -+        def b():
> -+            for i in range(10000000):
> -+                pass
> -+
> -+        def a():
> -+            b()
> -+
> -+        yappi.start(builtins=True)
> -+        a()
> -+        stats = yappi.get_func_stats()
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        self.assertTrue(fsa.children[0:1] is not None)
> -+        prev_afullname = fsa.full_name
> -+        prev_bchildfullname = fsa.children[fsb].full_name
> -+        stats.strip_dirs()
> -+        self.assertTrue(len(prev_afullname) > len(fsa.full_name))
> -+        self.assertTrue(
> -+            len(prev_bchildfullname) > len(fsa.children[fsb].full_name)
> -+        )
> -+
> -+    def test_children_stat_functions(self):
> -+        _timings = {"a_1": 5, "b_1": 3, "c_1": 1}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        def b():
> -+            pass
> -+
> -+        def c():
> -+            pass
> -+
> -+        def a():
> -+            b()
> -+            c()
> -+
> -+        yappi.start()
> -+        a()
> -+        b()  # non-child call
> -+        c()  # non-child call
> -+        stats = yappi.get_func_stats()
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        childs_of_a = fsa.children.get().sort("tavg", "desc")
> -+        prev_item = None
> -+        for item in childs_of_a:
> -+            if prev_item:
> -+                self.assertTrue(prev_item.tavg > item.tavg)
> -+            prev_item = item
> -+        childs_of_a.sort("name", "desc")
> -+        prev_item = None
> -+        for item in childs_of_a:
> -+            if prev_item:
> -+                self.assertTrue(prev_item.name > item.name)
> -+            prev_item = item
> -+        childs_of_a.clear()
> -+        self.assertTrue(childs_of_a.empty())
> -+
> -+    def test_no_stats_different_clock_type_load(self):
> -+
> -+        def a():
> -+            pass
> -+
> -+        yappi.start()
> -+        a()
> -+        yappi.stop()
> -+        yappi.get_func_stats().save("tests/ystats1.ys")
> -+        yappi.clear_stats()
> -+        yappi.set_clock_type("WALL")
> -+        yappi.start()
> -+        yappi.stop()
> -+        stats = yappi.get_func_stats().add("tests/ystats1.ys")
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        self.assertTrue(fsa is not None)
> -+
> -+    def test_subsequent_profile(self):
> -+        _timings = {"a_1": 1, "b_1": 1}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        def a():
> -+            pass
> -+
> -+        def b():
> -+            pass
> -+
> -+        yappi.start()
> -+        a()
> -+        yappi.stop()
> -+        yappi.start()
> -+        b()
> -+        yappi.stop()
> -+        stats = yappi.get_func_stats()
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        self.assertTrue(fsa is not None)
> -+        self.assertTrue(fsb is not None)
> -+        self.assertEqual(fsa.ttot, 1)
> -+        self.assertEqual(fsb.ttot, 1)
> -+
> -+    def test_lambda(self):
> -+        f = lambda: time.sleep(0.3)
> -+        yappi.set_clock_type("wall")
> -+        yappi.start()
> -+        f()
> -+        stats = yappi.get_func_stats()
> -+        fsa = utils.find_stat_by_name(stats, '<lambda>')
> -+        self.assertTrue(fsa.ttot > 0.1)
> -+
> -+    def test_module_stress(self):
> -+        self.assertEqual(yappi.is_running(), False)
> -+
> -+        yappi.start()
> -+        yappi.clear_stats()
> -+        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
> -+
> -+        yappi.stop()
> -+        yappi.clear_stats()
> -+        yappi.set_clock_type("cpu")
> -+        self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy")
> -+        self.assertEqual(yappi.is_running(), False)
> -+        yappi.clear_stats()
> -+        yappi.clear_stats()
> -+
> -+    def test_stat_sorting(self):
> -+        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        self._ncall = 1
> -+
> -+        def a():
> -+            b()
> -+
> -+        def b():
> -+            if self._ncall == 2:
> -+                return
> -+            self._ncall += 1
> -+            a()
> -+
> -+        stats = utils.run_and_get_func_stats(a)
> -+        stats = stats.sort("totaltime", "desc")
> -+        prev_stat = None
> -+        for stat in stats:
> -+            if prev_stat:
> -+                self.assertTrue(prev_stat.ttot >= stat.ttot)
> -+            prev_stat = stat
> -+        stats = stats.sort("totaltime", "asc")
> -+        prev_stat = None
> -+        for stat in stats:
> -+            if prev_stat:
> -+                self.assertTrue(prev_stat.ttot <= stat.ttot)
> -+            prev_stat = stat
> -+        stats = stats.sort("avgtime", "asc")
> -+        prev_stat = None
> -+        for stat in stats:
> -+            if prev_stat:
> -+                self.assertTrue(prev_stat.tavg <= stat.tavg)
> -+            prev_stat = stat
> -+        stats = stats.sort("name", "asc")
> -+        prev_stat = None
> -+        for stat in stats:
> -+            if prev_stat:
> -+                self.assertTrue(prev_stat.name <= stat.name)
> -+            prev_stat = stat
> -+        stats = stats.sort("subtime", "asc")
> -+        prev_stat = None
> -+        for stat in stats:
> -+            if prev_stat:
> -+                self.assertTrue(prev_stat.tsub <= stat.tsub)
> -+            prev_stat = stat
> -+
> -+        self.assertRaises(
> -+            yappi.YappiError, stats.sort, "invalid_func_sorttype_arg"
> -+        )
> -+        self.assertRaises(
> -+            yappi.YappiError, stats.sort, "totaltime",
> -+            "invalid_func_sortorder_arg"
> -+        )
> -+
> -+    def test_start_flags(self):
> -+        self.assertEqual(_yappi._get_start_flags(), None)
> -+        yappi.start()
> -+
> -+        def a():
> -+            pass
> -+
> -+        a()
> -+        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
> -+        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
> -+        self.assertEqual(len(yappi.get_thread_stats()), 1)
> -+
> -+    def test_builtin_profiling(self):
> -+
> -+        def a():
> -+            time.sleep(0.4)  # is a builtin function
> -+
> -+        yappi.set_clock_type('wall')
> -+
> -+        yappi.start(builtins=True)
> -+        a()
> -+        stats = yappi.get_func_stats()
> -+        fsa = utils.find_stat_by_name(stats, 'sleep')
> -+        self.assertTrue(fsa is not None)
> -+        self.assertTrue(fsa.ttot > 0.3)
> -+        yappi.stop()
> -+        yappi.clear_stats()
> -+
> -+        def a():
> -+            pass
> -+
> -+        yappi.start()
> -+        t = threading.Thread(target=a)
> -+        t.start()
> -+        t.join()
> -+        stats = yappi.get_func_stats()
> -+
> -+    def test_singlethread_profiling(self):
> -+        yappi.set_clock_type('wall')
> -+
> -+        def a():
> -+            time.sleep(0.2)
> -+
> -+        class Worker1(threading.Thread):
> -+
> -+            def a(self):
> -+                time.sleep(0.3)
> -+
> -+            def run(self):
> -+                self.a()
> -+
> -+        yappi.start(profile_threads=False)
> -+
> -+        c = Worker1()
> -+        c.start()
> -+        c.join()
> -+        a()
> -+        stats = yappi.get_func_stats()
> -+        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
> -+        fsa2 = utils.find_stat_by_name(stats, 'a')
> -+        self.assertTrue(fsa1 is None)
> -+        self.assertTrue(fsa2 is not None)
> -+        self.assertTrue(fsa2.ttot > 0.1)
> -+
> -+    def test_run(self):
> -+
> -+        def profiled():
> -+            pass
> -+
> -+        yappi.clear_stats()
> -+        try:
> -+            with yappi.run():
> -+                profiled()
> -+            stats = yappi.get_func_stats()
> -+        finally:
> -+            yappi.clear_stats()
> -+
> -+        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
> -+
> -+    def test_run_recursive(self):
> -+
> -+        def profiled():
> -+            pass
> -+
> -+        def not_profiled():
> -+            pass
> -+
> -+        yappi.clear_stats()
> -+        try:
> -+            with yappi.run():
> -+                with yappi.run():
> -+                    profiled()
> -+                # Profiling stopped here
> -+                not_profiled()
> -+            stats = yappi.get_func_stats()
> -+        finally:
> -+            yappi.clear_stats()
> -+
> -+        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
> -+        self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled'))
> -+
> -+
> -+class StatSaveScenarios(utils.YappiUnitTestCase):
> -+
> -+    def test_pstats_conversion(self):
> -+
> -+        def pstat_id(fs):
> -+            return (fs.module, fs.lineno, fs.name)
> -+
> -+        def a():
> -+            d()
> -+
> -+        def b():
> -+            d()
> -+
> -+        def c():
> -+            pass
> -+
> -+        def d():
> -+            pass
> -+
> -+        _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2}
> -+        _yappi._set_test_timings(_timings)
> -+        stats = utils.run_and_get_func_stats(a, )
> -+        stats.strip_dirs()
> -+        stats.save("tests/a1.pstats", type="pstat")
> -+        fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a"))
> -+        fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d"))
> -+        yappi.clear_stats()
> -+        _yappi._set_test_timings(_timings)
> -+        stats = utils.run_and_get_func_stats(a, )
> -+        stats.strip_dirs()
> -+        stats.save("tests/a2.pstats", type="pstat")
> -+        yappi.clear_stats()
> -+        _yappi._set_test_timings(_timings)
> -+        stats = utils.run_and_get_func_stats(b, )
> -+        stats.strip_dirs()
> -+        stats.save("tests/b1.pstats", type="pstat")
> -+        fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b"))
> -+        yappi.clear_stats()
> -+        _yappi._set_test_timings(_timings)
> -+        stats = utils.run_and_get_func_stats(c, )
> -+        stats.strip_dirs()
> -+        stats.save("tests/c1.pstats", type="pstat")
> -+        fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c"))
> -+
> -+        # merge saved stats and check pstats values are correct
> -+        import pstats
> -+        p = pstats.Stats(
> -+            'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats',
> -+            'tests/c1.pstats'
> -+        )
> -+        p.strip_dirs()
> -+        # ct = ttot, tt = tsub
> -+        (cc, nc, tt, ct, callers) = p.stats[fsa_pid]
> -+        self.assertEqual(cc, nc, 2)
> -+        self.assertEqual(tt, 20)
> -+        self.assertEqual(ct, 24)
> -+        (cc, nc, tt, ct, callers) = p.stats[fsd_pid]
> -+        self.assertEqual(cc, nc, 3)
> -+        self.assertEqual(tt, 6)
> -+        self.assertEqual(ct, 6)
> -+        self.assertEqual(len(callers), 2)
> -+        (cc, nc, tt, ct) = callers[fsa_pid]
> -+        self.assertEqual(cc, nc, 2)
> -+        self.assertEqual(tt, 4)
> -+        self.assertEqual(ct, 4)
> -+        (cc, nc, tt, ct) = callers[fsb_pid]
> -+        self.assertEqual(cc, nc, 1)
> -+        self.assertEqual(tt, 2)
> -+        self.assertEqual(ct, 2)
> -+
> -+    def test_merge_stats(self):
> -+        _timings = {
> -+            "a_1": 15,
> -+            "b_1": 14,
> -+            "c_1": 12,
> -+            "d_1": 10,
> -+            "e_1": 9,
> -+            "f_1": 7,
> -+            "g_1": 6,
> -+            "h_1": 5,
> -+            "i_1": 1
> -+        }
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        def a():
> -+            b()
> -+
> -+        def b():
> -+            c()
> -+
> -+        def c():
> -+            d()
> -+
> -+        def d():
> -+            e()
> -+
> -+        def e():
> -+            f()
> -+
> -+        def f():
> -+            g()
> -+
> -+        def g():
> -+            h()
> -+
> -+        def h():
> -+            i()
> -+
> -+        def i():
> -+            pass
> -+
> -+        yappi.start()
> -+        a()
> -+        a()
> -+        yappi.stop()
> -+        stats = yappi.get_func_stats()
> -+        self.assertRaises(
> -+            NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE"
> -+        )
> -+        stats.save("tests/ystats2.ys")
> -+        yappi.clear_stats()
> -+        _yappi._set_test_timings(_timings)
> -+        yappi.start()
> -+        a()
> -+        stats = yappi.get_func_stats().add("tests/ystats2.ys")
> -+        fsa = utils.find_stat_by_name(stats, "a")
> -+        fsb = utils.find_stat_by_name(stats, "b")
> -+        fsc = utils.find_stat_by_name(stats, "c")
> -+        fsd = utils.find_stat_by_name(stats, "d")
> -+        fse = utils.find_stat_by_name(stats, "e")
> -+        fsf = utils.find_stat_by_name(stats, "f")
> -+        fsg = utils.find_stat_by_name(stats, "g")
> -+        fsh = utils.find_stat_by_name(stats, "h")
> -+        fsi = utils.find_stat_by_name(stats, "i")
> -+        self.assertEqual(fsa.ttot, 45)
> -+        self.assertEqual(fsa.ncall, 3)
> -+        self.assertEqual(fsa.nactualcall, 3)
> -+        self.assertEqual(fsa.tsub, 3)
> -+        self.assertEqual(fsa.children[fsb].ttot, fsb.ttot)
> -+        self.assertEqual(fsa.children[fsb].tsub, fsb.tsub)
> -+        self.assertEqual(fsb.children[fsc].ttot, fsc.ttot)
> -+        self.assertEqual(fsb.children[fsc].tsub, fsc.tsub)
> -+        self.assertEqual(fsc.tsub, 6)
> -+        self.assertEqual(fsc.children[fsd].ttot, fsd.ttot)
> -+        self.assertEqual(fsc.children[fsd].tsub, fsd.tsub)
> -+        self.assertEqual(fsd.children[fse].ttot, fse.ttot)
> -+        self.assertEqual(fsd.children[fse].tsub, fse.tsub)
> -+        self.assertEqual(fse.children[fsf].ttot, fsf.ttot)
> -+        self.assertEqual(fse.children[fsf].tsub, fsf.tsub)
> -+        self.assertEqual(fsf.children[fsg].ttot, fsg.ttot)
> -+        self.assertEqual(fsf.children[fsg].tsub, fsg.tsub)
> -+        self.assertEqual(fsg.ttot, 18)
> -+        self.assertEqual(fsg.tsub, 3)
> -+        self.assertEqual(fsg.children[fsh].ttot, fsh.ttot)
> -+        self.assertEqual(fsg.children[fsh].tsub, fsh.tsub)
> -+        self.assertEqual(fsh.ttot, 15)
> -+        self.assertEqual(fsh.tsub, 12)
> -+        self.assertEqual(fsh.tavg, 5)
> -+        self.assertEqual(fsh.children[fsi].ttot, fsi.ttot)
> -+        self.assertEqual(fsh.children[fsi].tsub, fsi.tsub)
> -+        #stats.debug_print()
> -+
> -+    def test_merge_multithreaded_stats(self):
> -+        import _yappi
> -+        timings = {"a_1": 2, "b_1": 1}
> -+        _yappi._set_test_timings(timings)
> -+
> -+        def a():
> -+            pass
> -+
> -+        def b():
> -+            pass
> -+
> -+        yappi.start()
> -+        t = threading.Thread(target=a)
> -+        t.start()
> -+        t.join()
> -+        t = threading.Thread(target=b)
> -+        t.start()
> -+        t.join()
> -+        yappi.get_func_stats().save("tests/ystats1.ys")
> -+        yappi.clear_stats()
> -+        _yappi._set_test_timings(timings)
> -+        self.assertEqual(len(yappi.get_func_stats()), 0)
> -+        self.assertEqual(len(yappi.get_thread_stats()), 1)
> -+        t = threading.Thread(target=a)
> -+        t.start()
> -+        t.join()
> -+
> -+        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
> -+        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
> -+        yappi.get_func_stats().save("tests/ystats2.ys")
> -+
> -+        stats = yappi.YFuncStats([
> -+            "tests/ystats1.ys",
> -+            "tests/ystats2.ys",
> -+        ])
> -+        fsa = utils.find_stat_by_name(stats, "a")
> -+        fsb = utils.find_stat_by_name(stats, "b")
> -+        self.assertEqual(fsa.ncall, 2)
> -+        self.assertEqual(fsb.ncall, 1)
> -+        self.assertEqual(fsa.tsub, fsa.ttot, 4)
> -+        self.assertEqual(fsb.tsub, fsb.ttot, 1)
> -+
> -+    def test_merge_load_different_clock_types(self):
> -+        yappi.start(builtins=True)
> -+
> -+        def a():
> -+            b()
> -+
> -+        def b():
> -+            c()
> -+
> -+        def c():
> -+            pass
> -+
> -+        t = threading.Thread(target=a)
> -+        t.start()
> -+        t.join()
> -+        yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys")
> -+        yappi.stop()
> -+        yappi.clear_stats()
> -+        yappi.start(builtins=False)
> -+        t = threading.Thread(target=a)
> -+        t.start()
> -+        t.join()
> -+        yappi.get_func_stats().save("tests/ystats2.ys")
> -+        yappi.stop()
> -+        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
> -+        yappi.clear_stats()
> -+        yappi.set_clock_type("wall")
> -+        yappi.start()
> -+        t = threading.Thread(target=a)
> -+        t.start()
> -+        t.join()
> -+        yappi.get_func_stats().save("tests/ystats3.ys")
> -+        self.assertRaises(
> -+            yappi.YappiError,
> -+            yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys"
> -+        )
> -+        stats = yappi.YFuncStats(["tests/ystats1.ys",
> -+                                  "tests/ystats2.ys"]).sort("name")
> -+        fsa = utils.find_stat_by_name(stats, "a")
> -+        fsb = utils.find_stat_by_name(stats, "b")
> -+        fsc = utils.find_stat_by_name(stats, "c")
> -+        self.assertEqual(fsa.ncall, 2)
> -+        self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall)
> -+
> -+    def test_merge_aabab_aabbc(self):
> -+        _timings = {
> -+            "a_1": 15,
> -+            "a_2": 14,
> -+            "b_1": 12,
> -+            "a_3": 10,
> -+            "b_2": 9,
> -+            "c_1": 4
> -+        }
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        def a():
> -+            if self._ncall == 1:
> -+                self._ncall += 1
> -+                a()
> -+            elif self._ncall == 5:
> -+                self._ncall += 1
> -+                a()
> -+            else:
> -+                b()
> -+
> -+        def b():
> -+            if self._ncall == 2:
> -+                self._ncall += 1
> -+                a()
> -+            elif self._ncall == 6:
> -+                self._ncall += 1
> -+                b()
> -+            elif self._ncall == 7:
> -+                c()
> -+            else:
> -+                return
> -+
> -+        def c():
> -+            pass
> -+
> -+        self._ncall = 1
> -+        stats = utils.run_and_get_func_stats(a, )
> -+        stats.save("tests/ystats1.ys")
> -+        yappi.clear_stats()
> -+        _yappi._set_test_timings(_timings)
> -+        #stats.print_all()
> -+
> -+        self._ncall = 5
> -+        stats = utils.run_and_get_func_stats(a, )
> -+        stats.save("tests/ystats2.ys")
> -+
> -+        #stats.print_all()
> -+
> -+        def a():  # same name but another function(code object)
> -+            pass
> -+
> -+        yappi.start()
> -+        a()
> -+        stats = yappi.get_func_stats().add(
> -+            ["tests/ystats1.ys", "tests/ystats2.ys"]
> -+        )
> -+        #stats.print_all()
> -+        self.assertEqual(len(stats), 4)
> -+
> -+        fsa = None
> -+        for stat in stats:
> -+            if stat.name == "a" and stat.ttot == 45:
> -+                fsa = stat
> -+                break
> -+        self.assertTrue(fsa is not None)
> -+
> -+        self.assertEqual(fsa.ncall, 7)
> -+        self.assertEqual(fsa.nactualcall, 3)
> -+        self.assertEqual(fsa.ttot, 45)
> -+        self.assertEqual(fsa.tsub, 10)
> -+        fsb = utils.find_stat_by_name(stats, "b")
> -+        fsc = utils.find_stat_by_name(stats, "c")
> -+        self.assertEqual(fsb.ncall, 6)
> -+        self.assertEqual(fsb.nactualcall, 3)
> -+        self.assertEqual(fsb.ttot, 36)
> -+        self.assertEqual(fsb.tsub, 27)
> -+        self.assertEqual(fsb.tavg, 6)
> -+        self.assertEqual(fsc.ttot, 8)
> -+        self.assertEqual(fsc.tsub, 8)
> -+        self.assertEqual(fsc.tavg, 4)
> -+        self.assertEqual(fsc.nactualcall, fsc.ncall, 2)
> -+
> -+
> -+class MultithreadedScenarios(utils.YappiUnitTestCase):
> -+
> -+    def test_issue_32(self):
> -+        '''
> -+        Start yappi from different thread and we get Internal Error(15) as
> -+        the current_ctx_id() called while enumerating the threads in start()
> -+        and as it does not swap to the enumerated ThreadState* the THreadState_GetDict()
> -+        returns wrong object and thus sets an invalid id for the _ctx structure.
> -+
> -+        When this issue happens multiple Threads have same tid as the internal ts_ptr
> -+        will be same for different contexts. So, let's see if that happens
> -+        '''
> -+
> -+        def foo():
> -+            time.sleep(0.2)
> -+
> -+        def bar():
> -+            time.sleep(0.1)
> -+
> -+        def thread_func():
> -+            yappi.set_clock_type("wall")
> -+            yappi.start()
> -+
> -+            bar()
> -+
> -+        t = threading.Thread(target=thread_func)
> -+        t.start()
> -+        t.join()
> -+
> -+        foo()
> -+
> -+        yappi.stop()
> -+
> -+        thread_ids = set()
> -+        for tstat in yappi.get_thread_stats():
> -+            self.assertTrue(tstat.tid not in thread_ids)
> -+            thread_ids.add(tstat.tid)
> -+
> -+    def test_subsequent_profile(self):
> -+        WORKER_COUNT = 5
> -+
> -+        def a():
> -+            pass
> -+
> -+        def b():
> -+            pass
> -+
> -+        def c():
> -+            pass
> -+
> -+        _timings = {
> -+            "a_1": 3,
> -+            "b_1": 2,
> -+            "c_1": 1,
> -+        }
> -+
> -+        yappi.start()
> -+
> -+        def g():
> -+            pass
> -+
> -+        g()
> -+        yappi.stop()
> -+        yappi.clear_stats()
> -+        _yappi._set_test_timings(_timings)
> -+        yappi.start()
> -+
> -+        _dummy = []
> -+        for i in range(WORKER_COUNT):
> -+            t = threading.Thread(target=a)
> -+            t.start()
> -+            t.join()
> -+        for i in range(WORKER_COUNT):
> -+            t = threading.Thread(target=b)
> -+            t.start()
> -+            _dummy.append(t)
> -+            t.join()
> -+        for i in range(WORKER_COUNT):
> -+            t = threading.Thread(target=a)
> -+            t.start()
> -+            t.join()
> -+        for i in range(WORKER_COUNT):
> -+            t = threading.Thread(target=c)
> -+            t.start()
> -+            t.join()
> -+        yappi.stop()
> -+        yappi.start()
> -+
> -+        def f():
> -+            pass
> -+
> -+        f()
> -+        stats = yappi.get_func_stats()
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        fsc = utils.find_stat_by_name(stats, 'c')
> -+        self.assertEqual(fsa.ncall, 10)
> -+        self.assertEqual(fsb.ncall, 5)
> -+        self.assertEqual(fsc.ncall, 5)
> -+        self.assertEqual(fsa.ttot, fsa.tsub, 30)
> -+        self.assertEqual(fsb.ttot, fsb.tsub, 10)
> -+        self.assertEqual(fsc.ttot, fsc.tsub, 5)
> -+
> -+        # MACOSx optimizes by only creating one worker thread
> -+        self.assertTrue(len(yappi.get_thread_stats()) >= 2)
> -+
> -+    def test_basic(self):
> -+        yappi.set_clock_type('wall')
> -+
> -+        def dummy():
> -+            pass
> -+
> -+        def a():
> -+            time.sleep(0.2)
> -+
> -+        class Worker1(threading.Thread):
> -+
> -+            def a(self):
> -+                time.sleep(0.3)
> -+
> -+            def run(self):
> -+                self.a()
> -+
> -+        yappi.start(builtins=False, profile_threads=True)
> -+
> -+        c = Worker1()
> -+        c.start()
> -+        c.join()
> -+        a()
> -+        stats = yappi.get_func_stats()
> -+        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
> -+        fsa2 = utils.find_stat_by_name(stats, 'a')
> -+        self.assertTrue(fsa1 is not None)
> -+        self.assertTrue(fsa2 is not None)
> -+        self.assertTrue(fsa1.ttot > 0.2)
> -+        self.assertTrue(fsa2.ttot > 0.1)
> -+        tstats = yappi.get_thread_stats()
> -+        self.assertEqual(len(tstats), 2)
> -+        tsa = utils.find_stat_by_name(tstats, 'Worker1')
> -+        tsm = utils.find_stat_by_name(tstats, '_MainThread')
> -+        dummy()  # call dummy to force ctx name to be retrieved again.
> -+        self.assertTrue(tsa is not None)
> -+        # TODO: I put dummy() to fix below, remove the comments after a while.
> -+        self.assertTrue( # FIX: I see this fails sometimes?
> -+            tsm is not None,
> -+            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(tstats))))
> -+
> -+    def test_ctx_stats(self):
> -+        from threading import Thread
> -+        DUMMY_WORKER_COUNT = 5
> -+        yappi.start()
> -+
> -+        class DummyThread(Thread):
> -+            pass
> -+
> -+        def dummy():
> -+            pass
> -+
> -+        def dummy_worker():
> -+            pass
> -+
> -+        for i in range(DUMMY_WORKER_COUNT):
> -+            t = DummyThread(target=dummy_worker)
> -+            t.start()
> -+            t.join()
> -+        yappi.stop()
> -+        stats = yappi.get_thread_stats()
> -+        tsa = utils.find_stat_by_name(stats, "DummyThread")
> -+        self.assertTrue(tsa is not None)
> -+        yappi.clear_stats()
> -+        time.sleep(1.0)
> -+        _timings = {
> -+            "a_1": 6,
> -+            "b_1": 5,
> -+            "c_1": 3,
> -+            "d_1": 1,
> -+            "a_2": 4,
> -+            "b_2": 3,
> -+            "c_2": 2,
> -+            "d_2": 1
> -+        }
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        class Thread1(Thread):
> -+            pass
> -+
> -+        class Thread2(Thread):
> -+            pass
> -+
> -+        def a():
> -+            b()
> -+
> -+        def b():
> -+            c()
> -+
> -+        def c():
> -+            d()
> -+
> -+        def d():
> -+            time.sleep(0.6)
> -+
> -+        yappi.set_clock_type("wall")
> -+        yappi.start()
> -+        t1 = Thread1(target=a)
> -+        t1.start()
> -+        t2 = Thread2(target=a)
> -+        t2.start()
> -+        t1.join()
> -+        t2.join()
> -+        stats = yappi.get_thread_stats()
> -+
> -+        # the fist clear_stats clears the context table?
> -+        tsa = utils.find_stat_by_name(stats, "DummyThread")
> -+        self.assertTrue(tsa is None)
> -+
> -+        tst1 = utils.find_stat_by_name(stats, "Thread1")
> -+        tst2 = utils.find_stat_by_name(stats, "Thread2")
> -+        tsmain = utils.find_stat_by_name(stats, "_MainThread")
> -+        dummy()  # call dummy to force ctx name to be retrieved again.
> -+        self.assertTrue(len(stats) == 3)
> -+        self.assertTrue(tst1 is not None)
> -+        self.assertTrue(tst2 is not None)
> -+        # TODO: I put dummy() to fix below, remove the comments after a while.
> -+        self.assertTrue( # FIX: I see this fails sometimes
> -+            tsmain is not None,
> -+            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(stats))))
> -+        self.assertTrue(1.0 > tst2.ttot >= 0.5)
> -+        self.assertTrue(1.0 > tst1.ttot >= 0.5)
> -+
> -+        # test sorting of the ctx stats
> -+        stats = stats.sort("totaltime", "desc")
> -+        prev_stat = None
> -+        for stat in stats:
> -+            if prev_stat:
> -+                self.assertTrue(prev_stat.ttot >= stat.ttot)
> -+            prev_stat = stat
> -+        stats = stats.sort("totaltime", "asc")
> -+        prev_stat = None
> -+        for stat in stats:
> -+            if prev_stat:
> -+                self.assertTrue(prev_stat.ttot <= stat.ttot)
> -+            prev_stat = stat
> -+        stats = stats.sort("schedcount", "desc")
> -+        prev_stat = None
> -+        for stat in stats:
> -+            if prev_stat:
> -+                self.assertTrue(prev_stat.sched_count >= stat.sched_count)
> -+            prev_stat = stat
> -+        stats = stats.sort("name", "desc")
> -+        prev_stat = None
> -+        for stat in stats:
> -+            if prev_stat:
> -+                self.assertTrue(prev_stat.name.lower() >= stat.name.lower())
> -+            prev_stat = stat
> -+        self.assertRaises(
> -+            yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg"
> -+        )
> -+        self.assertRaises(
> -+            yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg"
> -+        )
> -+
> -+    def test_ctx_stats_cpu(self):
> -+
> -+        def get_thread_name():
> -+            try:
> -+                return threading.current_thread().name
> -+            except AttributeError:
> -+                return "Anonymous"
> -+
> -+        def burn_cpu(sec):
> -+            t0 = yappi.get_clock_time()
> -+            elapsed = 0
> -+            while (elapsed < sec):
> -+                for _ in range(1000):
> -+                    pass
> -+                elapsed = yappi.get_clock_time() - t0
> -+
> -+        def test():
> -+
> -+            ts = []
> -+            for i in (0.01, 0.05, 0.1):
> -+                t = threading.Thread(target=burn_cpu, args=(i, ))
> -+                t.name = "burn_cpu-%s" % str(i)
> -+                t.start()
> -+                ts.append(t)
> -+            for t in ts:
> -+                t.join()
> -+
> -+        yappi.set_clock_type("cpu")
> -+        yappi.set_context_name_callback(get_thread_name)
> -+
> -+        yappi.start()
> -+
> -+        test()
> -+
> -+        yappi.stop()
> -+
> -+        tstats = yappi.get_thread_stats()
> -+        r1 = '''
> -+        burn_cpu-0.1      3      123145356058624  0.100105  8
> -+        burn_cpu-0.05     2      123145361313792  0.050149  8
> -+        burn_cpu-0.01     1      123145356058624  0.010127  2
> -+        MainThread        0      4321620864       0.001632  6
> -+        '''
> -+        self.assert_ctx_stats_almost_equal(r1, tstats)
> -+
> -+    def test_producer_consumer_with_queues(self):
> -+        # we currently just stress yappi, no functionality test is done here.
> -+        yappi.start()
> -+        if utils.is_py3x():
> -+            from queue import Queue
> -+        else:
> -+            from Queue import Queue
> -+        from threading import Thread
> -+        WORKER_THREAD_COUNT = 50
> -+        WORK_ITEM_COUNT = 2000
> -+
> -+        def worker():
> -+            while True:
> -+                item = q.get()
> -+                # do the work with item
> -+                q.task_done()
> -+
> -+        q = Queue()
> -+        for i in range(WORKER_THREAD_COUNT):
> -+            t = Thread(target=worker)
> -+            t.daemon = True
> -+            t.start()
> -+
> -+        for item in range(WORK_ITEM_COUNT):
> -+            q.put(item)
> -+        q.join()  # block until all tasks are done
> -+        #yappi.get_func_stats().sort("callcount").print_all()
> -+        yappi.stop()
> -+
> -+    def test_temporary_lock_waiting(self):
> -+        yappi.start()
> -+        _lock = threading.Lock()
> -+
> -+        def worker():
> -+            _lock.acquire()
> -+            try:
> -+                time.sleep(1.0)
> -+            finally:
> -+                _lock.release()
> -+
> -+        t1 = threading.Thread(target=worker)
> -+        t2 = threading.Thread(target=worker)
> -+        t1.start()
> -+        t2.start()
> -+        t1.join()
> -+        t2.join()
> -+        #yappi.get_func_stats().sort("callcount").print_all()
> -+        yappi.stop()
> -+
> -+    @unittest.skipIf(os.name != "posix", "requires Posix compliant OS")
> -+    def test_signals_with_blocking_calls(self):
> -+        import signal, os, time
> -+
> -+        # just to verify if signal is handled correctly and stats/yappi are not corrupted.
> -+        def handler(signum, frame):
> -+            raise Exception("Signal handler executed!")
> -+
> -+        yappi.start()
> -+        signal.signal(signal.SIGALRM, handler)
> -+        signal.alarm(1)
> -+        self.assertRaises(Exception, time.sleep, 2)
> -+        stats = yappi.get_func_stats()
> -+        fsh = utils.find_stat_by_name(stats, "handler")
> -+        self.assertTrue(fsh is not None)
> -+
> -+    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
> -+    def test_concurrent_futures(self):
> -+        yappi.start()
> -+        from concurrent.futures import ThreadPoolExecutor
> -+        with ThreadPoolExecutor(max_workers=5) as executor:
> -+            f = executor.submit(pow, 5, 2)
> -+            self.assertEqual(f.result(), 25)
> -+        time.sleep(1.0)
> -+        yappi.stop()
> -+
> -+    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
> -+    def test_barrier(self):
> -+        yappi.start()
> -+        b = threading.Barrier(2, timeout=1)
> -+
> -+        def worker():
> -+            try:
> -+                b.wait()
> -+            except threading.BrokenBarrierError:
> -+                pass
> -+            except Exception:
> -+                raise Exception("BrokenBarrierError not raised")
> -+
> -+        t1 = threading.Thread(target=worker)
> -+        t1.start()
> -+        #b.wait()
> -+        t1.join()
> -+        yappi.stop()
> -+
> -+
> -+class NonRecursiveFunctions(utils.YappiUnitTestCase):
> -+
> -+    def test_abcd(self):
> -+        _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        def a():
> -+            b()
> -+
> -+        def b():
> -+            c()
> -+
> -+        def c():
> -+            d()
> -+
> -+        def d():
> -+            pass
> -+
> -+        stats = utils.run_and_get_func_stats(a)
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        fsc = utils.find_stat_by_name(stats, 'c')
> -+        fsd = utils.find_stat_by_name(stats, 'd')
> -+        cfsab = fsa.children[fsb]
> -+        cfsbc = fsb.children[fsc]
> -+        cfscd = fsc.children[fsd]
> -+
> -+        self.assertEqual(fsa.ttot, 6)
> -+        self.assertEqual(fsa.tsub, 1)
> -+        self.assertEqual(fsb.ttot, 5)
> -+        self.assertEqual(fsb.tsub, 2)
> -+        self.assertEqual(fsc.ttot, 3)
> -+        self.assertEqual(fsc.tsub, 2)
> -+        self.assertEqual(fsd.ttot, 1)
> -+        self.assertEqual(fsd.tsub, 1)
> -+        self.assertEqual(cfsab.ttot, 5)
> -+        self.assertEqual(cfsab.tsub, 2)
> -+        self.assertEqual(cfsbc.ttot, 3)
> -+        self.assertEqual(cfsbc.tsub, 2)
> -+        self.assertEqual(cfscd.ttot, 1)
> -+        self.assertEqual(cfscd.tsub, 1)
> -+
> -+    def test_stop_in_middle(self):
> -+        _timings = {"a_1": 6, "b_1": 4}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        def a():
> -+            b()
> -+            yappi.stop()
> -+
> -+        def b():
> -+            time.sleep(0.2)
> -+
> -+        yappi.start()
> -+        a()
> -+        stats = yappi.get_func_stats()
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+
> -+        self.assertEqual(fsa.ncall, 1)
> -+        self.assertEqual(fsa.nactualcall, 0)
> -+        self.assertEqual(fsa.ttot, 0)  # no call_leave called
> -+        self.assertEqual(fsa.tsub, 0)  # no call_leave called
> -+        self.assertEqual(fsb.ttot, 4)
> -+
> -+
> -+class RecursiveFunctions(utils.YappiUnitTestCase):
> -+
> -+    def test_fibonacci(self):
> -+
> -+        def fib(n):
> -+            if n > 1:
> -+                return fib(n - 1) + fib(n - 2)
> -+            else:
> -+                return n
> -+
> -+        stats = utils.run_and_get_func_stats(fib, 22)
> -+        fs = utils.find_stat_by_name(stats, 'fib')
> -+        self.assertEqual(fs.ncall, 57313)
> -+        self.assertEqual(fs.ttot, fs.tsub)
> -+
> -+    def test_abcadc(self):
> -+        _timings = {
> -+            "a_1": 20,
> -+            "b_1": 19,
> -+            "c_1": 17,
> -+            "a_2": 13,
> -+            "d_1": 12,
> -+            "c_2": 10,
> -+            "a_3": 5
> -+        }
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        def a(n):
> -+            if n == 3:
> -+                return
> -+            if n == 1 + 1:
> -+                d(n)
> -+            else:
> -+                b(n)
> -+
> -+        def b(n):
> -+            c(n)
> -+
> -+        def c(n):
> -+            a(n + 1)
> -+
> -+        def d(n):
> -+            c(n)
> -+
> -+        stats = utils.run_and_get_func_stats(a, 1)
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        fsc = utils.find_stat_by_name(stats, 'c')
> -+        fsd = utils.find_stat_by_name(stats, 'd')
> -+        self.assertEqual(fsa.ncall, 3)
> -+        self.assertEqual(fsa.nactualcall, 1)
> -+        self.assertEqual(fsa.ttot, 20)
> -+        self.assertEqual(fsa.tsub, 7)
> -+        self.assertEqual(fsb.ttot, 19)
> -+        self.assertEqual(fsb.tsub, 2)
> -+        self.assertEqual(fsc.ttot, 17)
> -+        self.assertEqual(fsc.tsub, 9)
> -+        self.assertEqual(fsd.ttot, 12)
> -+        self.assertEqual(fsd.tsub, 2)
> -+        cfsca = fsc.children[fsa]
> -+        self.assertEqual(cfsca.nactualcall, 0)
> -+        self.assertEqual(cfsca.ncall, 2)
> -+        self.assertEqual(cfsca.ttot, 13)
> -+        self.assertEqual(cfsca.tsub, 6)
> -+
> -+    def test_aaaa(self):
> -+        _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        def d(n):
> -+            if n == 3:
> -+                return
> -+            d(n + 1)
> -+
> -+        stats = utils.run_and_get_func_stats(d, 0)
> -+        fsd = utils.find_stat_by_name(stats, 'd')
> -+        self.assertEqual(fsd.ncall, 4)
> -+        self.assertEqual(fsd.nactualcall, 1)
> -+        self.assertEqual(fsd.ttot, 9)
> -+        self.assertEqual(fsd.tsub, 9)
> -+        cfsdd = fsd.children[fsd]
> -+        self.assertEqual(cfsdd.ttot, 7)
> -+        self.assertEqual(cfsdd.tsub, 7)
> -+        self.assertEqual(cfsdd.ncall, 3)
> -+        self.assertEqual(cfsdd.nactualcall, 0)
> -+
> -+    def test_abcabc(self):
> -+        _timings = {
> -+            "a_1": 20,
> -+            "b_1": 19,
> -+            "c_1": 17,
> -+            "a_2": 13,
> -+            "b_2": 11,
> -+            "c_2": 9,
> -+            "a_3": 6
> -+        }
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        def a(n):
> -+            if n == 3:
> -+                return
> -+            else:
> -+                b(n)
> -+
> -+        def b(n):
> -+            c(n)
> -+
> -+        def c(n):
> -+            a(n + 1)
> -+
> -+        stats = utils.run_and_get_func_stats(a, 1)
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        fsc = utils.find_stat_by_name(stats, 'c')
> -+        self.assertEqual(fsa.ncall, 3)
> -+        self.assertEqual(fsa.nactualcall, 1)
> -+        self.assertEqual(fsa.ttot, 20)
> -+        self.assertEqual(fsa.tsub, 9)
> -+        self.assertEqual(fsb.ttot, 19)
> -+        self.assertEqual(fsb.tsub, 4)
> -+        self.assertEqual(fsc.ttot, 17)
> -+        self.assertEqual(fsc.tsub, 7)
> -+        cfsab = fsa.children[fsb]
> -+        cfsbc = fsb.children[fsc]
> -+        cfsca = fsc.children[fsa]
> -+        self.assertEqual(cfsab.ttot, 19)
> -+        self.assertEqual(cfsab.tsub, 4)
> -+        self.assertEqual(cfsbc.ttot, 17)
> -+        self.assertEqual(cfsbc.tsub, 7)
> -+        self.assertEqual(cfsca.ttot, 13)
> -+        self.assertEqual(cfsca.tsub, 8)
> -+
> -+    def test_abcbca(self):
> -+        _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1}
> -+        _yappi._set_test_timings(_timings)
> -+        self._ncall = 1
> -+
> -+        def a():
> -+            if self._ncall == 1:
> -+                b()
> -+            else:
> -+                return
> -+
> -+        def b():
> -+            c()
> -+
> -+        def c():
> -+            if self._ncall == 1:
> -+                self._ncall += 1
> -+                b()
> -+            else:
> -+                a()
> -+
> -+        stats = utils.run_and_get_func_stats(a)
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        fsc = utils.find_stat_by_name(stats, 'c')
> -+        cfsab = fsa.children[fsb]
> -+        cfsbc = fsb.children[fsc]
> -+        cfsca = fsc.children[fsa]
> -+        self.assertEqual(fsa.ttot, 10)
> -+        self.assertEqual(fsa.tsub, 2)
> -+        self.assertEqual(fsb.ttot, 9)
> -+        self.assertEqual(fsb.tsub, 4)
> -+        self.assertEqual(fsc.ttot, 7)
> -+        self.assertEqual(fsc.tsub, 4)
> -+        self.assertEqual(cfsab.ttot, 9)
> -+        self.assertEqual(cfsab.tsub, 2)
> -+        self.assertEqual(cfsbc.ttot, 7)
> -+        self.assertEqual(cfsbc.tsub, 4)
> -+        self.assertEqual(cfsca.ttot, 1)
> -+        self.assertEqual(cfsca.tsub, 1)
> -+        self.assertEqual(cfsca.ncall, 1)
> -+        self.assertEqual(cfsca.nactualcall, 0)
> -+
> -+    def test_aabccb(self):
> -+        _timings = {
> -+            "a_1": 13,
> -+            "a_2": 11,
> -+            "b_1": 9,
> -+            "c_1": 5,
> -+            "c_2": 3,
> -+            "b_2": 1
> -+        }
> -+        _yappi._set_test_timings(_timings)
> -+        self._ncall = 1
> -+
> -+        def a():
> -+            if self._ncall == 1:
> -+                self._ncall += 1
> -+                a()
> -+            else:
> -+                b()
> -+
> -+        def b():
> -+            if self._ncall == 3:
> -+                return
> -+            else:
> -+                c()
> -+
> -+        def c():
> -+            if self._ncall == 2:
> -+                self._ncall += 1
> -+                c()
> -+            else:
> -+                b()
> -+
> -+        stats = utils.run_and_get_func_stats(a)
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        fsc = utils.find_stat_by_name(stats, 'c')
> -+        cfsaa = fsa.children[fsa.index]
> -+        cfsab = fsa.children[fsb]
> -+        cfsbc = fsb.children[fsc.full_name]
> -+        cfscc = fsc.children[fsc]
> -+        cfscb = fsc.children[fsb]
> -+        self.assertEqual(fsb.ttot, 9)
> -+        self.assertEqual(fsb.tsub, 5)
> -+        self.assertEqual(cfsbc.ttot, 5)
> -+        self.assertEqual(cfsbc.tsub, 2)
> -+        self.assertEqual(fsa.ttot, 13)
> -+        self.assertEqual(fsa.tsub, 4)
> -+        self.assertEqual(cfsab.ttot, 9)
> -+        self.assertEqual(cfsab.tsub, 4)
> -+        self.assertEqual(cfsaa.ttot, 11)
> -+        self.assertEqual(cfsaa.tsub, 2)
> -+        self.assertEqual(fsc.ttot, 5)
> -+        self.assertEqual(fsc.tsub, 4)
> -+
> -+    def test_abaa(self):
> -+        _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        self._ncall = 1
> -+
> -+        def a():
> -+            if self._ncall == 1:
> -+                b()
> -+            elif self._ncall == 2:
> -+                self._ncall += 1
> -+                a()
> -+            else:
> -+                return
> -+
> -+        def b():
> -+            self._ncall += 1
> -+            a()
> -+
> -+        stats = utils.run_and_get_func_stats(a)
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        cfsaa = fsa.children[fsa]
> -+        cfsba = fsb.children[fsa]
> -+        self.assertEqual(fsb.ttot, 10)
> -+        self.assertEqual(fsb.tsub, 1)
> -+        self.assertEqual(fsa.ttot, 13)
> -+        self.assertEqual(fsa.tsub, 12)
> -+        self.assertEqual(cfsaa.ttot, 5)
> -+        self.assertEqual(cfsaa.tsub, 5)
> -+        self.assertEqual(cfsba.ttot, 9)
> -+        self.assertEqual(cfsba.tsub, 4)
> -+
> -+    def test_aabb(self):
> -+        _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        self._ncall = 1
> -+
> -+        def a():
> -+            if self._ncall == 1:
> -+                self._ncall += 1
> -+                a()
> -+            elif self._ncall == 2:
> -+                b()
> -+            else:
> -+                return
> -+
> -+        def b():
> -+            if self._ncall == 2:
> -+                self._ncall += 1
> -+                b()
> -+            else:
> -+                return
> -+
> -+        stats = utils.run_and_get_func_stats(a)
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        cfsaa = fsa.children[fsa]
> -+        cfsab = fsa.children[fsb]
> -+        cfsbb = fsb.children[fsb]
> -+        self.assertEqual(fsa.ttot, 13)
> -+        self.assertEqual(fsa.tsub, 4)
> -+        self.assertEqual(fsb.ttot, 9)
> -+        self.assertEqual(fsb.tsub, 9)
> -+        self.assertEqual(cfsaa.ttot, 10)
> -+        self.assertEqual(cfsaa.tsub, 1)
> -+        self.assertEqual(cfsab.ttot, 9)
> -+        self.assertEqual(cfsab.tsub, 4)
> -+        self.assertEqual(cfsbb.ttot, 5)
> -+        self.assertEqual(cfsbb.tsub, 5)
> -+
> -+    def test_abbb(self):
> -+        _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        self._ncall = 1
> -+
> -+        def a():
> -+            if self._ncall == 1:
> -+                b()
> -+
> -+        def b():
> -+            if self._ncall == 3:
> -+                return
> -+            self._ncall += 1
> -+            b()
> -+
> -+        stats = utils.run_and_get_func_stats(a)
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        cfsab = fsa.children[fsb]
> -+        cfsbb = fsb.children[fsb]
> -+        self.assertEqual(fsa.ttot, 13)
> -+        self.assertEqual(fsa.tsub, 3)
> -+        self.assertEqual(fsb.ttot, 10)
> -+        self.assertEqual(fsb.tsub, 10)
> -+        self.assertEqual(fsb.ncall, 3)
> -+        self.assertEqual(fsb.nactualcall, 1)
> -+        self.assertEqual(cfsab.ttot, 10)
> -+        self.assertEqual(cfsab.tsub, 4)
> -+        self.assertEqual(cfsbb.ttot, 6)
> -+        self.assertEqual(cfsbb.tsub, 6)
> -+        self.assertEqual(cfsbb.nactualcall, 0)
> -+        self.assertEqual(cfsbb.ncall, 2)
> -+
> -+    def test_aaab(self):
> -+        _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        self._ncall = 1
> -+
> -+        def a():
> -+            if self._ncall == 3:
> -+                b()
> -+                return
> -+            self._ncall += 1
> -+            a()
> -+
> -+        def b():
> -+            return
> -+
> -+        stats = utils.run_and_get_func_stats(a)
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        cfsaa = fsa.children[fsa]
> -+        cfsab = fsa.children[fsb]
> -+        self.assertEqual(fsa.ttot, 13)
> -+        self.assertEqual(fsa.tsub, 12)
> -+        self.assertEqual(fsb.ttot, 1)
> -+        self.assertEqual(fsb.tsub, 1)
> -+        self.assertEqual(cfsaa.ttot, 10)
> -+        self.assertEqual(cfsaa.tsub, 9)
> -+        self.assertEqual(cfsab.ttot, 1)
> -+        self.assertEqual(cfsab.tsub, 1)
> -+
> -+    def test_abab(self):
> -+        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
> -+        _yappi._set_test_timings(_timings)
> -+
> -+        self._ncall = 1
> -+
> -+        def a():
> -+            b()
> -+
> -+        def b():
> -+            if self._ncall == 2:
> -+                return
> -+            self._ncall += 1
> -+            a()
> -+
> -+        stats = utils.run_and_get_func_stats(a)
> -+        fsa = utils.find_stat_by_name(stats, 'a')
> -+        fsb = utils.find_stat_by_name(stats, 'b')
> -+        cfsab = fsa.children[fsb]
> -+        cfsba = fsb.children[fsa]
> -+        self.assertEqual(fsa.ttot, 13)
> -+        self.assertEqual(fsa.tsub, 8)
> -+        self.assertEqual(fsb.ttot, 10)
> -+        self.assertEqual(fsb.tsub, 5)
> -+        self.assertEqual(cfsab.ttot, 10)
> -+        self.assertEqual(cfsab.tsub, 5)
> -+        self.assertEqual(cfsab.ncall, 2)
> -+        self.assertEqual(cfsab.nactualcall, 1)
> -+        self.assertEqual(cfsba.ttot, 6)
> -+        self.assertEqual(cfsba.tsub, 5)
> -+
> -+
> -+if __name__ == '__main__':
> -+    #     import sys;sys.argv = ['', 'BasicUsage.test_run_as_script']
> -+    #     import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile']
> -+    unittest.main()
> ---- a/tests/test_hooks.py
> -+++ b/tests/test_hooks.py
> -@@ -5,7 +5,7 @@ import unittest
> - import time
> -
> - import yappi
> --import utils
> -+import tests.utils as utils
> -
> -
> - def a():
> ---- a/tests/test_tags.py
> -+++ b/tests/test_tags.py
> -@@ -2,7 +2,7 @@ import unittest
> - import yappi
> - import threading
> - import time
> --from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
> -+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
> -
> -
> - class MultiThreadTests(YappiUnitTestCase):
> diff --git a/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch b/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch
> deleted file mode 100644
> index d40bd2b7c..000000000
> --- a/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch
> +++ /dev/null
> @@ -1,26 +0,0 @@
> -From 38afdacf526410f970afc58e147c7377c6c7112c Mon Sep 17 00:00:00 2001
> -From: =?UTF-8?q?S=C3=BCmer=20Cip?= <sumer.cip@platform.sh>
> -Date: Fri, 25 Nov 2022 15:58:03 +0300
> -Subject: [PATCH 2/2] add 3.11 to the setup
> -
> ----
> -Upstream-Status: Pending
> -
> - setup.py | 1 +
> - 1 file changed, 1 insertion(+)
> -
> -diff --git a/setup.py b/setup.py
> -index d006787..96e2a66 100644
> ---- a/setup.py
> -+++ b/setup.py
> -@@ -56,6 +56,7 @@ CLASSIFIERS = [
> -     'Programming Language :: Python :: 3.8',
> -     'Programming Language :: Python :: 3.9',
> -     'Programming Language :: Python :: 3.10',
> -+    'Programming Language :: Python :: 3.11',
> -     'Programming Language :: Python :: Implementation :: CPython',
> -     'Operating System :: OS Independent',
> -     'Topic :: Software Development :: Libraries',
> ---
> -2.30.2
> -
> diff --git a/meta-python/recipes-devtools/python/python3-yappi_1.4.0.bb b/meta-python/recipes-devtools/python/python3-yappi_1.6.0.bb
> similarity index 74%
> rename from meta-python/recipes-devtools/python/python3-yappi_1.4.0.bb
> rename to meta-python/recipes-devtools/python/python3-yappi_1.6.0.bb
> index 71e74e86f..435dc11bb 100644
> --- a/meta-python/recipes-devtools/python/python3-yappi_1.4.0.bb
> +++ b/meta-python/recipes-devtools/python/python3-yappi_1.6.0.bb
> @@ -4,13 +4,9 @@ HOMEPAGE = "https://github.com/sumerc/yappi"
>  LICENSE = "MIT"
>  LIC_FILES_CHKSUM = "file://LICENSE;md5=71c208c9a4fd864385eb69ad4caa3bee"
>
> -SRC_URI[sha256sum] = "504b5d8fc7433736cb5e257991d2e7f2946019174f1faec7b2fe947881a17fc0"
> +SRC_URI[sha256sum] = "a9aaf72009d8c03067294151ee0470ac7a6dfa7b33baab40b198d6c1ef00430a"
>
> -SRC_URI += " \
> -    file://run-ptest \
> -    file://0001-Fix-imports-for-ptests.patch \
> -    file://0002-add-3.11-to-the-setup.patch \
> -"
> +SRC_URI += "file://run-ptest"
>
>  inherit pypi setuptools3 ptest
>
> --
> 2.39.2
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#107753): https://lists.openembedded.org/g/openembedded-devel/message/107753
> Mute This Topic: https://lists.openembedded.org/mt/103319780/1997914
> Group Owner: openembedded-devel+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-devel/unsub [raj.khem@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
Alexander Kanavin Dec. 22, 2023, 4:12 p.m. UTC | #2
I didn't try that. And I have to ask: checking ptests by hand means
we're not running those ptests regularly in CI, and if so, then why
bother? It can regress at any point through seemingly unrelated
changes, and maybe already has even before this update.

If python 3.12 update has a chance of ever happening, ptests need to
be checked by someone else, as there are still some 25 build failures
I need to look at. Otherwise doing all the runtime testing and fixing
across the whole python stack simply exceeds my capacity.

Alex

On Fri, 22 Dec 2023 at 16:54, Khem Raj <raj.khem@gmail.com> wrote:
>
> On Fri, Dec 22, 2023 at 7:11 AM Alexander Kanavin
> <alex.kanavin@gmail.com> wrote:
> >
> > Drop patches:
> > 0002-add-3.11-to-the-setup.patch - issue resolved upstream
> > 0001-Fix-imports-for-ptests.patch - unclear what the problem is, too difficult to rebase.
>
> Does
> bitbake meta-python-image-ptest-python3-yappi
>
> show regression ?
>
> >
> > Signed-off-by: Alexander Kanavin <alex@linutronix.de>
> > ---
> >  .../0001-Fix-imports-for-ptests.patch         | 3895 -----------------
> >  .../0002-add-3.11-to-the-setup.patch          |   26 -
> >  ...-yappi_1.4.0.bb => python3-yappi_1.6.0.bb} |    8 +-
> >  3 files changed, 2 insertions(+), 3927 deletions(-)
> >  delete mode 100644 meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
> >  delete mode 100644 meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch
> >  rename meta-python/recipes-devtools/python/{python3-yappi_1.4.0.bb => python3-yappi_1.6.0.bb} (74%)
> >
> > diff --git a/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch b/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
> > deleted file mode 100644
> > index 476db4b7d..000000000
> > --- a/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
> > +++ /dev/null
> > @@ -1,3895 +0,0 @@
> > -From 0dedc1c573ddc4e87475eb03c64555cd54a72e92 Mon Sep 17 00:00:00 2001
> > -From: Trevor Gamblin <trevor.gamblin@windriver.com>
> > -Date: Mon, 7 Jun 2021 09:40:20 -0400
> > -Subject: [PATCH] Fix imports for tests
> > -
> > -Signed-off-by: Trevor Gamblin <trevor.gamblin@windriver.com>
> > ----
> > -Upstream-Status: Pending
> > -
> > - tests/test_asyncio.py              | 2 +-
> > - tests/test_asyncio_context_vars.py | 2 +-
> > - tests/test_functionality.py        | 2 +-
> > - tests/test_hooks.py                | 2 +-
> > - tests/test_tags.py                 | 2 +-
> > - 5 files changed, 6 insertions(+), 6 deletions(-)
> > -
> > ---- a/tests/test_asyncio.py
> > -+++ b/tests/test_asyncio.py
> > -@@ -2,7 +2,7 @@ import unittest
> > - import yappi
> > - import asyncio
> > - import threading
> > --from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
> > -+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
> > -
> > -
> > - async def async_sleep(sec):
> > ---- a/tests/test_asyncio_context_vars.py
> > -+++ b/tests/test_asyncio_context_vars.py
> > -@@ -5,7 +5,7 @@ import contextvars
> > - import functools
> > - import time
> > - import os
> > --import utils
> > -+import tests.utils as utils
> > - import yappi
> > -
> > - async_context_id = contextvars.ContextVar('async_context_id')
> > ---- a/tests/test_functionality.py
> > -+++ b/tests/test_functionality.py
> > -@@ -1,1916 +1,1916 @@
> > --import os
> > --import sys
> > --import time
> > --import threading
> > --import unittest
> > --import yappi
> > --import _yappi
> > --import utils
> > --import multiprocessing  # added to fix http://bugs.python.org/issue15881 for > Py2.6
> > --import subprocess
> > --
> > --_counter = 0
> > --
> > --
> > --class BasicUsage(utils.YappiUnitTestCase):
> > --
> > --    def test_callback_function_int_return_overflow(self):
> > --        # this test is just here to check if any errors are generated, as the err
> > --        # is printed in C side, I did not include it here. THere are ways to test
> > --        # this deterministically, I did not bother
> > --        import ctypes
> > --
> > --        def _unsigned_overflow_margin():
> > --            return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1
> > --
> > --        def foo():
> > --            pass
> > --
> > --        #with utils.captured_output() as (out, err):
> > --        yappi.set_context_id_callback(_unsigned_overflow_margin)
> > --        yappi.set_tag_callback(_unsigned_overflow_margin)
> > --        yappi.start()
> > --        foo()
> > --
> > --    def test_issue60(self):
> > --
> > --        def foo():
> > --            buf = bytearray()
> > --            buf += b't' * 200
> > --            view = memoryview(buf)[10:]
> > --            view = view.tobytes()
> > --            del buf[:10]  # this throws exception
> > --            return view
> > --
> > --        yappi.start(builtins=True)
> > --        foo()
> > --        self.assertTrue(
> > --            len(
> > --                yappi.get_func_stats(
> > --                    filter_callback=lambda x: yappi.
> > --                    func_matches(x, [memoryview.tobytes])
> > --                )
> > --            ) > 0
> > --        )
> > --        yappi.stop()
> > --
> > --    def test_issue54(self):
> > --
> > --        def _tag_cbk():
> > --            global _counter
> > --            _counter += 1
> > --            return _counter
> > --
> > --        def a():
> > --            pass
> > --
> > --        def b():
> > --            pass
> > --
> > --        yappi.set_tag_callback(_tag_cbk)
> > --        yappi.start()
> > --        a()
> > --        a()
> > --        a()
> > --        yappi.stop()
> > --        stats = yappi.get_func_stats()
> > --        self.assertEqual(stats.pop().ncall, 3)  # aggregated if no tag is given
> > --        stats = yappi.get_func_stats(tag=1)
> > --
> > --        for i in range(1, 3):
> > --            stats = yappi.get_func_stats(tag=i)
> > --            stats = yappi.get_func_stats(
> > --                tag=i, filter_callback=lambda x: yappi.func_matches(x, [a])
> > --            )
> > --
> > --            stat = stats.pop()
> > --            self.assertEqual(stat.ncall, 1)
> > --
> > --        yappi.set_tag_callback(None)
> > --        yappi.clear_stats()
> > --        yappi.start()
> > --        b()
> > --        b()
> > --        stats = yappi.get_func_stats()
> > --        self.assertEqual(len(stats), 1)
> > --        stat = stats.pop()
> > --        self.assertEqual(stat.ncall, 2)
> > --
> > --    def test_filter(self):
> > --
> > --        def a():
> > --            pass
> > --
> > --        def b():
> > --            a()
> > --
> > --        def c():
> > --            b()
> > --
> > --        _TCOUNT = 5
> > --
> > --        ts = []
> > --        yappi.start()
> > --        for i in range(_TCOUNT):
> > --            t = threading.Thread(target=c)
> > --            t.start()
> > --            ts.append(t)
> > --
> > --        for t in ts:
> > --            t.join()
> > --
> > --        yappi.stop()
> > --
> > --        ctx_ids = []
> > --        for tstat in yappi.get_thread_stats():
> > --            if tstat.name == '_MainThread':
> > --                main_ctx_id = tstat.id
> > --            else:
> > --                ctx_ids.append(tstat.id)
> > --
> > --        fstats = yappi.get_func_stats(filter={"ctx_id": 9})
> > --        self.assertTrue(fstats.empty())
> > --        fstats = yappi.get_func_stats(
> > --            filter={
> > --                "ctx_id": main_ctx_id,
> > --                "name": "c"
> > --            }
> > --        )  # main thread
> > --        self.assertTrue(fstats.empty())
> > --
> > --        for i in ctx_ids:
> > --            fstats = yappi.get_func_stats(
> > --                filter={
> > --                    "ctx_id": i,
> > --                    "name": "a",
> > --                    "ncall": 1
> > --                }
> > --            )
> > --            self.assertEqual(fstats.pop().ncall, 1)
> > --            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"})
> > --            self.assertEqual(fstats.pop().ncall, 1)
> > --            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"})
> > --            self.assertEqual(fstats.pop().ncall, 1)
> > --
> > --        yappi.clear_stats()
> > --        yappi.start(builtins=True)
> > --        time.sleep(0.1)
> > --        yappi.stop()
> > --        fstats = yappi.get_func_stats(filter={"module": "time"})
> > --        self.assertEqual(len(fstats), 1)
> > --
> > --        # invalid filters`
> > --        self.assertRaises(
> > --            Exception, yappi.get_func_stats, filter={'tag': "sss"}
> > --        )
> > --        self.assertRaises(
> > --            Exception, yappi.get_func_stats, filter={'ctx_id': "None"}
> > --        )
> > --
> > --    def test_filter_callback(self):
> > --
> > --        def a():
> > --            time.sleep(0.1)
> > --
> > --        def b():
> > --            a()
> > --
> > --        def c():
> > --            pass
> > --
> > --        def d():
> > --            pass
> > --
> > --        yappi.set_clock_type("wall")
> > --        yappi.start(builtins=True)
> > --        a()
> > --        b()
> > --        c()
> > --        d()
> > --        stats = yappi.get_func_stats(
> > --            filter_callback=lambda x: yappi.func_matches(x, [a, b])
> > --        )
> > --        #stats.print_all()
> > --        r1 = '''
> > --        tests/test_functionality.py:98 a      2      0.000000  0.200350  0.100175
> > --        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.100197
> > --        '''
> > --        self.assert_traces_almost_equal(r1, stats)
> > --        self.assertEqual(len(stats), 2)
> > --        stats = yappi.get_func_stats(
> > --            filter_callback=lambda x: yappi.
> > --            module_matches(x, [sys.modules[__name__]])
> > --        )
> > --        r1 = '''
> > --        tests/test_functionality.py:98 a      2      0.000000  0.230130  0.115065
> > --        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.109011
> > --        tests/test_functionality.py:104 c     1      0.000000  0.000002  0.000002
> > --        tests/test_functionality.py:107 d     1      0.000000  0.000001  0.000001
> > --        '''
> > --        self.assert_traces_almost_equal(r1, stats)
> > --        self.assertEqual(len(stats), 4)
> > --
> > --        stats = yappi.get_func_stats(
> > --            filter_callback=lambda x: yappi.func_matches(x, [time.sleep])
> > --        )
> > --        self.assertEqual(len(stats), 1)
> > --        r1 = '''
> > --        time.sleep                            2      0.206804  0.220000  0.103402
> > --        '''
> > --        self.assert_traces_almost_equal(r1, stats)
> > --
> > --    def test_print_formatting(self):
> > --
> > --        def a():
> > --            pass
> > --
> > --        def b():
> > --            a()
> > --
> > --        func_cols = {
> > --            1: ("name", 48),
> > --            0: ("ncall", 5),
> > --            2: ("tsub", 8),
> > --        }
> > --        thread_cols = {
> > --            1: ("name", 48),
> > --            0: ("ttot", 8),
> > --        }
> > --
> > --        yappi.start()
> > --        a()
> > --        b()
> > --        yappi.stop()
> > --        fs = yappi.get_func_stats()
> > --        cs = fs[1].children
> > --        ts = yappi.get_thread_stats()
> > --        #fs.print_all(out=sys.stderr, columns={1:("name", 70), })
> > --        #cs.print_all(out=sys.stderr, columns=func_cols)
> > --        #ts.print_all(out=sys.stderr, columns=thread_cols)
> > --        #cs.print_all(out=sys.stderr, columns={})
> > --
> > --        self.assertRaises(
> > --            yappi.YappiError, fs.print_all, columns={1: ("namee", 9)}
> > --        )
> > --        self.assertRaises(
> > --            yappi.YappiError, cs.print_all, columns={1: ("dd", 0)}
> > --        )
> > --        self.assertRaises(
> > --            yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)}
> > --        )
> > --
> > --    def test_get_clock(self):
> > --        yappi.set_clock_type('cpu')
> > --        self.assertEqual('cpu', yappi.get_clock_type())
> > --        clock_info = yappi.get_clock_info()
> > --        self.assertTrue('api' in clock_info)
> > --        self.assertTrue('resolution' in clock_info)
> > --
> > --        yappi.set_clock_type('wall')
> > --        self.assertEqual('wall', yappi.get_clock_type())
> > --
> > --        t0 = yappi.get_clock_time()
> > --        time.sleep(0.1)
> > --        duration = yappi.get_clock_time() - t0
> > --        self.assertTrue(0.05 < duration < 0.3)
> > --
> > --    def test_profile_decorator(self):
> > --
> > --        def aggregate(func, stats):
> > --            fname = "tests/%s.profile" % (func.__name__)
> > --            try:
> > --                stats.add(fname)
> > --            except IOError:
> > --                pass
> > --            stats.save(fname)
> > --            raise Exception("messing around")
> > --
> > --        @yappi.profile(return_callback=aggregate)
> > --        def a(x, y):
> > --            if x + y == 25:
> > --                raise Exception("")
> > --            return x + y
> > --
> > --        def b():
> > --            pass
> > --
> > --        try:
> > --            os.remove(
> > --                "tests/a.profile"
> > --            )  # remove the one from prev test, if available
> > --        except:
> > --            pass
> > --
> > --        # global profile is on to mess things up
> > --        yappi.start()
> > --        b()
> > --
> > --        # assert functionality and call function at same time
> > --        try:
> > --            self.assertEqual(a(1, 2), 3)
> > --        except:
> > --            pass
> > --        try:
> > --            self.assertEqual(a(2, 5), 7)
> > --        except:
> > --            pass
> > --        try:
> > --            a(4, 21)
> > --        except:
> > --            pass
> > --        stats = yappi.get_func_stats().add("tests/a.profile")
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        self.assertEqual(fsa.ncall, 3)
> > --        self.assertEqual(len(stats), 1)  # b() should be cleared out.
> > --
> > --        @yappi.profile(return_callback=aggregate)
> > --        def count_down_rec(n):
> > --            if n == 0:
> > --                return
> > --            count_down_rec(n - 1)
> > --
> > --        try:
> > --            os.remove(
> > --                "tests/count_down_rec.profile"
> > --            )  # remove the one from prev test, if available
> > --        except:
> > --            pass
> > --
> > --        try:
> > --            count_down_rec(4)
> > --        except:
> > --            pass
> > --        try:
> > --            count_down_rec(3)
> > --        except:
> > --            pass
> > --
> > --        stats = yappi.YFuncStats("tests/count_down_rec.profile")
> > --        fsrec = utils.find_stat_by_name(stats, 'count_down_rec')
> > --        self.assertEqual(fsrec.ncall, 9)
> > --        self.assertEqual(fsrec.nactualcall, 2)
> > --
> > --    def test_strip_dirs(self):
> > --
> > --        def a():
> > --            pass
> > --
> > --        stats = utils.run_and_get_func_stats(a, )
> > --        stats.strip_dirs()
> > --        fsa = utils.find_stat_by_name(stats, "a")
> > --        self.assertEqual(fsa.module, os.path.basename(fsa.module))
> > --
> > --    @unittest.skipIf(os.name == "nt", "do not run on Windows")
> > --    def test_run_as_script(self):
> > --        import re
> > --        p = subprocess.Popen(
> > --            ['yappi', os.path.join('./tests', 'run_as_script.py')],
> > --            stdout=subprocess.PIPE
> > --        )
> > --        out, err = p.communicate()
> > --        self.assertEqual(p.returncode, 0)
> > --        func_stats, thread_stats = re.split(
> > --            b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out
> > --        )
> > --        self.assertTrue(b'FancyThread' in thread_stats)
> > --
> > --    def test_yappi_overhead(self):
> > --        LOOP_COUNT = 100000
> > --
> > --        def a():
> > --            pass
> > --
> > --        def b():
> > --            for i in range(LOOP_COUNT):
> > --                a()
> > --
> > --        t0 = time.time()
> > --        yappi.start()
> > --        b()
> > --        yappi.stop()
> > --        time_with_yappi = time.time() - t0
> > --        t0 = time.time()
> > --        b()
> > --        time_without_yappi = time.time() - t0
> > --        if time_without_yappi == 0:
> > --            time_without_yappi = 0.000001
> > --
> > --        # in latest v0.82, I calculated this as close to "7.0" in my machine.
> > --        # however, %83 of this overhead is coming from tickcount(). The other %17
> > --        # seems to have been evenly distributed to the internal bookkeeping
> > --        # structures/algorithms which seems acceptable. Note that our test only
> > --        # tests one function being profiled at-a-time in a short interval.
> > --        # profiling high number of functions in a small time
> > --        # is a different beast, (which is pretty unlikely in most applications)
> > --        # So as a conclusion: I cannot see any optimization window for Yappi that
> > --        # is worth implementing as we will only optimize %17 of the time.
> > --        sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \
> > --            (time_with_yappi / time_without_yappi))
> > --
> > --    def test_clear_stats_while_running(self):
> > --
> > --        def a():
> > --            pass
> > --
> > --        yappi.start()
> > --        a()
> > --        yappi.clear_stats()
> > --        a()
> > --        stats = yappi.get_func_stats()
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        self.assertEqual(fsa.ncall, 1)
> > --
> > --    def test_generator(self):
> > --
> > --        def _gen(n):
> > --            while (n > 0):
> > --                yield n
> > --                n -= 1
> > --
> > --        yappi.start()
> > --        for x in _gen(5):
> > --            pass
> > --        self.assertTrue(
> > --            yappi.convert2pstats(yappi.get_func_stats()) is not None
> > --        )
> > --
> > --    def test_slice_child_stats_and_strip_dirs(self):
> > --
> > --        def b():
> > --            for i in range(10000000):
> > --                pass
> > --
> > --        def a():
> > --            b()
> > --
> > --        yappi.start(builtins=True)
> > --        a()
> > --        stats = yappi.get_func_stats()
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        self.assertTrue(fsa.children[0:1] is not None)
> > --        prev_afullname = fsa.full_name
> > --        prev_bchildfullname = fsa.children[fsb].full_name
> > --        stats.strip_dirs()
> > --        self.assertTrue(len(prev_afullname) > len(fsa.full_name))
> > --        self.assertTrue(
> > --            len(prev_bchildfullname) > len(fsa.children[fsb].full_name)
> > --        )
> > --
> > --    def test_children_stat_functions(self):
> > --        _timings = {"a_1": 5, "b_1": 3, "c_1": 1}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        def b():
> > --            pass
> > --
> > --        def c():
> > --            pass
> > --
> > --        def a():
> > --            b()
> > --            c()
> > --
> > --        yappi.start()
> > --        a()
> > --        b()  # non-child call
> > --        c()  # non-child call
> > --        stats = yappi.get_func_stats()
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        childs_of_a = fsa.children.get().sort("tavg", "desc")
> > --        prev_item = None
> > --        for item in childs_of_a:
> > --            if prev_item:
> > --                self.assertTrue(prev_item.tavg > item.tavg)
> > --            prev_item = item
> > --        childs_of_a.sort("name", "desc")
> > --        prev_item = None
> > --        for item in childs_of_a:
> > --            if prev_item:
> > --                self.assertTrue(prev_item.name > item.name)
> > --            prev_item = item
> > --        childs_of_a.clear()
> > --        self.assertTrue(childs_of_a.empty())
> > --
> > --    def test_no_stats_different_clock_type_load(self):
> > --
> > --        def a():
> > --            pass
> > --
> > --        yappi.start()
> > --        a()
> > --        yappi.stop()
> > --        yappi.get_func_stats().save("tests/ystats1.ys")
> > --        yappi.clear_stats()
> > --        yappi.set_clock_type("WALL")
> > --        yappi.start()
> > --        yappi.stop()
> > --        stats = yappi.get_func_stats().add("tests/ystats1.ys")
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        self.assertTrue(fsa is not None)
> > --
> > --    def test_subsequent_profile(self):
> > --        _timings = {"a_1": 1, "b_1": 1}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        def a():
> > --            pass
> > --
> > --        def b():
> > --            pass
> > --
> > --        yappi.start()
> > --        a()
> > --        yappi.stop()
> > --        yappi.start()
> > --        b()
> > --        yappi.stop()
> > --        stats = yappi.get_func_stats()
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        self.assertTrue(fsa is not None)
> > --        self.assertTrue(fsb is not None)
> > --        self.assertEqual(fsa.ttot, 1)
> > --        self.assertEqual(fsb.ttot, 1)
> > --
> > --    def test_lambda(self):
> > --        f = lambda: time.sleep(0.3)
> > --        yappi.set_clock_type("wall")
> > --        yappi.start()
> > --        f()
> > --        stats = yappi.get_func_stats()
> > --        fsa = utils.find_stat_by_name(stats, '<lambda>')
> > --        self.assertTrue(fsa.ttot > 0.1)
> > --
> > --    def test_module_stress(self):
> > --        self.assertEqual(yappi.is_running(), False)
> > --
> > --        yappi.start()
> > --        yappi.clear_stats()
> > --        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
> > --
> > --        yappi.stop()
> > --        yappi.clear_stats()
> > --        yappi.set_clock_type("cpu")
> > --        self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy")
> > --        self.assertEqual(yappi.is_running(), False)
> > --        yappi.clear_stats()
> > --        yappi.clear_stats()
> > --
> > --    def test_stat_sorting(self):
> > --        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        self._ncall = 1
> > --
> > --        def a():
> > --            b()
> > --
> > --        def b():
> > --            if self._ncall == 2:
> > --                return
> > --            self._ncall += 1
> > --            a()
> > --
> > --        stats = utils.run_and_get_func_stats(a)
> > --        stats = stats.sort("totaltime", "desc")
> > --        prev_stat = None
> > --        for stat in stats:
> > --            if prev_stat:
> > --                self.assertTrue(prev_stat.ttot >= stat.ttot)
> > --            prev_stat = stat
> > --        stats = stats.sort("totaltime", "asc")
> > --        prev_stat = None
> > --        for stat in stats:
> > --            if prev_stat:
> > --                self.assertTrue(prev_stat.ttot <= stat.ttot)
> > --            prev_stat = stat
> > --        stats = stats.sort("avgtime", "asc")
> > --        prev_stat = None
> > --        for stat in stats:
> > --            if prev_stat:
> > --                self.assertTrue(prev_stat.tavg <= stat.tavg)
> > --            prev_stat = stat
> > --        stats = stats.sort("name", "asc")
> > --        prev_stat = None
> > --        for stat in stats:
> > --            if prev_stat:
> > --                self.assertTrue(prev_stat.name <= stat.name)
> > --            prev_stat = stat
> > --        stats = stats.sort("subtime", "asc")
> > --        prev_stat = None
> > --        for stat in stats:
> > --            if prev_stat:
> > --                self.assertTrue(prev_stat.tsub <= stat.tsub)
> > --            prev_stat = stat
> > --
> > --        self.assertRaises(
> > --            yappi.YappiError, stats.sort, "invalid_func_sorttype_arg"
> > --        )
> > --        self.assertRaises(
> > --            yappi.YappiError, stats.sort, "totaltime",
> > --            "invalid_func_sortorder_arg"
> > --        )
> > --
> > --    def test_start_flags(self):
> > --        self.assertEqual(_yappi._get_start_flags(), None)
> > --        yappi.start()
> > --
> > --        def a():
> > --            pass
> > --
> > --        a()
> > --        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
> > --        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
> > --        self.assertEqual(len(yappi.get_thread_stats()), 1)
> > --
> > --    def test_builtin_profiling(self):
> > --
> > --        def a():
> > --            time.sleep(0.4)  # is a builtin function
> > --
> > --        yappi.set_clock_type('wall')
> > --
> > --        yappi.start(builtins=True)
> > --        a()
> > --        stats = yappi.get_func_stats()
> > --        fsa = utils.find_stat_by_name(stats, 'sleep')
> > --        self.assertTrue(fsa is not None)
> > --        self.assertTrue(fsa.ttot > 0.3)
> > --        yappi.stop()
> > --        yappi.clear_stats()
> > --
> > --        def a():
> > --            pass
> > --
> > --        yappi.start()
> > --        t = threading.Thread(target=a)
> > --        t.start()
> > --        t.join()
> > --        stats = yappi.get_func_stats()
> > --
> > --    def test_singlethread_profiling(self):
> > --        yappi.set_clock_type('wall')
> > --
> > --        def a():
> > --            time.sleep(0.2)
> > --
> > --        class Worker1(threading.Thread):
> > --
> > --            def a(self):
> > --                time.sleep(0.3)
> > --
> > --            def run(self):
> > --                self.a()
> > --
> > --        yappi.start(profile_threads=False)
> > --
> > --        c = Worker1()
> > --        c.start()
> > --        c.join()
> > --        a()
> > --        stats = yappi.get_func_stats()
> > --        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
> > --        fsa2 = utils.find_stat_by_name(stats, 'a')
> > --        self.assertTrue(fsa1 is None)
> > --        self.assertTrue(fsa2 is not None)
> > --        self.assertTrue(fsa2.ttot > 0.1)
> > --
> > --    def test_run(self):
> > --
> > --        def profiled():
> > --            pass
> > --
> > --        yappi.clear_stats()
> > --        try:
> > --            with yappi.run():
> > --                profiled()
> > --            stats = yappi.get_func_stats()
> > --        finally:
> > --            yappi.clear_stats()
> > --
> > --        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
> > --
> > --    def test_run_recursive(self):
> > --
> > --        def profiled():
> > --            pass
> > --
> > --        def not_profiled():
> > --            pass
> > --
> > --        yappi.clear_stats()
> > --        try:
> > --            with yappi.run():
> > --                with yappi.run():
> > --                    profiled()
> > --                # Profiling stopped here
> > --                not_profiled()
> > --            stats = yappi.get_func_stats()
> > --        finally:
> > --            yappi.clear_stats()
> > --
> > --        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
> > --        self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled'))
> > --
> > --
> > --class StatSaveScenarios(utils.YappiUnitTestCase):
> > --
> > --    def test_pstats_conversion(self):
> > --
> > --        def pstat_id(fs):
> > --            return (fs.module, fs.lineno, fs.name)
> > --
> > --        def a():
> > --            d()
> > --
> > --        def b():
> > --            d()
> > --
> > --        def c():
> > --            pass
> > --
> > --        def d():
> > --            pass
> > --
> > --        _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2}
> > --        _yappi._set_test_timings(_timings)
> > --        stats = utils.run_and_get_func_stats(a, )
> > --        stats.strip_dirs()
> > --        stats.save("tests/a1.pstats", type="pstat")
> > --        fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a"))
> > --        fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d"))
> > --        yappi.clear_stats()
> > --        _yappi._set_test_timings(_timings)
> > --        stats = utils.run_and_get_func_stats(a, )
> > --        stats.strip_dirs()
> > --        stats.save("tests/a2.pstats", type="pstat")
> > --        yappi.clear_stats()
> > --        _yappi._set_test_timings(_timings)
> > --        stats = utils.run_and_get_func_stats(b, )
> > --        stats.strip_dirs()
> > --        stats.save("tests/b1.pstats", type="pstat")
> > --        fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b"))
> > --        yappi.clear_stats()
> > --        _yappi._set_test_timings(_timings)
> > --        stats = utils.run_and_get_func_stats(c, )
> > --        stats.strip_dirs()
> > --        stats.save("tests/c1.pstats", type="pstat")
> > --        fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c"))
> > --
> > --        # merge saved stats and check pstats values are correct
> > --        import pstats
> > --        p = pstats.Stats(
> > --            'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats',
> > --            'tests/c1.pstats'
> > --        )
> > --        p.strip_dirs()
> > --        # ct = ttot, tt = tsub
> > --        (cc, nc, tt, ct, callers) = p.stats[fsa_pid]
> > --        self.assertEqual(cc, nc, 2)
> > --        self.assertEqual(tt, 20)
> > --        self.assertEqual(ct, 24)
> > --        (cc, nc, tt, ct, callers) = p.stats[fsd_pid]
> > --        self.assertEqual(cc, nc, 3)
> > --        self.assertEqual(tt, 6)
> > --        self.assertEqual(ct, 6)
> > --        self.assertEqual(len(callers), 2)
> > --        (cc, nc, tt, ct) = callers[fsa_pid]
> > --        self.assertEqual(cc, nc, 2)
> > --        self.assertEqual(tt, 4)
> > --        self.assertEqual(ct, 4)
> > --        (cc, nc, tt, ct) = callers[fsb_pid]
> > --        self.assertEqual(cc, nc, 1)
> > --        self.assertEqual(tt, 2)
> > --        self.assertEqual(ct, 2)
> > --
> > --    def test_merge_stats(self):
> > --        _timings = {
> > --            "a_1": 15,
> > --            "b_1": 14,
> > --            "c_1": 12,
> > --            "d_1": 10,
> > --            "e_1": 9,
> > --            "f_1": 7,
> > --            "g_1": 6,
> > --            "h_1": 5,
> > --            "i_1": 1
> > --        }
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        def a():
> > --            b()
> > --
> > --        def b():
> > --            c()
> > --
> > --        def c():
> > --            d()
> > --
> > --        def d():
> > --            e()
> > --
> > --        def e():
> > --            f()
> > --
> > --        def f():
> > --            g()
> > --
> > --        def g():
> > --            h()
> > --
> > --        def h():
> > --            i()
> > --
> > --        def i():
> > --            pass
> > --
> > --        yappi.start()
> > --        a()
> > --        a()
> > --        yappi.stop()
> > --        stats = yappi.get_func_stats()
> > --        self.assertRaises(
> > --            NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE"
> > --        )
> > --        stats.save("tests/ystats2.ys")
> > --        yappi.clear_stats()
> > --        _yappi._set_test_timings(_timings)
> > --        yappi.start()
> > --        a()
> > --        stats = yappi.get_func_stats().add("tests/ystats2.ys")
> > --        fsa = utils.find_stat_by_name(stats, "a")
> > --        fsb = utils.find_stat_by_name(stats, "b")
> > --        fsc = utils.find_stat_by_name(stats, "c")
> > --        fsd = utils.find_stat_by_name(stats, "d")
> > --        fse = utils.find_stat_by_name(stats, "e")
> > --        fsf = utils.find_stat_by_name(stats, "f")
> > --        fsg = utils.find_stat_by_name(stats, "g")
> > --        fsh = utils.find_stat_by_name(stats, "h")
> > --        fsi = utils.find_stat_by_name(stats, "i")
> > --        self.assertEqual(fsa.ttot, 45)
> > --        self.assertEqual(fsa.ncall, 3)
> > --        self.assertEqual(fsa.nactualcall, 3)
> > --        self.assertEqual(fsa.tsub, 3)
> > --        self.assertEqual(fsa.children[fsb].ttot, fsb.ttot)
> > --        self.assertEqual(fsa.children[fsb].tsub, fsb.tsub)
> > --        self.assertEqual(fsb.children[fsc].ttot, fsc.ttot)
> > --        self.assertEqual(fsb.children[fsc].tsub, fsc.tsub)
> > --        self.assertEqual(fsc.tsub, 6)
> > --        self.assertEqual(fsc.children[fsd].ttot, fsd.ttot)
> > --        self.assertEqual(fsc.children[fsd].tsub, fsd.tsub)
> > --        self.assertEqual(fsd.children[fse].ttot, fse.ttot)
> > --        self.assertEqual(fsd.children[fse].tsub, fse.tsub)
> > --        self.assertEqual(fse.children[fsf].ttot, fsf.ttot)
> > --        self.assertEqual(fse.children[fsf].tsub, fsf.tsub)
> > --        self.assertEqual(fsf.children[fsg].ttot, fsg.ttot)
> > --        self.assertEqual(fsf.children[fsg].tsub, fsg.tsub)
> > --        self.assertEqual(fsg.ttot, 18)
> > --        self.assertEqual(fsg.tsub, 3)
> > --        self.assertEqual(fsg.children[fsh].ttot, fsh.ttot)
> > --        self.assertEqual(fsg.children[fsh].tsub, fsh.tsub)
> > --        self.assertEqual(fsh.ttot, 15)
> > --        self.assertEqual(fsh.tsub, 12)
> > --        self.assertEqual(fsh.tavg, 5)
> > --        self.assertEqual(fsh.children[fsi].ttot, fsi.ttot)
> > --        self.assertEqual(fsh.children[fsi].tsub, fsi.tsub)
> > --        #stats.debug_print()
> > --
> > --    def test_merge_multithreaded_stats(self):
> > --        import _yappi
> > --        timings = {"a_1": 2, "b_1": 1}
> > --        _yappi._set_test_timings(timings)
> > --
> > --        def a():
> > --            pass
> > --
> > --        def b():
> > --            pass
> > --
> > --        yappi.start()
> > --        t = threading.Thread(target=a)
> > --        t.start()
> > --        t.join()
> > --        t = threading.Thread(target=b)
> > --        t.start()
> > --        t.join()
> > --        yappi.get_func_stats().save("tests/ystats1.ys")
> > --        yappi.clear_stats()
> > --        _yappi._set_test_timings(timings)
> > --        self.assertEqual(len(yappi.get_func_stats()), 0)
> > --        self.assertEqual(len(yappi.get_thread_stats()), 1)
> > --        t = threading.Thread(target=a)
> > --        t.start()
> > --        t.join()
> > --
> > --        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
> > --        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
> > --        yappi.get_func_stats().save("tests/ystats2.ys")
> > --
> > --        stats = yappi.YFuncStats([
> > --            "tests/ystats1.ys",
> > --            "tests/ystats2.ys",
> > --        ])
> > --        fsa = utils.find_stat_by_name(stats, "a")
> > --        fsb = utils.find_stat_by_name(stats, "b")
> > --        self.assertEqual(fsa.ncall, 2)
> > --        self.assertEqual(fsb.ncall, 1)
> > --        self.assertEqual(fsa.tsub, fsa.ttot, 4)
> > --        self.assertEqual(fsb.tsub, fsb.ttot, 1)
> > --
> > --    def test_merge_load_different_clock_types(self):
> > --        yappi.start(builtins=True)
> > --
> > --        def a():
> > --            b()
> > --
> > --        def b():
> > --            c()
> > --
> > --        def c():
> > --            pass
> > --
> > --        t = threading.Thread(target=a)
> > --        t.start()
> > --        t.join()
> > --        yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys")
> > --        yappi.stop()
> > --        yappi.clear_stats()
> > --        yappi.start(builtins=False)
> > --        t = threading.Thread(target=a)
> > --        t.start()
> > --        t.join()
> > --        yappi.get_func_stats().save("tests/ystats2.ys")
> > --        yappi.stop()
> > --        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
> > --        yappi.clear_stats()
> > --        yappi.set_clock_type("wall")
> > --        yappi.start()
> > --        t = threading.Thread(target=a)
> > --        t.start()
> > --        t.join()
> > --        yappi.get_func_stats().save("tests/ystats3.ys")
> > --        self.assertRaises(
> > --            yappi.YappiError,
> > --            yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys"
> > --        )
> > --        stats = yappi.YFuncStats(["tests/ystats1.ys",
> > --                                  "tests/ystats2.ys"]).sort("name")
> > --        fsa = utils.find_stat_by_name(stats, "a")
> > --        fsb = utils.find_stat_by_name(stats, "b")
> > --        fsc = utils.find_stat_by_name(stats, "c")
> > --        self.assertEqual(fsa.ncall, 2)
> > --        self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall)
> > --
> > --    def test_merge_aabab_aabbc(self):
> > --        _timings = {
> > --            "a_1": 15,
> > --            "a_2": 14,
> > --            "b_1": 12,
> > --            "a_3": 10,
> > --            "b_2": 9,
> > --            "c_1": 4
> > --        }
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        def a():
> > --            if self._ncall == 1:
> > --                self._ncall += 1
> > --                a()
> > --            elif self._ncall == 5:
> > --                self._ncall += 1
> > --                a()
> > --            else:
> > --                b()
> > --
> > --        def b():
> > --            if self._ncall == 2:
> > --                self._ncall += 1
> > --                a()
> > --            elif self._ncall == 6:
> > --                self._ncall += 1
> > --                b()
> > --            elif self._ncall == 7:
> > --                c()
> > --            else:
> > --                return
> > --
> > --        def c():
> > --            pass
> > --
> > --        self._ncall = 1
> > --        stats = utils.run_and_get_func_stats(a, )
> > --        stats.save("tests/ystats1.ys")
> > --        yappi.clear_stats()
> > --        _yappi._set_test_timings(_timings)
> > --        #stats.print_all()
> > --
> > --        self._ncall = 5
> > --        stats = utils.run_and_get_func_stats(a, )
> > --        stats.save("tests/ystats2.ys")
> > --
> > --        #stats.print_all()
> > --
> > --        def a():  # same name but another function(code object)
> > --            pass
> > --
> > --        yappi.start()
> > --        a()
> > --        stats = yappi.get_func_stats().add(
> > --            ["tests/ystats1.ys", "tests/ystats2.ys"]
> > --        )
> > --        #stats.print_all()
> > --        self.assertEqual(len(stats), 4)
> > --
> > --        fsa = None
> > --        for stat in stats:
> > --            if stat.name == "a" and stat.ttot == 45:
> > --                fsa = stat
> > --                break
> > --        self.assertTrue(fsa is not None)
> > --
> > --        self.assertEqual(fsa.ncall, 7)
> > --        self.assertEqual(fsa.nactualcall, 3)
> > --        self.assertEqual(fsa.ttot, 45)
> > --        self.assertEqual(fsa.tsub, 10)
> > --        fsb = utils.find_stat_by_name(stats, "b")
> > --        fsc = utils.find_stat_by_name(stats, "c")
> > --        self.assertEqual(fsb.ncall, 6)
> > --        self.assertEqual(fsb.nactualcall, 3)
> > --        self.assertEqual(fsb.ttot, 36)
> > --        self.assertEqual(fsb.tsub, 27)
> > --        self.assertEqual(fsb.tavg, 6)
> > --        self.assertEqual(fsc.ttot, 8)
> > --        self.assertEqual(fsc.tsub, 8)
> > --        self.assertEqual(fsc.tavg, 4)
> > --        self.assertEqual(fsc.nactualcall, fsc.ncall, 2)
> > --
> > --
> > --class MultithreadedScenarios(utils.YappiUnitTestCase):
> > --
> > --    def test_issue_32(self):
> > --        '''
> > --        Start yappi from different thread and we get Internal Error(15) as
> > --        the current_ctx_id() called while enumerating the threads in start()
> > --        and as it does not swap to the enumerated ThreadState* the THreadState_GetDict()
> > --        returns wrong object and thus sets an invalid id for the _ctx structure.
> > --
> > --        When this issue happens multiple Threads have same tid as the internal ts_ptr
> > --        will be same for different contexts. So, let's see if that happens
> > --        '''
> > --
> > --        def foo():
> > --            time.sleep(0.2)
> > --
> > --        def bar():
> > --            time.sleep(0.1)
> > --
> > --        def thread_func():
> > --            yappi.set_clock_type("wall")
> > --            yappi.start()
> > --
> > --            bar()
> > --
> > --        t = threading.Thread(target=thread_func)
> > --        t.start()
> > --        t.join()
> > --
> > --        foo()
> > --
> > --        yappi.stop()
> > --
> > --        thread_ids = set()
> > --        for tstat in yappi.get_thread_stats():
> > --            self.assertTrue(tstat.tid not in thread_ids)
> > --            thread_ids.add(tstat.tid)
> > --
> > --    def test_subsequent_profile(self):
> > --        WORKER_COUNT = 5
> > --
> > --        def a():
> > --            pass
> > --
> > --        def b():
> > --            pass
> > --
> > --        def c():
> > --            pass
> > --
> > --        _timings = {
> > --            "a_1": 3,
> > --            "b_1": 2,
> > --            "c_1": 1,
> > --        }
> > --
> > --        yappi.start()
> > --
> > --        def g():
> > --            pass
> > --
> > --        g()
> > --        yappi.stop()
> > --        yappi.clear_stats()
> > --        _yappi._set_test_timings(_timings)
> > --        yappi.start()
> > --
> > --        _dummy = []
> > --        for i in range(WORKER_COUNT):
> > --            t = threading.Thread(target=a)
> > --            t.start()
> > --            t.join()
> > --        for i in range(WORKER_COUNT):
> > --            t = threading.Thread(target=b)
> > --            t.start()
> > --            _dummy.append(t)
> > --            t.join()
> > --        for i in range(WORKER_COUNT):
> > --            t = threading.Thread(target=a)
> > --            t.start()
> > --            t.join()
> > --        for i in range(WORKER_COUNT):
> > --            t = threading.Thread(target=c)
> > --            t.start()
> > --            t.join()
> > --        yappi.stop()
> > --        yappi.start()
> > --
> > --        def f():
> > --            pass
> > --
> > --        f()
> > --        stats = yappi.get_func_stats()
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        fsc = utils.find_stat_by_name(stats, 'c')
> > --        self.assertEqual(fsa.ncall, 10)
> > --        self.assertEqual(fsb.ncall, 5)
> > --        self.assertEqual(fsc.ncall, 5)
> > --        self.assertEqual(fsa.ttot, fsa.tsub, 30)
> > --        self.assertEqual(fsb.ttot, fsb.tsub, 10)
> > --        self.assertEqual(fsc.ttot, fsc.tsub, 5)
> > --
> > --        # MACOSx optimizes by only creating one worker thread
> > --        self.assertTrue(len(yappi.get_thread_stats()) >= 2)
> > --
> > --    def test_basic(self):
> > --        yappi.set_clock_type('wall')
> > --
> > --        def dummy():
> > --            pass
> > --
> > --        def a():
> > --            time.sleep(0.2)
> > --
> > --        class Worker1(threading.Thread):
> > --
> > --            def a(self):
> > --                time.sleep(0.3)
> > --
> > --            def run(self):
> > --                self.a()
> > --
> > --        yappi.start(builtins=False, profile_threads=True)
> > --
> > --        c = Worker1()
> > --        c.start()
> > --        c.join()
> > --        a()
> > --        stats = yappi.get_func_stats()
> > --        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
> > --        fsa2 = utils.find_stat_by_name(stats, 'a')
> > --        self.assertTrue(fsa1 is not None)
> > --        self.assertTrue(fsa2 is not None)
> > --        self.assertTrue(fsa1.ttot > 0.2)
> > --        self.assertTrue(fsa2.ttot > 0.1)
> > --        tstats = yappi.get_thread_stats()
> > --        self.assertEqual(len(tstats), 2)
> > --        tsa = utils.find_stat_by_name(tstats, 'Worker1')
> > --        tsm = utils.find_stat_by_name(tstats, '_MainThread')
> > --        dummy()  # call dummy to force ctx name to be retrieved again.
> > --        self.assertTrue(tsa is not None)
> > --        # TODO: I put dummy() to fix below, remove the comments after a while.
> > --        self.assertTrue( # FIX: I see this fails sometimes?
> > --            tsm is not None,
> > --            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(tstats))))
> > --
> > --    def test_ctx_stats(self):
> > --        from threading import Thread
> > --        DUMMY_WORKER_COUNT = 5
> > --        yappi.start()
> > --
> > --        class DummyThread(Thread):
> > --            pass
> > --
> > --        def dummy():
> > --            pass
> > --
> > --        def dummy_worker():
> > --            pass
> > --
> > --        for i in range(DUMMY_WORKER_COUNT):
> > --            t = DummyThread(target=dummy_worker)
> > --            t.start()
> > --            t.join()
> > --        yappi.stop()
> > --        stats = yappi.get_thread_stats()
> > --        tsa = utils.find_stat_by_name(stats, "DummyThread")
> > --        self.assertTrue(tsa is not None)
> > --        yappi.clear_stats()
> > --        time.sleep(1.0)
> > --        _timings = {
> > --            "a_1": 6,
> > --            "b_1": 5,
> > --            "c_1": 3,
> > --            "d_1": 1,
> > --            "a_2": 4,
> > --            "b_2": 3,
> > --            "c_2": 2,
> > --            "d_2": 1
> > --        }
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        class Thread1(Thread):
> > --            pass
> > --
> > --        class Thread2(Thread):
> > --            pass
> > --
> > --        def a():
> > --            b()
> > --
> > --        def b():
> > --            c()
> > --
> > --        def c():
> > --            d()
> > --
> > --        def d():
> > --            time.sleep(0.6)
> > --
> > --        yappi.set_clock_type("wall")
> > --        yappi.start()
> > --        t1 = Thread1(target=a)
> > --        t1.start()
> > --        t2 = Thread2(target=a)
> > --        t2.start()
> > --        t1.join()
> > --        t2.join()
> > --        stats = yappi.get_thread_stats()
> > --
> > --        # the fist clear_stats clears the context table?
> > --        tsa = utils.find_stat_by_name(stats, "DummyThread")
> > --        self.assertTrue(tsa is None)
> > --
> > --        tst1 = utils.find_stat_by_name(stats, "Thread1")
> > --        tst2 = utils.find_stat_by_name(stats, "Thread2")
> > --        tsmain = utils.find_stat_by_name(stats, "_MainThread")
> > --        dummy()  # call dummy to force ctx name to be retrieved again.
> > --        self.assertTrue(len(stats) == 3)
> > --        self.assertTrue(tst1 is not None)
> > --        self.assertTrue(tst2 is not None)
> > --        # TODO: I put dummy() to fix below, remove the comments after a while.
> > --        self.assertTrue( # FIX: I see this fails sometimes
> > --            tsmain is not None,
> > --            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(stats))))
> > --        self.assertTrue(1.0 > tst2.ttot >= 0.5)
> > --        self.assertTrue(1.0 > tst1.ttot >= 0.5)
> > --
> > --        # test sorting of the ctx stats
> > --        stats = stats.sort("totaltime", "desc")
> > --        prev_stat = None
> > --        for stat in stats:
> > --            if prev_stat:
> > --                self.assertTrue(prev_stat.ttot >= stat.ttot)
> > --            prev_stat = stat
> > --        stats = stats.sort("totaltime", "asc")
> > --        prev_stat = None
> > --        for stat in stats:
> > --            if prev_stat:
> > --                self.assertTrue(prev_stat.ttot <= stat.ttot)
> > --            prev_stat = stat
> > --        stats = stats.sort("schedcount", "desc")
> > --        prev_stat = None
> > --        for stat in stats:
> > --            if prev_stat:
> > --                self.assertTrue(prev_stat.sched_count >= stat.sched_count)
> > --            prev_stat = stat
> > --        stats = stats.sort("name", "desc")
> > --        prev_stat = None
> > --        for stat in stats:
> > --            if prev_stat:
> > --                self.assertTrue(prev_stat.name.lower() >= stat.name.lower())
> > --            prev_stat = stat
> > --        self.assertRaises(
> > --            yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg"
> > --        )
> > --        self.assertRaises(
> > --            yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg"
> > --        )
> > --
> > --    def test_ctx_stats_cpu(self):
> > --
> > --        def get_thread_name():
> > --            try:
> > --                return threading.current_thread().name
> > --            except AttributeError:
> > --                return "Anonymous"
> > --
> > --        def burn_cpu(sec):
> > --            t0 = yappi.get_clock_time()
> > --            elapsed = 0
> > --            while (elapsed < sec):
> > --                for _ in range(1000):
> > --                    pass
> > --                elapsed = yappi.get_clock_time() - t0
> > --
> > --        def test():
> > --
> > --            ts = []
> > --            for i in (0.01, 0.05, 0.1):
> > --                t = threading.Thread(target=burn_cpu, args=(i, ))
> > --                t.name = "burn_cpu-%s" % str(i)
> > --                t.start()
> > --                ts.append(t)
> > --            for t in ts:
> > --                t.join()
> > --
> > --        yappi.set_clock_type("cpu")
> > --        yappi.set_context_name_callback(get_thread_name)
> > --
> > --        yappi.start()
> > --
> > --        test()
> > --
> > --        yappi.stop()
> > --
> > --        tstats = yappi.get_thread_stats()
> > --        r1 = '''
> > --        burn_cpu-0.1      3      123145356058624  0.100105  8
> > --        burn_cpu-0.05     2      123145361313792  0.050149  8
> > --        burn_cpu-0.01     1      123145356058624  0.010127  2
> > --        MainThread        0      4321620864       0.001632  6
> > --        '''
> > --        self.assert_ctx_stats_almost_equal(r1, tstats)
> > --
> > --    def test_producer_consumer_with_queues(self):
> > --        # we currently just stress yappi, no functionality test is done here.
> > --        yappi.start()
> > --        if utils.is_py3x():
> > --            from queue import Queue
> > --        else:
> > --            from Queue import Queue
> > --        from threading import Thread
> > --        WORKER_THREAD_COUNT = 50
> > --        WORK_ITEM_COUNT = 2000
> > --
> > --        def worker():
> > --            while True:
> > --                item = q.get()
> > --                # do the work with item
> > --                q.task_done()
> > --
> > --        q = Queue()
> > --        for i in range(WORKER_THREAD_COUNT):
> > --            t = Thread(target=worker)
> > --            t.daemon = True
> > --            t.start()
> > --
> > --        for item in range(WORK_ITEM_COUNT):
> > --            q.put(item)
> > --        q.join()  # block until all tasks are done
> > --        #yappi.get_func_stats().sort("callcount").print_all()
> > --        yappi.stop()
> > --
> > --    def test_temporary_lock_waiting(self):
> > --        yappi.start()
> > --        _lock = threading.Lock()
> > --
> > --        def worker():
> > --            _lock.acquire()
> > --            try:
> > --                time.sleep(1.0)
> > --            finally:
> > --                _lock.release()
> > --
> > --        t1 = threading.Thread(target=worker)
> > --        t2 = threading.Thread(target=worker)
> > --        t1.start()
> > --        t2.start()
> > --        t1.join()
> > --        t2.join()
> > --        #yappi.get_func_stats().sort("callcount").print_all()
> > --        yappi.stop()
> > --
> > --    @unittest.skipIf(os.name != "posix", "requires Posix compliant OS")
> > --    def test_signals_with_blocking_calls(self):
> > --        import signal, os, time
> > --
> > --        # just to verify if signal is handled correctly and stats/yappi are not corrupted.
> > --        def handler(signum, frame):
> > --            raise Exception("Signal handler executed!")
> > --
> > --        yappi.start()
> > --        signal.signal(signal.SIGALRM, handler)
> > --        signal.alarm(1)
> > --        self.assertRaises(Exception, time.sleep, 2)
> > --        stats = yappi.get_func_stats()
> > --        fsh = utils.find_stat_by_name(stats, "handler")
> > --        self.assertTrue(fsh is not None)
> > --
> > --    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
> > --    def test_concurrent_futures(self):
> > --        yappi.start()
> > --        from concurrent.futures import ThreadPoolExecutor
> > --        with ThreadPoolExecutor(max_workers=5) as executor:
> > --            f = executor.submit(pow, 5, 2)
> > --            self.assertEqual(f.result(), 25)
> > --        time.sleep(1.0)
> > --        yappi.stop()
> > --
> > --    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
> > --    def test_barrier(self):
> > --        yappi.start()
> > --        b = threading.Barrier(2, timeout=1)
> > --
> > --        def worker():
> > --            try:
> > --                b.wait()
> > --            except threading.BrokenBarrierError:
> > --                pass
> > --            except Exception:
> > --                raise Exception("BrokenBarrierError not raised")
> > --
> > --        t1 = threading.Thread(target=worker)
> > --        t1.start()
> > --        #b.wait()
> > --        t1.join()
> > --        yappi.stop()
> > --
> > --
> > --class NonRecursiveFunctions(utils.YappiUnitTestCase):
> > --
> > --    def test_abcd(self):
> > --        _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        def a():
> > --            b()
> > --
> > --        def b():
> > --            c()
> > --
> > --        def c():
> > --            d()
> > --
> > --        def d():
> > --            pass
> > --
> > --        stats = utils.run_and_get_func_stats(a)
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        fsc = utils.find_stat_by_name(stats, 'c')
> > --        fsd = utils.find_stat_by_name(stats, 'd')
> > --        cfsab = fsa.children[fsb]
> > --        cfsbc = fsb.children[fsc]
> > --        cfscd = fsc.children[fsd]
> > --
> > --        self.assertEqual(fsa.ttot, 6)
> > --        self.assertEqual(fsa.tsub, 1)
> > --        self.assertEqual(fsb.ttot, 5)
> > --        self.assertEqual(fsb.tsub, 2)
> > --        self.assertEqual(fsc.ttot, 3)
> > --        self.assertEqual(fsc.tsub, 2)
> > --        self.assertEqual(fsd.ttot, 1)
> > --        self.assertEqual(fsd.tsub, 1)
> > --        self.assertEqual(cfsab.ttot, 5)
> > --        self.assertEqual(cfsab.tsub, 2)
> > --        self.assertEqual(cfsbc.ttot, 3)
> > --        self.assertEqual(cfsbc.tsub, 2)
> > --        self.assertEqual(cfscd.ttot, 1)
> > --        self.assertEqual(cfscd.tsub, 1)
> > --
> > --    def test_stop_in_middle(self):
> > --        _timings = {"a_1": 6, "b_1": 4}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        def a():
> > --            b()
> > --            yappi.stop()
> > --
> > --        def b():
> > --            time.sleep(0.2)
> > --
> > --        yappi.start()
> > --        a()
> > --        stats = yappi.get_func_stats()
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --
> > --        self.assertEqual(fsa.ncall, 1)
> > --        self.assertEqual(fsa.nactualcall, 0)
> > --        self.assertEqual(fsa.ttot, 0)  # no call_leave called
> > --        self.assertEqual(fsa.tsub, 0)  # no call_leave called
> > --        self.assertEqual(fsb.ttot, 4)
> > --
> > --
> > --class RecursiveFunctions(utils.YappiUnitTestCase):
> > --
> > --    def test_fibonacci(self):
> > --
> > --        def fib(n):
> > --            if n > 1:
> > --                return fib(n - 1) + fib(n - 2)
> > --            else:
> > --                return n
> > --
> > --        stats = utils.run_and_get_func_stats(fib, 22)
> > --        fs = utils.find_stat_by_name(stats, 'fib')
> > --        self.assertEqual(fs.ncall, 57313)
> > --        self.assertEqual(fs.ttot, fs.tsub)
> > --
> > --    def test_abcadc(self):
> > --        _timings = {
> > --            "a_1": 20,
> > --            "b_1": 19,
> > --            "c_1": 17,
> > --            "a_2": 13,
> > --            "d_1": 12,
> > --            "c_2": 10,
> > --            "a_3": 5
> > --        }
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        def a(n):
> > --            if n == 3:
> > --                return
> > --            if n == 1 + 1:
> > --                d(n)
> > --            else:
> > --                b(n)
> > --
> > --        def b(n):
> > --            c(n)
> > --
> > --        def c(n):
> > --            a(n + 1)
> > --
> > --        def d(n):
> > --            c(n)
> > --
> > --        stats = utils.run_and_get_func_stats(a, 1)
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        fsc = utils.find_stat_by_name(stats, 'c')
> > --        fsd = utils.find_stat_by_name(stats, 'd')
> > --        self.assertEqual(fsa.ncall, 3)
> > --        self.assertEqual(fsa.nactualcall, 1)
> > --        self.assertEqual(fsa.ttot, 20)
> > --        self.assertEqual(fsa.tsub, 7)
> > --        self.assertEqual(fsb.ttot, 19)
> > --        self.assertEqual(fsb.tsub, 2)
> > --        self.assertEqual(fsc.ttot, 17)
> > --        self.assertEqual(fsc.tsub, 9)
> > --        self.assertEqual(fsd.ttot, 12)
> > --        self.assertEqual(fsd.tsub, 2)
> > --        cfsca = fsc.children[fsa]
> > --        self.assertEqual(cfsca.nactualcall, 0)
> > --        self.assertEqual(cfsca.ncall, 2)
> > --        self.assertEqual(cfsca.ttot, 13)
> > --        self.assertEqual(cfsca.tsub, 6)
> > --
> > --    def test_aaaa(self):
> > --        _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        def d(n):
> > --            if n == 3:
> > --                return
> > --            d(n + 1)
> > --
> > --        stats = utils.run_and_get_func_stats(d, 0)
> > --        fsd = utils.find_stat_by_name(stats, 'd')
> > --        self.assertEqual(fsd.ncall, 4)
> > --        self.assertEqual(fsd.nactualcall, 1)
> > --        self.assertEqual(fsd.ttot, 9)
> > --        self.assertEqual(fsd.tsub, 9)
> > --        cfsdd = fsd.children[fsd]
> > --        self.assertEqual(cfsdd.ttot, 7)
> > --        self.assertEqual(cfsdd.tsub, 7)
> > --        self.assertEqual(cfsdd.ncall, 3)
> > --        self.assertEqual(cfsdd.nactualcall, 0)
> > --
> > --    def test_abcabc(self):
> > --        _timings = {
> > --            "a_1": 20,
> > --            "b_1": 19,
> > --            "c_1": 17,
> > --            "a_2": 13,
> > --            "b_2": 11,
> > --            "c_2": 9,
> > --            "a_3": 6
> > --        }
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        def a(n):
> > --            if n == 3:
> > --                return
> > --            else:
> > --                b(n)
> > --
> > --        def b(n):
> > --            c(n)
> > --
> > --        def c(n):
> > --            a(n + 1)
> > --
> > --        stats = utils.run_and_get_func_stats(a, 1)
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        fsc = utils.find_stat_by_name(stats, 'c')
> > --        self.assertEqual(fsa.ncall, 3)
> > --        self.assertEqual(fsa.nactualcall, 1)
> > --        self.assertEqual(fsa.ttot, 20)
> > --        self.assertEqual(fsa.tsub, 9)
> > --        self.assertEqual(fsb.ttot, 19)
> > --        self.assertEqual(fsb.tsub, 4)
> > --        self.assertEqual(fsc.ttot, 17)
> > --        self.assertEqual(fsc.tsub, 7)
> > --        cfsab = fsa.children[fsb]
> > --        cfsbc = fsb.children[fsc]
> > --        cfsca = fsc.children[fsa]
> > --        self.assertEqual(cfsab.ttot, 19)
> > --        self.assertEqual(cfsab.tsub, 4)
> > --        self.assertEqual(cfsbc.ttot, 17)
> > --        self.assertEqual(cfsbc.tsub, 7)
> > --        self.assertEqual(cfsca.ttot, 13)
> > --        self.assertEqual(cfsca.tsub, 8)
> > --
> > --    def test_abcbca(self):
> > --        _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1}
> > --        _yappi._set_test_timings(_timings)
> > --        self._ncall = 1
> > --
> > --        def a():
> > --            if self._ncall == 1:
> > --                b()
> > --            else:
> > --                return
> > --
> > --        def b():
> > --            c()
> > --
> > --        def c():
> > --            if self._ncall == 1:
> > --                self._ncall += 1
> > --                b()
> > --            else:
> > --                a()
> > --
> > --        stats = utils.run_and_get_func_stats(a)
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        fsc = utils.find_stat_by_name(stats, 'c')
> > --        cfsab = fsa.children[fsb]
> > --        cfsbc = fsb.children[fsc]
> > --        cfsca = fsc.children[fsa]
> > --        self.assertEqual(fsa.ttot, 10)
> > --        self.assertEqual(fsa.tsub, 2)
> > --        self.assertEqual(fsb.ttot, 9)
> > --        self.assertEqual(fsb.tsub, 4)
> > --        self.assertEqual(fsc.ttot, 7)
> > --        self.assertEqual(fsc.tsub, 4)
> > --        self.assertEqual(cfsab.ttot, 9)
> > --        self.assertEqual(cfsab.tsub, 2)
> > --        self.assertEqual(cfsbc.ttot, 7)
> > --        self.assertEqual(cfsbc.tsub, 4)
> > --        self.assertEqual(cfsca.ttot, 1)
> > --        self.assertEqual(cfsca.tsub, 1)
> > --        self.assertEqual(cfsca.ncall, 1)
> > --        self.assertEqual(cfsca.nactualcall, 0)
> > --
> > --    def test_aabccb(self):
> > --        _timings = {
> > --            "a_1": 13,
> > --            "a_2": 11,
> > --            "b_1": 9,
> > --            "c_1": 5,
> > --            "c_2": 3,
> > --            "b_2": 1
> > --        }
> > --        _yappi._set_test_timings(_timings)
> > --        self._ncall = 1
> > --
> > --        def a():
> > --            if self._ncall == 1:
> > --                self._ncall += 1
> > --                a()
> > --            else:
> > --                b()
> > --
> > --        def b():
> > --            if self._ncall == 3:
> > --                return
> > --            else:
> > --                c()
> > --
> > --        def c():
> > --            if self._ncall == 2:
> > --                self._ncall += 1
> > --                c()
> > --            else:
> > --                b()
> > --
> > --        stats = utils.run_and_get_func_stats(a)
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        fsc = utils.find_stat_by_name(stats, 'c')
> > --        cfsaa = fsa.children[fsa.index]
> > --        cfsab = fsa.children[fsb]
> > --        cfsbc = fsb.children[fsc.full_name]
> > --        cfscc = fsc.children[fsc]
> > --        cfscb = fsc.children[fsb]
> > --        self.assertEqual(fsb.ttot, 9)
> > --        self.assertEqual(fsb.tsub, 5)
> > --        self.assertEqual(cfsbc.ttot, 5)
> > --        self.assertEqual(cfsbc.tsub, 2)
> > --        self.assertEqual(fsa.ttot, 13)
> > --        self.assertEqual(fsa.tsub, 4)
> > --        self.assertEqual(cfsab.ttot, 9)
> > --        self.assertEqual(cfsab.tsub, 4)
> > --        self.assertEqual(cfsaa.ttot, 11)
> > --        self.assertEqual(cfsaa.tsub, 2)
> > --        self.assertEqual(fsc.ttot, 5)
> > --        self.assertEqual(fsc.tsub, 4)
> > --
> > --    def test_abaa(self):
> > --        _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        self._ncall = 1
> > --
> > --        def a():
> > --            if self._ncall == 1:
> > --                b()
> > --            elif self._ncall == 2:
> > --                self._ncall += 1
> > --                a()
> > --            else:
> > --                return
> > --
> > --        def b():
> > --            self._ncall += 1
> > --            a()
> > --
> > --        stats = utils.run_and_get_func_stats(a)
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        cfsaa = fsa.children[fsa]
> > --        cfsba = fsb.children[fsa]
> > --        self.assertEqual(fsb.ttot, 10)
> > --        self.assertEqual(fsb.tsub, 1)
> > --        self.assertEqual(fsa.ttot, 13)
> > --        self.assertEqual(fsa.tsub, 12)
> > --        self.assertEqual(cfsaa.ttot, 5)
> > --        self.assertEqual(cfsaa.tsub, 5)
> > --        self.assertEqual(cfsba.ttot, 9)
> > --        self.assertEqual(cfsba.tsub, 4)
> > --
> > --    def test_aabb(self):
> > --        _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        self._ncall = 1
> > --
> > --        def a():
> > --            if self._ncall == 1:
> > --                self._ncall += 1
> > --                a()
> > --            elif self._ncall == 2:
> > --                b()
> > --            else:
> > --                return
> > --
> > --        def b():
> > --            if self._ncall == 2:
> > --                self._ncall += 1
> > --                b()
> > --            else:
> > --                return
> > --
> > --        stats = utils.run_and_get_func_stats(a)
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        cfsaa = fsa.children[fsa]
> > --        cfsab = fsa.children[fsb]
> > --        cfsbb = fsb.children[fsb]
> > --        self.assertEqual(fsa.ttot, 13)
> > --        self.assertEqual(fsa.tsub, 4)
> > --        self.assertEqual(fsb.ttot, 9)
> > --        self.assertEqual(fsb.tsub, 9)
> > --        self.assertEqual(cfsaa.ttot, 10)
> > --        self.assertEqual(cfsaa.tsub, 1)
> > --        self.assertEqual(cfsab.ttot, 9)
> > --        self.assertEqual(cfsab.tsub, 4)
> > --        self.assertEqual(cfsbb.ttot, 5)
> > --        self.assertEqual(cfsbb.tsub, 5)
> > --
> > --    def test_abbb(self):
> > --        _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        self._ncall = 1
> > --
> > --        def a():
> > --            if self._ncall == 1:
> > --                b()
> > --
> > --        def b():
> > --            if self._ncall == 3:
> > --                return
> > --            self._ncall += 1
> > --            b()
> > --
> > --        stats = utils.run_and_get_func_stats(a)
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        cfsab = fsa.children[fsb]
> > --        cfsbb = fsb.children[fsb]
> > --        self.assertEqual(fsa.ttot, 13)
> > --        self.assertEqual(fsa.tsub, 3)
> > --        self.assertEqual(fsb.ttot, 10)
> > --        self.assertEqual(fsb.tsub, 10)
> > --        self.assertEqual(fsb.ncall, 3)
> > --        self.assertEqual(fsb.nactualcall, 1)
> > --        self.assertEqual(cfsab.ttot, 10)
> > --        self.assertEqual(cfsab.tsub, 4)
> > --        self.assertEqual(cfsbb.ttot, 6)
> > --        self.assertEqual(cfsbb.tsub, 6)
> > --        self.assertEqual(cfsbb.nactualcall, 0)
> > --        self.assertEqual(cfsbb.ncall, 2)
> > --
> > --    def test_aaab(self):
> > --        _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        self._ncall = 1
> > --
> > --        def a():
> > --            if self._ncall == 3:
> > --                b()
> > --                return
> > --            self._ncall += 1
> > --            a()
> > --
> > --        def b():
> > --            return
> > --
> > --        stats = utils.run_and_get_func_stats(a)
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        cfsaa = fsa.children[fsa]
> > --        cfsab = fsa.children[fsb]
> > --        self.assertEqual(fsa.ttot, 13)
> > --        self.assertEqual(fsa.tsub, 12)
> > --        self.assertEqual(fsb.ttot, 1)
> > --        self.assertEqual(fsb.tsub, 1)
> > --        self.assertEqual(cfsaa.ttot, 10)
> > --        self.assertEqual(cfsaa.tsub, 9)
> > --        self.assertEqual(cfsab.ttot, 1)
> > --        self.assertEqual(cfsab.tsub, 1)
> > --
> > --    def test_abab(self):
> > --        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
> > --        _yappi._set_test_timings(_timings)
> > --
> > --        self._ncall = 1
> > --
> > --        def a():
> > --            b()
> > --
> > --        def b():
> > --            if self._ncall == 2:
> > --                return
> > --            self._ncall += 1
> > --            a()
> > --
> > --        stats = utils.run_and_get_func_stats(a)
> > --        fsa = utils.find_stat_by_name(stats, 'a')
> > --        fsb = utils.find_stat_by_name(stats, 'b')
> > --        cfsab = fsa.children[fsb]
> > --        cfsba = fsb.children[fsa]
> > --        self.assertEqual(fsa.ttot, 13)
> > --        self.assertEqual(fsa.tsub, 8)
> > --        self.assertEqual(fsb.ttot, 10)
> > --        self.assertEqual(fsb.tsub, 5)
> > --        self.assertEqual(cfsab.ttot, 10)
> > --        self.assertEqual(cfsab.tsub, 5)
> > --        self.assertEqual(cfsab.ncall, 2)
> > --        self.assertEqual(cfsab.nactualcall, 1)
> > --        self.assertEqual(cfsba.ttot, 6)
> > --        self.assertEqual(cfsba.tsub, 5)
> > --
> > --
> > --if __name__ == '__main__':
> > --    #     import sys;sys.argv = ['', 'BasicUsage.test_run_as_script']
> > --    #     import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile']
> > --    unittest.main()
> > -+import os
> > -+import sys
> > -+import time
> > -+import threading
> > -+import unittest
> > -+import yappi
> > -+import _yappi
> > -+import tests.utils as utils
> > -+import multiprocessing  # added to fix http://bugs.python.org/issue15881 for > Py2.6
> > -+import subprocess
> > -+
> > -+_counter = 0
> > -+
> > -+
> > -+class BasicUsage(utils.YappiUnitTestCase):
> > -+
> > -+    def test_callback_function_int_return_overflow(self):
> > -+        # this test is just here to check if any errors are generated, as the err
> > -+        # is printed in C side, I did not include it here. THere are ways to test
> > -+        # this deterministically, I did not bother
> > -+        import ctypes
> > -+
> > -+        def _unsigned_overflow_margin():
> > -+            return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1
> > -+
> > -+        def foo():
> > -+            pass
> > -+
> > -+        #with utils.captured_output() as (out, err):
> > -+        yappi.set_context_id_callback(_unsigned_overflow_margin)
> > -+        yappi.set_tag_callback(_unsigned_overflow_margin)
> > -+        yappi.start()
> > -+        foo()
> > -+
> > -+    def test_issue60(self):
> > -+
> > -+        def foo():
> > -+            buf = bytearray()
> > -+            buf += b't' * 200
> > -+            view = memoryview(buf)[10:]
> > -+            view = view.tobytes()
> > -+            del buf[:10]  # this throws exception
> > -+            return view
> > -+
> > -+        yappi.start(builtins=True)
> > -+        foo()
> > -+        self.assertTrue(
> > -+            len(
> > -+                yappi.get_func_stats(
> > -+                    filter_callback=lambda x: yappi.
> > -+                    func_matches(x, [memoryview.tobytes])
> > -+                )
> > -+            ) > 0
> > -+        )
> > -+        yappi.stop()
> > -+
> > -+    def test_issue54(self):
> > -+
> > -+        def _tag_cbk():
> > -+            global _counter
> > -+            _counter += 1
> > -+            return _counter
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        def b():
> > -+            pass
> > -+
> > -+        yappi.set_tag_callback(_tag_cbk)
> > -+        yappi.start()
> > -+        a()
> > -+        a()
> > -+        a()
> > -+        yappi.stop()
> > -+        stats = yappi.get_func_stats()
> > -+        self.assertEqual(stats.pop().ncall, 3)  # aggregated if no tag is given
> > -+        stats = yappi.get_func_stats(tag=1)
> > -+
> > -+        for i in range(1, 3):
> > -+            stats = yappi.get_func_stats(tag=i)
> > -+            stats = yappi.get_func_stats(
> > -+                tag=i, filter_callback=lambda x: yappi.func_matches(x, [a])
> > -+            )
> > -+
> > -+            stat = stats.pop()
> > -+            self.assertEqual(stat.ncall, 1)
> > -+
> > -+        yappi.set_tag_callback(None)
> > -+        yappi.clear_stats()
> > -+        yappi.start()
> > -+        b()
> > -+        b()
> > -+        stats = yappi.get_func_stats()
> > -+        self.assertEqual(len(stats), 1)
> > -+        stat = stats.pop()
> > -+        self.assertEqual(stat.ncall, 2)
> > -+
> > -+    def test_filter(self):
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        def b():
> > -+            a()
> > -+
> > -+        def c():
> > -+            b()
> > -+
> > -+        _TCOUNT = 5
> > -+
> > -+        ts = []
> > -+        yappi.start()
> > -+        for i in range(_TCOUNT):
> > -+            t = threading.Thread(target=c)
> > -+            t.start()
> > -+            ts.append(t)
> > -+
> > -+        for t in ts:
> > -+            t.join()
> > -+
> > -+        yappi.stop()
> > -+
> > -+        ctx_ids = []
> > -+        for tstat in yappi.get_thread_stats():
> > -+            if tstat.name == '_MainThread':
> > -+                main_ctx_id = tstat.id
> > -+            else:
> > -+                ctx_ids.append(tstat.id)
> > -+
> > -+        fstats = yappi.get_func_stats(filter={"ctx_id": 9})
> > -+        self.assertTrue(fstats.empty())
> > -+        fstats = yappi.get_func_stats(
> > -+            filter={
> > -+                "ctx_id": main_ctx_id,
> > -+                "name": "c"
> > -+            }
> > -+        )  # main thread
> > -+        self.assertTrue(fstats.empty())
> > -+
> > -+        for i in ctx_ids:
> > -+            fstats = yappi.get_func_stats(
> > -+                filter={
> > -+                    "ctx_id": i,
> > -+                    "name": "a",
> > -+                    "ncall": 1
> > -+                }
> > -+            )
> > -+            self.assertEqual(fstats.pop().ncall, 1)
> > -+            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"})
> > -+            self.assertEqual(fstats.pop().ncall, 1)
> > -+            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"})
> > -+            self.assertEqual(fstats.pop().ncall, 1)
> > -+
> > -+        yappi.clear_stats()
> > -+        yappi.start(builtins=True)
> > -+        time.sleep(0.1)
> > -+        yappi.stop()
> > -+        fstats = yappi.get_func_stats(filter={"module": "time"})
> > -+        self.assertEqual(len(fstats), 1)
> > -+
> > -+        # invalid filters`
> > -+        self.assertRaises(
> > -+            Exception, yappi.get_func_stats, filter={'tag': "sss"}
> > -+        )
> > -+        self.assertRaises(
> > -+            Exception, yappi.get_func_stats, filter={'ctx_id': "None"}
> > -+        )
> > -+
> > -+    def test_filter_callback(self):
> > -+
> > -+        def a():
> > -+            time.sleep(0.1)
> > -+
> > -+        def b():
> > -+            a()
> > -+
> > -+        def c():
> > -+            pass
> > -+
> > -+        def d():
> > -+            pass
> > -+
> > -+        yappi.set_clock_type("wall")
> > -+        yappi.start(builtins=True)
> > -+        a()
> > -+        b()
> > -+        c()
> > -+        d()
> > -+        stats = yappi.get_func_stats(
> > -+            filter_callback=lambda x: yappi.func_matches(x, [a, b])
> > -+        )
> > -+        #stats.print_all()
> > -+        r1 = '''
> > -+        tests/test_functionality.py:98 a      2      0.000000  0.200350  0.100175
> > -+        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.100197
> > -+        '''
> > -+        self.assert_traces_almost_equal(r1, stats)
> > -+        self.assertEqual(len(stats), 2)
> > -+        stats = yappi.get_func_stats(
> > -+            filter_callback=lambda x: yappi.
> > -+            module_matches(x, [sys.modules[__name__]])
> > -+        )
> > -+        r1 = '''
> > -+        tests/test_functionality.py:98 a      2      0.000000  0.230130  0.115065
> > -+        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.109011
> > -+        tests/test_functionality.py:104 c     1      0.000000  0.000002  0.000002
> > -+        tests/test_functionality.py:107 d     1      0.000000  0.000001  0.000001
> > -+        '''
> > -+        self.assert_traces_almost_equal(r1, stats)
> > -+        self.assertEqual(len(stats), 4)
> > -+
> > -+        stats = yappi.get_func_stats(
> > -+            filter_callback=lambda x: yappi.func_matches(x, [time.sleep])
> > -+        )
> > -+        self.assertEqual(len(stats), 1)
> > -+        r1 = '''
> > -+        time.sleep                            2      0.206804  0.220000  0.103402
> > -+        '''
> > -+        self.assert_traces_almost_equal(r1, stats)
> > -+
> > -+    def test_print_formatting(self):
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        def b():
> > -+            a()
> > -+
> > -+        func_cols = {
> > -+            1: ("name", 48),
> > -+            0: ("ncall", 5),
> > -+            2: ("tsub", 8),
> > -+        }
> > -+        thread_cols = {
> > -+            1: ("name", 48),
> > -+            0: ("ttot", 8),
> > -+        }
> > -+
> > -+        yappi.start()
> > -+        a()
> > -+        b()
> > -+        yappi.stop()
> > -+        fs = yappi.get_func_stats()
> > -+        cs = fs[1].children
> > -+        ts = yappi.get_thread_stats()
> > -+        #fs.print_all(out=sys.stderr, columns={1:("name", 70), })
> > -+        #cs.print_all(out=sys.stderr, columns=func_cols)
> > -+        #ts.print_all(out=sys.stderr, columns=thread_cols)
> > -+        #cs.print_all(out=sys.stderr, columns={})
> > -+
> > -+        self.assertRaises(
> > -+            yappi.YappiError, fs.print_all, columns={1: ("namee", 9)}
> > -+        )
> > -+        self.assertRaises(
> > -+            yappi.YappiError, cs.print_all, columns={1: ("dd", 0)}
> > -+        )
> > -+        self.assertRaises(
> > -+            yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)}
> > -+        )
> > -+
> > -+    def test_get_clock(self):
> > -+        yappi.set_clock_type('cpu')
> > -+        self.assertEqual('cpu', yappi.get_clock_type())
> > -+        clock_info = yappi.get_clock_info()
> > -+        self.assertTrue('api' in clock_info)
> > -+        self.assertTrue('resolution' in clock_info)
> > -+
> > -+        yappi.set_clock_type('wall')
> > -+        self.assertEqual('wall', yappi.get_clock_type())
> > -+
> > -+        t0 = yappi.get_clock_time()
> > -+        time.sleep(0.1)
> > -+        duration = yappi.get_clock_time() - t0
> > -+        self.assertTrue(0.05 < duration < 0.3)
> > -+
> > -+    def test_profile_decorator(self):
> > -+
> > -+        def aggregate(func, stats):
> > -+            fname = "tests/%s.profile" % (func.__name__)
> > -+            try:
> > -+                stats.add(fname)
> > -+            except IOError:
> > -+                pass
> > -+            stats.save(fname)
> > -+            raise Exception("messing around")
> > -+
> > -+        @yappi.profile(return_callback=aggregate)
> > -+        def a(x, y):
> > -+            if x + y == 25:
> > -+                raise Exception("")
> > -+            return x + y
> > -+
> > -+        def b():
> > -+            pass
> > -+
> > -+        try:
> > -+            os.remove(
> > -+                "tests/a.profile"
> > -+            )  # remove the one from prev test, if available
> > -+        except:
> > -+            pass
> > -+
> > -+        # global profile is on to mess things up
> > -+        yappi.start()
> > -+        b()
> > -+
> > -+        # assert functionality and call function at same time
> > -+        try:
> > -+            self.assertEqual(a(1, 2), 3)
> > -+        except:
> > -+            pass
> > -+        try:
> > -+            self.assertEqual(a(2, 5), 7)
> > -+        except:
> > -+            pass
> > -+        try:
> > -+            a(4, 21)
> > -+        except:
> > -+            pass
> > -+        stats = yappi.get_func_stats().add("tests/a.profile")
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        self.assertEqual(fsa.ncall, 3)
> > -+        self.assertEqual(len(stats), 1)  # b() should be cleared out.
> > -+
> > -+        @yappi.profile(return_callback=aggregate)
> > -+        def count_down_rec(n):
> > -+            if n == 0:
> > -+                return
> > -+            count_down_rec(n - 1)
> > -+
> > -+        try:
> > -+            os.remove(
> > -+                "tests/count_down_rec.profile"
> > -+            )  # remove the one from prev test, if available
> > -+        except:
> > -+            pass
> > -+
> > -+        try:
> > -+            count_down_rec(4)
> > -+        except:
> > -+            pass
> > -+        try:
> > -+            count_down_rec(3)
> > -+        except:
> > -+            pass
> > -+
> > -+        stats = yappi.YFuncStats("tests/count_down_rec.profile")
> > -+        fsrec = utils.find_stat_by_name(stats, 'count_down_rec')
> > -+        self.assertEqual(fsrec.ncall, 9)
> > -+        self.assertEqual(fsrec.nactualcall, 2)
> > -+
> > -+    def test_strip_dirs(self):
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        stats = utils.run_and_get_func_stats(a, )
> > -+        stats.strip_dirs()
> > -+        fsa = utils.find_stat_by_name(stats, "a")
> > -+        self.assertEqual(fsa.module, os.path.basename(fsa.module))
> > -+
> > -+    @unittest.skipIf(os.name == "nt", "do not run on Windows")
> > -+    def test_run_as_script(self):
> > -+        import re
> > -+        p = subprocess.Popen(
> > -+            ['yappi', os.path.join('./tests', 'run_as_script.py')],
> > -+            stdout=subprocess.PIPE
> > -+        )
> > -+        out, err = p.communicate()
> > -+        self.assertEqual(p.returncode, 0)
> > -+        func_stats, thread_stats = re.split(
> > -+            b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out
> > -+        )
> > -+        self.assertTrue(b'FancyThread' in thread_stats)
> > -+
> > -+    def test_yappi_overhead(self):
> > -+        LOOP_COUNT = 100000
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        def b():
> > -+            for i in range(LOOP_COUNT):
> > -+                a()
> > -+
> > -+        t0 = time.time()
> > -+        yappi.start()
> > -+        b()
> > -+        yappi.stop()
> > -+        time_with_yappi = time.time() - t0
> > -+        t0 = time.time()
> > -+        b()
> > -+        time_without_yappi = time.time() - t0
> > -+        if time_without_yappi == 0:
> > -+            time_without_yappi = 0.000001
> > -+
> > -+        # in latest v0.82, I calculated this as close to "7.0" in my machine.
> > -+        # however, %83 of this overhead is coming from tickcount(). The other %17
> > -+        # seems to have been evenly distributed to the internal bookkeeping
> > -+        # structures/algorithms which seems acceptable. Note that our test only
> > -+        # tests one function being profiled at-a-time in a short interval.
> > -+        # profiling high number of functions in a small time
> > -+        # is a different beast, (which is pretty unlikely in most applications)
> > -+        # So as a conclusion: I cannot see any optimization window for Yappi that
> > -+        # is worth implementing as we will only optimize %17 of the time.
> > -+        sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \
> > -+            (time_with_yappi / time_without_yappi))
> > -+
> > -+    def test_clear_stats_while_running(self):
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        yappi.start()
> > -+        a()
> > -+        yappi.clear_stats()
> > -+        a()
> > -+        stats = yappi.get_func_stats()
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        self.assertEqual(fsa.ncall, 1)
> > -+
> > -+    def test_generator(self):
> > -+
> > -+        def _gen(n):
> > -+            while (n > 0):
> > -+                yield n
> > -+                n -= 1
> > -+
> > -+        yappi.start()
> > -+        for x in _gen(5):
> > -+            pass
> > -+        self.assertTrue(
> > -+            yappi.convert2pstats(yappi.get_func_stats()) is not None
> > -+        )
> > -+
> > -+    def test_slice_child_stats_and_strip_dirs(self):
> > -+
> > -+        def b():
> > -+            for i in range(10000000):
> > -+                pass
> > -+
> > -+        def a():
> > -+            b()
> > -+
> > -+        yappi.start(builtins=True)
> > -+        a()
> > -+        stats = yappi.get_func_stats()
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        self.assertTrue(fsa.children[0:1] is not None)
> > -+        prev_afullname = fsa.full_name
> > -+        prev_bchildfullname = fsa.children[fsb].full_name
> > -+        stats.strip_dirs()
> > -+        self.assertTrue(len(prev_afullname) > len(fsa.full_name))
> > -+        self.assertTrue(
> > -+            len(prev_bchildfullname) > len(fsa.children[fsb].full_name)
> > -+        )
> > -+
> > -+    def test_children_stat_functions(self):
> > -+        _timings = {"a_1": 5, "b_1": 3, "c_1": 1}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        def b():
> > -+            pass
> > -+
> > -+        def c():
> > -+            pass
> > -+
> > -+        def a():
> > -+            b()
> > -+            c()
> > -+
> > -+        yappi.start()
> > -+        a()
> > -+        b()  # non-child call
> > -+        c()  # non-child call
> > -+        stats = yappi.get_func_stats()
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        childs_of_a = fsa.children.get().sort("tavg", "desc")
> > -+        prev_item = None
> > -+        for item in childs_of_a:
> > -+            if prev_item:
> > -+                self.assertTrue(prev_item.tavg > item.tavg)
> > -+            prev_item = item
> > -+        childs_of_a.sort("name", "desc")
> > -+        prev_item = None
> > -+        for item in childs_of_a:
> > -+            if prev_item:
> > -+                self.assertTrue(prev_item.name > item.name)
> > -+            prev_item = item
> > -+        childs_of_a.clear()
> > -+        self.assertTrue(childs_of_a.empty())
> > -+
> > -+    def test_no_stats_different_clock_type_load(self):
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        yappi.start()
> > -+        a()
> > -+        yappi.stop()
> > -+        yappi.get_func_stats().save("tests/ystats1.ys")
> > -+        yappi.clear_stats()
> > -+        yappi.set_clock_type("WALL")
> > -+        yappi.start()
> > -+        yappi.stop()
> > -+        stats = yappi.get_func_stats().add("tests/ystats1.ys")
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        self.assertTrue(fsa is not None)
> > -+
> > -+    def test_subsequent_profile(self):
> > -+        _timings = {"a_1": 1, "b_1": 1}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        def b():
> > -+            pass
> > -+
> > -+        yappi.start()
> > -+        a()
> > -+        yappi.stop()
> > -+        yappi.start()
> > -+        b()
> > -+        yappi.stop()
> > -+        stats = yappi.get_func_stats()
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        self.assertTrue(fsa is not None)
> > -+        self.assertTrue(fsb is not None)
> > -+        self.assertEqual(fsa.ttot, 1)
> > -+        self.assertEqual(fsb.ttot, 1)
> > -+
> > -+    def test_lambda(self):
> > -+        f = lambda: time.sleep(0.3)
> > -+        yappi.set_clock_type("wall")
> > -+        yappi.start()
> > -+        f()
> > -+        stats = yappi.get_func_stats()
> > -+        fsa = utils.find_stat_by_name(stats, '<lambda>')
> > -+        self.assertTrue(fsa.ttot > 0.1)
> > -+
> > -+    def test_module_stress(self):
> > -+        self.assertEqual(yappi.is_running(), False)
> > -+
> > -+        yappi.start()
> > -+        yappi.clear_stats()
> > -+        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
> > -+
> > -+        yappi.stop()
> > -+        yappi.clear_stats()
> > -+        yappi.set_clock_type("cpu")
> > -+        self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy")
> > -+        self.assertEqual(yappi.is_running(), False)
> > -+        yappi.clear_stats()
> > -+        yappi.clear_stats()
> > -+
> > -+    def test_stat_sorting(self):
> > -+        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        self._ncall = 1
> > -+
> > -+        def a():
> > -+            b()
> > -+
> > -+        def b():
> > -+            if self._ncall == 2:
> > -+                return
> > -+            self._ncall += 1
> > -+            a()
> > -+
> > -+        stats = utils.run_and_get_func_stats(a)
> > -+        stats = stats.sort("totaltime", "desc")
> > -+        prev_stat = None
> > -+        for stat in stats:
> > -+            if prev_stat:
> > -+                self.assertTrue(prev_stat.ttot >= stat.ttot)
> > -+            prev_stat = stat
> > -+        stats = stats.sort("totaltime", "asc")
> > -+        prev_stat = None
> > -+        for stat in stats:
> > -+            if prev_stat:
> > -+                self.assertTrue(prev_stat.ttot <= stat.ttot)
> > -+            prev_stat = stat
> > -+        stats = stats.sort("avgtime", "asc")
> > -+        prev_stat = None
> > -+        for stat in stats:
> > -+            if prev_stat:
> > -+                self.assertTrue(prev_stat.tavg <= stat.tavg)
> > -+            prev_stat = stat
> > -+        stats = stats.sort("name", "asc")
> > -+        prev_stat = None
> > -+        for stat in stats:
> > -+            if prev_stat:
> > -+                self.assertTrue(prev_stat.name <= stat.name)
> > -+            prev_stat = stat
> > -+        stats = stats.sort("subtime", "asc")
> > -+        prev_stat = None
> > -+        for stat in stats:
> > -+            if prev_stat:
> > -+                self.assertTrue(prev_stat.tsub <= stat.tsub)
> > -+            prev_stat = stat
> > -+
> > -+        self.assertRaises(
> > -+            yappi.YappiError, stats.sort, "invalid_func_sorttype_arg"
> > -+        )
> > -+        self.assertRaises(
> > -+            yappi.YappiError, stats.sort, "totaltime",
> > -+            "invalid_func_sortorder_arg"
> > -+        )
> > -+
> > -+    def test_start_flags(self):
> > -+        self.assertEqual(_yappi._get_start_flags(), None)
> > -+        yappi.start()
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        a()
> > -+        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
> > -+        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
> > -+        self.assertEqual(len(yappi.get_thread_stats()), 1)
> > -+
> > -+    def test_builtin_profiling(self):
> > -+
> > -+        def a():
> > -+            time.sleep(0.4)  # is a builtin function
> > -+
> > -+        yappi.set_clock_type('wall')
> > -+
> > -+        yappi.start(builtins=True)
> > -+        a()
> > -+        stats = yappi.get_func_stats()
> > -+        fsa = utils.find_stat_by_name(stats, 'sleep')
> > -+        self.assertTrue(fsa is not None)
> > -+        self.assertTrue(fsa.ttot > 0.3)
> > -+        yappi.stop()
> > -+        yappi.clear_stats()
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        yappi.start()
> > -+        t = threading.Thread(target=a)
> > -+        t.start()
> > -+        t.join()
> > -+        stats = yappi.get_func_stats()
> > -+
> > -+    def test_singlethread_profiling(self):
> > -+        yappi.set_clock_type('wall')
> > -+
> > -+        def a():
> > -+            time.sleep(0.2)
> > -+
> > -+        class Worker1(threading.Thread):
> > -+
> > -+            def a(self):
> > -+                time.sleep(0.3)
> > -+
> > -+            def run(self):
> > -+                self.a()
> > -+
> > -+        yappi.start(profile_threads=False)
> > -+
> > -+        c = Worker1()
> > -+        c.start()
> > -+        c.join()
> > -+        a()
> > -+        stats = yappi.get_func_stats()
> > -+        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
> > -+        fsa2 = utils.find_stat_by_name(stats, 'a')
> > -+        self.assertTrue(fsa1 is None)
> > -+        self.assertTrue(fsa2 is not None)
> > -+        self.assertTrue(fsa2.ttot > 0.1)
> > -+
> > -+    def test_run(self):
> > -+
> > -+        def profiled():
> > -+            pass
> > -+
> > -+        yappi.clear_stats()
> > -+        try:
> > -+            with yappi.run():
> > -+                profiled()
> > -+            stats = yappi.get_func_stats()
> > -+        finally:
> > -+            yappi.clear_stats()
> > -+
> > -+        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
> > -+
> > -+    def test_run_recursive(self):
> > -+
> > -+        def profiled():
> > -+            pass
> > -+
> > -+        def not_profiled():
> > -+            pass
> > -+
> > -+        yappi.clear_stats()
> > -+        try:
> > -+            with yappi.run():
> > -+                with yappi.run():
> > -+                    profiled()
> > -+                # Profiling stopped here
> > -+                not_profiled()
> > -+            stats = yappi.get_func_stats()
> > -+        finally:
> > -+            yappi.clear_stats()
> > -+
> > -+        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
> > -+        self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled'))
> > -+
> > -+
> > -+class StatSaveScenarios(utils.YappiUnitTestCase):
> > -+
> > -+    def test_pstats_conversion(self):
> > -+
> > -+        def pstat_id(fs):
> > -+            return (fs.module, fs.lineno, fs.name)
> > -+
> > -+        def a():
> > -+            d()
> > -+
> > -+        def b():
> > -+            d()
> > -+
> > -+        def c():
> > -+            pass
> > -+
> > -+        def d():
> > -+            pass
> > -+
> > -+        _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2}
> > -+        _yappi._set_test_timings(_timings)
> > -+        stats = utils.run_and_get_func_stats(a, )
> > -+        stats.strip_dirs()
> > -+        stats.save("tests/a1.pstats", type="pstat")
> > -+        fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a"))
> > -+        fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d"))
> > -+        yappi.clear_stats()
> > -+        _yappi._set_test_timings(_timings)
> > -+        stats = utils.run_and_get_func_stats(a, )
> > -+        stats.strip_dirs()
> > -+        stats.save("tests/a2.pstats", type="pstat")
> > -+        yappi.clear_stats()
> > -+        _yappi._set_test_timings(_timings)
> > -+        stats = utils.run_and_get_func_stats(b, )
> > -+        stats.strip_dirs()
> > -+        stats.save("tests/b1.pstats", type="pstat")
> > -+        fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b"))
> > -+        yappi.clear_stats()
> > -+        _yappi._set_test_timings(_timings)
> > -+        stats = utils.run_and_get_func_stats(c, )
> > -+        stats.strip_dirs()
> > -+        stats.save("tests/c1.pstats", type="pstat")
> > -+        fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c"))
> > -+
> > -+        # merge saved stats and check pstats values are correct
> > -+        import pstats
> > -+        p = pstats.Stats(
> > -+            'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats',
> > -+            'tests/c1.pstats'
> > -+        )
> > -+        p.strip_dirs()
> > -+        # ct = ttot, tt = tsub
> > -+        (cc, nc, tt, ct, callers) = p.stats[fsa_pid]
> > -+        self.assertEqual(cc, nc, 2)
> > -+        self.assertEqual(tt, 20)
> > -+        self.assertEqual(ct, 24)
> > -+        (cc, nc, tt, ct, callers) = p.stats[fsd_pid]
> > -+        self.assertEqual(cc, nc, 3)
> > -+        self.assertEqual(tt, 6)
> > -+        self.assertEqual(ct, 6)
> > -+        self.assertEqual(len(callers), 2)
> > -+        (cc, nc, tt, ct) = callers[fsa_pid]
> > -+        self.assertEqual(cc, nc, 2)
> > -+        self.assertEqual(tt, 4)
> > -+        self.assertEqual(ct, 4)
> > -+        (cc, nc, tt, ct) = callers[fsb_pid]
> > -+        self.assertEqual(cc, nc, 1)
> > -+        self.assertEqual(tt, 2)
> > -+        self.assertEqual(ct, 2)
> > -+
> > -+    def test_merge_stats(self):
> > -+        _timings = {
> > -+            "a_1": 15,
> > -+            "b_1": 14,
> > -+            "c_1": 12,
> > -+            "d_1": 10,
> > -+            "e_1": 9,
> > -+            "f_1": 7,
> > -+            "g_1": 6,
> > -+            "h_1": 5,
> > -+            "i_1": 1
> > -+        }
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        def a():
> > -+            b()
> > -+
> > -+        def b():
> > -+            c()
> > -+
> > -+        def c():
> > -+            d()
> > -+
> > -+        def d():
> > -+            e()
> > -+
> > -+        def e():
> > -+            f()
> > -+
> > -+        def f():
> > -+            g()
> > -+
> > -+        def g():
> > -+            h()
> > -+
> > -+        def h():
> > -+            i()
> > -+
> > -+        def i():
> > -+            pass
> > -+
> > -+        yappi.start()
> > -+        a()
> > -+        a()
> > -+        yappi.stop()
> > -+        stats = yappi.get_func_stats()
> > -+        self.assertRaises(
> > -+            NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE"
> > -+        )
> > -+        stats.save("tests/ystats2.ys")
> > -+        yappi.clear_stats()
> > -+        _yappi._set_test_timings(_timings)
> > -+        yappi.start()
> > -+        a()
> > -+        stats = yappi.get_func_stats().add("tests/ystats2.ys")
> > -+        fsa = utils.find_stat_by_name(stats, "a")
> > -+        fsb = utils.find_stat_by_name(stats, "b")
> > -+        fsc = utils.find_stat_by_name(stats, "c")
> > -+        fsd = utils.find_stat_by_name(stats, "d")
> > -+        fse = utils.find_stat_by_name(stats, "e")
> > -+        fsf = utils.find_stat_by_name(stats, "f")
> > -+        fsg = utils.find_stat_by_name(stats, "g")
> > -+        fsh = utils.find_stat_by_name(stats, "h")
> > -+        fsi = utils.find_stat_by_name(stats, "i")
> > -+        self.assertEqual(fsa.ttot, 45)
> > -+        self.assertEqual(fsa.ncall, 3)
> > -+        self.assertEqual(fsa.nactualcall, 3)
> > -+        self.assertEqual(fsa.tsub, 3)
> > -+        self.assertEqual(fsa.children[fsb].ttot, fsb.ttot)
> > -+        self.assertEqual(fsa.children[fsb].tsub, fsb.tsub)
> > -+        self.assertEqual(fsb.children[fsc].ttot, fsc.ttot)
> > -+        self.assertEqual(fsb.children[fsc].tsub, fsc.tsub)
> > -+        self.assertEqual(fsc.tsub, 6)
> > -+        self.assertEqual(fsc.children[fsd].ttot, fsd.ttot)
> > -+        self.assertEqual(fsc.children[fsd].tsub, fsd.tsub)
> > -+        self.assertEqual(fsd.children[fse].ttot, fse.ttot)
> > -+        self.assertEqual(fsd.children[fse].tsub, fse.tsub)
> > -+        self.assertEqual(fse.children[fsf].ttot, fsf.ttot)
> > -+        self.assertEqual(fse.children[fsf].tsub, fsf.tsub)
> > -+        self.assertEqual(fsf.children[fsg].ttot, fsg.ttot)
> > -+        self.assertEqual(fsf.children[fsg].tsub, fsg.tsub)
> > -+        self.assertEqual(fsg.ttot, 18)
> > -+        self.assertEqual(fsg.tsub, 3)
> > -+        self.assertEqual(fsg.children[fsh].ttot, fsh.ttot)
> > -+        self.assertEqual(fsg.children[fsh].tsub, fsh.tsub)
> > -+        self.assertEqual(fsh.ttot, 15)
> > -+        self.assertEqual(fsh.tsub, 12)
> > -+        self.assertEqual(fsh.tavg, 5)
> > -+        self.assertEqual(fsh.children[fsi].ttot, fsi.ttot)
> > -+        self.assertEqual(fsh.children[fsi].tsub, fsi.tsub)
> > -+        #stats.debug_print()
> > -+
> > -+    def test_merge_multithreaded_stats(self):
> > -+        import _yappi
> > -+        timings = {"a_1": 2, "b_1": 1}
> > -+        _yappi._set_test_timings(timings)
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        def b():
> > -+            pass
> > -+
> > -+        yappi.start()
> > -+        t = threading.Thread(target=a)
> > -+        t.start()
> > -+        t.join()
> > -+        t = threading.Thread(target=b)
> > -+        t.start()
> > -+        t.join()
> > -+        yappi.get_func_stats().save("tests/ystats1.ys")
> > -+        yappi.clear_stats()
> > -+        _yappi._set_test_timings(timings)
> > -+        self.assertEqual(len(yappi.get_func_stats()), 0)
> > -+        self.assertEqual(len(yappi.get_thread_stats()), 1)
> > -+        t = threading.Thread(target=a)
> > -+        t.start()
> > -+        t.join()
> > -+
> > -+        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
> > -+        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
> > -+        yappi.get_func_stats().save("tests/ystats2.ys")
> > -+
> > -+        stats = yappi.YFuncStats([
> > -+            "tests/ystats1.ys",
> > -+            "tests/ystats2.ys",
> > -+        ])
> > -+        fsa = utils.find_stat_by_name(stats, "a")
> > -+        fsb = utils.find_stat_by_name(stats, "b")
> > -+        self.assertEqual(fsa.ncall, 2)
> > -+        self.assertEqual(fsb.ncall, 1)
> > -+        self.assertEqual(fsa.tsub, fsa.ttot, 4)
> > -+        self.assertEqual(fsb.tsub, fsb.ttot, 1)
> > -+
> > -+    def test_merge_load_different_clock_types(self):
> > -+        yappi.start(builtins=True)
> > -+
> > -+        def a():
> > -+            b()
> > -+
> > -+        def b():
> > -+            c()
> > -+
> > -+        def c():
> > -+            pass
> > -+
> > -+        t = threading.Thread(target=a)
> > -+        t.start()
> > -+        t.join()
> > -+        yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys")
> > -+        yappi.stop()
> > -+        yappi.clear_stats()
> > -+        yappi.start(builtins=False)
> > -+        t = threading.Thread(target=a)
> > -+        t.start()
> > -+        t.join()
> > -+        yappi.get_func_stats().save("tests/ystats2.ys")
> > -+        yappi.stop()
> > -+        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
> > -+        yappi.clear_stats()
> > -+        yappi.set_clock_type("wall")
> > -+        yappi.start()
> > -+        t = threading.Thread(target=a)
> > -+        t.start()
> > -+        t.join()
> > -+        yappi.get_func_stats().save("tests/ystats3.ys")
> > -+        self.assertRaises(
> > -+            yappi.YappiError,
> > -+            yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys"
> > -+        )
> > -+        stats = yappi.YFuncStats(["tests/ystats1.ys",
> > -+                                  "tests/ystats2.ys"]).sort("name")
> > -+        fsa = utils.find_stat_by_name(stats, "a")
> > -+        fsb = utils.find_stat_by_name(stats, "b")
> > -+        fsc = utils.find_stat_by_name(stats, "c")
> > -+        self.assertEqual(fsa.ncall, 2)
> > -+        self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall)
> > -+
> > -+    def test_merge_aabab_aabbc(self):
> > -+        _timings = {
> > -+            "a_1": 15,
> > -+            "a_2": 14,
> > -+            "b_1": 12,
> > -+            "a_3": 10,
> > -+            "b_2": 9,
> > -+            "c_1": 4
> > -+        }
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        def a():
> > -+            if self._ncall == 1:
> > -+                self._ncall += 1
> > -+                a()
> > -+            elif self._ncall == 5:
> > -+                self._ncall += 1
> > -+                a()
> > -+            else:
> > -+                b()
> > -+
> > -+        def b():
> > -+            if self._ncall == 2:
> > -+                self._ncall += 1
> > -+                a()
> > -+            elif self._ncall == 6:
> > -+                self._ncall += 1
> > -+                b()
> > -+            elif self._ncall == 7:
> > -+                c()
> > -+            else:
> > -+                return
> > -+
> > -+        def c():
> > -+            pass
> > -+
> > -+        self._ncall = 1
> > -+        stats = utils.run_and_get_func_stats(a, )
> > -+        stats.save("tests/ystats1.ys")
> > -+        yappi.clear_stats()
> > -+        _yappi._set_test_timings(_timings)
> > -+        #stats.print_all()
> > -+
> > -+        self._ncall = 5
> > -+        stats = utils.run_and_get_func_stats(a, )
> > -+        stats.save("tests/ystats2.ys")
> > -+
> > -+        #stats.print_all()
> > -+
> > -+        def a():  # same name but another function(code object)
> > -+            pass
> > -+
> > -+        yappi.start()
> > -+        a()
> > -+        stats = yappi.get_func_stats().add(
> > -+            ["tests/ystats1.ys", "tests/ystats2.ys"]
> > -+        )
> > -+        #stats.print_all()
> > -+        self.assertEqual(len(stats), 4)
> > -+
> > -+        fsa = None
> > -+        for stat in stats:
> > -+            if stat.name == "a" and stat.ttot == 45:
> > -+                fsa = stat
> > -+                break
> > -+        self.assertTrue(fsa is not None)
> > -+
> > -+        self.assertEqual(fsa.ncall, 7)
> > -+        self.assertEqual(fsa.nactualcall, 3)
> > -+        self.assertEqual(fsa.ttot, 45)
> > -+        self.assertEqual(fsa.tsub, 10)
> > -+        fsb = utils.find_stat_by_name(stats, "b")
> > -+        fsc = utils.find_stat_by_name(stats, "c")
> > -+        self.assertEqual(fsb.ncall, 6)
> > -+        self.assertEqual(fsb.nactualcall, 3)
> > -+        self.assertEqual(fsb.ttot, 36)
> > -+        self.assertEqual(fsb.tsub, 27)
> > -+        self.assertEqual(fsb.tavg, 6)
> > -+        self.assertEqual(fsc.ttot, 8)
> > -+        self.assertEqual(fsc.tsub, 8)
> > -+        self.assertEqual(fsc.tavg, 4)
> > -+        self.assertEqual(fsc.nactualcall, fsc.ncall, 2)
> > -+
> > -+
> > -+class MultithreadedScenarios(utils.YappiUnitTestCase):
> > -+
> > -+    def test_issue_32(self):
> > -+        '''
> > -+        Start yappi from different thread and we get Internal Error(15) as
> > -+        the current_ctx_id() called while enumerating the threads in start()
> > -+        and as it does not swap to the enumerated ThreadState* the THreadState_GetDict()
> > -+        returns wrong object and thus sets an invalid id for the _ctx structure.
> > -+
> > -+        When this issue happens multiple Threads have same tid as the internal ts_ptr
> > -+        will be same for different contexts. So, let's see if that happens
> > -+        '''
> > -+
> > -+        def foo():
> > -+            time.sleep(0.2)
> > -+
> > -+        def bar():
> > -+            time.sleep(0.1)
> > -+
> > -+        def thread_func():
> > -+            yappi.set_clock_type("wall")
> > -+            yappi.start()
> > -+
> > -+            bar()
> > -+
> > -+        t = threading.Thread(target=thread_func)
> > -+        t.start()
> > -+        t.join()
> > -+
> > -+        foo()
> > -+
> > -+        yappi.stop()
> > -+
> > -+        thread_ids = set()
> > -+        for tstat in yappi.get_thread_stats():
> > -+            self.assertTrue(tstat.tid not in thread_ids)
> > -+            thread_ids.add(tstat.tid)
> > -+
> > -+    def test_subsequent_profile(self):
> > -+        WORKER_COUNT = 5
> > -+
> > -+        def a():
> > -+            pass
> > -+
> > -+        def b():
> > -+            pass
> > -+
> > -+        def c():
> > -+            pass
> > -+
> > -+        _timings = {
> > -+            "a_1": 3,
> > -+            "b_1": 2,
> > -+            "c_1": 1,
> > -+        }
> > -+
> > -+        yappi.start()
> > -+
> > -+        def g():
> > -+            pass
> > -+
> > -+        g()
> > -+        yappi.stop()
> > -+        yappi.clear_stats()
> > -+        _yappi._set_test_timings(_timings)
> > -+        yappi.start()
> > -+
> > -+        _dummy = []
> > -+        for i in range(WORKER_COUNT):
> > -+            t = threading.Thread(target=a)
> > -+            t.start()
> > -+            t.join()
> > -+        for i in range(WORKER_COUNT):
> > -+            t = threading.Thread(target=b)
> > -+            t.start()
> > -+            _dummy.append(t)
> > -+            t.join()
> > -+        for i in range(WORKER_COUNT):
> > -+            t = threading.Thread(target=a)
> > -+            t.start()
> > -+            t.join()
> > -+        for i in range(WORKER_COUNT):
> > -+            t = threading.Thread(target=c)
> > -+            t.start()
> > -+            t.join()
> > -+        yappi.stop()
> > -+        yappi.start()
> > -+
> > -+        def f():
> > -+            pass
> > -+
> > -+        f()
> > -+        stats = yappi.get_func_stats()
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        fsc = utils.find_stat_by_name(stats, 'c')
> > -+        self.assertEqual(fsa.ncall, 10)
> > -+        self.assertEqual(fsb.ncall, 5)
> > -+        self.assertEqual(fsc.ncall, 5)
> > -+        self.assertEqual(fsa.ttot, fsa.tsub, 30)
> > -+        self.assertEqual(fsb.ttot, fsb.tsub, 10)
> > -+        self.assertEqual(fsc.ttot, fsc.tsub, 5)
> > -+
> > -+        # MACOSx optimizes by only creating one worker thread
> > -+        self.assertTrue(len(yappi.get_thread_stats()) >= 2)
> > -+
> > -+    def test_basic(self):
> > -+        yappi.set_clock_type('wall')
> > -+
> > -+        def dummy():
> > -+            pass
> > -+
> > -+        def a():
> > -+            time.sleep(0.2)
> > -+
> > -+        class Worker1(threading.Thread):
> > -+
> > -+            def a(self):
> > -+                time.sleep(0.3)
> > -+
> > -+            def run(self):
> > -+                self.a()
> > -+
> > -+        yappi.start(builtins=False, profile_threads=True)
> > -+
> > -+        c = Worker1()
> > -+        c.start()
> > -+        c.join()
> > -+        a()
> > -+        stats = yappi.get_func_stats()
> > -+        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
> > -+        fsa2 = utils.find_stat_by_name(stats, 'a')
> > -+        self.assertTrue(fsa1 is not None)
> > -+        self.assertTrue(fsa2 is not None)
> > -+        self.assertTrue(fsa1.ttot > 0.2)
> > -+        self.assertTrue(fsa2.ttot > 0.1)
> > -+        tstats = yappi.get_thread_stats()
> > -+        self.assertEqual(len(tstats), 2)
> > -+        tsa = utils.find_stat_by_name(tstats, 'Worker1')
> > -+        tsm = utils.find_stat_by_name(tstats, '_MainThread')
> > -+        dummy()  # call dummy to force ctx name to be retrieved again.
> > -+        self.assertTrue(tsa is not None)
> > -+        # TODO: I put dummy() to fix below, remove the comments after a while.
> > -+        self.assertTrue( # FIX: I see this fails sometimes?
> > -+            tsm is not None,
> > -+            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(tstats))))
> > -+
> > -+    def test_ctx_stats(self):
> > -+        from threading import Thread
> > -+        DUMMY_WORKER_COUNT = 5
> > -+        yappi.start()
> > -+
> > -+        class DummyThread(Thread):
> > -+            pass
> > -+
> > -+        def dummy():
> > -+            pass
> > -+
> > -+        def dummy_worker():
> > -+            pass
> > -+
> > -+        for i in range(DUMMY_WORKER_COUNT):
> > -+            t = DummyThread(target=dummy_worker)
> > -+            t.start()
> > -+            t.join()
> > -+        yappi.stop()
> > -+        stats = yappi.get_thread_stats()
> > -+        tsa = utils.find_stat_by_name(stats, "DummyThread")
> > -+        self.assertTrue(tsa is not None)
> > -+        yappi.clear_stats()
> > -+        time.sleep(1.0)
> > -+        _timings = {
> > -+            "a_1": 6,
> > -+            "b_1": 5,
> > -+            "c_1": 3,
> > -+            "d_1": 1,
> > -+            "a_2": 4,
> > -+            "b_2": 3,
> > -+            "c_2": 2,
> > -+            "d_2": 1
> > -+        }
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        class Thread1(Thread):
> > -+            pass
> > -+
> > -+        class Thread2(Thread):
> > -+            pass
> > -+
> > -+        def a():
> > -+            b()
> > -+
> > -+        def b():
> > -+            c()
> > -+
> > -+        def c():
> > -+            d()
> > -+
> > -+        def d():
> > -+            time.sleep(0.6)
> > -+
> > -+        yappi.set_clock_type("wall")
> > -+        yappi.start()
> > -+        t1 = Thread1(target=a)
> > -+        t1.start()
> > -+        t2 = Thread2(target=a)
> > -+        t2.start()
> > -+        t1.join()
> > -+        t2.join()
> > -+        stats = yappi.get_thread_stats()
> > -+
> > -+        # the fist clear_stats clears the context table?
> > -+        tsa = utils.find_stat_by_name(stats, "DummyThread")
> > -+        self.assertTrue(tsa is None)
> > -+
> > -+        tst1 = utils.find_stat_by_name(stats, "Thread1")
> > -+        tst2 = utils.find_stat_by_name(stats, "Thread2")
> > -+        tsmain = utils.find_stat_by_name(stats, "_MainThread")
> > -+        dummy()  # call dummy to force ctx name to be retrieved again.
> > -+        self.assertTrue(len(stats) == 3)
> > -+        self.assertTrue(tst1 is not None)
> > -+        self.assertTrue(tst2 is not None)
> > -+        # TODO: I put dummy() to fix below, remove the comments after a while.
> > -+        self.assertTrue( # FIX: I see this fails sometimes
> > -+            tsmain is not None,
> > -+            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(stats))))
> > -+        self.assertTrue(1.0 > tst2.ttot >= 0.5)
> > -+        self.assertTrue(1.0 > tst1.ttot >= 0.5)
> > -+
> > -+        # test sorting of the ctx stats
> > -+        stats = stats.sort("totaltime", "desc")
> > -+        prev_stat = None
> > -+        for stat in stats:
> > -+            if prev_stat:
> > -+                self.assertTrue(prev_stat.ttot >= stat.ttot)
> > -+            prev_stat = stat
> > -+        stats = stats.sort("totaltime", "asc")
> > -+        prev_stat = None
> > -+        for stat in stats:
> > -+            if prev_stat:
> > -+                self.assertTrue(prev_stat.ttot <= stat.ttot)
> > -+            prev_stat = stat
> > -+        stats = stats.sort("schedcount", "desc")
> > -+        prev_stat = None
> > -+        for stat in stats:
> > -+            if prev_stat:
> > -+                self.assertTrue(prev_stat.sched_count >= stat.sched_count)
> > -+            prev_stat = stat
> > -+        stats = stats.sort("name", "desc")
> > -+        prev_stat = None
> > -+        for stat in stats:
> > -+            if prev_stat:
> > -+                self.assertTrue(prev_stat.name.lower() >= stat.name.lower())
> > -+            prev_stat = stat
> > -+        self.assertRaises(
> > -+            yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg"
> > -+        )
> > -+        self.assertRaises(
> > -+            yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg"
> > -+        )
> > -+
> > -+    def test_ctx_stats_cpu(self):
> > -+
> > -+        def get_thread_name():
> > -+            try:
> > -+                return threading.current_thread().name
> > -+            except AttributeError:
> > -+                return "Anonymous"
> > -+
> > -+        def burn_cpu(sec):
> > -+            t0 = yappi.get_clock_time()
> > -+            elapsed = 0
> > -+            while (elapsed < sec):
> > -+                for _ in range(1000):
> > -+                    pass
> > -+                elapsed = yappi.get_clock_time() - t0
> > -+
> > -+        def test():
> > -+
> > -+            ts = []
> > -+            for i in (0.01, 0.05, 0.1):
> > -+                t = threading.Thread(target=burn_cpu, args=(i, ))
> > -+                t.name = "burn_cpu-%s" % str(i)
> > -+                t.start()
> > -+                ts.append(t)
> > -+            for t in ts:
> > -+                t.join()
> > -+
> > -+        yappi.set_clock_type("cpu")
> > -+        yappi.set_context_name_callback(get_thread_name)
> > -+
> > -+        yappi.start()
> > -+
> > -+        test()
> > -+
> > -+        yappi.stop()
> > -+
> > -+        tstats = yappi.get_thread_stats()
> > -+        r1 = '''
> > -+        burn_cpu-0.1      3      123145356058624  0.100105  8
> > -+        burn_cpu-0.05     2      123145361313792  0.050149  8
> > -+        burn_cpu-0.01     1      123145356058624  0.010127  2
> > -+        MainThread        0      4321620864       0.001632  6
> > -+        '''
> > -+        self.assert_ctx_stats_almost_equal(r1, tstats)
> > -+
> > -+    def test_producer_consumer_with_queues(self):
> > -+        # we currently just stress yappi, no functionality test is done here.
> > -+        yappi.start()
> > -+        if utils.is_py3x():
> > -+            from queue import Queue
> > -+        else:
> > -+            from Queue import Queue
> > -+        from threading import Thread
> > -+        WORKER_THREAD_COUNT = 50
> > -+        WORK_ITEM_COUNT = 2000
> > -+
> > -+        def worker():
> > -+            while True:
> > -+                item = q.get()
> > -+                # do the work with item
> > -+                q.task_done()
> > -+
> > -+        q = Queue()
> > -+        for i in range(WORKER_THREAD_COUNT):
> > -+            t = Thread(target=worker)
> > -+            t.daemon = True
> > -+            t.start()
> > -+
> > -+        for item in range(WORK_ITEM_COUNT):
> > -+            q.put(item)
> > -+        q.join()  # block until all tasks are done
> > -+        #yappi.get_func_stats().sort("callcount").print_all()
> > -+        yappi.stop()
> > -+
> > -+    def test_temporary_lock_waiting(self):
> > -+        yappi.start()
> > -+        _lock = threading.Lock()
> > -+
> > -+        def worker():
> > -+            _lock.acquire()
> > -+            try:
> > -+                time.sleep(1.0)
> > -+            finally:
> > -+                _lock.release()
> > -+
> > -+        t1 = threading.Thread(target=worker)
> > -+        t2 = threading.Thread(target=worker)
> > -+        t1.start()
> > -+        t2.start()
> > -+        t1.join()
> > -+        t2.join()
> > -+        #yappi.get_func_stats().sort("callcount").print_all()
> > -+        yappi.stop()
> > -+
> > -+    @unittest.skipIf(os.name != "posix", "requires Posix compliant OS")
> > -+    def test_signals_with_blocking_calls(self):
> > -+        import signal, os, time
> > -+
> > -+        # just to verify if signal is handled correctly and stats/yappi are not corrupted.
> > -+        def handler(signum, frame):
> > -+            raise Exception("Signal handler executed!")
> > -+
> > -+        yappi.start()
> > -+        signal.signal(signal.SIGALRM, handler)
> > -+        signal.alarm(1)
> > -+        self.assertRaises(Exception, time.sleep, 2)
> > -+        stats = yappi.get_func_stats()
> > -+        fsh = utils.find_stat_by_name(stats, "handler")
> > -+        self.assertTrue(fsh is not None)
> > -+
> > -+    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
> > -+    def test_concurrent_futures(self):
> > -+        yappi.start()
> > -+        from concurrent.futures import ThreadPoolExecutor
> > -+        with ThreadPoolExecutor(max_workers=5) as executor:
> > -+            f = executor.submit(pow, 5, 2)
> > -+            self.assertEqual(f.result(), 25)
> > -+        time.sleep(1.0)
> > -+        yappi.stop()
> > -+
> > -+    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
> > -+    def test_barrier(self):
> > -+        yappi.start()
> > -+        b = threading.Barrier(2, timeout=1)
> > -+
> > -+        def worker():
> > -+            try:
> > -+                b.wait()
> > -+            except threading.BrokenBarrierError:
> > -+                pass
> > -+            except Exception:
> > -+                raise Exception("BrokenBarrierError not raised")
> > -+
> > -+        t1 = threading.Thread(target=worker)
> > -+        t1.start()
> > -+        #b.wait()
> > -+        t1.join()
> > -+        yappi.stop()
> > -+
> > -+
> > -+class NonRecursiveFunctions(utils.YappiUnitTestCase):
> > -+
> > -+    def test_abcd(self):
> > -+        _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        def a():
> > -+            b()
> > -+
> > -+        def b():
> > -+            c()
> > -+
> > -+        def c():
> > -+            d()
> > -+
> > -+        def d():
> > -+            pass
> > -+
> > -+        stats = utils.run_and_get_func_stats(a)
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        fsc = utils.find_stat_by_name(stats, 'c')
> > -+        fsd = utils.find_stat_by_name(stats, 'd')
> > -+        cfsab = fsa.children[fsb]
> > -+        cfsbc = fsb.children[fsc]
> > -+        cfscd = fsc.children[fsd]
> > -+
> > -+        self.assertEqual(fsa.ttot, 6)
> > -+        self.assertEqual(fsa.tsub, 1)
> > -+        self.assertEqual(fsb.ttot, 5)
> > -+        self.assertEqual(fsb.tsub, 2)
> > -+        self.assertEqual(fsc.ttot, 3)
> > -+        self.assertEqual(fsc.tsub, 2)
> > -+        self.assertEqual(fsd.ttot, 1)
> > -+        self.assertEqual(fsd.tsub, 1)
> > -+        self.assertEqual(cfsab.ttot, 5)
> > -+        self.assertEqual(cfsab.tsub, 2)
> > -+        self.assertEqual(cfsbc.ttot, 3)
> > -+        self.assertEqual(cfsbc.tsub, 2)
> > -+        self.assertEqual(cfscd.ttot, 1)
> > -+        self.assertEqual(cfscd.tsub, 1)
> > -+
> > -+    def test_stop_in_middle(self):
> > -+        _timings = {"a_1": 6, "b_1": 4}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        def a():
> > -+            b()
> > -+            yappi.stop()
> > -+
> > -+        def b():
> > -+            time.sleep(0.2)
> > -+
> > -+        yappi.start()
> > -+        a()
> > -+        stats = yappi.get_func_stats()
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+
> > -+        self.assertEqual(fsa.ncall, 1)
> > -+        self.assertEqual(fsa.nactualcall, 0)
> > -+        self.assertEqual(fsa.ttot, 0)  # no call_leave called
> > -+        self.assertEqual(fsa.tsub, 0)  # no call_leave called
> > -+        self.assertEqual(fsb.ttot, 4)
> > -+
> > -+
> > -+class RecursiveFunctions(utils.YappiUnitTestCase):
> > -+
> > -+    def test_fibonacci(self):
> > -+
> > -+        def fib(n):
> > -+            if n > 1:
> > -+                return fib(n - 1) + fib(n - 2)
> > -+            else:
> > -+                return n
> > -+
> > -+        stats = utils.run_and_get_func_stats(fib, 22)
> > -+        fs = utils.find_stat_by_name(stats, 'fib')
> > -+        self.assertEqual(fs.ncall, 57313)
> > -+        self.assertEqual(fs.ttot, fs.tsub)
> > -+
> > -+    def test_abcadc(self):
> > -+        _timings = {
> > -+            "a_1": 20,
> > -+            "b_1": 19,
> > -+            "c_1": 17,
> > -+            "a_2": 13,
> > -+            "d_1": 12,
> > -+            "c_2": 10,
> > -+            "a_3": 5
> > -+        }
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        def a(n):
> > -+            if n == 3:
> > -+                return
> > -+            if n == 1 + 1:
> > -+                d(n)
> > -+            else:
> > -+                b(n)
> > -+
> > -+        def b(n):
> > -+            c(n)
> > -+
> > -+        def c(n):
> > -+            a(n + 1)
> > -+
> > -+        def d(n):
> > -+            c(n)
> > -+
> > -+        stats = utils.run_and_get_func_stats(a, 1)
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        fsc = utils.find_stat_by_name(stats, 'c')
> > -+        fsd = utils.find_stat_by_name(stats, 'd')
> > -+        self.assertEqual(fsa.ncall, 3)
> > -+        self.assertEqual(fsa.nactualcall, 1)
> > -+        self.assertEqual(fsa.ttot, 20)
> > -+        self.assertEqual(fsa.tsub, 7)
> > -+        self.assertEqual(fsb.ttot, 19)
> > -+        self.assertEqual(fsb.tsub, 2)
> > -+        self.assertEqual(fsc.ttot, 17)
> > -+        self.assertEqual(fsc.tsub, 9)
> > -+        self.assertEqual(fsd.ttot, 12)
> > -+        self.assertEqual(fsd.tsub, 2)
> > -+        cfsca = fsc.children[fsa]
> > -+        self.assertEqual(cfsca.nactualcall, 0)
> > -+        self.assertEqual(cfsca.ncall, 2)
> > -+        self.assertEqual(cfsca.ttot, 13)
> > -+        self.assertEqual(cfsca.tsub, 6)
> > -+
> > -+    def test_aaaa(self):
> > -+        _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        def d(n):
> > -+            if n == 3:
> > -+                return
> > -+            d(n + 1)
> > -+
> > -+        stats = utils.run_and_get_func_stats(d, 0)
> > -+        fsd = utils.find_stat_by_name(stats, 'd')
> > -+        self.assertEqual(fsd.ncall, 4)
> > -+        self.assertEqual(fsd.nactualcall, 1)
> > -+        self.assertEqual(fsd.ttot, 9)
> > -+        self.assertEqual(fsd.tsub, 9)
> > -+        cfsdd = fsd.children[fsd]
> > -+        self.assertEqual(cfsdd.ttot, 7)
> > -+        self.assertEqual(cfsdd.tsub, 7)
> > -+        self.assertEqual(cfsdd.ncall, 3)
> > -+        self.assertEqual(cfsdd.nactualcall, 0)
> > -+
> > -+    def test_abcabc(self):
> > -+        _timings = {
> > -+            "a_1": 20,
> > -+            "b_1": 19,
> > -+            "c_1": 17,
> > -+            "a_2": 13,
> > -+            "b_2": 11,
> > -+            "c_2": 9,
> > -+            "a_3": 6
> > -+        }
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        def a(n):
> > -+            if n == 3:
> > -+                return
> > -+            else:
> > -+                b(n)
> > -+
> > -+        def b(n):
> > -+            c(n)
> > -+
> > -+        def c(n):
> > -+            a(n + 1)
> > -+
> > -+        stats = utils.run_and_get_func_stats(a, 1)
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        fsc = utils.find_stat_by_name(stats, 'c')
> > -+        self.assertEqual(fsa.ncall, 3)
> > -+        self.assertEqual(fsa.nactualcall, 1)
> > -+        self.assertEqual(fsa.ttot, 20)
> > -+        self.assertEqual(fsa.tsub, 9)
> > -+        self.assertEqual(fsb.ttot, 19)
> > -+        self.assertEqual(fsb.tsub, 4)
> > -+        self.assertEqual(fsc.ttot, 17)
> > -+        self.assertEqual(fsc.tsub, 7)
> > -+        cfsab = fsa.children[fsb]
> > -+        cfsbc = fsb.children[fsc]
> > -+        cfsca = fsc.children[fsa]
> > -+        self.assertEqual(cfsab.ttot, 19)
> > -+        self.assertEqual(cfsab.tsub, 4)
> > -+        self.assertEqual(cfsbc.ttot, 17)
> > -+        self.assertEqual(cfsbc.tsub, 7)
> > -+        self.assertEqual(cfsca.ttot, 13)
> > -+        self.assertEqual(cfsca.tsub, 8)
> > -+
> > -+    def test_abcbca(self):
> > -+        _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1}
> > -+        _yappi._set_test_timings(_timings)
> > -+        self._ncall = 1
> > -+
> > -+        def a():
> > -+            if self._ncall == 1:
> > -+                b()
> > -+            else:
> > -+                return
> > -+
> > -+        def b():
> > -+            c()
> > -+
> > -+        def c():
> > -+            if self._ncall == 1:
> > -+                self._ncall += 1
> > -+                b()
> > -+            else:
> > -+                a()
> > -+
> > -+        stats = utils.run_and_get_func_stats(a)
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        fsc = utils.find_stat_by_name(stats, 'c')
> > -+        cfsab = fsa.children[fsb]
> > -+        cfsbc = fsb.children[fsc]
> > -+        cfsca = fsc.children[fsa]
> > -+        self.assertEqual(fsa.ttot, 10)
> > -+        self.assertEqual(fsa.tsub, 2)
> > -+        self.assertEqual(fsb.ttot, 9)
> > -+        self.assertEqual(fsb.tsub, 4)
> > -+        self.assertEqual(fsc.ttot, 7)
> > -+        self.assertEqual(fsc.tsub, 4)
> > -+        self.assertEqual(cfsab.ttot, 9)
> > -+        self.assertEqual(cfsab.tsub, 2)
> > -+        self.assertEqual(cfsbc.ttot, 7)
> > -+        self.assertEqual(cfsbc.tsub, 4)
> > -+        self.assertEqual(cfsca.ttot, 1)
> > -+        self.assertEqual(cfsca.tsub, 1)
> > -+        self.assertEqual(cfsca.ncall, 1)
> > -+        self.assertEqual(cfsca.nactualcall, 0)
> > -+
> > -+    def test_aabccb(self):
> > -+        _timings = {
> > -+            "a_1": 13,
> > -+            "a_2": 11,
> > -+            "b_1": 9,
> > -+            "c_1": 5,
> > -+            "c_2": 3,
> > -+            "b_2": 1
> > -+        }
> > -+        _yappi._set_test_timings(_timings)
> > -+        self._ncall = 1
> > -+
> > -+        def a():
> > -+            if self._ncall == 1:
> > -+                self._ncall += 1
> > -+                a()
> > -+            else:
> > -+                b()
> > -+
> > -+        def b():
> > -+            if self._ncall == 3:
> > -+                return
> > -+            else:
> > -+                c()
> > -+
> > -+        def c():
> > -+            if self._ncall == 2:
> > -+                self._ncall += 1
> > -+                c()
> > -+            else:
> > -+                b()
> > -+
> > -+        stats = utils.run_and_get_func_stats(a)
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        fsc = utils.find_stat_by_name(stats, 'c')
> > -+        cfsaa = fsa.children[fsa.index]
> > -+        cfsab = fsa.children[fsb]
> > -+        cfsbc = fsb.children[fsc.full_name]
> > -+        cfscc = fsc.children[fsc]
> > -+        cfscb = fsc.children[fsb]
> > -+        self.assertEqual(fsb.ttot, 9)
> > -+        self.assertEqual(fsb.tsub, 5)
> > -+        self.assertEqual(cfsbc.ttot, 5)
> > -+        self.assertEqual(cfsbc.tsub, 2)
> > -+        self.assertEqual(fsa.ttot, 13)
> > -+        self.assertEqual(fsa.tsub, 4)
> > -+        self.assertEqual(cfsab.ttot, 9)
> > -+        self.assertEqual(cfsab.tsub, 4)
> > -+        self.assertEqual(cfsaa.ttot, 11)
> > -+        self.assertEqual(cfsaa.tsub, 2)
> > -+        self.assertEqual(fsc.ttot, 5)
> > -+        self.assertEqual(fsc.tsub, 4)
> > -+
> > -+    def test_abaa(self):
> > -+        _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        self._ncall = 1
> > -+
> > -+        def a():
> > -+            if self._ncall == 1:
> > -+                b()
> > -+            elif self._ncall == 2:
> > -+                self._ncall += 1
> > -+                a()
> > -+            else:
> > -+                return
> > -+
> > -+        def b():
> > -+            self._ncall += 1
> > -+            a()
> > -+
> > -+        stats = utils.run_and_get_func_stats(a)
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        cfsaa = fsa.children[fsa]
> > -+        cfsba = fsb.children[fsa]
> > -+        self.assertEqual(fsb.ttot, 10)
> > -+        self.assertEqual(fsb.tsub, 1)
> > -+        self.assertEqual(fsa.ttot, 13)
> > -+        self.assertEqual(fsa.tsub, 12)
> > -+        self.assertEqual(cfsaa.ttot, 5)
> > -+        self.assertEqual(cfsaa.tsub, 5)
> > -+        self.assertEqual(cfsba.ttot, 9)
> > -+        self.assertEqual(cfsba.tsub, 4)
> > -+
> > -+    def test_aabb(self):
> > -+        _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        self._ncall = 1
> > -+
> > -+        def a():
> > -+            if self._ncall == 1:
> > -+                self._ncall += 1
> > -+                a()
> > -+            elif self._ncall == 2:
> > -+                b()
> > -+            else:
> > -+                return
> > -+
> > -+        def b():
> > -+            if self._ncall == 2:
> > -+                self._ncall += 1
> > -+                b()
> > -+            else:
> > -+                return
> > -+
> > -+        stats = utils.run_and_get_func_stats(a)
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        cfsaa = fsa.children[fsa]
> > -+        cfsab = fsa.children[fsb]
> > -+        cfsbb = fsb.children[fsb]
> > -+        self.assertEqual(fsa.ttot, 13)
> > -+        self.assertEqual(fsa.tsub, 4)
> > -+        self.assertEqual(fsb.ttot, 9)
> > -+        self.assertEqual(fsb.tsub, 9)
> > -+        self.assertEqual(cfsaa.ttot, 10)
> > -+        self.assertEqual(cfsaa.tsub, 1)
> > -+        self.assertEqual(cfsab.ttot, 9)
> > -+        self.assertEqual(cfsab.tsub, 4)
> > -+        self.assertEqual(cfsbb.ttot, 5)
> > -+        self.assertEqual(cfsbb.tsub, 5)
> > -+
> > -+    def test_abbb(self):
> > -+        _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        self._ncall = 1
> > -+
> > -+        def a():
> > -+            if self._ncall == 1:
> > -+                b()
> > -+
> > -+        def b():
> > -+            if self._ncall == 3:
> > -+                return
> > -+            self._ncall += 1
> > -+            b()
> > -+
> > -+        stats = utils.run_and_get_func_stats(a)
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        cfsab = fsa.children[fsb]
> > -+        cfsbb = fsb.children[fsb]
> > -+        self.assertEqual(fsa.ttot, 13)
> > -+        self.assertEqual(fsa.tsub, 3)
> > -+        self.assertEqual(fsb.ttot, 10)
> > -+        self.assertEqual(fsb.tsub, 10)
> > -+        self.assertEqual(fsb.ncall, 3)
> > -+        self.assertEqual(fsb.nactualcall, 1)
> > -+        self.assertEqual(cfsab.ttot, 10)
> > -+        self.assertEqual(cfsab.tsub, 4)
> > -+        self.assertEqual(cfsbb.ttot, 6)
> > -+        self.assertEqual(cfsbb.tsub, 6)
> > -+        self.assertEqual(cfsbb.nactualcall, 0)
> > -+        self.assertEqual(cfsbb.ncall, 2)
> > -+
> > -+    def test_aaab(self):
> > -+        _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        self._ncall = 1
> > -+
> > -+        def a():
> > -+            if self._ncall == 3:
> > -+                b()
> > -+                return
> > -+            self._ncall += 1
> > -+            a()
> > -+
> > -+        def b():
> > -+            return
> > -+
> > -+        stats = utils.run_and_get_func_stats(a)
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        cfsaa = fsa.children[fsa]
> > -+        cfsab = fsa.children[fsb]
> > -+        self.assertEqual(fsa.ttot, 13)
> > -+        self.assertEqual(fsa.tsub, 12)
> > -+        self.assertEqual(fsb.ttot, 1)
> > -+        self.assertEqual(fsb.tsub, 1)
> > -+        self.assertEqual(cfsaa.ttot, 10)
> > -+        self.assertEqual(cfsaa.tsub, 9)
> > -+        self.assertEqual(cfsab.ttot, 1)
> > -+        self.assertEqual(cfsab.tsub, 1)
> > -+
> > -+    def test_abab(self):
> > -+        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
> > -+        _yappi._set_test_timings(_timings)
> > -+
> > -+        self._ncall = 1
> > -+
> > -+        def a():
> > -+            b()
> > -+
> > -+        def b():
> > -+            if self._ncall == 2:
> > -+                return
> > -+            self._ncall += 1
> > -+            a()
> > -+
> > -+        stats = utils.run_and_get_func_stats(a)
> > -+        fsa = utils.find_stat_by_name(stats, 'a')
> > -+        fsb = utils.find_stat_by_name(stats, 'b')
> > -+        cfsab = fsa.children[fsb]
> > -+        cfsba = fsb.children[fsa]
> > -+        self.assertEqual(fsa.ttot, 13)
> > -+        self.assertEqual(fsa.tsub, 8)
> > -+        self.assertEqual(fsb.ttot, 10)
> > -+        self.assertEqual(fsb.tsub, 5)
> > -+        self.assertEqual(cfsab.ttot, 10)
> > -+        self.assertEqual(cfsab.tsub, 5)
> > -+        self.assertEqual(cfsab.ncall, 2)
> > -+        self.assertEqual(cfsab.nactualcall, 1)
> > -+        self.assertEqual(cfsba.ttot, 6)
> > -+        self.assertEqual(cfsba.tsub, 5)
> > -+
> > -+
> > -+if __name__ == '__main__':
> > -+    #     import sys;sys.argv = ['', 'BasicUsage.test_run_as_script']
> > -+    #     import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile']
> > -+    unittest.main()
> > ---- a/tests/test_hooks.py
> > -+++ b/tests/test_hooks.py
> > -@@ -5,7 +5,7 @@ import unittest
> > - import time
> > -
> > - import yappi
> > --import utils
> > -+import tests.utils as utils
> > -
> > -
> > - def a():
> > ---- a/tests/test_tags.py
> > -+++ b/tests/test_tags.py
> > -@@ -2,7 +2,7 @@ import unittest
> > - import yappi
> > - import threading
> > - import time
> > --from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
> > -+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
> > -
> > -
> > - class MultiThreadTests(YappiUnitTestCase):
> > diff --git a/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch b/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch
> > deleted file mode 100644
> > index d40bd2b7c..000000000
> > --- a/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch
> > +++ /dev/null
> > @@ -1,26 +0,0 @@
> > -From 38afdacf526410f970afc58e147c7377c6c7112c Mon Sep 17 00:00:00 2001
> > -From: =?UTF-8?q?S=C3=BCmer=20Cip?= <sumer.cip@platform.sh>
> > -Date: Fri, 25 Nov 2022 15:58:03 +0300
> > -Subject: [PATCH 2/2] add 3.11 to the setup
> > -
> > ----
> > -Upstream-Status: Pending
> > -
> > - setup.py | 1 +
> > - 1 file changed, 1 insertion(+)
> > -
> > -diff --git a/setup.py b/setup.py
> > -index d006787..96e2a66 100644
> > ---- a/setup.py
> > -+++ b/setup.py
> > -@@ -56,6 +56,7 @@ CLASSIFIERS = [
> > -     'Programming Language :: Python :: 3.8',
> > -     'Programming Language :: Python :: 3.9',
> > -     'Programming Language :: Python :: 3.10',
> > -+    'Programming Language :: Python :: 3.11',
> > -     'Programming Language :: Python :: Implementation :: CPython',
> > -     'Operating System :: OS Independent',
> > -     'Topic :: Software Development :: Libraries',
> > ---
> > -2.30.2
> > -
> > diff --git a/meta-python/recipes-devtools/python/python3-yappi_1.4.0.bb b/meta-python/recipes-devtools/python/python3-yappi_1.6.0.bb
> > similarity index 74%
> > rename from meta-python/recipes-devtools/python/python3-yappi_1.4.0.bb
> > rename to meta-python/recipes-devtools/python/python3-yappi_1.6.0.bb
> > index 71e74e86f..435dc11bb 100644
> > --- a/meta-python/recipes-devtools/python/python3-yappi_1.4.0.bb
> > +++ b/meta-python/recipes-devtools/python/python3-yappi_1.6.0.bb
> > @@ -4,13 +4,9 @@ HOMEPAGE = "https://github.com/sumerc/yappi"
> >  LICENSE = "MIT"
> >  LIC_FILES_CHKSUM = "file://LICENSE;md5=71c208c9a4fd864385eb69ad4caa3bee"
> >
> > -SRC_URI[sha256sum] = "504b5d8fc7433736cb5e257991d2e7f2946019174f1faec7b2fe947881a17fc0"
> > +SRC_URI[sha256sum] = "a9aaf72009d8c03067294151ee0470ac7a6dfa7b33baab40b198d6c1ef00430a"
> >
> > -SRC_URI += " \
> > -    file://run-ptest \
> > -    file://0001-Fix-imports-for-ptests.patch \
> > -    file://0002-add-3.11-to-the-setup.patch \
> > -"
> > +SRC_URI += "file://run-ptest"
> >
> >  inherit pypi setuptools3 ptest
> >
> > --
> > 2.39.2
> >
> >
> > -=-=-=-=-=-=-=-=-=-=-=-
> > Links: You receive all messages sent to this group.
> > View/Reply Online (#107753): https://lists.openembedded.org/g/openembedded-devel/message/107753
> > Mute This Topic: https://lists.openembedded.org/mt/103319780/1997914
> > Group Owner: openembedded-devel+owner@lists.openembedded.org
> > Unsubscribe: https://lists.openembedded.org/g/openembedded-devel/unsub [raj.khem@gmail.com]
> > -=-=-=-=-=-=-=-=-=-=-=-
> >
Tim Orling Dec. 23, 2023, 8:11 p.m. UTC | #3
On Fri, Dec 22, 2023 at 8:12 AM Alexander Kanavin <alex.kanavin@gmail.com>
wrote:

> I didn't try that. And I have to ask: checking ptests by hand means
> we're not running those ptests regularly in CI, and if so, then why
> bother? It can regress at any point through seemingly unrelated
> changes, and maybe already has even before this update.
>
> If python 3.12 update has a chance of ever happening, ptests need to
> be checked by someone else, as there are still some 25 build failures
> I need to look at. Otherwise doing all the runtime testing and fixing
> across the whole python stack simply exceeds my capacity.
>

Thanks for starting the process, Alex. I’ll work in this one.

>
> Alex
>
> On Fri, 22 Dec 2023 at 16:54, Khem Raj <raj.khem@gmail.com> wrote:
> >
> > On Fri, Dec 22, 2023 at 7:11 AM Alexander Kanavin
> > <alex.kanavin@gmail.com> wrote:
> > >
> > > Drop patches:
> > > 0002-add-3.11-to-the-setup.patch - issue resolved upstream
> > > 0001-Fix-imports-for-ptests.patch - unclear what the problem is, too
> difficult to rebase.
> >
> > Does
> > bitbake meta-python-image-ptest-python3-yappi
> >
> > show regression ?
> >
> > >
> > > Signed-off-by: Alexander Kanavin <alex@linutronix.de>
> > > ---
> > >  .../0001-Fix-imports-for-ptests.patch         | 3895 -----------------
> > >  .../0002-add-3.11-to-the-setup.patch          |   26 -
> > >  ...-yappi_1.4.0.bb => python3-yappi_1.6.0.bb} |    8 +-
> > >  3 files changed, 2 insertions(+), 3927 deletions(-)
> > >  delete mode 100644
> meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
> > >  delete mode 100644
> meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch
> > >  rename meta-python/recipes-devtools/python/{python3-yappi_1.4.0.bb
> => python3-yappi_1.6.0.bb} (74%)
> > >
> > > diff --git
> a/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
> b/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
> > > deleted file mode 100644
> > > index 476db4b7d..000000000
> > > ---
> a/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
> > > +++ /dev/null
> > > @@ -1,3895 +0,0 @@
> > > -From 0dedc1c573ddc4e87475eb03c64555cd54a72e92 Mon Sep 17 00:00:00 2001
> > > -From: Trevor Gamblin <trevor.gamblin@windriver.com>
> > > -Date: Mon, 7 Jun 2021 09:40:20 -0400
> > > -Subject: [PATCH] Fix imports for tests
> > > -
> > > -Signed-off-by: Trevor Gamblin <trevor.gamblin@windriver.com>
> > > ----
> > > -Upstream-Status: Pending
> > > -
> > > - tests/test_asyncio.py              | 2 +-
> > > - tests/test_asyncio_context_vars.py | 2 +-
> > > - tests/test_functionality.py        | 2 +-
> > > - tests/test_hooks.py                | 2 +-
> > > - tests/test_tags.py                 | 2 +-
> > > - 5 files changed, 6 insertions(+), 6 deletions(-)
> > > -
> > > ---- a/tests/test_asyncio.py
> > > -+++ b/tests/test_asyncio.py
> > > -@@ -2,7 +2,7 @@ import unittest
> > > - import yappi
> > > - import asyncio
> > > - import threading
> > > --from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu,
> burn_io
> > > -+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu,
> burn_io
> > > -
> > > -
> > > - async def async_sleep(sec):
> > > ---- a/tests/test_asyncio_context_vars.py
> > > -+++ b/tests/test_asyncio_context_vars.py
> > > -@@ -5,7 +5,7 @@ import contextvars
> > > - import functools
> > > - import time
> > > - import os
> > > --import utils
> > > -+import tests.utils as utils
> > > - import yappi
> > > -
> > > - async_context_id = contextvars.ContextVar('async_context_id')
> > > ---- a/tests/test_functionality.py
> > > -+++ b/tests/test_functionality.py
> > > -@@ -1,1916 +1,1916 @@
> > > --import os
> > > --import sys
> > > --import time
> > > --import threading
> > > --import unittest
> > > --import yappi
> > > --import _yappi
> > > --import utils
> > > --import multiprocessing  # added to fix
> http://bugs.python.org/issue15881 for > Py2.6
> > > --import subprocess
> > > --
> > > --_counter = 0
> > > --
> > > --
> > > --class BasicUsage(utils.YappiUnitTestCase):
> > > --
> > > --    def test_callback_function_int_return_overflow(self):
> > > --        # this test is just here to check if any errors are
> generated, as the err
> > > --        # is printed in C side, I did not include it here. THere are
> ways to test
> > > --        # this deterministically, I did not bother
> > > --        import ctypes
> > > --
> > > --        def _unsigned_overflow_margin():
> > > --            return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1
> > > --
> > > --        def foo():
> > > --            pass
> > > --
> > > --        #with utils.captured_output() as (out, err):
> > > --        yappi.set_context_id_callback(_unsigned_overflow_margin)
> > > --        yappi.set_tag_callback(_unsigned_overflow_margin)
> > > --        yappi.start()
> > > --        foo()
> > > --
> > > --    def test_issue60(self):
> > > --
> > > --        def foo():
> > > --            buf = bytearray()
> > > --            buf += b't' * 200
> > > --            view = memoryview(buf)[10:]
> > > --            view = view.tobytes()
> > > --            del buf[:10]  # this throws exception
> > > --            return view
> > > --
> > > --        yappi.start(builtins=True)
> > > --        foo()
> > > --        self.assertTrue(
> > > --            len(
> > > --                yappi.get_func_stats(
> > > --                    filter_callback=lambda x: yappi.
> > > --                    func_matches(x, [memoryview.tobytes])
> > > --                )
> > > --            ) > 0
> > > --        )
> > > --        yappi.stop()
> > > --
> > > --    def test_issue54(self):
> > > --
> > > --        def _tag_cbk():
> > > --            global _counter
> > > --            _counter += 1
> > > --            return _counter
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        def b():
> > > --            pass
> > > --
> > > --        yappi.set_tag_callback(_tag_cbk)
> > > --        yappi.start()
> > > --        a()
> > > --        a()
> > > --        a()
> > > --        yappi.stop()
> > > --        stats = yappi.get_func_stats()
> > > --        self.assertEqual(stats.pop().ncall, 3)  # aggregated if no
> tag is given
> > > --        stats = yappi.get_func_stats(tag=1)
> > > --
> > > --        for i in range(1, 3):
> > > --            stats = yappi.get_func_stats(tag=i)
> > > --            stats = yappi.get_func_stats(
> > > --                tag=i, filter_callback=lambda x:
> yappi.func_matches(x, [a])
> > > --            )
> > > --
> > > --            stat = stats.pop()
> > > --            self.assertEqual(stat.ncall, 1)
> > > --
> > > --        yappi.set_tag_callback(None)
> > > --        yappi.clear_stats()
> > > --        yappi.start()
> > > --        b()
> > > --        b()
> > > --        stats = yappi.get_func_stats()
> > > --        self.assertEqual(len(stats), 1)
> > > --        stat = stats.pop()
> > > --        self.assertEqual(stat.ncall, 2)
> > > --
> > > --    def test_filter(self):
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        def b():
> > > --            a()
> > > --
> > > --        def c():
> > > --            b()
> > > --
> > > --        _TCOUNT = 5
> > > --
> > > --        ts = []
> > > --        yappi.start()
> > > --        for i in range(_TCOUNT):
> > > --            t = threading.Thread(target=c)
> > > --            t.start()
> > > --            ts.append(t)
> > > --
> > > --        for t in ts:
> > > --            t.join()
> > > --
> > > --        yappi.stop()
> > > --
> > > --        ctx_ids = []
> > > --        for tstat in yappi.get_thread_stats():
> > > --            if tstat.name == '_MainThread':
> > > --                main_ctx_id = tstat.id
> > > --            else:
> > > --                ctx_ids.append(tstat.id)
> > > --
> > > --        fstats = yappi.get_func_stats(filter={"ctx_id": 9})
> > > --        self.assertTrue(fstats.empty())
> > > --        fstats = yappi.get_func_stats(
> > > --            filter={
> > > --                "ctx_id": main_ctx_id,
> > > --                "name": "c"
> > > --            }
> > > --        )  # main thread
> > > --        self.assertTrue(fstats.empty())
> > > --
> > > --        for i in ctx_ids:
> > > --            fstats = yappi.get_func_stats(
> > > --                filter={
> > > --                    "ctx_id": i,
> > > --                    "name": "a",
> > > --                    "ncall": 1
> > > --                }
> > > --            )
> > > --            self.assertEqual(fstats.pop().ncall, 1)
> > > --            fstats = yappi.get_func_stats(filter={"ctx_id": i,
> "name": "b"})
> > > --            self.assertEqual(fstats.pop().ncall, 1)
> > > --            fstats = yappi.get_func_stats(filter={"ctx_id": i,
> "name": "c"})
> > > --            self.assertEqual(fstats.pop().ncall, 1)
> > > --
> > > --        yappi.clear_stats()
> > > --        yappi.start(builtins=True)
> > > --        time.sleep(0.1)
> > > --        yappi.stop()
> > > --        fstats = yappi.get_func_stats(filter={"module": "time"})
> > > --        self.assertEqual(len(fstats), 1)
> > > --
> > > --        # invalid filters`
> > > --        self.assertRaises(
> > > --            Exception, yappi.get_func_stats, filter={'tag': "sss"}
> > > --        )
> > > --        self.assertRaises(
> > > --            Exception, yappi.get_func_stats, filter={'ctx_id':
> "None"}
> > > --        )
> > > --
> > > --    def test_filter_callback(self):
> > > --
> > > --        def a():
> > > --            time.sleep(0.1)
> > > --
> > > --        def b():
> > > --            a()
> > > --
> > > --        def c():
> > > --            pass
> > > --
> > > --        def d():
> > > --            pass
> > > --
> > > --        yappi.set_clock_type("wall")
> > > --        yappi.start(builtins=True)
> > > --        a()
> > > --        b()
> > > --        c()
> > > --        d()
> > > --        stats = yappi.get_func_stats(
> > > --            filter_callback=lambda x: yappi.func_matches(x, [a, b])
> > > --        )
> > > --        #stats.print_all()
> > > --        r1 = '''
> > > --        tests/test_functionality.py:98 a      2      0.000000
> 0.200350  0.100175
> > > --        tests/test_functionality.py:101 b     1      0.000000
> 0.120000  0.100197
> > > --        '''
> > > --        self.assert_traces_almost_equal(r1, stats)
> > > --        self.assertEqual(len(stats), 2)
> > > --        stats = yappi.get_func_stats(
> > > --            filter_callback=lambda x: yappi.
> > > --            module_matches(x, [sys.modules[__name__]])
> > > --        )
> > > --        r1 = '''
> > > --        tests/test_functionality.py:98 a      2      0.000000
> 0.230130  0.115065
> > > --        tests/test_functionality.py:101 b     1      0.000000
> 0.120000  0.109011
> > > --        tests/test_functionality.py:104 c     1      0.000000
> 0.000002  0.000002
> > > --        tests/test_functionality.py:107 d     1      0.000000
> 0.000001  0.000001
> > > --        '''
> > > --        self.assert_traces_almost_equal(r1, stats)
> > > --        self.assertEqual(len(stats), 4)
> > > --
> > > --        stats = yappi.get_func_stats(
> > > --            filter_callback=lambda x: yappi.func_matches(x,
> [time.sleep])
> > > --        )
> > > --        self.assertEqual(len(stats), 1)
> > > --        r1 = '''
> > > --        time.sleep                            2      0.206804
> 0.220000  0.103402
> > > --        '''
> > > --        self.assert_traces_almost_equal(r1, stats)
> > > --
> > > --    def test_print_formatting(self):
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        def b():
> > > --            a()
> > > --
> > > --        func_cols = {
> > > --            1: ("name", 48),
> > > --            0: ("ncall", 5),
> > > --            2: ("tsub", 8),
> > > --        }
> > > --        thread_cols = {
> > > --            1: ("name", 48),
> > > --            0: ("ttot", 8),
> > > --        }
> > > --
> > > --        yappi.start()
> > > --        a()
> > > --        b()
> > > --        yappi.stop()
> > > --        fs = yappi.get_func_stats()
> > > --        cs = fs[1].children
> > > --        ts = yappi.get_thread_stats()
> > > --        #fs.print_all(out=sys.stderr, columns={1:("name", 70), })
> > > --        #cs.print_all(out=sys.stderr, columns=func_cols)
> > > --        #ts.print_all(out=sys.stderr, columns=thread_cols)
> > > --        #cs.print_all(out=sys.stderr, columns={})
> > > --
> > > --        self.assertRaises(
> > > --            yappi.YappiError, fs.print_all, columns={1: ("namee", 9)}
> > > --        )
> > > --        self.assertRaises(
> > > --            yappi.YappiError, cs.print_all, columns={1: ("dd", 0)}
> > > --        )
> > > --        self.assertRaises(
> > > --            yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)}
> > > --        )
> > > --
> > > --    def test_get_clock(self):
> > > --        yappi.set_clock_type('cpu')
> > > --        self.assertEqual('cpu', yappi.get_clock_type())
> > > --        clock_info = yappi.get_clock_info()
> > > --        self.assertTrue('api' in clock_info)
> > > --        self.assertTrue('resolution' in clock_info)
> > > --
> > > --        yappi.set_clock_type('wall')
> > > --        self.assertEqual('wall', yappi.get_clock_type())
> > > --
> > > --        t0 = yappi.get_clock_time()
> > > --        time.sleep(0.1)
> > > --        duration = yappi.get_clock_time() - t0
> > > --        self.assertTrue(0.05 < duration < 0.3)
> > > --
> > > --    def test_profile_decorator(self):
> > > --
> > > --        def aggregate(func, stats):
> > > --            fname = "tests/%s.profile" % (func.__name__)
> > > --            try:
> > > --                stats.add(fname)
> > > --            except IOError:
> > > --                pass
> > > --            stats.save(fname)
> > > --            raise Exception("messing around")
> > > --
> > > --        @yappi.profile(return_callback=aggregate)
> > > --        def a(x, y):
> > > --            if x + y == 25:
> > > --                raise Exception("")
> > > --            return x + y
> > > --
> > > --        def b():
> > > --            pass
> > > --
> > > --        try:
> > > --            os.remove(
> > > --                "tests/a.profile"
> > > --            )  # remove the one from prev test, if available
> > > --        except:
> > > --            pass
> > > --
> > > --        # global profile is on to mess things up
> > > --        yappi.start()
> > > --        b()
> > > --
> > > --        # assert functionality and call function at same time
> > > --        try:
> > > --            self.assertEqual(a(1, 2), 3)
> > > --        except:
> > > --            pass
> > > --        try:
> > > --            self.assertEqual(a(2, 5), 7)
> > > --        except:
> > > --            pass
> > > --        try:
> > > --            a(4, 21)
> > > --        except:
> > > --            pass
> > > --        stats = yappi.get_func_stats().add("tests/a.profile")
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        self.assertEqual(fsa.ncall, 3)
> > > --        self.assertEqual(len(stats), 1)  # b() should be cleared out.
> > > --
> > > --        @yappi.profile(return_callback=aggregate)
> > > --        def count_down_rec(n):
> > > --            if n == 0:
> > > --                return
> > > --            count_down_rec(n - 1)
> > > --
> > > --        try:
> > > --            os.remove(
> > > --                "tests/count_down_rec.profile"
> > > --            )  # remove the one from prev test, if available
> > > --        except:
> > > --            pass
> > > --
> > > --        try:
> > > --            count_down_rec(4)
> > > --        except:
> > > --            pass
> > > --        try:
> > > --            count_down_rec(3)
> > > --        except:
> > > --            pass
> > > --
> > > --        stats = yappi.YFuncStats("tests/count_down_rec.profile")
> > > --        fsrec = utils.find_stat_by_name(stats, 'count_down_rec')
> > > --        self.assertEqual(fsrec.ncall, 9)
> > > --        self.assertEqual(fsrec.nactualcall, 2)
> > > --
> > > --    def test_strip_dirs(self):
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        stats = utils.run_and_get_func_stats(a, )
> > > --        stats.strip_dirs()
> > > --        fsa = utils.find_stat_by_name(stats, "a")
> > > --        self.assertEqual(fsa.module, os.path.basename(fsa.module))
> > > --
> > > --    @unittest.skipIf(os.name == "nt", "do not run on Windows")
> > > --    def test_run_as_script(self):
> > > --        import re
> > > --        p = subprocess.Popen(
> > > --            ['yappi', os.path.join('./tests', 'run_as_script.py')],
> > > --            stdout=subprocess.PIPE
> > > --        )
> > > --        out, err = p.communicate()
> > > --        self.assertEqual(p.returncode, 0)
> > > --        func_stats, thread_stats = re.split(
> > > --            b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out
> > > --        )
> > > --        self.assertTrue(b'FancyThread' in thread_stats)
> > > --
> > > --    def test_yappi_overhead(self):
> > > --        LOOP_COUNT = 100000
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        def b():
> > > --            for i in range(LOOP_COUNT):
> > > --                a()
> > > --
> > > --        t0 = time.time()
> > > --        yappi.start()
> > > --        b()
> > > --        yappi.stop()
> > > --        time_with_yappi = time.time() - t0
> > > --        t0 = time.time()
> > > --        b()
> > > --        time_without_yappi = time.time() - t0
> > > --        if time_without_yappi == 0:
> > > --            time_without_yappi = 0.000001
> > > --
> > > --        # in latest v0.82, I calculated this as close to "7.0" in my
> machine.
> > > --        # however, %83 of this overhead is coming from tickcount().
> The other %17
> > > --        # seems to have been evenly distributed to the internal
> bookkeeping
> > > --        # structures/algorithms which seems acceptable. Note that
> our test only
> > > --        # tests one function being profiled at-a-time in a short
> interval.
> > > --        # profiling high number of functions in a small time
> > > --        # is a different beast, (which is pretty unlikely in most
> applications)
> > > --        # So as a conclusion: I cannot see any optimization window
> for Yappi that
> > > --        # is worth implementing as we will only optimize %17 of the
> time.
> > > --        sys.stderr.write("\r\nYappi puts %0.1f times overhead to the
> profiled application in average.\r\n" % \
> > > --            (time_with_yappi / time_without_yappi))
> > > --
> > > --    def test_clear_stats_while_running(self):
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        yappi.start()
> > > --        a()
> > > --        yappi.clear_stats()
> > > --        a()
> > > --        stats = yappi.get_func_stats()
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        self.assertEqual(fsa.ncall, 1)
> > > --
> > > --    def test_generator(self):
> > > --
> > > --        def _gen(n):
> > > --            while (n > 0):
> > > --                yield n
> > > --                n -= 1
> > > --
> > > --        yappi.start()
> > > --        for x in _gen(5):
> > > --            pass
> > > --        self.assertTrue(
> > > --            yappi.convert2pstats(yappi.get_func_stats()) is not None
> > > --        )
> > > --
> > > --    def test_slice_child_stats_and_strip_dirs(self):
> > > --
> > > --        def b():
> > > --            for i in range(10000000):
> > > --                pass
> > > --
> > > --        def a():
> > > --            b()
> > > --
> > > --        yappi.start(builtins=True)
> > > --        a()
> > > --        stats = yappi.get_func_stats()
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        self.assertTrue(fsa.children[0:1] is not None)
> > > --        prev_afullname = fsa.full_name
> > > --        prev_bchildfullname = fsa.children[fsb].full_name
> > > --        stats.strip_dirs()
> > > --        self.assertTrue(len(prev_afullname) > len(fsa.full_name))
> > > --        self.assertTrue(
> > > --            len(prev_bchildfullname) >
> len(fsa.children[fsb].full_name)
> > > --        )
> > > --
> > > --    def test_children_stat_functions(self):
> > > --        _timings = {"a_1": 5, "b_1": 3, "c_1": 1}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        def b():
> > > --            pass
> > > --
> > > --        def c():
> > > --            pass
> > > --
> > > --        def a():
> > > --            b()
> > > --            c()
> > > --
> > > --        yappi.start()
> > > --        a()
> > > --        b()  # non-child call
> > > --        c()  # non-child call
> > > --        stats = yappi.get_func_stats()
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        childs_of_a = fsa.children.get().sort("tavg", "desc")
> > > --        prev_item = None
> > > --        for item in childs_of_a:
> > > --            if prev_item:
> > > --                self.assertTrue(prev_item.tavg > item.tavg)
> > > --            prev_item = item
> > > --        childs_of_a.sort("name", "desc")
> > > --        prev_item = None
> > > --        for item in childs_of_a:
> > > --            if prev_item:
> > > --                self.assertTrue(prev_item.name > item.name)
> > > --            prev_item = item
> > > --        childs_of_a.clear()
> > > --        self.assertTrue(childs_of_a.empty())
> > > --
> > > --    def test_no_stats_different_clock_type_load(self):
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        yappi.start()
> > > --        a()
> > > --        yappi.stop()
> > > --        yappi.get_func_stats().save("tests/ystats1.ys")
> > > --        yappi.clear_stats()
> > > --        yappi.set_clock_type("WALL")
> > > --        yappi.start()
> > > --        yappi.stop()
> > > --        stats = yappi.get_func_stats().add("tests/ystats1.ys")
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        self.assertTrue(fsa is not None)
> > > --
> > > --    def test_subsequent_profile(self):
> > > --        _timings = {"a_1": 1, "b_1": 1}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        def b():
> > > --            pass
> > > --
> > > --        yappi.start()
> > > --        a()
> > > --        yappi.stop()
> > > --        yappi.start()
> > > --        b()
> > > --        yappi.stop()
> > > --        stats = yappi.get_func_stats()
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        self.assertTrue(fsa is not None)
> > > --        self.assertTrue(fsb is not None)
> > > --        self.assertEqual(fsa.ttot, 1)
> > > --        self.assertEqual(fsb.ttot, 1)
> > > --
> > > --    def test_lambda(self):
> > > --        f = lambda: time.sleep(0.3)
> > > --        yappi.set_clock_type("wall")
> > > --        yappi.start()
> > > --        f()
> > > --        stats = yappi.get_func_stats()
> > > --        fsa = utils.find_stat_by_name(stats, '<lambda>')
> > > --        self.assertTrue(fsa.ttot > 0.1)
> > > --
> > > --    def test_module_stress(self):
> > > --        self.assertEqual(yappi.is_running(), False)
> > > --
> > > --        yappi.start()
> > > --        yappi.clear_stats()
> > > --        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
> > > --
> > > --        yappi.stop()
> > > --        yappi.clear_stats()
> > > --        yappi.set_clock_type("cpu")
> > > --        self.assertRaises(yappi.YappiError, yappi.set_clock_type,
> "dummy")
> > > --        self.assertEqual(yappi.is_running(), False)
> > > --        yappi.clear_stats()
> > > --        yappi.clear_stats()
> > > --
> > > --    def test_stat_sorting(self):
> > > --        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        self._ncall = 1
> > > --
> > > --        def a():
> > > --            b()
> > > --
> > > --        def b():
> > > --            if self._ncall == 2:
> > > --                return
> > > --            self._ncall += 1
> > > --            a()
> > > --
> > > --        stats = utils.run_and_get_func_stats(a)
> > > --        stats = stats.sort("totaltime", "desc")
> > > --        prev_stat = None
> > > --        for stat in stats:
> > > --            if prev_stat:
> > > --                self.assertTrue(prev_stat.ttot >= stat.ttot)
> > > --            prev_stat = stat
> > > --        stats = stats.sort("totaltime", "asc")
> > > --        prev_stat = None
> > > --        for stat in stats:
> > > --            if prev_stat:
> > > --                self.assertTrue(prev_stat.ttot <= stat.ttot)
> > > --            prev_stat = stat
> > > --        stats = stats.sort("avgtime", "asc")
> > > --        prev_stat = None
> > > --        for stat in stats:
> > > --            if prev_stat:
> > > --                self.assertTrue(prev_stat.tavg <= stat.tavg)
> > > --            prev_stat = stat
> > > --        stats = stats.sort("name", "asc")
> > > --        prev_stat = None
> > > --        for stat in stats:
> > > --            if prev_stat:
> > > --                self.assertTrue(prev_stat.name <= stat.name)
> > > --            prev_stat = stat
> > > --        stats = stats.sort("subtime", "asc")
> > > --        prev_stat = None
> > > --        for stat in stats:
> > > --            if prev_stat:
> > > --                self.assertTrue(prev_stat.tsub <= stat.tsub)
> > > --            prev_stat = stat
> > > --
> > > --        self.assertRaises(
> > > --            yappi.YappiError, stats.sort, "invalid_func_sorttype_arg"
> > > --        )
> > > --        self.assertRaises(
> > > --            yappi.YappiError, stats.sort, "totaltime",
> > > --            "invalid_func_sortorder_arg"
> > > --        )
> > > --
> > > --    def test_start_flags(self):
> > > --        self.assertEqual(_yappi._get_start_flags(), None)
> > > --        yappi.start()
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        a()
> > > --
> self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
> > > --
> self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
> > > --        self.assertEqual(len(yappi.get_thread_stats()), 1)
> > > --
> > > --    def test_builtin_profiling(self):
> > > --
> > > --        def a():
> > > --            time.sleep(0.4)  # is a builtin function
> > > --
> > > --        yappi.set_clock_type('wall')
> > > --
> > > --        yappi.start(builtins=True)
> > > --        a()
> > > --        stats = yappi.get_func_stats()
> > > --        fsa = utils.find_stat_by_name(stats, 'sleep')
> > > --        self.assertTrue(fsa is not None)
> > > --        self.assertTrue(fsa.ttot > 0.3)
> > > --        yappi.stop()
> > > --        yappi.clear_stats()
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        yappi.start()
> > > --        t = threading.Thread(target=a)
> > > --        t.start()
> > > --        t.join()
> > > --        stats = yappi.get_func_stats()
> > > --
> > > --    def test_singlethread_profiling(self):
> > > --        yappi.set_clock_type('wall')
> > > --
> > > --        def a():
> > > --            time.sleep(0.2)
> > > --
> > > --        class Worker1(threading.Thread):
> > > --
> > > --            def a(self):
> > > --                time.sleep(0.3)
> > > --
> > > --            def run(self):
> > > --                self.a()
> > > --
> > > --        yappi.start(profile_threads=False)
> > > --
> > > --        c = Worker1()
> > > --        c.start()
> > > --        c.join()
> > > --        a()
> > > --        stats = yappi.get_func_stats()
> > > --        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
> > > --        fsa2 = utils.find_stat_by_name(stats, 'a')
> > > --        self.assertTrue(fsa1 is None)
> > > --        self.assertTrue(fsa2 is not None)
> > > --        self.assertTrue(fsa2.ttot > 0.1)
> > > --
> > > --    def test_run(self):
> > > --
> > > --        def profiled():
> > > --            pass
> > > --
> > > --        yappi.clear_stats()
> > > --        try:
> > > --            with yappi.run():
> > > --                profiled()
> > > --            stats = yappi.get_func_stats()
> > > --        finally:
> > > --            yappi.clear_stats()
> > > --
> > > --        self.assertIsNotNone(utils.find_stat_by_name(stats,
> 'profiled'))
> > > --
> > > --    def test_run_recursive(self):
> > > --
> > > --        def profiled():
> > > --            pass
> > > --
> > > --        def not_profiled():
> > > --            pass
> > > --
> > > --        yappi.clear_stats()
> > > --        try:
> > > --            with yappi.run():
> > > --                with yappi.run():
> > > --                    profiled()
> > > --                # Profiling stopped here
> > > --                not_profiled()
> > > --            stats = yappi.get_func_stats()
> > > --        finally:
> > > --            yappi.clear_stats()
> > > --
> > > --        self.assertIsNotNone(utils.find_stat_by_name(stats,
> 'profiled'))
> > > --        self.assertIsNone(utils.find_stat_by_name(stats,
> 'not_profiled'))
> > > --
> > > --
> > > --class StatSaveScenarios(utils.YappiUnitTestCase):
> > > --
> > > --    def test_pstats_conversion(self):
> > > --
> > > --        def pstat_id(fs):
> > > --            return (fs.module, fs.lineno, fs.name)
> > > --
> > > --        def a():
> > > --            d()
> > > --
> > > --        def b():
> > > --            d()
> > > --
> > > --        def c():
> > > --            pass
> > > --
> > > --        def d():
> > > --            pass
> > > --
> > > --        _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2}
> > > --        _yappi._set_test_timings(_timings)
> > > --        stats = utils.run_and_get_func_stats(a, )
> > > --        stats.strip_dirs()
> > > --        stats.save("tests/a1.pstats", type="pstat")
> > > --        fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a"))
> > > --        fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d"))
> > > --        yappi.clear_stats()
> > > --        _yappi._set_test_timings(_timings)
> > > --        stats = utils.run_and_get_func_stats(a, )
> > > --        stats.strip_dirs()
> > > --        stats.save("tests/a2.pstats", type="pstat")
> > > --        yappi.clear_stats()
> > > --        _yappi._set_test_timings(_timings)
> > > --        stats = utils.run_and_get_func_stats(b, )
> > > --        stats.strip_dirs()
> > > --        stats.save("tests/b1.pstats", type="pstat")
> > > --        fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b"))
> > > --        yappi.clear_stats()
> > > --        _yappi._set_test_timings(_timings)
> > > --        stats = utils.run_and_get_func_stats(c, )
> > > --        stats.strip_dirs()
> > > --        stats.save("tests/c1.pstats", type="pstat")
> > > --        fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c"))
> > > --
> > > --        # merge saved stats and check pstats values are correct
> > > --        import pstats
> > > --        p = pstats.Stats(
> > > --            'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats',
> > > --            'tests/c1.pstats'
> > > --        )
> > > --        p.strip_dirs()
> > > --        # ct = ttot, tt = tsub
> > > --        (cc, nc, tt, ct, callers) = p.stats[fsa_pid]
> > > --        self.assertEqual(cc, nc, 2)
> > > --        self.assertEqual(tt, 20)
> > > --        self.assertEqual(ct, 24)
> > > --        (cc, nc, tt, ct, callers) = p.stats[fsd_pid]
> > > --        self.assertEqual(cc, nc, 3)
> > > --        self.assertEqual(tt, 6)
> > > --        self.assertEqual(ct, 6)
> > > --        self.assertEqual(len(callers), 2)
> > > --        (cc, nc, tt, ct) = callers[fsa_pid]
> > > --        self.assertEqual(cc, nc, 2)
> > > --        self.assertEqual(tt, 4)
> > > --        self.assertEqual(ct, 4)
> > > --        (cc, nc, tt, ct) = callers[fsb_pid]
> > > --        self.assertEqual(cc, nc, 1)
> > > --        self.assertEqual(tt, 2)
> > > --        self.assertEqual(ct, 2)
> > > --
> > > --    def test_merge_stats(self):
> > > --        _timings = {
> > > --            "a_1": 15,
> > > --            "b_1": 14,
> > > --            "c_1": 12,
> > > --            "d_1": 10,
> > > --            "e_1": 9,
> > > --            "f_1": 7,
> > > --            "g_1": 6,
> > > --            "h_1": 5,
> > > --            "i_1": 1
> > > --        }
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        def a():
> > > --            b()
> > > --
> > > --        def b():
> > > --            c()
> > > --
> > > --        def c():
> > > --            d()
> > > --
> > > --        def d():
> > > --            e()
> > > --
> > > --        def e():
> > > --            f()
> > > --
> > > --        def f():
> > > --            g()
> > > --
> > > --        def g():
> > > --            h()
> > > --
> > > --        def h():
> > > --            i()
> > > --
> > > --        def i():
> > > --            pass
> > > --
> > > --        yappi.start()
> > > --        a()
> > > --        a()
> > > --        yappi.stop()
> > > --        stats = yappi.get_func_stats()
> > > --        self.assertRaises(
> > > --            NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE"
> > > --        )
> > > --        stats.save("tests/ystats2.ys")
> > > --        yappi.clear_stats()
> > > --        _yappi._set_test_timings(_timings)
> > > --        yappi.start()
> > > --        a()
> > > --        stats = yappi.get_func_stats().add("tests/ystats2.ys")
> > > --        fsa = utils.find_stat_by_name(stats, "a")
> > > --        fsb = utils.find_stat_by_name(stats, "b")
> > > --        fsc = utils.find_stat_by_name(stats, "c")
> > > --        fsd = utils.find_stat_by_name(stats, "d")
> > > --        fse = utils.find_stat_by_name(stats, "e")
> > > --        fsf = utils.find_stat_by_name(stats, "f")
> > > --        fsg = utils.find_stat_by_name(stats, "g")
> > > --        fsh = utils.find_stat_by_name(stats, "h")
> > > --        fsi = utils.find_stat_by_name(stats, "i")
> > > --        self.assertEqual(fsa.ttot, 45)
> > > --        self.assertEqual(fsa.ncall, 3)
> > > --        self.assertEqual(fsa.nactualcall, 3)
> > > --        self.assertEqual(fsa.tsub, 3)
> > > --        self.assertEqual(fsa.children[fsb].ttot, fsb.ttot)
> > > --        self.assertEqual(fsa.children[fsb].tsub, fsb.tsub)
> > > --        self.assertEqual(fsb.children[fsc].ttot, fsc.ttot)
> > > --        self.assertEqual(fsb.children[fsc].tsub, fsc.tsub)
> > > --        self.assertEqual(fsc.tsub, 6)
> > > --        self.assertEqual(fsc.children[fsd].ttot, fsd.ttot)
> > > --        self.assertEqual(fsc.children[fsd].tsub, fsd.tsub)
> > > --        self.assertEqual(fsd.children[fse].ttot, fse.ttot)
> > > --        self.assertEqual(fsd.children[fse].tsub, fse.tsub)
> > > --        self.assertEqual(fse.children[fsf].ttot, fsf.ttot)
> > > --        self.assertEqual(fse.children[fsf].tsub, fsf.tsub)
> > > --        self.assertEqual(fsf.children[fsg].ttot, fsg.ttot)
> > > --        self.assertEqual(fsf.children[fsg].tsub, fsg.tsub)
> > > --        self.assertEqual(fsg.ttot, 18)
> > > --        self.assertEqual(fsg.tsub, 3)
> > > --        self.assertEqual(fsg.children[fsh].ttot, fsh.ttot)
> > > --        self.assertEqual(fsg.children[fsh].tsub, fsh.tsub)
> > > --        self.assertEqual(fsh.ttot, 15)
> > > --        self.assertEqual(fsh.tsub, 12)
> > > --        self.assertEqual(fsh.tavg, 5)
> > > --        self.assertEqual(fsh.children[fsi].ttot, fsi.ttot)
> > > --        self.assertEqual(fsh.children[fsi].tsub, fsi.tsub)
> > > --        #stats.debug_print()
> > > --
> > > --    def test_merge_multithreaded_stats(self):
> > > --        import _yappi
> > > --        timings = {"a_1": 2, "b_1": 1}
> > > --        _yappi._set_test_timings(timings)
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        def b():
> > > --            pass
> > > --
> > > --        yappi.start()
> > > --        t = threading.Thread(target=a)
> > > --        t.start()
> > > --        t.join()
> > > --        t = threading.Thread(target=b)
> > > --        t.start()
> > > --        t.join()
> > > --        yappi.get_func_stats().save("tests/ystats1.ys")
> > > --        yappi.clear_stats()
> > > --        _yappi._set_test_timings(timings)
> > > --        self.assertEqual(len(yappi.get_func_stats()), 0)
> > > --        self.assertEqual(len(yappi.get_thread_stats()), 1)
> > > --        t = threading.Thread(target=a)
> > > --        t.start()
> > > --        t.join()
> > > --
> > > --
> self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
> > > --
> self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
> > > --        yappi.get_func_stats().save("tests/ystats2.ys")
> > > --
> > > --        stats = yappi.YFuncStats([
> > > --            "tests/ystats1.ys",
> > > --            "tests/ystats2.ys",
> > > --        ])
> > > --        fsa = utils.find_stat_by_name(stats, "a")
> > > --        fsb = utils.find_stat_by_name(stats, "b")
> > > --        self.assertEqual(fsa.ncall, 2)
> > > --        self.assertEqual(fsb.ncall, 1)
> > > --        self.assertEqual(fsa.tsub, fsa.ttot, 4)
> > > --        self.assertEqual(fsb.tsub, fsb.ttot, 1)
> > > --
> > > --    def test_merge_load_different_clock_types(self):
> > > --        yappi.start(builtins=True)
> > > --
> > > --        def a():
> > > --            b()
> > > --
> > > --        def b():
> > > --            c()
> > > --
> > > --        def c():
> > > --            pass
> > > --
> > > --        t = threading.Thread(target=a)
> > > --        t.start()
> > > --        t.join()
> > > --        yappi.get_func_stats().sort("name",
> "asc").save("tests/ystats1.ys")
> > > --        yappi.stop()
> > > --        yappi.clear_stats()
> > > --        yappi.start(builtins=False)
> > > --        t = threading.Thread(target=a)
> > > --        t.start()
> > > --        t.join()
> > > --        yappi.get_func_stats().save("tests/ystats2.ys")
> > > --        yappi.stop()
> > > --        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
> > > --        yappi.clear_stats()
> > > --        yappi.set_clock_type("wall")
> > > --        yappi.start()
> > > --        t = threading.Thread(target=a)
> > > --        t.start()
> > > --        t.join()
> > > --        yappi.get_func_stats().save("tests/ystats3.ys")
> > > --        self.assertRaises(
> > > --            yappi.YappiError,
> > > --            yappi.YFuncStats().add("tests/ystats1.ys").add,
> "tests/ystats3.ys"
> > > --        )
> > > --        stats = yappi.YFuncStats(["tests/ystats1.ys",
> > > --                                  "tests/ystats2.ys"]).sort("name")
> > > --        fsa = utils.find_stat_by_name(stats, "a")
> > > --        fsb = utils.find_stat_by_name(stats, "b")
> > > --        fsc = utils.find_stat_by_name(stats, "c")
> > > --        self.assertEqual(fsa.ncall, 2)
> > > --        self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall)
> > > --
> > > --    def test_merge_aabab_aabbc(self):
> > > --        _timings = {
> > > --            "a_1": 15,
> > > --            "a_2": 14,
> > > --            "b_1": 12,
> > > --            "a_3": 10,
> > > --            "b_2": 9,
> > > --            "c_1": 4
> > > --        }
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        def a():
> > > --            if self._ncall == 1:
> > > --                self._ncall += 1
> > > --                a()
> > > --            elif self._ncall == 5:
> > > --                self._ncall += 1
> > > --                a()
> > > --            else:
> > > --                b()
> > > --
> > > --        def b():
> > > --            if self._ncall == 2:
> > > --                self._ncall += 1
> > > --                a()
> > > --            elif self._ncall == 6:
> > > --                self._ncall += 1
> > > --                b()
> > > --            elif self._ncall == 7:
> > > --                c()
> > > --            else:
> > > --                return
> > > --
> > > --        def c():
> > > --            pass
> > > --
> > > --        self._ncall = 1
> > > --        stats = utils.run_and_get_func_stats(a, )
> > > --        stats.save("tests/ystats1.ys")
> > > --        yappi.clear_stats()
> > > --        _yappi._set_test_timings(_timings)
> > > --        #stats.print_all()
> > > --
> > > --        self._ncall = 5
> > > --        stats = utils.run_and_get_func_stats(a, )
> > > --        stats.save("tests/ystats2.ys")
> > > --
> > > --        #stats.print_all()
> > > --
> > > --        def a():  # same name but another function(code object)
> > > --            pass
> > > --
> > > --        yappi.start()
> > > --        a()
> > > --        stats = yappi.get_func_stats().add(
> > > --            ["tests/ystats1.ys", "tests/ystats2.ys"]
> > > --        )
> > > --        #stats.print_all()
> > > --        self.assertEqual(len(stats), 4)
> > > --
> > > --        fsa = None
> > > --        for stat in stats:
> > > --            if stat.name == "a" and stat.ttot == 45:
> > > --                fsa = stat
> > > --                break
> > > --        self.assertTrue(fsa is not None)
> > > --
> > > --        self.assertEqual(fsa.ncall, 7)
> > > --        self.assertEqual(fsa.nactualcall, 3)
> > > --        self.assertEqual(fsa.ttot, 45)
> > > --        self.assertEqual(fsa.tsub, 10)
> > > --        fsb = utils.find_stat_by_name(stats, "b")
> > > --        fsc = utils.find_stat_by_name(stats, "c")
> > > --        self.assertEqual(fsb.ncall, 6)
> > > --        self.assertEqual(fsb.nactualcall, 3)
> > > --        self.assertEqual(fsb.ttot, 36)
> > > --        self.assertEqual(fsb.tsub, 27)
> > > --        self.assertEqual(fsb.tavg, 6)
> > > --        self.assertEqual(fsc.ttot, 8)
> > > --        self.assertEqual(fsc.tsub, 8)
> > > --        self.assertEqual(fsc.tavg, 4)
> > > --        self.assertEqual(fsc.nactualcall, fsc.ncall, 2)
> > > --
> > > --
> > > --class MultithreadedScenarios(utils.YappiUnitTestCase):
> > > --
> > > --    def test_issue_32(self):
> > > --        '''
> > > --        Start yappi from different thread and we get Internal
> Error(15) as
> > > --        the current_ctx_id() called while enumerating the threads in
> start()
> > > --        and as it does not swap to the enumerated ThreadState* the
> THreadState_GetDict()
> > > --        returns wrong object and thus sets an invalid id for the
> _ctx structure.
> > > --
> > > --        When this issue happens multiple Threads have same tid as
> the internal ts_ptr
> > > --        will be same for different contexts. So, let's see if that
> happens
> > > --        '''
> > > --
> > > --        def foo():
> > > --            time.sleep(0.2)
> > > --
> > > --        def bar():
> > > --            time.sleep(0.1)
> > > --
> > > --        def thread_func():
> > > --            yappi.set_clock_type("wall")
> > > --            yappi.start()
> > > --
> > > --            bar()
> > > --
> > > --        t = threading.Thread(target=thread_func)
> > > --        t.start()
> > > --        t.join()
> > > --
> > > --        foo()
> > > --
> > > --        yappi.stop()
> > > --
> > > --        thread_ids = set()
> > > --        for tstat in yappi.get_thread_stats():
> > > --            self.assertTrue(tstat.tid not in thread_ids)
> > > --            thread_ids.add(tstat.tid)
> > > --
> > > --    def test_subsequent_profile(self):
> > > --        WORKER_COUNT = 5
> > > --
> > > --        def a():
> > > --            pass
> > > --
> > > --        def b():
> > > --            pass
> > > --
> > > --        def c():
> > > --            pass
> > > --
> > > --        _timings = {
> > > --            "a_1": 3,
> > > --            "b_1": 2,
> > > --            "c_1": 1,
> > > --        }
> > > --
> > > --        yappi.start()
> > > --
> > > --        def g():
> > > --            pass
> > > --
> > > --        g()
> > > --        yappi.stop()
> > > --        yappi.clear_stats()
> > > --        _yappi._set_test_timings(_timings)
> > > --        yappi.start()
> > > --
> > > --        _dummy = []
> > > --        for i in range(WORKER_COUNT):
> > > --            t = threading.Thread(target=a)
> > > --            t.start()
> > > --            t.join()
> > > --        for i in range(WORKER_COUNT):
> > > --            t = threading.Thread(target=b)
> > > --            t.start()
> > > --            _dummy.append(t)
> > > --            t.join()
> > > --        for i in range(WORKER_COUNT):
> > > --            t = threading.Thread(target=a)
> > > --            t.start()
> > > --            t.join()
> > > --        for i in range(WORKER_COUNT):
> > > --            t = threading.Thread(target=c)
> > > --            t.start()
> > > --            t.join()
> > > --        yappi.stop()
> > > --        yappi.start()
> > > --
> > > --        def f():
> > > --            pass
> > > --
> > > --        f()
> > > --        stats = yappi.get_func_stats()
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        fsc = utils.find_stat_by_name(stats, 'c')
> > > --        self.assertEqual(fsa.ncall, 10)
> > > --        self.assertEqual(fsb.ncall, 5)
> > > --        self.assertEqual(fsc.ncall, 5)
> > > --        self.assertEqual(fsa.ttot, fsa.tsub, 30)
> > > --        self.assertEqual(fsb.ttot, fsb.tsub, 10)
> > > --        self.assertEqual(fsc.ttot, fsc.tsub, 5)
> > > --
> > > --        # MACOSx optimizes by only creating one worker thread
> > > --        self.assertTrue(len(yappi.get_thread_stats()) >= 2)
> > > --
> > > --    def test_basic(self):
> > > --        yappi.set_clock_type('wall')
> > > --
> > > --        def dummy():
> > > --            pass
> > > --
> > > --        def a():
> > > --            time.sleep(0.2)
> > > --
> > > --        class Worker1(threading.Thread):
> > > --
> > > --            def a(self):
> > > --                time.sleep(0.3)
> > > --
> > > --            def run(self):
> > > --                self.a()
> > > --
> > > --        yappi.start(builtins=False, profile_threads=True)
> > > --
> > > --        c = Worker1()
> > > --        c.start()
> > > --        c.join()
> > > --        a()
> > > --        stats = yappi.get_func_stats()
> > > --        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
> > > --        fsa2 = utils.find_stat_by_name(stats, 'a')
> > > --        self.assertTrue(fsa1 is not None)
> > > --        self.assertTrue(fsa2 is not None)
> > > --        self.assertTrue(fsa1.ttot > 0.2)
> > > --        self.assertTrue(fsa2.ttot > 0.1)
> > > --        tstats = yappi.get_thread_stats()
> > > --        self.assertEqual(len(tstats), 2)
> > > --        tsa = utils.find_stat_by_name(tstats, 'Worker1')
> > > --        tsm = utils.find_stat_by_name(tstats, '_MainThread')
> > > --        dummy()  # call dummy to force ctx name to be retrieved
> again.
> > > --        self.assertTrue(tsa is not None)
> > > --        # TODO: I put dummy() to fix below, remove the comments
> after a while.
> > > --        self.assertTrue( # FIX: I see this fails sometimes?
> > > --            tsm is not None,
> > > --            'Could not find "_MainThread". Found: %s' % (',
> '.join(utils.get_stat_names(tstats))))
> > > --
> > > --    def test_ctx_stats(self):
> > > --        from threading import Thread
> > > --        DUMMY_WORKER_COUNT = 5
> > > --        yappi.start()
> > > --
> > > --        class DummyThread(Thread):
> > > --            pass
> > > --
> > > --        def dummy():
> > > --            pass
> > > --
> > > --        def dummy_worker():
> > > --            pass
> > > --
> > > --        for i in range(DUMMY_WORKER_COUNT):
> > > --            t = DummyThread(target=dummy_worker)
> > > --            t.start()
> > > --            t.join()
> > > --        yappi.stop()
> > > --        stats = yappi.get_thread_stats()
> > > --        tsa = utils.find_stat_by_name(stats, "DummyThread")
> > > --        self.assertTrue(tsa is not None)
> > > --        yappi.clear_stats()
> > > --        time.sleep(1.0)
> > > --        _timings = {
> > > --            "a_1": 6,
> > > --            "b_1": 5,
> > > --            "c_1": 3,
> > > --            "d_1": 1,
> > > --            "a_2": 4,
> > > --            "b_2": 3,
> > > --            "c_2": 2,
> > > --            "d_2": 1
> > > --        }
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        class Thread1(Thread):
> > > --            pass
> > > --
> > > --        class Thread2(Thread):
> > > --            pass
> > > --
> > > --        def a():
> > > --            b()
> > > --
> > > --        def b():
> > > --            c()
> > > --
> > > --        def c():
> > > --            d()
> > > --
> > > --        def d():
> > > --            time.sleep(0.6)
> > > --
> > > --        yappi.set_clock_type("wall")
> > > --        yappi.start()
> > > --        t1 = Thread1(target=a)
> > > --        t1.start()
> > > --        t2 = Thread2(target=a)
> > > --        t2.start()
> > > --        t1.join()
> > > --        t2.join()
> > > --        stats = yappi.get_thread_stats()
> > > --
> > > --        # the fist clear_stats clears the context table?
> > > --        tsa = utils.find_stat_by_name(stats, "DummyThread")
> > > --        self.assertTrue(tsa is None)
> > > --
> > > --        tst1 = utils.find_stat_by_name(stats, "Thread1")
> > > --        tst2 = utils.find_stat_by_name(stats, "Thread2")
> > > --        tsmain = utils.find_stat_by_name(stats, "_MainThread")
> > > --        dummy()  # call dummy to force ctx name to be retrieved
> again.
> > > --        self.assertTrue(len(stats) == 3)
> > > --        self.assertTrue(tst1 is not None)
> > > --        self.assertTrue(tst2 is not None)
> > > --        # TODO: I put dummy() to fix below, remove the comments
> after a while.
> > > --        self.assertTrue( # FIX: I see this fails sometimes
> > > --            tsmain is not None,
> > > --            'Could not find "_MainThread". Found: %s' % (',
> '.join(utils.get_stat_names(stats))))
> > > --        self.assertTrue(1.0 > tst2.ttot >= 0.5)
> > > --        self.assertTrue(1.0 > tst1.ttot >= 0.5)
> > > --
> > > --        # test sorting of the ctx stats
> > > --        stats = stats.sort("totaltime", "desc")
> > > --        prev_stat = None
> > > --        for stat in stats:
> > > --            if prev_stat:
> > > --                self.assertTrue(prev_stat.ttot >= stat.ttot)
> > > --            prev_stat = stat
> > > --        stats = stats.sort("totaltime", "asc")
> > > --        prev_stat = None
> > > --        for stat in stats:
> > > --            if prev_stat:
> > > --                self.assertTrue(prev_stat.ttot <= stat.ttot)
> > > --            prev_stat = stat
> > > --        stats = stats.sort("schedcount", "desc")
> > > --        prev_stat = None
> > > --        for stat in stats:
> > > --            if prev_stat:
> > > --                self.assertTrue(prev_stat.sched_count >=
> stat.sched_count)
> > > --            prev_stat = stat
> > > --        stats = stats.sort("name", "desc")
> > > --        prev_stat = None
> > > --        for stat in stats:
> > > --            if prev_stat:
> > > --                self.assertTrue(prev_stat.name.lower() >=
> stat.name.lower())
> > > --            prev_stat = stat
> > > --        self.assertRaises(
> > > --            yappi.YappiError, stats.sort,
> "invalid_thread_sorttype_arg"
> > > --        )
> > > --        self.assertRaises(
> > > --            yappi.YappiError, stats.sort,
> "invalid_thread_sortorder_arg"
> > > --        )
> > > --
> > > --    def test_ctx_stats_cpu(self):
> > > --
> > > --        def get_thread_name():
> > > --            try:
> > > --                return threading.current_thread().name
> > > --            except AttributeError:
> > > --                return "Anonymous"
> > > --
> > > --        def burn_cpu(sec):
> > > --            t0 = yappi.get_clock_time()
> > > --            elapsed = 0
> > > --            while (elapsed < sec):
> > > --                for _ in range(1000):
> > > --                    pass
> > > --                elapsed = yappi.get_clock_time() - t0
> > > --
> > > --        def test():
> > > --
> > > --            ts = []
> > > --            for i in (0.01, 0.05, 0.1):
> > > --                t = threading.Thread(target=burn_cpu, args=(i, ))
> > > --                t.name = "burn_cpu-%s" % str(i)
> > > --                t.start()
> > > --                ts.append(t)
> > > --            for t in ts:
> > > --                t.join()
> > > --
> > > --        yappi.set_clock_type("cpu")
> > > --        yappi.set_context_name_callback(get_thread_name)
> > > --
> > > --        yappi.start()
> > > --
> > > --        test()
> > > --
> > > --        yappi.stop()
> > > --
> > > --        tstats = yappi.get_thread_stats()
> > > --        r1 = '''
> > > --        burn_cpu-0.1      3      123145356058624  0.100105  8
> > > --        burn_cpu-0.05     2      123145361313792  0.050149  8
> > > --        burn_cpu-0.01     1      123145356058624  0.010127  2
> > > --        MainThread        0      4321620864       0.001632  6
> > > --        '''
> > > --        self.assert_ctx_stats_almost_equal(r1, tstats)
> > > --
> > > --    def test_producer_consumer_with_queues(self):
> > > --        # we currently just stress yappi, no functionality test is
> done here.
> > > --        yappi.start()
> > > --        if utils.is_py3x():
> > > --            from queue import Queue
> > > --        else:
> > > --            from Queue import Queue
> > > --        from threading import Thread
> > > --        WORKER_THREAD_COUNT = 50
> > > --        WORK_ITEM_COUNT = 2000
> > > --
> > > --        def worker():
> > > --            while True:
> > > --                item = q.get()
> > > --                # do the work with item
> > > --                q.task_done()
> > > --
> > > --        q = Queue()
> > > --        for i in range(WORKER_THREAD_COUNT):
> > > --            t = Thread(target=worker)
> > > --            t.daemon = True
> > > --            t.start()
> > > --
> > > --        for item in range(WORK_ITEM_COUNT):
> > > --            q.put(item)
> > > --        q.join()  # block until all tasks are done
> > > --        #yappi.get_func_stats().sort("callcount").print_all()
> > > --        yappi.stop()
> > > --
> > > --    def test_temporary_lock_waiting(self):
> > > --        yappi.start()
> > > --        _lock = threading.Lock()
> > > --
> > > --        def worker():
> > > --            _lock.acquire()
> > > --            try:
> > > --                time.sleep(1.0)
> > > --            finally:
> > > --                _lock.release()
> > > --
> > > --        t1 = threading.Thread(target=worker)
> > > --        t2 = threading.Thread(target=worker)
> > > --        t1.start()
> > > --        t2.start()
> > > --        t1.join()
> > > --        t2.join()
> > > --        #yappi.get_func_stats().sort("callcount").print_all()
> > > --        yappi.stop()
> > > --
> > > --    @unittest.skipIf(os.name != "posix", "requires Posix compliant
> OS")
> > > --    def test_signals_with_blocking_calls(self):
> > > --        import signal, os, time
> > > --
> > > --        # just to verify if signal is handled correctly and
> stats/yappi are not corrupted.
> > > --        def handler(signum, frame):
> > > --            raise Exception("Signal handler executed!")
> > > --
> > > --        yappi.start()
> > > --        signal.signal(signal.SIGALRM, handler)
> > > --        signal.alarm(1)
> > > --        self.assertRaises(Exception, time.sleep, 2)
> > > --        stats = yappi.get_func_stats()
> > > --        fsh = utils.find_stat_by_name(stats, "handler")
> > > --        self.assertTrue(fsh is not None)
> > > --
> > > --    @unittest.skipIf(not sys.version_info >= (3, 2), "requires
> Python 3.2")
> > > --    def test_concurrent_futures(self):
> > > --        yappi.start()
> > > --        from concurrent.futures import ThreadPoolExecutor
> > > --        with ThreadPoolExecutor(max_workers=5) as executor:
> > > --            f = executor.submit(pow, 5, 2)
> > > --            self.assertEqual(f.result(), 25)
> > > --        time.sleep(1.0)
> > > --        yappi.stop()
> > > --
> > > --    @unittest.skipIf(not sys.version_info >= (3, 2), "requires
> Python 3.2")
> > > --    def test_barrier(self):
> > > --        yappi.start()
> > > --        b = threading.Barrier(2, timeout=1)
> > > --
> > > --        def worker():
> > > --            try:
> > > --                b.wait()
> > > --            except threading.BrokenBarrierError:
> > > --                pass
> > > --            except Exception:
> > > --                raise Exception("BrokenBarrierError not raised")
> > > --
> > > --        t1 = threading.Thread(target=worker)
> > > --        t1.start()
> > > --        #b.wait()
> > > --        t1.join()
> > > --        yappi.stop()
> > > --
> > > --
> > > --class NonRecursiveFunctions(utils.YappiUnitTestCase):
> > > --
> > > --    def test_abcd(self):
> > > --        _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        def a():
> > > --            b()
> > > --
> > > --        def b():
> > > --            c()
> > > --
> > > --        def c():
> > > --            d()
> > > --
> > > --        def d():
> > > --            pass
> > > --
> > > --        stats = utils.run_and_get_func_stats(a)
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        fsc = utils.find_stat_by_name(stats, 'c')
> > > --        fsd = utils.find_stat_by_name(stats, 'd')
> > > --        cfsab = fsa.children[fsb]
> > > --        cfsbc = fsb.children[fsc]
> > > --        cfscd = fsc.children[fsd]
> > > --
> > > --        self.assertEqual(fsa.ttot, 6)
> > > --        self.assertEqual(fsa.tsub, 1)
> > > --        self.assertEqual(fsb.ttot, 5)
> > > --        self.assertEqual(fsb.tsub, 2)
> > > --        self.assertEqual(fsc.ttot, 3)
> > > --        self.assertEqual(fsc.tsub, 2)
> > > --        self.assertEqual(fsd.ttot, 1)
> > > --        self.assertEqual(fsd.tsub, 1)
> > > --        self.assertEqual(cfsab.ttot, 5)
> > > --        self.assertEqual(cfsab.tsub, 2)
> > > --        self.assertEqual(cfsbc.ttot, 3)
> > > --        self.assertEqual(cfsbc.tsub, 2)
> > > --        self.assertEqual(cfscd.ttot, 1)
> > > --        self.assertEqual(cfscd.tsub, 1)
> > > --
> > > --    def test_stop_in_middle(self):
> > > --        _timings = {"a_1": 6, "b_1": 4}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        def a():
> > > --            b()
> > > --            yappi.stop()
> > > --
> > > --        def b():
> > > --            time.sleep(0.2)
> > > --
> > > --        yappi.start()
> > > --        a()
> > > --        stats = yappi.get_func_stats()
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --
> > > --        self.assertEqual(fsa.ncall, 1)
> > > --        self.assertEqual(fsa.nactualcall, 0)
> > > --        self.assertEqual(fsa.ttot, 0)  # no call_leave called
> > > --        self.assertEqual(fsa.tsub, 0)  # no call_leave called
> > > --        self.assertEqual(fsb.ttot, 4)
> > > --
> > > --
> > > --class RecursiveFunctions(utils.YappiUnitTestCase):
> > > --
> > > --    def test_fibonacci(self):
> > > --
> > > --        def fib(n):
> > > --            if n > 1:
> > > --                return fib(n - 1) + fib(n - 2)
> > > --            else:
> > > --                return n
> > > --
> > > --        stats = utils.run_and_get_func_stats(fib, 22)
> > > --        fs = utils.find_stat_by_name(stats, 'fib')
> > > --        self.assertEqual(fs.ncall, 57313)
> > > --        self.assertEqual(fs.ttot, fs.tsub)
> > > --
> > > --    def test_abcadc(self):
> > > --        _timings = {
> > > --            "a_1": 20,
> > > --            "b_1": 19,
> > > --            "c_1": 17,
> > > --            "a_2": 13,
> > > --            "d_1": 12,
> > > --            "c_2": 10,
> > > --            "a_3": 5
> > > --        }
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        def a(n):
> > > --            if n == 3:
> > > --                return
> > > --            if n == 1 + 1:
> > > --                d(n)
> > > --            else:
> > > --                b(n)
> > > --
> > > --        def b(n):
> > > --            c(n)
> > > --
> > > --        def c(n):
> > > --            a(n + 1)
> > > --
> > > --        def d(n):
> > > --            c(n)
> > > --
> > > --        stats = utils.run_and_get_func_stats(a, 1)
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        fsc = utils.find_stat_by_name(stats, 'c')
> > > --        fsd = utils.find_stat_by_name(stats, 'd')
> > > --        self.assertEqual(fsa.ncall, 3)
> > > --        self.assertEqual(fsa.nactualcall, 1)
> > > --        self.assertEqual(fsa.ttot, 20)
> > > --        self.assertEqual(fsa.tsub, 7)
> > > --        self.assertEqual(fsb.ttot, 19)
> > > --        self.assertEqual(fsb.tsub, 2)
> > > --        self.assertEqual(fsc.ttot, 17)
> > > --        self.assertEqual(fsc.tsub, 9)
> > > --        self.assertEqual(fsd.ttot, 12)
> > > --        self.assertEqual(fsd.tsub, 2)
> > > --        cfsca = fsc.children[fsa]
> > > --        self.assertEqual(cfsca.nactualcall, 0)
> > > --        self.assertEqual(cfsca.ncall, 2)
> > > --        self.assertEqual(cfsca.ttot, 13)
> > > --        self.assertEqual(cfsca.tsub, 6)
> > > --
> > > --    def test_aaaa(self):
> > > --        _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        def d(n):
> > > --            if n == 3:
> > > --                return
> > > --            d(n + 1)
> > > --
> > > --        stats = utils.run_and_get_func_stats(d, 0)
> > > --        fsd = utils.find_stat_by_name(stats, 'd')
> > > --        self.assertEqual(fsd.ncall, 4)
> > > --        self.assertEqual(fsd.nactualcall, 1)
> > > --        self.assertEqual(fsd.ttot, 9)
> > > --        self.assertEqual(fsd.tsub, 9)
> > > --        cfsdd = fsd.children[fsd]
> > > --        self.assertEqual(cfsdd.ttot, 7)
> > > --        self.assertEqual(cfsdd.tsub, 7)
> > > --        self.assertEqual(cfsdd.ncall, 3)
> > > --        self.assertEqual(cfsdd.nactualcall, 0)
> > > --
> > > --    def test_abcabc(self):
> > > --        _timings = {
> > > --            "a_1": 20,
> > > --            "b_1": 19,
> > > --            "c_1": 17,
> > > --            "a_2": 13,
> > > --            "b_2": 11,
> > > --            "c_2": 9,
> > > --            "a_3": 6
> > > --        }
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        def a(n):
> > > --            if n == 3:
> > > --                return
> > > --            else:
> > > --                b(n)
> > > --
> > > --        def b(n):
> > > --            c(n)
> > > --
> > > --        def c(n):
> > > --            a(n + 1)
> > > --
> > > --        stats = utils.run_and_get_func_stats(a, 1)
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        fsc = utils.find_stat_by_name(stats, 'c')
> > > --        self.assertEqual(fsa.ncall, 3)
> > > --        self.assertEqual(fsa.nactualcall, 1)
> > > --        self.assertEqual(fsa.ttot, 20)
> > > --        self.assertEqual(fsa.tsub, 9)
> > > --        self.assertEqual(fsb.ttot, 19)
> > > --        self.assertEqual(fsb.tsub, 4)
> > > --        self.assertEqual(fsc.ttot, 17)
> > > --        self.assertEqual(fsc.tsub, 7)
> > > --        cfsab = fsa.children[fsb]
> > > --        cfsbc = fsb.children[fsc]
> > > --        cfsca = fsc.children[fsa]
> > > --        self.assertEqual(cfsab.ttot, 19)
> > > --        self.assertEqual(cfsab.tsub, 4)
> > > --        self.assertEqual(cfsbc.ttot, 17)
> > > --        self.assertEqual(cfsbc.tsub, 7)
> > > --        self.assertEqual(cfsca.ttot, 13)
> > > --        self.assertEqual(cfsca.tsub, 8)
> > > --
> > > --    def test_abcbca(self):
> > > --        _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2":
> 2, "a_2": 1}
> > > --        _yappi._set_test_timings(_timings)
> > > --        self._ncall = 1
> > > --
> > > --        def a():
> > > --            if self._ncall == 1:
> > > --                b()
> > > --            else:
> > > --                return
> > > --
> > > --        def b():
> > > --            c()
> > > --
> > > --        def c():
> > > --            if self._ncall == 1:
> > > --                self._ncall += 1
> > > --                b()
> > > --            else:
> > > --                a()
> > > --
> > > --        stats = utils.run_and_get_func_stats(a)
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        fsc = utils.find_stat_by_name(stats, 'c')
> > > --        cfsab = fsa.children[fsb]
> > > --        cfsbc = fsb.children[fsc]
> > > --        cfsca = fsc.children[fsa]
> > > --        self.assertEqual(fsa.ttot, 10)
> > > --        self.assertEqual(fsa.tsub, 2)
> > > --        self.assertEqual(fsb.ttot, 9)
> > > --        self.assertEqual(fsb.tsub, 4)
> > > --        self.assertEqual(fsc.ttot, 7)
> > > --        self.assertEqual(fsc.tsub, 4)
> > > --        self.assertEqual(cfsab.ttot, 9)
> > > --        self.assertEqual(cfsab.tsub, 2)
> > > --        self.assertEqual(cfsbc.ttot, 7)
> > > --        self.assertEqual(cfsbc.tsub, 4)
> > > --        self.assertEqual(cfsca.ttot, 1)
> > > --        self.assertEqual(cfsca.tsub, 1)
> > > --        self.assertEqual(cfsca.ncall, 1)
> > > --        self.assertEqual(cfsca.nactualcall, 0)
> > > --
> > > --    def test_aabccb(self):
> > > --        _timings = {
> > > --            "a_1": 13,
> > > --            "a_2": 11,
> > > --            "b_1": 9,
> > > --            "c_1": 5,
> > > --            "c_2": 3,
> > > --            "b_2": 1
> > > --        }
> > > --        _yappi._set_test_timings(_timings)
> > > --        self._ncall = 1
> > > --
> > > --        def a():
> > > --            if self._ncall == 1:
> > > --                self._ncall += 1
> > > --                a()
> > > --            else:
> > > --                b()
> > > --
> > > --        def b():
> > > --            if self._ncall == 3:
> > > --                return
> > > --            else:
> > > --                c()
> > > --
> > > --        def c():
> > > --            if self._ncall == 2:
> > > --                self._ncall += 1
> > > --                c()
> > > --            else:
> > > --                b()
> > > --
> > > --        stats = utils.run_and_get_func_stats(a)
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        fsc = utils.find_stat_by_name(stats, 'c')
> > > --        cfsaa = fsa.children[fsa.index]
> > > --        cfsab = fsa.children[fsb]
> > > --        cfsbc = fsb.children[fsc.full_name]
> > > --        cfscc = fsc.children[fsc]
> > > --        cfscb = fsc.children[fsb]
> > > --        self.assertEqual(fsb.ttot, 9)
> > > --        self.assertEqual(fsb.tsub, 5)
> > > --        self.assertEqual(cfsbc.ttot, 5)
> > > --        self.assertEqual(cfsbc.tsub, 2)
> > > --        self.assertEqual(fsa.ttot, 13)
> > > --        self.assertEqual(fsa.tsub, 4)
> > > --        self.assertEqual(cfsab.ttot, 9)
> > > --        self.assertEqual(cfsab.tsub, 4)
> > > --        self.assertEqual(cfsaa.ttot, 11)
> > > --        self.assertEqual(cfsaa.tsub, 2)
> > > --        self.assertEqual(fsc.ttot, 5)
> > > --        self.assertEqual(fsc.tsub, 4)
> > > --
> > > --    def test_abaa(self):
> > > --        _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        self._ncall = 1
> > > --
> > > --        def a():
> > > --            if self._ncall == 1:
> > > --                b()
> > > --            elif self._ncall == 2:
> > > --                self._ncall += 1
> > > --                a()
> > > --            else:
> > > --                return
> > > --
> > > --        def b():
> > > --            self._ncall += 1
> > > --            a()
> > > --
> > > --        stats = utils.run_and_get_func_stats(a)
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        cfsaa = fsa.children[fsa]
> > > --        cfsba = fsb.children[fsa]
> > > --        self.assertEqual(fsb.ttot, 10)
> > > --        self.assertEqual(fsb.tsub, 1)
> > > --        self.assertEqual(fsa.ttot, 13)
> > > --        self.assertEqual(fsa.tsub, 12)
> > > --        self.assertEqual(cfsaa.ttot, 5)
> > > --        self.assertEqual(cfsaa.tsub, 5)
> > > --        self.assertEqual(cfsba.ttot, 9)
> > > --        self.assertEqual(cfsba.tsub, 4)
> > > --
> > > --    def test_aabb(self):
> > > --        _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        self._ncall = 1
> > > --
> > > --        def a():
> > > --            if self._ncall == 1:
> > > --                self._ncall += 1
> > > --                a()
> > > --            elif self._ncall == 2:
> > > --                b()
> > > --            else:
> > > --                return
> > > --
> > > --        def b():
> > > --            if self._ncall == 2:
> > > --                self._ncall += 1
> > > --                b()
> > > --            else:
> > > --                return
> > > --
> > > --        stats = utils.run_and_get_func_stats(a)
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        cfsaa = fsa.children[fsa]
> > > --        cfsab = fsa.children[fsb]
> > > --        cfsbb = fsb.children[fsb]
> > > --        self.assertEqual(fsa.ttot, 13)
> > > --        self.assertEqual(fsa.tsub, 4)
> > > --        self.assertEqual(fsb.ttot, 9)
> > > --        self.assertEqual(fsb.tsub, 9)
> > > --        self.assertEqual(cfsaa.ttot, 10)
> > > --        self.assertEqual(cfsaa.tsub, 1)
> > > --        self.assertEqual(cfsab.ttot, 9)
> > > --        self.assertEqual(cfsab.tsub, 4)
> > > --        self.assertEqual(cfsbb.ttot, 5)
> > > --        self.assertEqual(cfsbb.tsub, 5)
> > > --
> > > --    def test_abbb(self):
> > > --        _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        self._ncall = 1
> > > --
> > > --        def a():
> > > --            if self._ncall == 1:
> > > --                b()
> > > --
> > > --        def b():
> > > --            if self._ncall == 3:
> > > --                return
> > > --            self._ncall += 1
> > > --            b()
> > > --
> > > --        stats = utils.run_and_get_func_stats(a)
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        cfsab = fsa.children[fsb]
> > > --        cfsbb = fsb.children[fsb]
> > > --        self.assertEqual(fsa.ttot, 13)
> > > --        self.assertEqual(fsa.tsub, 3)
> > > --        self.assertEqual(fsb.ttot, 10)
> > > --        self.assertEqual(fsb.tsub, 10)
> > > --        self.assertEqual(fsb.ncall, 3)
> > > --        self.assertEqual(fsb.nactualcall, 1)
> > > --        self.assertEqual(cfsab.ttot, 10)
> > > --        self.assertEqual(cfsab.tsub, 4)
> > > --        self.assertEqual(cfsbb.ttot, 6)
> > > --        self.assertEqual(cfsbb.tsub, 6)
> > > --        self.assertEqual(cfsbb.nactualcall, 0)
> > > --        self.assertEqual(cfsbb.ncall, 2)
> > > --
> > > --    def test_aaab(self):
> > > --        _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        self._ncall = 1
> > > --
> > > --        def a():
> > > --            if self._ncall == 3:
> > > --                b()
> > > --                return
> > > --            self._ncall += 1
> > > --            a()
> > > --
> > > --        def b():
> > > --            return
> > > --
> > > --        stats = utils.run_and_get_func_stats(a)
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        cfsaa = fsa.children[fsa]
> > > --        cfsab = fsa.children[fsb]
> > > --        self.assertEqual(fsa.ttot, 13)
> > > --        self.assertEqual(fsa.tsub, 12)
> > > --        self.assertEqual(fsb.ttot, 1)
> > > --        self.assertEqual(fsb.tsub, 1)
> > > --        self.assertEqual(cfsaa.ttot, 10)
> > > --        self.assertEqual(cfsaa.tsub, 9)
> > > --        self.assertEqual(cfsab.ttot, 1)
> > > --        self.assertEqual(cfsab.tsub, 1)
> > > --
> > > --    def test_abab(self):
> > > --        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
> > > --        _yappi._set_test_timings(_timings)
> > > --
> > > --        self._ncall = 1
> > > --
> > > --        def a():
> > > --            b()
> > > --
> > > --        def b():
> > > --            if self._ncall == 2:
> > > --                return
> > > --            self._ncall += 1
> > > --            a()
> > > --
> > > --        stats = utils.run_and_get_func_stats(a)
> > > --        fsa = utils.find_stat_by_name(stats, 'a')
> > > --        fsb = utils.find_stat_by_name(stats, 'b')
> > > --        cfsab = fsa.children[fsb]
> > > --        cfsba = fsb.children[fsa]
> > > --        self.assertEqual(fsa.ttot, 13)
> > > --        self.assertEqual(fsa.tsub, 8)
> > > --        self.assertEqual(fsb.ttot, 10)
> > > --        self.assertEqual(fsb.tsub, 5)
> > > --        self.assertEqual(cfsab.ttot, 10)
> > > --        self.assertEqual(cfsab.tsub, 5)
> > > --        self.assertEqual(cfsab.ncall, 2)
> > > --        self.assertEqual(cfsab.nactualcall, 1)
> > > --        self.assertEqual(cfsba.ttot, 6)
> > > --        self.assertEqual(cfsba.tsub, 5)
> > > --
> > > --
> > > --if __name__ == '__main__':
> > > --    #     import sys;sys.argv = ['', 'BasicUsage.test_run_as_script']
> > > --    #     import sys;sys.argv = ['',
> 'MultithreadedScenarios.test_subsequent_profile']
> > > --    unittest.main()
> > > -+import os
> > > -+import sys
> > > -+import time
> > > -+import threading
> > > -+import unittest
> > > -+import yappi
> > > -+import _yappi
> > > -+import tests.utils as utils
> > > -+import multiprocessing  # added to fix
> http://bugs.python.org/issue15881 for > Py2.6
> > > -+import subprocess
> > > -+
> > > -+_counter = 0
> > > -+
> > > -+
> > > -+class BasicUsage(utils.YappiUnitTestCase):
> > > -+
> > > -+    def test_callback_function_int_return_overflow(self):
> > > -+        # this test is just here to check if any errors are
> generated, as the err
> > > -+        # is printed in C side, I did not include it here. THere are
> ways to test
> > > -+        # this deterministically, I did not bother
> > > -+        import ctypes
> > > -+
> > > -+        def _unsigned_overflow_margin():
> > > -+            return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1
> > > -+
> > > -+        def foo():
> > > -+            pass
> > > -+
> > > -+        #with utils.captured_output() as (out, err):
> > > -+        yappi.set_context_id_callback(_unsigned_overflow_margin)
> > > -+        yappi.set_tag_callback(_unsigned_overflow_margin)
> > > -+        yappi.start()
> > > -+        foo()
> > > -+
> > > -+    def test_issue60(self):
> > > -+
> > > -+        def foo():
> > > -+            buf = bytearray()
> > > -+            buf += b't' * 200
> > > -+            view = memoryview(buf)[10:]
> > > -+            view = view.tobytes()
> > > -+            del buf[:10]  # this throws exception
> > > -+            return view
> > > -+
> > > -+        yappi.start(builtins=True)
> > > -+        foo()
> > > -+        self.assertTrue(
> > > -+            len(
> > > -+                yappi.get_func_stats(
> > > -+                    filter_callback=lambda x: yappi.
> > > -+                    func_matches(x, [memoryview.tobytes])
> > > -+                )
> > > -+            ) > 0
> > > -+        )
> > > -+        yappi.stop()
> > > -+
> > > -+    def test_issue54(self):
> > > -+
> > > -+        def _tag_cbk():
> > > -+            global _counter
> > > -+            _counter += 1
> > > -+            return _counter
> > > -+
> > > -+        def a():
> > > -+            pass
> > > -+
> > > -+        def b():
> > > -+            pass
> > > -+
> > > -+        yappi.set_tag_callback(_tag_cbk)
> > > -+        yappi.start()
> > > -+        a()
> > > -+        a()
> > > -+        a()
> > > -+        yappi.stop()
> > > -+        stats = yappi.get_func_stats()
> > > -+        self.assertEqual(stats.pop().ncall, 3)  # aggregated if no
> tag is given
> > > -+        stats = yappi.get_func_stats(tag=1)
> > > -+
> > > -+        for i in range(1, 3):
> > > -+            stats = yappi.get_func_stats(tag=i)
> > > -+            stats = yappi.get_func_stats(
> > > -+
diff mbox series

Patch

diff --git a/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch b/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
deleted file mode 100644
index 476db4b7d..000000000
--- a/meta-python/recipes-devtools/python/python3-yappi/0001-Fix-imports-for-ptests.patch
+++ /dev/null
@@ -1,3895 +0,0 @@ 
-From 0dedc1c573ddc4e87475eb03c64555cd54a72e92 Mon Sep 17 00:00:00 2001
-From: Trevor Gamblin <trevor.gamblin@windriver.com>
-Date: Mon, 7 Jun 2021 09:40:20 -0400
-Subject: [PATCH] Fix imports for tests
-
-Signed-off-by: Trevor Gamblin <trevor.gamblin@windriver.com>
----
-Upstream-Status: Pending
-
- tests/test_asyncio.py              | 2 +-
- tests/test_asyncio_context_vars.py | 2 +-
- tests/test_functionality.py        | 2 +-
- tests/test_hooks.py                | 2 +-
- tests/test_tags.py                 | 2 +-
- 5 files changed, 6 insertions(+), 6 deletions(-)
-
---- a/tests/test_asyncio.py
-+++ b/tests/test_asyncio.py
-@@ -2,7 +2,7 @@ import unittest
- import yappi
- import asyncio
- import threading
--from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
-+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
- 
- 
- async def async_sleep(sec):
---- a/tests/test_asyncio_context_vars.py
-+++ b/tests/test_asyncio_context_vars.py
-@@ -5,7 +5,7 @@ import contextvars
- import functools
- import time
- import os
--import utils
-+import tests.utils as utils
- import yappi
- 
- async_context_id = contextvars.ContextVar('async_context_id')
---- a/tests/test_functionality.py
-+++ b/tests/test_functionality.py
-@@ -1,1916 +1,1916 @@
--import os
--import sys
--import time
--import threading
--import unittest
--import yappi
--import _yappi
--import utils
--import multiprocessing  # added to fix http://bugs.python.org/issue15881 for > Py2.6
--import subprocess
--
--_counter = 0
--
--
--class BasicUsage(utils.YappiUnitTestCase):
--
--    def test_callback_function_int_return_overflow(self):
--        # this test is just here to check if any errors are generated, as the err
--        # is printed in C side, I did not include it here. THere are ways to test
--        # this deterministically, I did not bother
--        import ctypes
--
--        def _unsigned_overflow_margin():
--            return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1
--
--        def foo():
--            pass
--
--        #with utils.captured_output() as (out, err):
--        yappi.set_context_id_callback(_unsigned_overflow_margin)
--        yappi.set_tag_callback(_unsigned_overflow_margin)
--        yappi.start()
--        foo()
--
--    def test_issue60(self):
--
--        def foo():
--            buf = bytearray()
--            buf += b't' * 200
--            view = memoryview(buf)[10:]
--            view = view.tobytes()
--            del buf[:10]  # this throws exception
--            return view
--
--        yappi.start(builtins=True)
--        foo()
--        self.assertTrue(
--            len(
--                yappi.get_func_stats(
--                    filter_callback=lambda x: yappi.
--                    func_matches(x, [memoryview.tobytes])
--                )
--            ) > 0
--        )
--        yappi.stop()
--
--    def test_issue54(self):
--
--        def _tag_cbk():
--            global _counter
--            _counter += 1
--            return _counter
--
--        def a():
--            pass
--
--        def b():
--            pass
--
--        yappi.set_tag_callback(_tag_cbk)
--        yappi.start()
--        a()
--        a()
--        a()
--        yappi.stop()
--        stats = yappi.get_func_stats()
--        self.assertEqual(stats.pop().ncall, 3)  # aggregated if no tag is given
--        stats = yappi.get_func_stats(tag=1)
--
--        for i in range(1, 3):
--            stats = yappi.get_func_stats(tag=i)
--            stats = yappi.get_func_stats(
--                tag=i, filter_callback=lambda x: yappi.func_matches(x, [a])
--            )
--
--            stat = stats.pop()
--            self.assertEqual(stat.ncall, 1)
--
--        yappi.set_tag_callback(None)
--        yappi.clear_stats()
--        yappi.start()
--        b()
--        b()
--        stats = yappi.get_func_stats()
--        self.assertEqual(len(stats), 1)
--        stat = stats.pop()
--        self.assertEqual(stat.ncall, 2)
--
--    def test_filter(self):
--
--        def a():
--            pass
--
--        def b():
--            a()
--
--        def c():
--            b()
--
--        _TCOUNT = 5
--
--        ts = []
--        yappi.start()
--        for i in range(_TCOUNT):
--            t = threading.Thread(target=c)
--            t.start()
--            ts.append(t)
--
--        for t in ts:
--            t.join()
--
--        yappi.stop()
--
--        ctx_ids = []
--        for tstat in yappi.get_thread_stats():
--            if tstat.name == '_MainThread':
--                main_ctx_id = tstat.id
--            else:
--                ctx_ids.append(tstat.id)
--
--        fstats = yappi.get_func_stats(filter={"ctx_id": 9})
--        self.assertTrue(fstats.empty())
--        fstats = yappi.get_func_stats(
--            filter={
--                "ctx_id": main_ctx_id,
--                "name": "c"
--            }
--        )  # main thread
--        self.assertTrue(fstats.empty())
--
--        for i in ctx_ids:
--            fstats = yappi.get_func_stats(
--                filter={
--                    "ctx_id": i,
--                    "name": "a",
--                    "ncall": 1
--                }
--            )
--            self.assertEqual(fstats.pop().ncall, 1)
--            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"})
--            self.assertEqual(fstats.pop().ncall, 1)
--            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"})
--            self.assertEqual(fstats.pop().ncall, 1)
--
--        yappi.clear_stats()
--        yappi.start(builtins=True)
--        time.sleep(0.1)
--        yappi.stop()
--        fstats = yappi.get_func_stats(filter={"module": "time"})
--        self.assertEqual(len(fstats), 1)
--
--        # invalid filters`
--        self.assertRaises(
--            Exception, yappi.get_func_stats, filter={'tag': "sss"}
--        )
--        self.assertRaises(
--            Exception, yappi.get_func_stats, filter={'ctx_id': "None"}
--        )
--
--    def test_filter_callback(self):
--
--        def a():
--            time.sleep(0.1)
--
--        def b():
--            a()
--
--        def c():
--            pass
--
--        def d():
--            pass
--
--        yappi.set_clock_type("wall")
--        yappi.start(builtins=True)
--        a()
--        b()
--        c()
--        d()
--        stats = yappi.get_func_stats(
--            filter_callback=lambda x: yappi.func_matches(x, [a, b])
--        )
--        #stats.print_all()
--        r1 = '''
--        tests/test_functionality.py:98 a      2      0.000000  0.200350  0.100175
--        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.100197
--        '''
--        self.assert_traces_almost_equal(r1, stats)
--        self.assertEqual(len(stats), 2)
--        stats = yappi.get_func_stats(
--            filter_callback=lambda x: yappi.
--            module_matches(x, [sys.modules[__name__]])
--        )
--        r1 = '''
--        tests/test_functionality.py:98 a      2      0.000000  0.230130  0.115065
--        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.109011
--        tests/test_functionality.py:104 c     1      0.000000  0.000002  0.000002
--        tests/test_functionality.py:107 d     1      0.000000  0.000001  0.000001
--        '''
--        self.assert_traces_almost_equal(r1, stats)
--        self.assertEqual(len(stats), 4)
--
--        stats = yappi.get_func_stats(
--            filter_callback=lambda x: yappi.func_matches(x, [time.sleep])
--        )
--        self.assertEqual(len(stats), 1)
--        r1 = '''
--        time.sleep                            2      0.206804  0.220000  0.103402
--        '''
--        self.assert_traces_almost_equal(r1, stats)
--
--    def test_print_formatting(self):
--
--        def a():
--            pass
--
--        def b():
--            a()
--
--        func_cols = {
--            1: ("name", 48),
--            0: ("ncall", 5),
--            2: ("tsub", 8),
--        }
--        thread_cols = {
--            1: ("name", 48),
--            0: ("ttot", 8),
--        }
--
--        yappi.start()
--        a()
--        b()
--        yappi.stop()
--        fs = yappi.get_func_stats()
--        cs = fs[1].children
--        ts = yappi.get_thread_stats()
--        #fs.print_all(out=sys.stderr, columns={1:("name", 70), })
--        #cs.print_all(out=sys.stderr, columns=func_cols)
--        #ts.print_all(out=sys.stderr, columns=thread_cols)
--        #cs.print_all(out=sys.stderr, columns={})
--
--        self.assertRaises(
--            yappi.YappiError, fs.print_all, columns={1: ("namee", 9)}
--        )
--        self.assertRaises(
--            yappi.YappiError, cs.print_all, columns={1: ("dd", 0)}
--        )
--        self.assertRaises(
--            yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)}
--        )
--
--    def test_get_clock(self):
--        yappi.set_clock_type('cpu')
--        self.assertEqual('cpu', yappi.get_clock_type())
--        clock_info = yappi.get_clock_info()
--        self.assertTrue('api' in clock_info)
--        self.assertTrue('resolution' in clock_info)
--
--        yappi.set_clock_type('wall')
--        self.assertEqual('wall', yappi.get_clock_type())
--
--        t0 = yappi.get_clock_time()
--        time.sleep(0.1)
--        duration = yappi.get_clock_time() - t0
--        self.assertTrue(0.05 < duration < 0.3)
--
--    def test_profile_decorator(self):
--
--        def aggregate(func, stats):
--            fname = "tests/%s.profile" % (func.__name__)
--            try:
--                stats.add(fname)
--            except IOError:
--                pass
--            stats.save(fname)
--            raise Exception("messing around")
--
--        @yappi.profile(return_callback=aggregate)
--        def a(x, y):
--            if x + y == 25:
--                raise Exception("")
--            return x + y
--
--        def b():
--            pass
--
--        try:
--            os.remove(
--                "tests/a.profile"
--            )  # remove the one from prev test, if available
--        except:
--            pass
--
--        # global profile is on to mess things up
--        yappi.start()
--        b()
--
--        # assert functionality and call function at same time
--        try:
--            self.assertEqual(a(1, 2), 3)
--        except:
--            pass
--        try:
--            self.assertEqual(a(2, 5), 7)
--        except:
--            pass
--        try:
--            a(4, 21)
--        except:
--            pass
--        stats = yappi.get_func_stats().add("tests/a.profile")
--        fsa = utils.find_stat_by_name(stats, 'a')
--        self.assertEqual(fsa.ncall, 3)
--        self.assertEqual(len(stats), 1)  # b() should be cleared out.
--
--        @yappi.profile(return_callback=aggregate)
--        def count_down_rec(n):
--            if n == 0:
--                return
--            count_down_rec(n - 1)
--
--        try:
--            os.remove(
--                "tests/count_down_rec.profile"
--            )  # remove the one from prev test, if available
--        except:
--            pass
--
--        try:
--            count_down_rec(4)
--        except:
--            pass
--        try:
--            count_down_rec(3)
--        except:
--            pass
--
--        stats = yappi.YFuncStats("tests/count_down_rec.profile")
--        fsrec = utils.find_stat_by_name(stats, 'count_down_rec')
--        self.assertEqual(fsrec.ncall, 9)
--        self.assertEqual(fsrec.nactualcall, 2)
--
--    def test_strip_dirs(self):
--
--        def a():
--            pass
--
--        stats = utils.run_and_get_func_stats(a, )
--        stats.strip_dirs()
--        fsa = utils.find_stat_by_name(stats, "a")
--        self.assertEqual(fsa.module, os.path.basename(fsa.module))
--
--    @unittest.skipIf(os.name == "nt", "do not run on Windows")
--    def test_run_as_script(self):
--        import re
--        p = subprocess.Popen(
--            ['yappi', os.path.join('./tests', 'run_as_script.py')],
--            stdout=subprocess.PIPE
--        )
--        out, err = p.communicate()
--        self.assertEqual(p.returncode, 0)
--        func_stats, thread_stats = re.split(
--            b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out
--        )
--        self.assertTrue(b'FancyThread' in thread_stats)
--
--    def test_yappi_overhead(self):
--        LOOP_COUNT = 100000
--
--        def a():
--            pass
--
--        def b():
--            for i in range(LOOP_COUNT):
--                a()
--
--        t0 = time.time()
--        yappi.start()
--        b()
--        yappi.stop()
--        time_with_yappi = time.time() - t0
--        t0 = time.time()
--        b()
--        time_without_yappi = time.time() - t0
--        if time_without_yappi == 0:
--            time_without_yappi = 0.000001
--
--        # in latest v0.82, I calculated this as close to "7.0" in my machine.
--        # however, %83 of this overhead is coming from tickcount(). The other %17
--        # seems to have been evenly distributed to the internal bookkeeping
--        # structures/algorithms which seems acceptable. Note that our test only
--        # tests one function being profiled at-a-time in a short interval.
--        # profiling high number of functions in a small time
--        # is a different beast, (which is pretty unlikely in most applications)
--        # So as a conclusion: I cannot see any optimization window for Yappi that
--        # is worth implementing as we will only optimize %17 of the time.
--        sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \
--            (time_with_yappi / time_without_yappi))
--
--    def test_clear_stats_while_running(self):
--
--        def a():
--            pass
--
--        yappi.start()
--        a()
--        yappi.clear_stats()
--        a()
--        stats = yappi.get_func_stats()
--        fsa = utils.find_stat_by_name(stats, 'a')
--        self.assertEqual(fsa.ncall, 1)
--
--    def test_generator(self):
--
--        def _gen(n):
--            while (n > 0):
--                yield n
--                n -= 1
--
--        yappi.start()
--        for x in _gen(5):
--            pass
--        self.assertTrue(
--            yappi.convert2pstats(yappi.get_func_stats()) is not None
--        )
--
--    def test_slice_child_stats_and_strip_dirs(self):
--
--        def b():
--            for i in range(10000000):
--                pass
--
--        def a():
--            b()
--
--        yappi.start(builtins=True)
--        a()
--        stats = yappi.get_func_stats()
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        self.assertTrue(fsa.children[0:1] is not None)
--        prev_afullname = fsa.full_name
--        prev_bchildfullname = fsa.children[fsb].full_name
--        stats.strip_dirs()
--        self.assertTrue(len(prev_afullname) > len(fsa.full_name))
--        self.assertTrue(
--            len(prev_bchildfullname) > len(fsa.children[fsb].full_name)
--        )
--
--    def test_children_stat_functions(self):
--        _timings = {"a_1": 5, "b_1": 3, "c_1": 1}
--        _yappi._set_test_timings(_timings)
--
--        def b():
--            pass
--
--        def c():
--            pass
--
--        def a():
--            b()
--            c()
--
--        yappi.start()
--        a()
--        b()  # non-child call
--        c()  # non-child call
--        stats = yappi.get_func_stats()
--        fsa = utils.find_stat_by_name(stats, 'a')
--        childs_of_a = fsa.children.get().sort("tavg", "desc")
--        prev_item = None
--        for item in childs_of_a:
--            if prev_item:
--                self.assertTrue(prev_item.tavg > item.tavg)
--            prev_item = item
--        childs_of_a.sort("name", "desc")
--        prev_item = None
--        for item in childs_of_a:
--            if prev_item:
--                self.assertTrue(prev_item.name > item.name)
--            prev_item = item
--        childs_of_a.clear()
--        self.assertTrue(childs_of_a.empty())
--
--    def test_no_stats_different_clock_type_load(self):
--
--        def a():
--            pass
--
--        yappi.start()
--        a()
--        yappi.stop()
--        yappi.get_func_stats().save("tests/ystats1.ys")
--        yappi.clear_stats()
--        yappi.set_clock_type("WALL")
--        yappi.start()
--        yappi.stop()
--        stats = yappi.get_func_stats().add("tests/ystats1.ys")
--        fsa = utils.find_stat_by_name(stats, 'a')
--        self.assertTrue(fsa is not None)
--
--    def test_subsequent_profile(self):
--        _timings = {"a_1": 1, "b_1": 1}
--        _yappi._set_test_timings(_timings)
--
--        def a():
--            pass
--
--        def b():
--            pass
--
--        yappi.start()
--        a()
--        yappi.stop()
--        yappi.start()
--        b()
--        yappi.stop()
--        stats = yappi.get_func_stats()
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        self.assertTrue(fsa is not None)
--        self.assertTrue(fsb is not None)
--        self.assertEqual(fsa.ttot, 1)
--        self.assertEqual(fsb.ttot, 1)
--
--    def test_lambda(self):
--        f = lambda: time.sleep(0.3)
--        yappi.set_clock_type("wall")
--        yappi.start()
--        f()
--        stats = yappi.get_func_stats()
--        fsa = utils.find_stat_by_name(stats, '<lambda>')
--        self.assertTrue(fsa.ttot > 0.1)
--
--    def test_module_stress(self):
--        self.assertEqual(yappi.is_running(), False)
--
--        yappi.start()
--        yappi.clear_stats()
--        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
--
--        yappi.stop()
--        yappi.clear_stats()
--        yappi.set_clock_type("cpu")
--        self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy")
--        self.assertEqual(yappi.is_running(), False)
--        yappi.clear_stats()
--        yappi.clear_stats()
--
--    def test_stat_sorting(self):
--        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
--        _yappi._set_test_timings(_timings)
--
--        self._ncall = 1
--
--        def a():
--            b()
--
--        def b():
--            if self._ncall == 2:
--                return
--            self._ncall += 1
--            a()
--
--        stats = utils.run_and_get_func_stats(a)
--        stats = stats.sort("totaltime", "desc")
--        prev_stat = None
--        for stat in stats:
--            if prev_stat:
--                self.assertTrue(prev_stat.ttot >= stat.ttot)
--            prev_stat = stat
--        stats = stats.sort("totaltime", "asc")
--        prev_stat = None
--        for stat in stats:
--            if prev_stat:
--                self.assertTrue(prev_stat.ttot <= stat.ttot)
--            prev_stat = stat
--        stats = stats.sort("avgtime", "asc")
--        prev_stat = None
--        for stat in stats:
--            if prev_stat:
--                self.assertTrue(prev_stat.tavg <= stat.tavg)
--            prev_stat = stat
--        stats = stats.sort("name", "asc")
--        prev_stat = None
--        for stat in stats:
--            if prev_stat:
--                self.assertTrue(prev_stat.name <= stat.name)
--            prev_stat = stat
--        stats = stats.sort("subtime", "asc")
--        prev_stat = None
--        for stat in stats:
--            if prev_stat:
--                self.assertTrue(prev_stat.tsub <= stat.tsub)
--            prev_stat = stat
--
--        self.assertRaises(
--            yappi.YappiError, stats.sort, "invalid_func_sorttype_arg"
--        )
--        self.assertRaises(
--            yappi.YappiError, stats.sort, "totaltime",
--            "invalid_func_sortorder_arg"
--        )
--
--    def test_start_flags(self):
--        self.assertEqual(_yappi._get_start_flags(), None)
--        yappi.start()
--
--        def a():
--            pass
--
--        a()
--        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
--        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
--        self.assertEqual(len(yappi.get_thread_stats()), 1)
--
--    def test_builtin_profiling(self):
--
--        def a():
--            time.sleep(0.4)  # is a builtin function
--
--        yappi.set_clock_type('wall')
--
--        yappi.start(builtins=True)
--        a()
--        stats = yappi.get_func_stats()
--        fsa = utils.find_stat_by_name(stats, 'sleep')
--        self.assertTrue(fsa is not None)
--        self.assertTrue(fsa.ttot > 0.3)
--        yappi.stop()
--        yappi.clear_stats()
--
--        def a():
--            pass
--
--        yappi.start()
--        t = threading.Thread(target=a)
--        t.start()
--        t.join()
--        stats = yappi.get_func_stats()
--
--    def test_singlethread_profiling(self):
--        yappi.set_clock_type('wall')
--
--        def a():
--            time.sleep(0.2)
--
--        class Worker1(threading.Thread):
--
--            def a(self):
--                time.sleep(0.3)
--
--            def run(self):
--                self.a()
--
--        yappi.start(profile_threads=False)
--
--        c = Worker1()
--        c.start()
--        c.join()
--        a()
--        stats = yappi.get_func_stats()
--        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
--        fsa2 = utils.find_stat_by_name(stats, 'a')
--        self.assertTrue(fsa1 is None)
--        self.assertTrue(fsa2 is not None)
--        self.assertTrue(fsa2.ttot > 0.1)
--
--    def test_run(self):
--
--        def profiled():
--            pass
--
--        yappi.clear_stats()
--        try:
--            with yappi.run():
--                profiled()
--            stats = yappi.get_func_stats()
--        finally:
--            yappi.clear_stats()
--
--        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
--
--    def test_run_recursive(self):
--
--        def profiled():
--            pass
--
--        def not_profiled():
--            pass
--
--        yappi.clear_stats()
--        try:
--            with yappi.run():
--                with yappi.run():
--                    profiled()
--                # Profiling stopped here
--                not_profiled()
--            stats = yappi.get_func_stats()
--        finally:
--            yappi.clear_stats()
--
--        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
--        self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled'))
--
--
--class StatSaveScenarios(utils.YappiUnitTestCase):
--
--    def test_pstats_conversion(self):
--
--        def pstat_id(fs):
--            return (fs.module, fs.lineno, fs.name)
--
--        def a():
--            d()
--
--        def b():
--            d()
--
--        def c():
--            pass
--
--        def d():
--            pass
--
--        _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2}
--        _yappi._set_test_timings(_timings)
--        stats = utils.run_and_get_func_stats(a, )
--        stats.strip_dirs()
--        stats.save("tests/a1.pstats", type="pstat")
--        fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a"))
--        fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d"))
--        yappi.clear_stats()
--        _yappi._set_test_timings(_timings)
--        stats = utils.run_and_get_func_stats(a, )
--        stats.strip_dirs()
--        stats.save("tests/a2.pstats", type="pstat")
--        yappi.clear_stats()
--        _yappi._set_test_timings(_timings)
--        stats = utils.run_and_get_func_stats(b, )
--        stats.strip_dirs()
--        stats.save("tests/b1.pstats", type="pstat")
--        fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b"))
--        yappi.clear_stats()
--        _yappi._set_test_timings(_timings)
--        stats = utils.run_and_get_func_stats(c, )
--        stats.strip_dirs()
--        stats.save("tests/c1.pstats", type="pstat")
--        fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c"))
--
--        # merge saved stats and check pstats values are correct
--        import pstats
--        p = pstats.Stats(
--            'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats',
--            'tests/c1.pstats'
--        )
--        p.strip_dirs()
--        # ct = ttot, tt = tsub
--        (cc, nc, tt, ct, callers) = p.stats[fsa_pid]
--        self.assertEqual(cc, nc, 2)
--        self.assertEqual(tt, 20)
--        self.assertEqual(ct, 24)
--        (cc, nc, tt, ct, callers) = p.stats[fsd_pid]
--        self.assertEqual(cc, nc, 3)
--        self.assertEqual(tt, 6)
--        self.assertEqual(ct, 6)
--        self.assertEqual(len(callers), 2)
--        (cc, nc, tt, ct) = callers[fsa_pid]
--        self.assertEqual(cc, nc, 2)
--        self.assertEqual(tt, 4)
--        self.assertEqual(ct, 4)
--        (cc, nc, tt, ct) = callers[fsb_pid]
--        self.assertEqual(cc, nc, 1)
--        self.assertEqual(tt, 2)
--        self.assertEqual(ct, 2)
--
--    def test_merge_stats(self):
--        _timings = {
--            "a_1": 15,
--            "b_1": 14,
--            "c_1": 12,
--            "d_1": 10,
--            "e_1": 9,
--            "f_1": 7,
--            "g_1": 6,
--            "h_1": 5,
--            "i_1": 1
--        }
--        _yappi._set_test_timings(_timings)
--
--        def a():
--            b()
--
--        def b():
--            c()
--
--        def c():
--            d()
--
--        def d():
--            e()
--
--        def e():
--            f()
--
--        def f():
--            g()
--
--        def g():
--            h()
--
--        def h():
--            i()
--
--        def i():
--            pass
--
--        yappi.start()
--        a()
--        a()
--        yappi.stop()
--        stats = yappi.get_func_stats()
--        self.assertRaises(
--            NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE"
--        )
--        stats.save("tests/ystats2.ys")
--        yappi.clear_stats()
--        _yappi._set_test_timings(_timings)
--        yappi.start()
--        a()
--        stats = yappi.get_func_stats().add("tests/ystats2.ys")
--        fsa = utils.find_stat_by_name(stats, "a")
--        fsb = utils.find_stat_by_name(stats, "b")
--        fsc = utils.find_stat_by_name(stats, "c")
--        fsd = utils.find_stat_by_name(stats, "d")
--        fse = utils.find_stat_by_name(stats, "e")
--        fsf = utils.find_stat_by_name(stats, "f")
--        fsg = utils.find_stat_by_name(stats, "g")
--        fsh = utils.find_stat_by_name(stats, "h")
--        fsi = utils.find_stat_by_name(stats, "i")
--        self.assertEqual(fsa.ttot, 45)
--        self.assertEqual(fsa.ncall, 3)
--        self.assertEqual(fsa.nactualcall, 3)
--        self.assertEqual(fsa.tsub, 3)
--        self.assertEqual(fsa.children[fsb].ttot, fsb.ttot)
--        self.assertEqual(fsa.children[fsb].tsub, fsb.tsub)
--        self.assertEqual(fsb.children[fsc].ttot, fsc.ttot)
--        self.assertEqual(fsb.children[fsc].tsub, fsc.tsub)
--        self.assertEqual(fsc.tsub, 6)
--        self.assertEqual(fsc.children[fsd].ttot, fsd.ttot)
--        self.assertEqual(fsc.children[fsd].tsub, fsd.tsub)
--        self.assertEqual(fsd.children[fse].ttot, fse.ttot)
--        self.assertEqual(fsd.children[fse].tsub, fse.tsub)
--        self.assertEqual(fse.children[fsf].ttot, fsf.ttot)
--        self.assertEqual(fse.children[fsf].tsub, fsf.tsub)
--        self.assertEqual(fsf.children[fsg].ttot, fsg.ttot)
--        self.assertEqual(fsf.children[fsg].tsub, fsg.tsub)
--        self.assertEqual(fsg.ttot, 18)
--        self.assertEqual(fsg.tsub, 3)
--        self.assertEqual(fsg.children[fsh].ttot, fsh.ttot)
--        self.assertEqual(fsg.children[fsh].tsub, fsh.tsub)
--        self.assertEqual(fsh.ttot, 15)
--        self.assertEqual(fsh.tsub, 12)
--        self.assertEqual(fsh.tavg, 5)
--        self.assertEqual(fsh.children[fsi].ttot, fsi.ttot)
--        self.assertEqual(fsh.children[fsi].tsub, fsi.tsub)
--        #stats.debug_print()
--
--    def test_merge_multithreaded_stats(self):
--        import _yappi
--        timings = {"a_1": 2, "b_1": 1}
--        _yappi._set_test_timings(timings)
--
--        def a():
--            pass
--
--        def b():
--            pass
--
--        yappi.start()
--        t = threading.Thread(target=a)
--        t.start()
--        t.join()
--        t = threading.Thread(target=b)
--        t.start()
--        t.join()
--        yappi.get_func_stats().save("tests/ystats1.ys")
--        yappi.clear_stats()
--        _yappi._set_test_timings(timings)
--        self.assertEqual(len(yappi.get_func_stats()), 0)
--        self.assertEqual(len(yappi.get_thread_stats()), 1)
--        t = threading.Thread(target=a)
--        t.start()
--        t.join()
--
--        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
--        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
--        yappi.get_func_stats().save("tests/ystats2.ys")
--
--        stats = yappi.YFuncStats([
--            "tests/ystats1.ys",
--            "tests/ystats2.ys",
--        ])
--        fsa = utils.find_stat_by_name(stats, "a")
--        fsb = utils.find_stat_by_name(stats, "b")
--        self.assertEqual(fsa.ncall, 2)
--        self.assertEqual(fsb.ncall, 1)
--        self.assertEqual(fsa.tsub, fsa.ttot, 4)
--        self.assertEqual(fsb.tsub, fsb.ttot, 1)
--
--    def test_merge_load_different_clock_types(self):
--        yappi.start(builtins=True)
--
--        def a():
--            b()
--
--        def b():
--            c()
--
--        def c():
--            pass
--
--        t = threading.Thread(target=a)
--        t.start()
--        t.join()
--        yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys")
--        yappi.stop()
--        yappi.clear_stats()
--        yappi.start(builtins=False)
--        t = threading.Thread(target=a)
--        t.start()
--        t.join()
--        yappi.get_func_stats().save("tests/ystats2.ys")
--        yappi.stop()
--        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
--        yappi.clear_stats()
--        yappi.set_clock_type("wall")
--        yappi.start()
--        t = threading.Thread(target=a)
--        t.start()
--        t.join()
--        yappi.get_func_stats().save("tests/ystats3.ys")
--        self.assertRaises(
--            yappi.YappiError,
--            yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys"
--        )
--        stats = yappi.YFuncStats(["tests/ystats1.ys",
--                                  "tests/ystats2.ys"]).sort("name")
--        fsa = utils.find_stat_by_name(stats, "a")
--        fsb = utils.find_stat_by_name(stats, "b")
--        fsc = utils.find_stat_by_name(stats, "c")
--        self.assertEqual(fsa.ncall, 2)
--        self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall)
--
--    def test_merge_aabab_aabbc(self):
--        _timings = {
--            "a_1": 15,
--            "a_2": 14,
--            "b_1": 12,
--            "a_3": 10,
--            "b_2": 9,
--            "c_1": 4
--        }
--        _yappi._set_test_timings(_timings)
--
--        def a():
--            if self._ncall == 1:
--                self._ncall += 1
--                a()
--            elif self._ncall == 5:
--                self._ncall += 1
--                a()
--            else:
--                b()
--
--        def b():
--            if self._ncall == 2:
--                self._ncall += 1
--                a()
--            elif self._ncall == 6:
--                self._ncall += 1
--                b()
--            elif self._ncall == 7:
--                c()
--            else:
--                return
--
--        def c():
--            pass
--
--        self._ncall = 1
--        stats = utils.run_and_get_func_stats(a, )
--        stats.save("tests/ystats1.ys")
--        yappi.clear_stats()
--        _yappi._set_test_timings(_timings)
--        #stats.print_all()
--
--        self._ncall = 5
--        stats = utils.run_and_get_func_stats(a, )
--        stats.save("tests/ystats2.ys")
--
--        #stats.print_all()
--
--        def a():  # same name but another function(code object)
--            pass
--
--        yappi.start()
--        a()
--        stats = yappi.get_func_stats().add(
--            ["tests/ystats1.ys", "tests/ystats2.ys"]
--        )
--        #stats.print_all()
--        self.assertEqual(len(stats), 4)
--
--        fsa = None
--        for stat in stats:
--            if stat.name == "a" and stat.ttot == 45:
--                fsa = stat
--                break
--        self.assertTrue(fsa is not None)
--
--        self.assertEqual(fsa.ncall, 7)
--        self.assertEqual(fsa.nactualcall, 3)
--        self.assertEqual(fsa.ttot, 45)
--        self.assertEqual(fsa.tsub, 10)
--        fsb = utils.find_stat_by_name(stats, "b")
--        fsc = utils.find_stat_by_name(stats, "c")
--        self.assertEqual(fsb.ncall, 6)
--        self.assertEqual(fsb.nactualcall, 3)
--        self.assertEqual(fsb.ttot, 36)
--        self.assertEqual(fsb.tsub, 27)
--        self.assertEqual(fsb.tavg, 6)
--        self.assertEqual(fsc.ttot, 8)
--        self.assertEqual(fsc.tsub, 8)
--        self.assertEqual(fsc.tavg, 4)
--        self.assertEqual(fsc.nactualcall, fsc.ncall, 2)
--
--
--class MultithreadedScenarios(utils.YappiUnitTestCase):
--
--    def test_issue_32(self):
--        '''
--        Start yappi from different thread and we get Internal Error(15) as 
--        the current_ctx_id() called while enumerating the threads in start() 
--        and as it does not swap to the enumerated ThreadState* the THreadState_GetDict()
--        returns wrong object and thus sets an invalid id for the _ctx structure.
--
--        When this issue happens multiple Threads have same tid as the internal ts_ptr
--        will be same for different contexts. So, let's see if that happens
--        '''
--
--        def foo():
--            time.sleep(0.2)
--
--        def bar():
--            time.sleep(0.1)
--
--        def thread_func():
--            yappi.set_clock_type("wall")
--            yappi.start()
--
--            bar()
--
--        t = threading.Thread(target=thread_func)
--        t.start()
--        t.join()
--
--        foo()
--
--        yappi.stop()
--
--        thread_ids = set()
--        for tstat in yappi.get_thread_stats():
--            self.assertTrue(tstat.tid not in thread_ids)
--            thread_ids.add(tstat.tid)
--
--    def test_subsequent_profile(self):
--        WORKER_COUNT = 5
--
--        def a():
--            pass
--
--        def b():
--            pass
--
--        def c():
--            pass
--
--        _timings = {
--            "a_1": 3,
--            "b_1": 2,
--            "c_1": 1,
--        }
--
--        yappi.start()
--
--        def g():
--            pass
--
--        g()
--        yappi.stop()
--        yappi.clear_stats()
--        _yappi._set_test_timings(_timings)
--        yappi.start()
--
--        _dummy = []
--        for i in range(WORKER_COUNT):
--            t = threading.Thread(target=a)
--            t.start()
--            t.join()
--        for i in range(WORKER_COUNT):
--            t = threading.Thread(target=b)
--            t.start()
--            _dummy.append(t)
--            t.join()
--        for i in range(WORKER_COUNT):
--            t = threading.Thread(target=a)
--            t.start()
--            t.join()
--        for i in range(WORKER_COUNT):
--            t = threading.Thread(target=c)
--            t.start()
--            t.join()
--        yappi.stop()
--        yappi.start()
--
--        def f():
--            pass
--
--        f()
--        stats = yappi.get_func_stats()
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        fsc = utils.find_stat_by_name(stats, 'c')
--        self.assertEqual(fsa.ncall, 10)
--        self.assertEqual(fsb.ncall, 5)
--        self.assertEqual(fsc.ncall, 5)
--        self.assertEqual(fsa.ttot, fsa.tsub, 30)
--        self.assertEqual(fsb.ttot, fsb.tsub, 10)
--        self.assertEqual(fsc.ttot, fsc.tsub, 5)
--
--        # MACOSx optimizes by only creating one worker thread
--        self.assertTrue(len(yappi.get_thread_stats()) >= 2)
--
--    def test_basic(self):
--        yappi.set_clock_type('wall')
--
--        def dummy():
--            pass
--
--        def a():
--            time.sleep(0.2)
--
--        class Worker1(threading.Thread):
--
--            def a(self):
--                time.sleep(0.3)
--
--            def run(self):
--                self.a()
--
--        yappi.start(builtins=False, profile_threads=True)
--
--        c = Worker1()
--        c.start()
--        c.join()
--        a()
--        stats = yappi.get_func_stats()
--        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
--        fsa2 = utils.find_stat_by_name(stats, 'a')
--        self.assertTrue(fsa1 is not None)
--        self.assertTrue(fsa2 is not None)
--        self.assertTrue(fsa1.ttot > 0.2)
--        self.assertTrue(fsa2.ttot > 0.1)
--        tstats = yappi.get_thread_stats()
--        self.assertEqual(len(tstats), 2)
--        tsa = utils.find_stat_by_name(tstats, 'Worker1')
--        tsm = utils.find_stat_by_name(tstats, '_MainThread')
--        dummy()  # call dummy to force ctx name to be retrieved again.
--        self.assertTrue(tsa is not None)
--        # TODO: I put dummy() to fix below, remove the comments after a while.
--        self.assertTrue( # FIX: I see this fails sometimes?
--            tsm is not None,
--            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(tstats))))
--
--    def test_ctx_stats(self):
--        from threading import Thread
--        DUMMY_WORKER_COUNT = 5
--        yappi.start()
--
--        class DummyThread(Thread):
--            pass
--
--        def dummy():
--            pass
--
--        def dummy_worker():
--            pass
--
--        for i in range(DUMMY_WORKER_COUNT):
--            t = DummyThread(target=dummy_worker)
--            t.start()
--            t.join()
--        yappi.stop()
--        stats = yappi.get_thread_stats()
--        tsa = utils.find_stat_by_name(stats, "DummyThread")
--        self.assertTrue(tsa is not None)
--        yappi.clear_stats()
--        time.sleep(1.0)
--        _timings = {
--            "a_1": 6,
--            "b_1": 5,
--            "c_1": 3,
--            "d_1": 1,
--            "a_2": 4,
--            "b_2": 3,
--            "c_2": 2,
--            "d_2": 1
--        }
--        _yappi._set_test_timings(_timings)
--
--        class Thread1(Thread):
--            pass
--
--        class Thread2(Thread):
--            pass
--
--        def a():
--            b()
--
--        def b():
--            c()
--
--        def c():
--            d()
--
--        def d():
--            time.sleep(0.6)
--
--        yappi.set_clock_type("wall")
--        yappi.start()
--        t1 = Thread1(target=a)
--        t1.start()
--        t2 = Thread2(target=a)
--        t2.start()
--        t1.join()
--        t2.join()
--        stats = yappi.get_thread_stats()
--
--        # the fist clear_stats clears the context table?
--        tsa = utils.find_stat_by_name(stats, "DummyThread")
--        self.assertTrue(tsa is None)
--
--        tst1 = utils.find_stat_by_name(stats, "Thread1")
--        tst2 = utils.find_stat_by_name(stats, "Thread2")
--        tsmain = utils.find_stat_by_name(stats, "_MainThread")
--        dummy()  # call dummy to force ctx name to be retrieved again.
--        self.assertTrue(len(stats) == 3)
--        self.assertTrue(tst1 is not None)
--        self.assertTrue(tst2 is not None)
--        # TODO: I put dummy() to fix below, remove the comments after a while.
--        self.assertTrue( # FIX: I see this fails sometimes
--            tsmain is not None,
--            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(stats))))
--        self.assertTrue(1.0 > tst2.ttot >= 0.5)
--        self.assertTrue(1.0 > tst1.ttot >= 0.5)
--
--        # test sorting of the ctx stats
--        stats = stats.sort("totaltime", "desc")
--        prev_stat = None
--        for stat in stats:
--            if prev_stat:
--                self.assertTrue(prev_stat.ttot >= stat.ttot)
--            prev_stat = stat
--        stats = stats.sort("totaltime", "asc")
--        prev_stat = None
--        for stat in stats:
--            if prev_stat:
--                self.assertTrue(prev_stat.ttot <= stat.ttot)
--            prev_stat = stat
--        stats = stats.sort("schedcount", "desc")
--        prev_stat = None
--        for stat in stats:
--            if prev_stat:
--                self.assertTrue(prev_stat.sched_count >= stat.sched_count)
--            prev_stat = stat
--        stats = stats.sort("name", "desc")
--        prev_stat = None
--        for stat in stats:
--            if prev_stat:
--                self.assertTrue(prev_stat.name.lower() >= stat.name.lower())
--            prev_stat = stat
--        self.assertRaises(
--            yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg"
--        )
--        self.assertRaises(
--            yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg"
--        )
--
--    def test_ctx_stats_cpu(self):
--
--        def get_thread_name():
--            try:
--                return threading.current_thread().name
--            except AttributeError:
--                return "Anonymous"
--
--        def burn_cpu(sec):
--            t0 = yappi.get_clock_time()
--            elapsed = 0
--            while (elapsed < sec):
--                for _ in range(1000):
--                    pass
--                elapsed = yappi.get_clock_time() - t0
--
--        def test():
--
--            ts = []
--            for i in (0.01, 0.05, 0.1):
--                t = threading.Thread(target=burn_cpu, args=(i, ))
--                t.name = "burn_cpu-%s" % str(i)
--                t.start()
--                ts.append(t)
--            for t in ts:
--                t.join()
--
--        yappi.set_clock_type("cpu")
--        yappi.set_context_name_callback(get_thread_name)
--
--        yappi.start()
--
--        test()
--
--        yappi.stop()
--
--        tstats = yappi.get_thread_stats()
--        r1 = '''
--        burn_cpu-0.1      3      123145356058624  0.100105  8
--        burn_cpu-0.05     2      123145361313792  0.050149  8
--        burn_cpu-0.01     1      123145356058624  0.010127  2
--        MainThread        0      4321620864       0.001632  6
--        '''
--        self.assert_ctx_stats_almost_equal(r1, tstats)
--
--    def test_producer_consumer_with_queues(self):
--        # we currently just stress yappi, no functionality test is done here.
--        yappi.start()
--        if utils.is_py3x():
--            from queue import Queue
--        else:
--            from Queue import Queue
--        from threading import Thread
--        WORKER_THREAD_COUNT = 50
--        WORK_ITEM_COUNT = 2000
--
--        def worker():
--            while True:
--                item = q.get()
--                # do the work with item
--                q.task_done()
--
--        q = Queue()
--        for i in range(WORKER_THREAD_COUNT):
--            t = Thread(target=worker)
--            t.daemon = True
--            t.start()
--
--        for item in range(WORK_ITEM_COUNT):
--            q.put(item)
--        q.join()  # block until all tasks are done
--        #yappi.get_func_stats().sort("callcount").print_all()
--        yappi.stop()
--
--    def test_temporary_lock_waiting(self):
--        yappi.start()
--        _lock = threading.Lock()
--
--        def worker():
--            _lock.acquire()
--            try:
--                time.sleep(1.0)
--            finally:
--                _lock.release()
--
--        t1 = threading.Thread(target=worker)
--        t2 = threading.Thread(target=worker)
--        t1.start()
--        t2.start()
--        t1.join()
--        t2.join()
--        #yappi.get_func_stats().sort("callcount").print_all()
--        yappi.stop()
--
--    @unittest.skipIf(os.name != "posix", "requires Posix compliant OS")
--    def test_signals_with_blocking_calls(self):
--        import signal, os, time
--
--        # just to verify if signal is handled correctly and stats/yappi are not corrupted.
--        def handler(signum, frame):
--            raise Exception("Signal handler executed!")
--
--        yappi.start()
--        signal.signal(signal.SIGALRM, handler)
--        signal.alarm(1)
--        self.assertRaises(Exception, time.sleep, 2)
--        stats = yappi.get_func_stats()
--        fsh = utils.find_stat_by_name(stats, "handler")
--        self.assertTrue(fsh is not None)
--
--    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
--    def test_concurrent_futures(self):
--        yappi.start()
--        from concurrent.futures import ThreadPoolExecutor
--        with ThreadPoolExecutor(max_workers=5) as executor:
--            f = executor.submit(pow, 5, 2)
--            self.assertEqual(f.result(), 25)
--        time.sleep(1.0)
--        yappi.stop()
--
--    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
--    def test_barrier(self):
--        yappi.start()
--        b = threading.Barrier(2, timeout=1)
--
--        def worker():
--            try:
--                b.wait()
--            except threading.BrokenBarrierError:
--                pass
--            except Exception:
--                raise Exception("BrokenBarrierError not raised")
--
--        t1 = threading.Thread(target=worker)
--        t1.start()
--        #b.wait()
--        t1.join()
--        yappi.stop()
--
--
--class NonRecursiveFunctions(utils.YappiUnitTestCase):
--
--    def test_abcd(self):
--        _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1}
--        _yappi._set_test_timings(_timings)
--
--        def a():
--            b()
--
--        def b():
--            c()
--
--        def c():
--            d()
--
--        def d():
--            pass
--
--        stats = utils.run_and_get_func_stats(a)
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        fsc = utils.find_stat_by_name(stats, 'c')
--        fsd = utils.find_stat_by_name(stats, 'd')
--        cfsab = fsa.children[fsb]
--        cfsbc = fsb.children[fsc]
--        cfscd = fsc.children[fsd]
--
--        self.assertEqual(fsa.ttot, 6)
--        self.assertEqual(fsa.tsub, 1)
--        self.assertEqual(fsb.ttot, 5)
--        self.assertEqual(fsb.tsub, 2)
--        self.assertEqual(fsc.ttot, 3)
--        self.assertEqual(fsc.tsub, 2)
--        self.assertEqual(fsd.ttot, 1)
--        self.assertEqual(fsd.tsub, 1)
--        self.assertEqual(cfsab.ttot, 5)
--        self.assertEqual(cfsab.tsub, 2)
--        self.assertEqual(cfsbc.ttot, 3)
--        self.assertEqual(cfsbc.tsub, 2)
--        self.assertEqual(cfscd.ttot, 1)
--        self.assertEqual(cfscd.tsub, 1)
--
--    def test_stop_in_middle(self):
--        _timings = {"a_1": 6, "b_1": 4}
--        _yappi._set_test_timings(_timings)
--
--        def a():
--            b()
--            yappi.stop()
--
--        def b():
--            time.sleep(0.2)
--
--        yappi.start()
--        a()
--        stats = yappi.get_func_stats()
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--
--        self.assertEqual(fsa.ncall, 1)
--        self.assertEqual(fsa.nactualcall, 0)
--        self.assertEqual(fsa.ttot, 0)  # no call_leave called
--        self.assertEqual(fsa.tsub, 0)  # no call_leave called
--        self.assertEqual(fsb.ttot, 4)
--
--
--class RecursiveFunctions(utils.YappiUnitTestCase):
--
--    def test_fibonacci(self):
--
--        def fib(n):
--            if n > 1:
--                return fib(n - 1) + fib(n - 2)
--            else:
--                return n
--
--        stats = utils.run_and_get_func_stats(fib, 22)
--        fs = utils.find_stat_by_name(stats, 'fib')
--        self.assertEqual(fs.ncall, 57313)
--        self.assertEqual(fs.ttot, fs.tsub)
--
--    def test_abcadc(self):
--        _timings = {
--            "a_1": 20,
--            "b_1": 19,
--            "c_1": 17,
--            "a_2": 13,
--            "d_1": 12,
--            "c_2": 10,
--            "a_3": 5
--        }
--        _yappi._set_test_timings(_timings)
--
--        def a(n):
--            if n == 3:
--                return
--            if n == 1 + 1:
--                d(n)
--            else:
--                b(n)
--
--        def b(n):
--            c(n)
--
--        def c(n):
--            a(n + 1)
--
--        def d(n):
--            c(n)
--
--        stats = utils.run_and_get_func_stats(a, 1)
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        fsc = utils.find_stat_by_name(stats, 'c')
--        fsd = utils.find_stat_by_name(stats, 'd')
--        self.assertEqual(fsa.ncall, 3)
--        self.assertEqual(fsa.nactualcall, 1)
--        self.assertEqual(fsa.ttot, 20)
--        self.assertEqual(fsa.tsub, 7)
--        self.assertEqual(fsb.ttot, 19)
--        self.assertEqual(fsb.tsub, 2)
--        self.assertEqual(fsc.ttot, 17)
--        self.assertEqual(fsc.tsub, 9)
--        self.assertEqual(fsd.ttot, 12)
--        self.assertEqual(fsd.tsub, 2)
--        cfsca = fsc.children[fsa]
--        self.assertEqual(cfsca.nactualcall, 0)
--        self.assertEqual(cfsca.ncall, 2)
--        self.assertEqual(cfsca.ttot, 13)
--        self.assertEqual(cfsca.tsub, 6)
--
--    def test_aaaa(self):
--        _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2}
--        _yappi._set_test_timings(_timings)
--
--        def d(n):
--            if n == 3:
--                return
--            d(n + 1)
--
--        stats = utils.run_and_get_func_stats(d, 0)
--        fsd = utils.find_stat_by_name(stats, 'd')
--        self.assertEqual(fsd.ncall, 4)
--        self.assertEqual(fsd.nactualcall, 1)
--        self.assertEqual(fsd.ttot, 9)
--        self.assertEqual(fsd.tsub, 9)
--        cfsdd = fsd.children[fsd]
--        self.assertEqual(cfsdd.ttot, 7)
--        self.assertEqual(cfsdd.tsub, 7)
--        self.assertEqual(cfsdd.ncall, 3)
--        self.assertEqual(cfsdd.nactualcall, 0)
--
--    def test_abcabc(self):
--        _timings = {
--            "a_1": 20,
--            "b_1": 19,
--            "c_1": 17,
--            "a_2": 13,
--            "b_2": 11,
--            "c_2": 9,
--            "a_3": 6
--        }
--        _yappi._set_test_timings(_timings)
--
--        def a(n):
--            if n == 3:
--                return
--            else:
--                b(n)
--
--        def b(n):
--            c(n)
--
--        def c(n):
--            a(n + 1)
--
--        stats = utils.run_and_get_func_stats(a, 1)
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        fsc = utils.find_stat_by_name(stats, 'c')
--        self.assertEqual(fsa.ncall, 3)
--        self.assertEqual(fsa.nactualcall, 1)
--        self.assertEqual(fsa.ttot, 20)
--        self.assertEqual(fsa.tsub, 9)
--        self.assertEqual(fsb.ttot, 19)
--        self.assertEqual(fsb.tsub, 4)
--        self.assertEqual(fsc.ttot, 17)
--        self.assertEqual(fsc.tsub, 7)
--        cfsab = fsa.children[fsb]
--        cfsbc = fsb.children[fsc]
--        cfsca = fsc.children[fsa]
--        self.assertEqual(cfsab.ttot, 19)
--        self.assertEqual(cfsab.tsub, 4)
--        self.assertEqual(cfsbc.ttot, 17)
--        self.assertEqual(cfsbc.tsub, 7)
--        self.assertEqual(cfsca.ttot, 13)
--        self.assertEqual(cfsca.tsub, 8)
--
--    def test_abcbca(self):
--        _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1}
--        _yappi._set_test_timings(_timings)
--        self._ncall = 1
--
--        def a():
--            if self._ncall == 1:
--                b()
--            else:
--                return
--
--        def b():
--            c()
--
--        def c():
--            if self._ncall == 1:
--                self._ncall += 1
--                b()
--            else:
--                a()
--
--        stats = utils.run_and_get_func_stats(a)
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        fsc = utils.find_stat_by_name(stats, 'c')
--        cfsab = fsa.children[fsb]
--        cfsbc = fsb.children[fsc]
--        cfsca = fsc.children[fsa]
--        self.assertEqual(fsa.ttot, 10)
--        self.assertEqual(fsa.tsub, 2)
--        self.assertEqual(fsb.ttot, 9)
--        self.assertEqual(fsb.tsub, 4)
--        self.assertEqual(fsc.ttot, 7)
--        self.assertEqual(fsc.tsub, 4)
--        self.assertEqual(cfsab.ttot, 9)
--        self.assertEqual(cfsab.tsub, 2)
--        self.assertEqual(cfsbc.ttot, 7)
--        self.assertEqual(cfsbc.tsub, 4)
--        self.assertEqual(cfsca.ttot, 1)
--        self.assertEqual(cfsca.tsub, 1)
--        self.assertEqual(cfsca.ncall, 1)
--        self.assertEqual(cfsca.nactualcall, 0)
--
--    def test_aabccb(self):
--        _timings = {
--            "a_1": 13,
--            "a_2": 11,
--            "b_1": 9,
--            "c_1": 5,
--            "c_2": 3,
--            "b_2": 1
--        }
--        _yappi._set_test_timings(_timings)
--        self._ncall = 1
--
--        def a():
--            if self._ncall == 1:
--                self._ncall += 1
--                a()
--            else:
--                b()
--
--        def b():
--            if self._ncall == 3:
--                return
--            else:
--                c()
--
--        def c():
--            if self._ncall == 2:
--                self._ncall += 1
--                c()
--            else:
--                b()
--
--        stats = utils.run_and_get_func_stats(a)
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        fsc = utils.find_stat_by_name(stats, 'c')
--        cfsaa = fsa.children[fsa.index]
--        cfsab = fsa.children[fsb]
--        cfsbc = fsb.children[fsc.full_name]
--        cfscc = fsc.children[fsc]
--        cfscb = fsc.children[fsb]
--        self.assertEqual(fsb.ttot, 9)
--        self.assertEqual(fsb.tsub, 5)
--        self.assertEqual(cfsbc.ttot, 5)
--        self.assertEqual(cfsbc.tsub, 2)
--        self.assertEqual(fsa.ttot, 13)
--        self.assertEqual(fsa.tsub, 4)
--        self.assertEqual(cfsab.ttot, 9)
--        self.assertEqual(cfsab.tsub, 4)
--        self.assertEqual(cfsaa.ttot, 11)
--        self.assertEqual(cfsaa.tsub, 2)
--        self.assertEqual(fsc.ttot, 5)
--        self.assertEqual(fsc.tsub, 4)
--
--    def test_abaa(self):
--        _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5}
--        _yappi._set_test_timings(_timings)
--
--        self._ncall = 1
--
--        def a():
--            if self._ncall == 1:
--                b()
--            elif self._ncall == 2:
--                self._ncall += 1
--                a()
--            else:
--                return
--
--        def b():
--            self._ncall += 1
--            a()
--
--        stats = utils.run_and_get_func_stats(a)
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        cfsaa = fsa.children[fsa]
--        cfsba = fsb.children[fsa]
--        self.assertEqual(fsb.ttot, 10)
--        self.assertEqual(fsb.tsub, 1)
--        self.assertEqual(fsa.ttot, 13)
--        self.assertEqual(fsa.tsub, 12)
--        self.assertEqual(cfsaa.ttot, 5)
--        self.assertEqual(cfsaa.tsub, 5)
--        self.assertEqual(cfsba.ttot, 9)
--        self.assertEqual(cfsba.tsub, 4)
--
--    def test_aabb(self):
--        _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5}
--        _yappi._set_test_timings(_timings)
--
--        self._ncall = 1
--
--        def a():
--            if self._ncall == 1:
--                self._ncall += 1
--                a()
--            elif self._ncall == 2:
--                b()
--            else:
--                return
--
--        def b():
--            if self._ncall == 2:
--                self._ncall += 1
--                b()
--            else:
--                return
--
--        stats = utils.run_and_get_func_stats(a)
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        cfsaa = fsa.children[fsa]
--        cfsab = fsa.children[fsb]
--        cfsbb = fsb.children[fsb]
--        self.assertEqual(fsa.ttot, 13)
--        self.assertEqual(fsa.tsub, 4)
--        self.assertEqual(fsb.ttot, 9)
--        self.assertEqual(fsb.tsub, 9)
--        self.assertEqual(cfsaa.ttot, 10)
--        self.assertEqual(cfsaa.tsub, 1)
--        self.assertEqual(cfsab.ttot, 9)
--        self.assertEqual(cfsab.tsub, 4)
--        self.assertEqual(cfsbb.ttot, 5)
--        self.assertEqual(cfsbb.tsub, 5)
--
--    def test_abbb(self):
--        _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1}
--        _yappi._set_test_timings(_timings)
--
--        self._ncall = 1
--
--        def a():
--            if self._ncall == 1:
--                b()
--
--        def b():
--            if self._ncall == 3:
--                return
--            self._ncall += 1
--            b()
--
--        stats = utils.run_and_get_func_stats(a)
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        cfsab = fsa.children[fsb]
--        cfsbb = fsb.children[fsb]
--        self.assertEqual(fsa.ttot, 13)
--        self.assertEqual(fsa.tsub, 3)
--        self.assertEqual(fsb.ttot, 10)
--        self.assertEqual(fsb.tsub, 10)
--        self.assertEqual(fsb.ncall, 3)
--        self.assertEqual(fsb.nactualcall, 1)
--        self.assertEqual(cfsab.ttot, 10)
--        self.assertEqual(cfsab.tsub, 4)
--        self.assertEqual(cfsbb.ttot, 6)
--        self.assertEqual(cfsbb.tsub, 6)
--        self.assertEqual(cfsbb.nactualcall, 0)
--        self.assertEqual(cfsbb.ncall, 2)
--
--    def test_aaab(self):
--        _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1}
--        _yappi._set_test_timings(_timings)
--
--        self._ncall = 1
--
--        def a():
--            if self._ncall == 3:
--                b()
--                return
--            self._ncall += 1
--            a()
--
--        def b():
--            return
--
--        stats = utils.run_and_get_func_stats(a)
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        cfsaa = fsa.children[fsa]
--        cfsab = fsa.children[fsb]
--        self.assertEqual(fsa.ttot, 13)
--        self.assertEqual(fsa.tsub, 12)
--        self.assertEqual(fsb.ttot, 1)
--        self.assertEqual(fsb.tsub, 1)
--        self.assertEqual(cfsaa.ttot, 10)
--        self.assertEqual(cfsaa.tsub, 9)
--        self.assertEqual(cfsab.ttot, 1)
--        self.assertEqual(cfsab.tsub, 1)
--
--    def test_abab(self):
--        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
--        _yappi._set_test_timings(_timings)
--
--        self._ncall = 1
--
--        def a():
--            b()
--
--        def b():
--            if self._ncall == 2:
--                return
--            self._ncall += 1
--            a()
--
--        stats = utils.run_and_get_func_stats(a)
--        fsa = utils.find_stat_by_name(stats, 'a')
--        fsb = utils.find_stat_by_name(stats, 'b')
--        cfsab = fsa.children[fsb]
--        cfsba = fsb.children[fsa]
--        self.assertEqual(fsa.ttot, 13)
--        self.assertEqual(fsa.tsub, 8)
--        self.assertEqual(fsb.ttot, 10)
--        self.assertEqual(fsb.tsub, 5)
--        self.assertEqual(cfsab.ttot, 10)
--        self.assertEqual(cfsab.tsub, 5)
--        self.assertEqual(cfsab.ncall, 2)
--        self.assertEqual(cfsab.nactualcall, 1)
--        self.assertEqual(cfsba.ttot, 6)
--        self.assertEqual(cfsba.tsub, 5)
--
--
--if __name__ == '__main__':
--    #     import sys;sys.argv = ['', 'BasicUsage.test_run_as_script']
--    #     import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile']
--    unittest.main()
-+import os
-+import sys
-+import time
-+import threading
-+import unittest
-+import yappi
-+import _yappi
-+import tests.utils as utils
-+import multiprocessing  # added to fix http://bugs.python.org/issue15881 for > Py2.6
-+import subprocess
-+
-+_counter = 0
-+
-+
-+class BasicUsage(utils.YappiUnitTestCase):
-+
-+    def test_callback_function_int_return_overflow(self):
-+        # this test is just here to check if any errors are generated, as the err
-+        # is printed in C side, I did not include it here. THere are ways to test
-+        # this deterministically, I did not bother
-+        import ctypes
-+
-+        def _unsigned_overflow_margin():
-+            return 2**(ctypes.sizeof(ctypes.c_void_p) * 8) - 1
-+
-+        def foo():
-+            pass
-+
-+        #with utils.captured_output() as (out, err):
-+        yappi.set_context_id_callback(_unsigned_overflow_margin)
-+        yappi.set_tag_callback(_unsigned_overflow_margin)
-+        yappi.start()
-+        foo()
-+
-+    def test_issue60(self):
-+
-+        def foo():
-+            buf = bytearray()
-+            buf += b't' * 200
-+            view = memoryview(buf)[10:]
-+            view = view.tobytes()
-+            del buf[:10]  # this throws exception
-+            return view
-+
-+        yappi.start(builtins=True)
-+        foo()
-+        self.assertTrue(
-+            len(
-+                yappi.get_func_stats(
-+                    filter_callback=lambda x: yappi.
-+                    func_matches(x, [memoryview.tobytes])
-+                )
-+            ) > 0
-+        )
-+        yappi.stop()
-+
-+    def test_issue54(self):
-+
-+        def _tag_cbk():
-+            global _counter
-+            _counter += 1
-+            return _counter
-+
-+        def a():
-+            pass
-+
-+        def b():
-+            pass
-+
-+        yappi.set_tag_callback(_tag_cbk)
-+        yappi.start()
-+        a()
-+        a()
-+        a()
-+        yappi.stop()
-+        stats = yappi.get_func_stats()
-+        self.assertEqual(stats.pop().ncall, 3)  # aggregated if no tag is given
-+        stats = yappi.get_func_stats(tag=1)
-+
-+        for i in range(1, 3):
-+            stats = yappi.get_func_stats(tag=i)
-+            stats = yappi.get_func_stats(
-+                tag=i, filter_callback=lambda x: yappi.func_matches(x, [a])
-+            )
-+
-+            stat = stats.pop()
-+            self.assertEqual(stat.ncall, 1)
-+
-+        yappi.set_tag_callback(None)
-+        yappi.clear_stats()
-+        yappi.start()
-+        b()
-+        b()
-+        stats = yappi.get_func_stats()
-+        self.assertEqual(len(stats), 1)
-+        stat = stats.pop()
-+        self.assertEqual(stat.ncall, 2)
-+
-+    def test_filter(self):
-+
-+        def a():
-+            pass
-+
-+        def b():
-+            a()
-+
-+        def c():
-+            b()
-+
-+        _TCOUNT = 5
-+
-+        ts = []
-+        yappi.start()
-+        for i in range(_TCOUNT):
-+            t = threading.Thread(target=c)
-+            t.start()
-+            ts.append(t)
-+
-+        for t in ts:
-+            t.join()
-+
-+        yappi.stop()
-+
-+        ctx_ids = []
-+        for tstat in yappi.get_thread_stats():
-+            if tstat.name == '_MainThread':
-+                main_ctx_id = tstat.id
-+            else:
-+                ctx_ids.append(tstat.id)
-+
-+        fstats = yappi.get_func_stats(filter={"ctx_id": 9})
-+        self.assertTrue(fstats.empty())
-+        fstats = yappi.get_func_stats(
-+            filter={
-+                "ctx_id": main_ctx_id,
-+                "name": "c"
-+            }
-+        )  # main thread
-+        self.assertTrue(fstats.empty())
-+
-+        for i in ctx_ids:
-+            fstats = yappi.get_func_stats(
-+                filter={
-+                    "ctx_id": i,
-+                    "name": "a",
-+                    "ncall": 1
-+                }
-+            )
-+            self.assertEqual(fstats.pop().ncall, 1)
-+            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "b"})
-+            self.assertEqual(fstats.pop().ncall, 1)
-+            fstats = yappi.get_func_stats(filter={"ctx_id": i, "name": "c"})
-+            self.assertEqual(fstats.pop().ncall, 1)
-+
-+        yappi.clear_stats()
-+        yappi.start(builtins=True)
-+        time.sleep(0.1)
-+        yappi.stop()
-+        fstats = yappi.get_func_stats(filter={"module": "time"})
-+        self.assertEqual(len(fstats), 1)
-+
-+        # invalid filters`
-+        self.assertRaises(
-+            Exception, yappi.get_func_stats, filter={'tag': "sss"}
-+        )
-+        self.assertRaises(
-+            Exception, yappi.get_func_stats, filter={'ctx_id': "None"}
-+        )
-+
-+    def test_filter_callback(self):
-+
-+        def a():
-+            time.sleep(0.1)
-+
-+        def b():
-+            a()
-+
-+        def c():
-+            pass
-+
-+        def d():
-+            pass
-+
-+        yappi.set_clock_type("wall")
-+        yappi.start(builtins=True)
-+        a()
-+        b()
-+        c()
-+        d()
-+        stats = yappi.get_func_stats(
-+            filter_callback=lambda x: yappi.func_matches(x, [a, b])
-+        )
-+        #stats.print_all()
-+        r1 = '''
-+        tests/test_functionality.py:98 a      2      0.000000  0.200350  0.100175
-+        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.100197
-+        '''
-+        self.assert_traces_almost_equal(r1, stats)
-+        self.assertEqual(len(stats), 2)
-+        stats = yappi.get_func_stats(
-+            filter_callback=lambda x: yappi.
-+            module_matches(x, [sys.modules[__name__]])
-+        )
-+        r1 = '''
-+        tests/test_functionality.py:98 a      2      0.000000  0.230130  0.115065
-+        tests/test_functionality.py:101 b     1      0.000000  0.120000  0.109011
-+        tests/test_functionality.py:104 c     1      0.000000  0.000002  0.000002
-+        tests/test_functionality.py:107 d     1      0.000000  0.000001  0.000001
-+        '''
-+        self.assert_traces_almost_equal(r1, stats)
-+        self.assertEqual(len(stats), 4)
-+
-+        stats = yappi.get_func_stats(
-+            filter_callback=lambda x: yappi.func_matches(x, [time.sleep])
-+        )
-+        self.assertEqual(len(stats), 1)
-+        r1 = '''
-+        time.sleep                            2      0.206804  0.220000  0.103402
-+        '''
-+        self.assert_traces_almost_equal(r1, stats)
-+
-+    def test_print_formatting(self):
-+
-+        def a():
-+            pass
-+
-+        def b():
-+            a()
-+
-+        func_cols = {
-+            1: ("name", 48),
-+            0: ("ncall", 5),
-+            2: ("tsub", 8),
-+        }
-+        thread_cols = {
-+            1: ("name", 48),
-+            0: ("ttot", 8),
-+        }
-+
-+        yappi.start()
-+        a()
-+        b()
-+        yappi.stop()
-+        fs = yappi.get_func_stats()
-+        cs = fs[1].children
-+        ts = yappi.get_thread_stats()
-+        #fs.print_all(out=sys.stderr, columns={1:("name", 70), })
-+        #cs.print_all(out=sys.stderr, columns=func_cols)
-+        #ts.print_all(out=sys.stderr, columns=thread_cols)
-+        #cs.print_all(out=sys.stderr, columns={})
-+
-+        self.assertRaises(
-+            yappi.YappiError, fs.print_all, columns={1: ("namee", 9)}
-+        )
-+        self.assertRaises(
-+            yappi.YappiError, cs.print_all, columns={1: ("dd", 0)}
-+        )
-+        self.assertRaises(
-+            yappi.YappiError, ts.print_all, columns={1: ("tidd", 0)}
-+        )
-+
-+    def test_get_clock(self):
-+        yappi.set_clock_type('cpu')
-+        self.assertEqual('cpu', yappi.get_clock_type())
-+        clock_info = yappi.get_clock_info()
-+        self.assertTrue('api' in clock_info)
-+        self.assertTrue('resolution' in clock_info)
-+
-+        yappi.set_clock_type('wall')
-+        self.assertEqual('wall', yappi.get_clock_type())
-+
-+        t0 = yappi.get_clock_time()
-+        time.sleep(0.1)
-+        duration = yappi.get_clock_time() - t0
-+        self.assertTrue(0.05 < duration < 0.3)
-+
-+    def test_profile_decorator(self):
-+
-+        def aggregate(func, stats):
-+            fname = "tests/%s.profile" % (func.__name__)
-+            try:
-+                stats.add(fname)
-+            except IOError:
-+                pass
-+            stats.save(fname)
-+            raise Exception("messing around")
-+
-+        @yappi.profile(return_callback=aggregate)
-+        def a(x, y):
-+            if x + y == 25:
-+                raise Exception("")
-+            return x + y
-+
-+        def b():
-+            pass
-+
-+        try:
-+            os.remove(
-+                "tests/a.profile"
-+            )  # remove the one from prev test, if available
-+        except:
-+            pass
-+
-+        # global profile is on to mess things up
-+        yappi.start()
-+        b()
-+
-+        # assert functionality and call function at same time
-+        try:
-+            self.assertEqual(a(1, 2), 3)
-+        except:
-+            pass
-+        try:
-+            self.assertEqual(a(2, 5), 7)
-+        except:
-+            pass
-+        try:
-+            a(4, 21)
-+        except:
-+            pass
-+        stats = yappi.get_func_stats().add("tests/a.profile")
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        self.assertEqual(fsa.ncall, 3)
-+        self.assertEqual(len(stats), 1)  # b() should be cleared out.
-+
-+        @yappi.profile(return_callback=aggregate)
-+        def count_down_rec(n):
-+            if n == 0:
-+                return
-+            count_down_rec(n - 1)
-+
-+        try:
-+            os.remove(
-+                "tests/count_down_rec.profile"
-+            )  # remove the one from prev test, if available
-+        except:
-+            pass
-+
-+        try:
-+            count_down_rec(4)
-+        except:
-+            pass
-+        try:
-+            count_down_rec(3)
-+        except:
-+            pass
-+
-+        stats = yappi.YFuncStats("tests/count_down_rec.profile")
-+        fsrec = utils.find_stat_by_name(stats, 'count_down_rec')
-+        self.assertEqual(fsrec.ncall, 9)
-+        self.assertEqual(fsrec.nactualcall, 2)
-+
-+    def test_strip_dirs(self):
-+
-+        def a():
-+            pass
-+
-+        stats = utils.run_and_get_func_stats(a, )
-+        stats.strip_dirs()
-+        fsa = utils.find_stat_by_name(stats, "a")
-+        self.assertEqual(fsa.module, os.path.basename(fsa.module))
-+
-+    @unittest.skipIf(os.name == "nt", "do not run on Windows")
-+    def test_run_as_script(self):
-+        import re
-+        p = subprocess.Popen(
-+            ['yappi', os.path.join('./tests', 'run_as_script.py')],
-+            stdout=subprocess.PIPE
-+        )
-+        out, err = p.communicate()
-+        self.assertEqual(p.returncode, 0)
-+        func_stats, thread_stats = re.split(
-+            b'name\\s+id\\s+tid\\s+ttot\\s+scnt\\s*\n', out
-+        )
-+        self.assertTrue(b'FancyThread' in thread_stats)
-+
-+    def test_yappi_overhead(self):
-+        LOOP_COUNT = 100000
-+
-+        def a():
-+            pass
-+
-+        def b():
-+            for i in range(LOOP_COUNT):
-+                a()
-+
-+        t0 = time.time()
-+        yappi.start()
-+        b()
-+        yappi.stop()
-+        time_with_yappi = time.time() - t0
-+        t0 = time.time()
-+        b()
-+        time_without_yappi = time.time() - t0
-+        if time_without_yappi == 0:
-+            time_without_yappi = 0.000001
-+
-+        # in latest v0.82, I calculated this as close to "7.0" in my machine.
-+        # however, %83 of this overhead is coming from tickcount(). The other %17
-+        # seems to have been evenly distributed to the internal bookkeeping
-+        # structures/algorithms which seems acceptable. Note that our test only
-+        # tests one function being profiled at-a-time in a short interval.
-+        # profiling high number of functions in a small time
-+        # is a different beast, (which is pretty unlikely in most applications)
-+        # So as a conclusion: I cannot see any optimization window for Yappi that
-+        # is worth implementing as we will only optimize %17 of the time.
-+        sys.stderr.write("\r\nYappi puts %0.1f times overhead to the profiled application in average.\r\n" % \
-+            (time_with_yappi / time_without_yappi))
-+
-+    def test_clear_stats_while_running(self):
-+
-+        def a():
-+            pass
-+
-+        yappi.start()
-+        a()
-+        yappi.clear_stats()
-+        a()
-+        stats = yappi.get_func_stats()
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        self.assertEqual(fsa.ncall, 1)
-+
-+    def test_generator(self):
-+
-+        def _gen(n):
-+            while (n > 0):
-+                yield n
-+                n -= 1
-+
-+        yappi.start()
-+        for x in _gen(5):
-+            pass
-+        self.assertTrue(
-+            yappi.convert2pstats(yappi.get_func_stats()) is not None
-+        )
-+
-+    def test_slice_child_stats_and_strip_dirs(self):
-+
-+        def b():
-+            for i in range(10000000):
-+                pass
-+
-+        def a():
-+            b()
-+
-+        yappi.start(builtins=True)
-+        a()
-+        stats = yappi.get_func_stats()
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        self.assertTrue(fsa.children[0:1] is not None)
-+        prev_afullname = fsa.full_name
-+        prev_bchildfullname = fsa.children[fsb].full_name
-+        stats.strip_dirs()
-+        self.assertTrue(len(prev_afullname) > len(fsa.full_name))
-+        self.assertTrue(
-+            len(prev_bchildfullname) > len(fsa.children[fsb].full_name)
-+        )
-+
-+    def test_children_stat_functions(self):
-+        _timings = {"a_1": 5, "b_1": 3, "c_1": 1}
-+        _yappi._set_test_timings(_timings)
-+
-+        def b():
-+            pass
-+
-+        def c():
-+            pass
-+
-+        def a():
-+            b()
-+            c()
-+
-+        yappi.start()
-+        a()
-+        b()  # non-child call
-+        c()  # non-child call
-+        stats = yappi.get_func_stats()
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        childs_of_a = fsa.children.get().sort("tavg", "desc")
-+        prev_item = None
-+        for item in childs_of_a:
-+            if prev_item:
-+                self.assertTrue(prev_item.tavg > item.tavg)
-+            prev_item = item
-+        childs_of_a.sort("name", "desc")
-+        prev_item = None
-+        for item in childs_of_a:
-+            if prev_item:
-+                self.assertTrue(prev_item.name > item.name)
-+            prev_item = item
-+        childs_of_a.clear()
-+        self.assertTrue(childs_of_a.empty())
-+
-+    def test_no_stats_different_clock_type_load(self):
-+
-+        def a():
-+            pass
-+
-+        yappi.start()
-+        a()
-+        yappi.stop()
-+        yappi.get_func_stats().save("tests/ystats1.ys")
-+        yappi.clear_stats()
-+        yappi.set_clock_type("WALL")
-+        yappi.start()
-+        yappi.stop()
-+        stats = yappi.get_func_stats().add("tests/ystats1.ys")
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        self.assertTrue(fsa is not None)
-+
-+    def test_subsequent_profile(self):
-+        _timings = {"a_1": 1, "b_1": 1}
-+        _yappi._set_test_timings(_timings)
-+
-+        def a():
-+            pass
-+
-+        def b():
-+            pass
-+
-+        yappi.start()
-+        a()
-+        yappi.stop()
-+        yappi.start()
-+        b()
-+        yappi.stop()
-+        stats = yappi.get_func_stats()
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        self.assertTrue(fsa is not None)
-+        self.assertTrue(fsb is not None)
-+        self.assertEqual(fsa.ttot, 1)
-+        self.assertEqual(fsb.ttot, 1)
-+
-+    def test_lambda(self):
-+        f = lambda: time.sleep(0.3)
-+        yappi.set_clock_type("wall")
-+        yappi.start()
-+        f()
-+        stats = yappi.get_func_stats()
-+        fsa = utils.find_stat_by_name(stats, '<lambda>')
-+        self.assertTrue(fsa.ttot > 0.1)
-+
-+    def test_module_stress(self):
-+        self.assertEqual(yappi.is_running(), False)
-+
-+        yappi.start()
-+        yappi.clear_stats()
-+        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
-+
-+        yappi.stop()
-+        yappi.clear_stats()
-+        yappi.set_clock_type("cpu")
-+        self.assertRaises(yappi.YappiError, yappi.set_clock_type, "dummy")
-+        self.assertEqual(yappi.is_running(), False)
-+        yappi.clear_stats()
-+        yappi.clear_stats()
-+
-+    def test_stat_sorting(self):
-+        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
-+        _yappi._set_test_timings(_timings)
-+
-+        self._ncall = 1
-+
-+        def a():
-+            b()
-+
-+        def b():
-+            if self._ncall == 2:
-+                return
-+            self._ncall += 1
-+            a()
-+
-+        stats = utils.run_and_get_func_stats(a)
-+        stats = stats.sort("totaltime", "desc")
-+        prev_stat = None
-+        for stat in stats:
-+            if prev_stat:
-+                self.assertTrue(prev_stat.ttot >= stat.ttot)
-+            prev_stat = stat
-+        stats = stats.sort("totaltime", "asc")
-+        prev_stat = None
-+        for stat in stats:
-+            if prev_stat:
-+                self.assertTrue(prev_stat.ttot <= stat.ttot)
-+            prev_stat = stat
-+        stats = stats.sort("avgtime", "asc")
-+        prev_stat = None
-+        for stat in stats:
-+            if prev_stat:
-+                self.assertTrue(prev_stat.tavg <= stat.tavg)
-+            prev_stat = stat
-+        stats = stats.sort("name", "asc")
-+        prev_stat = None
-+        for stat in stats:
-+            if prev_stat:
-+                self.assertTrue(prev_stat.name <= stat.name)
-+            prev_stat = stat
-+        stats = stats.sort("subtime", "asc")
-+        prev_stat = None
-+        for stat in stats:
-+            if prev_stat:
-+                self.assertTrue(prev_stat.tsub <= stat.tsub)
-+            prev_stat = stat
-+
-+        self.assertRaises(
-+            yappi.YappiError, stats.sort, "invalid_func_sorttype_arg"
-+        )
-+        self.assertRaises(
-+            yappi.YappiError, stats.sort, "totaltime",
-+            "invalid_func_sortorder_arg"
-+        )
-+
-+    def test_start_flags(self):
-+        self.assertEqual(_yappi._get_start_flags(), None)
-+        yappi.start()
-+
-+        def a():
-+            pass
-+
-+        a()
-+        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
-+        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
-+        self.assertEqual(len(yappi.get_thread_stats()), 1)
-+
-+    def test_builtin_profiling(self):
-+
-+        def a():
-+            time.sleep(0.4)  # is a builtin function
-+
-+        yappi.set_clock_type('wall')
-+
-+        yappi.start(builtins=True)
-+        a()
-+        stats = yappi.get_func_stats()
-+        fsa = utils.find_stat_by_name(stats, 'sleep')
-+        self.assertTrue(fsa is not None)
-+        self.assertTrue(fsa.ttot > 0.3)
-+        yappi.stop()
-+        yappi.clear_stats()
-+
-+        def a():
-+            pass
-+
-+        yappi.start()
-+        t = threading.Thread(target=a)
-+        t.start()
-+        t.join()
-+        stats = yappi.get_func_stats()
-+
-+    def test_singlethread_profiling(self):
-+        yappi.set_clock_type('wall')
-+
-+        def a():
-+            time.sleep(0.2)
-+
-+        class Worker1(threading.Thread):
-+
-+            def a(self):
-+                time.sleep(0.3)
-+
-+            def run(self):
-+                self.a()
-+
-+        yappi.start(profile_threads=False)
-+
-+        c = Worker1()
-+        c.start()
-+        c.join()
-+        a()
-+        stats = yappi.get_func_stats()
-+        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
-+        fsa2 = utils.find_stat_by_name(stats, 'a')
-+        self.assertTrue(fsa1 is None)
-+        self.assertTrue(fsa2 is not None)
-+        self.assertTrue(fsa2.ttot > 0.1)
-+
-+    def test_run(self):
-+
-+        def profiled():
-+            pass
-+
-+        yappi.clear_stats()
-+        try:
-+            with yappi.run():
-+                profiled()
-+            stats = yappi.get_func_stats()
-+        finally:
-+            yappi.clear_stats()
-+
-+        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
-+
-+    def test_run_recursive(self):
-+
-+        def profiled():
-+            pass
-+
-+        def not_profiled():
-+            pass
-+
-+        yappi.clear_stats()
-+        try:
-+            with yappi.run():
-+                with yappi.run():
-+                    profiled()
-+                # Profiling stopped here
-+                not_profiled()
-+            stats = yappi.get_func_stats()
-+        finally:
-+            yappi.clear_stats()
-+
-+        self.assertIsNotNone(utils.find_stat_by_name(stats, 'profiled'))
-+        self.assertIsNone(utils.find_stat_by_name(stats, 'not_profiled'))
-+
-+
-+class StatSaveScenarios(utils.YappiUnitTestCase):
-+
-+    def test_pstats_conversion(self):
-+
-+        def pstat_id(fs):
-+            return (fs.module, fs.lineno, fs.name)
-+
-+        def a():
-+            d()
-+
-+        def b():
-+            d()
-+
-+        def c():
-+            pass
-+
-+        def d():
-+            pass
-+
-+        _timings = {"a_1": 12, "b_1": 7, "c_1": 5, "d_1": 2}
-+        _yappi._set_test_timings(_timings)
-+        stats = utils.run_and_get_func_stats(a, )
-+        stats.strip_dirs()
-+        stats.save("tests/a1.pstats", type="pstat")
-+        fsa_pid = pstat_id(utils.find_stat_by_name(stats, "a"))
-+        fsd_pid = pstat_id(utils.find_stat_by_name(stats, "d"))
-+        yappi.clear_stats()
-+        _yappi._set_test_timings(_timings)
-+        stats = utils.run_and_get_func_stats(a, )
-+        stats.strip_dirs()
-+        stats.save("tests/a2.pstats", type="pstat")
-+        yappi.clear_stats()
-+        _yappi._set_test_timings(_timings)
-+        stats = utils.run_and_get_func_stats(b, )
-+        stats.strip_dirs()
-+        stats.save("tests/b1.pstats", type="pstat")
-+        fsb_pid = pstat_id(utils.find_stat_by_name(stats, "b"))
-+        yappi.clear_stats()
-+        _yappi._set_test_timings(_timings)
-+        stats = utils.run_and_get_func_stats(c, )
-+        stats.strip_dirs()
-+        stats.save("tests/c1.pstats", type="pstat")
-+        fsc_pid = pstat_id(utils.find_stat_by_name(stats, "c"))
-+
-+        # merge saved stats and check pstats values are correct
-+        import pstats
-+        p = pstats.Stats(
-+            'tests/a1.pstats', 'tests/a2.pstats', 'tests/b1.pstats',
-+            'tests/c1.pstats'
-+        )
-+        p.strip_dirs()
-+        # ct = ttot, tt = tsub
-+        (cc, nc, tt, ct, callers) = p.stats[fsa_pid]
-+        self.assertEqual(cc, nc, 2)
-+        self.assertEqual(tt, 20)
-+        self.assertEqual(ct, 24)
-+        (cc, nc, tt, ct, callers) = p.stats[fsd_pid]
-+        self.assertEqual(cc, nc, 3)
-+        self.assertEqual(tt, 6)
-+        self.assertEqual(ct, 6)
-+        self.assertEqual(len(callers), 2)
-+        (cc, nc, tt, ct) = callers[fsa_pid]
-+        self.assertEqual(cc, nc, 2)
-+        self.assertEqual(tt, 4)
-+        self.assertEqual(ct, 4)
-+        (cc, nc, tt, ct) = callers[fsb_pid]
-+        self.assertEqual(cc, nc, 1)
-+        self.assertEqual(tt, 2)
-+        self.assertEqual(ct, 2)
-+
-+    def test_merge_stats(self):
-+        _timings = {
-+            "a_1": 15,
-+            "b_1": 14,
-+            "c_1": 12,
-+            "d_1": 10,
-+            "e_1": 9,
-+            "f_1": 7,
-+            "g_1": 6,
-+            "h_1": 5,
-+            "i_1": 1
-+        }
-+        _yappi._set_test_timings(_timings)
-+
-+        def a():
-+            b()
-+
-+        def b():
-+            c()
-+
-+        def c():
-+            d()
-+
-+        def d():
-+            e()
-+
-+        def e():
-+            f()
-+
-+        def f():
-+            g()
-+
-+        def g():
-+            h()
-+
-+        def h():
-+            i()
-+
-+        def i():
-+            pass
-+
-+        yappi.start()
-+        a()
-+        a()
-+        yappi.stop()
-+        stats = yappi.get_func_stats()
-+        self.assertRaises(
-+            NotImplementedError, stats.save, "", "INVALID_SAVE_TYPE"
-+        )
-+        stats.save("tests/ystats2.ys")
-+        yappi.clear_stats()
-+        _yappi._set_test_timings(_timings)
-+        yappi.start()
-+        a()
-+        stats = yappi.get_func_stats().add("tests/ystats2.ys")
-+        fsa = utils.find_stat_by_name(stats, "a")
-+        fsb = utils.find_stat_by_name(stats, "b")
-+        fsc = utils.find_stat_by_name(stats, "c")
-+        fsd = utils.find_stat_by_name(stats, "d")
-+        fse = utils.find_stat_by_name(stats, "e")
-+        fsf = utils.find_stat_by_name(stats, "f")
-+        fsg = utils.find_stat_by_name(stats, "g")
-+        fsh = utils.find_stat_by_name(stats, "h")
-+        fsi = utils.find_stat_by_name(stats, "i")
-+        self.assertEqual(fsa.ttot, 45)
-+        self.assertEqual(fsa.ncall, 3)
-+        self.assertEqual(fsa.nactualcall, 3)
-+        self.assertEqual(fsa.tsub, 3)
-+        self.assertEqual(fsa.children[fsb].ttot, fsb.ttot)
-+        self.assertEqual(fsa.children[fsb].tsub, fsb.tsub)
-+        self.assertEqual(fsb.children[fsc].ttot, fsc.ttot)
-+        self.assertEqual(fsb.children[fsc].tsub, fsc.tsub)
-+        self.assertEqual(fsc.tsub, 6)
-+        self.assertEqual(fsc.children[fsd].ttot, fsd.ttot)
-+        self.assertEqual(fsc.children[fsd].tsub, fsd.tsub)
-+        self.assertEqual(fsd.children[fse].ttot, fse.ttot)
-+        self.assertEqual(fsd.children[fse].tsub, fse.tsub)
-+        self.assertEqual(fse.children[fsf].ttot, fsf.ttot)
-+        self.assertEqual(fse.children[fsf].tsub, fsf.tsub)
-+        self.assertEqual(fsf.children[fsg].ttot, fsg.ttot)
-+        self.assertEqual(fsf.children[fsg].tsub, fsg.tsub)
-+        self.assertEqual(fsg.ttot, 18)
-+        self.assertEqual(fsg.tsub, 3)
-+        self.assertEqual(fsg.children[fsh].ttot, fsh.ttot)
-+        self.assertEqual(fsg.children[fsh].tsub, fsh.tsub)
-+        self.assertEqual(fsh.ttot, 15)
-+        self.assertEqual(fsh.tsub, 12)
-+        self.assertEqual(fsh.tavg, 5)
-+        self.assertEqual(fsh.children[fsi].ttot, fsi.ttot)
-+        self.assertEqual(fsh.children[fsi].tsub, fsi.tsub)
-+        #stats.debug_print()
-+
-+    def test_merge_multithreaded_stats(self):
-+        import _yappi
-+        timings = {"a_1": 2, "b_1": 1}
-+        _yappi._set_test_timings(timings)
-+
-+        def a():
-+            pass
-+
-+        def b():
-+            pass
-+
-+        yappi.start()
-+        t = threading.Thread(target=a)
-+        t.start()
-+        t.join()
-+        t = threading.Thread(target=b)
-+        t.start()
-+        t.join()
-+        yappi.get_func_stats().save("tests/ystats1.ys")
-+        yappi.clear_stats()
-+        _yappi._set_test_timings(timings)
-+        self.assertEqual(len(yappi.get_func_stats()), 0)
-+        self.assertEqual(len(yappi.get_thread_stats()), 1)
-+        t = threading.Thread(target=a)
-+        t.start()
-+        t.join()
-+
-+        self.assertEqual(_yappi._get_start_flags()["profile_builtins"], 0)
-+        self.assertEqual(_yappi._get_start_flags()["profile_multicontext"], 1)
-+        yappi.get_func_stats().save("tests/ystats2.ys")
-+
-+        stats = yappi.YFuncStats([
-+            "tests/ystats1.ys",
-+            "tests/ystats2.ys",
-+        ])
-+        fsa = utils.find_stat_by_name(stats, "a")
-+        fsb = utils.find_stat_by_name(stats, "b")
-+        self.assertEqual(fsa.ncall, 2)
-+        self.assertEqual(fsb.ncall, 1)
-+        self.assertEqual(fsa.tsub, fsa.ttot, 4)
-+        self.assertEqual(fsb.tsub, fsb.ttot, 1)
-+
-+    def test_merge_load_different_clock_types(self):
-+        yappi.start(builtins=True)
-+
-+        def a():
-+            b()
-+
-+        def b():
-+            c()
-+
-+        def c():
-+            pass
-+
-+        t = threading.Thread(target=a)
-+        t.start()
-+        t.join()
-+        yappi.get_func_stats().sort("name", "asc").save("tests/ystats1.ys")
-+        yappi.stop()
-+        yappi.clear_stats()
-+        yappi.start(builtins=False)
-+        t = threading.Thread(target=a)
-+        t.start()
-+        t.join()
-+        yappi.get_func_stats().save("tests/ystats2.ys")
-+        yappi.stop()
-+        self.assertRaises(_yappi.error, yappi.set_clock_type, "wall")
-+        yappi.clear_stats()
-+        yappi.set_clock_type("wall")
-+        yappi.start()
-+        t = threading.Thread(target=a)
-+        t.start()
-+        t.join()
-+        yappi.get_func_stats().save("tests/ystats3.ys")
-+        self.assertRaises(
-+            yappi.YappiError,
-+            yappi.YFuncStats().add("tests/ystats1.ys").add, "tests/ystats3.ys"
-+        )
-+        stats = yappi.YFuncStats(["tests/ystats1.ys",
-+                                  "tests/ystats2.ys"]).sort("name")
-+        fsa = utils.find_stat_by_name(stats, "a")
-+        fsb = utils.find_stat_by_name(stats, "b")
-+        fsc = utils.find_stat_by_name(stats, "c")
-+        self.assertEqual(fsa.ncall, 2)
-+        self.assertEqual(fsa.ncall, fsb.ncall, fsc.ncall)
-+
-+    def test_merge_aabab_aabbc(self):
-+        _timings = {
-+            "a_1": 15,
-+            "a_2": 14,
-+            "b_1": 12,
-+            "a_3": 10,
-+            "b_2": 9,
-+            "c_1": 4
-+        }
-+        _yappi._set_test_timings(_timings)
-+
-+        def a():
-+            if self._ncall == 1:
-+                self._ncall += 1
-+                a()
-+            elif self._ncall == 5:
-+                self._ncall += 1
-+                a()
-+            else:
-+                b()
-+
-+        def b():
-+            if self._ncall == 2:
-+                self._ncall += 1
-+                a()
-+            elif self._ncall == 6:
-+                self._ncall += 1
-+                b()
-+            elif self._ncall == 7:
-+                c()
-+            else:
-+                return
-+
-+        def c():
-+            pass
-+
-+        self._ncall = 1
-+        stats = utils.run_and_get_func_stats(a, )
-+        stats.save("tests/ystats1.ys")
-+        yappi.clear_stats()
-+        _yappi._set_test_timings(_timings)
-+        #stats.print_all()
-+
-+        self._ncall = 5
-+        stats = utils.run_and_get_func_stats(a, )
-+        stats.save("tests/ystats2.ys")
-+
-+        #stats.print_all()
-+
-+        def a():  # same name but another function(code object)
-+            pass
-+
-+        yappi.start()
-+        a()
-+        stats = yappi.get_func_stats().add(
-+            ["tests/ystats1.ys", "tests/ystats2.ys"]
-+        )
-+        #stats.print_all()
-+        self.assertEqual(len(stats), 4)
-+
-+        fsa = None
-+        for stat in stats:
-+            if stat.name == "a" and stat.ttot == 45:
-+                fsa = stat
-+                break
-+        self.assertTrue(fsa is not None)
-+
-+        self.assertEqual(fsa.ncall, 7)
-+        self.assertEqual(fsa.nactualcall, 3)
-+        self.assertEqual(fsa.ttot, 45)
-+        self.assertEqual(fsa.tsub, 10)
-+        fsb = utils.find_stat_by_name(stats, "b")
-+        fsc = utils.find_stat_by_name(stats, "c")
-+        self.assertEqual(fsb.ncall, 6)
-+        self.assertEqual(fsb.nactualcall, 3)
-+        self.assertEqual(fsb.ttot, 36)
-+        self.assertEqual(fsb.tsub, 27)
-+        self.assertEqual(fsb.tavg, 6)
-+        self.assertEqual(fsc.ttot, 8)
-+        self.assertEqual(fsc.tsub, 8)
-+        self.assertEqual(fsc.tavg, 4)
-+        self.assertEqual(fsc.nactualcall, fsc.ncall, 2)
-+
-+
-+class MultithreadedScenarios(utils.YappiUnitTestCase):
-+
-+    def test_issue_32(self):
-+        '''
-+        Start yappi from different thread and we get Internal Error(15) as
-+        the current_ctx_id() called while enumerating the threads in start()
-+        and as it does not swap to the enumerated ThreadState* the THreadState_GetDict()
-+        returns wrong object and thus sets an invalid id for the _ctx structure.
-+
-+        When this issue happens multiple Threads have same tid as the internal ts_ptr
-+        will be same for different contexts. So, let's see if that happens
-+        '''
-+
-+        def foo():
-+            time.sleep(0.2)
-+
-+        def bar():
-+            time.sleep(0.1)
-+
-+        def thread_func():
-+            yappi.set_clock_type("wall")
-+            yappi.start()
-+
-+            bar()
-+
-+        t = threading.Thread(target=thread_func)
-+        t.start()
-+        t.join()
-+
-+        foo()
-+
-+        yappi.stop()
-+
-+        thread_ids = set()
-+        for tstat in yappi.get_thread_stats():
-+            self.assertTrue(tstat.tid not in thread_ids)
-+            thread_ids.add(tstat.tid)
-+
-+    def test_subsequent_profile(self):
-+        WORKER_COUNT = 5
-+
-+        def a():
-+            pass
-+
-+        def b():
-+            pass
-+
-+        def c():
-+            pass
-+
-+        _timings = {
-+            "a_1": 3,
-+            "b_1": 2,
-+            "c_1": 1,
-+        }
-+
-+        yappi.start()
-+
-+        def g():
-+            pass
-+
-+        g()
-+        yappi.stop()
-+        yappi.clear_stats()
-+        _yappi._set_test_timings(_timings)
-+        yappi.start()
-+
-+        _dummy = []
-+        for i in range(WORKER_COUNT):
-+            t = threading.Thread(target=a)
-+            t.start()
-+            t.join()
-+        for i in range(WORKER_COUNT):
-+            t = threading.Thread(target=b)
-+            t.start()
-+            _dummy.append(t)
-+            t.join()
-+        for i in range(WORKER_COUNT):
-+            t = threading.Thread(target=a)
-+            t.start()
-+            t.join()
-+        for i in range(WORKER_COUNT):
-+            t = threading.Thread(target=c)
-+            t.start()
-+            t.join()
-+        yappi.stop()
-+        yappi.start()
-+
-+        def f():
-+            pass
-+
-+        f()
-+        stats = yappi.get_func_stats()
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        fsc = utils.find_stat_by_name(stats, 'c')
-+        self.assertEqual(fsa.ncall, 10)
-+        self.assertEqual(fsb.ncall, 5)
-+        self.assertEqual(fsc.ncall, 5)
-+        self.assertEqual(fsa.ttot, fsa.tsub, 30)
-+        self.assertEqual(fsb.ttot, fsb.tsub, 10)
-+        self.assertEqual(fsc.ttot, fsc.tsub, 5)
-+
-+        # MACOSx optimizes by only creating one worker thread
-+        self.assertTrue(len(yappi.get_thread_stats()) >= 2)
-+
-+    def test_basic(self):
-+        yappi.set_clock_type('wall')
-+
-+        def dummy():
-+            pass
-+
-+        def a():
-+            time.sleep(0.2)
-+
-+        class Worker1(threading.Thread):
-+
-+            def a(self):
-+                time.sleep(0.3)
-+
-+            def run(self):
-+                self.a()
-+
-+        yappi.start(builtins=False, profile_threads=True)
-+
-+        c = Worker1()
-+        c.start()
-+        c.join()
-+        a()
-+        stats = yappi.get_func_stats()
-+        fsa1 = utils.find_stat_by_name(stats, 'Worker1.a')
-+        fsa2 = utils.find_stat_by_name(stats, 'a')
-+        self.assertTrue(fsa1 is not None)
-+        self.assertTrue(fsa2 is not None)
-+        self.assertTrue(fsa1.ttot > 0.2)
-+        self.assertTrue(fsa2.ttot > 0.1)
-+        tstats = yappi.get_thread_stats()
-+        self.assertEqual(len(tstats), 2)
-+        tsa = utils.find_stat_by_name(tstats, 'Worker1')
-+        tsm = utils.find_stat_by_name(tstats, '_MainThread')
-+        dummy()  # call dummy to force ctx name to be retrieved again.
-+        self.assertTrue(tsa is not None)
-+        # TODO: I put dummy() to fix below, remove the comments after a while.
-+        self.assertTrue( # FIX: I see this fails sometimes?
-+            tsm is not None,
-+            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(tstats))))
-+
-+    def test_ctx_stats(self):
-+        from threading import Thread
-+        DUMMY_WORKER_COUNT = 5
-+        yappi.start()
-+
-+        class DummyThread(Thread):
-+            pass
-+
-+        def dummy():
-+            pass
-+
-+        def dummy_worker():
-+            pass
-+
-+        for i in range(DUMMY_WORKER_COUNT):
-+            t = DummyThread(target=dummy_worker)
-+            t.start()
-+            t.join()
-+        yappi.stop()
-+        stats = yappi.get_thread_stats()
-+        tsa = utils.find_stat_by_name(stats, "DummyThread")
-+        self.assertTrue(tsa is not None)
-+        yappi.clear_stats()
-+        time.sleep(1.0)
-+        _timings = {
-+            "a_1": 6,
-+            "b_1": 5,
-+            "c_1": 3,
-+            "d_1": 1,
-+            "a_2": 4,
-+            "b_2": 3,
-+            "c_2": 2,
-+            "d_2": 1
-+        }
-+        _yappi._set_test_timings(_timings)
-+
-+        class Thread1(Thread):
-+            pass
-+
-+        class Thread2(Thread):
-+            pass
-+
-+        def a():
-+            b()
-+
-+        def b():
-+            c()
-+
-+        def c():
-+            d()
-+
-+        def d():
-+            time.sleep(0.6)
-+
-+        yappi.set_clock_type("wall")
-+        yappi.start()
-+        t1 = Thread1(target=a)
-+        t1.start()
-+        t2 = Thread2(target=a)
-+        t2.start()
-+        t1.join()
-+        t2.join()
-+        stats = yappi.get_thread_stats()
-+
-+        # the fist clear_stats clears the context table?
-+        tsa = utils.find_stat_by_name(stats, "DummyThread")
-+        self.assertTrue(tsa is None)
-+
-+        tst1 = utils.find_stat_by_name(stats, "Thread1")
-+        tst2 = utils.find_stat_by_name(stats, "Thread2")
-+        tsmain = utils.find_stat_by_name(stats, "_MainThread")
-+        dummy()  # call dummy to force ctx name to be retrieved again.
-+        self.assertTrue(len(stats) == 3)
-+        self.assertTrue(tst1 is not None)
-+        self.assertTrue(tst2 is not None)
-+        # TODO: I put dummy() to fix below, remove the comments after a while.
-+        self.assertTrue( # FIX: I see this fails sometimes
-+            tsmain is not None,
-+            'Could not find "_MainThread". Found: %s' % (', '.join(utils.get_stat_names(stats))))
-+        self.assertTrue(1.0 > tst2.ttot >= 0.5)
-+        self.assertTrue(1.0 > tst1.ttot >= 0.5)
-+
-+        # test sorting of the ctx stats
-+        stats = stats.sort("totaltime", "desc")
-+        prev_stat = None
-+        for stat in stats:
-+            if prev_stat:
-+                self.assertTrue(prev_stat.ttot >= stat.ttot)
-+            prev_stat = stat
-+        stats = stats.sort("totaltime", "asc")
-+        prev_stat = None
-+        for stat in stats:
-+            if prev_stat:
-+                self.assertTrue(prev_stat.ttot <= stat.ttot)
-+            prev_stat = stat
-+        stats = stats.sort("schedcount", "desc")
-+        prev_stat = None
-+        for stat in stats:
-+            if prev_stat:
-+                self.assertTrue(prev_stat.sched_count >= stat.sched_count)
-+            prev_stat = stat
-+        stats = stats.sort("name", "desc")
-+        prev_stat = None
-+        for stat in stats:
-+            if prev_stat:
-+                self.assertTrue(prev_stat.name.lower() >= stat.name.lower())
-+            prev_stat = stat
-+        self.assertRaises(
-+            yappi.YappiError, stats.sort, "invalid_thread_sorttype_arg"
-+        )
-+        self.assertRaises(
-+            yappi.YappiError, stats.sort, "invalid_thread_sortorder_arg"
-+        )
-+
-+    def test_ctx_stats_cpu(self):
-+
-+        def get_thread_name():
-+            try:
-+                return threading.current_thread().name
-+            except AttributeError:
-+                return "Anonymous"
-+
-+        def burn_cpu(sec):
-+            t0 = yappi.get_clock_time()
-+            elapsed = 0
-+            while (elapsed < sec):
-+                for _ in range(1000):
-+                    pass
-+                elapsed = yappi.get_clock_time() - t0
-+
-+        def test():
-+
-+            ts = []
-+            for i in (0.01, 0.05, 0.1):
-+                t = threading.Thread(target=burn_cpu, args=(i, ))
-+                t.name = "burn_cpu-%s" % str(i)
-+                t.start()
-+                ts.append(t)
-+            for t in ts:
-+                t.join()
-+
-+        yappi.set_clock_type("cpu")
-+        yappi.set_context_name_callback(get_thread_name)
-+
-+        yappi.start()
-+
-+        test()
-+
-+        yappi.stop()
-+
-+        tstats = yappi.get_thread_stats()
-+        r1 = '''
-+        burn_cpu-0.1      3      123145356058624  0.100105  8
-+        burn_cpu-0.05     2      123145361313792  0.050149  8
-+        burn_cpu-0.01     1      123145356058624  0.010127  2
-+        MainThread        0      4321620864       0.001632  6
-+        '''
-+        self.assert_ctx_stats_almost_equal(r1, tstats)
-+
-+    def test_producer_consumer_with_queues(self):
-+        # we currently just stress yappi, no functionality test is done here.
-+        yappi.start()
-+        if utils.is_py3x():
-+            from queue import Queue
-+        else:
-+            from Queue import Queue
-+        from threading import Thread
-+        WORKER_THREAD_COUNT = 50
-+        WORK_ITEM_COUNT = 2000
-+
-+        def worker():
-+            while True:
-+                item = q.get()
-+                # do the work with item
-+                q.task_done()
-+
-+        q = Queue()
-+        for i in range(WORKER_THREAD_COUNT):
-+            t = Thread(target=worker)
-+            t.daemon = True
-+            t.start()
-+
-+        for item in range(WORK_ITEM_COUNT):
-+            q.put(item)
-+        q.join()  # block until all tasks are done
-+        #yappi.get_func_stats().sort("callcount").print_all()
-+        yappi.stop()
-+
-+    def test_temporary_lock_waiting(self):
-+        yappi.start()
-+        _lock = threading.Lock()
-+
-+        def worker():
-+            _lock.acquire()
-+            try:
-+                time.sleep(1.0)
-+            finally:
-+                _lock.release()
-+
-+        t1 = threading.Thread(target=worker)
-+        t2 = threading.Thread(target=worker)
-+        t1.start()
-+        t2.start()
-+        t1.join()
-+        t2.join()
-+        #yappi.get_func_stats().sort("callcount").print_all()
-+        yappi.stop()
-+
-+    @unittest.skipIf(os.name != "posix", "requires Posix compliant OS")
-+    def test_signals_with_blocking_calls(self):
-+        import signal, os, time
-+
-+        # just to verify if signal is handled correctly and stats/yappi are not corrupted.
-+        def handler(signum, frame):
-+            raise Exception("Signal handler executed!")
-+
-+        yappi.start()
-+        signal.signal(signal.SIGALRM, handler)
-+        signal.alarm(1)
-+        self.assertRaises(Exception, time.sleep, 2)
-+        stats = yappi.get_func_stats()
-+        fsh = utils.find_stat_by_name(stats, "handler")
-+        self.assertTrue(fsh is not None)
-+
-+    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
-+    def test_concurrent_futures(self):
-+        yappi.start()
-+        from concurrent.futures import ThreadPoolExecutor
-+        with ThreadPoolExecutor(max_workers=5) as executor:
-+            f = executor.submit(pow, 5, 2)
-+            self.assertEqual(f.result(), 25)
-+        time.sleep(1.0)
-+        yappi.stop()
-+
-+    @unittest.skipIf(not sys.version_info >= (3, 2), "requires Python 3.2")
-+    def test_barrier(self):
-+        yappi.start()
-+        b = threading.Barrier(2, timeout=1)
-+
-+        def worker():
-+            try:
-+                b.wait()
-+            except threading.BrokenBarrierError:
-+                pass
-+            except Exception:
-+                raise Exception("BrokenBarrierError not raised")
-+
-+        t1 = threading.Thread(target=worker)
-+        t1.start()
-+        #b.wait()
-+        t1.join()
-+        yappi.stop()
-+
-+
-+class NonRecursiveFunctions(utils.YappiUnitTestCase):
-+
-+    def test_abcd(self):
-+        _timings = {"a_1": 6, "b_1": 5, "c_1": 3, "d_1": 1}
-+        _yappi._set_test_timings(_timings)
-+
-+        def a():
-+            b()
-+
-+        def b():
-+            c()
-+
-+        def c():
-+            d()
-+
-+        def d():
-+            pass
-+
-+        stats = utils.run_and_get_func_stats(a)
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        fsc = utils.find_stat_by_name(stats, 'c')
-+        fsd = utils.find_stat_by_name(stats, 'd')
-+        cfsab = fsa.children[fsb]
-+        cfsbc = fsb.children[fsc]
-+        cfscd = fsc.children[fsd]
-+
-+        self.assertEqual(fsa.ttot, 6)
-+        self.assertEqual(fsa.tsub, 1)
-+        self.assertEqual(fsb.ttot, 5)
-+        self.assertEqual(fsb.tsub, 2)
-+        self.assertEqual(fsc.ttot, 3)
-+        self.assertEqual(fsc.tsub, 2)
-+        self.assertEqual(fsd.ttot, 1)
-+        self.assertEqual(fsd.tsub, 1)
-+        self.assertEqual(cfsab.ttot, 5)
-+        self.assertEqual(cfsab.tsub, 2)
-+        self.assertEqual(cfsbc.ttot, 3)
-+        self.assertEqual(cfsbc.tsub, 2)
-+        self.assertEqual(cfscd.ttot, 1)
-+        self.assertEqual(cfscd.tsub, 1)
-+
-+    def test_stop_in_middle(self):
-+        _timings = {"a_1": 6, "b_1": 4}
-+        _yappi._set_test_timings(_timings)
-+
-+        def a():
-+            b()
-+            yappi.stop()
-+
-+        def b():
-+            time.sleep(0.2)
-+
-+        yappi.start()
-+        a()
-+        stats = yappi.get_func_stats()
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+
-+        self.assertEqual(fsa.ncall, 1)
-+        self.assertEqual(fsa.nactualcall, 0)
-+        self.assertEqual(fsa.ttot, 0)  # no call_leave called
-+        self.assertEqual(fsa.tsub, 0)  # no call_leave called
-+        self.assertEqual(fsb.ttot, 4)
-+
-+
-+class RecursiveFunctions(utils.YappiUnitTestCase):
-+
-+    def test_fibonacci(self):
-+
-+        def fib(n):
-+            if n > 1:
-+                return fib(n - 1) + fib(n - 2)
-+            else:
-+                return n
-+
-+        stats = utils.run_and_get_func_stats(fib, 22)
-+        fs = utils.find_stat_by_name(stats, 'fib')
-+        self.assertEqual(fs.ncall, 57313)
-+        self.assertEqual(fs.ttot, fs.tsub)
-+
-+    def test_abcadc(self):
-+        _timings = {
-+            "a_1": 20,
-+            "b_1": 19,
-+            "c_1": 17,
-+            "a_2": 13,
-+            "d_1": 12,
-+            "c_2": 10,
-+            "a_3": 5
-+        }
-+        _yappi._set_test_timings(_timings)
-+
-+        def a(n):
-+            if n == 3:
-+                return
-+            if n == 1 + 1:
-+                d(n)
-+            else:
-+                b(n)
-+
-+        def b(n):
-+            c(n)
-+
-+        def c(n):
-+            a(n + 1)
-+
-+        def d(n):
-+            c(n)
-+
-+        stats = utils.run_and_get_func_stats(a, 1)
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        fsc = utils.find_stat_by_name(stats, 'c')
-+        fsd = utils.find_stat_by_name(stats, 'd')
-+        self.assertEqual(fsa.ncall, 3)
-+        self.assertEqual(fsa.nactualcall, 1)
-+        self.assertEqual(fsa.ttot, 20)
-+        self.assertEqual(fsa.tsub, 7)
-+        self.assertEqual(fsb.ttot, 19)
-+        self.assertEqual(fsb.tsub, 2)
-+        self.assertEqual(fsc.ttot, 17)
-+        self.assertEqual(fsc.tsub, 9)
-+        self.assertEqual(fsd.ttot, 12)
-+        self.assertEqual(fsd.tsub, 2)
-+        cfsca = fsc.children[fsa]
-+        self.assertEqual(cfsca.nactualcall, 0)
-+        self.assertEqual(cfsca.ncall, 2)
-+        self.assertEqual(cfsca.ttot, 13)
-+        self.assertEqual(cfsca.tsub, 6)
-+
-+    def test_aaaa(self):
-+        _timings = {"d_1": 9, "d_2": 7, "d_3": 3, "d_4": 2}
-+        _yappi._set_test_timings(_timings)
-+
-+        def d(n):
-+            if n == 3:
-+                return
-+            d(n + 1)
-+
-+        stats = utils.run_and_get_func_stats(d, 0)
-+        fsd = utils.find_stat_by_name(stats, 'd')
-+        self.assertEqual(fsd.ncall, 4)
-+        self.assertEqual(fsd.nactualcall, 1)
-+        self.assertEqual(fsd.ttot, 9)
-+        self.assertEqual(fsd.tsub, 9)
-+        cfsdd = fsd.children[fsd]
-+        self.assertEqual(cfsdd.ttot, 7)
-+        self.assertEqual(cfsdd.tsub, 7)
-+        self.assertEqual(cfsdd.ncall, 3)
-+        self.assertEqual(cfsdd.nactualcall, 0)
-+
-+    def test_abcabc(self):
-+        _timings = {
-+            "a_1": 20,
-+            "b_1": 19,
-+            "c_1": 17,
-+            "a_2": 13,
-+            "b_2": 11,
-+            "c_2": 9,
-+            "a_3": 6
-+        }
-+        _yappi._set_test_timings(_timings)
-+
-+        def a(n):
-+            if n == 3:
-+                return
-+            else:
-+                b(n)
-+
-+        def b(n):
-+            c(n)
-+
-+        def c(n):
-+            a(n + 1)
-+
-+        stats = utils.run_and_get_func_stats(a, 1)
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        fsc = utils.find_stat_by_name(stats, 'c')
-+        self.assertEqual(fsa.ncall, 3)
-+        self.assertEqual(fsa.nactualcall, 1)
-+        self.assertEqual(fsa.ttot, 20)
-+        self.assertEqual(fsa.tsub, 9)
-+        self.assertEqual(fsb.ttot, 19)
-+        self.assertEqual(fsb.tsub, 4)
-+        self.assertEqual(fsc.ttot, 17)
-+        self.assertEqual(fsc.tsub, 7)
-+        cfsab = fsa.children[fsb]
-+        cfsbc = fsb.children[fsc]
-+        cfsca = fsc.children[fsa]
-+        self.assertEqual(cfsab.ttot, 19)
-+        self.assertEqual(cfsab.tsub, 4)
-+        self.assertEqual(cfsbc.ttot, 17)
-+        self.assertEqual(cfsbc.tsub, 7)
-+        self.assertEqual(cfsca.ttot, 13)
-+        self.assertEqual(cfsca.tsub, 8)
-+
-+    def test_abcbca(self):
-+        _timings = {"a_1": 10, "b_1": 9, "c_1": 7, "b_2": 4, "c_2": 2, "a_2": 1}
-+        _yappi._set_test_timings(_timings)
-+        self._ncall = 1
-+
-+        def a():
-+            if self._ncall == 1:
-+                b()
-+            else:
-+                return
-+
-+        def b():
-+            c()
-+
-+        def c():
-+            if self._ncall == 1:
-+                self._ncall += 1
-+                b()
-+            else:
-+                a()
-+
-+        stats = utils.run_and_get_func_stats(a)
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        fsc = utils.find_stat_by_name(stats, 'c')
-+        cfsab = fsa.children[fsb]
-+        cfsbc = fsb.children[fsc]
-+        cfsca = fsc.children[fsa]
-+        self.assertEqual(fsa.ttot, 10)
-+        self.assertEqual(fsa.tsub, 2)
-+        self.assertEqual(fsb.ttot, 9)
-+        self.assertEqual(fsb.tsub, 4)
-+        self.assertEqual(fsc.ttot, 7)
-+        self.assertEqual(fsc.tsub, 4)
-+        self.assertEqual(cfsab.ttot, 9)
-+        self.assertEqual(cfsab.tsub, 2)
-+        self.assertEqual(cfsbc.ttot, 7)
-+        self.assertEqual(cfsbc.tsub, 4)
-+        self.assertEqual(cfsca.ttot, 1)
-+        self.assertEqual(cfsca.tsub, 1)
-+        self.assertEqual(cfsca.ncall, 1)
-+        self.assertEqual(cfsca.nactualcall, 0)
-+
-+    def test_aabccb(self):
-+        _timings = {
-+            "a_1": 13,
-+            "a_2": 11,
-+            "b_1": 9,
-+            "c_1": 5,
-+            "c_2": 3,
-+            "b_2": 1
-+        }
-+        _yappi._set_test_timings(_timings)
-+        self._ncall = 1
-+
-+        def a():
-+            if self._ncall == 1:
-+                self._ncall += 1
-+                a()
-+            else:
-+                b()
-+
-+        def b():
-+            if self._ncall == 3:
-+                return
-+            else:
-+                c()
-+
-+        def c():
-+            if self._ncall == 2:
-+                self._ncall += 1
-+                c()
-+            else:
-+                b()
-+
-+        stats = utils.run_and_get_func_stats(a)
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        fsc = utils.find_stat_by_name(stats, 'c')
-+        cfsaa = fsa.children[fsa.index]
-+        cfsab = fsa.children[fsb]
-+        cfsbc = fsb.children[fsc.full_name]
-+        cfscc = fsc.children[fsc]
-+        cfscb = fsc.children[fsb]
-+        self.assertEqual(fsb.ttot, 9)
-+        self.assertEqual(fsb.tsub, 5)
-+        self.assertEqual(cfsbc.ttot, 5)
-+        self.assertEqual(cfsbc.tsub, 2)
-+        self.assertEqual(fsa.ttot, 13)
-+        self.assertEqual(fsa.tsub, 4)
-+        self.assertEqual(cfsab.ttot, 9)
-+        self.assertEqual(cfsab.tsub, 4)
-+        self.assertEqual(cfsaa.ttot, 11)
-+        self.assertEqual(cfsaa.tsub, 2)
-+        self.assertEqual(fsc.ttot, 5)
-+        self.assertEqual(fsc.tsub, 4)
-+
-+    def test_abaa(self):
-+        _timings = {"a_1": 13, "b_1": 10, "a_2": 9, "a_3": 5}
-+        _yappi._set_test_timings(_timings)
-+
-+        self._ncall = 1
-+
-+        def a():
-+            if self._ncall == 1:
-+                b()
-+            elif self._ncall == 2:
-+                self._ncall += 1
-+                a()
-+            else:
-+                return
-+
-+        def b():
-+            self._ncall += 1
-+            a()
-+
-+        stats = utils.run_and_get_func_stats(a)
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        cfsaa = fsa.children[fsa]
-+        cfsba = fsb.children[fsa]
-+        self.assertEqual(fsb.ttot, 10)
-+        self.assertEqual(fsb.tsub, 1)
-+        self.assertEqual(fsa.ttot, 13)
-+        self.assertEqual(fsa.tsub, 12)
-+        self.assertEqual(cfsaa.ttot, 5)
-+        self.assertEqual(cfsaa.tsub, 5)
-+        self.assertEqual(cfsba.ttot, 9)
-+        self.assertEqual(cfsba.tsub, 4)
-+
-+    def test_aabb(self):
-+        _timings = {"a_1": 13, "a_2": 10, "b_1": 9, "b_2": 5}
-+        _yappi._set_test_timings(_timings)
-+
-+        self._ncall = 1
-+
-+        def a():
-+            if self._ncall == 1:
-+                self._ncall += 1
-+                a()
-+            elif self._ncall == 2:
-+                b()
-+            else:
-+                return
-+
-+        def b():
-+            if self._ncall == 2:
-+                self._ncall += 1
-+                b()
-+            else:
-+                return
-+
-+        stats = utils.run_and_get_func_stats(a)
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        cfsaa = fsa.children[fsa]
-+        cfsab = fsa.children[fsb]
-+        cfsbb = fsb.children[fsb]
-+        self.assertEqual(fsa.ttot, 13)
-+        self.assertEqual(fsa.tsub, 4)
-+        self.assertEqual(fsb.ttot, 9)
-+        self.assertEqual(fsb.tsub, 9)
-+        self.assertEqual(cfsaa.ttot, 10)
-+        self.assertEqual(cfsaa.tsub, 1)
-+        self.assertEqual(cfsab.ttot, 9)
-+        self.assertEqual(cfsab.tsub, 4)
-+        self.assertEqual(cfsbb.ttot, 5)
-+        self.assertEqual(cfsbb.tsub, 5)
-+
-+    def test_abbb(self):
-+        _timings = {"a_1": 13, "b_1": 10, "b_2": 6, "b_3": 1}
-+        _yappi._set_test_timings(_timings)
-+
-+        self._ncall = 1
-+
-+        def a():
-+            if self._ncall == 1:
-+                b()
-+
-+        def b():
-+            if self._ncall == 3:
-+                return
-+            self._ncall += 1
-+            b()
-+
-+        stats = utils.run_and_get_func_stats(a)
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        cfsab = fsa.children[fsb]
-+        cfsbb = fsb.children[fsb]
-+        self.assertEqual(fsa.ttot, 13)
-+        self.assertEqual(fsa.tsub, 3)
-+        self.assertEqual(fsb.ttot, 10)
-+        self.assertEqual(fsb.tsub, 10)
-+        self.assertEqual(fsb.ncall, 3)
-+        self.assertEqual(fsb.nactualcall, 1)
-+        self.assertEqual(cfsab.ttot, 10)
-+        self.assertEqual(cfsab.tsub, 4)
-+        self.assertEqual(cfsbb.ttot, 6)
-+        self.assertEqual(cfsbb.tsub, 6)
-+        self.assertEqual(cfsbb.nactualcall, 0)
-+        self.assertEqual(cfsbb.ncall, 2)
-+
-+    def test_aaab(self):
-+        _timings = {"a_1": 13, "a_2": 10, "a_3": 6, "b_1": 1}
-+        _yappi._set_test_timings(_timings)
-+
-+        self._ncall = 1
-+
-+        def a():
-+            if self._ncall == 3:
-+                b()
-+                return
-+            self._ncall += 1
-+            a()
-+
-+        def b():
-+            return
-+
-+        stats = utils.run_and_get_func_stats(a)
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        cfsaa = fsa.children[fsa]
-+        cfsab = fsa.children[fsb]
-+        self.assertEqual(fsa.ttot, 13)
-+        self.assertEqual(fsa.tsub, 12)
-+        self.assertEqual(fsb.ttot, 1)
-+        self.assertEqual(fsb.tsub, 1)
-+        self.assertEqual(cfsaa.ttot, 10)
-+        self.assertEqual(cfsaa.tsub, 9)
-+        self.assertEqual(cfsab.ttot, 1)
-+        self.assertEqual(cfsab.tsub, 1)
-+
-+    def test_abab(self):
-+        _timings = {"a_1": 13, "b_1": 10, "a_2": 6, "b_2": 1}
-+        _yappi._set_test_timings(_timings)
-+
-+        self._ncall = 1
-+
-+        def a():
-+            b()
-+
-+        def b():
-+            if self._ncall == 2:
-+                return
-+            self._ncall += 1
-+            a()
-+
-+        stats = utils.run_and_get_func_stats(a)
-+        fsa = utils.find_stat_by_name(stats, 'a')
-+        fsb = utils.find_stat_by_name(stats, 'b')
-+        cfsab = fsa.children[fsb]
-+        cfsba = fsb.children[fsa]
-+        self.assertEqual(fsa.ttot, 13)
-+        self.assertEqual(fsa.tsub, 8)
-+        self.assertEqual(fsb.ttot, 10)
-+        self.assertEqual(fsb.tsub, 5)
-+        self.assertEqual(cfsab.ttot, 10)
-+        self.assertEqual(cfsab.tsub, 5)
-+        self.assertEqual(cfsab.ncall, 2)
-+        self.assertEqual(cfsab.nactualcall, 1)
-+        self.assertEqual(cfsba.ttot, 6)
-+        self.assertEqual(cfsba.tsub, 5)
-+
-+
-+if __name__ == '__main__':
-+    #     import sys;sys.argv = ['', 'BasicUsage.test_run_as_script']
-+    #     import sys;sys.argv = ['', 'MultithreadedScenarios.test_subsequent_profile']
-+    unittest.main()
---- a/tests/test_hooks.py
-+++ b/tests/test_hooks.py
-@@ -5,7 +5,7 @@ import unittest
- import time
- 
- import yappi
--import utils
-+import tests.utils as utils
- 
- 
- def a():
---- a/tests/test_tags.py
-+++ b/tests/test_tags.py
-@@ -2,7 +2,7 @@ import unittest
- import yappi
- import threading
- import time
--from utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
-+from .utils import YappiUnitTestCase, find_stat_by_name, burn_cpu, burn_io
- 
- 
- class MultiThreadTests(YappiUnitTestCase):
diff --git a/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch b/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch
deleted file mode 100644
index d40bd2b7c..000000000
--- a/meta-python/recipes-devtools/python/python3-yappi/0002-add-3.11-to-the-setup.patch
+++ /dev/null
@@ -1,26 +0,0 @@ 
-From 38afdacf526410f970afc58e147c7377c6c7112c Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?S=C3=BCmer=20Cip?= <sumer.cip@platform.sh>
-Date: Fri, 25 Nov 2022 15:58:03 +0300
-Subject: [PATCH 2/2] add 3.11 to the setup
-
----
-Upstream-Status: Pending
-
- setup.py | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/setup.py b/setup.py
-index d006787..96e2a66 100644
---- a/setup.py
-+++ b/setup.py
-@@ -56,6 +56,7 @@ CLASSIFIERS = [
-     'Programming Language :: Python :: 3.8',
-     'Programming Language :: Python :: 3.9',
-     'Programming Language :: Python :: 3.10',
-+    'Programming Language :: Python :: 3.11',
-     'Programming Language :: Python :: Implementation :: CPython',
-     'Operating System :: OS Independent',
-     'Topic :: Software Development :: Libraries',
--- 
-2.30.2
-
diff --git a/meta-python/recipes-devtools/python/python3-yappi_1.4.0.bb b/meta-python/recipes-devtools/python/python3-yappi_1.6.0.bb
similarity index 74%
rename from meta-python/recipes-devtools/python/python3-yappi_1.4.0.bb
rename to meta-python/recipes-devtools/python/python3-yappi_1.6.0.bb
index 71e74e86f..435dc11bb 100644
--- a/meta-python/recipes-devtools/python/python3-yappi_1.4.0.bb
+++ b/meta-python/recipes-devtools/python/python3-yappi_1.6.0.bb
@@ -4,13 +4,9 @@  HOMEPAGE = "https://github.com/sumerc/yappi"
 LICENSE = "MIT"
 LIC_FILES_CHKSUM = "file://LICENSE;md5=71c208c9a4fd864385eb69ad4caa3bee"
 
-SRC_URI[sha256sum] = "504b5d8fc7433736cb5e257991d2e7f2946019174f1faec7b2fe947881a17fc0"
+SRC_URI[sha256sum] = "a9aaf72009d8c03067294151ee0470ac7a6dfa7b33baab40b198d6c1ef00430a"
 
-SRC_URI += " \
-    file://run-ptest \
-    file://0001-Fix-imports-for-ptests.patch \
-    file://0002-add-3.11-to-the-setup.patch \
-"
+SRC_URI += "file://run-ptest"
 
 inherit pypi setuptools3 ptest