Example #1
0
def test_display_sample_count(capsys, stderr):
    traces = [
        CallTrace(func, {
            'a': int,
            'b': str
        }, NoneType),
        CallTrace(func, {
            'a': str,
            'b': str
        }, NoneType),
        CallTrace(func2, {
            'a': str,
            'b': int
        }, NoneType),
        CallTrace(func2, {
            'a': int,
            'b': str
        }, NoneType),
        CallTrace(func2, {
            'a': str,
            'b': int
        }, NoneType)
    ]
    cli.display_sample_count(traces, stderr)
    expected = """Annotation for tests.test_cli.func based on 2 call trace(s).
Annotation for tests.test_cli.func2 based on 3 call trace(s).
"""
    assert stderr.getvalue() == expected
Example #2
0
 def test_nested_callee_throws_recovers(self, collector):
     with trace_calls(collector):
         nested_throw(should_recover=True)
     expected = [
         CallTrace(throw, {'should_recover': bool}, NoneType),
         CallTrace(nested_throw, {'should_recover': bool}, str),
     ]
     assert collector.traces == expected
Example #3
0
 def test_caller_handles_callee_exception(self, collector):
     with trace_calls(collector):
         recover_from_nested_throw()
     expected = [
         CallTrace(throw, {'should_recover': bool}),
         CallTrace(recover_from_nested_throw, {}, str),
     ]
     assert collector.traces == expected
Example #4
0
 def test_return_none(self, collector):
     """Ensure traces have a return_type of NoneType for functions that return a value of None"""
     with trace_calls(collector):
         implicit_return_none()
         explicit_return_none()
     expected = [
         CallTrace(implicit_return_none, {}, NoneType),
         CallTrace(explicit_return_none, {}, NoneType),
     ]
     assert collector.traces == expected
Example #5
0
def test_verbose_failed_traces(store, db_file, stdout, stderr):
    traces = [
        CallTrace(func, {'a': int, 'b': str}, NoneType),
        CallTrace(func2, {'a': int, 'b': int}, NoneType),
    ]
    store.add(traces)
    with mock.patch("monkeytype.encoding.CallTraceRow.to_trace", side_effect=MonkeyTypeError("the-trace")):
        ret = cli.main(['-v', 'stub', func.__module__], stdout, stderr)
    assert "WARNING: Failed decoding trace: the-trace" in stderr.getvalue()
    assert ret == 0
Example #6
0
 def test_nested_callee_throws_caller_doesnt_recover(self, collector):
     with trace_calls(collector):
         try:
             nested_throw(should_recover=False)
         except Exception:
             pass
     expected = [
         CallTrace(throw, {'should_recover': bool}),
         CallTrace(nested_throw, {'should_recover': bool}),
     ]
     assert collector.traces == expected
Example #7
0
def test_display_sample_count_from_cli(store, db_file, stdout, stderr):
    traces = [
        CallTrace(func, {'a': int, 'b': str}, NoneType),
        CallTrace(func2, {'a': int, 'b': int}, NoneType),
    ]
    store.add(traces)
    with mock.patch.dict(os.environ, {DefaultConfig.DB_PATH_VAR: db_file.name}):
        ret = cli.main(['stub', func.__module__, '--sample-count'], stdout, stderr)
    expected = """Annotation for tests.test_cli.func based on 1 call trace(s).
Annotation for tests.test_cli.func2 based on 1 call trace(s).
"""
    assert stderr.getvalue() == expected
    assert ret == 0
def test_limit_resultset(store):
    """Limit the number of results returned"""
    traces = [
        CallTrace(func, {
            'a': int,
            'b': str
        }, None),
        CallTrace(func2, {
            'a': int,
            'b': int
        }, None),
    ]
    store.add(traces)
    thunks = store.filter(func.__module__, limit=1)
    assert len(thunks) == 1
Example #9
0
 def test_shrink_args(self):
     traces = [
         CallTrace(tie_helper, {
             'a': str,
             'b': int
         }),
         CallTrace(tie_helper, {
             'a': str,
             'b': NoneType
         }),
     ]
     assert shrink_traced_types(traces) == ({
         'a': str,
         'b': Optional[int]
     }, None, None)
Example #10
0
def test_generate_stub(store, db_file, stdout, stderr):
    traces = [
        CallTrace(func, {'a': int, 'b': str}, NoneType),
        CallTrace(func2, {'a': int, 'b': int}, NoneType),
    ]
    store.add(traces)
    ret = cli.main(['stub', func.__module__], stdout, stderr)
    expected = """def func(a: int, b: str) -> None: ...


def func2(a: int, b: int) -> None: ...
"""
    assert stdout.getvalue() == expected
    assert stderr.getvalue() == ''
    assert ret == 0
def test_qualname_filtering(store):
    """Prefix match on qualname"""
    traces = [
        CallTrace(func, {
            'a': int,
            'b': str
        }, None),
        CallTrace(func2, {
            'a': int,
            'b': int
        }, None),
    ]
    store.add(traces)
    thunks = store.filter(func.__module__, qualname_prefix='func')
    assert len(thunks) == 2
    assert traces == [thunk.to_trace() for thunk in thunks]
