Handle dynamic routes (#250)
This commit is contained in:
parent
98e9edd98a
commit
9d59936737
@ -184,11 +184,13 @@ class App(Base):
|
||||
), "Path must be set if component is not a callable."
|
||||
path = component.__name__
|
||||
|
||||
# Get args from the path for dynamic routes.
|
||||
args = utils.get_path_args(path)
|
||||
# Check if the path given is valid
|
||||
utils.verify_path_validity(path)
|
||||
|
||||
self.state.setup_dynamic_args(utils.get_path_args(path))
|
||||
|
||||
# Generate the component if it is a callable.
|
||||
component = component if isinstance(component, Component) else component(*args)
|
||||
component = component if isinstance(component, Component) else component()
|
||||
|
||||
# Add meta information to the component.
|
||||
compiler_utils.add_meta(
|
||||
|
@ -279,6 +279,39 @@ class State(Base, ABC):
|
||||
"""
|
||||
return self.router_data.get("query", {})
|
||||
|
||||
@classmethod
|
||||
def setup_dynamic_args(cls, args: dict[str, str]):
|
||||
"""Set up args for easy access in renderer.
|
||||
|
||||
Args:
|
||||
args: a dict of args
|
||||
"""
|
||||
|
||||
def param_factory(param):
|
||||
@ComputedVar
|
||||
def inner_func(self) -> str:
|
||||
return self.get_query_params().get(param, "")
|
||||
|
||||
return inner_func
|
||||
|
||||
def catchall_factory(param):
|
||||
@ComputedVar
|
||||
def inner_func(self) -> List:
|
||||
return self.get_query_params().get(param, [])
|
||||
|
||||
return inner_func
|
||||
|
||||
for param, value in args.items():
|
||||
|
||||
if value == "catchall":
|
||||
func = catchall_factory(param)
|
||||
elif value == "patharg":
|
||||
func = param_factory(param)
|
||||
else:
|
||||
continue
|
||||
cls.computed_vars[param] = func.set_state(cls) # type: ignore
|
||||
setattr(cls, param, func)
|
||||
|
||||
def __getattribute__(self, name: str) -> Any:
|
||||
"""Get the state var.
|
||||
|
||||
|
@ -771,12 +771,34 @@ def indent(text: str, indent_level: int = 2) -> str:
|
||||
return os.linesep.join(f"{' ' * indent_level}{line}" for line in lines) + os.linesep
|
||||
|
||||
|
||||
def get_path_args(path: str) -> List[str]:
|
||||
def verify_path_validity(path: str) -> None:
|
||||
"""Verify if the path is valid, and throw an error if not.
|
||||
|
||||
Args:
|
||||
path: the path that need to be checked
|
||||
|
||||
Raises:
|
||||
ValueError: explains what is wrong with the path.
|
||||
"""
|
||||
check_catchall = re.compile(r"^\[\.\.\.(.+)\]$")
|
||||
catchall_found = False
|
||||
for part in path.split("/"):
|
||||
if catchall_found:
|
||||
raise ValueError(f"Catch-all must be the last part of the URL: {path}")
|
||||
match = check_catchall.match(part)
|
||||
if match:
|
||||
catchall_found = True
|
||||
|
||||
|
||||
def get_path_args(path: str) -> Dict[str, str]:
|
||||
"""Get the path arguments for the given path.
|
||||
|
||||
Args:
|
||||
path: The path to get the arguments for.
|
||||
|
||||
Raises:
|
||||
ValueError: explains what is wrong with the path.
|
||||
|
||||
Returns:
|
||||
The path arguments.
|
||||
"""
|
||||
@ -785,19 +807,27 @@ def get_path_args(path: str) -> List[str]:
|
||||
|
||||
# Regex to check for path args.
|
||||
check = re.compile(r"^\[(.+)\]$")
|
||||
check_catchall = re.compile(r"^\[\.\.\.(.+)\]$")
|
||||
|
||||
# Iterate over the path parts and check for path args.
|
||||
args = []
|
||||
for part in os.path.split(path):
|
||||
args = {}
|
||||
for part in path.split("/"):
|
||||
match = check_catchall.match(part)
|
||||
if match:
|
||||
arg_name = match.groups()[0]
|
||||
if arg_name in args:
|
||||
raise ValueError(f"arg [{arg_name}] is used more than once in this URL")
|
||||
|
||||
args[arg_name] = "catchall"
|
||||
continue
|
||||
|
||||
match = check.match(part)
|
||||
if match:
|
||||
# Add the path arg to the list.
|
||||
v = BaseVar(
|
||||
name=match.groups()[0],
|
||||
type_=str,
|
||||
state=f"{constants.ROUTER}.query",
|
||||
)
|
||||
args.append(v)
|
||||
arg_name = match.groups()[0]
|
||||
if arg_name in args:
|
||||
raise ValueError(f"arg [{arg_name}] is used more than once in this URL")
|
||||
args[arg_name] = "patharg"
|
||||
return args
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user