Skip to content

Commit

Permalink
CLN refactor some big functions (#70)
Browse files Browse the repository at this point in the history
* refactor some big functions

* add some doctests

* ignore docs during testing
  • Loading branch information
MarcoGorelli committed Jul 17, 2020
1 parent d4d46dc commit 1725850
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 30 deletions.
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ steps:
displayName: 'static analysis'

- script: |
pytest --junitxml=junit/test-results.xml --cov=nbqa --cov-report=xml --cov-report=html -vv
pytest --junitxml=junit/test-results.xml --cov-report=xml --cov-report=html -vv
displayName: 'pytest'

- task: PublishCodeCoverageResults@1
Expand Down
126 changes: 97 additions & 29 deletions nbqa/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,38 @@ def _temp_python_file_for_notebook(notebook, tmpdir):
return temp_python_file


def _replace_temp_python_file_references_in_out_err(
temp_python_file, notebook, out, err
):
def _replace_full_path_out_err(out, err, temp_python_file, notebook):
"""
Out and err refer to temporary Python files - make them refer to Jupyter notebooks.
Needs docstring with example, gotta doctest it.
Take care of case when out/err display full path.
Examples
--------
>>> out = ""
>>> err = "reformatted tmpdir/notebook .py\\nAll done!"
>>> temp_python_file = Path('tmpdir').joinpath('notebook .py')
>>> notebook = Path('notebook.ipynb')
>>> out, err = _replace_full_path_out_err(out, err, temp_python_file, notebook)
>>> err
'reformatted notebook.ipynb\\nAll done!'
"""
# Take care of case when out/err display full path
out = out.replace(str(temp_python_file), str(notebook))
err = err.replace(str(temp_python_file), str(notebook))
return out, err

# Take care of case when out/err display relative path

def _replace_relative_path_out_err(out, err, notebook):
"""
Take care of case when out/err display relative path.
Examples
--------
>>> out = "notebook .py ."
>>> err = ""
>>> notebook = Path('notebook.ipynb')
>>> out, err = _replace_relative_path_out_err(out, err, notebook)
>>> out
'notebook.ipynb .'
"""
out = out.replace(
str(notebook.parent.joinpath(f"{notebook.stem} ").with_suffix(".py")),
str(notebook),
Expand All @@ -68,7 +87,13 @@ def _replace_temp_python_file_references_in_out_err(
str(notebook.parent.joinpath(f"{notebook.stem} ").with_suffix(".py")),
str(notebook),
)
return out, err


def _map_python_line_to_nb_lines(out, err, temp_python_file, notebook):
"""
Make sure stdout and stderr make reference to Jupyter Notebook lines.
"""
with open(str(temp_python_file), "r") as handle:
cells = handle.readlines()
mapping = {}
Expand All @@ -84,16 +109,49 @@ def _replace_temp_python_file_references_in_out_err(
out = re.sub(
rf"(?<={notebook.name}:)\d+", lambda x: str(mapping[int(x.group())]), out,
)
err = re.sub(
rf"(?<={notebook.name}:)\d+", lambda x: str(mapping[int(x.group())]), err,
)
return out, err


def _replace_temp_python_file_references_in_out_err(
temp_python_file, notebook, out, err
):
"""
Replace references to temporary directory name with current working directory.
"""
out, err = _replace_full_path_out_err(out, err, temp_python_file, notebook)
out, err = _replace_relative_path_out_err(out, err, notebook)
out, err = _map_python_line_to_nb_lines(out, err, temp_python_file, notebook)
return out, err


def _replace_tmpdir_references(out, err, tmpdirname):
out = re.sub(rf"{tmpdirname}(?=\s)", str(Path.cwd()), out)
err = re.sub(rf"{tmpdirname}(?=\s)", str(Path.cwd()), err)
def _replace_tmpdir_references(out, err, tmpdirname, cwd=None):
"""
Replace references to temporary directory name with current working directory.
Examples
--------
>>> out = "rootdir: /tmp/tmpdir\\n"
>>> err = ""
>>> tmpdirname = "/tmp/tmpdir"
>>> cwd = Path("nbQA-dev")
>>> out, err = _replace_tmpdir_references(out, err, tmpdirname, cwd)
>>> out
'rootdir: nbQA-dev\\n'
"""
if cwd is None:
cwd = Path.cwd()
out = re.sub(rf"{tmpdirname}(?=\s)", str(cwd), out)
err = re.sub(rf"{tmpdirname}(?=\s)", str(cwd), err)
return out, err


def _create_blank_init_files(notebook, tmpdirname):
"""
Replicate local (possibly blank) __init__ files to temporary directory.
"""
parts = notebook.parts
init_files = Path(parts[0]).rglob("__init__.py")
for i in init_files:
Expand All @@ -111,6 +169,32 @@ def _ensure_cell_separators_remain(temp_python_file):
handle.write(py_file)


def _run_command(command, root_dir, tmpdirname, nb_to_py_mapping, kwargs):
"""
Run third-party tool against given file or directory.
"""
env = os.environ.copy()
env["PYTHONPATH"] = os.getcwd()

if Path(root_dir).is_dir():
arg = str(Path(tmpdirname).joinpath(root_dir))
else:
assert len(nb_to_py_mapping) == 1
arg = str(next(iter(nb_to_py_mapping.values())))
output = subprocess.run(
[command, arg, *kwargs],
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
cwd=tmpdirname,
env=env,
)
output_code = output.returncode

out = output.stdout.decode()
err = output.stderr.decode()
return out, err, output_code


def main(raw_args=None):

command, root_dir, kwargs = _parse_args(raw_args)
Expand All @@ -129,25 +213,9 @@ def main(raw_args=None):
replace_magics.main(temp_python_file)
_create_blank_init_files(notebook, tmpdirname)

env = os.environ.copy()
env["PYTHONPATH"] = os.getcwd()

if Path(root_dir).is_dir():
arg = str(Path(tmpdirname).joinpath(root_dir))
else:
assert len(nb_to_py_mapping) == 1
arg = str(next(iter(nb_to_py_mapping.values())))
output = subprocess.run(
[command, arg, *kwargs],
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
cwd=tmpdirname,
env=env,
out, err, output_code = _run_command(
command, root_dir, tmpdirname, nb_to_py_mapping, kwargs
)
output_code = output.returncode

out = output.stdout.decode()
err = output.stderr.decode()

out, err = _replace_tmpdir_references(out, err, tmpdirname)

Expand Down
1 change: 1 addition & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
[pytest]
addopts = --doctest-modules -W error --cov=nbqa --cov-report=term-missing --ignore=docs

0 comments on commit 1725850

Please sign in to comment.