Skip to content

Commit

Permalink
fix: make sure functions can be excluded
Browse files Browse the repository at this point in the history
Changes in 68ff82e meant that it was no longer possible to exclude a
function by name. These changes make it work again.
  • Loading branch information
apotterri committed Oct 27, 2023
1 parent 2d7ff3a commit 9a8167d
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 6 deletions.
13 changes: 8 additions & 5 deletions _appmap/importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,15 @@ def instrument_functions(filterable, selected_functions=None):
logger.debug(" functions %s", functions)

for fn_name, static_fn, fn in functions:
if selected_functions and fn_name not in selected_functions:
continue

new_fn = cls.filter_chain.wrap(FilterableFn(filterable, fn, static_fn))
if fn != new_fn:
wrapt.wrap_function_wrapper(filterable.obj, fn_name, new_fn)
# Only instrument the function if it was specifically called out for the package
# (e.g. because it should be labeled), or it's included by the filters
filterableFn = FilterableFn(filterable, fn, static_fn)
matched = cls.filter_chain.filter(filterableFn)
if (selected_functions and fn_name in selected_functions) or matched:
new_fn = cls.filter_chain.wrap(filterableFn)
if fn != new_fn:
wrapt.wrap_function_wrapper(filterable.obj, fn_name, new_fn)

# Import Config here, to avoid circular top-level imports.
from .configuration import Config # pylint: disable=import-outside-toplevel
Expand Down
10 changes: 9 additions & 1 deletion _appmap/test/conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import importlib
import sys
from distutils.dir_util import copy_tree
from functools import partialmethod

Expand Down Expand Up @@ -65,6 +66,10 @@ def pytest_runtest_setup(item):
# Reload it to make sure it's instrumented, or not, as set in appmap.yml.
importlib.reload(yaml)

# Remove the example_class module, so it will get reinstrumented the next time it's needed. We
# should find a way to do this more generically, i.e. for any modules loaded by a test case.
sys.modules.pop("example_class", None)


@pytest.fixture(scope="session", name="git_directory")
def git_directory_fixture(tmp_path_factory):
Expand Down Expand Up @@ -100,6 +105,7 @@ def _dj_autoclear_mailbox() -> None:

@pytest.fixture(name="verify_example_appmap")
def fixture_verify_appmap(monkeypatch):

def _generate(check_fn, method_name):
monkeypatch.setattr(
generation.FuncEntry,
Expand All @@ -110,7 +116,9 @@ def _generate(check_fn, method_name):
rec = appmap.Recording()
with rec:
# pylint: disable=import-outside-toplevel, import-error
from example_class import ExampleClass
from example_class import ( # pyright: ignore[reportMissingImports]
ExampleClass,
)

# pylint: enable=import-outside-toplevel, import-error

Expand Down
7 changes: 7 additions & 0 deletions _appmap/test/data/appmap-exclude-fn.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

name: TestApp
packages:
- path: example_class
exclude:
- ExampleClass.another_method
- path: package1.package2.Mod1Class
13 changes: 13 additions & 0 deletions _appmap/test/data/appmap-no-pyyaml.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: TestApp
packages:
# note: this rule needs to go first, before the more general rule
- path: example_class.Super
shallow: true
- path: example_class
- path: appmap_testing
- path: package1
labels:
serialization: yaml.dump
example-label:
- example_class.ExampleClass.test_exception
- yaml.dump
18 changes: 18 additions & 0 deletions _appmap/test/test_importer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import sys

import pytest

from _appmap.importer import Importer, wrap_exec_module
from _appmap.wrapt.wrappers import BoundFunctionWrapper


def test_exec_module_protection(monkeypatch):
Expand All @@ -28,3 +31,18 @@ def do_import(*args, **kwargs): # pylint: disable=unused-argument

f()
assert True


@pytest.mark.appmap_enabled(config="appmap-exclude-fn.yml")
@pytest.mark.usefixtures("with_data_dir")
def test_excluded(verify_example_appmap):
def check_imports(*_):
# pylint: disable=import-outside-toplevel, import-error
from example_class import ExampleClass # pyright: ignore[reportMissingImports]

# pylint: enable=import-outside-toplevel, import-error

assert isinstance(ExampleClass.instance_method, BoundFunctionWrapper)
assert not isinstance(ExampleClass.another_method, BoundFunctionWrapper)

verify_example_appmap(check_imports, "instance_method")
1 change: 1 addition & 0 deletions _appmap/test/test_labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def check_labels(*_):

verify_example_appmap(check_labels, "instance_method")

@pytest.mark.appmap_enabled(config="appmap-no-pyyaml.yml")
def test_mod_instrumented_by_preset(self, verify_example_appmap):
def check_labels(*_):
import yaml # pylint: disable=import-outside-toplevel
Expand Down

0 comments on commit 9a8167d

Please sign in to comment.