mito-ai 0.1.46__py3-none-any.whl → 0.1.49__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. mito_ai/_version.py +1 -1
  2. mito_ai/app_deploy/app_deploy_utils.py +28 -9
  3. mito_ai/app_deploy/handlers.py +123 -84
  4. mito_ai/app_deploy/models.py +19 -12
  5. mito_ai/completions/models.py +6 -1
  6. mito_ai/completions/prompt_builders/agent_execution_prompt.py +13 -1
  7. mito_ai/completions/prompt_builders/agent_system_message.py +63 -4
  8. mito_ai/completions/prompt_builders/chat_system_message.py +4 -0
  9. mito_ai/completions/prompt_builders/prompt_constants.py +1 -0
  10. mito_ai/completions/prompt_builders/utils.py +13 -0
  11. mito_ai/path_utils.py +70 -0
  12. mito_ai/streamlit_conversion/agent_utils.py +4 -201
  13. mito_ai/streamlit_conversion/prompts/prompt_constants.py +142 -152
  14. mito_ai/streamlit_conversion/prompts/streamlit_error_correction_prompt.py +3 -3
  15. mito_ai/streamlit_conversion/prompts/streamlit_finish_todo_prompt.py +2 -2
  16. mito_ai/streamlit_conversion/prompts/update_existing_app_prompt.py +2 -2
  17. mito_ai/streamlit_conversion/search_replace_utils.py +94 -0
  18. mito_ai/streamlit_conversion/streamlit_agent_handler.py +35 -46
  19. mito_ai/streamlit_conversion/streamlit_utils.py +13 -75
  20. mito_ai/streamlit_conversion/validate_streamlit_app.py +6 -21
  21. mito_ai/streamlit_preview/__init__.py +1 -2
  22. mito_ai/streamlit_preview/handlers.py +54 -85
  23. mito_ai/streamlit_preview/manager.py +11 -18
  24. mito_ai/streamlit_preview/utils.py +12 -28
  25. mito_ai/tests/deploy_app/test_app_deploy_utils.py +22 -4
  26. mito_ai/tests/message_history/test_message_history_utils.py +3 -0
  27. mito_ai/tests/streamlit_conversion/test_apply_search_replace.py +240 -0
  28. mito_ai/tests/streamlit_conversion/test_streamlit_agent_handler.py +40 -60
  29. mito_ai/tests/streamlit_conversion/test_streamlit_utils.py +26 -29
  30. mito_ai/tests/streamlit_conversion/test_validate_streamlit_app.py +25 -20
  31. mito_ai/tests/streamlit_preview/test_streamlit_preview_handler.py +87 -57
  32. mito_ai/tests/streamlit_preview/test_streamlit_preview_manager.py +27 -40
  33. mito_ai/user/handlers.py +15 -3
  34. mito_ai/utils/create.py +17 -1
  35. mito_ai/utils/error_classes.py +42 -0
  36. mito_ai/utils/message_history_utils.py +3 -1
  37. mito_ai/utils/telemetry_utils.py +78 -13
  38. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/build_log.json +100 -100
  39. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/package.json +2 -2
  40. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/package.json.orig +1 -1
  41. mito_ai-0.1.46.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.20f12766ecd3d430568e.js → mito_ai-0.1.49.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.8f1845da6bf2b128c049.js +3571 -1442
  42. mito_ai-0.1.49.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.8f1845da6bf2b128c049.js.map +1 -0
  43. mito_ai-0.1.46.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.54126ab6511271265443.js → mito_ai-0.1.49.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.8b24b5b3b93f95205b56.js +24 -24
  44. mito_ai-0.1.46.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.54126ab6511271265443.js.map → mito_ai-0.1.49.data/data/share/jupyter/labextensions/mito_ai/static/remoteEntry.8b24b5b3b93f95205b56.js.map +1 -1
  45. {mito_ai-0.1.46.dist-info → mito_ai-0.1.49.dist-info}/METADATA +1 -1
  46. {mito_ai-0.1.46.dist-info → mito_ai-0.1.49.dist-info}/RECORD +71 -69
  47. mito_ai/tests/streamlit_conversion/test_apply_patch_to_text.py +0 -368
  48. mito_ai/tests/streamlit_conversion/test_fix_diff_headers.py +0 -533
  49. mito_ai-0.1.46.data/data/share/jupyter/labextensions/mito_ai/static/lib_index_js.20f12766ecd3d430568e.js.map +0 -1
  50. /mito_ai/streamlit_conversion/{streamlit_system_prompt.py → prompts/streamlit_system_prompt.py} +0 -0
  51. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/etc/jupyter/jupyter_server_config.d/mito_ai.json +0 -0
  52. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/schemas/mito_ai/toolbar-buttons.json +0 -0
  53. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js +0 -0
  54. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/node_modules_process_browser_js.4b128e94d31a81ebd209.js.map +0 -0
  55. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/style.js +0 -0
  56. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js +0 -0
  57. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/style_index_js.5876024bb17dbd6a3ee6.js.map +0 -0
  58. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_apis_signOut_mjs-node_module-75790d.688c25857e7b81b1740f.js +0 -0
  59. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_apis_signOut_mjs-node_module-75790d.688c25857e7b81b1740f.js.map +0 -0
  60. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_tokenProvider_tokenProvider_-72f1c8.a917210f057fcfe224ad.js +0 -0
  61. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_auth_dist_esm_providers_cognito_tokenProvider_tokenProvider_-72f1c8.a917210f057fcfe224ad.js.map +0 -0
  62. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js +0 -0
  63. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_dist_esm_index_mjs.6bac1a8c4cc93f15f6b7.js.map +0 -0
  64. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js +0 -0
  65. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_aws-amplify_ui-react_dist_esm_index_mjs.4fcecd65bef9e9847609.js.map +0 -0
  66. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_react-dom_client_js-node_modules_aws-amplify_ui-react_dist_styles_css.b43d4249e4d3dac9ad7b.js +0 -0
  67. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_react-dom_client_js-node_modules_aws-amplify_ui-react_dist_styles_css.b43d4249e4d3dac9ad7b.js.map +0 -0
  68. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js +0 -0
  69. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_semver_index_js.3f6754ac5116d47de76b.js.map +0 -0
  70. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js +0 -0
  71. {mito_ai-0.1.46.data → mito_ai-0.1.49.data}/data/share/jupyter/labextensions/mito_ai/static/vendors-node_modules_vscode-diff_dist_index_js.ea55f1f9346638aafbcf.js.map +0 -0
  72. {mito_ai-0.1.46.dist-info → mito_ai-0.1.49.dist-info}/WHEEL +0 -0
  73. {mito_ai-0.1.46.dist-info → mito_ai-0.1.49.dist-info}/entry_points.txt +0 -0
  74. {mito_ai-0.1.46.dist-info → mito_ai-0.1.49.dist-info}/licenses/LICENSE +0 -0
