import re def clean_route_name(name: str) -> str: parts = name.split(".", 1) name = parts[-1] for target in ("_", ".", " "): name = name.replace(target, " ") return name.title() def get_uri_filter(app): """ Return a filter function that takes a URI and returns whether it should be filter out from the swagger documentation or not. Arguments: app: The application to take `config.API_URI_FILTER` from. Possible values for this config option are: `slash` (to keep URIs that end with a `/`), `all` (to keep all URIs). All other values default to keep all URIs that don't end with a `/`. Returns: `True` if the URI should be *filtered out* from the swagger documentation, and `False` if it should be kept in the documentation. """ choice = getattr(app.config, "API_URI_FILTER", None) if choice == "slash": # Keep URIs that end with a /. return lambda uri: not uri.endswith("/") if choice == "all": # Keep all URIs. return lambda uri: False # Keep URIs that don't end with a /, (special case: "/"). return lambda uri: len(uri) > 1 and uri.endswith("/") def remove_nulls(dictionary, deep=True): """ Removes all null values from a dictionary. """ return { k: remove_nulls(v, deep) if deep and isinstance(v, dict) else v for k, v in dictionary.items() if v is not None } def remove_nulls_from_kwargs(**kwargs): return remove_nulls(kwargs, deep=False) def get_blueprinted_routes(app): for blueprint in app.blueprints.values(): if not hasattr(blueprint, "routes"): continue for route in blueprint.routes: if hasattr(route.handler, "view_class"): # before sanic 21.3, route.handler could be a number of # different things, so have to type check for http_method in route.methods: _handler = getattr( route.handler.view_class, http_method.lower(), None ) if _handler: yield (blueprint.name, _handler) else: yield (blueprint.name, route.handler) def get_all_routes(app, skip_prefix): uri_filter = get_uri_filter(app) for group in app.router.groups.values(): uri = f"/{group.path}" # prior to sanic 21.3 routes came in both forms # (e.g. /test and /test/ ) # after sanic 21.3 routes come in one form, # with an attribute "strict", # so we simulate that ourselves: uris = [uri] if not group.strict and len(uri) > 1: alt = uri[:-1] if uri.endswith("/") else f"{uri}/" uris.append(alt) for uri in uris: if uri_filter(uri): continue if skip_prefix and group.raw_path.startswith( skip_prefix.lstrip("/") ): continue for parameter in group.params.values(): uri = re.sub( f"<{parameter.name}.*?>", f"{{{parameter.name}}}", uri, ) for route in group: if getattr(route.extra, "static", False): continue method_handlers = [ (method, route.handler) for method in route.methods ] _, name = route.name.split(".", 1) yield ( uri, name, route.params.values(), method_handlers, route.requirements.get("host"), )