Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,19 +63,20 @@ or you can put the following in your :code:`pyproject.toml` file
Ignore cells
~~~~~~~~~~~~

By default, :code:`nbQA` will ignore line magics (e.g. :code:`%matplotlib inline`), and :code:`%%bash` and :code:`%%script` cell magics.
To ignore extra cells, you can use the :code:`--nbqa-ignore-cells` CLI argument, e.g.
By default, :code:`nbQA` will ignore line magics (e.g. :code:`%matplotlib inline`), as well as most cell magics.
To process code in cells with cell magics, you can use the :code:`--nbqa-process-cells` CLI argument, e.g. to process
code within :code:``%%add_to`` cell magics, use

.. code-block:: bash

nbqa black my_notebook.ipynb --nbqa-ignore-cells %%html,%%cython
nbqa black my_notebook.ipynb --nbqa-process-cells add_to

or the :code:`ignore_cells` option in your :code:`pyproject.toml` file, e.g.
or the :code:`process_cells` option in your :code:`pyproject.toml` file, e.g.

.. code-block:: toml

[tool.nbqa.ignore_cells]
black = "%%html,%%cython"
[tool.nbqa.process_cells]
black = add_to

Include / exclude
~~~~~~~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion nbqa/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ def _run_on_one_root_dir(
nb_info_mapping[notebook] = save_source.main(
notebook,
temp_python_file,
configs.nbqa_ignore_cells,
configs.nbqa_process_cells,
cli_args.command,
)
except Exception as exc:
Expand Down
19 changes: 16 additions & 3 deletions nbqa/cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ class CLIArgs: # pylint: disable=R0902,R0903
nbqa_config
Config file for 3rd party tool (e.g. :code:`.mypy.ini`)
nbqa_ignore_cells
Ignore cells whose first line starts with the input token
Deprecated.
nbqa_process_cells
Process code within these cell magics.
nbqa_addopts
Any additional flags passed to third-party tool (e.g. :code:`--quiet`).
nbqa_files
Expand All @@ -60,6 +62,7 @@ class CLIArgs: # pylint: disable=R0902,R0903
nbqa_addopts: Sequence[str]
nbqa_mutate: bool
nbqa_ignore_cells: Optional[str]
nbqa_process_cells: Optional[str]
nbqa_config: Optional[str]
nbqa_diff: bool
nbqa_files: Optional[str]
Expand All @@ -82,6 +85,7 @@ def __init__(self, args: argparse.Namespace, cmd_args: Sequence[str]) -> None:
self.nbqa_mutate = args.nbqa_mutate or False
self.nbqa_config = args.nbqa_config or None
self.nbqa_ignore_cells = args.nbqa_ignore_cells or None
self.nbqa_process_cells = args.nbqa_process_cells or None
self.nbqa_diff = args.nbqa_diff or False
self.nbqa_files = args.nbqa_files or None
self.nbqa_exclude = args.nbqa_exclude or None
Expand Down Expand Up @@ -136,8 +140,17 @@ def parse_args(argv: Optional[Sequence[str]]) -> "CLIArgs":
required=False,
help=dedent(
r"""
Ignore cells whose first line starts with this. You can pass multiple options,
e.g. `nbqa black my_notebook.ipynb --nbqa-ignore-cells %%%%cython,%%%%html`
Deprecated, do not use.
"""
),
)
parser.add_argument(
"--nbqa-process-cells",
required=False,
help=dedent(
r"""
Process code within these cell magics. You can pass multiple options,
e.g. `nbqa black my_notebook.ipynb --nbqa-process-cells add_to,write_to`
by placing commas between them.
"""
),
Expand Down
28 changes: 25 additions & 3 deletions nbqa/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class _ConfigSections(NamedTuple): # pylint: disable=R0903
ADDOPTS: str = "addopts"
CONFIG: str = "config"
IGNORE_CELLS: str = "ignore_cells"
PROCESS_CELLS: str = "process_cells"
MUTATE: str = "mutate"
DIFF: str = "diff"
FILES: str = "files"
Expand All @@ -75,7 +76,9 @@ class Configs:
nbqa_config
Configuration of the third party tool.
nbqa_ignore_cells
Extra cells which nbqa should ignore.
Deprecated.
nbqa_process_cells
Process code within cells with these cell magics.
nbqa_addopts
Additional arguments passed to the third party tool
nbqa_files
Expand All @@ -92,6 +95,9 @@ class Configs:
_config_section_parsers[CONFIG_SECTIONS.IGNORE_CELLS] = (
lambda arg: arg.split(",") if isinstance(arg, str) else arg
)
_config_section_parsers[CONFIG_SECTIONS.PROCESS_CELLS] = (
lambda arg: arg.split(",") if isinstance(arg, str) else arg
)
_config_section_parsers[CONFIG_SECTIONS.MUTATE] = bool
_config_section_parsers[CONFIG_SECTIONS.DIFF] = bool
_config_section_parsers[CONFIG_SECTIONS.FILES] = str
Expand All @@ -100,6 +106,7 @@ class Configs:
_mutate: bool = False
_config: Optional[str] = None
_ignore_cells: Sequence[str] = []
_process_cells: Sequence[str] = []
_addopts: Sequence[str] = []
_diff: bool = False
_files: Optional[str] = None
Expand Down Expand Up @@ -141,9 +148,14 @@ def nbqa_addopts(self) -> Sequence[str]:

@property
def nbqa_ignore_cells(self) -> Sequence[str]:
"""Additional cells which nbqa should ignore."""
"""Don't use, deprecated."""
return self._ignore_cells

@property
def nbqa_process_cells(self) -> Sequence[str]:
"""Additional cells which nbqa should process."""
return self._process_cells

@property
def nbqa_files(self) -> Optional[str]:
"""Additional cells which nbqa should ignore."""
Expand Down Expand Up @@ -172,6 +184,10 @@ def merge(self, other: "Configs") -> "Configs":
config.set_config(
CONFIG_SECTIONS.IGNORE_CELLS, self._ignore_cells or other.nbqa_ignore_cells
)
config.set_config(
CONFIG_SECTIONS.PROCESS_CELLS,
self._process_cells or other.nbqa_process_cells,
)
config.set_config(CONFIG_SECTIONS.MUTATE, self._mutate or other.nbqa_mutate)
config.set_config(CONFIG_SECTIONS.DIFF, self._diff or other.nbqa_diff)
config.set_config(CONFIG_SECTIONS.FILES, self._files or other.nbqa_files)
Expand All @@ -193,6 +209,7 @@ def parse_from_cli_args(cli_args: CLIArgs) -> "Configs":
config.set_config(CONFIG_SECTIONS.ADDOPTS, cli_args.nbqa_addopts)
config.set_config(CONFIG_SECTIONS.CONFIG, cli_args.nbqa_config)
config.set_config(CONFIG_SECTIONS.IGNORE_CELLS, cli_args.nbqa_ignore_cells)
config.set_config(CONFIG_SECTIONS.PROCESS_CELLS, cli_args.nbqa_process_cells)
config.set_config(CONFIG_SECTIONS.MUTATE, cli_args.nbqa_mutate)
config.set_config(CONFIG_SECTIONS.DIFF, cli_args.nbqa_diff)
config.set_config(CONFIG_SECTIONS.FILES, cli_args.nbqa_files)
Expand All @@ -211,7 +228,7 @@ def get_default_config(command: str) -> "Configs":
CONFIG_SECTIONS.CONFIG, DEFAULT_CONFIG["config"].get(command)
)
defaults.set_config(
CONFIG_SECTIONS.IGNORE_CELLS, DEFAULT_CONFIG["ignore_cells"].get(command)
CONFIG_SECTIONS.PROCESS_CELLS, DEFAULT_CONFIG["process_cells"].get(command)
)
defaults.set_config(
CONFIG_SECTIONS.MUTATE, DEFAULT_CONFIG["mutate"].get(command)
Expand Down Expand Up @@ -247,3 +264,8 @@ def validate(self) -> None:
)
if self.nbqa_config and not Path(self.nbqa_config).exists():
raise FileNotFoundError(f"{self.nbqa_config} not found.")
if self.nbqa_ignore_cells:
raise ValueError(
"--nbqa-ignore-cells is deprecated since version 0.6.0, "
"most cell magics are now excluded by default."
)
2 changes: 1 addition & 1 deletion nbqa/config/default_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ isort = ["--treat-comment-as-code", "# %%NBQA-CELL-SEP"]

