appmap 1.24.0__tar.gz → 2.0.0__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.
Files changed (165) hide show
  1. {appmap-1.24.0 → appmap-2.0.0}/PKG-INFO +6 -2
  2. {appmap-1.24.0 → appmap-2.0.0}/README.md +5 -1
  3. {appmap-1.24.0 → appmap-2.0.0}/_appmap/configuration.py +3 -0
  4. {appmap-1.24.0 → appmap-2.0.0}/_appmap/env.py +19 -29
  5. {appmap-1.24.0 → appmap-2.0.0}/_appmap/event.py +3 -0
  6. {appmap-1.24.0 → appmap-2.0.0}/_appmap/recording.py +1 -4
  7. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/trial/test/test_deferred.py +1 -1
  8. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/simple/test_simple.py +2 -2
  9. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/normalize.py +1 -0
  10. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_command.py +14 -10
  11. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_configuration.py +52 -25
  12. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_describe_value.py +1 -1
  13. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_django.py +15 -1
  14. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_env.py +2 -2
  15. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_flask.py +16 -1
  16. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_http.py +2 -2
  17. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_runner.py +1 -1
  18. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_test_frameworks.py +8 -1
  19. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_util.py +1 -2
  20. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/web_framework.py +1 -0
  21. {appmap-1.24.0 → appmap-2.0.0}/_appmap/unittest.py +0 -3
  22. {appmap-1.24.0 → appmap-2.0.0}/_appmap/utils.py +9 -10
  23. {appmap-1.24.0 → appmap-2.0.0}/_appmap/web_framework.py +3 -2
  24. appmap-2.0.0/appmap/__init__.py +48 -0
  25. {appmap-1.24.0 → appmap-2.0.0}/appmap/command/runner.py +1 -2
  26. {appmap-1.24.0 → appmap-2.0.0}/appmap/http.py +1 -1
  27. {appmap-1.24.0 → appmap-2.0.0}/appmap/labeling/__init__.py +1 -1
  28. {appmap-1.24.0 → appmap-2.0.0}/appmap/pytest.py +2 -6
  29. appmap-2.0.0/appmap/unittest.py +8 -0
  30. {appmap-1.24.0 → appmap-2.0.0}/pyproject.toml +2 -3
  31. appmap-1.24.0/appmap/__init__.py +0 -48
  32. appmap-1.24.0/appmap/unittest.py +0 -7
  33. {appmap-1.24.0 → appmap-2.0.0}/LICENSE +0 -0
  34. {appmap-1.24.0 → appmap-2.0.0}/_appmap/__init__.py +0 -0
  35. {appmap-1.24.0 → appmap-2.0.0}/_appmap/django.py +0 -0
  36. {appmap-1.24.0 → appmap-2.0.0}/_appmap/fastapi.py +0 -0
  37. {appmap-1.24.0 → appmap-2.0.0}/_appmap/flask.py +0 -0
  38. {appmap-1.24.0 → appmap-2.0.0}/_appmap/generation.py +0 -0
  39. {appmap-1.24.0 → appmap-2.0.0}/_appmap/importer.py +0 -0
  40. {appmap-1.24.0 → appmap-2.0.0}/_appmap/instrument.py +0 -0
  41. {appmap-1.24.0 → appmap-2.0.0}/_appmap/labels.py +0 -0
  42. {appmap-1.24.0 → appmap-2.0.0}/_appmap/metadata.py +0 -0
  43. {appmap-1.24.0 → appmap-2.0.0}/_appmap/noappmap.py +0 -0
  44. {appmap-1.24.0 → appmap-2.0.0}/_appmap/py_version_check.py +0 -0
  45. {appmap-1.24.0 → appmap-2.0.0}/_appmap/recorder.py +0 -0
  46. {appmap-1.24.0 → appmap-2.0.0}/_appmap/remote_recording.py +0 -0
  47. {appmap-1.24.0 → appmap-2.0.0}/_appmap/singleton.py +0 -0
  48. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/__init__.py +0 -0
  49. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/appmap_test_base.py +0 -0
  50. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/bin/server_runner +0 -0
  51. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/conftest.py +0 -0
  52. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap-all-paths-malformed.yml +0 -0
  53. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap-broken.yml +0 -0
  54. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap-class.yml +0 -0
  55. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap-empty-path.yml +0 -0
  56. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap-exclude-fn.yml +0 -0
  57. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap-func.yml +0 -0
  58. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap-malformed-path.yml +0 -0
  59. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap-no-pyyaml.yml +0 -0
  60. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap.yml +0 -0
  61. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap_testing/__init__.py +0 -0
  62. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/appmap_testing/django_simplelazyobject.py +0 -0
  63. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/config/src/package/__init__.py +0 -0
  64. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/config/test/__init__.py +0 -0
  65. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/config/test/foo.py +0 -0
  66. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/config-exclude/.hide/hidden_mod/__init__.py +0 -0
  67. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/config-exclude/node_modules/node_mod/__init__.py +0 -0
  68. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/config-exclude/src/package/__init__.py +0 -0
  69. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/config-exclude/test/__init__.py +0 -0
  70. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/config-exclude/venv/venv_mod/__init__.py +0 -0
  71. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/config-up/appmap.yml +0 -0
  72. {appmap-1.24.0/_appmap/test/data/config-up/subprojects → appmap-2.0.0/_appmap/test/data/config-up/project}/p1/__init__.py +0 -0
  73. {appmap-1.24.0/_appmap/test/data/config-up/subprojects → appmap-2.0.0/_appmap/test/data/config-up/project}/p2/sub1/__init__.py +0 -0
  74. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/appmap.yml +0 -0
  75. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/djangoapp/__init__.py +0 -0
  76. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/djangoapp/djangoapp.py +0 -0
  77. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/djangoapp/hello_world.html +0 -0
  78. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/djangoapp/middleware.py +0 -0
  79. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/djangoapp/settings.py +0 -0
  80. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/djangoapp/settings_dev.py +0 -0
  81. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/djangoapp/urls.py +0 -0
  82. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/init/sitecustomize.py +0 -0
  83. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/manage.py +0 -0
  84. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/pytest.ini +0 -0
  85. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/test/__init__.py +0 -0
  86. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/django/test/test_app.py +0 -0
  87. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/example_class.py +0 -0
  88. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/expected.appmap.json +0 -0
  89. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/fastapi/appmap.yml +0 -0
  90. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/fastapi/fastapiapp/__init__.py +0 -0
  91. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/fastapi/fastapiapp/main.py +0 -0
  92. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/fastapi/init/sitecustomize.py +0 -0
  93. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/fastapi/test_app.py +0 -0
  94. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/flask/appmap.yml +0 -0
  95. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/flask/flaskapp.py +0 -0
  96. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/flask/init/sitecustomize.py +0 -0
  97. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/flask/templates/test.html +0 -0
  98. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/flask/test_app.py +0 -0
  99. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/package1/__init__.py +0 -0
  100. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/package1/package2/__init__.py +0 -0
  101. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/package1/package2/__main__.py +0 -0
  102. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/package1/package2/mod1.py +0 -0
  103. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/params.py +0 -0
  104. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/pytest/appmap.yml +0 -0
  105. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/pytest/expected/pytest.appmap.json +0 -0
  106. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/pytest/expected/status_errored.metadata.json +0 -0
  107. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/pytest/expected/status_failed.metadata.json +0 -0
  108. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/pytest/expected/status_xfailed.metadata.json +0 -0
  109. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/pytest/simple.py +0 -0
  110. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/pytest/test_noappmap.py +0 -0
  111. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/pytest/test_simple.py +0 -0
  112. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/remote.appmap.json +0 -0
  113. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/trial/.gitignore +0 -0
  114. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/trial/appmap.yml +0 -0
  115. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/trial/expected/pytest.appmap.json +0 -0
  116. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/trial/init/sitecustomize.py +0 -0
  117. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/trial/test/__init__.py +0 -0
  118. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/appmap.yml +0 -0
  119. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/expected/pytest.appmap.json +0 -0
  120. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/expected/status_errored.metadata.json +0 -0
  121. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/expected/status_failed.metadata.json +0 -0
  122. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/expected/status_xfailed.metadata.json +0 -0
  123. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/expected/status_xsucceeded.metadata.json +0 -0
  124. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/expected/unittest.appmap.json +0 -0
  125. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/init/sitecustomize.py +0 -0
  126. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/simple/__init__.py +0 -0
  127. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/data/unittest/simple/test_noappmap.py +0 -0
  128. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/helpers.py +0 -0
  129. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_django_simplelazyobject.py +0 -0
  130. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_events.py +0 -0
  131. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_fastapi.py +0 -0
  132. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_generation.py +0 -0
  133. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_importer.py +0 -0
  134. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_labels.py +0 -0
  135. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_metadata.py +0 -0
  136. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_params.py +0 -0
  137. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_recording.py +0 -0
  138. {appmap-1.24.0 → appmap-2.0.0}/_appmap/test/test_sqlalchemy.py +0 -0
  139. {appmap-1.24.0 → appmap-2.0.0}/_appmap/testing_framework.py +0 -0
  140. {appmap-1.24.0 → appmap-2.0.0}/_appmap/trace_logger.py +0 -0
  141. {appmap-1.24.0 → appmap-2.0.0}/appmap/command/__init__.py +0 -0
  142. {appmap-1.24.0 → appmap-2.0.0}/appmap/command/appmap_agent_init.py +0 -0
  143. {appmap-1.24.0 → appmap-2.0.0}/appmap/command/appmap_agent_status.py +0 -0
  144. {appmap-1.24.0 → appmap-2.0.0}/appmap/command/appmap_agent_validate.py +0 -0
  145. {appmap-1.24.0 → appmap-2.0.0}/appmap/django.py +0 -0
  146. {appmap-1.24.0 → appmap-2.0.0}/appmap/fastapi.py +0 -0
  147. {appmap-1.24.0 → appmap-2.0.0}/appmap/flask.py +0 -0
  148. {appmap-1.24.0 → appmap-2.0.0}/appmap/labeling/crypto.yml +0 -0
  149. {appmap-1.24.0 → appmap-2.0.0}/appmap/labeling/django.yml +0 -0
  150. {appmap-1.24.0 → appmap-2.0.0}/appmap/labeling/flask.yml +0 -0
  151. {appmap-1.24.0 → appmap-2.0.0}/appmap/labeling/formats.yml +0 -0
  152. {appmap-1.24.0 → appmap-2.0.0}/appmap/labeling/http.yml +0 -0
  153. {appmap-1.24.0 → appmap-2.0.0}/appmap/labeling/jobs.yml +0 -0
  154. {appmap-1.24.0 → appmap-2.0.0}/appmap/labeling/jwt.yml +0 -0
  155. {appmap-1.24.0 → appmap-2.0.0}/appmap/labeling/logger.yml +0 -0
  156. {appmap-1.24.0 → appmap-2.0.0}/appmap/labeling/random.yml +0 -0
  157. {appmap-1.24.0 → appmap-2.0.0}/appmap/sqlalchemy.py +0 -0
  158. {appmap-1.24.0 → appmap-2.0.0}/appmap/uvicorn.py +0 -0
  159. {appmap-1.24.0 → appmap-2.0.0}/appmap.pth +0 -0
  160. {appmap-1.24.0 → appmap-2.0.0}/vendor/_appmap/wrapt/LICENSE +0 -0
  161. {appmap-1.24.0 → appmap-2.0.0}/vendor/_appmap/wrapt/__init__.py +0 -0
  162. {appmap-1.24.0 → appmap-2.0.0}/vendor/_appmap/wrapt/arguments.py +0 -0
  163. {appmap-1.24.0 → appmap-2.0.0}/vendor/_appmap/wrapt/decorators.py +0 -0
  164. {appmap-1.24.0 → appmap-2.0.0}/vendor/_appmap/wrapt/importer.py +0 -0
  165. {appmap-1.24.0 → appmap-2.0.0}/vendor/_appmap/wrapt/wrappers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: appmap