@@ -1,533 +0,0 @@
1
- # Copyright (c) Saga Inc.
2
- # Distributed under the terms of the GNU Affero General Public License v3.0 License.
3
-
4
- import pytest
5
- from mito_ai.streamlit_conversion.agent_utils import fix_diff_headers
6
-
7
-
8
- @pytest.mark.parametrize("input_diff,expected_output", [
9
- # Test case 1: Simple replacement with correct counts
10
- (
11
- """--- a/app.py
12
- +++ b/app.py
13
- @@ -11,1 +11,1 @@
14
- -st.title("Simple Calculation")
15
- +st.title("Math Examples")""",
16
- """--- a/app.py
17
- +++ b/app.py
18
- @@ -11,1 +11,1 @@
19
- -st.title("Simple Calculation")
20
- +st.title("Math Examples")"""
21
- ),
22
-
23
- # Test case 2: Simple replacement with incorrect counts (AI's typical mistake)
24
- (
25
- """--- a/app.py
26
- +++ b/app.py
27
- @@ -11,6 +11,6 @@
28
- -st.title("Simple Calculation")
29
- +st.title("Math Examples")""",
30
- """--- a/app.py
31
- +++ b/app.py
32
- @@ -11,1 +11,1 @@
33
- -st.title("Simple Calculation")
34
- +st.title("Math Examples")"""
35
- ),
36
- # Test case 3: Simple replacement with incorrect double digit counts (AI's typical mistake)
37
- (
38
- """--- a/app.py
39
- +++ b/app.py
40
- @@ -11,12 +11,16 @@
41
- -st.title("Simple Calculation")
42
- +st.title("Math Examples")""",
43
- """--- a/app.py
44
- +++ b/app.py
45
- @@ -11,1 +11,1 @@
46
- -st.title("Simple Calculation")
47
- +st.title("Math Examples")"""
48
- ),
49
-
50
- # Test case 4: Multiple context lines with replacement
51
- (
52
- """--- a/app.py
53
- +++ b/app.py
54
- @@ -10,3 +10,3 @@
55
- \"\"\", unsafe_allow_html=True)
56
-
57
- -st.title("Simple Calculation")
58
- +st.title("Math Examples")
59
-
60
- x = 5""",
61
- """--- a/app.py
62
- +++ b/app.py
63
- @@ -10,5 +10,5 @@
64
- \"\"\", unsafe_allow_html=True)
65
-
66
- -st.title("Simple Calculation")
67
- +st.title("Math Examples")
68
-
69
- x = 5"""
70
- ),
71
-
72
- # Test case 5: Add lines (only + lines)
73
- (
74
- """--- a/app.py
75
- +++ b/app.py
76
- @@ -5,1 +5,3 @@
77
- st.title("My App")
78
- +st.header("Welcome")
79
- +st.write("New content")""",
80
- """--- a/app.py
81
- +++ b/app.py
82
- @@ -5,1 +5,3 @@
83
- st.title("My App")
84
- +st.header("Welcome")
85
- +st.write("New content")"""
86
- ),
87
-
88
- # Test case 6: Remove lines (only - lines)
89
- (
90
- """--- a/app.py
91
- +++ b/app.py
92
- @@ -5,3 +5,1 @@
93
- st.title("My App")
94
- -st.header("Welcome")
95
- -st.write("Old content")""",
96
- """--- a/app.py
97
- +++ b/app.py
98
- @@ -5,3 +5,1 @@
99
- st.title("My App")
100
- -st.header("Welcome")
101
- -st.write("Old content")"""
102
- ),
103
-
104
- # Test case 7: Multiple hunks
105
- (
106
- """--- a/app.py
107
- +++ b/app.py
108
- @@ -1,2 +1,2 @@
109
- import streamlit as st
110
- -st.title("Old Title")
111
- +st.title("New Title")
112
- @@ -5,2 +5,2 @@
113
- x = 5
114
- -st.write("Old message")
115
- +st.write("New message")""",
116
- """--- a/app.py
117
- +++ b/app.py
118
- @@ -1,2 +1,2 @@
119
- import streamlit as st
120
- -st.title("Old Title")
121
- +st.title("New Title")
122
- @@ -5,2 +5,2 @@
123
- x = 5
124
- -st.write("Old message")
125
- +st.write("New message")"""
126
- ),
127
-
128
- # Test case 8: Complex hunk with mixed context, additions, and removals
129
- (
130
- """--- a/app.py
131
- +++ b/app.py
132
- @@ -8,5 +8,6 @@
133
- \"\"\", unsafe_allow_html=True)
134
-
135
- -st.title("Simple Calculation")
136
- +st.title("Math Examples")
137
- +st.subheader("Basic Operations")
138
-
139
- x = 5
140
- y = 10""",
141
- """--- a/app.py
142
- +++ b/app.py
143
- @@ -8,6 +8,7 @@
144
- \"\"\", unsafe_allow_html=True)
145
-
146
- -st.title("Simple Calculation")
147
- +st.title("Math Examples")
148
- +st.subheader("Basic Operations")
149
-
150
- x = 5
151
- y = 10"""
152
- ),
153
-
154
- # Test case 9: Empty diff
155
- (
156
- "",
157
- ""
158
- ),
159
-
160
- # Test case 10: No hunks (just file headers)
161
- (
162
- """--- a/app.py
163
- +++ b/app.py""",
164
- """--- a/app.py
165
- +++ b/app.py"""
166
- ),
167
-
168
- # Test case 11: Single line addition at end
169
- (
170
- """--- a/app.py
171
- +++ b/app.py
172
- @@ -3,0 +3,1 @@
173
- st.title("My App")
174
- +st.write("Footer")""",
175
- """--- a/app.py
176
- +++ b/app.py
177
- @@ -3,1 +3,2 @@
178
- st.title("My App")
179
- +st.write("Footer")"""
180
- ),
181
-
182
- # Test case 12: Single line removal
183
- (
184
- """--- a/app.py
185
- +++ b/app.py
186
- @@ -3,1 +3,0 @@
187
- st.title("My App")
188
- -st.write("Footer")""",
189
- """--- a/app.py
190
- +++ b/app.py
191
- @@ -3,2 +3,1 @@
192
- st.title("My App")
193
- -st.write("Footer")"""
194
- ),
195
-
196
- # Test case 13: Multiple consecutive additions
197
- (
198
- """--- a/app.py
199
- +++ b/app.py
200
- @@ -2,0 +2,3 @@
201
- import streamlit as st
202
- +import pandas as pd
203
- +import numpy as np
204
- +import matplotlib.pyplot as plt
205
-
206
- st.title("My App")""",
207
- """--- a/app.py
208
- +++ b/app.py
209
- @@ -2,3 +2,6 @@
210
- import streamlit as st
211
- +import pandas as pd
212
- +import numpy as np
213
- +import matplotlib.pyplot as plt
214
-
215
- st.title("My App")"""
216
- ),
217
-
218
- # Test case 14: Multiple consecutive removals
219
- (
220
- """--- a/app.py
221
- +++ b/app.py
222
- @@ -2,3 +2,0 @@
223
- import streamlit as st
224
- -import pandas as pd
225
- -import numpy as np
226
- -import matplotlib.pyplot as plt
227
-
228
- st.title("My App")""",
229
- """--- a/app.py
230
- +++ b/app.py
231
- @@ -2,6 +2,3 @@
232
- import streamlit as st
233
- -import pandas as pd
234
- -import numpy as np
235
- -import matplotlib.pyplot as plt
236
-
237
- st.title("My App")"""
238
- ),
239
-
240
- # Test case 15: Edge case - hunk at very end of file
241
- (
242
- """--- a/app.py
243
- +++ b/app.py
244
- @@ -5,2 +5,3 @@
245
- st.title("My App")
246
- -st.write("Old")
247
- +st.write("New")
248
- +st.write("Extra")""",
249
- """--- a/app.py
250
- +++ b/app.py
251
- @@ -5,2 +5,3 @@
252
- st.title("My App")
253
- -st.write("Old")
254
- +st.write("New")
255
- +st.write("Extra")"""
256
- ),
257
-
258
- # Test case 16: Edge case - hunk at very beginning of file
259
- (
260
- """--- a/app.py
261
- +++ b/app.py
262
- @@ -1,2 +1,3 @@
263
- -import streamlit as st
264
- +import streamlit as st
265
- +import pandas as pd
266
-
267
- st.title("My App")""",
268
- """--- a/app.py
269
- +++ b/app.py
270
- @@ -1,3 +1,4 @@
271
- -import streamlit as st
272
- +import streamlit as st
273
- +import pandas as pd
274
-
275
- st.title("My App")"""
276
- ),
277
-
278
- # Test case 17: Multiple hunks - real world example
279
- (
280
- """--- a/app.py
281
- +++ b/app.py
282
- @@ -28,10 +28,10 @@
283
- # Display initial dataframe
284
- st.subheader("Meta Stock Prices Dataset")
285
- -st.dataframe(meta_stock_prices_df.head())
286
-
287
- # Create visualization
288
- st.subheader("Meta Stock Price and Major Acquisitions since 2012")
289
-
290
- # Matplotlib figure
291
- fig, ax = plt.subplots(figsize=(14,6))
292
- ax.plot(meta_stock_prices_df['date'], meta_stock_prices_df['close'], label='Meta Stock Price (Close)')
293
- @@ -62,7 +62,10 @@
294
- ax.set_title("Meta Stock Price and Major Acquisitions since 2012", fontsize=16)
295
- ax.set_xlabel('Date')
296
- ax.set_ylabel('Closing Price ($)')
297
- ax.legend()
298
- plt.tight_layout()
299
-
300
- # Display the plot in Streamlit
301
- st.pyplot(fig)
302
- +
303
- +# Display initial dataframe
304
- +st.dataframe(meta_stock_prices_df.head())""",
305
- """--- a/app.py
306
- +++ b/app.py
307
- @@ -28,10 +28,9 @@
308
- # Display initial dataframe
309
- st.subheader("Meta Stock Prices Dataset")
310
- -st.dataframe(meta_stock_prices_df.head())
311
-
312
- # Create visualization
313
- st.subheader("Meta Stock Price and Major Acquisitions since 2012")
314
-
315
- # Matplotlib figure
316
- fig, ax = plt.subplots(figsize=(14,6))
317
- ax.plot(meta_stock_prices_df['date'], meta_stock_prices_df['close'], label='Meta Stock Price (Close)')
318
- @@ -62,8 +62,11 @@
319
- ax.set_title("Meta Stock Price and Major Acquisitions since 2012", fontsize=16)
320
- ax.set_xlabel('Date')
321
- ax.set_ylabel('Closing Price ($)')
322
- ax.legend()
323
- plt.tight_layout()
324
-
325
- # Display the plot in Streamlit
326
- st.pyplot(fig)
327
- +
328
- +# Display initial dataframe
329
- +st.dataframe(meta_stock_prices_df.head())"""
330
- ),
331
-
332
- # Test case 18: Simple multiple hunks - title change and add footer
333
- (
334
- """--- a/app.py
335
- +++ b/app.py
336
- @@ -1,2 +1,2 @@
337
- import streamlit as st
338
- -st.title("Old App")
339
- +st.title("New App")
340
- @@ -3,1 +3,3 @@
341
- st.write("Hello World")
342
- +
343
- +st.write("Footer text")""",
344
- """--- a/app.py
345
- +++ b/app.py
346
- @@ -1,2 +1,2 @@
347
- import streamlit as st
348
- -st.title("Old App")
349
- +st.title("New App")
350
- @@ -3,1 +3,3 @@
351
- st.write("Hello World")
352
- +
353
- +st.write("Footer text")"""
354
- ),
355
-
356
- # Test case 19: Simple multiple hunks - remove and add lines
357
- (
358
- """--- a/app.py
359
- +++ b/app.py
360
- @@ -1,3 +1,2 @@
361
- import streamlit as st
362
- -st.write("Remove this")
363
- st.title("My App")
364
- @@ -3,1 +3,2 @@
365
- st.title("My App")
366
- +st.write("Add this")""",
367
- """--- a/app.py
368
- +++ b/app.py
369
- @@ -1,3 +1,2 @@
370
- import streamlit as st
371
- -st.write("Remove this")
372
- st.title("My App")
373
- @@ -3,1 +3,2 @@
374
- st.title("My App")
375
- +st.write("Add this")"""
376
- ),
377
-
378
- # Test case 20: Multiple hunks with context lines
379
- (
380
- """--- a/app.py
381
- +++ b/app.py
382
- @@ -2,3 +2,3 @@
383
- import streamlit as st
384
-
385
- -st.title("Old Title")
386
- +st.title("New Title")
387
- @@ -6,3 +6,3 @@
388
- st.write("Some content")
389
-
390
- -st.write("Old message")
391
- +st.write("New message")""",
392
- """--- a/app.py
393
- +++ b/app.py
394
- @@ -2,3 +2,3 @@
395
- import streamlit as st
396
-
397
- -st.title("Old Title")
398
- +st.title("New Title")
399
- @@ -6,3 +6,3 @@
400
- st.write("Some content")
401
-
402
- -st.write("Old message")
403
- +st.write("New message")"""
404
- ),
405
-
406
- # Test case 21: Add emoji in newly added line
407
- (
408
- """--- a/app.py
409
- +++ b/app.py
410
- @@ -2,1 +2,1 @@
411
- import streamlit as st
412
-
413
- +st.title("My App 🚀")
414
- st.write("Welcome to the app!")""",
415
- """--- a/app.py
416
- +++ b/app.py
417
- @@ -2,3 +2,4 @@
418
- import streamlit as st
419
-
420
- +st.title("My App 🚀")
421
- st.write("Welcome to the app!")"""
422
- ),
423
-
424
- # Add missing file header component
425
- (
426
- """@@ -11,1 +11,1 @@
427
- -st.title("Simple Calculation")
428
- +st.title("Math Examples")""",
429
- """--- a/app.py
430
- +++ b/app.py
431
- @@ -11,1 +11,1 @@
432
- -st.title("Simple Calculation")
433
- +st.title("Math Examples")"""
434
- ),
435
-
436
- # Correct invalid (single line) file header component
437
- (
438
- """--- a/app.py +++ b/app.py
439
- @@ -11,1 +11,1 @@
440
- -st.title("Simple Calculation")
441
- +st.title("Math Examples")""",
442
- """--- a/app.py
443
- +++ b/app.py
444
- @@ -11,1 +11,1 @@
445
- -st.title("Simple Calculation")
446
- +st.title("Math Examples")"""
447
- ),
448
- ])
449
- def test_fix_diff_headers(input_diff, expected_output):
450
- """Test the fix_diff_headers function with various diff scenarios."""
451
- result = fix_diff_headers(input_diff)
452
- assert result == expected_output, f"""
453
- Input:
454
- {repr(input_diff)}
455
-
456
- Expected:
457
- {repr(expected_output)}
458
-
459
- Got:
460
- {repr(result)}
461
- """
462
-
463
-
464
- def test_fix_diff_headers_preserves_structure():
465
- """Test that fix_diff_headers preserves the overall structure of the diff."""
466
- input_diff = """--- a/app.py
467
- +++ b/app.py
468
- @@ -11,6 +11,6 @@
469
- \"\"\", unsafe_allow_html=True)
470
-
471
- -st.title("Simple Calculation")
472
- +st.title("Math Examples")
473
-
474
- x = 5
475
- y = 10"""
476
-
477
- result = fix_diff_headers(input_diff)
478
-
479
- # Should preserve file headers
480
- assert "--- a/app.py" in result
481
- assert "+++ b/app.py" in result
482
-
483
- # Should preserve the hunk content
484
- assert "-st.title(\"Simple Calculation\")" in result
485
- assert "+st.title(\"Math Examples\")" in result
486
-
487
- # Should have exactly one hunk header
488
- hunk_headers = [line for line in result.split('\n') if line.startswith('@@')]
489
- assert len(hunk_headers) == 1
490
-
491
- # The hunk header should have correct format
492
- hunk_header = hunk_headers[0]
493
- assert hunk_header.startswith('@@ -')
494
- assert hunk_header.endswith(' @@')
495
- assert ',' in hunk_header # Should have count numbers
496
-
497
-
498
- def test_fix_diff_headers_line_counting():
499
- """Test that the line counting logic is correct."""
500
- # Test case with known line counts
501
- input_diff = """--- a/app.py
502
- +++ b/app.py
503
- @@ -10,999 +10,999 @@
504
- context line 1
505
- -context line 2
506
- +modified line 2
507
- context line 3"""
508
-
509
- result = fix_diff_headers(input_diff)
510
-
511
- # Should fix the counts to be correct
512
- hunk_headers = [line for line in result.split('\n') if line.startswith('@@')]
513
- assert len(hunk_headers) == 1
514
-
515
- hunk_header = hunk_headers[0]
516
- # Should be @@ -10,3 +10,3 @@ (3 lines: context, -line, +line, context)
517
- assert "@@ -10,3 +10,3 @@" in result or "@@ -10,3 +10,3@@" in result
518
-
519
-
520
- @pytest.mark.parametrize("input_diff", [
521
- # Test various malformed inputs that should be handled gracefully
522
- "",
523
- "not a diff",
524
- "--- a/app.py\n+++ b/app.py",
525
- "--- a/app.py\n+++ b/app.py\n@@ -1,1 +1,1 @@\n",
526
- "--- a/app.py\n+++ b/app.py\n@@ -1,1 +1,1 @@\n+added line",
527
- "--- a/app.py\n+++ b/app.py\n@@ -1,1 +1,1 @@\n-removed line",
528
- ])
529
- def test_fix_diff_headers_edge_cases(input_diff):
530
- """Test that fix_diff_headers handles edge cases gracefully."""
531
- # Should not raise an exception
532
- result = fix_diff_headers(input_diff)
533
- assert isinstance(result, str)