]>
git.madduck.net Git - etc/vim.git/blobdiff - src/black/handle_ipynb_magics.py
madduck's git repository
Every one of the projects in this repository is available at the canonical
URL git://git.madduck.net/madduck/pub/<projectpath> — see
each project's metadata for the exact URL.
All patches and comments are welcome. Please squash your changes to logical
commits before using git-format-patch and git-send-email to
patches@ git. madduck. net .
If you'd read over the Git project's submission guidelines and adhered to them,
I'd be especially grateful.
SSH access, as well as push access can be individually
arranged .
If you use my repositories frequently, consider adding the following
snippet to ~/.gitconfig and using the third clone URL listed for each
project:
[url "git://git.madduck.net/madduck/"]
insteadOf = madduck:
"""Functions to process IPython magics with."""
"""Functions to process IPython magics with."""
-from functools import lru_cache
-import dataclasses
-from typing import Dict, List, Tuple, Optional
-
+import collections
+import dataclasses
import secrets
import sys
import secrets
import sys
+from functools import lru_cache
+from typing import Dict, List, Optional, Tuple
if sys.version_info >= (3, 10):
from typing import TypeGuard
else:
from typing_extensions import TypeGuard
if sys.version_info >= (3, 10):
from typing import TypeGuard
else:
from typing_extensions import TypeGuard
-from black.report import NothingChanged
from black.output import out
from black.output import out
+from black.report import NothingChanged
TRANSFORMED_MAGICS = frozenset(
(
TRANSFORMED_MAGICS = frozenset(
(
-NON_ PYTHON_CELL_MAGICS = frozenset(
+PYTHON_CELL_MAGICS = frozenset(
- "bash",
- "html",
- "javascript",
- "js",
- "latex",
- "markdown",
- "perl",
- "ruby",
- "script",
- "sh",
- "svg",
- "writefile",
+ "capture",
+ "prun",
+ "pypy",
+ "python",
+ "python3",
+ "time",
+ "timeit",
)
)
TOKEN_HEX = secrets.token_hex
)
)
TOKEN_HEX = secrets.token_hex
Mirrors the logic in `quiet` from `IPython.core.displayhook`, but uses
``tokenize_rt`` so that round-tripping works fine.
"""
Mirrors the logic in `quiet` from `IPython.core.displayhook`, but uses
``tokenize_rt`` so that round-tripping works fine.
"""
- from tokenize_rt import (
- src_to_tokens,
- tokens_to_src,
- reversed_enumerate,
- )
+ from tokenize_rt import reversed_enumerate, src_to_tokens, tokens_to_src
tokens = src_to_tokens(src)
trailing_semicolon = False
tokens = src_to_tokens(src)
trailing_semicolon = False
"""
if not has_trailing_semicolon:
return src
"""
if not has_trailing_semicolon:
return src
- from tokenize_rt import src_to_tokens, tokens_to_src, reversed_enumerate
+ from tokenize_rt import reversed_enumerate, src_to_tokens, tokens_to_src
tokens = src_to_tokens(src)
for idx, token in reversed_enumerate(tokens):
tokens = src_to_tokens(src)
for idx, token in reversed_enumerate(tokens):
cell_magic_finder.visit(tree)
if cell_magic_finder.cell_magic is None:
return src, replacements
cell_magic_finder.visit(tree)
if cell_magic_finder.cell_magic is None:
return src, replacements
- if cell_magic_finder.cell_magic.name in NON_PYTHON_CELL_MAGICS:
- raise NothingChanged
header = cell_magic_finder.cell_magic.header
mask = get_token(src, header)
replacements.append(Replacement(mask=mask, src=header))
header = cell_magic_finder.cell_magic.header
mask = get_token(src, header)
replacements.append(Replacement(mask=mask, src=header))
+# ast.NodeVisitor + dataclass = breakage under mypyc.
class CellMagicFinder(ast.NodeVisitor):
"""Find cell magics.
class CellMagicFinder(ast.NodeVisitor):
"""Find cell magics.
and we look for instances of the latter.
"""
and we look for instances of the latter.
"""
- cell_magic: Optional[CellMagic] = None
+ def __init__(self, cell_magic: Optional[CellMagic] = None) -> None:
+ self.cell_magic = cell_magic
def visit_Expr(self, node: ast.Expr) -> None:
"""Find cell magic, extract header and body."""
def visit_Expr(self, node: ast.Expr) -> None:
"""Find cell magic, extract header and body."""
+# Unsurprisingly, subclassing ast.NodeVisitor means we can't use dataclasses here
+# as mypyc will generate broken code.
class MagicFinder(ast.NodeVisitor):
"""Visit cell to look for get_ipython calls.
class MagicFinder(ast.NodeVisitor):
"""Visit cell to look for get_ipython calls.
- magics: Dict[int, List[OffsetAndMagic]] = dataclasses.field(
- default_factory=lambda: collections.defaultdict(list)
- )
+ def __init__(self) -> None:
+ self.magics: Dict[int, List[OffsetAndMagic]] = collections.defaultdict(list)
def visit_Assign(self, node: ast.Assign) -> None:
"""Look for system assign magics.
def visit_Assign(self, node: ast.Assign) -> None:
"""Look for system assign magics.
For example,
black_version = !black --version
For example,
black_version = !black --version
- would have been transformed to
+ would have been (respectively) transformed to
black_version = get_ipython().getoutput('black --version')
black_version = get_ipython().getoutput('black --version')
+ env = get_ipython().run_line_magic('env', 'var')
- and we look for instances of the latter.
+ and we look for instances of any of the latter.
- if (
- isinstance(node.value, ast.Call)
- and _is_ipython_magic(node.value.func)
- and node.value.func.attr == "getoutput"
- ):
- (arg,) = _get_str_args(node.value.args)
- src = f"!{arg}"
+ if isinstance(node.value, ast.Call) and _is_ipython_magic(node.value.func):
+ args = _get_str_args(node.value.args)
+ if node.value.func.attr == "getoutput":
+ src = f"!{args[0]}"
+ elif node.value.func.attr == "run_line_magic":
+ src = f"%{args[0]}"
+ if args[1]:
+ src += f" {args[1]}"
+ else:
+ raise AssertionError(
+ f"Unexpected IPython magic {node.value.func.attr!r} found. "
+ "Please report a bug on https://github.com/psf/black/issues."
+ ) from None
self.magics[node.value.lineno].append(
OffsetAndMagic(node.value.col_offset, src)
)
self.magics[node.value.lineno].append(
OffsetAndMagic(node.value.col_offset, src)
)
else:
src = f"%{args[0]}"
if args[1]:
else:
src = f"%{args[0]}"
if args[1]:
src += f" {args[1]}"
elif node.value.func.attr == "system":
src = f"!{args[0]}"
src += f" {args[1]}"
elif node.value.func.attr == "system":
src = f"!{args[0]}"