diff --git a/flask_restx/swagger.py b/flask_restx/swagger.py index 478aa86e..2b67709e 100644 --- a/flask_restx/swagger.py +++ b/flask_restx/swagger.py @@ -15,7 +15,6 @@ from six import string_types, itervalues, iteritems, iterkeys from flask import current_app -from werkzeug.routing import parse_rule from . import fields from .model import Model, ModelBase, OrderedModel @@ -36,7 +35,6 @@ "default": "string", } - #: Maps Python primitives types to Swagger ones PY_TYPES = { int: "integer", @@ -55,6 +53,21 @@ r"^:raises\s+(?P[\w\d_]+)\s*:\s*(?P.*)$", re.MULTILINE ) +RE_PARSE_RULE = re.compile( + r""" + (?P[^<]*) # static rule data + < + (?: + (?P[a-zA-Z_][a-zA-Z0-9_]*) # converter name + (?:\((?P.*?)\))? # converter arguments + \: # variable delimiter + )? + (?P[a-zA-Z_][a-zA-Z0-9_]*) # variable name + > + """, + re.VERBOSE, +) + def ref(model): """Return a reference to model in definitions""" @@ -74,6 +87,39 @@ def extract_path(path): return RE_URL.sub(r"{\1}", path) +def parse_rule(rule): + """ + 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. + + Note: This originally lived in werkzeug.routing.parse_rule until it was removed in werkzeug 2.2.0. + """ + pos = 0 + end = len(rule) + do_match = RE_PARSE_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 + + def extract_path_params(path): """ Extract Flask-style parameters from an URL pattern as Swagger ones.