Skip to content

Commit 9ad727c

Browse files
mango-dbi80and
andauthored
DOP-1148: Improve string-handling (#172)
* Import Protocol from typing_extensions to fix py3.7 * Bump to v0.4.11 * DOP-1148: Improve string handling * DOP-1148: Update Changelog * DOP-1148: Add writer feedback * DOP-1148: Reconfigure string-handling failures * DOP-1148: Remove uncallable diagnostics, add parser test * DOP-1148: Correct formatting errors Co-authored-by: Andrew Aldridge <[email protected]>
1 parent 0d5b755 commit 9ad727c

File tree

6 files changed

+63
-23
lines changed

6 files changed

+63
-23
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
- Support additional ordered list labels (DOP-1129)
1414
- Support ordered list "start" attribute (DOP-1210)
1515

16+
### Changed
17+
18+
- Improve string-handling in spec-parser (DOP-1148).
19+
1620
## [v0.4.11] - 2020-06-22
1721

1822
### Fixed

snooty/rstspec.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ example = """.. include:: ${1:/includes/file.rst}
167167
[directive.literalinclude]
168168
help = """Include a file as a block of code."""
169169
inherit = "include"
170-
options.start-after = "linenos"
171-
options.end-before = "linenos"
170+
options.start-after = "string"
171+
options.end-before = "string"
172172
options.linenos = "flag"
173173
options.copyable = "boolean"
174174
options.language = "string"

snooty/specparser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,13 @@ class RefRoleType:
108108
VALIDATORS: Dict[PrimitiveType, Callable[[Any], Any]] = {
109109
PrimitiveType.integer: int,
110110
PrimitiveType.nonnegative_integer: docutils.parsers.rst.directives.nonnegative_int,
111-
PrimitiveType.path: str,
111+
PrimitiveType.path: util.option_string,
112112
PrimitiveType.uri: docutils.parsers.rst.directives.uri,
113-
PrimitiveType.string: str,
113+
PrimitiveType.string: util.option_string,
114114
PrimitiveType.length: docutils.parsers.rst.directives.length_or_percentage_or_unitless,
115115
PrimitiveType.boolean: util.option_bool,
116116
PrimitiveType.flag: util.option_flag,
117-
PrimitiveType.linenos: str,
117+
PrimitiveType.linenos: util.option_string,
118118
}
119119

120120
#: Option types can be a primitive type (PrimitiveType), an enum

snooty/test_parser.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,19 @@ def test_literalinclude() -> None:
384384
assert len(diagnostics) == 1
385385
assert isinstance(diagnostics[0], DocUtilsParseError)
386386

387+
# Test poorly specified arbitrary string option
388+
page, diagnostics = parse_rst(
389+
parser,
390+
path,
391+
"""
392+
.. literalinclude:: /test_parser/includes/sample_code.py
393+
:start-after:
394+
""",
395+
)
396+
page.finish(diagnostics)
397+
assert len(diagnostics) == 1
398+
assert isinstance(diagnostics[0], DocUtilsParseError)
399+
387400

388401
def test_include() -> None:
389402
path = ROOT_PATH.joinpath(Path("test.rst"))

snooty/test_util.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,10 @@
44
import time
55
import watchdog.events
66
from pathlib import Path, PurePath
7-
from typing import Callable, List, Tuple, Type
7+
from typing import List, Tuple
88
from . import util
99

1010

11-
def expect_exception(f: Callable[[], None], exception_ty: Type[Exception]) -> None:
12-
"""Assert that the given function f raises the given exception type."""
13-
try:
14-
f()
15-
except exception_ty:
16-
return
17-
except Exception as err:
18-
raise AssertionError(f"Expected {exception_ty.__name__}; got {err}")
19-
20-
raise AssertionError(f"Expected {exception_ty.__name__} to be raised")
21-
22-
2311
def test_reroot_path() -> None:
2412
relative, absolute = util.reroot_path(
2513
PurePath("/foo/bar/baz.rst"), PurePath("/foo/dir/test.txt"), Path("foo")
@@ -31,6 +19,34 @@ def test_reroot_path() -> None:
3119
)[0] == PurePath("foo/bar/baz.rst")
3220

3321

22+
def test_option_string() -> None:
23+
assert util.option_string("Test") == "Test"
24+
# No input or blank input should raise a ValueError
25+
try:
26+
util.option_string(" ")
27+
except ValueError:
28+
pass
29+
30+
31+
def test_option_bool() -> None:
32+
assert util.option_bool("tRuE") == True
33+
assert util.option_bool("FaLsE") == False
34+
# No input or blank input should raise a ValueError
35+
try:
36+
util.option_bool(" ")
37+
except ValueError:
38+
pass
39+
40+
41+
def test_option_flag() -> None:
42+
assert util.option_flag("") == True
43+
# Specifying an argument should raise a ValueError
44+
try:
45+
util.option_flag("test")
46+
except ValueError:
47+
pass
48+
49+
3450
def test_get_files() -> None:
3551
assert set(util.get_files(PurePath("test_data"), (".toml",))) == {
3652
Path("test_data/snooty.toml"),

snooty/util.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,16 @@ def __len__(self) -> int:
191191
return sum(len(w) for w in self.directories.values())
192192

193193

194+
def option_string(argument: Optional[str]) -> Optional[str]:
195+
"""
196+
Check for a valid string option and return it. If no argument is given,
197+
raise ``ValueError``.
198+
"""
199+
if argument and argument.strip():
200+
return argument
201+
raise ValueError("Must supply string argument to option")
202+
203+
194204
def option_bool(argument: Optional[str]) -> bool:
195205
"""
196206
Check for a valid boolean option return it. If no argument is given,
@@ -199,8 +209,7 @@ def option_bool(argument: Optional[str]) -> bool:
199209
if argument and argument.strip():
200210
output = docutils.parsers.rst.directives.choice(argument, ("true", "false"))
201211
return output == "true"
202-
else:
203-
return True
212+
return True
204213

205214

206215
def option_flag(argument: Optional[str]) -> bool:
@@ -213,8 +222,7 @@ def option_flag(argument: Optional[str]) -> bool:
213222
"""
214223
if argument and argument.strip():
215224
raise ValueError('no argument is allowed; "%s" supplied' % argument)
216-
else:
217-
return True
225+
return True
218226

219227

220228
def split_domain(name: str) -> Tuple[str, str]:
@@ -227,7 +235,6 @@ def split_domain(name: str) -> Tuple[str, str]:
227235
parts = name.split(":", 1)
228236
if len(parts) == 1:
229237
return "", parts[0]
230-
231238
return parts[0], parts[1]
232239

233240

0 commit comments

Comments
 (0)