Pyjoyment 0.1.0__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.
- Pyjo/App/ASGI.py +735 -0
- Pyjo/App/CGI.py +773 -0
- Pyjo/App/FastCGI.py +631 -0
- Pyjo/App/Lambda.py +987 -0
- Pyjo/App/WSGI.py +427 -0
- Pyjo/App/__init__.py +409 -0
- Pyjo/Asset/File.py +377 -0
- Pyjo/Asset/Memory.py +235 -0
- Pyjo/Asset/__init__.py +200 -0
- Pyjo/Base.py +215 -0
- Pyjo/Cache.py +119 -0
- Pyjo/Collection.py +570 -0
- Pyjo/Content/MultiPart.py +325 -0
- Pyjo/Content/Single.py +193 -0
- Pyjo/Content/__init__.py +806 -0
- Pyjo/Cookie/Request.py +90 -0
- Pyjo/Cookie/Response.py +294 -0
- Pyjo/Cookie/__init__.py +143 -0
- Pyjo/DOM/CSS.py +1019 -0
- Pyjo/DOM/HTML.py +550 -0
- Pyjo/DOM/__init__.py +1329 -0
- Pyjo/Date.py +294 -0
- Pyjo/EventEmitter.py +522 -0
- Pyjo/Exception.py +494 -0
- Pyjo/File.py +959 -0
- Pyjo/GetOpt.py +605 -0
- Pyjo/Headers.py +760 -0
- Pyjo/HelloWorld.py +77 -0
- Pyjo/Home.py +109 -0
- Pyjo/IOLoop/ChildProcess.py +591 -0
- Pyjo/IOLoop/Client.py +736 -0
- Pyjo/IOLoop/Datagram.py +982 -0
- Pyjo/IOLoop/Messages.py +664 -0
- Pyjo/IOLoop/Server.py +458 -0
- Pyjo/IOLoop/Stdio.py +446 -0
- Pyjo/IOLoop/Stream.py +644 -0
- Pyjo/IOLoop/Subprocess.py +419 -0
- Pyjo/IOLoop/TLS.py +360 -0
- Pyjo/IOLoop/__init__.py +1036 -0
- Pyjo/IOLoop/certs/README.md +41 -0
- Pyjo/IOLoop/certs/ca.crt +20 -0
- Pyjo/IOLoop/certs/server.crt +21 -0
- Pyjo/IOLoop/certs/server.key +28 -0
- Pyjo/JSON/Pointer.py +135 -0
- Pyjo/JSON/RPC.py +772 -0
- Pyjo/JSON/Schema.py +2506 -0
- Pyjo/JSON/__init__.py +573 -0
- Pyjo/Loader.py +342 -0
- Pyjo/Log.py +723 -0
- Pyjo/Message/Request.py +725 -0
- Pyjo/Message/Response.py +476 -0
- Pyjo/Message/__init__.py +830 -0
- Pyjo/Parameters.py +472 -0
- Pyjo/Path.py +419 -0
- Pyjo/Promise.py +894 -0
- Pyjo/Prove.py +1305 -0
- Pyjo/Reactor/Asyncio.py +854 -0
- Pyjo/Reactor/Poll.py +439 -0
- Pyjo/Reactor/__init__.py +525 -0
- Pyjo/SSE.py +119 -0
- Pyjo/Server/ASGI.py +486 -0
- Pyjo/Server/CGI.py +259 -0
- Pyjo/Server/Daemon.py +1007 -0
- Pyjo/Server/FastCGI.py +517 -0
- Pyjo/Server/Hot/__init__.py +687 -0
- Pyjo/Server/Hot/__main__.py +5 -0
- Pyjo/Server/Lambda.py +641 -0
- Pyjo/Server/Prefork.py +917 -0
- Pyjo/Server/Prethread.py +394 -0
- Pyjo/Server/Reload/Backend/Poll.py +114 -0
- Pyjo/Server/Reload/Backend/__init__.py +126 -0
- Pyjo/Server/Reload/__init__.py +482 -0
- Pyjo/Server/Reload/__main__.py +5 -0
- Pyjo/Server/Stdio.py +228 -0
- Pyjo/Server/WSGI.py +349 -0
- Pyjo/Server/__init__.py +396 -0
- Pyjo/String/Bytes.py +532 -0
- Pyjo/String/HTML.py +210 -0
- Pyjo/String/Mixin.py +333 -0
- Pyjo/String/Template.py +470 -0
- Pyjo/String/Unicode.py +553 -0
- Pyjo/String/__init__.py +0 -0
- Pyjo/TOML.py +232 -0
- Pyjo/Template.py +1290 -0
- Pyjo/Test/Pyjo.py +1454 -0
- Pyjo/Test/__init__.py +1233 -0
- Pyjo/Test/pytest_plugin.py +305 -0
- Pyjo/Transaction/HTTP.py +374 -0
- Pyjo/Transaction/WebSocket.py +709 -0
- Pyjo/Transaction/__init__.py +429 -0
- Pyjo/URL/Template.py +459 -0
- Pyjo/URL/__init__.py +651 -0
- Pyjo/Upload.py +139 -0
- Pyjo/UserAgent/CookieJar.py +391 -0
- Pyjo/UserAgent/Proxy.py +138 -0
- Pyjo/UserAgent/Server.py +239 -0
- Pyjo/UserAgent/Transactor.py +766 -0
- Pyjo/UserAgent/__init__.py +1243 -0
- Pyjo/Util.py +3567 -0
- Pyjo/WebSocket.py +332 -0
- Pyjo/YAML.py +1167 -0
- Pyjo/__init__.py +441 -0
- Pyjo/__main__.py +35 -0
- Pyjo/py.typed +0 -0
- Pyjoyment/Command/Author/__init__.py +20 -0
- Pyjoyment/Command/Author/generate/__init__.py +106 -0
- Pyjoyment/Command/Author/generate/app.py +299 -0
- Pyjoyment/Command/Author/generate/dockerfile.py +281 -0
- Pyjoyment/Command/Author/generate/kubernetes.py +514 -0
- Pyjoyment/Command/Author/generate/lambda_zip.py +372 -0
- Pyjoyment/Command/Author/generate/lite_app.py +113 -0
- Pyjoyment/Command/Author/generate/plugin.py +267 -0
- Pyjoyment/Command/Author/generate/pyproject.py +123 -0
- Pyjoyment/Command/Author/inflate.py +101 -0
- Pyjoyment/Command/__init__.py +332 -0
- Pyjoyment/Command/asgi.py +92 -0
- Pyjoyment/Command/cgi.py +90 -0
- Pyjoyment/Command/daemon.py +160 -0
- Pyjoyment/Command/eval.py +128 -0
- Pyjoyment/Command/fastcgi.py +99 -0
- Pyjoyment/Command/get.py +305 -0
- Pyjoyment/Command/lambda.py +117 -0
- Pyjoyment/Command/prefork.py +181 -0
- Pyjoyment/Command/prethread.py +126 -0
- Pyjoyment/Command/routes.py +133 -0
- Pyjoyment/Command/stdio.py +92 -0
- Pyjoyment/Command/version.py +141 -0
- Pyjoyment/Command/wsgi.py +93 -0
- Pyjoyment/Commands.py +546 -0
- Pyjoyment/Controller.py +1307 -0
- Pyjoyment/HelloWorld.py +56 -0
- Pyjoyment/Lite.py +494 -0
- Pyjoyment/Plugin/AllowedHosts.py +205 -0
- Pyjoyment/Plugin/Config.py +248 -0
- Pyjoyment/Plugin/DefaultHelpers.py +1202 -0
- Pyjoyment/Plugin/EPLRenderer.py +134 -0
- Pyjoyment/Plugin/EPRenderer.py +212 -0
- Pyjoyment/Plugin/HeaderCondition.py +98 -0
- Pyjoyment/Plugin/Health.py +325 -0
- Pyjoyment/Plugin/JSONConfig.py +172 -0
- Pyjoyment/Plugin/Mount.py +223 -0
- Pyjoyment/Plugin/PyRenderer.py +209 -0
- Pyjoyment/Plugin/TOMLConfig.py +141 -0
- Pyjoyment/Plugin/TagHelpers.py +959 -0
- Pyjoyment/Plugin/YAMLConfig.py +178 -0
- Pyjoyment/Plugin/__init__.py +80 -0
- Pyjoyment/Plugins.py +215 -0
- Pyjoyment/Renderer.py +673 -0
- Pyjoyment/Routes/Match.py +251 -0
- Pyjoyment/Routes/Pattern.py +443 -0
- Pyjoyment/Routes/Route.py +827 -0
- Pyjoyment/Routes/__init__.py +419 -0
- Pyjoyment/Sessions.py +255 -0
- Pyjoyment/Static.py +421 -0
- Pyjoyment/Types.py +238 -0
- Pyjoyment/Validator/Validation.py +395 -0
- Pyjoyment/Validator/__init__.py +304 -0
- Pyjoyment/__init__.py +1083 -0
- Pyjoyment/__main__.py +5 -0
- Pyjoyment/py.typed +0 -0
- Pyjoyment/resources/public/favicon.ico +0 -0
- Pyjoyment/resources/public/favicon.svg +345 -0
- Pyjoyment/resources/public/pyjo/bootstrap/LICENSE +21 -0
- Pyjoyment/resources/public/pyjo/bootstrap/bootstrap.bundle.min.js.map +1 -0
- Pyjoyment/resources/public/pyjo/bootstrap/bootstrap.css +6 -0
- Pyjoyment/resources/public/pyjo/bootstrap/bootstrap.js +7 -0
- Pyjoyment/resources/public/pyjo/bootstrap/bootstrap.min.css.map +1 -0
- Pyjoyment/resources/public/pyjo/failunicat.png +0 -0
- Pyjoyment/resources/public/pyjo/failunicat.svg +50 -0
- Pyjoyment/resources/public/pyjo/highlight.js/LICENSE +29 -0
- Pyjoyment/resources/public/pyjo/highlight.js/highlight-mojo-dark.css +56 -0
- Pyjoyment/resources/public/pyjo/highlight.js/highlight.min.js +1262 -0
- Pyjoyment/resources/public/pyjo/highlight.js/pyjoyment.min.js +1 -0
- Pyjoyment/resources/public/pyjo/logo-black-4x.png +0 -0
- Pyjoyment/resources/public/pyjo/logo-black-4x.svg +346 -0
- Pyjoyment/resources/public/pyjo/logo-white-2x.png +0 -0
- Pyjoyment/resources/public/pyjo/logo-white-2x.svg +346 -0
- Pyjoyment/resources/public/pyjo/logo-white-4x.png +0 -0
- Pyjoyment/resources/public/pyjo/logo-white-4x.svg +346 -0
- Pyjoyment/resources/public/pyjo/logo-white.png +0 -0
- Pyjoyment/resources/public/pyjo/logo-white.svg +346 -0
- Pyjoyment/resources/public/pyjo/logo.png +0 -0
- Pyjoyment/resources/public/pyjo/logo.svg +346 -0
- Pyjoyment/resources/public/pyjo/notfound.png +0 -0
- Pyjoyment/resources/public/pyjo/notfound.svg +3 -0
- Pyjoyment/resources/public/pyjo/nounicat.png +0 -0
- Pyjoyment/resources/public/pyjo/nounicat.svg +5 -0
- Pyjoyment/resources/public/pyjo/pinstripe-dark.png +0 -0
- Pyjoyment/resources/public/pyjo/pinstripe-dark.svg +4 -0
- Pyjoyment/resources/public/pyjo/pinstripe-light.png +0 -0
- Pyjoyment/resources/public/pyjo/pinstripe-light.svg +4 -0
- Pyjoyment/resources/public/pyjo/pyjo.css +204 -0
- Pyjoyment/resources/templates/pyjo/debug.html.ep +346 -0
- Pyjoyment/resources/templates/pyjo/exception.html.ep +32 -0
- Pyjoyment/resources/templates/pyjo/not_found.html.ep +45 -0
- pyjoyment-0.1.0.dist-info/METADATA +376 -0
- pyjoyment-0.1.0.dist-info/RECORD +200 -0
- pyjoyment-0.1.0.dist-info/WHEEL +4 -0
- pyjoyment-0.1.0.dist-info/entry_points.txt +8 -0
- pyjoyment-0.1.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pyjoyment.Plugin.YAMLConfig - YAML configuration plugin
|
|
3
|
+
=======================================================
|
|
4
|
+
::
|
|
5
|
+
|
|
6
|
+
# myapp.yml (it's just YAML with embedded Python)
|
|
7
|
+
---
|
|
8
|
+
foo: bar
|
|
9
|
+
baz:
|
|
10
|
+
- ♥
|
|
11
|
+
music_dir: <%= app.home.child('music') %>
|
|
12
|
+
|
|
13
|
+
# Pyjoyment
|
|
14
|
+
config = app.plugin('YAMLConfig')
|
|
15
|
+
print(config['foo'])
|
|
16
|
+
|
|
17
|
+
# Pyjoyment.Lite
|
|
18
|
+
config = plugin('YAMLConfig')
|
|
19
|
+
print(config['foo'])
|
|
20
|
+
|
|
21
|
+
# foo.html.ep
|
|
22
|
+
%= config()['foo']
|
|
23
|
+
|
|
24
|
+
# The configuration is available application-wide
|
|
25
|
+
config = app.config()
|
|
26
|
+
print(config['foo'])
|
|
27
|
+
|
|
28
|
+
# Everything can be customized with options
|
|
29
|
+
config = plugin('YAMLConfig', file='/etc/myapp.conf')
|
|
30
|
+
|
|
31
|
+
:mod:`Pyjoyment.Plugin.YAMLConfig` is a YAML configuration plugin that
|
|
32
|
+
preprocesses its input with :mod:`Pyjo.Template`. By default it uses
|
|
33
|
+
:mod:`Pyjo.YAML` for parsing, which is not the best YAML module available, but
|
|
34
|
+
good enough for most config files. If you need something more correct you can
|
|
35
|
+
use a different module like PyYAML with the ``module`` option.
|
|
36
|
+
|
|
37
|
+
The application object can be accessed via ``app``. A default configuration
|
|
38
|
+
filename in the application home directory will be generated from the value
|
|
39
|
+
of :attr:`Pyjoyment.Pyjoyment_App.moniker` (``$moniker.yml``). You can extend
|
|
40
|
+
the normal configuration file ``$moniker.yml`` with ``mode`` specific ones
|
|
41
|
+
like ``$moniker.$mode.yml``, which will be detected automatically.
|
|
42
|
+
|
|
43
|
+
These configuration values are currently reserved:
|
|
44
|
+
|
|
45
|
+
``config_override``
|
|
46
|
+
If this configuration value has been set in
|
|
47
|
+
:meth:`Pyjoyment.Pyjoyment_App.config` when this plugin is loaded, it will
|
|
48
|
+
not do anything besides loading deployment specific plugins.
|
|
49
|
+
|
|
50
|
+
``plugins`` ::
|
|
51
|
+
|
|
52
|
+
plugins:
|
|
53
|
+
- SetUserGroup:
|
|
54
|
+
user: sri
|
|
55
|
+
group: staff
|
|
56
|
+
|
|
57
|
+
One or more deployment specific plugins that should be loaded right after
|
|
58
|
+
this plugin has been loaded.
|
|
59
|
+
|
|
60
|
+
The code of this plugin is a good example for learning to build new plugins,
|
|
61
|
+
you're welcome to fork it.
|
|
62
|
+
|
|
63
|
+
See :mod:`Pyjoyment.Plugins` for a list of plugins that are available by
|
|
64
|
+
default.
|
|
65
|
+
|
|
66
|
+
Options
|
|
67
|
+
-------
|
|
68
|
+
|
|
69
|
+
:mod:`Pyjoyment.Plugin.YAMLConfig` inherits all options from
|
|
70
|
+
:mod:`Pyjoyment.Plugin.JSONConfig` and supports the following new ones.
|
|
71
|
+
|
|
72
|
+
module ::
|
|
73
|
+
|
|
74
|
+
# Pyjoyment.Lite
|
|
75
|
+
plugin('YAMLConfig', module='yaml')
|
|
76
|
+
plugin('YAMLConfig', module=yaml.safe_load)
|
|
77
|
+
|
|
78
|
+
Alternative YAML module to use for parsing, whose function ``safe_load``, or
|
|
79
|
+
``load``, takes a string, or such a function.
|
|
80
|
+
|
|
81
|
+
See also
|
|
82
|
+
--------
|
|
83
|
+
|
|
84
|
+
:mod:`Pyjoyment`, https://mojolicious.org.
|
|
85
|
+
|
|
86
|
+
Ported from `Mojolicious::Plugin::NotYAMLConfig
|
|
87
|
+
<https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Plugin/NotYAMLConfig.pm>`_ of Mojolicious 9.49.
|
|
88
|
+
|
|
89
|
+
Classes
|
|
90
|
+
-------
|
|
91
|
+
"""
|
|
92
|
+
|
|
93
|
+
# Renamed from Mojolicious: YAMLConfig, where Mojo has NotYAMLConfig, as the file is YAML once its template is rendered,
|
|
94
|
+
# as the files of JSONConfig and TOMLConfig are JSON and TOML
|
|
95
|
+
|
|
96
|
+
import Pyjo.Exception
|
|
97
|
+
import Pyjo.YAML
|
|
98
|
+
import Pyjoyment.Plugin.JSONConfig
|
|
99
|
+
|
|
100
|
+
import importlib
|
|
101
|
+
|
|
102
|
+
from collections.abc import Callable
|
|
103
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
if TYPE_CHECKING:
|
|
107
|
+
import Pyjoyment
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class Pyjoyment_Plugin_YAMLConfig(Pyjoyment.Plugin.JSONConfig.object):
|
|
111
|
+
"""
|
|
112
|
+
:mod:`Pyjoyment.Plugin.YAMLConfig` inherits all methods from
|
|
113
|
+
:mod:`Pyjoyment.Plugin.JSONConfig` and implements the following new ones.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def __init__(self) -> None:
|
|
117
|
+
super().__init__()
|
|
118
|
+
self._yaml: Callable[[str], Any] = Pyjo.YAML.load
|
|
119
|
+
|
|
120
|
+
def parse(self, content: str, file: str, conf: dict[str, Any], app: 'Pyjoyment.object') -> dict[str, Any]:
|
|
121
|
+
"""::
|
|
122
|
+
|
|
123
|
+
plugin.parse(content, file, conf, app)
|
|
124
|
+
|
|
125
|
+
Process content with
|
|
126
|
+
:meth:`~Pyjoyment.Plugin.JSONConfig.Pyjoyment_Plugin_JSONConfig.render`
|
|
127
|
+
and parse it with :mod:`Pyjo.YAML`. ::
|
|
128
|
+
|
|
129
|
+
def parse(self, content, file, conf, app):
|
|
130
|
+
...
|
|
131
|
+
content = self.render(content, file, conf, app)
|
|
132
|
+
...
|
|
133
|
+
return config
|
|
134
|
+
"""
|
|
135
|
+
try:
|
|
136
|
+
config = self._yaml(self.render(content, file, conf, app))
|
|
137
|
+
except Exception as e:
|
|
138
|
+
raise Pyjo.Exception.new(f'Can\'t load configuration from file "{file}": {e}') from e
|
|
139
|
+
if not isinstance(config, dict):
|
|
140
|
+
raise Pyjo.Exception.new(f'Configuration file "{file}" did not return a YAML mapping')
|
|
141
|
+
return cast(dict[str, Any], config)
|
|
142
|
+
|
|
143
|
+
def register(self, app: 'Pyjoyment.object', conf: dict[str, Any] | None = None) -> dict[str, Any]:
|
|
144
|
+
"""::
|
|
145
|
+
|
|
146
|
+
config = plugin.register(Pyjoyment.new())
|
|
147
|
+
config = plugin.register(Pyjoyment.new(), {'file': '/etc/foo.conf'})
|
|
148
|
+
|
|
149
|
+
Register plugin in :mod:`Pyjoyment` application and merge
|
|
150
|
+
configuration.
|
|
151
|
+
"""
|
|
152
|
+
conf = {'ext': 'yml', **(conf or {})}
|
|
153
|
+
|
|
154
|
+
self._yaml = Pyjo.YAML.load
|
|
155
|
+
if module := conf.get('module'):
|
|
156
|
+
if (load := _load(module)) is None:
|
|
157
|
+
raise Pyjo.Exception.new(f'YAML module {module} has no Load function')
|
|
158
|
+
self._yaml = load
|
|
159
|
+
|
|
160
|
+
return super().register(app, conf)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# Not in Mojolicious: a function of a module, safe_load or load, as the YAML modules of Python name it, or the function
|
|
164
|
+
# itself, where Mojo takes the function Load of a module
|
|
165
|
+
def _load(module: Any) -> Callable[[str], Any] | None:
|
|
166
|
+
if callable(module):
|
|
167
|
+
return cast(Callable[[str], Any], module)
|
|
168
|
+
try:
|
|
169
|
+
mod = importlib.import_module(str(module))
|
|
170
|
+
except ImportError:
|
|
171
|
+
return None
|
|
172
|
+
load = getattr(mod, 'safe_load', None) or getattr(mod, 'load', None)
|
|
173
|
+
return cast(Callable[[str], Any], load) if callable(load) else None
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
new = Pyjoyment_Plugin_YAMLConfig.new
|
|
177
|
+
object = Pyjoyment_Plugin_YAMLConfig
|
|
178
|
+
YAMLConfig = Pyjoyment_Plugin_YAMLConfig
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pyjoyment.Plugin - Plugin base class
|
|
3
|
+
====================================
|
|
4
|
+
::
|
|
5
|
+
|
|
6
|
+
# CamelCase plugin name
|
|
7
|
+
from Pyjoyment.Plugin import Plugin
|
|
8
|
+
|
|
9
|
+
class Pyjoyment_Plugin_MyPlugin(Plugin):
|
|
10
|
+
def register(self, app, conf):
|
|
11
|
+
# Magic here! :)
|
|
12
|
+
...
|
|
13
|
+
|
|
14
|
+
object = Pyjoyment_Plugin_MyPlugin
|
|
15
|
+
|
|
16
|
+
# Or import the module, as in Google Python Style Guide
|
|
17
|
+
|
|
18
|
+
# CamelCase plugin name
|
|
19
|
+
import Pyjoyment.Plugin
|
|
20
|
+
|
|
21
|
+
class Pyjoyment_Plugin_MyPlugin(Pyjoyment.Plugin.object):
|
|
22
|
+
def register(self, app, conf):
|
|
23
|
+
# Magic here! :)
|
|
24
|
+
...
|
|
25
|
+
|
|
26
|
+
object = Pyjoyment_Plugin_MyPlugin
|
|
27
|
+
|
|
28
|
+
:mod:`Pyjoyment.Plugin` is an abstract base class for :mod:`Pyjoyment`
|
|
29
|
+
plugins.
|
|
30
|
+
|
|
31
|
+
See :mod:`Pyjoyment.Plugins` for a list of plugins that are available by
|
|
32
|
+
default.
|
|
33
|
+
|
|
34
|
+
A plugin of another distribution is a module in the namespace
|
|
35
|
+
``Pyjoyment.Plugin``, which :func:`pkgutil.extend_path` keeps open, and the
|
|
36
|
+
class that the module names ``object``.
|
|
37
|
+
|
|
38
|
+
See also
|
|
39
|
+
--------
|
|
40
|
+
|
|
41
|
+
:mod:`Pyjoyment`, https://mojolicious.org.
|
|
42
|
+
|
|
43
|
+
Ported from `Mojolicious::Plugin <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Plugin.pm>`_
|
|
44
|
+
of Mojolicious 9.49.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
import Pyjo.Base
|
|
48
|
+
|
|
49
|
+
from pkgutil import extend_path
|
|
50
|
+
from typing import TYPE_CHECKING, Any
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if TYPE_CHECKING:
|
|
54
|
+
import Pyjoyment
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class Pyjoyment_Plugin(Pyjo.Base.object):
|
|
58
|
+
"""
|
|
59
|
+
:mod:`Pyjoyment.Plugin` inherits all methods from :mod:`Pyjo.Base` and
|
|
60
|
+
implements the following new ones.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
def register(self, app: 'Pyjoyment.object', conf: dict[str, Any]) -> Any:
|
|
64
|
+
"""::
|
|
65
|
+
|
|
66
|
+
plugin.register(Pyjoyment.new(), {})
|
|
67
|
+
plugin.register(Pyjoyment.new(), {'foo': 'bar'})
|
|
68
|
+
|
|
69
|
+
This method will be called by :mod:`Pyjoyment.Plugins` at startup time.
|
|
70
|
+
Meant to be overloaded in a subclass.
|
|
71
|
+
"""
|
|
72
|
+
raise NotImplementedError('Method "register" not implemented by subclass')
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# Not in Mojolicious: a namespace that other distributions can add plugins to
|
|
76
|
+
__path__ = extend_path(__path__, __name__)
|
|
77
|
+
|
|
78
|
+
new = Pyjoyment_Plugin.new
|
|
79
|
+
object = Pyjoyment_Plugin
|
|
80
|
+
Plugin = Pyjoyment_Plugin
|
Pyjoyment/Plugins.py
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pyjoyment.Plugins - Plugin manager
|
|
3
|
+
==================================
|
|
4
|
+
::
|
|
5
|
+
|
|
6
|
+
from Pyjoyment.Plugins import Plugins
|
|
7
|
+
|
|
8
|
+
plugins = Plugins()
|
|
9
|
+
plugins.namespaces.append('MyApp.Plugin')
|
|
10
|
+
|
|
11
|
+
# Or import the module, as in Google Python Style Guide
|
|
12
|
+
|
|
13
|
+
import Pyjoyment.Plugins
|
|
14
|
+
|
|
15
|
+
plugins = Pyjoyment.Plugins.new()
|
|
16
|
+
plugins.namespaces.append('MyApp.Plugin')
|
|
17
|
+
|
|
18
|
+
:mod:`Pyjoyment.Plugins` is the plugin manager of :mod:`Pyjoyment`.
|
|
19
|
+
|
|
20
|
+
Plugins
|
|
21
|
+
-------
|
|
22
|
+
|
|
23
|
+
The following plugins are included in the :mod:`Pyjoyment` distribution as
|
|
24
|
+
examples.
|
|
25
|
+
|
|
26
|
+
:mod:`Pyjoyment.Plugin.AllowedHosts`
|
|
27
|
+
Validation of ``Host`` and ``Origin`` against DNS rebinding.
|
|
28
|
+
|
|
29
|
+
:mod:`Pyjoyment.Plugin.Config`
|
|
30
|
+
Python-ish configuration files.
|
|
31
|
+
|
|
32
|
+
:mod:`Pyjoyment.Plugin.DefaultHelpers`
|
|
33
|
+
General purpose helper collection, loaded automatically.
|
|
34
|
+
|
|
35
|
+
:mod:`Pyjoyment.Plugin.EPLRenderer`
|
|
36
|
+
Renderer for plain embedded Python templates, loaded automatically.
|
|
37
|
+
|
|
38
|
+
:mod:`Pyjoyment.Plugin.EPRenderer`
|
|
39
|
+
Renderer for more sophisticated embedded Python templates, loaded
|
|
40
|
+
automatically.
|
|
41
|
+
|
|
42
|
+
:mod:`Pyjoyment.Plugin.Health`
|
|
43
|
+
Liveness and readiness of containers and orchestrators.
|
|
44
|
+
|
|
45
|
+
:mod:`Pyjoyment.Plugin.HeaderCondition`
|
|
46
|
+
Route condition for all kinds of headers, loaded automatically.
|
|
47
|
+
|
|
48
|
+
:mod:`Pyjoyment.Plugin.JSONConfig`
|
|
49
|
+
JSON configuration files.
|
|
50
|
+
|
|
51
|
+
:mod:`Pyjoyment.Plugin.Mount`
|
|
52
|
+
Mount whole :mod:`Pyjoyment` applications.
|
|
53
|
+
|
|
54
|
+
:mod:`Pyjoyment.Plugin.PyRenderer`
|
|
55
|
+
Renderer for template strings, loaded automatically.
|
|
56
|
+
|
|
57
|
+
:mod:`Pyjoyment.Plugin.TagHelpers`
|
|
58
|
+
Template specific helper collection, loaded automatically.
|
|
59
|
+
|
|
60
|
+
:mod:`Pyjoyment.Plugin.TOMLConfig`
|
|
61
|
+
TOML configuration files.
|
|
62
|
+
|
|
63
|
+
:mod:`Pyjoyment.Plugin.YAMLConfig`
|
|
64
|
+
YAML configuration files.
|
|
65
|
+
|
|
66
|
+
Events
|
|
67
|
+
------
|
|
68
|
+
|
|
69
|
+
:mod:`Pyjoyment.Plugins` inherits all events from :mod:`Pyjo.EventEmitter`.
|
|
70
|
+
|
|
71
|
+
See also
|
|
72
|
+
--------
|
|
73
|
+
|
|
74
|
+
:mod:`Pyjoyment`, https://mojolicious.org.
|
|
75
|
+
|
|
76
|
+
Ported from `Mojolicious::Plugins <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Plugins.pm>`_
|
|
77
|
+
of Mojolicious 9.49.
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
import Pyjo.EventEmitter
|
|
81
|
+
import Pyjo.Exception
|
|
82
|
+
import Pyjo.Loader
|
|
83
|
+
import Pyjoyment.Plugin
|
|
84
|
+
|
|
85
|
+
from Pyjo.Util import camelize
|
|
86
|
+
|
|
87
|
+
import re
|
|
88
|
+
|
|
89
|
+
from collections.abc import Callable
|
|
90
|
+
from typing import TYPE_CHECKING, Any, Self
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
if TYPE_CHECKING:
|
|
94
|
+
import Pyjoyment
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class Pyjoyment_Plugins(Pyjo.EventEmitter.object):
|
|
98
|
+
"""
|
|
99
|
+
:mod:`Pyjoyment.Plugins` inherits all methods from
|
|
100
|
+
:mod:`Pyjo.EventEmitter` and implements the following new ones.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
def __init__(self) -> None:
|
|
104
|
+
"""::
|
|
105
|
+
|
|
106
|
+
plugins = Pyjoyment.Plugins.new()
|
|
107
|
+
|
|
108
|
+
Construct a new :mod:`Pyjoyment.Plugins` object.
|
|
109
|
+
"""
|
|
110
|
+
super().__init__()
|
|
111
|
+
|
|
112
|
+
self.namespaces = ['Pyjoyment.Plugin']
|
|
113
|
+
"""::
|
|
114
|
+
|
|
115
|
+
namespaces = plugins.namespaces
|
|
116
|
+
plugins.namespaces = ['Pyjoyment.Plugin']
|
|
117
|
+
|
|
118
|
+
Namespaces to load plugins from, defaults to :mod:`Pyjoyment.Plugin`. ::
|
|
119
|
+
|
|
120
|
+
# Add another namespace to load plugins from
|
|
121
|
+
plugins.namespaces.append('MyApp.Plugin')
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
def emit_chain(self, name: str, *args: Any) -> Any:
|
|
125
|
+
"""::
|
|
126
|
+
|
|
127
|
+
plugins.emit_chain('foo')
|
|
128
|
+
plugins.emit_chain('foo', 123)
|
|
129
|
+
|
|
130
|
+
Emit events as chained hooks.
|
|
131
|
+
"""
|
|
132
|
+
wrapper: Callable[[], Any] | None = None
|
|
133
|
+
for cb in reversed(self.subscribers(name)):
|
|
134
|
+
wrapper = _wrap(cb, wrapper, args)
|
|
135
|
+
|
|
136
|
+
return wrapper() if wrapper is not None else None
|
|
137
|
+
|
|
138
|
+
def emit_hook(self, name: str, *args: Any) -> Self:
|
|
139
|
+
"""::
|
|
140
|
+
|
|
141
|
+
plugins = plugins.emit_hook('foo')
|
|
142
|
+
plugins = plugins.emit_hook('foo', 123)
|
|
143
|
+
|
|
144
|
+
Emit events as hooks.
|
|
145
|
+
"""
|
|
146
|
+
for cb in self.subscribers(name):
|
|
147
|
+
cb(*args)
|
|
148
|
+
return self
|
|
149
|
+
|
|
150
|
+
def emit_hook_reverse(self, name: str, *args: Any) -> Self:
|
|
151
|
+
"""::
|
|
152
|
+
|
|
153
|
+
plugins = plugins.emit_hook_reverse('foo')
|
|
154
|
+
plugins = plugins.emit_hook_reverse('foo', 123)
|
|
155
|
+
|
|
156
|
+
Emit events as hooks in reverse order.
|
|
157
|
+
"""
|
|
158
|
+
for cb in reversed(self.subscribers(name)):
|
|
159
|
+
cb(*args)
|
|
160
|
+
return self
|
|
161
|
+
|
|
162
|
+
def load_plugin(self, name: str) -> Pyjoyment.Plugin.object:
|
|
163
|
+
"""::
|
|
164
|
+
|
|
165
|
+
plugin = plugins.load_plugin('some_thing')
|
|
166
|
+
plugin = plugins.load_plugin('SomeThing')
|
|
167
|
+
plugin = plugins.load_plugin('MyApp.Plugin.SomeThing')
|
|
168
|
+
|
|
169
|
+
Load a plugin from the configured namespaces or by full module name.
|
|
170
|
+
"""
|
|
171
|
+
# Try all namespaces and full module name
|
|
172
|
+
suffix = camelize(name).replace('::', '.') if re.match(r'^[a-z]', name) else name
|
|
173
|
+
classes = [f'{namespace}.{suffix}' for namespace in self.namespaces]
|
|
174
|
+
for cls in [*classes, name]:
|
|
175
|
+
if (plugin := _load(cls)) is not None:
|
|
176
|
+
return plugin.new()
|
|
177
|
+
|
|
178
|
+
# Not found
|
|
179
|
+
raise Pyjo.Exception.new(f'Plugin "{name}" missing, maybe you need to install it?\n')
|
|
180
|
+
|
|
181
|
+
def register_plugin(
|
|
182
|
+
self, name: str, app: 'Pyjoyment.object', conf: dict[str, Any] | None = None, /, **values: Any
|
|
183
|
+
) -> Any:
|
|
184
|
+
"""::
|
|
185
|
+
|
|
186
|
+
plugins.register_plugin('some_thing', Pyjoyment.new())
|
|
187
|
+
plugins.register_plugin('some_thing', Pyjoyment.new(), foo=23)
|
|
188
|
+
plugins.register_plugin('some_thing', Pyjoyment.new(), {'foo': 23})
|
|
189
|
+
plugins.register_plugin('SomeThing', Pyjoyment.new())
|
|
190
|
+
plugins.register_plugin('SomeThing', Pyjoyment.new(), foo=23)
|
|
191
|
+
plugins.register_plugin('SomeThing', Pyjoyment.new(), {'foo': 23})
|
|
192
|
+
plugins.register_plugin('MyApp.Plugin.SomeThing', Pyjoyment.new())
|
|
193
|
+
plugins.register_plugin('MyApp.Plugin.SomeThing', Pyjoyment.new(), foo=23)
|
|
194
|
+
plugins.register_plugin('MyApp.Plugin.SomeThing', Pyjoyment.new(), {'foo': 23})
|
|
195
|
+
|
|
196
|
+
Load a plugin from the configured namespaces or by full module name and
|
|
197
|
+
run ``register``, optional arguments are passed through.
|
|
198
|
+
"""
|
|
199
|
+
return self.load_plugin(name).register(app, {**(conf or {}), **values})
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _load(name: str) -> type[Pyjoyment.Plugin.object] | None:
|
|
203
|
+
if isinstance(e := Pyjo.Loader.load_class(name), Exception):
|
|
204
|
+
raise e
|
|
205
|
+
cls = Pyjo.Loader._class(name) # pyright: ignore[reportPrivateUsage]
|
|
206
|
+
return cls if cls is not None and issubclass(cls, Pyjoyment.Plugin.object) else None
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _wrap(cb: Callable[..., Any], next: Callable[[], Any] | None, args: tuple[Any, ...]) -> Callable[[], Any]:
|
|
210
|
+
return lambda: cb(next, *args)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
new = Pyjoyment_Plugins.new
|
|
214
|
+
object = Pyjoyment_Plugins
|
|
215
|
+
Plugins = Pyjoyment_Plugins
|