@@ -147,101 +147,106 @@ def test_from_ansi_wrapper() -> None:
147
147
148
148
@pytest .mark .parametrize (
149
149
# Print with style and verify that everything but newline characters have style.
150
- ('objects' , 'expected ' , 'sep ' , 'end ' ),
150
+ ('objects' , 'sep ' , 'end ' , 'expected ' ),
151
151
[
152
152
# Print nothing
153
- ((), "\n " , " " , "\n " ),
153
+ ((), " " , "\n " , "\n " ),
154
154
# Empty string
155
- (("" ,), "\n " , " " , "\n " ),
155
+ (("" ,), " " , "\n " , "\n " ),
156
156
# Multple empty strings
157
- (("" , "" ), ' \ x1b [34;47m \x1b [0m\n ' , " " , " \n " ),
157
+ (("" , "" ), " " , " \n " , " \ x1b [34;47m \x1b [0m\n " ),
158
158
# Basic string
159
159
(
160
160
("str_1" ,),
161
- "\x1b [34;47mstr_1\x1b [0m\n " ,
162
161
" " ,
163
162
"\n " ,
163
+ "\x1b [34;47mstr_1\x1b [0m\n " ,
164
164
),
165
165
# String which ends with newline
166
166
(
167
167
("str_1\n " ,),
168
- "\x1b [34;47mstr_1\x1b [0m\n \n " ,
169
168
" " ,
170
169
"\n " ,
170
+ "\x1b [34;47mstr_1\x1b [0m\n \n " ,
171
171
),
172
172
# String which ends with multiple newlines
173
173
(
174
174
("str_1\n \n " ,),
175
- "\x1b [34;47mstr_1\x1b [0m\n \n \n " ,
176
175
" " ,
177
176
"\n " ,
177
+ "\x1b [34;47mstr_1\x1b [0m\n \n \n " ,
178
178
),
179
179
# Mutiple lines
180
180
(
181
181
("str_1\n str_2" ,),
182
- "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47mstr_2\x1b [0m\n " ,
183
182
" " ,
184
183
"\n " ,
184
+ "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47mstr_2\x1b [0m\n " ,
185
185
),
186
186
# Multiple strings
187
187
(
188
188
("str_1" , "str_2" ),
189
- "\x1b [34;47mstr_1 str_2\x1b [0m\n " ,
190
189
" " ,
191
190
"\n " ,
191
+ "\x1b [34;47mstr_1 str_2\x1b [0m\n " ,
192
192
),
193
193
# Multiple strings with newline between them.
194
194
(
195
195
("str_1\n " , "str_2" ),
196
- "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47m str_2\x1b [0m\n " ,
197
196
" " ,
198
197
"\n " ,
198
+ "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47m str_2\x1b [0m\n " ,
199
199
),
200
200
# Multiple strings and non-space value for sep
201
201
(
202
202
("str_1" , "str_2" ),
203
- "\x1b [34;47mstr_1(sep)str_2\x1b [0m\n " ,
204
203
"(sep)" ,
205
204
"\n " ,
205
+ "\x1b [34;47mstr_1(sep)str_2\x1b [0m\n " ,
206
206
),
207
207
# Multiple strings and sep is a newline
208
208
(
209
209
("str_1" , "str_2" ),
210
- "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47mstr_2\x1b [0m\n " ,
211
210
"\n " ,
212
211
"\n " ,
212
+ "\x1b [34;47mstr_1\x1b [0m\n \x1b [34;47mstr_2\x1b [0m\n " ,
213
213
),
214
214
# Multiple strings and sep has newlines
215
215
(
216
216
("str_1" , "str_2" ),
217
- "\x1b [34;47mstr_1(sep1)\x1b [0m\n \x1b [34;47m(sep2)str_2\x1b [0m\n " ,
218
- "(sep1)\n (sep2)" ,
217
+ "(sep1)\n (sep2)\n " ,
219
218
"\n " ,
219
+ ("\x1b [34;47mstr_1(sep1)\x1b [0m\n \x1b [34;47m(sep2)\x1b [0m\n \x1b [34;47mstr_2\x1b [0m\n " ),
220
220
),
221
221
# Non-newline value for end.
222
222
(
223
223
("str_1" , "str_2" ),
224
- "\x1b [34;47mstr_1(sep1)\x1b [0m\n \x1b [34;47m(sep2)str_2\x1b [0m\x1b [34;47m(end)\x1b [0m" ,
225
224
"(sep1)\n (sep2)" ,
226
225
"(end)" ,
226
+ "\x1b [34;47mstr_1(sep1)\x1b [0m\n \x1b [34;47m(sep2)str_2\x1b [0m\x1b [34;47m(end)\x1b [0m" ,
227
227
),
228
228
# end has newlines.
229
229
(
230
230
("str_1" , "str_2" ),
231
- "\x1b [34;47mstr_1(sep1)\x1b [0m\n \x1b [34;47m(sep2)str_2\x1b [0m\x1b [34;47m(end1)\x1b [0m\n \x1b [34;47m(end2)\x1b [0m" ,
232
- "(sep1)\n (sep2)" ,
233
- "(end1)\n (end2)" ,
231
+ "(sep1)\n (sep2)\n " ,
232
+ "(end1)\n (end2)\n " ,
233
+ (
234
+ "\x1b [34;47mstr_1(sep1)\x1b [0m\n "
235
+ "\x1b [34;47m(sep2)\x1b [0m\n "
236
+ "\x1b [34;47mstr_2\x1b [0m\x1b [34;47m(end1)\x1b [0m\n "
237
+ "\x1b [34;47m(end2)\x1b [0m\n "
238
+ ),
234
239
),
235
240
# Empty sep and end values
236
241
(
237
242
("str_1" , "str_2" ),
238
- "\x1b [34;47mstr_1str_2\x1b [0m" ,
239
243
"" ,
240
244
"" ,
245
+ "\x1b [34;47mstr_1str_2\x1b [0m" ,
241
246
),
242
247
],
243
248
)
244
- def test_apply_style_wrapper (objects : tuple [str ], expected : str , sep : str , end : str ) -> None :
249
+ def test_apply_style_wrapper_soft_wrap (objects : tuple [str ], sep : str , end : str , expected : str ) -> None :
245
250
# Check if we are still patching Segment.apply_style(). If this check fails, then Rich
246
251
# has fixed the bug. Therefore, we can remove this test function and ru._apply_style_wrapper.
247
252
assert Segment .apply_style .__func__ is ru ._apply_style_wrapper .__func__ # type: ignore[attr-defined]
@@ -275,3 +280,52 @@ def test_apply_style_wrapper(objects: tuple[str], expected: str, sep: str, end:
275
280
finally :
276
281
# Restore the patch
277
282
Segment .apply_style = ru ._apply_style_wrapper # type: ignore[assignment]
283
+
284
+
285
+ def test_apply_style_wrapper_word_wrap () -> None :
286
+ """
287
+ Test that our patch didn't mess up word wrapping.
288
+ Make sure it does not insert styled newlines or apply style to existing newlines.
289
+ """
290
+ # Check if we are still patching Segment.apply_style(). If this check fails, then Rich
291
+ # has fixed the bug. Therefore, we can remove this test function and ru._apply_style_wrapper.
292
+ assert Segment .apply_style .__func__ is ru ._apply_style_wrapper .__func__ # type: ignore[attr-defined]
293
+
294
+ str1 = "this\n will word wrap\n "
295
+ str2 = "and\n so will this\n "
296
+ sep = "(sep1)\n (sep2)\n "
297
+ end = "(end1)\n (end2)\n "
298
+ style = "blue on white"
299
+
300
+ # All newlines should appear outside of ANSI style sequences.
301
+ expected = (
302
+ "\x1b [34;47mthis\x1b [0m\n "
303
+ "\x1b [34;47mwill word \x1b [0m\n "
304
+ "\x1b [34;47mwrap\x1b [0m\n "
305
+ "\x1b [34;47m(sep1)\x1b [0m\n "
306
+ "\x1b [34;47m(sep2)\x1b [0m\n "
307
+ "\x1b [34;47mand\x1b [0m\n "
308
+ "\x1b [34;47mso will \x1b [0m\n "
309
+ "\x1b [34;47mthis\x1b [0m\n "
310
+ "\x1b [34;47m(end1)\x1b [0m\n "
311
+ "\x1b [34;47m(end2)\x1b [0m\n "
312
+ )
313
+
314
+ # Set a width which will cause word wrapping.
315
+ console = Console (force_terminal = True , width = 10 )
316
+
317
+ try :
318
+ with console .capture () as capture :
319
+ console .print (str1 , str2 , sep = sep , end = end , style = style , soft_wrap = False )
320
+ assert capture .get () == expected
321
+
322
+ # Now remove our patch and make sure it produced the same result as unpatched Rich.
323
+ Segment .apply_style = ru ._orig_segment_apply_style # type: ignore[assignment]
324
+
325
+ with console .capture () as capture :
326
+ console .print (str1 , str2 , sep = sep , end = end , style = style , soft_wrap = False )
327
+ assert capture .get () == expected
328
+
329
+ finally :
330
+ # Restore the patch
331
+ Segment .apply_style = ru ._apply_style_wrapper # type: ignore[assignment]
0 commit comments