Skip to content

Commit abc3c5b

Browse files
authored
Merge pull request #1 from Nixtla/tests
[tests] tests for the parser
2 parents 559c0c5 + f250e4d commit abc3c5b

13 files changed

+644
-23
lines changed

.github/workflows/pytest.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: pytest
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
11+
jobs:
12+
run-tests:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Clone repo
16+
uses: actions/checkout@v4
17+
18+
- name: Setup python
19+
uses: actions/setup-python@v4
20+
with:
21+
python-version: 3.11
22+
cache: 'pip'
23+
24+
- name: Install dependencies
25+
run: |
26+
pip install -r requirements.txt
27+
28+
- name: Run tests
29+
run: pytest

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# mkdocstring-parser
22

3-
This repo creates a simple parser for mkdocstrings. The idea is simple, given a `mkdocstrings` signature block, replace it with it rendered markdown in-place
3+
This repo creates a simple parser for mkdocstrings. The idea is simple, given
4+
a `mkdocstrings` signature block, replace it with it rendered markdown in-place.
5+
6+
To view the complete guide on generating Nixtlaverse documentation, click [here](https://www.notion.so/nixtla/Env-Setup-1aa34e7ecc8c804096f7d0915aa4f2d5?source=copy_link#2a334e7ecc8c8006901aed0eb6ebd2f0)
47

58
## example
69

parser.py

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -82,37 +82,41 @@ def generate_documentation(self, module_path: str, options: Dict[str, Any]) -> s
8282
except:
8383
pass # Fall back to griffe's detection
8484

85+
# Determine which parser to use based on docstring_style option
86+
docstring_style = options.get("docstring_style", "google")
87+
88+
# Map docstring style to parser function
89+
parser_map = {
90+
"google": griffe.parse_google,
91+
"numpy": griffe.parse_numpy,
92+
"sphinx": griffe.parse_sphinx,
93+
"auto": griffe.parse_auto,
94+
}
95+
96+
parser_func = parser_map.get(docstring_style, griffe.parse_google)
97+
8598
if obj.docstring:
86-
# Force parsing with Google parser to get structured sections
87-
obj.docstring.parsed = griffe.parse_google(obj.docstring)
99+
# Parse with the appropriate parser to get structured sections
100+
obj.docstring.parsed = parser_func(obj.docstring)
88101

89102
# Handle different object types
90103
if hasattr(obj, "members"):
91104
# This is a class or module - parse docstrings for all methods/functions
92105
for member_name, member in obj.members.items():
93106
if member.docstring:
94-
member.docstring.parsed = griffe.parse_google(member.docstring)
107+
member.docstring.parsed = parser_func(member.docstring)
95108

96-
# Create ConfigDict with the options
97-
# Adjust default options based on object type
98-
if hasattr(obj, "kind") and obj.kind.value == "function":
99-
# Configuration for functions
100-
default_options = {
101-
"docstring_section_style": "table",
102-
"heading_level": 3,
103-
"show_root_heading": True,
104-
"show_source": True,
105-
"show_signature": True,
106-
}
107-
else:
109+
default_options = {
110+
"docstring_section_style": "table",
111+
"heading_level": 3,
112+
"show_root_heading": True,
113+
"show_source": True,
114+
}
115+
116+
117+
if hasattr(obj, "kind") and obj.kind.value != "function":
108118
# Configuration for classes and modules
109-
default_options = {
110-
"docstring_section_style": "table",
111-
"heading_level": 3,
112-
"show_root_heading": True,
113-
"show_source": True,
114-
"summary": {"functions": False},
115-
}
119+
default_options["summary"] = {"functions": False}
116120

117121
default_options.update(options)
118122
config = ConfigDict(**default_options)

pytest.ini

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[pytest]
2+
testpaths = tests
3+
addopts = -vv
4+
markers =
5+
datasets: tests for datasetsforecast

requirements.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
griffe2md
2+
rich
3+
pyyaml
4+
neuralforecast
5+
mlforecast[dask]
6+
statsforecast
7+
hierarchicalforecast
8+
nixtla
9+
coreforecast
10+
utilsforecast
11+
datasetsforecast
12+
pytest

tests/conftest.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import os
2+
import sys
3+
4+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
5+
from parser import MkDocstringsParser
6+
7+
import pytest
8+
9+
10+
@pytest.fixture(scope="module")
11+
def setup_parser():
12+
parser = MkDocstringsParser()
13+
yield parser

tests/test_coreforecast.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
def test_regular_fn(setup_parser):
2+
parser = setup_parser
3+
regular_fn = """::: coreforecast.differences.num_diffs"""
4+
output = parser.process_markdown(regular_fn)
5+
6+
assert output == """### `num_diffs`
7+
8+
```python
9+
num_diffs(x, max_d=1)
10+
```
11+
12+
Find the optimal number of differences
13+
14+
**Parameters:**
15+
16+
Name | Type | Description | Default
17+
---- | ---- | ----------- | -------
18+
`x` | <code>[ndarray](#numpy.ndarray)</code> | Array with the time series. | *required*
19+
`max_d` | <code>[int](#int)</code> | Maximum number of differences to consider. Defaults to 1. | <code>1</code>
20+
21+
**Returns:**
22+
23+
Name | Type | Description
24+
---- | ---- | -----------
25+
`int` | <code>[int](#int)</code> | Optimal number of differences.
26+
"""
27+
28+
def test_fn_w_decorator(setup_parser):
29+
parser = setup_parser
30+
fn_w_decorator = """::: coreforecast.expanding.expanding_mean"""
31+
output = parser.process_markdown(fn_w_decorator)
32+
assert output == """### `expanding_mean`
33+
34+
```python
35+
expanding_mean(x)
36+
```
37+
38+
Compute the expanding_mean of the input array.
39+
40+
**Parameters:**
41+
42+
Name | Type | Description | Default
43+
---- | ---- | ----------- | -------
44+
`x` | <code>np.ndarray</code> | Input array. | *required*
45+
46+
**Returns:**
47+
48+
Type | Description
49+
---- | -----------
50+
| np.ndarray: Array with the expanding statistic
51+
"""

tests/test_datasetsforecast.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import pytest
2+
3+
4+
@pytest.mark.datasets
5+
def test_yearly_dataclass(setup_parser):
6+
fn = "::: datasetsforecast.m3.Yearly"
7+
rendered = setup_parser.process_markdown(fn)
8+
9+
assert rendered == """### `Yearly`
10+
11+
```python
12+
Yearly(seasonality=1, horizon=6, freq='Y', sheet_name='M3Year', name='Yearly', n_ts=645)
13+
```
14+
15+
#### `Yearly.freq`
16+
17+
```python
18+
freq: str = 'Y'
19+
```
20+
21+
#### `Yearly.horizon`
22+
23+
```python
24+
horizon: int = 6
25+
```
26+
27+
#### `Yearly.n_ts`
28+
29+
```python
30+
n_ts: int = 645
31+
```
32+
33+
#### `Yearly.name`
34+
35+
```python
36+
name: str = 'Yearly'
37+
```
38+
39+
#### `Yearly.seasonality`
40+
41+
```python
42+
seasonality: int = 1
43+
```
44+
45+
#### `Yearly.sheet_name`
46+
47+
```python
48+
sheet_name: str = 'M3Year'
49+
```
50+
"""
51+
52+
@pytest.mark.datasets
53+
def test_download_file(setup_parser):
54+
fn = """::: datasetsforecast.utils.download_file
55+
handler: python
56+
options:
57+
docstring_style: numpy
58+
heading_level: 3
59+
show_root_heading: true
60+
show_source: true"""
61+
rendered = setup_parser.process_markdown(fn)
62+
63+
assert rendered == """### `download_file`
64+
65+
```python
66+
download_file(directory, source_url, decompress=False)
67+
```
68+
69+
Download data from source_ulr inside directory.
70+
71+
**Parameters:**
72+
73+
Name | Type | Description | Default
74+
---- | ---- | ----------- | -------
75+
`directory` | <code>[str](#str)</code> | Custom directory where data will be downloaded. | *required*
76+
`source_url` | <code>[str](#str)</code> | URL where data is hosted. | *required*
77+
`decompress` | <code>[bool](#bool)</code> | Wheter decompress downloaded file. Default False. | <code>False</code>
78+
"""

0 commit comments

Comments
 (0)