fastapi_chameleon 0.1.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ """fastapi-chameleon - Adds integration of the Chameleon template language to FastAPI."""
2
+
3
+ __version__ = '0.1.9'
4
+ __author__ = 'Michael Kennedy <michael@talkpython.fm>'
5
+ __all__ = ['template', 'global_init']
6
+
7
+ from .engine import global_init
8
+ from .engine import template
9
+ from .engine import response
@@ -0,0 +1,115 @@
1
+ import inspect
2
+ import os
3
+ from functools import wraps
4
+ from typing import Optional, Union, Callable
5
+
6
+ import fastapi
7
+ from chameleon import PageTemplateLoader, PageTemplate
8
+
9
+ from fastapi_chameleon.exceptions import FastAPIChameleonException
10
+
11
+ __templates: Optional[PageTemplateLoader] = None
12
+ template_path: Optional[str] = None
13
+
14
+
15
+ def global_init(template_folder: str, auto_reload=False, cache_init=True):
16
+ global __templates, template_path
17
+
18
+ if __templates and cache_init:
19
+ return
20
+
21
+ if not template_folder:
22
+ msg = f'The template_folder must be specified.'
23
+ raise FastAPIChameleonException(msg)
24
+
25
+ if not os.path.isdir(template_folder):
26
+ msg = f"The specified template folder must be a folder, it's not: {template_folder}"
27
+ raise FastAPIChameleonException(msg)
28
+
29
+ template_path = template_folder
30
+ __templates = PageTemplateLoader(template_folder, auto_reload=auto_reload)
31
+
32
+
33
+ def clear():
34
+ global __templates, template_path
35
+ __templates = None
36
+ template_path = None
37
+
38
+
39
+ def render(template_file: str, **template_data):
40
+ if not __templates:
41
+ raise FastAPIChameleonException("You must call global_init() before rendering templates.")
42
+
43
+ page: PageTemplate = __templates[template_file]
44
+ return page.render(encoding='utf-8', **template_data)
45
+
46
+
47
+ def response(template_file: str, mimetype='text/html', status_code=200, **template_data):
48
+ html = render(template_file, **template_data)
49
+ return fastapi.Response(content=html, media_type=mimetype, status_code=status_code)
50
+
51
+
52
+ def template(template_file: Optional[Union[Callable, str]] = None, mimetype: str = 'text/html'):
53
+ """
54
+ Decorate a FastAPI view method to render an HTML response.
55
+
56
+ :param str template_file: Optional, the Chameleon template file (path relative to template folder, *.pt).
57
+ :param str mimetype: The mimetype response (defaults to text/html).
58
+ :return: Decorator to be consumed by FastAPI
59
+ """
60
+
61
+ wrapped_function = None
62
+ if callable(template_file):
63
+ wrapped_function = template_file
64
+ template_file = None
65
+
66
+ def response_inner(f):
67
+ nonlocal template_file
68
+ global template_path
69
+
70
+ if not template_path:
71
+ template_path = 'templates'
72
+ # raise FastAPIChameleonException("Cannot continue: fastapi_chameleon.global_init() has not been called.")
73
+
74
+ if not template_file:
75
+ # Use the default naming scheme: template_folder/module_name/function_name.pt
76
+ module = f.__module__
77
+ if '.' in module:
78
+ module = module.split('.')[-1]
79
+ view = f.__name__
80
+ template_file = f'{module}/{view}.html'
81
+
82
+ if not os.path.exists(os.path.join(template_path, template_file)):
83
+ template_file = f'{module}/{view}.pt'
84
+
85
+ @wraps(f)
86
+ def sync_view_method(*args, **kwargs):
87
+ response_val = f(*args, **kwargs)
88
+ return __render_response(template_file, response_val, mimetype)
89
+
90
+ @wraps(f)
91
+ async def async_view_method(*args, **kwargs):
92
+ response_val = await f(*args, **kwargs)
93
+ return __render_response(template_file, response_val, mimetype)
94
+
95
+ if inspect.iscoroutinefunction(f):
96
+ return async_view_method
97
+ else:
98
+ return sync_view_method
99
+
100
+ return response_inner(wrapped_function) if wrapped_function else response_inner
101
+
102
+
103
+ def __render_response(template_file, response_val, mimetype):
104
+ # source skip: assign-if-exp
105
+ if isinstance(response_val, fastapi.Response):
106
+ return response_val
107
+
108
+ if template_file and not isinstance(response_val, dict):
109
+ msg = f"Invalid return type {type(response_val)}, we expected a dict or fastapi.Response as the return value."
110
+ raise FastAPIChameleonException(msg)
111
+
112
+ model = response_val
113
+
114
+ html = render(template_file, **model)
115
+ return fastapi.Response(content=html, media_type=mimetype)
@@ -0,0 +1,2 @@
1
+ class FastAPIChameleonException(Exception):
2
+ pass
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Michael Kennedy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.1
2
+ Name: fastapi-chameleon
3
+ Version: 0.1.9
4
+ Summary: Adds integration of the Chameleon template language to FastAPI.
5
+ Home-page: https://github.com/mikeckennedy/fastapi-chameleon
6
+ Author: Michael Kennedy
7
+ Author-email: michael@talkpython.fm
8
+ License: MIT
9
+ Platform: UNKNOWN
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3.6
14
+ Classifier: Programming Language :: Python :: 3.7
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: fastapi
21
+ Requires-Dist: Chameleon
22
+
23
+ # fastapi-chameleon
24
+
25
+ Adds integration of the Chameleon template language to FastAPI. If you are interested in Jinja instead, see the sister project: [github.com/AGeekInside/fastapi-jinja](https://github.com/AGeekInside/fastapi-jinja).
26
+
27
+ ## Installation
28
+
29
+ Simply `pip install fastapi_chameleon`.
30
+
31
+ ## Usage
32
+
33
+ This is easy to use. Just create a folder within your web app to hold the templates such as:
34
+
35
+ ```
36
+ ├── main.py
37
+ ├── views.py
38
+ │
39
+ ├── templates
40
+ │ ├── home
41
+ │ │ └── index.pt
42
+ │ └── shared
43
+ │ └── layout.pt
44
+
45
+ ```
46
+
47
+ In the app startup, tell the library about the folder you wish to use:
48
+
49
+ ```python
50
+ import os
51
+ import fastapi_chameleon
52
+
53
+ dev_mode = True
54
+
55
+ folder = os.path.dirname(__file__)
56
+ template_folder = os.path.join(folder, 'templates')
57
+ template_folder = os.path.abspath(template_folder)
58
+
59
+ fastapi_chameleon.global_init(template_folder, auto_reload=dev_mode)
60
+ ```
61
+
62
+ Then just decorate the FastAPI view methods (works on sync and async methods):
63
+
64
+ ```python
65
+ @router.post('/')
66
+ @fastapi_chameleon.template('home/index.pt')
67
+ async def home_post(request: Request):
68
+ form = await request.form()
69
+ vm = PersonViewModel(**form)
70
+
71
+ return vm.dict() # {'first':'Michael', 'last':'Kennedy', ...}
72
+
73
+ ```
74
+
75
+ The view method should return a `dict` to be passed as variables/values to the template.
76
+
77
+ If a `fastapi.Response` is returned, the template is skipped and the response along with status_code and
78
+ other values is directly passed through. This is common for redirects and error responses not meant
79
+ for this page template.
80
+
81
+
@@ -0,0 +1,8 @@
1
+ fastapi_chameleon/__init__.py,sha256=LBPvG4Ylc2XSgSGVNnn-HIE1Rubz_2EIxrgpSNfqFEs,297
2
+ fastapi_chameleon/engine.py,sha256=30OGDUXAcxGUQQMlJ2pWZoEanBX8gWLq8tdcz3pvp5U,3939
3
+ fastapi_chameleon/exceptions.py,sha256=qjxR28_YzuPwUmYsbCZLUUAMt2Kl4b8Arjtr24Xmo9E,53
4
+ fastapi_chameleon-0.1.9.dist-info/LICENSE,sha256=G9Edv3jcTxX10DuIIQqR3yzEHsSsDssPuGlM-pWjV-s,1072
5
+ fastapi_chameleon-0.1.9.dist-info/METADATA,sha256=tXKFDb51eBDHVsKRdquQXAqKZ_sCtFS6rIeb9D8jUV4,2365
6
+ fastapi_chameleon-0.1.9.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
7
+ fastapi_chameleon-0.1.9.dist-info/top_level.txt,sha256=nBgDUgc1tkIDIL-YY-BplWuaKgE5N2kbrpGrmGwo0ns,18
8
+ fastapi_chameleon-0.1.9.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.36.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ fastapi_chameleon