From 45c9d3546599351857c7024786fdac11f9c0f087 Mon Sep 17 00:00:00 2001 From: CoprDistGit Date: Mon, 10 Apr 2023 09:16:52 +0000 Subject: automatic import of python-sanic-routing --- .gitignore | 1 + python-sanic-routing.spec | 636 ++++++++++++++++++++++++++++++++++++++++++++++ sources | 1 + 3 files changed, 638 insertions(+) create mode 100644 python-sanic-routing.spec create mode 100644 sources diff --git a/.gitignore b/.gitignore index e69de29..8e30ca0 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1 @@ +/sanic-routing-22.8.0.tar.gz diff --git a/python-sanic-routing.spec b/python-sanic-routing.spec new file mode 100644 index 0000000..13ef35c --- /dev/null +++ b/python-sanic-routing.spec @@ -0,0 +1,636 @@ +%global _empty_manifest_terminate_build 0 +Name: python-sanic-routing +Version: 22.8.0 +Release: 1 +Summary: Core routing component for Sanic +License: MIT +URL: https://github.com/sanic-org/sanic-routing/ +Source0: https://mirrors.nju.edu.cn/pypi/web/packages/c0/a4/0f7be9c81ff3dd4cb389374db29f0f598b940361f7ddcc5c8f38f48f7655/sanic-routing-22.8.0.tar.gz +BuildArch: noarch + + +%description +# Sanic Routing + +## Background + +Beginning in v21.3, Sanic makes use of this new AST-style router in two use cases: + +1. Routing paths; and +2. Routing signals. + +Therefore, this package comes with a `BaseRouter` that needs to be subclassed in order to be used for its specific needs. + +Most Sanic users should never need to concern themselves with the details here. + +## Basic Example + +A simple implementation: + +```python +import logging + +from sanic_routing import BaseRouter + +logging.basicConfig(level=logging.DEBUG) + + +class Router(BaseRouter): + def get(self, path, *args, **kwargs): + return self.resolve(path, *args, **kwargs) + + +router = Router() + +router.add("/", lambda: ...) +router.finalize() +router.tree.display() +logging.info(router.find_route_src) + +route, handler, params = router.get("/matchme", method="BASE", extra=None) +``` + +The above snippet uses `router.tree.display()` to show how the router has decided to arrange the routes into a tree. In this simple example: + +``` + + len=1>], dynamic=True> +``` + +We can can see the code that the router has generated for us. It is available as a string at `router.find_route_src`. + +```python +def find_route(path, method, router, basket, extra): + parts = tuple(path[1:].split(router.delimiter)) + num = len(parts) + + # node=1 // part=__dynamic__:str + if num == 1: # CHECK 1 + try: + basket['__matches__'][0] = str(parts[0]) + except ValueError: + pass + else: + # Return 1 + return router.dynamic_routes[('<__dynamic__:str>',)][0], basket + raise NotFound +``` + +_FYI: If you are on Python 3.9, you can see a representation of the source after compilation at `router.find_route_src_compiled`_ + +## What's it doing? + +Therefore, in general implementation requires you to: + +1. Define a router with a `get` method; +2. Add one or more routes; +3. Finalize the router (`router.finalize()`); and +4. Call the router's `get` method. + +_NOTE: You can call `router.finalize(False)` if you do not want to compile the source code into executable form. This is useful if you only intend to review the generated output._ + +Every time you call `router.add` you create one (1) new `Route` instance. Even if that one route is created with multiple methods, it generates a single instance. If you `add()` another `Route` that has a similar path structure (but, perhaps has differen methods) they will be grouped together into a `RouteGroup`. It is worth also noting that a `RouteGroup` is created the first time you call `add()`, but subsequent similar routes will reuse the existing grouping instance. + + +When you call `finalize()`, it is taking the defined route groups and arranging them into "nodes" in a hierarchical tree. A single node is a path segment. A `Node` instance can have one or more `RouteGroup` on it where the `Node` is the termination point for that path. + +Perhaps an example is easier: + +```python +router.add("/path/to/", lambda: ...) +router.add("/path/to/", lambda: ...) +router.add("/path/to/different/", lambda: ...) +router.add("/path/to/different/", lambda: ..., methods=["one", "two"]) +``` + +The generated `RouteGroup` instances (3): + +``` + len=1> + len=1> + len=2> +``` + +The generated `Route` instances (4): + +``` +> +> +> +> +``` + +The Node Tree: + +``` + + + + + len=2>], dynamic=True> + len=1>], dynamic=True> + len=1>], dynamic=True> +``` + +And, the generated source code: + +```python +def find_route(path, method, router, basket, extra): + parts = tuple(path[1:].split(router.delimiter)) + num = len(parts) + + # node=1 // part=path + if num > 1: # CHECK 1 + if parts[0] == "path": # CHECK 4 + + # node=1.1 // part=to + if num > 2: # CHECK 1 + if parts[1] == "to": # CHECK 4 + + # node=1.1.1 // part=different + if num > 3: # CHECK 1 + if parts[2] == "different": # CHECK 4 + + # node=1.1.1.1 // part=__dynamic__:str + if num == 4: # CHECK 1 + try: + basket['__matches__'][3] = str(parts[3]) + except ValueError: + pass + else: + if method in frozenset({'one', 'two'}): + route_idx = 0 + elif method in frozenset({'BASE'}): + route_idx = 1 + else: + raise NoMethod + # Return 1.1.1.1 + return router.dynamic_routes[('path', 'to', 'different', '<__dynamic__:str>')][route_idx], basket + + # node=1.1.2 // part=__dynamic__:int + if num >= 3: # CHECK 1 + try: + basket['__matches__'][2] = int(parts[2]) + except ValueError: + pass + else: + if num == 3: # CHECK 5 + # Return 1.1.2 + return router.dynamic_routes[('path', 'to', '<__dynamic__:int>')][0], basket + + # node=1.1.3 // part=__dynamic__:str + if num >= 3: # CHECK 1 + try: + basket['__matches__'][2] = str(parts[2]) + except ValueError: + pass + else: + if num == 3: # CHECK 5 + # Return 1.1.3 + return router.dynamic_routes[('path', 'to', '<__dynamic__:str>')][0], basket + raise NotFound +``` + +## Special cases + +The above example only shows routes that have a dynamic path segment in them (example: ``). But, there are other use cases that are covered differently: + +1. *fully static paths* - These are paths with no parameters (example: `/user/login`). These are basically matched against a key/value store. +2. *regex paths* - If a route as a single regular expression match, then the whole route will be matched via regex. In general, this happens inline not too dissimilar than what we see in the above example. +3. *special regex paths* - The router comes with a special `path` type (example: ``) that can match on an expanded delimiter. This is also true for any regex that uses the path delimiter in it. These cannot be matched in the normal course since they are of unknown length. + + +%package -n python3-sanic-routing +Summary: Core routing component for Sanic +Provides: python-sanic-routing +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-sanic-routing +# Sanic Routing + +## Background + +Beginning in v21.3, Sanic makes use of this new AST-style router in two use cases: + +1. Routing paths; and +2. Routing signals. + +Therefore, this package comes with a `BaseRouter` that needs to be subclassed in order to be used for its specific needs. + +Most Sanic users should never need to concern themselves with the details here. + +## Basic Example + +A simple implementation: + +```python +import logging + +from sanic_routing import BaseRouter + +logging.basicConfig(level=logging.DEBUG) + + +class Router(BaseRouter): + def get(self, path, *args, **kwargs): + return self.resolve(path, *args, **kwargs) + + +router = Router() + +router.add("/", lambda: ...) +router.finalize() +router.tree.display() +logging.info(router.find_route_src) + +route, handler, params = router.get("/matchme", method="BASE", extra=None) +``` + +The above snippet uses `router.tree.display()` to show how the router has decided to arrange the routes into a tree. In this simple example: + +``` + + len=1>], dynamic=True> +``` + +We can can see the code that the router has generated for us. It is available as a string at `router.find_route_src`. + +```python +def find_route(path, method, router, basket, extra): + parts = tuple(path[1:].split(router.delimiter)) + num = len(parts) + + # node=1 // part=__dynamic__:str + if num == 1: # CHECK 1 + try: + basket['__matches__'][0] = str(parts[0]) + except ValueError: + pass + else: + # Return 1 + return router.dynamic_routes[('<__dynamic__:str>',)][0], basket + raise NotFound +``` + +_FYI: If you are on Python 3.9, you can see a representation of the source after compilation at `router.find_route_src_compiled`_ + +## What's it doing? + +Therefore, in general implementation requires you to: + +1. Define a router with a `get` method; +2. Add one or more routes; +3. Finalize the router (`router.finalize()`); and +4. Call the router's `get` method. + +_NOTE: You can call `router.finalize(False)` if you do not want to compile the source code into executable form. This is useful if you only intend to review the generated output._ + +Every time you call `router.add` you create one (1) new `Route` instance. Even if that one route is created with multiple methods, it generates a single instance. If you `add()` another `Route` that has a similar path structure (but, perhaps has differen methods) they will be grouped together into a `RouteGroup`. It is worth also noting that a `RouteGroup` is created the first time you call `add()`, but subsequent similar routes will reuse the existing grouping instance. + + +When you call `finalize()`, it is taking the defined route groups and arranging them into "nodes" in a hierarchical tree. A single node is a path segment. A `Node` instance can have one or more `RouteGroup` on it where the `Node` is the termination point for that path. + +Perhaps an example is easier: + +```python +router.add("/path/to/", lambda: ...) +router.add("/path/to/", lambda: ...) +router.add("/path/to/different/", lambda: ...) +router.add("/path/to/different/", lambda: ..., methods=["one", "two"]) +``` + +The generated `RouteGroup` instances (3): + +``` + len=1> + len=1> + len=2> +``` + +The generated `Route` instances (4): + +``` +> +> +> +> +``` + +The Node Tree: + +``` + + + + + len=2>], dynamic=True> + len=1>], dynamic=True> + len=1>], dynamic=True> +``` + +And, the generated source code: + +```python +def find_route(path, method, router, basket, extra): + parts = tuple(path[1:].split(router.delimiter)) + num = len(parts) + + # node=1 // part=path + if num > 1: # CHECK 1 + if parts[0] == "path": # CHECK 4 + + # node=1.1 // part=to + if num > 2: # CHECK 1 + if parts[1] == "to": # CHECK 4 + + # node=1.1.1 // part=different + if num > 3: # CHECK 1 + if parts[2] == "different": # CHECK 4 + + # node=1.1.1.1 // part=__dynamic__:str + if num == 4: # CHECK 1 + try: + basket['__matches__'][3] = str(parts[3]) + except ValueError: + pass + else: + if method in frozenset({'one', 'two'}): + route_idx = 0 + elif method in frozenset({'BASE'}): + route_idx = 1 + else: + raise NoMethod + # Return 1.1.1.1 + return router.dynamic_routes[('path', 'to', 'different', '<__dynamic__:str>')][route_idx], basket + + # node=1.1.2 // part=__dynamic__:int + if num >= 3: # CHECK 1 + try: + basket['__matches__'][2] = int(parts[2]) + except ValueError: + pass + else: + if num == 3: # CHECK 5 + # Return 1.1.2 + return router.dynamic_routes[('path', 'to', '<__dynamic__:int>')][0], basket + + # node=1.1.3 // part=__dynamic__:str + if num >= 3: # CHECK 1 + try: + basket['__matches__'][2] = str(parts[2]) + except ValueError: + pass + else: + if num == 3: # CHECK 5 + # Return 1.1.3 + return router.dynamic_routes[('path', 'to', '<__dynamic__:str>')][0], basket + raise NotFound +``` + +## Special cases + +The above example only shows routes that have a dynamic path segment in them (example: ``). But, there are other use cases that are covered differently: + +1. *fully static paths* - These are paths with no parameters (example: `/user/login`). These are basically matched against a key/value store. +2. *regex paths* - If a route as a single regular expression match, then the whole route will be matched via regex. In general, this happens inline not too dissimilar than what we see in the above example. +3. *special regex paths* - The router comes with a special `path` type (example: ``) that can match on an expanded delimiter. This is also true for any regex that uses the path delimiter in it. These cannot be matched in the normal course since they are of unknown length. + + +%package help +Summary: Development documents and examples for sanic-routing +Provides: python3-sanic-routing-doc +%description help +# Sanic Routing + +## Background + +Beginning in v21.3, Sanic makes use of this new AST-style router in two use cases: + +1. Routing paths; and +2. Routing signals. + +Therefore, this package comes with a `BaseRouter` that needs to be subclassed in order to be used for its specific needs. + +Most Sanic users should never need to concern themselves with the details here. + +## Basic Example + +A simple implementation: + +```python +import logging + +from sanic_routing import BaseRouter + +logging.basicConfig(level=logging.DEBUG) + + +class Router(BaseRouter): + def get(self, path, *args, **kwargs): + return self.resolve(path, *args, **kwargs) + + +router = Router() + +router.add("/", lambda: ...) +router.finalize() +router.tree.display() +logging.info(router.find_route_src) + +route, handler, params = router.get("/matchme", method="BASE", extra=None) +``` + +The above snippet uses `router.tree.display()` to show how the router has decided to arrange the routes into a tree. In this simple example: + +``` + + len=1>], dynamic=True> +``` + +We can can see the code that the router has generated for us. It is available as a string at `router.find_route_src`. + +```python +def find_route(path, method, router, basket, extra): + parts = tuple(path[1:].split(router.delimiter)) + num = len(parts) + + # node=1 // part=__dynamic__:str + if num == 1: # CHECK 1 + try: + basket['__matches__'][0] = str(parts[0]) + except ValueError: + pass + else: + # Return 1 + return router.dynamic_routes[('<__dynamic__:str>',)][0], basket + raise NotFound +``` + +_FYI: If you are on Python 3.9, you can see a representation of the source after compilation at `router.find_route_src_compiled`_ + +## What's it doing? + +Therefore, in general implementation requires you to: + +1. Define a router with a `get` method; +2. Add one or more routes; +3. Finalize the router (`router.finalize()`); and +4. Call the router's `get` method. + +_NOTE: You can call `router.finalize(False)` if you do not want to compile the source code into executable form. This is useful if you only intend to review the generated output._ + +Every time you call `router.add` you create one (1) new `Route` instance. Even if that one route is created with multiple methods, it generates a single instance. If you `add()` another `Route` that has a similar path structure (but, perhaps has differen methods) they will be grouped together into a `RouteGroup`. It is worth also noting that a `RouteGroup` is created the first time you call `add()`, but subsequent similar routes will reuse the existing grouping instance. + + +When you call `finalize()`, it is taking the defined route groups and arranging them into "nodes" in a hierarchical tree. A single node is a path segment. A `Node` instance can have one or more `RouteGroup` on it where the `Node` is the termination point for that path. + +Perhaps an example is easier: + +```python +router.add("/path/to/", lambda: ...) +router.add("/path/to/", lambda: ...) +router.add("/path/to/different/", lambda: ...) +router.add("/path/to/different/", lambda: ..., methods=["one", "two"]) +``` + +The generated `RouteGroup` instances (3): + +``` + len=1> + len=1> + len=2> +``` + +The generated `Route` instances (4): + +``` +> +> +> +> +``` + +The Node Tree: + +``` + + + + + len=2>], dynamic=True> + len=1>], dynamic=True> + len=1>], dynamic=True> +``` + +And, the generated source code: + +```python +def find_route(path, method, router, basket, extra): + parts = tuple(path[1:].split(router.delimiter)) + num = len(parts) + + # node=1 // part=path + if num > 1: # CHECK 1 + if parts[0] == "path": # CHECK 4 + + # node=1.1 // part=to + if num > 2: # CHECK 1 + if parts[1] == "to": # CHECK 4 + + # node=1.1.1 // part=different + if num > 3: # CHECK 1 + if parts[2] == "different": # CHECK 4 + + # node=1.1.1.1 // part=__dynamic__:str + if num == 4: # CHECK 1 + try: + basket['__matches__'][3] = str(parts[3]) + except ValueError: + pass + else: + if method in frozenset({'one', 'two'}): + route_idx = 0 + elif method in frozenset({'BASE'}): + route_idx = 1 + else: + raise NoMethod + # Return 1.1.1.1 + return router.dynamic_routes[('path', 'to', 'different', '<__dynamic__:str>')][route_idx], basket + + # node=1.1.2 // part=__dynamic__:int + if num >= 3: # CHECK 1 + try: + basket['__matches__'][2] = int(parts[2]) + except ValueError: + pass + else: + if num == 3: # CHECK 5 + # Return 1.1.2 + return router.dynamic_routes[('path', 'to', '<__dynamic__:int>')][0], basket + + # node=1.1.3 // part=__dynamic__:str + if num >= 3: # CHECK 1 + try: + basket['__matches__'][2] = str(parts[2]) + except ValueError: + pass + else: + if num == 3: # CHECK 5 + # Return 1.1.3 + return router.dynamic_routes[('path', 'to', '<__dynamic__:str>')][0], basket + raise NotFound +``` + +## Special cases + +The above example only shows routes that have a dynamic path segment in them (example: ``). But, there are other use cases that are covered differently: + +1. *fully static paths* - These are paths with no parameters (example: `/user/login`). These are basically matched against a key/value store. +2. *regex paths* - If a route as a single regular expression match, then the whole route will be matched via regex. In general, this happens inline not too dissimilar than what we see in the above example. +3. *special regex paths* - The router comes with a special `path` type (example: ``) that can match on an expanded delimiter. This is also true for any regex that uses the path delimiter in it. These cannot be matched in the normal course since they are of unknown length. + + +%prep +%autosetup -n sanic-routing-22.8.0 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-sanic-routing -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Mon Apr 10 2023 Python_Bot - 22.8.0-1 +- Package Spec generated diff --git a/sources b/sources new file mode 100644 index 0000000..5826928 --- /dev/null +++ b/sources @@ -0,0 +1 @@ +15d367258c8f13f8b4bda9c46cfa3be3 sanic-routing-22.8.0.tar.gz -- cgit v1.2.3