def test_dedup(store):
    """The store shouldn't return duplicates"""
    trace = CallTrace(func, {'a': int, 'b': str}, None)
    store.add([trace, trace, trace, trace])
    thunks = store.filter(func.__module__)
    assert len(thunks) == 1
    assert thunks[0].to_trace() == trace
def test_round_trip(store):
    """Save and retrieve a trace"""
    trace = CallTrace(func, {'a': int, 'b': str}, None)
    store.add([trace])
    thunks = store.filter(func.__module__)
    assert len(thunks) == 1
    assert thunks[0].to_trace() == trace
Example #14
0
def test_retype_failure(store_data, stdout, stderr):
    store, db_file = store_data
    traces = [
        CallTrace(func, {'a': int, 'b': str}, NoneType),
        CallTrace(func2, {'a': int, 'b': int}, NoneType),
    ]
    store.add(traces)
    msg = "this is a test"
    err = subprocess.CalledProcessError(returncode=100, cmd='retype')
    err.stdout = msg.encode()
    with mock.patch.dict(os.environ, {DefaultConfig.DB_PATH_VAR: db_file.name}):
        with mock.patch('subprocess.run', side_effect=err):
            ret = cli.main(['apply', func.__module__], stdout, stderr)
    assert stdout.getvalue() == ""
    assert stderr.getvalue() == f"ERROR: Failed applying stub with retype:\n{msg}\n"
    assert ret == 1
Example #15
0
def test_get_diff(store, db_file, stdout, stderr):
    traces = [
        CallTrace(func_anno, {'a': int, 'b': int}, int),
        CallTrace(func_anno2, {'a': str, 'b': str}, None),
    ]
    store.add(traces)
    with mock.patch.dict(os.environ, {DefaultConfig.DB_PATH_VAR: db_file.name}):
        ret = cli.main(['stub', func.__module__, '--diff'], stdout, stderr)
    expected = """- def func_anno(a: int, b: str) -> None: ...
?                          ^ -     ^^ ^
+ def func_anno(a: int, b: int) -> int: ...
?                          ^^      ^ ^
"""
    assert stdout.getvalue() == expected
    assert stderr.getvalue() == ''
    assert ret == 0
Example #16
0
 def test_callee_throws(self, collector):
     with trace_calls(collector):
         try:
             throw(should_recover=False)
         except Exception:
             pass
     assert collector.traces == [CallTrace(throw, {'should_recover': bool})]
Example #17
0
def test_apply_stub_file_with_spaces(store_data, stdout, stderr):
    """Regression test for applying a stub to a filename containing spaces"""
    src = """
def my_test_function(a, b):
  return a + b
"""
    with tempfile.TemporaryDirectory(prefix='monkey type') as tempdir:
        module = 'my_test_module'
        src_path = os.path.join(tempdir, module + '.py')
        with open(src_path, 'w+') as f:
            f.write(src)
        with mock.patch('sys.path', sys.path + [tempdir]):
            import my_test_module as mtm
            traces = [
                CallTrace(mtm.my_test_function, {
                    'a': int,
                    'b': str
                }, NoneType)
            ]
            store, db_file = store_data
            store.add(traces)
            with mock.patch.dict(os.environ,
                                 {DefaultConfig.DB_PATH_VAR: db_file.name}):
                ret = cli.main(['apply', 'my_test_module'], stdout, stderr)
    assert ret == 0
    assert 'warning:' not in stdout.getvalue()
Example #18
0
 def test_generator_trace(self, collector):
     with trace_calls(collector):
         for _ in squares(3):
             pass
     assert collector.traces == [
         CallTrace(squares, {'n': int}, NoneType, int)
     ]
Example #19
0
def test_generate_stub(store_data, stdout, stderr):
    store, db_file = store_data
    traces = [
        CallTrace(func, {'a': int, 'b': str}, NoneType),
        CallTrace(func2, {'a': int, 'b': int}, NoneType),
    ]
    store.add(traces)
    with mock.patch.dict(os.environ, {DefaultConfig.DB_PATH_VAR: db_file.name}):
        ret = cli.main(['stub', func.__module__], stdout, stderr)
    expected = """def func(a: int, b: str) -> None: ...


def func2(a: int, b: int) -> None: ...
"""
    assert stdout.getvalue() == expected
    assert stderr.getvalue() == ''
    assert ret == 0
Example #20
0
 def test_access_property(self, collector):
     """Check that we correctly trace functions decorated with @property"""
     o = Oracle()
     with trace_calls(collector):
         o.meaning_of_life
     assert collector.traces == [
         CallTrace(Oracle.meaning_of_life.fget, {'self': Oracle}, int)
     ]
Example #21
0
 def test_simple_call(self, collector):
     with trace_calls(collector):
         simple_add(1, 2)
     assert collector.traces == [
         CallTrace(simple_add, {
             'a': int,
             'b': int
         }, int)
     ]
