Skip to content

Commit

Permalink
Merge pull request #85 from MarcoGorelli/multi-platform
Browse files Browse the repository at this point in the history
CI: try making multiplatform
  • Loading branch information
MarcoGorelli committed Jul 21, 2020
2 parents 877940e + d559c7f commit 35a0803
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 170 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ docs/_build
dist
.tox
build/
.coverage*
125 changes: 80 additions & 45 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
@@ -1,48 +1,83 @@
# Python package
# Create and test a Python package on multiple Python versions.
# Add steps that analyze code, save the dist with the build record, publish to a PyPI-compatible index, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/python

trigger:
- master
name: $(Year:yy)$(DayOfYear)$(Rev:r)


stages:
- stage: Unit_Test
jobs:

- job: 'Test_Linux'
pool:
vmImage: 'Ubuntu-16.04'
strategy:
matrix:
Python36:
python.version: '3.6'
Python37:
python.version: '3.7'
Python38:
python.version: '3.8'

steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(python.version)'
architecture: 'x64'

- script: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
displayName: 'Install dependencies'
- script: |
black . --check
isort . --check-only
flake8
displayName: 'static analysis'
- script: |
pytest --junitxml=junit/test-results.xml --cov-report=xml --cov-report=html -vv
displayName: 'pytest'
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
reportDirectory: '$(System.DefaultWorkingDirectory)/**/htmlcov'



- job: 'Test_Windows'
pool:
vmImage: 'vs2017-win2016'
strategy:
matrix:
Python36:
python.version: '3.6'
Python37:
python.version: '3.7'
Python38:
python.version: '3.8'


steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(python.version)'
architecture: 'x64'

- script: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
displayName: 'Install dependencies'
- script: |
black . --check
isort . --check-only
flake8
displayName: 'static analysis'
variables:
disable.coverage.autogenerate: 'true'

pool:
vmImage: 'ubuntu-latest'
strategy:
matrix:
Python36:
python.version: '3.6'
Python37:
python.version: '3.7'
Python38:
python.version: '3.8'

steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(python.version)'
displayName: 'Use Python $(python.version)'

- script: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
displayName: 'Install dependencies'

- script: |
black . --check
isort . --check-only
flake8
displayName: 'static analysis'

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

- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml'
reportDirectory: '$(System.DefaultWorkingDirectory)/**/htmlcov'
- script: |
pytest -vv
displayName: 'pytest'
55 changes: 33 additions & 22 deletions nbqa/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _temp_python_file_for_notebook(notebook, tmpdir):
# Add 3 extra whitespaces because `ipynb` is 3 chars longer than `py`.
temp_python_file = (
Path(tmpdir)
.joinpath(notebook.parent)
.joinpath(notebook.resolve().relative_to(Path.cwd()).parent)
.joinpath(f"{notebook.stem} ")
.with_suffix(".py")
)
Expand All @@ -71,19 +71,15 @@ def _temp_python_file_for_notebook(notebook, tmpdir):
def _replace_full_path_out_err(out, err, temp_python_file, notebook):
"""
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!'
"""
out = out.replace(str(temp_python_file), str(notebook))
err = err.replace(str(temp_python_file), str(notebook))
out = out.replace(str(temp_python_file), str(notebook.resolve()))
err = err.replace(str(temp_python_file), str(notebook.resolve()))

# This next part is necessary to handle cases when `resolve` changes the path.
# I couldn't reproduce this locally, but during CI, on the Windows job, I found
# that VSSADM~1 was changing into VssAdministrator.
out = out.replace(str(temp_python_file.resolve()), str(notebook.resolve()))
err = err.replace(str(temp_python_file.resolve()), str(notebook.resolve()))
return out, err