3
- Version: 1.24.0
3
+ Version: 2.0.0
4
4
  Summary: Create AppMap files by recording a Python application.
5
5
  Home-page: https://github.com/applandinc/appmap-python
6
6
  License: MIT
@@ -118,9 +118,13 @@ reenabled as soon as possible.]
118
118
  ### pytest
119
119
 
120
120
  Note that you must install the dependencies contained in
121
- [requirements-test.txt](requirements-test.txt) before running tests. See the explanation in
121
+ [requirements-dev.txt](requirements-dev.txt) before running tests. See the explanation in
122
122
  [pyproject.toml](pyproject.toml) for details.
123
123
 
124
+ Additionally, the tests currently require that you set `APPMAP=true`. You can
125
+ either run `pytest` with `appmap-python` (see [tox.ini](tox.ini)), or you can explicitly
126
+ set the environment variable.
127
+
124
128
  [pytest](https://docs.pytest.org/en/stable/) for testing:
125
129
 
126
130
  ```
@@ -87,9 +87,13 @@ reenabled as soon as possible.]
87
87
  ### pytest
88
88
 
89
89
  Note that you must install the dependencies contained in
90
- [requirements-test.txt](requirements-test.txt) before running tests. See the explanation in
90
+ [requirements-dev.txt](requirements-dev.txt) before running tests. See the explanation in
91
91
  [pyproject.toml](pyproject.toml) for details.
92
92
 
93
+ Additionally, the tests currently require that you set `APPMAP=true`. You can
94
+ either run `pytest` with `appmap-python` (see [tox.ini](tox.ini)), or you can explicitly
95
+ set the environment variable.
96
+
93
97
  [pytest](https://docs.pytest.org/en/stable/) for testing:
94
98
 
95
99
  ```
@@ -196,6 +196,7 @@ class Config(metaclass=SingletonMeta):
196
196
  )
