@@ -194,64 +194,100 @@ async def test_async_execute_returns_result(self):
194194 assert result .value == 4
195195
196196
197- @pytest .mark .django_db
198197class TestResultOutput :
199- def test_format_large_queryset_truncates_at_10 (self , shell ):
200- for i in range (15 ):
201- AModel .objects .create (name = f"Item { i } " , value = i )
198+ def test_expression_with_value_no_stdout (self , shell ):
199+ result = shell ._execute ("42" )
200+ assert isinstance (result , ExpressionResult )
201+ assert result .output == "42"
202202
203- shell ._execute ("from tests.models import AModel" )
203+ def test_expression_with_none_no_stdout (self , shell ):
204+ result = shell ._execute ("None" )
205+ assert isinstance (result , ExpressionResult )
206+ assert result .output == ""
204207
205- result = shell ._execute ("AModel.objects.all()" )
208+ def test_expression_with_stdout_and_value (self , shell ):
209+ code = """\
210+ print('hello')
211+ 42
212+ """
213+ result = shell ._execute (code .strip ())
214+ assert isinstance (result , ExpressionResult )
215+ assert result .output == "hello" # No "42" shown
206216
217+ def test_expression_with_stdout_and_none (self , shell ):
218+ result = shell ._execute ("print('hello')" )
207219 assert isinstance (result , ExpressionResult )
208- assert "... and 5 more items" in result .output
209- assert "Item 0" in result .output
210- # Should show first 10, not the last 5
211- assert "Item 9" in result .output
212- assert "Item 14" not in result .output
220+ assert result .output == "hello" # No "None" shown
221+
222+ def test_multiline_ending_with_print (self , shell ):
223+ code = """\
224+ x = 5
225+ y = 10
226+ print(f"Sum: {x + y}")
227+ """
228+ result = shell ._execute (code .strip ())
229+ assert isinstance (result , ExpressionResult )
230+ assert result .output == "Sum: 15" # No "None" appended
231+
232+ def test_function_returning_none (self , shell ):
233+ code = """\
234+ def foo():
235+ x = 2
236+ foo()
237+ """
238+ result = shell ._execute (code .strip ())
239+ assert isinstance (result , ExpressionResult )
240+ assert result .output == ""
213241
214- def test_format_small_queryset_shows_all (self , shell ):
215- for i in range (5 ):
242+ @pytest .mark .django_db
243+ def test_queryset_shows_standard_repr (self , shell ):
244+ for i in range (3 ):
216245 AModel .objects .create (name = f"Item { i } " , value = i )
217246
218247 shell ._execute ("from tests.models import AModel" )
219-
220248 result = shell ._execute ("AModel.objects.all()" )
221249
222250 assert isinstance (result , ExpressionResult )
223- # Should show all items, no truncation message for <10 items
251+ assert result . output . startswith ( "<QuerySet [<AModel:" )
224252 assert "Item 0" in result .output
225- assert "Item 4" in result .output
226- assert "... and" not in result .output
227-
228- def test_format_empty_queryset_shows_message (self , shell ):
229- shell ._execute ("from tests.models import AModel" )
253+ assert "Item 2" in result .output
230254
231- result = shell ._execute ("AModel.objects.none()" )
255+ def test_statement_with_stdout (self , shell ):
256+ result = shell ._execute ("x = 5; print(x)" )
257+ assert isinstance (result , StatementResult )
258+ assert result .output == "5\n " # print adds a newline
232259
233- assert isinstance (result , ExpressionResult )
234- assert "Empty queryset/list" in result .output
260+ def test_statement_no_stdout (self , shell ):
261+ result = shell ._execute ("x = 5" )
262+ assert isinstance (result , StatementResult )
263+ assert result .output == "OK"
235264
236- def test_format_empty_list_shows_message (self , shell ):
237- """Integration test for empty list formatting."""
238- result = shell ._execute ("[]" )
265+ def test_error_with_stdout (self , shell ):
266+ code = """\
267+ print("Starting...")
268+ print("Processing...")
269+ 1 / 0
270+ """
271+ result = shell ._execute (code .strip ())
272+ assert isinstance (result , ErrorResult )
273+ assert "Starting..." in result .output
274+ assert "Processing..." in result .output
275+ assert "ZeroDivisionError" in result .output
276+ # Stdout should come before the error
277+ assert result .output .index ("Starting..." ) < result .output .index (
278+ "ZeroDivisionError"
279+ )
239280
240- assert isinstance (result , ExpressionResult )
241- assert "Empty queryset/list" in result .output
242-
243- def test_format_bad_iterable_uses_repr (self , shell ):
244- result = shell ._execute ("""\
245- class BadIterable:
246- def __iter__(self):
247- raise RuntimeError("Can't iterate")
248- def __repr__(self):
249- return "BadIterable()"
250- BadIterable()
251- """ )
281+ def test_error_no_stdout (self , shell ):
282+ result = shell ._execute ("1 / 0" )
283+ assert isinstance (result , ErrorResult )
284+ assert "ZeroDivisionError" in result .output
285+ assert "Traceback:" in result .output
252286
253- assert isinstance (result , ExpressionResult )
254- assert "BadIterable()" in result .output
287+ def test_error_filters_framework_lines (self , shell ):
288+ result = shell ._execute ("1 / 0" )
289+ assert isinstance (result , ErrorResult )
290+ assert "mcp_django_shell" not in result .output
255291
256292
257293class TestShellState :
0 commit comments