Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
diegomirandap committed Oct 21, 2024
1 parent 1bfb819 commit ccffb38
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 20 deletions.
1 change: 1 addition & 0 deletions falcon/routing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from falcon.routing.compiled import CompiledRouter
from falcon.routing.compiled import CompiledRouterOptions
from falcon.routing.converters import BaseConverter
from falcon.routing.converters import BaseConverterMultipleSegment
from falcon.routing.converters import DateTimeConverter
from falcon.routing.converters import FloatConverter
from falcon.routing.converters import IntConverter
Expand Down
10 changes: 4 additions & 6 deletions falcon/routing/compiled.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class CompiledRouter:

def __init__(self) -> None:
self._ast: _CxParent = _CxParent()
self._converters: List[converters.BaseConverter] = []
self._converters: List[Union[converters.BaseConverter, converters.BaseConverterMultipleSegment]] = []
self._finder_src: str = ''

self._options = CompiledRouterOptions()
Expand Down Expand Up @@ -231,9 +231,7 @@ def find_cmp_converter(node: CompiledRouterNode) -> Optional[Tuple[str, str]]:
value = [
(field, converter)
for field, converter, _ in node.var_converter_map
if converters._consumes_multiple_segments(
self._converter_map[converter]
)
if isinstance(self._converter_map[converter], converters.BaseConverterMultipleSegment)
]
if value:
return value[0]
Expand Down Expand Up @@ -525,7 +523,7 @@ def _generate_ast( # noqa: C901
)
converter_idx = len(self._converters)
self._converters.append(converter_obj)
if converters._consumes_multiple_segments(converter_obj):
if isinstance(converter_obj, converters.BaseConverterMultipleSegment):
consume_multiple_segments = True
parent.append_child(_CxSetFragmentFromRemainingPaths(level))
else:
Expand Down Expand Up @@ -619,7 +617,7 @@ def _generate_conversion_ast(
# a series of nested "if" constructs.
for field_name, converter_name, converter_argstr in node.var_converter_map:
converter_class = self._converter_map[converter_name]
assert not converters._consumes_multiple_segments(converter_class)
assert not isinstance(converter_class, converters.BaseConverterMultipleSegment)

converter_obj = self._instantiate_converter(
converter_class, converter_argstr
Expand Down
33 changes: 19 additions & 14 deletions falcon/routing/converters.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@
import abc
from datetime import datetime
from math import isfinite
from typing import Any, ClassVar, Iterable, Optional, overload, Union
from typing import Any, ClassVar, Iterable, List, Optional, overload, Union
import uuid

__all__ = (
'BaseConverter',
'BaseConverterMultipleSegments',
'DateTimeConverter',
'FloatConverter',
'IntConverter',
Expand All @@ -34,34 +35,38 @@


class BaseConverter(metaclass=abc.ABCMeta):
"""Abstract base class for URI template field converters."""
"""Abstract base class for URI template field converters that consume a single segment."""

CONSUME_MULTIPLE_SEGMENTS: ClassVar[bool] = False
"""When set to ``True`` it indicates that this converter will consume
multiple URL path segments. Currently a converter with
``CONSUME_MULTIPLE_SEGMENTS=True`` must be at the end of the URL template
effectively meaning that it will consume all of the remaining URL path
segments.
"""

@abc.abstractmethod
def convert(self, value: str) -> Any:
"""Convert a URI template field value to another format or type.
Args:
value (str or List[str]): Original string to convert.
If ``CONSUME_MULTIPLE_SEGMENTS=True`` this value is a
list of strings containing the path segments matched by
the converter.
value (str): Original string to convert.
Returns:
object: Converted field value, or ``None`` if the field
can not be converted.
"""


def _consumes_multiple_segments(converter: object) -> bool:
return getattr(converter, 'CONSUME_MULTIPLE_SEGMENTS', False)
class BaseConverterMultipleSegment(BaseConverter):
"""A URI template field converter that consumes multiple URL path segments."""

CONSUME_MULTIPLE_SEGMENTS: ClassVar[bool] = True

def convert(self, value: List[str]) -> Any:
"""Convert multiple URI template field values (path segments).
Args:
value (List[str]): List of path segments to convert.
Returns:
object: Converted field value, or ``None`` if the field
can not be converted.
"""


class IntConverter(BaseConverter):
Expand Down

0 comments on commit ccffb38

Please sign in to comment.