# Buggy code
def _compile_builder(self, append_unknown=True):
    defaults = self.defaults or {}
    dom_ops = []
    url_ops = []

    opl = dom_ops
    for is_dynamic, data in self._trace:
        if data == "|" and opl is dom_ops:
            opl = url_ops
            continue
        # this seems like a silly case to ever come up but:
        # if a default is given for a value that appears in the rule,
        # resolve it to a constant ahead of time
        if is_dynamic and data in defaults:
            data = self._converters[data].to_url(defaults[data])
            opl.append((False, data))
        elif not is_dynamic:
            opl.append(
                (False, url_quote(to_bytes(data, self.map.charset), safe="/:|+"))
            )
        else:
            opl.append((True, data))

    def _convert(elem):
        ret = _prefix_names(_CALL_CONVERTER_CODE_FMT.format(elem=elem))
        ret.args = [ast.Name(str(elem), ast.Load())]  # str for py2
        return ret

    def _parts(ops):
        parts = [
            _convert(elem) if is_dynamic else ast.Str(s=elem)
            for is_dynamic, elem in ops
        ]
        parts = parts or [ast.Str("")]
        # constant fold
        ret = [parts[0]]
        for p in parts[1:]:
            if isinstance(p, ast.Str) and isinstance(ret[-1], ast.Str):
                ret[-1] = ast.Str(ret[-1].s + p.s)
            else:
                ret.append(p)
        return ret

    dom_parts = _parts(dom_ops)
    url_parts = _parts(url_ops)
    if not append_unknown:
        body = []
    else:
        body = [_IF_KWARGS_URL_ENCODE_AST]
        url_parts.extend(_URL_ENCODE_AST_NAMES)

    def _join(parts):
        if len(parts) == 1:  # shortcut
            return parts[0]
        elif hasattr(ast, "JoinedStr"):  # py36+
            return ast.JoinedStr(parts)
        else:
            call = _prefix_names('"".join()')
            call.args = [ast.Tuple(parts, ast.Load())]
            return call

    body.append(ast.Return(ast.Tuple([_join(dom_parts), _join(url_parts)], ast.Load())))

    # str is necessary for python2
    pargs = [
        str(elem)
        for is_dynamic, elem in dom_ops + url_ops
        if is_dynamic and elem not in defaults
    ]
    kargs = [str(k) for k in defaults]

    func_ast = _prefix_names("def _(): pass")
    func_ast.name = "<builder:{!r}>".format(self.rule)
    if hasattr(ast, "arg"):  # py3
        func_ast.args.args.append(ast.arg(".self", None))
        for arg in pargs + kargs:
            func_ast.args.args.append(ast.arg(arg, None))
        func_ast.args.kwarg = ast.arg(".kwargs", None)
    else:
        func_ast.args.args.append(ast.Name(".self", ast.Load()))
        for arg in pargs + kargs:
            func_ast.args.args.append(ast.Name(arg, ast.Load()))
        func_ast.args.kwarg = ".kwargs"
    for _ in kargs:
        func_ast.args.defaults.append(ast.Str(""))
    func_ast.body = body

    module = ast.fix_missing_locations(ast.Module([func_ast]))
    code = compile(module, "<werkzeug routing>", "exec")
    return self._get_func_code(code, func_ast.name)