Example #22
0
    def test_remove_funcs_with_unparsable_defaults(self):
        """We should remove stubs for functions with default values whose reprs are unparsable.

        During application, retype needs to parse the stubs that we give it. We
        use repr() to produce what is used for the default value.
        """
        trace = CallTrace(has_unparsable_default, {})
        stubs = build_module_stubs_from_traces([trace])
        assert stubs == {}
Example #23
0
def test_get_diff2(store_data, stdout, stderr):
    store, db_file = store_data
    traces = [
        CallTrace(
            super_long_function_with_long_params, {
                'long_param1': str,
                'long_param2': str,
                'long_param3': int,
                'long_param4': str,
                'long_param5': int,
            }, None),
        CallTrace(func_anno, {
            'a': int,
            'b': int
        }, int),
    ]
    store.add(traces)
    with mock.patch.dict(os.environ,
                         {DefaultConfig.DB_PATH_VAR: db_file.name}):
        ret = cli.main(['stub', func.__module__, '--diff'], stdout, stderr)
    expected = """- def func_anno(a: int, b: str) -> None: ...
?                          ^ -     ^^ ^
+ def func_anno(a: int, b: int) -> int: ...
?                          ^^      ^ ^


  def super_long_function_with_long_params(
      long_param1: str,
      long_param2: str,
-     long_param3: str,
?                  ^ -
+     long_param3: int,
?                  ^^
      long_param4: str,
-     long_param5: str
?                  ^ -
+     long_param5: int
?                  ^^
  ) -> None: ...
"""
    assert stdout.getvalue() == expected
    assert stderr.getvalue() == ''
    assert ret == 0
Example #24
0
 def test_log_failure_and_continue(self, caplog):
     traces = [
         CallTrace(dummy_func, {
             'a': int,
             'b': int
         }, int),
         CallTrace(object(), {}),  # object() will fail to serialize
         CallTrace(dummy_func, {
             'a': str,
             'b': str
         }, str),
     ]
     rows = list(serialize_traces(traces))
     expected = [
         CallTraceRow.from_trace(traces[0]),
         CallTraceRow.from_trace(traces[2]),
     ]
     assert rows == expected
     assert [r.msg for r in caplog.records] == ["Failed to serialize trace"]
Example #25
0
def trace(provide_callables_from_fixtures_modules):
    return CallTrace(
        func=provide_callables_from_fixtures_modules["triangle"],
        arg_types={
            "x": int,
            "y": int,
            "z": int
        },
        return_type=None,
        yield_type=None,
    )
Example #26
0
 def test_filtering(self, collector):
     """If supplied, the code filter should decide which code objects are traced"""
     with trace_calls(collector, lambda code: code.co_name == 'simple_add'):
         simple_add(1, 2)
         explicit_return_none()
     assert collector.traces == [
         CallTrace(simple_add, {
             'a': int,
             'b': int
         }, int)
     ]
Example #27
0
    def test_cython_wrapper(self, collector):
        """Check that we can dig through Cython wrappers in looking for methods.

        As long as the Cython decorator sets __wrapped__ correctly, anyway.
        """
        cython_test_obj = CythonTest()
        with trace_calls(collector, max_typed_dict_size=0):
            cython_test_obj.cython_testfunc()

        trace = CallTrace(cython_test_obj.cython_testfunc.__wrapped__, {'self': CythonTest}, int)
        assert trace in collector.traces
Example #28
0
def test_display_list_of_modules(store, db_file, stdout, stderr):
    traces = [
        CallTrace(func, {'a': int, 'b': str}, NoneType),
    ]
    store.add(traces)
    with mock.patch.dict(os.environ, {DefaultConfig.DB_PATH_VAR: db_file.name}):
        ret = cli.main(['list-modules'], stdout, stderr)

    expected = ""
    assert stderr.getvalue() == expected
    expected = "tests.test_cli\n"
    assert stdout.getvalue() == expected
    assert ret == 0
Example #29
0
def test_print_stub_ignore_existing_annotations(store, db_file, stdout, stderr):
    traces = [
        CallTrace(func_anno, {'a': int, 'b': int}, int),
    ]
    store.add(traces)
    with mock.patch.dict(os.environ, {DefaultConfig.DB_PATH_VAR: db_file.name}):
        ret = cli.main(['stub', func.__module__, '--ignore-existing-annotations'],
                       stdout, stderr)
    expected = """def func_anno(a: int, b: int) -> int: ...
"""
    assert stdout.getvalue() == expected
    assert stderr.getvalue() == ''
    assert ret == 0
Example #30
0
 def test_build_index(self):
     idxb = StubIndexBuilder('tests')
     idxb.log(CallTrace(untyped_helper, {'x': int, 'y': str}, str))
     sig = Signature.from_callable(untyped_helper)
     sig = sig.replace(parameters=[
         Parameter('x', Parameter.POSITIONAL_OR_KEYWORD, annotation=int),
         Parameter('y', Parameter.POSITIONAL_OR_KEYWORD, annotation=str),
     ],
                       return_annotation=str)
     mod_stub = ModuleStub(function_stubs=[
         FunctionStub('untyped_helper', sig, FunctionKind.MODULE)
     ])
     expected = {'tests.test_stubs': mod_stub}
     assert idxb.get_stubs() == expected