197
197
 
198
198
  def _load_config(self, show_warnings=False):
199
+ # pylint: disable=too-many-branches
199
200
  self._config = {"name": None, "packages": []}
200
201
 
201
202
  # Only use a default config if the user hasn't specified a
@@ -221,6 +222,7 @@ class Config(metaclass=SingletonMeta):
221
222
  path = _resolve_relative_to(Path(env_config_filename), Path(config_dir))
222
223
 
223
224
  if path.is_file():
225
+ self._file = path
224
226
  self.file_present = True
225
227
 
226
228
  should_enable = Env.current.enabled
@@ -480,6 +482,7 @@ _startup_messages_shown = os.environ.get("_APPMAP_MESSAGES_SHOWN")
480
482
  if _startup_messages_shown is None:
481
483
  # pylint: disable=protected-access
482
484
  c._load_config(show_warnings=True)
485
+ logger.info("file: %s", c._file)
483
486
  logger.info("config: %s", c._config)
484
487
  logger.debug("package_functions: %s", c.package_functions)
485
488
  logger.info("env: %r", os.environ)
@@ -3,7 +3,6 @@
3
3
  import logging
4
4
  import logging.config
5
5
  import os
6
- import warnings
7
6
  from contextlib import contextmanager
8
7
  from os import environ
