-
Notifications
You must be signed in to change notification settings - Fork 2
Lex Jupyter line magic with Mode::Jupyter
#23
Conversation
Current dependencies on/for this PR: This comment was auto-generated by Graphite. |
0977561
to
17bdc29
Compare
7509cd4
to
94fafb5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat!
I'm a bit concerned about how we want to disambiguate magics from modulo operators that split over multiple lines (something our formatter will create). Let's add some test cases for module operators to see if we handle them correctly
Same for /
and even comma
# This is a tuple
(
a
,
)
# This is a division operation
(
a
/
b
)
# Indented magic | ||
for a in range(5): | ||
%ls | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add some cases that look like magics but are none:
a % 5
(
a
%
5
)
%
a \
% 5
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a % 5 ( a % 5 ) % # [*] a \ % 5
They should all work assuming that for the marked ([*]
) line, the %
sign is a standalone (not part of another expression). It isn't as Python throws a Syntax error on that line and the tokenizer gives the MagicCommand
token only for that line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, cool! Does this work because we only call into lex_indentation
when the lexr is not in a parenthesized expression?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes that's correct.
#[cfg(feature = "full-lexer")] | ||
Tok::NonLogicalNewline, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is the correct way to do this. It seems the tests in CI are not run using --all-features
flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the easiest is to remove the feature flag. We always use full-lexer
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but the CI doesn't use it:
CARGO_ARGS: --no-default-features --features stdlib,zlib,importlib,encodings,ssl,jit |
Or, it uses it only for certain steps:
run: cargo clippy --all --features malachite-bigint,full-lexer,serde -- -Dwarnings |
/// [line magics]: https://ipython.readthedocs.io/en/stable/interactive/magics.html#line-magics | ||
/// [Dynamic object information]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#dynamic-object-information | ||
/// [System shell access]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#system-shell-access | ||
/// [Automatic parentheses and quotes]: https://ipython.readthedocs.io/en/stable/interactive/reference.html#automatic-parentheses-and-quotes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. This comment is excellent!
#[cfg(feature = "full-lexer")] | ||
Tok::NonLogicalNewline, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the easiest is to remove the feature flag. We always use full-lexer
.
kind: MagicKind::Magic, | ||
}, | ||
#[cfg(feature = "full-lexer")] | ||
Tok::NonLogicalNewline, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reasoning that this is a non logical newline. Isn't it a logical newline, because it terminates a statement?
Can we add a test where a magic command uses an invalid indent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the reasoning that this is a non logical newline. Isn't it a logical newline, because it terminates a statement?
My main reason being that as these tokens are filtered out before parsing, they should end with a NonLogicalNewline
as otherwise there'll be multiple newline tokens i.e., multiple blank lines. This is similar to the Comment
token.
Although, now that I think of it, without the full-lexer
feature (but with Mode::Jupyter
), the NonLogicalNewline
won't be filtered out while the MagicCommand
token will be.
Can we add a test where a magic command uses an invalid indent.
Do you mean something like the following?
for i in range(10):
print('hello')
!pwd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean something like the following?
Yes, exactly. Sorry, I should have provided an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've decided to move ahead with the current implementation but will have to consider indentation once the parser is updated to account for any indentation error.
/// When in [`Mode::Jupyter`], this will filter out all the Jupyter magic commands | ||
/// before parsing the tokens. | ||
/// |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this temporary or the final solution? I assumed that our plan is to introduce a new MagicCommand ast node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we will be adding a new AST node for this (probably 2).
Very well done! |
Lex Jupyter line magic with
Mode::Jupyter
This PR adds a new token
MagicCommand
1 which the lexer will recognize when inMode::Jupyter
. The rules for the lexer is as follows:Given that we are at the start of line, skip the indentation and look for characters that represent the start of a magic command, determine the magic kind and capture all the characters following it as the command string.
If the command extends multiple lines, the lexer will skip the line continuation character (
\
) but only if it's followed by a newline (\n
or\r
). The reason to skip this only in case of newline is because they can occur in the command string which we should not skip:The parser, when in
Mode::Jupyter
, will filter these tokens before the parsing begins. There is a small caveat when the magic command is indented. In the following example, when the parser filters out magic command, it'll throw an indentation error:Footnotes
I would prefer to have some other name as this not only represent a line magic (
%
) but also shell command (!
), help command (?
) and others. In original implementation, it's named as "IPython Syntax" ↩