Show More
@@ -0,0 +1,7 b'' | |||||
|
1 | Don't start a multiline cell with sunken parenthesis | |||
|
2 | ---------------------------------------------------- | |||
|
3 | ||||
|
4 | From now on IPython will not ask for the next line of input when given a single | |||
|
5 | line with more closing than opening brackets. For example, this means that if | |||
|
6 | you (mis)type ']]' instead of '[]', a ``SyntaxError`` will show up, instead of | |||
|
7 | the ``...:`` prompt continuation. |
@@ -508,6 +508,20 b' def make_tokens_by_line(lines:List[str]):' | |||||
508 |
|
508 | |||
509 | return tokens_by_line |
|
509 | return tokens_by_line | |
510 |
|
510 | |||
|
511 | ||||
|
512 | def has_sunken_brackets(tokens: List[tokenize.TokenInfo]): | |||
|
513 | """Check if the depth of brackets in the list of tokens drops below 0""" | |||
|
514 | parenlev = 0 | |||
|
515 | for token in tokens: | |||
|
516 | if token.string in {"(", "[", "{"}: | |||
|
517 | parenlev += 1 | |||
|
518 | elif token.string in {")", "]", "}"}: | |||
|
519 | parenlev -= 1 | |||
|
520 | if parenlev < 0: | |||
|
521 | return True | |||
|
522 | return False | |||
|
523 | ||||
|
524 | ||||
511 | def show_linewise_tokens(s: str): |
|
525 | def show_linewise_tokens(s: str): | |
512 | """For investigation and debugging""" |
|
526 | """For investigation and debugging""" | |
513 | if not s.endswith('\n'): |
|
527 | if not s.endswith('\n'): | |
@@ -662,6 +676,15 b' class TransformerManager:' | |||||
662 |
|
676 | |||
663 | tokens_by_line = make_tokens_by_line(lines) |
|
677 | tokens_by_line = make_tokens_by_line(lines) | |
664 |
|
678 | |||
|
679 | # Bail if we got one line and there are more closing parentheses than | |||
|
680 | # the opening ones | |||
|
681 | if ( | |||
|
682 | len(lines) == 1 | |||
|
683 | and tokens_by_line | |||
|
684 | and has_sunken_brackets(tokens_by_line[0]) | |||
|
685 | ): | |||
|
686 | return "invalid", None | |||
|
687 | ||||
665 | if not tokens_by_line: |
|
688 | if not tokens_by_line: | |
666 | return 'incomplete', find_last_indent(lines) |
|
689 | return 'incomplete', find_last_indent(lines) | |
667 |
|
690 |
@@ -255,18 +255,18 b' def test_find_assign_op_dedent():' | |||||
255 |
|
255 | |||
256 | def test_check_complete(): |
|
256 | def test_check_complete(): | |
257 | cc = ipt2.TransformerManager().check_complete |
|
257 | cc = ipt2.TransformerManager().check_complete | |
258 |
nt.assert_equal(cc("a = 1"), ( |
|
258 | nt.assert_equal(cc("a = 1"), ("complete", None)) | |
259 |
nt.assert_equal(cc("for a in range(5):"), ( |
|
259 | nt.assert_equal(cc("for a in range(5):"), ("incomplete", 4)) | |
260 |
nt.assert_equal(cc("for a in range(5):\n if a > 0:"), ( |
|
260 | nt.assert_equal(cc("for a in range(5):\n if a > 0:"), ("incomplete", 8)) | |
261 |
nt.assert_equal(cc("raise = 2"), ( |
|
261 | nt.assert_equal(cc("raise = 2"), ("invalid", None)) | |
262 |
nt.assert_equal(cc("a = [1,\n2,"), ( |
|
262 | nt.assert_equal(cc("a = [1,\n2,"), ("incomplete", 0)) | |
263 |
nt.assert_equal(cc(")"), ( |
|
263 | nt.assert_equal(cc("(\n))"), ("incomplete", 0)) | |
264 |
nt.assert_equal(cc("\\\r\n"), ( |
|
264 | nt.assert_equal(cc("\\\r\n"), ("incomplete", 0)) | |
265 |
nt.assert_equal(cc("a = '''\n hi"), ( |
|
265 | nt.assert_equal(cc("a = '''\n hi"), ("incomplete", 3)) | |
266 |
nt.assert_equal(cc("def a():\n x=1\n global x"), ( |
|
266 | nt.assert_equal(cc("def a():\n x=1\n global x"), ("invalid", None)) | |
267 |
nt.assert_equal(cc("a \\ "), ( |
|
267 | nt.assert_equal(cc("a \\ "), ("invalid", None)) # Nothing allowed after backslash | |
268 |
nt.assert_equal(cc("1\\\n+2"), ( |
|
268 | nt.assert_equal(cc("1\\\n+2"), ("complete", None)) | |
269 |
nt.assert_equal(cc("exit"), ( |
|
269 | nt.assert_equal(cc("exit"), ("complete", None)) | |
270 |
|
270 | |||
271 | example = dedent(""" |
|
271 | example = dedent(""" | |
272 | if True: |
|
272 | if True: | |
@@ -297,6 +297,24 b' def test_check_complete_II():' | |||||
297 | nt.assert_equal(cc('''def foo():\n """'''), ('incomplete', 4)) |
|
297 | nt.assert_equal(cc('''def foo():\n """'''), ('incomplete', 4)) | |
298 |
|
298 | |||
299 |
|
299 | |||
|
300 | def test_check_complete_invalidates_sunken_brackets(): | |||
|
301 | """ | |||
|
302 | Test that a single line with more closing brackets than the opening ones is | |||
|
303 | interpretted as invalid | |||
|
304 | """ | |||
|
305 | cc = ipt2.TransformerManager().check_complete | |||
|
306 | nt.assert_equal(cc(")"), ("invalid", None)) | |||
|
307 | nt.assert_equal(cc("]"), ("invalid", None)) | |||
|
308 | nt.assert_equal(cc("}"), ("invalid", None)) | |||
|
309 | nt.assert_equal(cc(")("), ("invalid", None)) | |||
|
310 | nt.assert_equal(cc("]["), ("invalid", None)) | |||
|
311 | nt.assert_equal(cc("}{"), ("invalid", None)) | |||
|
312 | nt.assert_equal(cc("]()("), ("invalid", None)) | |||
|
313 | nt.assert_equal(cc("())("), ("invalid", None)) | |||
|
314 | nt.assert_equal(cc(")[]("), ("invalid", None)) | |||
|
315 | nt.assert_equal(cc("()]("), ("invalid", None)) | |||
|
316 | ||||
|
317 | ||||
300 | def test_null_cleanup_transformer(): |
|
318 | def test_null_cleanup_transformer(): | |
301 | manager = ipt2.TransformerManager() |
|
319 | manager = ipt2.TransformerManager() | |
302 | manager.cleanup_transforms.insert(0, null_cleanup_transformer) |
|
320 | manager.cleanup_transforms.insert(0, null_cleanup_transformer) |
General Comments 0
You need to be logged in to leave comments.
Login now