Repository: ipython/ipython

Issue:
script magic output truncated
## Description

The output of script magic is truncated when assigning it to a variable.

## Reproduce

1. Start IPython by issuing the `ipython` command from your shell.

```bash
$ ipython
Python 3.12.2 | packaged by conda-forge | (main, Feb 16 2024, 20:50:58) [GCC 12.3.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 9.3.0 -- An enhanced Interactive Python. Type '?' for help.
Tip: Use `object?` to see the help on `object`, `object??` to view its source

In [1]: 
```

3. Write the following content (don't forget to press enter twice -two empty lines- at the end for the cell magic to be run):
```bash
In [1]: %%script bash
   ...: ls -la "/"
   ...: 
   ...: 
```

3. The output shows something similar to:

```bash
total 80
drwxr-xr-x   1 root root 4096 Jul 28 07:57 .
drwxr-xr-x   1 root root 4096 Jul 28 07:57 ..
lrwxrwxrwx   1 root root    7 May 20 02:00 bin -> usr/bin
drwxr-xr-x   2 root root 4096 May  9 16:50 boot
drwxr-xr-x   5 root root  340 Jul 30 07:07 dev
-rwxr-xr-x   1 root root    0 Jul 28 07:57 .dockerenv
drwxr-xr-x   1 root root 4096 Jul 30 07:07 etc
drwxr-xr-x   1 root root 4096 May 30 12:57 home
lrwxrwxrwx   1 root root    7 May 20 02:00 lib -> usr/lib
lrwxrwxrwx   1 root root    9 May 20 02:00 lib64 -> usr/lib64
drwxr-xr-x   2 root root 4096 May 20 02:00 media
drwxr-xr-x   2 root root 4096 May 20 02:00 mnt
drwxr-xr-x   2 root root 4096 May 20 02:00 opt
dr-xr-xr-x 528 root root    0 Jul 30 07:07 proc
drwx------   1 root root 4096 Jun  4 13:13 root
drwxr-xr-x   1 root root 4096 Jul 30 07:07 run
lrwxrwxrwx   1 root root    8 May 20 02:00 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 May 20 02:00 srv
dr-xr-xr-x  13 root root    0 Jul 30 07:07 sys
drwxrwxrwt   1 root root 4096 Jul 30 07:13 tmp
drwxr-xr-x   1 root root 4096 May 20 02:00 usr
drwxr-xr-x   1 root root 4096 Jul 28 07:57 var
drwxr-xr-x   4 root root 4096 May 10  2023 vscode
drwxr-xr-x   3 root root 4096 Jul 28 07:57 workspaces

In [2]:
```

4. Write the following content and press enter:

```bash
In [2]: output = ""

In [3]:
```

5. Write the following content (don't forget to press enter twice -two empty lines- at the end for the cell magic to be run):

```bash
In [3]: %%script bash --out output
   ...: ls -la "/"
   ...: 
   ...: 

In [4]:
```

6. Write following content and press enter:

```bash
In [4]: print(output)
```

7. The output shows something similar to:

```bash
spaces


In [5]:
```

## Expected behavior

The full output of the `ls -la "/"` command is saved in the `output` variable and printed.

## Context

- Operating System and version: Ubuntu 22.04.5 LTS
- Python version: 3.12.2
- IPython version: 9.3.0



Discussion:
As a side note, running `ls -la "/"` as a shell command (vs. cell magic) it works as expected:

```bash
In [5]: output = !ls -la "/"

In [6]: print(output)
['total 80', 'drwxr-xr-x   1 root root 4096 Jul 28 07:57 .', 'drwxr-xr-x   1 root root 4096 Jul 28 07:57 ..', 'lrwxrwxrwx   1 root root    7 May 20 02:00 bin -> usr/bin', 'drwxr-xr-x   2 root root 4096 May  9 16:50 boot', 'drwxr-xr-x   5 root root  340 Jul 30 07:07 dev', '-rwxr-xr-x   1 root root    0 Jul 28 07:57 .dockerenv', 'drwxr-xr-x   1 root root 4096 Jul 30 07:07 etc', 'drwxr-xr-x   1 root root 4096 May 30 12:57 home', 'lrwxrwxrwx   1 root root    7 May 20 02:00 lib -> usr/lib', 'lrwxrwxrwx   1 root root    9 May 20 02:00 lib64 -> usr/lib64', 'drwxr-xr-x   2 root root 4096 May 20 02:00 media', 'drwxr-xr-x   2 root root 4096 May 20 02:00 mnt', 'drwxr-xr-x   2 root root 4096 May 20 02:00 opt', 'dr-xr-xr-x 528 root root    0 Jul 30 07:07 proc', 'drwx------   1 root root 4096 Jun  4 13:13 root', 'drwxr-xr-x   1 root root 4096 Jul 30 07:07 run', 'lrwxrwxrwx   1 root root    8 May 20 02:00 sbin -> usr/sbin', 'drwxr-xr-x   2 root root 4096 May 20 02:00 srv', 'dr-xr-xr-x  13 root root    0 Jul 30 07:07 sys', 'drwxrwxrwt   1 root root 4096 Jul 30 07:13 tmp', 'drwxr-xr-x   1 root root 4096 May 20 02:00 usr', 'drwxr-xr-x   1 root root 4096 Jul 28 07:57 var', 'drwxr-xr-x   4 root root 4096 May 10  2023 vscode', 'drwxr-xr-x   3 root root 4096 Jul 28 07:57 workspaces']

In [7]: 
```
Just upgraded to IPYthon 9.4.0 with same results:

```bash
$ ipython
Python 3.12.2 | packaged by conda-forge | (main, Feb 16 2024, 20:50:58) [GCC 12.3.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 9.4.0 -- An enhanced Interactive Python. Type '?' for help.
Tip: Use `ipython --help-all | less` to view all the IPython configuration options.

In [1]: %%script bash
   ...: ls -la "/"
   ...: 
   ...: 
total 80
drwxr-xr-x   1 root root 4096 Jul 30 08:01 .
drwxr-xr-x   1 root root 4096 Jul 30 08:01 ..
lrwxrwxrwx   1 root root    7 May 20 02:00 bin -> usr/bin
drwxr-xr-x   2 root root 4096 May  9 16:50 boot
drwxr-xr-x   5 root root  340 Jul 30 08:01 dev
-rwxr-xr-x   1 root root    0 Jul 30 08:01 .dockerenv
drwxr-xr-x   1 root root 4096 Jul 30 08:01 etc
drwxr-xr-x   1 root root 4096 May 30 12:57 home
lrwxrwxrwx   1 root root    7 May 20 02:00 lib -> usr/lib
lrwxrwxrwx   1 root root    9 May 20 02:00 lib64 -> usr/lib64
drwxr-xr-x   2 root root 4096 May 20 02:00 media
drwxr-xr-x   2 root root 4096 May 20 02:00 mnt
drwxr-xr-x   2 root root 4096 May 20 02:00 opt
dr-xr-xr-x 553 root root    0 Jul 30 08:01 proc
drwx------   1 root root 4096 Jun  4 13:13 root
drwxr-xr-x   1 root root 4096 Jun  4 13:14 run
lrwxrwxrwx   1 root root    8 May 20 02:00 sbin -> usr/sbin
drwxr-xr-x   2 root root 4096 May 20 02:00 srv
dr-xr-xr-x  13 root root    0 Jul 30 08:01 sys
drwxrwxrwt   1 root root 4096 Jul 30 08:01 tmp
drwxr-xr-x   1 root root 4096 May 20 02:00 usr
drwxr-xr-x   1 root root 4096 Jul 30 08:01 var
drwxr-xr-x   4 root root 4096 May 10  2023 vscode
drwxr-xr-x   3 root root 4096 Jul 30 08:01 workspaces

In [2]: output = ""

In [3]: %%script bash --out output
   ...: ls -la "/"
   ...: 
   ...: 

In [4]: print(output)
spaces


In [5]: 
````



Patch:
diff --git a/IPython/core/magics/script.py b/IPython/core/magics/script.py
index e6aa8f43a44..1f7e6b3cb68 100644
--- a/IPython/core/magics/script.py
+++ b/IPython/core/magics/script.py
@@ -237,7 +237,7 @@ async def _handle_stream(stream, stream_arg, file_object):
                     chunk = decoder.decode("", final=True)
                     should_break = True
                 if stream_arg:
-                    self.shell.user_ns[stream_arg] = chunk
+                    self.shell.user_ns[stream_arg] += chunk
                 else:
                     file_object.write(chunk)
                     file_object.flush()
@@ -259,6 +259,11 @@ async def _stream_communicate(process, cell):
         argv = arg_split(line, posix=not sys.platform.startswith("win"))
         args, cmd = self.shebang.parser.parse_known_args(argv)
 
+        if args.out:
+            self.shell.user_ns[args.out] = ""
+        if args.err:
+            self.shell.user_ns[args.err] = ""
+
         try:
             p = in_thread(
                 asyncio.create_subprocess_exec(


Test patch:
diff --git a/tests/test_magic.py b/tests/test_magic.py
index 09c112f8068..cc772e10e73 100644
--- a/tests/test_magic.py
+++ b/tests/test_magic.py
@@ -1344,6 +1344,13 @@ def test_script_out():
     assert ip.user_ns["output"].strip() == "hi"
 
 
+def test_script_out_multiple_lines():
+    ip = get_ipython()
+    code = "print('hi')\nprint('this')\nprint('is')\nprint('ipython')"
+    ip.run_cell_magic("script", f"--out output {sys.executable}", code)
+    assert ip.user_ns["output"].strip().splitlines() == ["hi", "this", "is", "ipython"]
+
+
 def test_script_err():
     ip = get_ipython()
     ip.run_cell_magic(