Skip to content

Commit

Permalink
release 0.10.4 to fix werkzeug bug
Browse files Browse the repository at this point in the history
Signed-off-by: Keming <[email protected]>
  • Loading branch information
yedpodtrzitko authored and kemingy committed Aug 3, 2022
1 parent c78c177 commit 3fa67be
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 9 deletions.
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

setup(
name="spectree",
version="0.10.3",
version="0.10.4",
license="Apache-2.0",
author="Keming Yang",
author_email="[email protected]",
Expand Down Expand Up @@ -43,8 +43,8 @@
install_requires=requires,
extras_require={
"email": ["pydantic[email]>=1.2"],
"flask": ["flask", "werkzeug<2.2"],
"falcon": ["falcon"],
"flask": ["flask"],
"falcon": ["falcon>=3.0.0"],
"starlette": ["starlette[full]"],
"dev": [
"pytest~=7.1",
Expand Down
6 changes: 3 additions & 3 deletions spectree/plugins/flask_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from .._types import ModelType
from ..response import Response
from ..utils import get_multidict_items
from ..utils import get_multidict_items, werkzeug_parse_rule
from .base import BasePlugin, Context


Expand Down Expand Up @@ -59,12 +59,12 @@ def parse_func(self, route: Any):
yield method, func

def parse_path(self, route, path_parameter_descriptions):
from werkzeug.routing import parse_converter_args, parse_rule
from werkzeug.routing import parse_converter_args

subs = []
parameters = []

for converter, arguments, variable in parse_rule(str(route)):
for converter, arguments, variable in werkzeug_parse_rule(str(route)):
if converter is None:
subs.append(variable)
continue
Expand Down
6 changes: 3 additions & 3 deletions spectree/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,16 +243,16 @@ def _generate_spec(self) -> Dict[str, Any]:
tags = {}
for route in self.backend.find_routes():
for method, func in self.backend.parse_func(route):
if self.backend.bypass(func, method) or self.bypass(func):
continue

path_parameter_descriptions = getattr(
func, "path_parameter_descriptions", None
)
path, parameters = self.backend.parse_path(
route, path_parameter_descriptions
)

if self.backend.bypass(func, method) or self.bypass(func):
continue

name = parse_name(func)
summary, desc = parse_comments(func)
func_tags = getattr(func, "tags", ())
Expand Down
51 changes: 51 additions & 0 deletions spectree/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
Any,
Callable,
Dict,
Iterator,
List,
Mapping,
Optional,
Expand All @@ -22,6 +23,22 @@
# parse HTTP status code to get the code
HTTP_CODE = re.compile(r"^HTTP_(?P<code>\d{3})$")

RE_FLASK_RULE = re.compile(
r"""
(?P<static>[^<]*) # static rule data
<
(?:
(?P<converter>[a-zA-Z_][a-zA-Z0-9_]*) # converter name
(?:\((?P<args>.*?)\))? # converter arguments
\: # variable delimiter
)?
(?P<variable>[a-zA-Z_][a-zA-Z0-9_]*) # variable name
>
""",
re.VERBOSE,
)


logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -277,3 +294,37 @@ def gen_list_model(model: Type[BaseModel]) -> Type[BaseModel]:
},
)
return ListModel


def werkzeug_parse_rule(
rule: str,
) -> Iterator[Tuple[Optional[str], Optional[str], str]]:
"""A copy of werkzeug.parse_rule which is now removed.
Parse a rule and return it as generator. Each iteration yields tuples
in the form ``(converter, arguments, variable)``. If the converter is
`None` it's a static url part, otherwise it's a dynamic one.
"""
pos = 0
end = len(rule)
do_match = RE_FLASK_RULE.match
used_names = set()
while pos < end:
m = do_match(rule, pos)
if m is None:
break
data = m.groupdict()
if data["static"]:
yield None, None, data["static"]
variable = data["variable"]
converter = data["converter"] or "default"
if variable in used_names:
raise ValueError(f"variable name {variable!r} used twice.")
used_names.add(variable)
yield converter, data["args"] or None, variable
pos = m.end()
if pos < end:
remaining = rule[pos:]
if ">" in remaining or "<" in remaining:
raise ValueError(f"malformed url rule: {rule!r}")
yield None, None, remaining

0 comments on commit 3fa67be

Please sign in to comment.