@@ -101,6 +101,9 @@ class _InfoDict(TypedDict, total=False):
101101class AbstractResource (Sized , Iterable ["AbstractRoute" ]):
102102 def __init__ (self , * , name : str | None = None ) -> None :
103103 self ._name = name
104+ self ._routes : dict [str , ResourceRoute ] = {}
105+ self ._any_route : ResourceRoute | None = None
106+ self ._allowed_methods : set [str ] = set ()
104107
105108 @property
106109 def name (self ) -> str | None :
@@ -119,6 +122,33 @@ def canonical(self) -> str:
119122 def url_for (self , ** kwargs : str ) -> URL :
120123 """Construct url for resource with additional params."""
121124
125+ def add_route (
126+ self ,
127+ method : str ,
128+ handler : type [AbstractView ] | Handler ,
129+ * ,
130+ expect_handler : _ExpectHandler | None = None ,
131+ ) -> "ResourceRoute" :
132+ if route := self ._routes .get (method , self ._any_route ):
133+ raise RuntimeError (
134+ "Added route will never be executed, "
135+ f"method { route .method } is already "
136+ "registered"
137+ )
138+
139+ route_obj = ResourceRoute (method , handler , self , expect_handler = expect_handler )
140+ self .register_route (route_obj )
141+ return route_obj
142+
143+ def register_route (self , route : "ResourceRoute" ) -> None :
144+ assert isinstance (
145+ route , ResourceRoute
146+ ), f"Instance of Route class is required, got { route !r} "
147+ if route .method == hdrs .METH_ANY :
148+ self ._any_route = route
149+ self ._allowed_methods .add (route .method )
150+ self ._routes [route .method ] = route
151+
122152 @abc .abstractmethod # pragma: no branch
123153 async def resolve (self , request : Request ) -> _Resolve :
124154 """Resolve resource.
@@ -308,36 +338,6 @@ async def _default_expect_handler(request: Request) -> None:
308338class Resource (AbstractResource ):
309339 def __init__ (self , * , name : str | None = None ) -> None :
310340 super ().__init__ (name = name )
311- self ._routes : dict [str , ResourceRoute ] = {}
312- self ._any_route : ResourceRoute | None = None
313- self ._allowed_methods : set [str ] = set ()
314-
315- def add_route (
316- self ,
317- method : str ,
318- handler : type [AbstractView ] | Handler ,
319- * ,
320- expect_handler : _ExpectHandler | None = None ,
321- ) -> "ResourceRoute" :
322- if route := self ._routes .get (method , self ._any_route ):
323- raise RuntimeError (
324- "Added route will never be executed, "
325- f"method { route .method } is already "
326- "registered"
327- )
328-
329- route_obj = ResourceRoute (method , handler , self , expect_handler = expect_handler )
330- self .register_route (route_obj )
331- return route_obj
332-
333- def register_route (self , route : "ResourceRoute" ) -> None :
334- assert isinstance (
335- route , ResourceRoute
336- ), f"Instance of Route class is required, got { route !r} "
337- if route .method == hdrs .METH_ANY :
338- self ._any_route = route
339- self ._allowed_methods .add (route .method )
340- self ._routes [route .method ] = route
341341
342342 async def resolve (self , request : Request ) -> _Resolve :
343343 if (match_dict := self ._match (request .rel_url .path_safe )) is None :
@@ -589,12 +589,7 @@ def get_info(self) -> _InfoDict:
589589 }
590590
591591 def set_options_route (self , handler : Handler ) -> None :
592- if "OPTIONS" in self ._routes :
593- raise RuntimeError ("OPTIONS route was set already" )
594- self ._routes ["OPTIONS" ] = ResourceRoute (
595- "OPTIONS" , handler , self , expect_handler = self ._expect_handler
596- )
597- self ._allowed_methods .add ("OPTIONS" )
592+ self .add_route ("OPTIONS" , handler )
598593
599594 async def resolve (self , request : Request ) -> _Resolve :
600595 path = request .rel_url .path_safe
0 commit comments