# Traceback (TypeError)
flask run
* Serving Flask app "flask_test.py"
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
Traceback (most recent call last):
File "d:\tool\python\38\lib\runpy.py", line 192, in _run_module_as_main
return _run_code(code, main_globals, None,
File "d:\tool\python\38\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "d:\tool\python\38\Scripts\flask.exe\__main__.py", line 9, in <module>
File "d:\tool\python\38\lib\site-packages\flask\cli.py", line 906, in main
cli.main(args=args, prog_name=name)
File "d:\tool\python\38\lib\site-packages\flask\cli.py", line 569, in main
return super(FlaskGroup, self).main(*args, **kwargs)
File "d:\tool\python\38\lib\site-packages\click\core.py", line 717, in main
rv = self.invoke(ctx)
File "d:\tool\python\38\lib\site-packages\click\core.py", line 1137, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "d:\tool\python\38\lib\site-packages\click\core.py", line 956, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "d:\tool\python\38\lib\site-packages\click\core.py", line 555, in invoke
return callback(*args, **kwargs)
File "d:\tool\python\38\lib\site-packages\click\decorators.py", line 64, in new_func
return ctx.invoke(f, obj, *args, **kwargs)
File "d:\tool\python\38\lib\site-packages\click\core.py", line 555, in invoke
return callback(*args, **kwargs)
File "d:\tool\python\38\lib\site-packages\flask\cli.py", line 779, in run_command
app = DispatchingApp(info.load_app, use_eager_loading=eager_loading)
File "d:\tool\python\38\lib\site-packages\flask\cli.py", line 300, in __init__
self._load_unlocked()
File "d:\tool\python\38\lib\site-packages\flask\cli.py", line 324, in _load_unlocked
self._app = rv = self.loader()
File "d:\tool\python\38\lib\site-packages\flask\cli.py", line 381, in load_app
app = locate_app(self, import_name, name)
File "d:\tool\python\38\lib\site-packages\flask\cli.py", line 236, in locate_app
__import__(module_name)
File "D:\flask_test.py", line 3, in <module>
app = Flask(__name__)
File "d:\tool\python\38\lib\site-packages\flask\app.py", line 559, in __init__
self.add_url_rule(
File "d:\tool\python\38\lib\site-packages\flask\app.py", line 67, in wrapper_func
return f(self, *args, **kwargs)
File "d:\tool\python\38\lib\site-packages\flask\app.py", line 1217, in add_url_rule
self.url_map.add(rule)
File "d:\tool\python\38\lib\site-packages\werkzeug\routing.py", line 1388, in add
rule.bind(self)
File "d:\tool\python\38\lib\site-packages\werkzeug\routing.py", line 730, in bind
self.compile()
File "d:\tool\python\38\lib\site-packages\werkzeug\routing.py", line 794, in compile
self._build = self._compile_builder(False).__get__(self, None)
File "d:\tool\python\38\lib\site-packages\werkzeug\routing.py", line 951, in _compile_builder
code = compile(module, "<werkzeug routing>", "exec")
TypeError: required field "type_ignores" missing from Module

# Fixed code
def _compile_builder(self, append_unknown=True):
    defaults = self.defaults or {}
    dom_ops = []
    url_ops = []

    opl = dom_ops
    for is_dynamic, data in self._trace:
        if data == "|" and opl is dom_ops:
            opl = url_ops
            continue
        # this seems like a silly case to ever come up but:
        # if a default is given for a value that appears in the rule,
        # resolve it to a constant ahead of time
        if is_dynamic and data in defaults:
            data = self._converters[data].to_url(defaults[data])
            opl.append((False, data))
        elif not is_dynamic:
            opl.append(
                (False, url_quote(to_bytes(data, self.map.charset), safe="/:|+"))
            )
        else:
            opl.append((True, data))

    def _convert(elem):
        ret = _prefix_names(_CALL_CONVERTER_CODE_FMT.format(elem=elem))
        ret.args = [ast.Name(str(elem), ast.Load())]  # str for py2
        return ret

    def _parts(ops):
        parts = [
            _convert(elem) if is_dynamic else ast.Str(s=elem)
            for is_dynamic, elem in ops
        ]
        parts = parts or [ast.Str("")]
        # constant fold
        ret = [parts[0]]
        for p in parts[1:]:
            if isinstance(p, ast.Str) and isinstance(ret[-1], ast.Str):
                ret[-1] = ast.Str(ret[-1].s + p.s)
            else:
                ret.append(p)
        return ret

    dom_parts = _parts(dom_ops)
    url_parts = _parts(url_ops)
    if not append_unknown:
        body = []
    else:
        body = [_IF_KWARGS_URL_ENCODE_AST]
        url_parts.extend(_URL_ENCODE_AST_NAMES)

    def _join(parts):
        if len(parts) == 1:  # shortcut
            return parts[0]
        elif hasattr(ast, "JoinedStr"):  # py36+
            return ast.JoinedStr(parts)
        else:
            call = _prefix_names('"".join()')
            call.args = [ast.Tuple(parts, ast.Load())]
            return call

    body.append(ast.Return(ast.Tuple([_join(dom_parts), _join(url_parts)], ast.Load())))

    # str is necessary for python2
    pargs = [
        str(elem)
        for is_dynamic, elem in dom_ops + url_ops
        if is_dynamic and elem not in defaults
    ]
    kargs = [str(k) for k in defaults]

    func_ast = _prefix_names("def _(): pass")
    func_ast.name = "<builder:{!r}>".format(self.rule)
    if hasattr(ast, "arg"):  # py3
        func_ast.args.args.append(ast.arg(".self", None))
        for arg in pargs + kargs:
            func_ast.args.args.append(ast.arg(arg, None))
        func_ast.args.kwarg = ast.arg(".kwargs", None)
    else:
        func_ast.args.args.append(ast.Name(".self", ast.Load()))
        for arg in pargs + kargs:
            func_ast.args.args.append(ast.Name(arg, ast.Load()))
        func_ast.args.kwarg = ".kwargs"
    for _ in kargs:
        func_ast.args.defaults.append(ast.Str(""))
    func_ast.body = body

    # use `ast.parse` instead of `ast.Module` for better portability
    # python3.8 changes the signature of `ast.Module`
    module = ast.parse("")
    module.body = [func_ast]
    module = ast.fix_missing_locations(module)
    code = compile(module, "<werkzeug routing>", "exec")
    return self._get_func_code(code, func_ast.name)