9
8
  from pathlib import Path
@@ -13,20 +12,6 @@ from _appmap.singleton import SingletonMeta
13
12
 
14
13
  from . import trace_logger
15
14
 
16
- _ENABLED_BY_DEFAULT_MSG = """
17
-
18
- The APPMAP environment variable is unset. Your code will be
19
- instrumented and recorded according to the configuration in appmap.yml.
20
-
21
- Starting with version 2, this behavior will change: when APPMAP is
22
- unset, no code will be instrumented. You will need to use the
23
- appmap-python script to run your application, or explicitly set
24
- APPMAP.
25
-
26
- Visit https://appmap.io/docs/reference/appmap-python.html#appmap-python-script for more
27
- details.
28
- """
29
-
30
15
  _cwd = Path.cwd()
31
16
  _bootenv = environ.copy()
32
17
 
@@ -36,9 +21,9 @@ def _recording_method_key(recording_method):
36
21
 
37
22
 
38
23
  class Env(metaclass=SingletonMeta):
39
- def __init__(self, env=None, cwd=None):
40
- warnings.filterwarnings("once", _ENABLED_BY_DEFAULT_MSG)
24
+ RECORD_PROCESS_DEFAULT = "false"
41
25
 
26
+ def __init__(self, env=None, cwd=None):
42
27
  # root_dir and root_dir_len are going to be used when
43
28
  # instrumenting every function, so preprocess them as
44
29
  # much as possible.
@@ -54,7 +39,6 @@ class Env(metaclass=SingletonMeta):
54
39
 
55
40
  self._configure_logging()
56
41
  enabled = self._env.get("_APPMAP", None)
57
- self._enabled_by_default = enabled is None
58
42
  self._enabled = enabled is None or enabled.lower() != "false"
59
43
 
60
44
  self._root_dir = str(self._cwd) + "/"
@@ -73,6 +57,9 @@ class Env(metaclass=SingletonMeta):
73
57
  def set(self, name, value):
74
58
  self._env[name] = value
75
59
 
60
+ def setdefault(self, name, default_value):
61
+ self._env.setdefault(name, default_value)
62
+
76
63
  def get(self, name, default=None):
77
64
  return self._env.get(name, default)
78
65
 
@@ -95,14 +82,6 @@ class Env(metaclass=SingletonMeta):
95
82
  def output_dir(self, value):
96
83
  self._output_dir = value
97
84
 
98
- @property
99
- def enabled_by_default(self):
100
- return self._enabled_by_default
101
-
102
- def warn_enabled_by_default(self):
103
- if self._enabled_by_default:
104
- warnings.warn(_ENABLED_BY_DEFAULT_MSG, category=DeprecationWarning, stacklevel=2)
105
-
106
85
  @property
107
86
  def enabled(self):
108
87
  return self._enabled
@@ -115,14 +94,25 @@ class Env(metaclass=SingletonMeta):
115
94
  if not self.enabled:
116
95
  return False
117
96
 
118
- v = self.get(_recording_method_key(recording_method), default).lower()
119
- return v != "false"
97
+ process_enabled = self._enables("process", self.RECORD_PROCESS_DEFAULT)
98
+ if recording_method == "process":
99
+ return process_enabled
100
+
101
+ # If process recording is enabled, others should be disabled
102
+ if process_enabled:
103
+ return False
104
+
105
+ # Otherwise, check the environment variable
106
+ return self._enables(recording_method, default)
107
+
108
+ def _enables(self, recording_method, default):
109
+ return self.get(_recording_method_key(recording_method), default).lower() != "false"
120
110
 
121
111
  @contextmanager
122
112
  def disabled(self, recording_method: str):
123
113
  key = _recording_method_key(recording_method)
124
114
  value = self.get(key)
125
- self.set(key, "false")
115
+ self.setdefault(key, "false")
126
116
  try:
127
117
  yield
128
118
  finally:
@@ -173,6 +173,7 @@ class Param:
173
173
 
174
174
 
175
175
  class CallEvent(Event):
176
+ # pylint: disable=method-cache-max-size-none
176
177
  __slots__ = ["_fn", "_fqfn", "static", "receiver", "parameters", "labels"]
177
178
 
178
179
  @staticmethod
@@ -217,6 +218,7 @@ class CallEvent(Event):
217
218
 
218
219
  @staticmethod
219
220
  def set_params(params, instance, args, kwargs):
221
+ # pylint: disable=too-many-branches
220
222
  # Note that set_params expects args and kwargs as a tuple and
221
223
  # dict, respectively. It operates on them as collections, so
222
224
  # it doesn't unpack them.
@@ -400,6 +402,7 @@ class HttpServerRequestEvent(MessageEvent):
400
402
 
401
403
  __slots__ = ["http_server_request"]
402
404
 