Expand Down Expand Up @@ -154,28 +150,43 @@ def _replace_tmpdir_references(out, err, tmpdirname, cwd=None):
Examples
--------
>>> out = "rootdir: /tmp/tmpdir\\n"
>>> out = f"rootdir: {os.path.join('tmp', 'tmpdir')}\\n"
>>> err = ""
>>> tmpdirname = "/tmp/tmpdir"
>>> tmpdirname = os.path.join('tmp', 'tmpdir')
>>> cwd = Path("nbQA-dev")
>>> out, err = _replace_tmpdir_references(out, err, tmpdirname, cwd)
>>> out
'rootdir: nbQA-dev\\n'
>>> out.strip(os.linesep)
'rootdir: nbQA-dev'
"""
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
cwd = Path.cwd().resolve()
new_out = os.linesep.join(
[
i if not i.startswith("rootdir: ") else f"rootdir: {str(cwd)}"
for i in out.splitlines()
]
)
new_err = os.linesep.join(
[
i if not i.startswith("rootdir: ") else f"rootdir: {str(cwd)}"
for i in err.splitlines()
]
)
if new_out:
new_out += os.linesep
if new_err:
new_err += os.linesep
return new_out, new_err


def _create_blank_init_files(notebook, tmpdirname):
"""
Replicate local (possibly blank) __init__ files to temporary directory.
"""
parts = notebook.parts
parts = notebook.resolve().relative_to(Path.cwd()).parts
init_files = Path(parts[0]).rglob("__init__.py")
for i in init_files:
Path(tmpdirname).joinpath(i).parent.mkdir(parents=True, exist_ok=True)
Path(tmpdirname).joinpath(i).touch()


Expand Down
30 changes: 0 additions & 30 deletions tests/data/test_isort_works.py

This file was deleted.

9 changes: 6 additions & 3 deletions tests/test_black.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import difflib
import os

import pytest

Expand All @@ -12,8 +13,9 @@ def test_black_works(tmp_notebook_for_testing, capsys):
# check diff
with open(tmp_notebook_for_testing, "r") as handle:
before = handle.readlines()
path = os.path.abspath(os.path.join("tests", "data", "notebook_for_testing.ipynb"))
with pytest.raises(SystemExit):
main(["black", "tests/data/notebook_for_testing.ipynb"])
main(["black", path])
with open(tmp_notebook_for_testing, "r") as handle:
after = handle.readlines()

Expand All @@ -28,6 +30,7 @@ def test_black_works(tmp_notebook_for_testing, capsys):
# check out and err
out, err = capsys.readouterr()
expected_out = ""
expected_err = "reformatted tests/data/notebook_for_testing.ipynb\nAll done! ✨ 🍰 ✨\n1 file reformatted.\n" # noqa
expected_err = f"reformatted {path}{os.linesep}All done! {os.linesep}1 file reformatted.{os.linesep}" # noqa
assert out == expected_out
assert err == expected_err
for i in (0, 2): # haven't figured out how to test the emojis part
assert err.splitlines()[i] == expected_err.splitlines()[i]
11 changes: 9 additions & 2 deletions tests/test_create_blank_init_files.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from pathlib import Path

from nbqa.__main__ import _create_blank_init_files
Expand All @@ -7,6 +8,12 @@ def test_create_blank_init_files(tmpdir):
"""
Check that if a notebook is in current working directory then no init file is made.
"""
_create_blank_init_files(Path("some_notebook.ipynb"), tmpdir)
_create_blank_init_files(
Path(os.path.join("tests", "data", "notebook_for_testing.ipynb")), tmpdir
)
result = list(Path(tmpdir).rglob("__init__.py"))
assert result == []
expected = [
Path(tmpdir).joinpath(os.path.join("tests", "__init__.py")),
Path(tmpdir).joinpath(os.path.join("tests", "data", "__init__.py")),
]
assert result == expected
38 changes: 16 additions & 22 deletions tests/test_doctest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import difflib
import platform
import re
import os
from pathlib import Path
from textwrap import dedent

import pytest

Expand All @@ -27,25 +25,21 @@ def test_pytest_doctest_works(tmp_notebook_for_testing, capsys):

# check out and err
out, err = capsys.readouterr()
expected_out = dedent(
f"""\
============================= test session starts ==============================
platform {platform.system().lower()} -- Python {platform.python_version()}, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: {str(Path.cwd())}
plugins: cov-2.10.0
collected 3 items
tests/data/notebook_for_testing.ipynb . [ 33%]
tests/data/notebook_for_testing_copy.ipynb . [ 66%]
tests/data/notebook_starting_with_md.ipynb . [100%]
============================== 3 passed in ===============================
""" # noqa
)
expected_err = ""
assert f"rootdir: {str(Path.cwd())}" in out.splitlines()[2]
assert any(
os.path.join("tests", "data", "notebook_for_testing.ipynb") in i
for i in out.splitlines()
)
assert any(
os.path.join("tests", "data", "notebook_for_testing_copy.ipynb") in i
for i in out.splitlines()
)
assert any(
os.path.join("tests", "data", "notebook_starting_with_md.ipynb") in i
for i in out.splitlines()
)

print(out.splitlines())

# remove references to how many seconds the test took
out = re.sub(r"(?<=passed in) \d+\.\d+s", "", out)
err = re.sub(r"(?<=passed in) \d+\.\d+s", "", err)
assert out == expected_out
assert err == expected_err

0 comments on commit 35a0803

Please sign in to comment.