From c0b34141477972dfd4681494d9ff99ed68395245 Mon Sep 17 00:00:00 2001 From: Frank Dressler Date: Mon, 5 Oct 2026 08:42:25 +0100 Subject: [PATCH] autorun: clear builtins._ so a False result does not fail later tests Tests that followed one ending in False were reported as failed. UTScapy uses the last expression value as the result, and a successful assert does not replace it. autorun_commands did not delete builtins._ at the start of a test, so the previous False stayed in place. The following uts file demonstrates the problem: % False result carries over + Carry over = one False = two assert True `two` raises nothing and does not set a new value, but it was reported as failed. The purpose of the scapy_session code was unclear. The history showed that it belonged to session save/load, removed in 13621d11 ("Sessions removed"), and that this code had been left behind. Searching the rest of the tree for those leftovers by hand looked like more work than it was worth, and a good fit for AI, so I asked it to find and remove them as well. Fixes #5220 AI-Assisted: yes (Grok 4.7) Co-authored-by: Cursor --- doc/scapy/introduction.rst | 14 ++------------ scapy/autorun.py | 7 ++----- scapy/config.py | 1 - scapy/main.py | 23 +---------------------- test/regression.uts | 12 ++++++++++++ 5 files changed, 17 insertions(+), 40 deletions(-) diff --git a/doc/scapy/introduction.rst b/doc/scapy/introduction.rst index ab8b97cf1f6..b308755c1e8 100644 --- a/doc/scapy/introduction.rst +++ b/doc/scapy/introduction.rst @@ -62,10 +62,9 @@ Interpreting results can help users that don't know what a port scan is, but it Quick demo ========== -First, we play a bit and create four IP packets at once. Let's see how it works. We first instantiate the IP class. Then, we instantiate it again and we provide a destination that is worth four IP addresses (/30 gives the netmask). Using a Python idiom, we develop this implicit packet in a set of explicit packets. Then, we quit the interpreter. As we provided a session file, the variables we were working on are saved, then reloaded:: +First, we play a bit and create four IP packets at once. Let's see how it works. We first instantiate the IP class. Then, we instantiate it again and we provide a destination that is worth four IP addresses (/30 gives the netmask). Using a Python idiom, we develop this implicit packet in a set of explicit packets:: - # ./run_scapy -s mysession - New session [mysession] + # ./run_scapy Welcome to Scapy (2.4.0) >>> IP() @@ -76,15 +75,6 @@ First, we play a bit and create four IP packets at once. Let's see how it works. >>> [p for p in ip] [, , , ] - >>> ^D - -:: - - # ./run_scapy -s mysession - Using session [mysession] - Welcome to Scapy (2.4.0) - >>> ip - |> Now, let's manipulate some packets:: diff --git a/scapy/autorun.py b/scapy/autorun.py index a677f1e1c79..d3560f6ac8e 100644 --- a/scapy/autorun.py +++ b/scapy/autorun.py @@ -66,7 +66,7 @@ def autorun_commands(_cmds, my_globals=None, verb=None): my_globals = _scapy_builtins() interp = ScapyAutorunInterpreter(locals=my_globals) try: - del builtins.__dict__["scapy_session"]["_"] + del builtins.__dict__["_"] except KeyError: pass if verb is not None: @@ -113,10 +113,7 @@ def autorun_commands(_cmds, my_globals=None, verb=None): pass finally: conf.verb = sv - try: - return builtins.__dict__["scapy_session"]["_"] - except KeyError: - return builtins.__dict__.get("_", None) + return builtins.__dict__.get("_", None) def autorun_commands_timeout(cmds, timeout=None, **kwargs): diff --git a/scapy/config.py b/scapy/config.py index bb1437d8a19..8219fb89425 100755 --- a/scapy/config.py +++ b/scapy/config.py @@ -963,7 +963,6 @@ class Conf(ConfClass): This object contains the configuration of Scapy. """ version: str = ReadOnlyAttribute("version", VERSION) - session: str = "" #: filename where the session will be saved interactive = False #: can be "ipython", "bpython", "ptpython", "ptipython", "python" or "auto". #: Default: Auto diff --git a/scapy/main.py b/scapy/main.py index e56562eea03..ee42b7f4cc7 100644 --- a/scapy/main.py +++ b/scapy/main.py @@ -445,23 +445,6 @@ def list_contrib(name=None, # type: Optional[str] return None -############################## -# Session saving/restoring # -############################## - -def update_ipython_session(session): - # type: (Dict[str, Any]) -> None - """Updates IPython session with a custom one""" - if "_oh" not in session: - session["_oh"] = session["Out"] = {} - session["In"] = {} - try: - from IPython import get_ipython - get_ipython().user_ns.update(session) - except Exception: - pass - - def _scapy_prestart_builtins(): # type: () -> Dict[str, Any] """Load Scapy prestart and return all builtins""" @@ -527,14 +510,10 @@ def init_session(mydict=None, # type: Optional[Union[Dict[str, Any], None]] scapy_builtins.update(_scapy_exts()) SESSION = {"conf": conf} # type: Dict[str, Any] - SESSION.update(scapy_builtins) - SESSION["_scpybuiltins"] = scapy_builtins.keys() - builtins.__dict__["scapy_session"] = SESSION if mydict is not None: - builtins.__dict__["scapy_session"].update(mydict) - update_ipython_session(mydict) + SESSION.update(mydict) if ret: return SESSION return None diff --git a/test/regression.uts b/test/regression.uts index 1807df69758..cfb63a89a84 100644 --- a/test/regression.uts +++ b/test/regression.uts @@ -1161,6 +1161,18 @@ assert ret == ("\\textcolor{blue}{{\\tt\\char62}{\\tt\\char62}{\\tt\\char62} }IP ret = autorun_get_text_interactive_session("scapy_undefined") assert "NameError" in ret[0] += Test autorun does not reuse a previous False result +~ autorun + +# The last non-None expression is the test result. A following test that only +# asserts produces no new value; it must not inherit the previous False. + +out, res = autorun_get_text_interactive_session("False\n") +assert res is False + +out, res = autorun_get_text_interactive_session("assert 1 == 1\n") +assert res is None + = Test autorun with logging cmds = """log_runtime.info(hex_bytes("446166742050756e6b"))\n"""