예제 #1
0
def test_watch():
    class Foo(object):
        def __init__(self):
            self.x = 2

        def square(self):
            self.x **= 2

    @pysnooper.snoop(watch=(
        'foo.x',
        'io.__name__',
        'len(foo.__dict__["x"] * "abc")',
    ))
    def my_function():
        foo = Foo()
        for i in range(2):
            foo.square()

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = my_function()
    assert result is None
    output = output_capturer.string_io.getvalue()
    assert_output(
        output,
        (VariableEntry('Foo'), VariableEntry('io.__name__', "'io'"),
         CallEntry('def my_function():'), LineEntry('foo = Foo()'),
         VariableEntry('foo'), VariableEntry('foo.x', '2'),
         VariableEntry('len(foo.__dict__["x"] * "abc")', '6'), LineEntry(),
         VariableEntry('i', '0'), LineEntry(), VariableEntry('foo.x', '4'),
         VariableEntry('len(foo.__dict__["x"] * "abc")', '12'), LineEntry(),
         VariableEntry('i', '1'), LineEntry(), VariableEntry('foo.x', '16'),
         VariableEntry('len(foo.__dict__["x"] * "abc")', '48'), LineEntry(),
         ReturnEntry(), ReturnValueEntry('None')))
예제 #2
0
def test_unavailable_source():
    with temp_file_tools.create_temp_folder(prefix='pysnooper') as folder, \
            sys_tools.TempSysPathAdder(str(folder)):
        module_name = 'iaerojajsijf'
        python_file_path = folder / ('%s.py' % (module_name, ))
        content = textwrap.dedent(u'''
            import pysnooper
            @pysnooper.snoop()
            def f(x):
                return x
        ''')
        with python_file_path.open('w') as python_file:
            python_file.write(content)
        module = __import__(module_name)
        python_file_path.unlink()
        with sys_tools.OutputCapturer(stdout=False,
                                      stderr=True) as output_capturer:
            result = getattr(module, 'f')(7)
        assert result == 7
        output = output_capturer.output
        assert_output(output, (
            VariableEntry(stage='starting'),
            CallEntry('SOURCE IS UNAVAILABLE'),
            LineEntry('SOURCE IS UNAVAILABLE'),
            ReturnEntry('SOURCE IS UNAVAILABLE'),
            ReturnValueEntry('7'),
        ))
예제 #3
0
def test_variables_classes():
    class WithSlots(object):
        __slots__ = ('x', 'y')

        def __init__(self):
            self.x = 3
            self.y = 4

    @pysnooper.snoop(watch=(
        pysnooper.Keys('_d', exclude='c'),
        pysnooper.Attrs('_d'),  # doesn't have attributes
        pysnooper.Attrs('_s'),
        pysnooper.Indices('_lst')[-3:],
    ))
    def my_function():
        _d = {'a': 1, 'b': 2, 'c': 'ignore'}
        _s = WithSlots()
        _lst = list(range(1000))

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = my_function()
    assert result is None
    output = output_capturer.string_io.getvalue()
    assert_output(
        output,
        (VariableEntry('WithSlots'), CallEntry('def my_function():'),
         LineEntry(), VariableEntry('_d'), VariableEntry("_d['a']", '1'),
         VariableEntry("_d['b']", '2'), LineEntry(), VariableEntry('_s'),
         VariableEntry('_s.x', '3'), VariableEntry('_s.y', '4'), LineEntry(),
         VariableEntry('_lst'), VariableEntry('_lst[997]', '997'),
         VariableEntry('_lst[998]', '998'), VariableEntry(
             '_lst[999]', '999'), ReturnEntry(), ReturnValueEntry('None')))
예제 #4
0
def test_method_and_prefix():
    class Baz(object):
        def __init__(self):
            self.x = 2

        @pysnooper.snoop(watch=('self.x', ), prefix='ZZZ')
        def square(self):
            foo = 7
            self.x **= 2
            return self

    baz = Baz()

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = baz.square()
    assert result is baz
    assert result.x == 4
    output = output_capturer.string_io.getvalue()
    assert_output(output, (
        VariableEntry('self', prefix='ZZZ'),
        VariableEntry('self.x', '2', prefix='ZZZ'),
        CallEntry('def square(self):', prefix='ZZZ'),
        LineEntry('foo = 7', prefix='ZZZ'),
        VariableEntry('foo', '7', prefix='ZZZ'),
        LineEntry('self.x **= 2', prefix='ZZZ'),
        VariableEntry('self.x', '4', prefix='ZZZ'),
        LineEntry(prefix='ZZZ'),
        ReturnEntry(prefix='ZZZ'),
        ReturnValueEntry(prefix='ZZZ'),
    ),
                  prefix='ZZZ')
