diff --git a/_appmap/recording.py b/_appmap/recording.py index ea05b0d7..dafe9c1f 100644 --- a/_appmap/recording.py +++ b/_appmap/recording.py @@ -54,6 +54,33 @@ def __exit__(self, exc_type, exc_value, tb): return False +class NoopRecording: + """ + A noop context manager to export as "Recording" instead of class + Recording when not Env.current.enabled. + """ + + def __init__(self, exit_hook=None): + self.exit_hook = exit_hook + + def start(self): + pass + + def stop(self): + pass + + def is_running(self): + return False + + def __enter__(self): + pass + + def __exit__(self, exc_type, exc_value, tb): + if self.exit_hook is not None: + self.exit_hook(self) + return False + + def write_appmap( appmap, appmap_fname, recorder_type, metadata=None, basedir=Env.current.output_dir ): diff --git a/appmap/__init__.py b/appmap/__init__.py index a1638b17..b5750595 100644 --- a/appmap/__init__.py +++ b/appmap/__init__.py @@ -8,6 +8,7 @@ # execute the imports in a function, the modules all get put into the funtion's # globals, rather than into appmap's globals. _enabled = os.environ.get("APPMAP", None) +_recording_exported = False if _enabled is None or _enabled.upper() == "TRUE": if _enabled is not None: # Use setdefault so tests can manage _APPMAP as necessary @@ -18,6 +19,7 @@ from _appmap.labels import labels # noqa: F401 from _appmap.noappmap import decorator as noappmap # noqa: F401 from _appmap.recording import Recording # noqa: F401 + _recording_exported = True try: from . import django # noqa: F401 @@ -51,4 +53,11 @@ def enabled(): else: os.environ.pop("_APPMAP", None) else: - os.environ.setdefault("_APPMAP", "false") \ No newline at end of file + os.environ.setdefault("_APPMAP", "false") + +if not _recording_exported: + # Client code that imports appmap.Recording should run correctly + # even when not Env.current.enabled (not APPMAP=true). + # This prevents: + # ImportError: cannot import name 'Recording' from 'appmap'... + from _appmap.recording import NoopRecording as Recording # noqa: F401 diff --git a/ci/smoketest.sh b/ci/smoketest.sh index 79ad567f..ba4ed9d3 100755 --- a/ci/smoketest.sh +++ b/ci/smoketest.sh @@ -27,3 +27,22 @@ else find $PWD exit 1 fi + +# Ensure that client code using appmap.Recording does not fail when APPMAP=false +export APPMAP=false + +cat < test_client.py +from appmap import Recording + +with Recording(): + print("Hello from appmap library client") +EOF + +python test_client.py + +if [[ $? -eq 0 ]]; then + echo 'Script executed successfully with APPMAP=false' +else + echo 'Script execution failed with APPMAP=false' + exit 1 +fi \ No newline at end of file