Skip to content

Commit 967c63a

Browse files
authored
Test Python docstring in markdown files (#38)
* Test Python docstring in markdown files And experiment with tested snippets * Use two CLI snippets * Appease flake8
1 parent fc0a73d commit 967c63a

File tree

6 files changed

+72
-9
lines changed

6 files changed

+72
-9
lines changed

conftest.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import pytest
2+
3+
from fio_planet import snuggs
4+
5+
6+
@pytest.fixture(autouse=True)
7+
def add_snuggs(doctest_namespace):
8+
doctest_namespace["snuggs"] = snuggs

docs/expressions.md

+28-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,15 @@ includes:
1919
Expressions are evaluated by `fio_planet.features.snuggs.eval()`. Let's look at
2020
some examples using that function.
2121

22-
Note: the outer parentheses are not optional within `snuggs.eval()`.
22+
!!! note
23+
24+
The outer parentheses are not optional within `snuggs.eval()`.
25+
26+
!!! note
27+
28+
`snuggs.eval()` does not use Python's builtin `eval()` but isn't intended
29+
to be a secure computing environment. Expressions which access the
30+
computer's filesystem and create new processes are possible.
2331

2432
## Builtin Python functions
2533

@@ -28,27 +36,31 @@ Note: the outer parentheses are not optional within `snuggs.eval()`.
2836
```python
2937
>>> snuggs.eval('(bool 0)')
3038
False
39+
3140
```
3241

3342
`range`:
3443

3544
```python
3645
>>> snuggs.eval('(range 1 4)')
3746
range(1, 4)
47+
3848
```
3949

4050
`list`:
4151

4252
```python
4353
>>> snuggs.eval('(list (range 1 4))')
4454
[1, 2, 3]
55+
4556
```
4657

4758
Values can be bound to names for use in expressions.
4859

4960
```python
5061
>>> snuggs.eval('(list (range start stop))', start=0, stop=5)
5162
[0, 1, 2, 3, 4]
63+
5264
```
5365

5466
## Itertools functions
@@ -58,6 +70,7 @@ Here's an example of using `itertools.repeat()`.
5870
```python
5971
>>> snuggs.eval('(list (repeat "*" times))', times=6)
6072
['*', '*', '*', '*', '*', '*']
73+
6174
```
6275

6376
## Shapely functions
@@ -67,13 +80,15 @@ Here's an expression that evaluates to a Shapely Point instance.
6780
```python
6881
>>> snuggs.eval('(Point 0 0)')
6982
<POINT (0 0)>
83+
7084
```
7185

7286
The expression below evaluates to a MultiPoint instance.
7387

7488
```python
7589
>>> snuggs.eval('(union (Point 0 0) (Point 1 1))')
7690
<MULTIPOINT (0 0, 1 1)>
91+
7792
```
7893

7994
## Functions specific to fio-planet
@@ -91,20 +106,23 @@ geometries.
91106
<GEOMETRYCOLLECTION (POINT (0 0), POINT (1 1))>
92107
>>> snuggs.eval('(list (dump (collect (Point 0 0) (Point 1 1))))')
93108
[<POINT (0 0)>, <POINT (1 1)>]
109+
94110
```
95111

96112
The `identity` function returns its single argument.
97113

98114
```python
99115
>>> snuggs.eval('(identity 42)')
100116
42
117+
101118
```
102119

103120
To count the number of vertices in a geometry, use `vertex_count`.
104121

105122
```python
106123
>>> snuggs.eval('(vertex_count (Point 0 0))')
107124
1
125+
108126
```
109127

110128
The `area`, `buffer`, `distance`, `length`, `simplify`, and `set_precision`
@@ -119,6 +137,7 @@ longitude and latitude degrees, by a given distance in meters.
119137
```python
120138
>>> snuggs.eval('(buffer (Point 0 0) :distance 100)')
121139
<POLYGON ((0.001 0, 0.001 0, 0.001 0, 0.001 0, 0.001 -0.001, 0.001 -0.001, 0...>
140+
122141
```
123142

124143
The `area` and `length` of this polygon have units of square meter and meter.
@@ -128,13 +147,15 @@ The `area` and `length` of this polygon have units of square meter and meter.
128147
31214.451487413342
129148
>>> snuggs.eval('(length (buffer (Point 0 0) :distance 100))')
130149
627.3096977558143
150+
131151
```
132152

133153
The `distance` between two geometries is in meters.
134154

135155
```python
136156
>>> snuggs.eval('(distance (Point 0 0) (Point 0.1 0.1))')
137157
15995.164946207413
158+
138159
```
139160

140161
A geometry can be simplified to a tolerance value in meters using `simplify`.
@@ -144,6 +165,7 @@ There are more examples of this function under
144165
```python
145166
>>> snuggs.eval('(simplify (buffer (Point 0 0) :distance 100) :tolerance 100)')
146167
<POLYGON ((0.001 0, 0 -0.001, -0.001 0, 0 0.001, 0.001 0))>
168+
147169
```
148170

149171
The `set_precision` function snaps a geometry to a fixed precision grid with a
@@ -152,23 +174,24 @@ size in meters.
152174
```python
153175
>>> snuggs.eval('(set_precision (Point 0.001 0.001) :grid_size 500)')
154176
<POINT (0 0)>
177+
155178
```
156179

157180
## Feature and geometry context for expressions
158181

159182
`fio-filter` and `fio-map` evaluate expressions in the context of a GeoJSON
160183
feature and its geometry attribute. These are named `f` and `g`. For example,
161-
here is an expression that tests whether the input feature is within 50 meters
162-
of the given point.
184+
here is an expression that tests whether the input feature is within 62.5
185+
kilometers of the given point.
163186

164187
```lisp
165-
<= (distance g (Point -105.0 39.753056)) 50.0
188+
--8<-- "tests/test_cli.py:filter"
166189
```
167190

168191
`fio-reduce` evaluates expressions in the context of the sequence of all input
169192
geometries, named `c`. For example, this expression dissolves input
170193
geometries using Shapely's `unary_union`.
171194

172195
```lisp
173-
unary_union c
196+
--8<-- "tests/test_cli.py:reduce"
174197
```

mkdocs.yml

+3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ nav:
6868
- "Topics": 'topics'
6969

7070
markdown_extensions:
71+
- pymdownx.inlinehilite
72+
- pymdownx.snippets:
73+
dedent_subsections: True
7174
- pymdownx.highlight
7275
- pymdownx.superfences
7376
- mkdocs-click

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,4 @@ filterwarnings = [
5353
"ignore:.*pkg_resources is deprecated as an API",
5454
"ignore:.*module \\'sre_constants\\' is deprecated",
5555
]
56+
doctest_optionflags = "NORMALIZE_WHITESPACE"

tests/test_cli.py

+31-3
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,22 @@ def test_map_count():
2525
with open("tests/data/trio.seq") as seq:
2626
data = seq.read()
2727

28+
# Define our map arg using a mkdocs snippet.
29+
arg = """
30+
--8<-- [start:map]
31+
centroid (buffer g 1.0)
32+
--8<-- [end:map]
33+
""".splitlines()[
34+
2
35+
].strip()
36+
2837
runner = CliRunner()
2938
result = runner.invoke(
3039
main_group,
31-
["map", "centroid (buffer g 1.0)"],
40+
["map", arg], # "centroid (buffer g 1.0)"],
3241
input=data,
3342
)
43+
3444
assert result.exit_code == 0
3545
assert result.output.count('"type": "Point"') == 3
3646

@@ -56,8 +66,17 @@ def test_reduce_union():
5666
with open("tests/data/trio.seq") as seq:
5767
data = seq.read()
5868

69+
# Define our reduce command using a mkdocs snippet.
70+
arg = """
71+
--8<-- [start:reduce]
72+
unary_union c
73+
--8<-- [end:reduce]
74+
""".splitlines()[
75+
2
76+
].strip()
77+
5978
runner = CliRunner()
60-
result = runner.invoke(main_group, ["reduce", "unary_union c"], input=data)
79+
result = runner.invoke(main_group, ["reduce", arg], input=data)
6180
assert result.exit_code == 0
6281
assert result.output.count('"type": "Polygon"') == 1
6382
assert result.output.count('"type": "LineString"') == 1
@@ -88,10 +107,19 @@ def test_filter():
88107
with open("tests/data/trio.seq") as seq:
89108
data = seq.read()
90109

110+
# Define our reduce command using a mkdocs snippet.
111+
arg = """
112+
--8<-- [start:filter]
113+
< (distance g (Point 4 43)) 62.5E3
114+
--8<-- [end:filter]
115+
""".splitlines()[
116+
2
117+
].strip()
118+
91119
runner = CliRunner()
92120
result = runner.invoke(
93121
main_group,
94-
["filter", "< (distance g (Point 4 43)) 62.5E3"],
122+
["filter", arg],
95123
input=data,
96124
catch_exceptions=False,
97125
)

tox.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ envlist =
77
deps =
88
pytest-cov
99
commands =
10-
python -m pytest -v --cov fio_planet --cov-report term-missing --pdb
10+
python -m pytest -v --cov fio_planet --cov-report term-missing --doctest-glob="*.md"
1111

1212
[gh-actions]
1313
python =

0 commit comments

Comments
 (0)