예제 #5
0
def test_single_watch_no_comma():
    class Foo(object):
        def __init__(self):
            self.x = 2

        def square(self):
            self.x **= 2

    @pysnooper.snoop(watch='foo')
    def my_function():
        foo = Foo()
        for i in range(2):
            foo.square()

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = my_function()
    assert result is None
    output = output_capturer.string_io.getvalue()
    assert_output(output,
                  (VariableEntry('Foo'), CallEntry('def my_function():'),
                   LineEntry('foo = Foo()'), VariableEntry('foo'), LineEntry(),
                   VariableEntry('i', '0'), LineEntry(), LineEntry(),
                   VariableEntry('i', '1'), LineEntry(), LineEntry(),
                   ReturnEntry(), ReturnValueEntry('None')))
예제 #6
0
def test_repr_exception():
    class Bad(object):
        def __repr__(self):
            1 / 0

    @pysnooper.snoop()
    def my_function():
        bad = Bad()

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = my_function()
    assert result is None
    output = output_capturer.string_io.getvalue()
    assert_output(
        output,
        (
            VariableEntry('Bad'),
            CallEntry('def my_function():'),
            LineEntry('bad = Bad()'),
            VariableEntry('bad', value_regex=r'<Bad instance at 0x\w+ \(__repr__ raised ZeroDivisionError\)>'),
            ReturnEntry(),
            ReturnValueEntry('None')
        )
    )
예제 #7
0
def test_watch_explode():
    class Foo:
        def __init__(self, x, y):
            self.x = x
            self.y = y

    @pysnooper.snoop(watch_explode=('_d', '_point', 'lst + []'))
    def my_function():
        _d = {'a': 1, 'b': 2, 'c': 'ignore'}
        _point = Foo(x=3, y=4)
        lst = [7, 8, 9]
        lst.append(10)

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = my_function()
    assert result is None
    output = output_capturer.string_io.getvalue()
    assert_output(
        output,
        (VariableEntry('Foo'), CallEntry('def my_function():'), LineEntry(),
         VariableEntry('_d'), VariableEntry("_d['a']", '1'),
         VariableEntry("_d['b']", '2'), VariableEntry(
             "_d['c']", "'ignore'"), LineEntry(), VariableEntry('_point'),
         VariableEntry('_point.x', '3'), VariableEntry(
             '_point.y', '4'), LineEntry(), VariableEntry(
                 '(lst + [])[0]', '7'), VariableEntry('(lst + [])[1]', '8'),
         VariableEntry('(lst + [])[2]', '9'), VariableEntry('lst'),
         VariableEntry('lst + []'), LineEntry(),
         VariableEntry('(lst + [])[3]', '10'), VariableEntry('lst'),
         VariableEntry('lst + []'), ReturnEntry(), ReturnValueEntry('None')))
예제 #8
0
def assert_output(verbose, expect):
    torchsnooper.register_snoop(verbose=verbose)
    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        assert sys.gettrace() is None
        snoop(func)()
        assert sys.gettrace() is None
    output = output_capturer.string_io.getvalue()
    output = ansi_escape.sub('', output)
    assert clean_output(output) == clean_output(expect)
    snoop.config = default_config
예제 #9
0
def test_long_variable():
    @pysnooper.snoop()
    def my_function():
        foo = list(range(1000))
        return foo

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = my_function()
    assert result == list(range(1000))
    output = output_capturer.string_io.getvalue()
    assert_output(
        output,
        (CallEntry('def my_function():'), LineEntry('foo = list(range(1000))'),
         VariableEntry('foo', '[0, 1, 2, 3, 4, 5, ...]'), LineEntry(),
         ReturnEntry(), ReturnValueEntry('[0, 1, 2, 3, 4, 5, ...]')))
예제 #10
0
def test_long_variable():
    @pysnooper.snoop()
    def my_function():
        foo = list(range(1000))
        return foo

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = my_function()
    assert result == list(range(1000))
    output = output_capturer.string_io.getvalue()
    regex = r'^\[0, 1, 2, .*\.\.\..*, 997, 998, 999\]$'
    assert_output(
        output,
        (CallEntry('def my_function():'), LineEntry('foo = list(range(1000))'),
         VariableEntry('foo', value_regex=regex), LineEntry(), ReturnEntry(),
         ReturnValueEntry(value_regex=regex)))
