Repository: iterative/datachain

Issue:
show() method does not honor the preceding limit()
### Description

somehow the combination of limit() and show() stopped to work.

Consider this output

```

>>> images = DataChain.from_storage("gs://datachain-demo/coco2017/images/val/")
>>> images.limit(1).to_pandas()
Listing gs://datachain-demo: 5000 objects [00:01, 3773.46 objects/s]
Processed: 5000 rows [00:00, 22386.69 rows/s]
                  file                                                                                                                                             
                source               parent              name    size           version              etag is_latest                    last_modified location vtype
0  gs://datachain-demo  coco2017/images/val  000000000139.jpg  161811  1719096046021595  CNvXoemj8IYDEAE=         1 2024-06-22 22:40:46.070000+00:00     None      
>>> images.limit(1).show()
Processed: 5000 rows [00:00, 24980.79 rows/s]
                   file                 file              file    file              file              file      file                             file     file  file
                 source               parent              name    size           version              etag is_latest                    last_modified location vtype
0   gs://datachain-demo  coco2017/images/val  000000000139.jpg  161811  1719096046021595  CNvXoemj8IYDEAE=         1 2024-06-22 22:40:46.070000+00:00     None      
1   gs://datachain-demo  coco2017/images/val  000000000285.jpg  335861  1719095431616920  CJizpcSh8IYDEAE=         1 2024-06-22 22:30:31.666000+00:00     None      
2   gs://datachain-demo  coco2017/images/val  000000000632.jpg  155667  1719093730283762  CPKhhJmb8IYDEAE=         1 2024-06-22 22:02:10.325000+00:00     None      
3   gs://datachain-demo  coco2017/images/val  000000000724.jpg  130107  1719096205012425  CMnbibWk8IYDEAE=         1 2024-06-22 22:43:25.053000+00:00     None      
4   gs://datachain-demo  coco2017/images/val  000000000776.jpg  176410  1719094642208901  CIXh78ue8IYDEAE=         1 2024-06-22 22:17:22.250000+00:00     None      
5   gs://datachain-demo  coco2017/images/val  000000000785.jpg  133674  1719095650133526  CJbMvqyi8IYDEAE=         1 2024-06-22 22:34:10.178000+00:00     None      
6   gs://datachain-demo  coco2017/images/val  000000000802.jpg   62406  1719095069772315  CJuU4Jeg8IYDEAE=         1 2024-06-22 22:24:29.820000+00:00     None      
7   gs://datachain-demo  coco2017/images/val  000000000872.jpg  317669  1719096064784113  CPHtmvKj8IYDEAE=         1 2024-06-22 22:41:04.832000+00:00     None      
8   gs://datachain-demo  coco2017/images/val  000000000885.jpg  111441  1719095348191762  CJLEwZyh8IYDEAE=         1 2024-06-22 22:29:08.240000+00:00     None      
9   gs://datachain-demo  coco2017/images/val  000000001000.jpg  321136  1719095125901441  CIGBwrKg8IYDEAE=         1 2024-06-22 22:25:25.950000+00:00     None      
10  gs://datachain-demo  coco2017/images/val  000000001268.jpg  180751  1719094597329677  CI3GvLae8IYDEAE=         1 2024-06-22 22:16:37.371000+00:00     None      
11  gs://datachain-demo  coco2017/images/val  000000001296.jpg  204829  1719095276503932  CPyGqvqg8IYDEAE=         1 2024-06-22 22:27:56.545000+00:00     None      
12  gs://datachain-demo  coco2017/images/val  000000001353.jpg   83033  1719095960027901  CP2FocCj8IYDEAE=         1 2024-06-22 22:39:20.079000+00:00     None      
13  gs://datachain-demo  coco2017/images/val  000000001425.jpg  111309  1719096008477829  CIWZrtej8IYDEAE=         1 2024-06-22 22:40:08.525000+00:00     None      
14  gs://datachain-demo  coco2017/images/val  000000001490.jpg  101098  1719094496818123  CMvnxYae8IYDEAE=         1 2024-06-22 22:14:56.859000+00:00     None      
15  gs://datachain-demo  coco2017/images/val  000000001503.jpg   15259  1719095089976497  CLGpsaGg8IYDEAE=         1 2024-06-22 22:24:50.018000+00:00     None      
16  gs://datachain-demo  coco2017/images/val  000000001532.jpg  174022  1719094589381217  COG017Ke8IYDEAE=         1 2024-06-22 22:16:29.430000+00:00     None      
17  gs://datachain-demo  coco2017/images/val  000000001584.jpg  138202  1719094759822594  CIKq+oOf8IYDEAE=         1 2024-06-22 22:19:19.871000+00:00     None      
18  gs://datachain-demo  coco2017/images/val  000000001675.jpg   97643  1719093907856789  CJW72u2b8IYDEAE=         1 2024-06-22 22:05:07.897000+00:00     None      
19  gs://datachain-demo  coco2017/images/val  000000001761.jpg  115835  1719096071989341  CN3Q0vWj8IYDEAE=         1 2024-06-22 22:41:12.030000+00:00     None      

[Limited by 20 rows]


```