[mutate]

[ignore_cells]
[process_cells]

[diff]

Expand Down
12 changes: 3 additions & 9 deletions nbqa/handle_magics.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class IPythonMagicType(Enum):
HELP = 1
LINE = 2
CELL = 3
NO_MAGIC = 4


class MagicHandler(ABC):
Expand Down Expand Up @@ -191,22 +192,15 @@ def get_ipython_magic_type(ipython_magic: str) -> Optional[IPythonMagicType]:
-------
Optional[IPythonMagicType]
Type of the IPython magic

Raises
------
RuntimeError
This shouldn't normally happen, it's just a defensive check.
"""
python_code = INPUT_SPLITTER.transform_cell(ipython_magic)
magic_type: Optional[IPythonMagicType] = None
for magic, prefixes in MagicHandler._MAGIC_PREFIXES.items():
if any(prefix in python_code for prefix in prefixes):
magic_type = magic
break
else: # pragma: nocover
raise RuntimeError(
"Unreachable code reached - please report a bug at https://github.com/nbQA-dev/nbQA"
)
else:
magic_type = IPythonMagicType.NO_MAGIC

return magic_type

Expand Down
44 changes: 14 additions & 30 deletions nbqa/save_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,27 +28,7 @@
from pathlib import Path

CODE_SEPARATOR = "# %%NBQA-CELL-SEP\n"
MAGIC = [
"%%!",
"%%bash",
"%%cython",
"%%HTML",
"%%html",
"%%javascript",
"%%js",
"%%latex",
"%%markdown",
"%%perl",
"%%python2",
"%%ruby",
"%%script",
"%%sh",
"%%sx",
"%%system",
"%%SVG",
"%%svg",
"%%writefile",
]
MAGIC = ["time", "timeit", "capture", "pypy", "python", "python3"]
NEWLINE = "\n"
NEWLINES = defaultdict(lambda: NEWLINE * 3)
NEWLINES["isort"] = NEWLINE * 2
Expand Down Expand Up @@ -296,7 +276,7 @@ def _get_line_numbers_for_mapping(


def _should_ignore_code_cell(
source: Sequence[str], ignore_cells: Sequence[str]
source: Sequence[str], process_cells: Sequence[str]
) -> bool:
"""
Return True if the current cell should be ignored from processing.
Expand All @@ -305,8 +285,8 @@ def _should_ignore_code_cell(
----------
source
Source from the notebook cell
ignore_cells
Extra cells which nbqa should ignore.
process_cells
Extra cells which nbqa should process.

Returns
-------
Expand All @@ -315,14 +295,18 @@ def _should_ignore_code_cell(
"""
if not source:
return True
ignore = MAGIC + [i.strip() for i in ignore_cells]
return any(source[0].lstrip().startswith(i) for i in ignore)
process = MAGIC + [i.strip() for i in process_cells]
magic_type = MagicHandler.get_ipython_magic_type(source[0])
if magic_type != IPythonMagicType.CELL:
return False
first_line = source[0].lstrip()
return first_line.split()[0] not in {f"%%{magic}" for magic in process}


def main(
notebook: "Path",
temp_python_file: "Path",
ignore_cells: Sequence[str],
process_cells: Sequence[str],
command: str,
) -> NotebookInfo:
"""
Expand All @@ -334,8 +318,8 @@ def main(
Jupyter Notebook third-party tool is being run against.
temp_python_file
Temporary Python file to save converted notebook in.
ignore_cells
Extra cells which nbqa should ignore.
process_cells
Extra cells which nbqa should process.
command
The third-party tool being run.

Expand All @@ -358,7 +342,7 @@ def main(
if cell["cell_type"] == "code":
cell_number += 1

if _should_ignore_code_cell(cell["source"], ignore_cells):
if _should_ignore_code_cell(cell["source"], process_cells):
code_cells_to_ignore.add(cell_number)
continue

Expand Down
36 changes: 36 additions & 0 deletions tests/data/default_magic.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%timeit\n",
"\n",
"a = 2 "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
36 changes: 36 additions & 0 deletions tests/data/non_default_magic.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%javascript\n",
"\n",
"a = 2 "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
Loading