예제 #11
0
파일: utils.py 프로젝트: zbx91/PySnooper
def assert_sample_output(module):
    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        module.main()

    time = '21:10:42.298924'
    time_pattern = re.sub(r'\d', r'\\d', time)

    def normalise(out):
        return re.sub(time_pattern, time, out).strip()

    output = output_capturer.string_io.getvalue()

    try:
        assert (normalise(output) == normalise(module.expected_output))
    except AssertionError:
        print('\n\nActual Output:\n\n' +
              output)  # to copy paste into expected_output
        raise  # show pytest diff (may need -vv flag to see in full)
예제 #12
0
def test_repr_exception():
    class Bad(object):
        def __repr__(self):
            1 / 0

    @pysnooper.snoop()
    def my_function():
        bad = Bad()

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = my_function()
    assert result is None
    output = output_capturer.string_io.getvalue()
    assert_output(
        output,
        (VariableEntry('Bad'), CallEntry('def my_function():'),
         LineEntry('bad = Bad()'), VariableEntry('bad', value='REPR FAILED'),
         ReturnEntry(), ReturnValueEntry('None')))
예제 #13
0
def test_thread_info():
    @pysnooper.snoop(thread_info=True)
    def my_function(foo):
        x = 7
        y = 8
        return y + x

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = my_function('baba')
    assert result == 15
    output = output_capturer.string_io.getvalue()
    assert_output(output, (
        VariableEntry('foo', value_regex="u?'baba'"),
        CallEntry('def my_function(foo):'),
        LineEntry('x = 7'),
        VariableEntry('x', '7'),
        LineEntry('y = 8'),
        VariableEntry('y', '8'),
        LineEntry('return y + x'),
        ReturnEntry('return y + x'),
        ReturnValueEntry('15'),
    ))
예제 #14
0
파일: test_snoop.py 프로젝트: xcbat/snoop
def assert_sample_output(module):
    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        assert sys.gettrace() is None
        module.main()
        assert sys.gettrace() is None

    time = '12:34:56.78'
    time_pattern = re.sub(r'\d', r'\\d', time)

    output = output_capturer.string_io.getvalue()

    normalised = re.sub(time_pattern, time, output).strip()
    normalised = re.sub(r'0x\w+', '0xABC', normalised)
    normalised = normalised.replace('<genexpr>.<genexpr>', '<genexpr>')
    normalised = normalised.replace('<list_iterator', '<tupleiterator')
    normalised = normalised.replace('<listiterator', '<tupleiterator')
    normalised = normalised.replace('<tuple_iterator', '<tupleiterator')
    normalised = normalised.replace('<sequenceiterator', '<tupleiterator')

    try:
        assert (normalised == module.expected_output.strip())
    except AssertionError:
        if os.environ.get('FIX_SNOOP_TESTS'):
            path = module.__file__.rstrip('c')
            contents = file_to_string(path)
            match = re.search(
                r'expected_output = r?"""',
                contents,
            )
            contents = contents[:match.end(0)] + '\n{}\n"""\n'.format(
                normalised)
            string_to_file(contents, path)
        else:
            print('\n\nNormalised actual output:\n\n' + normalised)
            raise  # show pytest diff (may need -vv flag to see in full)