### Version Info

```Text
0.2.12.dev52+gef29481

Python 3.11.9
```


Discussion:
cloudflare-pages[bot]: ## Deploying datachain-documentation with &nbsp;<a href="https://pages.dev"><img alt="Cloudflare Pages" src="https://user-images.githubusercontent.com/23264/106598434-9e719e00-654f-11eb-9e59-6167043cfa01.png" width="16"></a> &nbsp;Cloudflare Pages

<table><tr><td><strong>Latest commit:</strong> </td><td>
<code>50c3df1</code>
</td></tr>
<tr><td><strong>Status:</strong></td><td>&nbsp;✅&nbsp; Deploy successful!</td></tr>
<tr><td><strong>Preview URL:</strong></td><td>
<a href='https://317252db.datachain-documentation.pages.dev'>https://317252db.datachain-documentation.pages.dev</a>
</td></tr>
<tr><td><strong>Branch Preview URL:</strong></td><td>
<a href='https://show-respect-limit.datachain-documentation.pages.dev'>https://show-respect-limit.datachain-documentation.pages.dev</a>
</td></tr>
</table>

[View logs](https://dash.cloudflare.com/?to=/:account/pages/view/datachain-documentation/317252db-b439-4fc5-99c9-4c8876942871)


Patch:
diff --git a/src/datachain/lib/dc.py b/src/datachain/lib/dc.py
index 8b89eb2..c827e46 100644
--- a/src/datachain/lib/dc.py
+++ b/src/datachain/lib/dc.py
@@ -193,6 +193,8 @@ class DataChain(DatasetQuery):
         ```
     """
 
+    max_row_count: Optional[int] = None
+
     DEFAULT_FILE_RECORD: ClassVar[dict] = {
         "source": "",
         "name": "",
@@ -1600,7 +1602,18 @@ class DataChain(DatasetQuery):
     @detach
     def limit(self, n: int) -> "Self":
         """Return the first n rows of the chain."""
-        return super().limit(n)
+        n = max(n, 0)
+
+        if self.max_row_count is None:
+            self.max_row_count = n
+            return super().limit(n)
+
+        limit = min(n, self.max_row_count)
+        if limit == self.max_row_count:
+            return self
+
+        self.max_row_count = limit
+        return super().limit(self.max_row_count)
 
     @detach
     def offset(self, offset: int) -> "Self":


Test patch:
diff --git a/tests/func/test_datachain.py b/tests/func/test_datachain.py
index 2ee0a0e..896df23 100644
--- a/tests/func/test_datachain.py
+++ b/tests/func/test_datachain.py
@@ -174,6 +174,22 @@ def test_show(capsys, catalog):
         assert f"{i} {first_name[i]}" in normalized_output
 
 
+def test_show_limit(capsys, catalog):
+    first_name = ["Alice", "Bob", "Charlie"]
+    DataChain.from_values(
+        first_name=first_name,
+        age=[40, 30, None],
+        city=[
+            "Houston",
+            "Los Angeles",
+            None,
+        ],
+    ).limit(1).show()
+    captured = capsys.readouterr()
+    new_line_count = captured.out.count("\n")
+    assert new_line_count == 2
+
+
 def test_show_transpose(capsys, catalog):
     first_name = ["Alice", "Bob", "Charlie"]
     last_name = ["A", "B", "C"]