pytest-codeblock 0.1.6__tar.gz → 0.1.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (19) hide show
  1. {pytest_codeblock-0.1.6/pytest_codeblock.egg-info → pytest_codeblock-0.1.8}/PKG-INFO +2 -3
  2. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8}/README.rst +1 -2
  3. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8}/pyproject.toml +6 -4
  4. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8/src}/pytest_codeblock/__init__.py +1 -1
  5. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8/src}/pytest_codeblock/rst.py +10 -4
  6. pytest_codeblock-0.1.8/src/pytest_codeblock/tests/__init__.py +0 -0
  7. pytest_codeblock-0.1.8/src/pytest_codeblock/tests/test_pytest_codeblock.py +108 -0
  8. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8/src/pytest_codeblock.egg-info}/PKG-INFO +2 -3
  9. pytest_codeblock-0.1.8/src/pytest_codeblock.egg-info/SOURCES.txt +16 -0
  10. pytest_codeblock-0.1.6/pytest_codeblock.egg-info/SOURCES.txt +0 -14
  11. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8}/LICENSE +0 -0
  12. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8}/setup.cfg +0 -0
  13. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8/src}/pytest_codeblock/collector.py +0 -0
  14. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8/src}/pytest_codeblock/constants.py +0 -0
  15. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8/src}/pytest_codeblock/md.py +0 -0
  16. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8/src}/pytest_codeblock.egg-info/dependency_links.txt +0 -0
  17. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8/src}/pytest_codeblock.egg-info/entry_points.txt +0 -0
  18. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8/src}/pytest_codeblock.egg-info/requires.txt +0 -0
  19. {pytest_codeblock-0.1.6 → pytest_codeblock-0.1.8/src}/pytest_codeblock.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytest-codeblock
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: Pytest plugin to collect and test code blocks in reStructuredText and Markdown files.
5
5
  Author-email: Artur Barseghyan <artur.barseghyan@gmail.com>
6
6
  Maintainer-email: Artur Barseghyan <artur.barseghyan@gmail.com>
@@ -128,8 +128,7 @@ Features
128
128
  - **Grouping by name**: Split a single example across multiple code blocks;
129
129
  the plugin concatenates them into one test.
130
130
  - **Pytest markers support**: Add existing or custom `pytest`_ markers
131
- to the code blocks and add hook into the tests life-cycle
132
- using ``conftest.py``.
131
+ to the code blocks and hook into the tests life-cycle using ``conftest.py``.
133
132
 
134
133
  Prerequisites
135
134
  =============
@@ -69,8 +69,7 @@ Features
69
69
  - **Grouping by name**: Split a single example across multiple code blocks;
70
70
  the plugin concatenates them into one test.
71
71
  - **Pytest markers support**: Add existing or custom `pytest`_ markers
72
- to the code blocks and add hook into the tests life-cycle
73
- using ``conftest.py``.
72
+ to the code blocks and hook into the tests life-cycle using ``conftest.py``.
74
73
 
75
74
  Prerequisites
76
75
  =============
@@ -2,7 +2,7 @@
2
2
  name = "pytest-codeblock"
3
3
  description = "Pytest plugin to collect and test code blocks in reStructuredText and Markdown files."
4
4
  readme = "README.rst"
5
- version = "0.1.6"
5
+ version = "0.1.8"
6
6
  requires-python = ">=3.9"