405
+ # pylint: disable=too-many-arguments
403
406
  def __init__(
404
407
  self,
405
408
  request_method,
@@ -44,7 +44,6 @@ class Recording:
44
44
  return Recorder.get_enabled()
45
45
 
46
46
  def __enter__(self):
47
- Env.current.warn_enabled_by_default()
48
47
  self.start()
49
48
 
50
49
  def __exit__(self, exc_type, exc_value, tb):
@@ -80,9 +79,7 @@ def write_appmap(
80
79
 
81
80
 
82
81
  def initialize():
83
- if Env.current.enables("process", "false"):
84
- Env.current.warn_enabled_by_default()
85
-
82
+ if Env.current.enables("process", Env.RECORD_PROCESS_DEFAULT):
86
83
  r = Recording()
87
84
  r.start()
88
85
 
@@ -1,4 +1,4 @@
1
- import time
1
+ import time # noqa: F401
2
2
 
3
3
  from twisted.internet import defer, reactor
4
4
  from twisted.trial import unittest
@@ -1,11 +1,11 @@
1
1
  import unittest
2
2
  from unittest.mock import patch
3
3
 
4
- import simple
4
+ import simple # isort: skip
5
5
 
6
6
  # Importing from decouple will cause a failure if we're not hooking
7
7
  # finders correctly.
8
- from decouple import config
8
+ from decouple import config # noqa: F401
9
9
 
10
10
  import appmap
11
11
 
@@ -67,6 +67,7 @@ def normalize_appmap(generated_appmap):
67
67
  """
68
68
 
69
69
  def normalize(dct):
70
+ # pylint: disable=too-many-branches
70
71
  if "classMap" in dct:
71
72
  dct["classMap"].sort(key=itemgetter("name"))
72
73
  if "children" in dct:
@@ -11,7 +11,7 @@ from appmap.command import appmap_agent_init, appmap_agent_status, appmap_agent_
11
11
  from .helpers import DictIncluding
12
12
 
13
13
 
14
- @pytest.fixture(name="cmd_setup")
14
+ @pytest.fixture(name="_cmd_setup")
15
15
  def _cmd_setup(request, git, data_dir, monkeypatch):
16
16
  repo_root = git.cwd
17
17
  copy_tree(data_dir / request.param, str(repo_root))
@@ -23,8 +23,8 @@ def _cmd_setup(request, git, data_dir, monkeypatch):
23
23
  return monkeypatch
24
24
 
25
25
 
26
- @pytest.mark.parametrize("cmd_setup", ["config"], indirect=True)
27
- def test_agent_init(cmd_setup, capsys):
26
+ @pytest.mark.parametrize("_cmd_setup", ["config"], indirect=True)
27
+ def test_agent_init(_cmd_setup, capsys):
28
28
  rc = appmap_agent_init._run() # pylint: disable=protected-access
29
29
 
30
30
  assert rc == 0
@@ -39,19 +39,23 @@ def test_agent_init(cmd_setup, capsys):
39
39
 
40
40
 
41
41
  class TestAgentStatus:
42
- @pytest.mark.parametrize("cmd_setup", ["pytest"], indirect=True)
42
+ @pytest.mark.parametrize("_cmd_setup", ["pytest"], indirect=True)
43
43
  @pytest.mark.parametrize("do_discovery", [True, False])
44
- def test_test_discovery_control(self, cmd_setup, do_discovery, mocker):
44
+ def test_test_discovery_control(self, _cmd_setup, do_discovery, mocker):
45
45
  mocker.patch("appmap.command.appmap_agent_status.discover_pytest_tests")
46
46
  rc = appmap_agent_status._run( # pylint: disable=protected-access
47
47
  discover_tests=do_discovery
48
48
  )
49
49
  assert rc == 0
50
50
  call_count = 1 if do_discovery else 0
51
+
52
+ # Well, pylint, if it didn't have call_count, assertion would fail,
53
+ # wouldn't it?
54
+ # pylint: disable=no-member
51
55
  assert appmap_agent_status.discover_pytest_tests.call_count == call_count
52
56
 
53
- @pytest.mark.parametrize("cmd_setup", ["pytest"], indirect=True)
54
- def test_agent_status(self, cmd_setup, capsys):
57
+ @pytest.mark.parametrize("_cmd_setup", ["pytest"], indirect=True)
58
+ def test_agent_status(self, _cmd_setup, capsys):
55
59
  rc = appmap_agent_status._run(discover_tests=True) # pylint: disable=protected-access
56
60
 
57
61
  assert rc == 0
@@ -77,8 +81,8 @@ class TestAgentStatus:
77
81
  {"args": [], "framework": "pytest", "command": "pytest"}
78
82
  )
79
83
 
80
- @pytest.mark.parametrize("cmd_setup", ["package1"], indirect=True)
81
- def test_agent_status_no_commands(self, cmd_setup, capsys):
84
+ @pytest.mark.parametrize("_cmd_setup", ["package1"], indirect=True)
85
+ def test_agent_status_no_commands(self, _cmd_setup, capsys):
82
86
  rc = appmap_agent_status._run(discover_tests=True) # pylint: disable=protected-access
83
87
 
84
88
  assert rc == 0
@@ -103,7 +107,7 @@ class TestAgentValidate:
103
107
  assert err["level"] == "error"
104
108
  assert re.match(msg, err["message"]) is not None
105
109
 
106
- def test_no_errors(self, capsys, mocker):
110
+ def test_no_errors(self, capsys):
107
111
  # Both Django and flask are installed in a dev environment, so
108
112
  # validation will succeed.
109
113
  self.check_errors(capsys, 0, 0, None)
@@ -4,6 +4,7 @@
4
4
  from contextlib import contextmanager
5
5
  from distutils.dir_util import copy_tree
6
6
  from pathlib import Path
7
+ from textwrap import dedent
7
8
 
8
9
  import pytest
9
10
  import yaml
@@ -15,10 +16,6 @@ from _appmap.env import Env
15
16
  from _appmap.importer import Filterable, NullFilter
16
17
 
17
18
 
18
- def test_enabled_by_default():
19
- assert appmap.enabled()
20
-
21
-
22
19
  @pytest.mark.appmap_enabled
23
20
  def test_can_be_configured():
24
21
  """
@@ -44,8 +41,6 @@ def test_reports_invalid():
44
41
  @pytest.mark.appmap_enabled(config="appmap-broken.yml")
45
42
  def test_is_disabled_when_unset():
46
43
  """Test that recording is disabled when APPMAP is unset but the config is broken"""
47
- assert Env.current.get("_APPMAP", None) is None
48
-
49
44
  assert not appmap.enabled()
50
45
 
51
46
 
@@ -207,7 +202,7 @@ class TestDefaultConfig(DefaultHelpers):
207
202
  # pylint: disable=protected-access
208
203
  _appmap.initialize(cwd=repo_root)
209
204
 
210
- Config.current # write the file as a side-effect
205
+ Config.current # pylint: disable=pointless-statement
211
206
  assert path.is_file()
212
207
  with open(path, encoding="utf-8") as cfg:
213
208
  actual_config = yaml.safe_load(cfg)
@@ -227,7 +222,7 @@ class TestDefaultConfig(DefaultHelpers):
227
222
  # pylint: disable=protected-access
228
223
  _appmap.initialize(cwd=repo_root, env={"_APPMAP": "false"})
229
224
 
230
- Config.current
225
+ Config.current # pylint: disable=pointless-statement
231
226
  assert not path.is_file()
232
227
 
233
228
 
@@ -240,7 +235,7 @@ class TestEmpty(DefaultHelpers):
240
235
  @contextmanager
241
236
  def incomplete_config(self):
242
237
  # pylint: disable=protected-access
243
- with open("appmap-incomplete.yml", mode="w", buffering=1) as f:
238
+ with open("appmap-incomplete.yml", mode="w", buffering=1, encoding="utf-8") as f:
244
239
  print("# Incomplete file", file=f)
245
240
  yield f
246
241
 
@@ -271,42 +266,74 @@ class TestEmpty(DefaultHelpers):
271
266
  self.check_default_config(Path(tmpdir).name)
272
267
 
273
268
  class TestSearchConfig:
269
+ # pylint: disable=too-many-arguments
270
+
274
271
  def test_config_in_parent_folder(self, data_dir, tmpdir, monkeypatch):
275
272
  copy_tree(data_dir / "config-up", str(tmpdir))
276
- project_root = tmpdir / "subprojects" / "p1"
277
- monkeypatch.chdir(project_root)
273
+ wd = tmpdir / "project" / "p1"
274
+ monkeypatch.chdir(wd)
278
275
 
279
276
  # pylint: disable=protected-access
280
- _appmap.initialize(cwd=project_root)
277
+ _appmap.initialize(cwd=wd)
281
278
  assert Config.current.name == "config-up-name"
282
279
  assert str(Env.current.output_dir).endswith(str(tmpdir / "tmp" / "appmap"))
283
280
 
284
- def test_config_not_found_until_repo_root(self, data_dir, tmpdir, git_directory, monkeypatch):
281
+ def _init_repo(self, data_dir, tmpdir, git_directory, repo_root, appmapdir):
285
282
  copy_tree(data_dir / "config-up", str(tmpdir))
286
- repo_root = tmpdir / "subprojects" / "p2"
287
283
  copy_tree(git_directory, str(repo_root))
288
- project_root = repo_root / "sub1"
289
- monkeypatch.chdir(project_root)
284
+ with open(appmapdir / "appmap.yml", "w+", encoding="utf-8") as f:
285
+ f.writelines(
286
+ dedent("""
287
+ name: project
288
+ packages: []
289
+ """)
290
+ )
291
+
292
+ @pytest.mark.parametrize("subdir", [Path("p1"), Path("p2", "sub1")])
293
+ def test_config_in_repo_root(self, data_dir, tmpdir, git_directory, monkeypatch, subdir):
294
+ repo_root = tmpdir / "project"
295
+ self._init_repo(data_dir, tmpdir, git_directory, repo_root, repo_root)
296
+
297
+ wd = repo_root / subdir
298
+ monkeypatch.chdir(wd)
290
299
 
291
300
  # pylint: disable=protected-access
292
- _appmap.initialize(cwd=project_root)
293
- # It should stop searching at repo_root.
294
- # Check that it did not find appmap.yml
295
- # in config-up folder.
296
- assert Config.current.name != "config-up-name"
301
+ _appmap.initialize(cwd=wd)
302
+
303
+ # There's a config in the repo root. It should have been found, and have
304
+ # the correct contents.
305
+ assert Config.current.file_present
306
+ assert Config.current.name == "project"
307
+
308
+ assert Env.current.enabled
309
+
310
+ @pytest.mark.parametrize("subdir", [Path("p1"), Path("p2", "sub1")])
311
+ def test_config_above_repo_root(self, data_dir, tmpdir, git_directory, monkeypatch, subdir):
312
+ repo_root = tmpdir / "project"
313
+ self._init_repo(data_dir, tmpdir, git_directory, repo_root, tmpdir)
314
+
315
+ wd = repo_root / subdir
316
+ monkeypatch.chdir(wd)
317
+
318
+ # pylint: disable=protected-access
319
+ _appmap.initialize(cwd=wd)
320
+
321
+ # We should have stopped at the repo root without finding a config.
322
+ assert not Config.current.file_present
323
+
297
324
  # It should go on with default config
298
325
  assert Env.current.enabled
299
326
 
300
327
  def test_config_not_found_in_path_hierarchy(self, data_dir, tmpdir, monkeypatch):
301
328
  copy_tree(data_dir / "config-up", str(tmpdir))
302
- project_root = tmpdir / "subprojects" / "p1"
303
- monkeypatch.chdir(project_root)
329
+ wd = tmpdir / "project" / "p1"
330
+ monkeypatch.chdir(wd)
304
331
 
305
332
  # pylint: disable=protected-access
306
333
  _appmap.initialize(
307
- cwd=project_root,
334
+ cwd=wd,
308
335
  env={"APPMAP_CONFIG": "notfound.yml"},
309
336
  )
310
- Config.current
337
+ Config.current # pylint: disable=pointless-statement
311
338
  # No default config since we specified APPMAP_CONFIG
312
339
  assert not Env.current.enabled
@@ -13,7 +13,7 @@ def test_describe_value_does_not_call_class():
13
13
  # pylint: disable=missing-class-docstring,too-few-public-methods
14
14
  @property
15
15
  def __class__(self):
16
- raise Exception("__class__ called")
16
+ raise RuntimeError("__class__ called")
17
17
 
18
18
  describe_value(None, WithOverloadedClass())
19
19
 
@@ -32,7 +32,8 @@ from .web_framework import (
32
32
  sys.path += [str(Path(__file__).parent / "data" / "django")]
33
33
 
34
34
  # Import app just for the side-effects. It must happen after sys.path has been modified.
35
- import djangoapp # pyright: ignore pylint: disable=import-error, unused-import,wrong-import-order,wrong-import-position
35
+ # pylint: disable=import-error, unused-import,wrong-import-order,wrong-import-position
36
+ import djangoapp # pyright: ignore # noqa: F401
36
37
 
37
38
 
38
39
  class TestFormCapture(_TestFormCapture):
@@ -215,6 +216,19 @@ class TestDjangoApp:
215
216
  result.assert_outcomes(passed=1, failed=0, errors=0)
216
217
  assert not (pytester.path / "tmp").exists()
217
218
 
219
+ def test_disabled_for_process(self, pytester, monkeypatch):
220
+ monkeypatch.setenv("APPMAP_RECORD_PROCESS", "true")
221
+
222
+ result = pytester.runpytest("-svv")
223
+
224
+ # There are two tests for remote recording. They should both fail,
225
+ # because process recording should disable remote recording.
226
+ result.assert_outcomes(passed=2, failed=2, errors=0)
227
+
228
+ assert (pytester.path / "tmp" / "appmap" / "process").exists()
229
+ assert not (pytester.path / "tmp" / "appmap" / "requests").exists()
230
+ assert not (pytester.path / "tmp" / "appmap" / "pytest").exists()
231
+
218
232
 
219
233
  @pytest.fixture(name="server")
220
234
  def django_server(xprocess, server_base):
@@ -7,7 +7,7 @@ def test_disable_temporarily():
7
7
  try:
8
8
  with env.disabled("requests"):
9
9
  assert not env.enables("requests")
10
- raise 'hell'
11
- except:
10
+ raise RuntimeError("hell")
11
+ except RuntimeError:
12
12
  ...
13
13
  assert env.enables("requests")
@@ -8,10 +8,10 @@ from types import SimpleNamespace as NS
8
8
 
9
9
  import flask
10
10
  import pytest
11
- from appmap.flask import AppmapFlask
12
11
 
13
12
  from _appmap.env import Env
14
13
  from _appmap.metadata import Metadata
14
+ from appmap.flask import AppmapFlask
15
15
 
16
16
  from ..test.helpers import DictIncluding
17
17
  from .web_framework import (
@@ -144,7 +144,11 @@ class TestFlaskApp:
144
144
  appmap_file = (
145
145
  pytester.path / "tmp" / "appmap" / "pytest" / "test_request.appmap.json"
146
146
  )
147
+
148
+ # No request recordings should have been created
147
149
  assert not os.path.exists(pytester.path / "tmp" / "appmap" / "requests")
150
+
151
+ # but there should be a test recording
148
152
  assert appmap_file.exists()
149
153
 
150
154
  def test_disabled(self, pytester, monkeypatch):
@@ -154,3 +158,14 @@ class TestFlaskApp:
154
158
 
155
159
  result.assert_outcomes(passed=1, failed=0, errors=0)
156
160
  assert not (pytester.path / "tmp" / "appmap").exists()
161
+
162
+ def test_disabled_for_process(self, pytester, monkeypatch):
163
+ monkeypatch.setenv("APPMAP_RECORD_PROCESS", "true")
164
+
165
+ result = pytester.runpytest("-svv")
166
+
167
+ result.assert_outcomes(passed=1, failed=0, errors=0)
168
+
169
+ assert (pytester.path / "tmp" / "appmap" / "process").exists()
170
+ assert not (pytester.path / "tmp" / "appmap" / "requests").exists()
171
+ assert not (pytester.path / "tmp" / "appmap" / "pytest").exists()
@@ -4,13 +4,13 @@ import httpretty
4
4
  import pytest
5
5
  import requests
6
6
 
7
- import appmap.http
7
+ import appmap.http # noqa: F401
8
8
 
9
9
  from ..test.helpers import DictIncluding
10
10
 
11
11
 
12
12
  def test_http_client_capture(mock_requests, events):
13
- requests.get("https://example.test/foo/bar?q=one&q=two&q2=%F0%9F%A6%A0")
13
+ requests.get("https://example.test/foo/bar?q=one&q=two&q2=%F0%9F%A6%A0", timeout=1)
14
14
 
15
15
  assert events[0].to_dict() == DictIncluding(
16
16
  {
@@ -15,7 +15,7 @@ def test_runner_help(script_runner):
15
15
  assert result.stdout.startswith("usage")
16
16
 
17
17
 
18
- @pytest.mark.parametrize("recording_type", ["process", "pytest", "remote", "requests", "unittest"])
18
+ @pytest.mark.parametrize("recording_type", ["process", "remote", "requests", "tests"])
19
19
  def test_runner_recording_type(script_runner, recording_type):
20
20
  result = script_runner.run(["appmap-python", "--record", recording_type])
21
21
  assert result.returncode == 0
@@ -39,11 +39,18 @@ class _TestTestRunner(ABC):
39
39
  assert not testdir.output().exists()
40
40
 
41
41
  def test_disabled(self, testdir, monkeypatch):
42
- monkeypatch.setenv(f"APPMAP_RECORD_{self._test_type.upper()}", "false")
42
+ monkeypatch.setenv("APPMAP_RECORD_TESTS", "false")
43
43
 
44
44
  self.run_tests(testdir)
45
45
  assert not testdir.output().exists()
46
46
 
47
+ def test_disabled_for_process(self, testdir, monkeypatch):
48
+ monkeypatch.setenv("APPMAP_RECORD_PROCESS", "true")
49
+
50
+ self.run_tests(testdir)
51
+ assert (testdir.path / "tmp" / "appmap" / "process").exists()
52
+ assert not testdir.output().exists()
53
+
47
54
 
48
55
  class TestUnittestRunner(_TestTestRunner):
49
56
  @classmethod
@@ -2,9 +2,8 @@
2
2
  Test util functionality
3
3
  """
4
4
 
5
- import os
6
- from pathlib import Path
7
5
  import uuid
6
+ from pathlib import Path
8
7
 
9
8
  from _appmap.utils import locate_file_up, scenario_filename
10
9
 
@@ -339,6 +339,7 @@ class _TestRecordRequests:
339
339
  return requests.get(cls.server_url() + "/test", timeout=30)
340
340
 
341
341
  def record_requests(self, record_remote):
342
+ # pylint: disable=too-many-locals
342
343
  if record_remote:
343
344
  # when remote recording is enabled, this test also
344
345
  # verifies the global recorder doesn't save duplicate
@@ -3,7 +3,6 @@ import unittest
3
3
  from contextlib import contextmanager
4
4
 
5
5
  from _appmap import noappmap, testing_framework, wrapt
6
- from _appmap.env import Env
7
6
  from _appmap.utils import get_function_location
8
7
 
9
8
  _session = testing_framework.session("unittest", "tests")
@@ -43,7 +42,6 @@ if sys.version_info[1] < 8:
43
42
  with _session.record(
44
43
  test_case.__class__, method_name, location=location
45
44
  ) as metadata:
46
- Env.current.warn_enabled_by_default()
47
45
  if metadata:
48
46
  with wrapped(
49
47
  *args, **kwargs
@@ -69,7 +67,6 @@ else:
69
67
  method_name = test_case.id().split(".")[-1]
70
68
  location = _get_test_location(test_case.__class__, method_name)
71
69
  with _session.record(test_case.__class__, method_name, location=location) as metadata:
72
- Env.current.warn_enabled_by_default()
73
70
  if metadata:
74
71
  with testing_framework.collect_result_metadata(metadata):
75
72
  wrapped(*args, **kwargs)