appmap 2.1.5__tar.gz → 2.1.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {appmap-2.1.5 → appmap-2.1.6}/PKG-INFO +1 -1
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/event.py +0 -1
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/importer.py +1 -1
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/instrument.py +0 -1
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/recording.py +1 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/djangoapp/settings.py +13 -0
- appmap-2.1.6/_appmap/test/data/django/test/test_request.py +8 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_django.py +3 -3
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_properties.py +1 -1
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_recording.py +38 -23
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_test_frameworks.py +14 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/pytest.py +8 -1
- {appmap-2.1.5 → appmap-2.1.6}/pyproject.toml +1 -1
- {appmap-2.1.5 → appmap-2.1.6}/vendor/_appmap/wrapt/wrappers.py +40 -21
- {appmap-2.1.5 → appmap-2.1.6}/LICENSE +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/README.md +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/configuration.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/django.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/env.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/fastapi.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/flask.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/generation.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/labels.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/metadata.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/noappmap.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/py_version_check.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/recorder.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/remote_recording.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/singleton.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/appmap_test_base.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/bin/server_runner +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/conftest.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap-all-paths-malformed.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap-broken.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap-class.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap-empty-path.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap-exclude-fn.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap-func.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap-malformed-path.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap-no-pyyaml.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap_testing/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/appmap_testing/django_simplelazyobject.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config/src/package/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config/test/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config/test/foo.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config-exclude/.hide/hidden_mod/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config-exclude/node_modules/node_mod/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config-exclude/src/package/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config-exclude/test/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config-exclude/venv/venv_mod/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config-up/appmap.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config-up/project/p1/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config-up/project/p2/sub1/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/appmap.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/djangoapp/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/djangoapp/djangoapp.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/djangoapp/hello_world.html +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/djangoapp/middleware.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/djangoapp/settings_dev.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/djangoapp/urls.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/init/sitecustomize.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/manage.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/pytest.ini +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/test/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/test/test_app.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/django/test/test_unittest_setup.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/example_class.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/expected.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/fastapi/appmap.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/fastapi/fastapiapp/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/fastapi/fastapiapp/main.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/fastapi/init/sitecustomize.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/fastapi/test_app.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/flask/appmap.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/flask/flaskapp.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/flask/init/sitecustomize.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/flask/templates/test.html +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/flask/test_app.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/flask-instrumented/appmap.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/flask-instrumented/flaskapp.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/flask-instrumented/init/sitecustomize.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/flask-instrumented/test_app.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/package1/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/package1/package2/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/package1/package2/__main__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/package1/package2/mod1.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/params.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/properties_class.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/appmap-no-test-cases.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/appmap.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/expected/pytest-numpy1-no-test-cases.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/expected/pytest-numpy1.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/expected/pytest-numpy2-no-test-cases.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/expected/pytest-numpy2.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/expected/status_errored.metadata.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/expected/status_failed.metadata.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/expected/status_xfailed.metadata.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/simple.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/tests/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/tests/test_noappmap.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/tests/test_simple.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest-instrumented/appmap.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest-instrumented/init/sitecustomize.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest-instrumented/test_instrumented.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/remote.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/trial/.gitignore +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/trial/appmap-no-test-cases.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/trial/appmap.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/trial/expected/pytest-no-test-cases.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/trial/expected/pytest.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/trial/init/sitecustomize.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/trial/test/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/trial/test/test_deferred.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/appmap-no-test-cases.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/appmap.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/pytest.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/status_errored.metadata.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/status_failed.metadata.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/status_xfailed.metadata.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/status_xsucceeded.metadata.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/unittest-no-test-cases.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/unittest.appmap.json +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/init/sitecustomize.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/simple/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/simple/test_noappmap.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/simple/test_simple.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/helpers.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/normalize.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_command.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_configuration.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_describe_value.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_django_simplelazyobject.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_env.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_events.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_fastapi.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_flask.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_generation.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_http.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_importer.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_labels.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_metadata.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_params.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_runner.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_sqlalchemy.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/test_util.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/test/web_framework.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/testing_framework.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/trace_logger.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/unittest.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/utils.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/_appmap/web_framework.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/command/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/command/appmap_agent_init.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/command/appmap_agent_status.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/command/appmap_agent_validate.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/command/runner.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/django.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/fastapi.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/flask.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/http.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/labeling/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/labeling/crypto.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/labeling/django.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/labeling/flask.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/labeling/formats.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/labeling/http.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/labeling/jobs.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/labeling/jwt.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/labeling/logger.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/labeling/random.yml +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/sqlalchemy.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/unittest.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap/uvicorn.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/appmap.pth +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/vendor/_appmap/wrapt/LICENSE +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/vendor/_appmap/wrapt/__init__.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/vendor/_appmap/wrapt/arguments.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/vendor/_appmap/wrapt/decorators.py +0 -0
- {appmap-2.1.5 → appmap-2.1.6}/vendor/_appmap/wrapt/importer.py +0 -0
|
@@ -119,7 +119,6 @@ def call_instrumented(f, instance, args, kwargs):
|
|
|
119
119
|
def instrument(filterable):
|
|
120
120
|
"""return an instrumented function"""
|
|
121
121
|
logger.debug("hooking %s", filterable.fqname)
|
|
122
|
-
fn = filterable.obj
|
|
123
122
|
|
|
124
123
|
make_call_event = event.CallEvent.make(filterable)
|
|
125
124
|
params = CallEvent.make_params(filterable)
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
5
|
+
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
6
|
+
|
|
1
7
|
# If the SECRET_KEY isn't defined we get the misleading error message
|
|
2
8
|
# CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False.
|
|
3
9
|
SECRET_KEY = "3*+d^_kjnr2gz)4q2m(&&^%$p4fj5dk3%lz4pl3g4m-%6!gf&)"
|
|
@@ -10,3 +16,10 @@ ROOT_URLCONF = "djangoapp.urls"
|
|
|
10
16
|
|
|
11
17
|
# Turn off deprecation warning
|
|
12
18
|
USE_TZ = True
|
|
19
|
+
|
|
20
|
+
DATABASES = {
|
|
21
|
+
"default": {
|
|
22
|
+
"ENGINE": "django.db.backends.sqlite3",
|
|
23
|
+
"NAME": BASE_DIR / "db.sqlite3",
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -198,7 +198,7 @@ class TestDjangoApp:
|
|
|
198
198
|
# To really check middleware reset, the tests must run in order,
|
|
199
199
|
# so disable randomly.
|
|
200
200
|
result = pytester.runpytest("-svv", "-p", "no:randomly")
|
|
201
|
-
result.assert_outcomes(passed=
|
|
201
|
+
result.assert_outcomes(passed=6, failed=0, errors=0)
|
|
202
202
|
# Look for the http_server_request event in test_app's appmap. If
|
|
203
203
|
# middleware reset is broken, it won't be there.
|
|
204
204
|
appmap_file = pytester.path / "tmp" / "appmap" / "pytest" / "test_request.appmap.json"
|
|
@@ -212,7 +212,7 @@ class TestDjangoApp:
|
|
|
212
212
|
def test_disabled(self, pytester, monkeypatch):
|
|
213
213
|
monkeypatch.setenv("_APPMAP", "false")
|
|
214
214
|
result = pytester.runpytest("-svv", "-p", "no:randomly", "-k", "test_request")
|
|
215
|
-
result.assert_outcomes(passed=
|
|
215
|
+
result.assert_outcomes(passed=3, failed=0, errors=0)
|
|
216
216
|
assert not (pytester.path / "tmp").exists()
|
|
217
217
|
|
|
218
218
|
def test_disabled_for_process(self, pytester, monkeypatch):
|
|
@@ -222,7 +222,7 @@ class TestDjangoApp:
|
|
|
222
222
|
|
|
223
223
|
# There are two tests for remote recording. They should both fail,
|
|
224
224
|
# because process recording should disable remote recording.
|
|
225
|
-
result.assert_outcomes(passed=
|
|
225
|
+
result.assert_outcomes(passed=4, failed=2, errors=0)
|
|
226
226
|
|
|
227
227
|
assert (pytester.path / "tmp" / "appmap" / "process").exists()
|
|
228
228
|
assert not (pytester.path / "tmp" / "appmap" / "requests").exists()
|
|
@@ -9,6 +9,7 @@ from threading import Thread
|
|
|
9
9
|
import pytest
|
|
10
10
|
|
|
11
11
|
import appmap
|
|
12
|
+
from _appmap.configuration import Config
|
|
12
13
|
from _appmap.event import Event
|
|
13
14
|
from _appmap.recorder import Recorder, ThreadRecorder
|
|
14
15
|
from _appmap.wrapt import FunctionWrapper
|
|
@@ -16,6 +17,17 @@ from _appmap.wrapt import FunctionWrapper
|
|
|
16
17
|
from .normalize import normalize_appmap, remove_line_numbers
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
def _call_modfunc(q):
|
|
21
|
+
r = appmap.Recording()
|
|
22
|
+
with r:
|
|
23
|
+
f = q.get()
|
|
24
|
+
f()
|
|
25
|
+
events = r.events
|
|
26
|
+
assert len(events) == 2
|
|
27
|
+
assert events[0].event == "call"
|
|
28
|
+
assert events[0].method_id == "modfunc"
|
|
29
|
+
|
|
30
|
+
|
|
19
31
|
@pytest.mark.appmap_enabled
|
|
20
32
|
@pytest.mark.usefixtures("with_data_dir")
|
|
21
33
|
class TestRecordingWhenEnabled:
|
|
@@ -47,11 +59,12 @@ class TestRecordingWhenEnabled:
|
|
|
47
59
|
), f"expected path {expected_path}"
|
|
48
60
|
|
|
49
61
|
def test_recording_clears(self):
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
62
|
+
# pylint: disable=import-error
|
|
63
|
+
from example_class import ExampleClass # pyright: ignore[reportMissingImports]
|
|
64
|
+
# pylint: enable=import-error
|
|
53
65
|
|
|
54
|
-
|
|
66
|
+
rec = appmap.Recording()
|
|
67
|
+
with rec:
|
|
55
68
|
ExampleClass.static_method()
|
|
56
69
|
|
|
57
70
|
# fresh recording shouldn't contain previous traces
|
|
@@ -68,9 +81,9 @@ class TestRecordingWhenEnabled:
|
|
|
68
81
|
assert rec.events[2].method_id == "instance_method"
|
|
69
82
|
|
|
70
83
|
def test_recording_shallow(self):
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
# pylint: disable=import-error
|
|
85
|
+
from example_class import ExampleClass # pyright: ignore[reportMissingImports]
|
|
86
|
+
# pylint: enable=import-error
|
|
74
87
|
|
|
75
88
|
rec = appmap.Recording()
|
|
76
89
|
with rec:
|
|
@@ -82,9 +95,9 @@ class TestRecordingWhenEnabled:
|
|
|
82
95
|
assert len(rec.events) == 8
|
|
83
96
|
|
|
84
97
|
def test_recording_wrapped(self):
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
98
|
+
# pylint: disable=import-error
|
|
99
|
+
from example_class import ExampleClass # pyright: ignore[reportMissingImports]
|
|
100
|
+
# pylint: enable=import-error
|
|
88
101
|
|
|
89
102
|
rec = appmap.Recording()
|
|
90
103
|
with rec:
|
|
@@ -117,21 +130,23 @@ class TestRecordingWhenEnabled:
|
|
|
117
130
|
f1 = deepcopy(modfunc)
|
|
118
131
|
f1()
|
|
119
132
|
|
|
120
|
-
def test_can_pickle(self):
|
|
121
|
-
|
|
133
|
+
def test_can_pickle(self, monkeypatch):
|
|
134
|
+
# Make sure subprocesses see whatever config is set for us.
|
|
135
|
+
monkeypatch.setenv("APPMAP_CONFIG", str(Config.current._file)) # pylint: disable=protected-access
|
|
122
136
|
|
|
123
|
-
from
|
|
124
|
-
modfunc,
|
|
125
|
-
)
|
|
137
|
+
from multiprocessing import Process, Queue
|
|
126
138
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
139
|
+
# pylint: disable=import-error
|
|
140
|
+
from example_class import modfunc # pyright: ignore[reportMissingImports]
|
|
141
|
+
# pylint: enable=import-error
|
|
142
|
+
|
|
143
|
+
assert isinstance(modfunc, FunctionWrapper), "modfunc isn't instrumented?"
|
|
144
|
+
|
|
145
|
+
q = Queue()
|
|
146
|
+
q.put(modfunc)
|
|
147
|
+
p = Process(target=_call_modfunc, args=(q,))
|
|
148
|
+
p.start()
|
|
149
|
+
p.join()
|
|
135
150
|
|
|
136
151
|
|
|
137
152
|
@pytest.mark.appmap_enabled
|
|
@@ -122,6 +122,20 @@ class TestPytestRunnerPytest(_TestTestRunner):
|
|
|
122
122
|
verify_expected_appmap(testdir, f"-numpy{numpy_version.major}-no-test-cases")
|
|
123
123
|
verify_expected_metadata(testdir)
|
|
124
124
|
|
|
125
|
+
@pytest.mark.example_dir("django")
|
|
126
|
+
def test_pytest_django(testdir):
|
|
127
|
+
result = testdir.runpytest("-svv", "-k", "test_request_test")
|
|
128
|
+
result.assert_outcomes(passed=1)
|
|
129
|
+
# django.test.TestCase is a subclass of unittest.TestCase, so recorder type is unittest
|
|
130
|
+
assert (
|
|
131
|
+
testdir.path
|
|
132
|
+
/ "tmp"
|
|
133
|
+
/ "appmap"
|
|
134
|
+
/ "unittest"
|
|
135
|
+
/ "test_test_request_TestRequest_test_request_test.appmap.json"
|
|
136
|
+
).exists()
|
|
137
|
+
assert not (testdir.path / "tmp" / "appmap" / "requests").exists()
|
|
138
|
+
|
|
125
139
|
|
|
126
140
|
@pytest.mark.example_dir("trial")
|
|
127
141
|
class TestPytestRunnerTrial(_TestTestRunner):
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
from importlib.metadata import version
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
|
+
try:
|
|
5
|
+
from pytest_django.django_compat import is_django_unittest
|
|
6
|
+
except ImportError:
|
|
7
|
+
|
|
8
|
+
def is_django_unittest(item):
|
|
9
|
+
return False
|
|
10
|
+
|
|
4
11
|
|
|
5
12
|
from _appmap import noappmap, testing_framework, wrapt
|
|
6
13
|
from _appmap.env import Env
|
|
@@ -51,7 +58,7 @@ if not Env.current.is_appmap_repo and Env.current.enables("tests"):
|
|
|
51
58
|
# running the test case. (This nesting of function calls is
|
|
52
59
|
# verified by the expected appmap in the test for a unittest
|
|
53
60
|
# TestCase run by pytest.)
|
|
54
|
-
if hasattr(item, "_testcase"):
|
|
61
|
+
if hasattr(item, "_testcase") and not is_django_unittest(item):
|
|
55
62
|
setattr(
|
|
56
63
|
item._testcase, # pylint: disable=protected-access
|
|
57
64
|
"_appmap_pytest_recording",
|
|
@@ -457,11 +457,8 @@ class ObjectProxy(with_metaclass(_ObjectProxyMetaType)):
|
|
|
457
457
|
raise NotImplementedError(
|
|
458
458
|
'object proxy must define __reduce_ex__()')
|
|
459
459
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
# AppMaps.
|
|
463
|
-
def __reduce_ex__(self, protocol):
|
|
464
|
-
return self.__wrapped__.__qualname__
|
|
460
|
+
def __reduce_ex__(self):
|
|
461
|
+
raise NotImplementedError("object proxy must define __reduce_ex__()")
|
|
465
462
|
|
|
466
463
|
class CallableObjectProxy(ObjectProxy):
|
|
467
464
|
|
|
@@ -508,6 +505,20 @@ class PartialCallableObjectProxy(ObjectProxy):
|
|
|
508
505
|
|
|
509
506
|
return self.__wrapped__(*_args, **_kwargs)
|
|
510
507
|
|
|
508
|
+
def _unpickle_functionwrapper(modname, qualname):
|
|
509
|
+
"""
|
|
510
|
+
Given the module name and qualname of a function, return a FunctionWrapper instance for it. This
|
|
511
|
+
simply imports the module, then fetches the appropriate function. Provided AppMap
|
|
512
|
+
instrumentation has been configured correctly when unpickling, the attribute for the function
|
|
513
|
+
will be a FunctionWrapper. If it hasn't been configured correctly, the attribute will simply be
|
|
514
|
+
the original function. (This means the application will function correctly, but no events will
|
|
515
|
+
get generated when the function is called.)
|
|
516
|
+
"""
|
|
517
|
+
_, _, original = resolve_path(modname, qualname)
|
|
518
|
+
|
|
519
|
+
return original
|
|
520
|
+
|
|
521
|
+
|
|
511
522
|
class _FunctionWrapperBase(ObjectProxy):
|
|
512
523
|
__slots__ = (
|
|
513
524
|
"_self_instance",
|
|
@@ -656,6 +667,20 @@ class _FunctionWrapperBase(ObjectProxy):
|
|
|
656
667
|
else:
|
|
657
668
|
return issubclass(subclass, self.__wrapped__)
|
|
658
669
|
|
|
670
|
+
# Implement this here, rather than in ObjectProxy, because _unpickle_functionwrapper will only
|
|
671
|
+
# create new instances of subclasses of _FunctionWrapperBase via the agent's import hooks.
|
|
672
|
+
def __reduce_ex__(self, _):
|
|
673
|
+
modname = self.__wrapped__.__module__
|
|
674
|
+
qualname = getattr(self.__wrapped__, "__qualname__", None)
|
|
675
|
+
if qualname is None:
|
|
676
|
+
qualname = self.__wrapped__.__name__
|
|
677
|
+
|
|
678
|
+
return (
|
|
679
|
+
_unpickle_functionwrapper,
|
|
680
|
+
(modname, qualname),
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
|
|
659
684
|
class BoundFunctionWrapper(_FunctionWrapperBase):
|
|
660
685
|
|
|
661
686
|
def __new__(cls, *args, **kwargs):
|
|
@@ -738,24 +763,18 @@ class BoundFunctionWrapper(_FunctionWrapperBase):
|
|
|
738
763
|
return self._self_wrapper(self.__wrapped__, instance, args,
|
|
739
764
|
kwargs)
|
|
740
765
|
|
|
741
|
-
|
|
766
|
+
def __getattribute__(self, name):
|
|
767
|
+
if name == "__func__":
|
|
768
|
+
# The __func__ attribute of a bound method is the unbound method. The corresponding
|
|
769
|
+
# attribute of a BoundFunctionWrapper is the associated FunctionWrapper (saved in
|
|
770
|
+
# _self_parent when the BFW is created).
|
|
771
|
+
return self._self_parent
|
|
742
772
|
|
|
743
|
-
|
|
773
|
+
return super().__getattribute__(name)
|
|
744
774
|
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
# string, which would cause deepcopy to return the original FunctionWrapper.
|
|
749
|
-
#
|
|
750
|
-
|
|
751
|
-
# def __reduce_ex__(self, protocol):
|
|
752
|
-
# return self.__wrapped__.__qualname__
|
|
753
|
-
|
|
754
|
-
# return FunctionWrapper, (
|
|
755
|
-
# self.__wrapped__,
|
|
756
|
-
# self._self_wrapper,
|
|
757
|
-
# self._self_enabled,
|
|
758
|
-
# )
|
|
775
|
+
|
|
776
|
+
class FunctionWrapper(_FunctionWrapperBase):
|
|
777
|
+
__bound_function_wrapper__ = BoundFunctionWrapper
|
|
759
778
|
|
|
760
779
|
def __init__(self, wrapped, wrapper, enabled=None):
|
|
761
780
|
# What it is we are wrapping here could be anything. We need to
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/config-exclude/node_modules/node_mod/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/expected/status_errored.metadata.json
RENAMED
|
File without changes
|
|
File without changes
|
{appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/pytest/expected/status_xfailed.metadata.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/trial/expected/pytest-no-test-cases.appmap.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/status_errored.metadata.json
RENAMED
|
File without changes
|
{appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/status_failed.metadata.json
RENAMED
|
File without changes
|
{appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/status_xfailed.metadata.json
RENAMED
|
File without changes
|
{appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/status_xsucceeded.metadata.json
RENAMED
|
File without changes
|
{appmap-2.1.5 → appmap-2.1.6}/_appmap/test/data/unittest/expected/unittest-no-test-cases.appmap.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|