7
7
  dependencies = [
8
8
  "pytest",
@@ -85,9 +85,10 @@ pytest_codeblock = "pytest_codeblock"
85
85
 
86
86
  [tool.setuptools]
87
87
  # No single-file modules; we use packages.find below
88
+ package-dir = {"" = "src"}
88
89
 
89
90
  [tool.setuptools.packages.find]
90
- where = ["."]
91
+ where = ["src"]
91
92
  include = ["pytest_codeblock", "pytest_codeblock.*"]
92
93
 
93
94
  [build-system]
@@ -119,7 +120,7 @@ lint.ignore = [
119
120
  ]
120
121
  # Enable auto-fix for formatting and import sorting
121
122
  fix = true
122
- src = ["pytest_codeblock"]
123
+ src = ["src/pytest_codeblock"]
123
124
  exclude = [
124
125
  ".bzr",
125
126
  ".direnv",
@@ -155,7 +156,7 @@ known-third-party = []
155
156
  [tool.doc8]
156
157
  ignore-path = [
157
158
  "docs/requirements.txt",
158
- "pytest-codeblock.egg-info/SOURCES.txt",
159
+ "src/pytest-codeblock.egg-info/SOURCES.txt",
159
160
  ]
160
161
 
161
162
  [tool.pytest.ini_options]
@@ -183,6 +184,7 @@ testpaths = [
183
184
  "**/*.md",
184
185
  ]
185
186
  pythonpath = [
187
+ "src",
186
188
  "examples/md_example",
187
189
  "examples/rst_example",
188
190
  ]
@@ -2,7 +2,7 @@ from .md import MarkdownFile
2
2
  from .rst import RSTFile
3
3
 
4
4
  __title__ = "pytest-codeblock"
5
- __version__ = "0.1.6"
5
+ __version__ = "0.1.8"
6
6
  __author__ = "Artur Barseghyan <artur.barseghyan@gmail.com>"
7
7
  __copyright__ = "2025 Artur Barseghyan"
8
8
  __license__ = "MIT"
@@ -2,7 +2,7 @@ import re
2
2
  import textwrap
3
3
  import traceback
4
4
  from pathlib import Path
5
- from typing import Optional
5
+ from typing import Optional, Union
6
6
 
7
7
  import pytest
8
8
 
@@ -21,7 +21,7 @@ __all__ = (
21
21
 
22
22
 
23
23
  def resolve_literalinclude_path(
24
- base_dir: Path,
24
+ base_dir: Union[str, Path],
25
25
  include_path: str,
26
26
  ) -> Optional[str]:
27
27
  """
@@ -29,12 +29,18 @@ def resolve_literalinclude_path(
29
29
  Returns None if the file doesn't exist.
30
30
  """
31
31
  _include_path = Path(include_path)
32
+
33
+ # If `include_path` is already absolute or relative and exists, done
32
34
  if _include_path.exists():
33
35
  return str(_include_path.resolve())
34
36
 
35
- _base_dir = Path(base_dir.dirname) if base_dir.is_file() else base_dir
37
+ # If base_path is a file, switch to its parent directory
38
+ _base_path = Path(base_dir)
39
+ if _base_path.is_file():
40
+ _base_path = _base_path.parent
41
+
36
42
  try:
37
- full_path = _base_dir / include_path
43
+ full_path = _base_path / include_path
38
44
  if full_path.exists():
39
45
  return str(full_path.resolve())
40
46
  except Exception:
@@ -0,0 +1,108 @@
1
+ from pytest_codeblock.collector import CodeSnippet, group_snippets
2
+ from pytest_codeblock.md import parse_markdown
3
+ from pytest_codeblock.rst import (
4
+ get_literalinclude_content,
5
+ parse_rst,
6
+ resolve_literalinclude_path,
7
+ )
8
+
9
+
10
+ def test_group_snippets_merges_named():
11
+ # Two snippets with the same name should be combined
12
+ sn1 = CodeSnippet(name="foo", code="a=1", line=1, marks=["codeblock"])
13
+ sn2 = CodeSnippet(name="foo", code="b=2", line=2, marks=["codeblock", "m"])
14
+ combined = group_snippets([sn1, sn2])
15
+ assert len(combined) == 1
16
+ cs = combined[0]
17
+ assert cs.name == "foo"
18
+ # Both code parts should appear
19
+ assert "a=1" in cs.code
20
+ assert "b=2" in cs.code
21
+ # Marks should accumulate
22
+ assert "m" in cs.marks
23
+
24
+
25
+ def test_group_snippets_different_names():
26
+ # Snippets with different names are not grouped
27
+ sn1 = CodeSnippet(name="foo", code="x=1", line=1)
28
+ sn2 = CodeSnippet(name="bar", code="y=2", line=2)
29
+ combined = group_snippets([sn1, sn2])
30
+ assert len(combined) == 2
31
+ assert combined[0].name.startswith("foo")
32
+ assert combined[1].name.startswith("bar")
33
+
34
+
35
+ def test_parse_markdown_simple():
36
+ text = """
37
+ ```python name=test_example
38
+ x=1
39
+ assert x==1
40
+ ```"""
41
+ snippets = parse_markdown(text)
42
+ assert len(snippets) == 1
43
+ sn = snippets[0]
44
+ assert sn.name == "test_example"
45
+ assert "x=1" in sn.code
46
+
47
+
48
+ def test_parse_markdown_with_pytestmark():
49
+ text = """
50
+ <!-- pytestmark: django_db -->
51
+ ```python name=test_db
52
+ from django.db import models
53
+ ```"""
54
+ snippets = parse_markdown(text)
55
+ assert len(snippets) == 1
56
+ sn = snippets[0]
57
+ # Should include both default and django_db marks
58
+ assert "django_db" in sn.marks
59
+ assert "codeblock" in sn.marks
60
+
61
+
62
+ def test_resolve_literalinclude_and_content(tmp_path):
63
+ base = tmp_path / "dir"
64
+ base.mkdir()
65
+ file = base / "a.py"
66
+ file.write_text("print('hello')")
67
+ # Absolute path resolution
68
+ abs_path = resolve_literalinclude_path(base, str(file))
69
+ assert abs_path == str(file.resolve())
70
+ # Relative path resolution
71
+ rel_path = resolve_literalinclude_path(base, "a.py")
72
+ assert rel_path == str(file.resolve())
73
+ # Content read
74
+ content = get_literalinclude_content(str(file))
75
+ assert content == "print('hello')"
76
+
77
+
78
+ def test_parse_rst_simple(tmp_path):
79
+ # Basic code-block directive
80
+ rst = """
81
+ .. code-block:: python
82
+ :name: test_simple
83
+
84
+ a=2
85
+ assert a==2
86
+ """
87
+ snippets = parse_rst(rst, tmp_path)
88
+ assert len(snippets) == 1
89
+ sn = snippets[0]
90
+ assert sn.name == "test_simple"
91
+ assert "a=2" in sn.code
92
+
93
+
94
+ def test_parse_rst_literalinclude(tmp_path):
95
+ # Create an external file to include
96
+ include_dir = tmp_path / "inc"
97
+ include_dir.mkdir()
98
+ target = include_dir / "foo.py"
99
+ target.write_text("z=3\nassert z==3")
100
+ rst = f"""
101
+ .. literalinclude:: {target.name}
102
+ :name: test_li
103
+ """
104
+ snippets = parse_rst(rst, include_dir)
105
+ assert len(snippets) == 1
106
+ sn = snippets[0]
107
+ assert sn.name == "test_li"
108
+ assert "z=3" in sn.code
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytest-codeblock
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: Pytest plugin to collect and test code blocks in reStructuredText and Markdown files.
5
5
  Author-email: Artur Barseghyan <artur.barseghyan@gmail.com>
6
6
  Maintainer-email: Artur Barseghyan <artur.barseghyan@gmail.com>
@@ -128,8 +128,7 @@ Features
128
128
  - **Grouping by name**: Split a single example across multiple code blocks;
129
129
  the plugin concatenates them into one test.
130
130
  - **Pytest markers support**: Add existing or custom `pytest`_ markers
131
- to the code blocks and add hook into the tests life-cycle
132
- using ``conftest.py``.
131
+ to the code blocks and hook into the tests life-cycle using ``conftest.py``.
133
132
 
134
133
  Prerequisites
135
134
  =============
@@ -0,0 +1,16 @@
1
+ LICENSE
2
+ README.rst
3
+ pyproject.toml
4
+ src/pytest_codeblock/__init__.py
5
+ src/pytest_codeblock/collector.py
6
+ src/pytest_codeblock/constants.py
7
+ src/pytest_codeblock/md.py
8
+ src/pytest_codeblock/rst.py
9
+ src/pytest_codeblock.egg-info/PKG-INFO
10
+ src/pytest_codeblock.egg-info/SOURCES.txt
11
+ src/pytest_codeblock.egg-info/dependency_links.txt
12
+ src/pytest_codeblock.egg-info/entry_points.txt
13
+ src/pytest_codeblock.egg-info/requires.txt
14
+ src/pytest_codeblock.egg-info/top_level.txt
15
+ src/pytest_codeblock/tests/__init__.py
16
+ src/pytest_codeblock/tests/test_pytest_codeblock.py
@@ -1,14 +0,0 @@
1
- LICENSE
2
- README.rst
3
- pyproject.toml
4
- pytest_codeblock/__init__.py
5
- pytest_codeblock/collector.py
6
- pytest_codeblock/constants.py
7
- pytest_codeblock/md.py
8
- pytest_codeblock/rst.py
9
- pytest_codeblock.egg-info/PKG-INFO
10
- pytest_codeblock.egg-info/SOURCES.txt
11
- pytest_codeblock.egg-info/dependency_links.txt
12
- pytest_codeblock.egg-info/entry_points.txt
13
- pytest_codeblock.egg-info/requires.txt
14
- pytest_codeblock.egg-info/top_level.txt