(self)
| 2290 | |
| 2291 | @force_not_colorized |
| 2292 | def test_no_newline(self): |
| 2293 | env = os.environ.copy() |
| 2294 | env.pop("PYTHON_BASIC_REPL", "") |
| 2295 | env["PYTHON_BASIC_REPL"] = "1" |
| 2296 | |
| 2297 | commands = "print('Something pretty long', end='')\nexit()\n" |
| 2298 | expected_output_sequence = "Something pretty long>>> exit()" |
| 2299 | |
| 2300 | # gh-143394: The basic REPL needs the readline module to turn off |
| 2301 | # ECHO terminal attribute. |
| 2302 | if readline_module is not None: |
| 2303 | basic_output, basic_exit_code = self.run_repl(commands, env=env) |
| 2304 | self.assertEqual(basic_exit_code, 0) |
| 2305 | self.assertIn(expected_output_sequence, basic_output) |
| 2306 | |
| 2307 | output, exit_code = self.run_repl(commands) |
| 2308 | self.assertEqual(exit_code, 0) |
| 2309 | |
| 2310 | # Build patterns for escape sequences that don't affect cursor position |
| 2311 | # or visual output. Use terminfo to get platform-specific sequences, |
| 2312 | # falling back to hard-coded patterns for capabilities not in terminfo. |
| 2313 | from _pyrepl.terminfo import TermInfo |
| 2314 | ti = TermInfo(os.environ.get("TERM", "")) |
| 2315 | |
| 2316 | safe_patterns = [] |
| 2317 | |
| 2318 | # smkx/rmkx - application cursor keys and keypad mode |
| 2319 | smkx = ti.get("smkx") |
| 2320 | rmkx = ti.get("rmkx") |
| 2321 | if smkx: |
| 2322 | safe_patterns.append(re.escape(smkx.decode("ascii"))) |
| 2323 | if rmkx: |
| 2324 | safe_patterns.append(re.escape(rmkx.decode("ascii"))) |
| 2325 | if not smkx and not rmkx: |
| 2326 | safe_patterns.append(r'\x1b\[\?1[hl]') # application cursor keys |
| 2327 | safe_patterns.append(r'\x1b[=>]') # application keypad mode |
| 2328 | |
| 2329 | # ich1 - insert character (only safe form that inserts exactly 1 char) |
| 2330 | ich1 = ti.get("ich1") |
| 2331 | if ich1: |
| 2332 | safe_patterns.append(re.escape(ich1.decode("ascii")) + r'(?=[ -~])') |
| 2333 | else: |
| 2334 | safe_patterns.append(r'\x1b\[(?:1)?@(?=[ -~])') |
| 2335 | |
| 2336 | # civis/cnorm - cursor visibility (may include cursor blinking control) |
| 2337 | civis = ti.get("civis") |
| 2338 | cnorm = ti.get("cnorm") |
| 2339 | if civis: |
| 2340 | safe_patterns.append(re.escape(civis.decode("ascii"))) |
| 2341 | if cnorm: |
| 2342 | safe_patterns.append(re.escape(cnorm.decode("ascii"))) |
| 2343 | if not civis and not cnorm: |
| 2344 | safe_patterns.append(r'\x1b\[\?25[hl]') # cursor visibility |
| 2345 | safe_patterns.append(r'\x1b\[\?12[hl]') # cursor blinking |
| 2346 | |
| 2347 | # rmam / smam - automatic margins |
| 2348 | rmam = ti.get("rmam") |
| 2349 | smam = ti.get("smam") |
nothing calls this directly
no test coverage detected