예제 #15
0
def test_with_block():
    # Testing that a single Tracer can handle many mixed uses
    snoop = pysnooper.snoop()

    def foo(x):
        if x == 0:
            bar1(x)
            qux()
            return

        with snoop:
            # There should be line entries for these three lines,
            # no line entries for anything else in this function,
            # but calls to all bar functions should be traced
            foo(x - 1)
            bar2(x)
            qux()
        int(4)
        bar3(9)
        return x

    @snoop
    def bar1(_x):
        qux()

    @snoop
    def bar2(_x):
        qux()

    @snoop
    def bar3(_x):
        qux()

    def qux():
        return 9  # not traced, mustn't show up

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        result = foo(2)
    assert result == 2
    output = output_capturer.string_io.getvalue()
    assert_output(
        output,
        (
            # In first with
            VariableEntry('bar1'),
            VariableEntry('bar2'),
            VariableEntry('bar3'),
            VariableEntry('foo'),
            VariableEntry('qux'),
            VariableEntry('snoop'),
            VariableEntry('x', '2'),
            LineEntry('foo(x - 1)'),

            # In with in recursive call
            VariableEntry('bar1'),
            VariableEntry('bar2'),
            VariableEntry('bar3'),
            VariableEntry('foo'),
            VariableEntry('qux'),
            VariableEntry('snoop'),
            VariableEntry('x', '1'),
            LineEntry('foo(x - 1)'),

            # Call to bar1 from if block outside with
            VariableEntry('_x', '0'),
            VariableEntry('qux'),
            CallEntry('def bar1(_x):'),
            LineEntry('qux()'),
            ReturnEntry('qux()'),
            ReturnValueEntry('None'),

            # In with in recursive call
            LineEntry('bar2(x)'),

            # Call to bar2 from within with
            VariableEntry('_x', '1'),
            VariableEntry('qux'),
            CallEntry('def bar2(_x):'),
            LineEntry('qux()'),
            ReturnEntry('qux()'),
            ReturnValueEntry('None'),

            # In with in recursive call
            LineEntry('qux()'),

            # Call to bar3 from after with
            VariableEntry('_x', '9'),
            VariableEntry('qux'),
            CallEntry('def bar3(_x):'),
            LineEntry('qux()'),
            ReturnEntry('qux()'),
            ReturnValueEntry('None'),

            # -- Similar to previous few sections,
            # -- but from first call to foo

            # In with in first call
            LineEntry('bar2(x)'),

            # Call to bar2 from within with
            VariableEntry('_x', '2'),
            VariableEntry('qux'),
            CallEntry('def bar2(_x):'),
            LineEntry('qux()'),
            ReturnEntry('qux()'),
            ReturnValueEntry('None'),

            # In with in first call
            LineEntry('qux()'),

            # Call to bar3 from after with
            VariableEntry('_x', '9'),
            VariableEntry('qux'),
            CallEntry('def bar3(_x):'),
            LineEntry('qux()'),
            ReturnEntry('qux()'),
            ReturnValueEntry('None'),
        ),
    )
예제 #16
0
def test_multi_thread_info():
    @pysnooper.snoop(thread_info=True)
    def my_function(foo):
        x = 7
        y = 8
        return y + x

    with sys_tools.OutputCapturer(stdout=False,
                                  stderr=True) as output_capturer:
        my_function('baba')
        t1 = threading.Thread(target=my_function,
                              name="test123",
                              args=['bubu'])
        t1.start()
        t1.join()
        t1 = threading.Thread(target=my_function, name="bibi", args=['bibi'])
        t1.start()
        t1.join()
    output = output_capturer.string_io.getvalue()
    calls = [line for line in output.split("\n") if "call" in line]
    main_thread = calls[0]
    assert len(main_thread) == len(calls[1])
    assert len(main_thread) == len(calls[2])
    main_thread_call_str = main_thread.find("call")
    assert main_thread_call_str == calls[1].find("call")
    assert main_thread_call_str == calls[2].find("call")
    thread_info_regex = '([0-9]+-{name}+[ ]+)'
    assert_output(output, (
        VariableEntry('foo', value_regex="u?'baba'"),
        CallEntry(
            'def my_function(foo):',
            thread_info_regex=thread_info_regex.format(name="MainThread")),
        LineEntry(
            'x = 7',
            thread_info_regex=thread_info_regex.format(name="MainThread")),
        VariableEntry('x', '7'),
        LineEntry(
            'y = 8',
            thread_info_regex=thread_info_regex.format(name="MainThread")),
        VariableEntry('y', '8'),
        LineEntry(
            'return y + x',
            thread_info_regex=thread_info_regex.format(name="MainThread")),
        ReturnEntry('return y + x'),
        ReturnValueEntry('15'),
        VariableEntry('foo', value_regex="u?'bubu'"),
        CallEntry('def my_function(foo):',
                  thread_info_regex=thread_info_regex.format(name="test123")),
        LineEntry('x = 7',
                  thread_info_regex=thread_info_regex.format(name="test123")),
        VariableEntry('x', '7'),
        LineEntry('y = 8',
                  thread_info_regex=thread_info_regex.format(name="test123")),
        VariableEntry('y', '8'),
        LineEntry('return y + x',
                  thread_info_regex=thread_info_regex.format(name="test123")),
        ReturnEntry('return y + x'),
        ReturnValueEntry('15'),
        VariableEntry('foo', value_regex="u?'bibi'"),
        CallEntry('def my_function(foo):',
                  thread_info_regex=thread_info_regex.format(name='bibi')),
        LineEntry('x = 7',
                  thread_info_regex=thread_info_regex.format(name='bibi')),
        VariableEntry('x', '7'),
        LineEntry('y = 8',
                  thread_info_regex=thread_info_regex.format(name='bibi')),
        VariableEntry('y', '8'),
        LineEntry('return y + x',
                  thread_info_regex=thread_info_regex.format(name='bibi')),
        ReturnEntry('return y + x'),
        ReturnValueEntry('15'),
    ))