Skip to content

Commit

Permalink
Merge pull request #80 from nschloe/importorskip
Browse files Browse the repository at this point in the history
Importorskip
  • Loading branch information
nschloe authored Apr 18, 2022
2 parents a749494 + c109ded commit 2b58b11
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 2 deletions.
2 changes: 1 addition & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2020-2021 Nico Schlömer
Copyright (c) 2020-2022 Nico Schlömer

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
[![PyPI pyversions](https://img.shields.io/pypi/pyversions/pytest-codeblocks.svg?style=flat-square)](https://pypi.org/project/pytest-codeblocks/)
[![GitHub stars](https://img.shields.io/github/stars/nschloe/pytest-codeblocks.svg?style=flat-square&logo=github&label=Stars&logoColor=white)](https://github.com/nschloe/pytest-codeblocks)
[![Downloads](https://pepy.tech/badge/pytest-codeblocks/month?style=flat-square)](https://pepy.tech/project/pytest-codeblocks)

<!--[![PyPi downloads](https://img.shields.io/pypi/dm/pytest-codeblocks.svg?style=flat-square)](https://pypistats.org/packages/pytest-codeblocks)-->

[![gh-actions](https://img.shields.io/github/workflow/status/nschloe/pytest-codeblocks/ci?style=flat-square)](https://github.com/nschloe/pytest-codeblocks/actions?query=workflow%3Aci)
Expand Down Expand Up @@ -63,14 +64,23 @@ dolor sit amet.
````

Conditionally skipping code blocks works with `skipif`, e.g.,

```markdown
<!--pytest-codeblocks:skipif(sys.version_info <= (3, 7))-->
```

You can skip code blocks on import errors with

```markdown
<!--pytest-codeblocks:importorskip(sympy)-->
```

Skip the entire file by putting

```markdown
<!--pytest-codeblocks:skipfile-->
```

in the first line.

#### Merging code blocks
Expand Down
2 changes: 1 addition & 1 deletion src/pytest_codeblocks/__about__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.14.0"
__version__ = "0.15.0"
18 changes: 18 additions & 0 deletions src/pytest_codeblocks/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class CodeBlock:
expect_exception: bool = False
skip: bool = False
skipif: str | None = None
importorskip: str | None = None


def extract_from_file(
Expand Down Expand Up @@ -99,6 +100,7 @@ def extract_from_buffer(f, max_num_lines: int = 10000) -> list[CodeBlock]:
+ "but block already has expected_output."
)
out[-1].expected_output = "".join(code_block)

elif keyword == "cont":
if len(out) == 0:
raise RuntimeError(
Expand All @@ -111,8 +113,10 @@ def extract_from_buffer(f, max_num_lines: int = 10000) -> list[CodeBlock]:
out[-1].expected_output,
out[-1].expect_exception,
)

elif keyword == "skip":
out.append(CodeBlock("".join(code_block), lineno, syntax, skip=True))

elif keyword.startswith("skipif"):
m = re.match(r"skipif\((.*)\)", keyword)
if m is None:
Expand All @@ -122,12 +126,26 @@ def extract_from_buffer(f, max_num_lines: int = 10000) -> list[CodeBlock]:
out.append(
CodeBlock("".join(code_block), lineno, syntax, skipif=m.group(1))
)

elif keyword.startswith("importorskip"):
m = re.match(r"importorskip\((.*)\)", keyword)
if m is None:
raise RuntimeError(
"pytest-codeblocks: Expected importorskip(some-module)"
)
out.append(
CodeBlock(
"".join(code_block), lineno, syntax, importorskip=m.group(1)
)
)

elif keyword in ["expect-exception", "expect-error"]:
out.append(
CodeBlock(
"".join(code_block), lineno, syntax, expect_exception=True
)
)

else:
raise RuntimeError(f'Unknown pytest-codeblocks keyword "{keyword}."')

Expand Down
6 changes: 6 additions & 0 deletions src/pytest_codeblocks/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ def runtest(self):
if eval(self.obj.skipif):
pytest.skip()

if self.obj.importorskip is not None:
try:
__import__(self.obj.importorskip)
except (ImportError, ModuleNotFoundError):
pytest.skip()

if self.obj.syntax == "python":
if self.obj.expect_exception:
with pytest.raises(Exception):
Expand Down
28 changes: 28 additions & 0 deletions tests/test_skipif.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,31 @@ def test_skipif_expected_output(testdir):
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)


def test_importorskip(testdir):
string = """
Lorem ipsum
<!--pytest-codeblocks:importorskip(some_nonexistent_module)-->
```python
print(1 + 3)
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(skipped=1)

string = """
Lorem ipsum
<!--pytest-codeblocks:importorskip(sys)-->
```python
print(1 + 3)
```
"""
testdir.makefile(".md", string)
result = testdir.runpytest("--codeblocks")
result.assert_outcomes(passed=1)

0 comments on commit 2b58b11

Please sign in to comment.