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,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pyjoyment.Command.wsgi - WSGI command
|
|
3
|
+
=====================================
|
|
4
|
+
::
|
|
5
|
+
|
|
6
|
+
Usage: APPLICATION wsgi [OPTIONS]
|
|
7
|
+
|
|
8
|
+
application = app.start('wsgi')
|
|
9
|
+
PYJO_WSGI=1 gunicorn myapp:application
|
|
10
|
+
|
|
11
|
+
Options:
|
|
12
|
+
-h, --help Show this summary of available options
|
|
13
|
+
--home <path> Path to home directory of your application,
|
|
14
|
+
defaults to the value of PYJO_HOME or
|
|
15
|
+
auto-detection
|
|
16
|
+
--log-format <name> Format of log messages, "text" or "json",
|
|
17
|
+
defaults to the value of PYJO_LOG_FORMAT or
|
|
18
|
+
"text"
|
|
19
|
+
-m, --mode <name> Operating mode for your application, defaults to
|
|
20
|
+
the value of PYJO_MODE or "development"
|
|
21
|
+
|
|
22
|
+
:mod:`Pyjoyment.Command.wsgi` starts applications with the
|
|
23
|
+
:mod:`Pyjo.Server.WSGI` backend: it returns the WSGI application, which a
|
|
24
|
+
script keeps for the WSGI server that imports it. The script of an application
|
|
25
|
+
that ends with ``application = app.start()`` runs this command when the
|
|
26
|
+
``PYJO_WSGI`` environment variable is set, and the command of its arguments
|
|
27
|
+
otherwise.
|
|
28
|
+
|
|
29
|
+
This is a core command, that means it is always enabled and its code a good
|
|
30
|
+
example for learning to build new commands, you're welcome to fork it.
|
|
31
|
+
|
|
32
|
+
See :mod:`Pyjoyment.Commands` for a list of commands that are available by
|
|
33
|
+
default.
|
|
34
|
+
|
|
35
|
+
See also
|
|
36
|
+
--------
|
|
37
|
+
|
|
38
|
+
:mod:`Pyjoyment`, https://mojolicious.org.
|
|
39
|
+
|
|
40
|
+
Ported from `Mojolicious::Command::psgi
|
|
41
|
+
<https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/psgi.pm>`_ of Mojolicious 9.49, for WSGI
|
|
42
|
+
instead of PSGI.
|
|
43
|
+
|
|
44
|
+
Classes
|
|
45
|
+
-------
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
# Renamed from Mojolicious: wsgi, where Mojo has psgi, as WSGI is the PSGI of Python
|
|
49
|
+
|
|
50
|
+
import Pyjo.Server.WSGI
|
|
51
|
+
import Pyjoyment.Command
|
|
52
|
+
|
|
53
|
+
from Pyjo.Util import extract_usage
|
|
54
|
+
|
|
55
|
+
from typing import Any
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class Pyjoyment_Command_wsgi(Pyjoyment.Command.object):
|
|
59
|
+
"""
|
|
60
|
+
:mod:`Pyjoyment.Command.wsgi` inherits all attributes and methods from
|
|
61
|
+
:mod:`Pyjoyment.Command` and implements the following new ones.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
description = 'Start application with WSGI'
|
|
65
|
+
"""::
|
|
66
|
+
|
|
67
|
+
description = wsgi.description
|
|
68
|
+
wsgi.description = 'Foo'
|
|
69
|
+
|
|
70
|
+
Short description of this command, used for the command list.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
usage = extract_usage()
|
|
74
|
+
"""::
|
|
75
|
+
|
|
76
|
+
usage = wsgi.usage
|
|
77
|
+
wsgi.usage = 'Foo'
|
|
78
|
+
|
|
79
|
+
Usage information for this command, used for the help screen.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
def run(self, *args: str) -> Any:
|
|
83
|
+
"""::
|
|
84
|
+
|
|
85
|
+
application = wsgi.run()
|
|
86
|
+
|
|
87
|
+
Run this command.
|
|
88
|
+
"""
|
|
89
|
+
return Pyjo.Server.WSGI.new(app=self.app).to_wsgi_app()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
new = Pyjoyment_Command_wsgi.new
|
|
93
|
+
object = Pyjoyment_Command_wsgi
|
Pyjoyment/Commands.py
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pyjoyment.Commands - Command line interface
|
|
3
|
+
===========================================
|
|
4
|
+
::
|
|
5
|
+
|
|
6
|
+
Usage: APPLICATION COMMAND [OPTIONS]
|
|
7
|
+
|
|
8
|
+
pyjo version
|
|
9
|
+
pyjo generate lite-app
|
|
10
|
+
./myapp.py daemon -m production -l http://*:8080
|
|
11
|
+
./myapp.py get /foo
|
|
12
|
+
./myapp.py routes -v
|
|
13
|
+
|
|
14
|
+
Tip: CGI, FastCGI and AWS Lambda environments, and WSGI and ASGI ones with
|
|
15
|
+
PYJO_WSGI and PYJO_ASGI, can be automatically detected very often and
|
|
16
|
+
work without commands.
|
|
17
|
+
|
|
18
|
+
Options (for all commands):
|
|
19
|
+
-h, --help Get more information on a specific command
|
|
20
|
+
--home <path> Path to home directory of your application,
|
|
21
|
+
defaults to the value of PYJO_HOME or
|
|
22
|
+
auto-detection
|
|
23
|
+
--log-format <name> Format of log messages, "text" or "json",
|
|
24
|
+
defaults to the value of PYJO_LOG_FORMAT or
|
|
25
|
+
"text"
|
|
26
|
+
-m, --mode <name> Operating mode for your application, defaults to
|
|
27
|
+
the value of PYJO_MODE or "development"
|
|
28
|
+
|
|
29
|
+
:mod:`Pyjoyment.Commands` is the interactive command line interface for the
|
|
30
|
+
:mod:`Pyjoyment` framework. It will automatically detect available commands in
|
|
31
|
+
the ``Pyjoyment.Command`` and ``Pyjoyment.Command.Author`` namespaces.
|
|
32
|
+
|
|
33
|
+
The command line interface of :mod:`Pyjoyment.HelloWorld` is the ``pyjo``
|
|
34
|
+
script, or ``python -m Pyjoyment``.
|
|
35
|
+
|
|
36
|
+
Commands
|
|
37
|
+
--------
|
|
38
|
+
|
|
39
|
+
These commands are available by default.
|
|
40
|
+
|
|
41
|
+
asgi
|
|
42
|
+
~~~~
|
|
43
|
+
::
|
|
44
|
+
|
|
45
|
+
application = app.start('asgi')
|
|
46
|
+
|
|
47
|
+
Use :mod:`Pyjoyment.Command.asgi` to start application with ASGI backend,
|
|
48
|
+
auto detected with the ``PYJO_ASGI`` environment variable.
|
|
49
|
+
|
|
50
|
+
cgi
|
|
51
|
+
~~~
|
|
52
|
+
::
|
|
53
|
+
|
|
54
|
+
$ ./myapp.py cgi
|
|
55
|
+
|
|
56
|
+
Use :mod:`Pyjoyment.Command.cgi` to start application with CGI backend,
|
|
57
|
+
usually auto detected.
|
|
58
|
+
|
|
59
|
+
daemon
|
|
60
|
+
~~~~~~
|
|
61
|
+
::
|
|
62
|
+
|
|
63
|
+
$ ./myapp.py daemon
|
|
64
|
+
|
|
65
|
+
Use :mod:`Pyjoyment.Command.daemon` to start application with standalone
|
|
66
|
+
HTTP and WebSocket server.
|
|
67
|
+
|
|
68
|
+
eval
|
|
69
|
+
~~~~
|
|
70
|
+
::
|
|
71
|
+
|
|
72
|
+
$ ./myapp.py eval 'print(app.home)'
|
|
73
|
+
|
|
74
|
+
Use :mod:`Pyjoyment.Command.eval` to run code against application.
|
|
75
|
+
|
|
76
|
+
fastcgi
|
|
77
|
+
~~~~~~~
|
|
78
|
+
::
|
|
79
|
+
|
|
80
|
+
$ ./myapp.py fastcgi
|
|
81
|
+
|
|
82
|
+
Use :mod:`Pyjoyment.Command.fastcgi` to start application with the FastCGI
|
|
83
|
+
of a web server that starts it, usually auto detected.
|
|
84
|
+
|
|
85
|
+
generate
|
|
86
|
+
~~~~~~~~
|
|
87
|
+
::
|
|
88
|
+
|
|
89
|
+
$ pyjo generate
|
|
90
|
+
$ pyjo generate help
|
|
91
|
+
$ ./myapp.py generate help
|
|
92
|
+
|
|
93
|
+
List available generator commands with short descriptions. ::
|
|
94
|
+
|
|
95
|
+
$ pyjo generate help <generator>
|
|
96
|
+
$ ./myapp.py generate help <generator>
|
|
97
|
+
|
|
98
|
+
List available options for generator command with short descriptions.
|
|
99
|
+
|
|
100
|
+
generate app
|
|
101
|
+
~~~~~~~~~~~~
|
|
102
|
+
::
|
|
103
|
+
|
|
104
|
+
$ pyjo generate app <AppName>
|
|
105
|
+
|
|
106
|
+
Use :mod:`Pyjoyment.Command.Author.generate.app` to generate application
|
|
107
|
+
directory structure for a fully functional :mod:`Pyjoyment` application.
|
|
108
|
+
|
|
109
|
+
generate dockerfile
|
|
110
|
+
~~~~~~~~~~~~~~~~~~~
|
|
111
|
+
::
|
|
112
|
+
|
|
113
|
+
$ ./myapp.py generate dockerfile
|
|
114
|
+
$ python -m MyApp generate dockerfile
|
|
115
|
+
|
|
116
|
+
Use :mod:`Pyjoyment.Command.Author.generate.dockerfile` to generate
|
|
117
|
+
``Dockerfile`` for application.
|
|
118
|
+
|
|
119
|
+
generate kubernetes
|
|
120
|
+
~~~~~~~~~~~~~~~~~~~
|
|
121
|
+
::
|
|
122
|
+
|
|
123
|
+
$ ./myapp.py generate kubernetes
|
|
124
|
+
$ python -m MyApp generate kubernetes
|
|
125
|
+
|
|
126
|
+
Use :mod:`Pyjoyment.Command.Author.generate.kubernetes` to generate the
|
|
127
|
+
manifests of Kubernetes for application, with the overlays of Kustomize for
|
|
128
|
+
development and production.
|
|
129
|
+
|
|
130
|
+
generate lambda-zip
|
|
131
|
+
~~~~~~~~~~~~~~~~~~~
|
|
132
|
+
::
|
|
133
|
+
|
|
134
|
+
$ ./myapp.py generate lambda-zip
|
|
135
|
+
$ python -m MyApp generate lambda-zip
|
|
136
|
+
|
|
137
|
+
Use :mod:`Pyjoyment.Command.Author.generate.lambda_zip` to generate the ZIP
|
|
138
|
+
files of an event function of AWS Lambda on a custom runtime, with a layer of
|
|
139
|
+
Python.
|
|
140
|
+
|
|
141
|
+
generate lite-app
|
|
142
|
+
~~~~~~~~~~~~~~~~~
|
|
143
|
+
::
|
|
144
|
+
|
|
145
|
+
$ pyjo generate lite-app
|
|
146
|
+
|
|
147
|
+
Use :mod:`Pyjoyment.Command.Author.generate.lite_app` to generate a fully
|
|
148
|
+
functional :mod:`Pyjoyment.Lite` application.
|
|
149
|
+
|
|
150
|
+
generate plugin
|
|
151
|
+
~~~~~~~~~~~~~~~
|
|
152
|
+
::
|
|
153
|
+
|
|
154
|
+
$ pyjo generate plugin <PluginName>
|
|
155
|
+
|
|
156
|
+
Use :mod:`Pyjoyment.Command.Author.generate.plugin` to generate directory
|
|
157
|
+
structure for a fully functional :mod:`Pyjoyment` plugin.
|
|
158
|
+
|
|
159
|
+
generate pyproject
|
|
160
|
+
~~~~~~~~~~~~~~~~~~
|
|
161
|
+
::
|
|
162
|
+
|
|
163
|
+
$ pyjo generate pyproject
|
|
164
|
+
$ ./myapp.py generate pyproject
|
|
165
|
+
|
|
166
|
+
Use :mod:`Pyjoyment.Command.Author.generate.pyproject` to generate
|
|
167
|
+
``pyproject.toml`` file for application.
|
|
168
|
+
|
|
169
|
+
get
|
|
170
|
+
~~~
|
|
171
|
+
::
|
|
172
|
+
|
|
173
|
+
$ pyjo get https://mojolicious.org
|
|
174
|
+
$ ./myapp.py get /foo
|
|
175
|
+
|
|
176
|
+
Use :mod:`Pyjoyment.Command.get` to perform requests to remote host or local
|
|
177
|
+
application.
|
|
178
|
+
|
|
179
|
+
help
|
|
180
|
+
~~~~
|
|
181
|
+
::
|
|
182
|
+
|
|
183
|
+
$ pyjo
|
|
184
|
+
$ pyjo help
|
|
185
|
+
$ ./myapp.py help
|
|
186
|
+
|
|
187
|
+
List available commands with short descriptions. ::
|
|
188
|
+
|
|
189
|
+
$ pyjo help <command>
|
|
190
|
+
$ ./myapp.py help <command>
|
|
191
|
+
|
|
192
|
+
List available options for the command with short descriptions.
|
|
193
|
+
|
|
194
|
+
inflate
|
|
195
|
+
~~~~~~~
|
|
196
|
+
::
|
|
197
|
+
|
|
198
|
+
$ ./myapp.py inflate
|
|
199
|
+
|
|
200
|
+
Use :mod:`Pyjoyment.Command.Author.inflate` to turn templates and static files
|
|
201
|
+
embedded in the ``DATA`` sections of your application into real files.
|
|
202
|
+
|
|
203
|
+
lambda
|
|
204
|
+
~~~~~~
|
|
205
|
+
::
|
|
206
|
+
|
|
207
|
+
handler = app.start('lambda')
|
|
208
|
+
|
|
209
|
+
Use :mod:`Pyjoyment.Command.lambda` to start application as an event function
|
|
210
|
+
of AWS Lambda, auto detected with the ``AWS_LAMBDA_RUNTIME_API`` environment
|
|
211
|
+
variable.
|
|
212
|
+
|
|
213
|
+
prefork
|
|
214
|
+
~~~~~~~
|
|
215
|
+
::
|
|
216
|
+
|
|
217
|
+
$ ./myapp.py prefork
|
|
218
|
+
|
|
219
|
+
Use :mod:`Pyjoyment.Command.prefork` to start application with standalone
|
|
220
|
+
pre-forking HTTP and WebSocket server.
|
|
221
|
+
|
|
222
|
+
prethread
|
|
223
|
+
~~~~~~~~~
|
|
224
|
+
::
|
|
225
|
+
|
|
226
|
+
$ ./myapp.py prethread
|
|
227
|
+
|
|
228
|
+
Use :mod:`Pyjoyment.Command.prethread` to start application with standalone
|
|
229
|
+
pre-threading HTTP and WebSocket server.
|
|
230
|
+
|
|
231
|
+
routes
|
|
232
|
+
~~~~~~
|
|
233
|
+
::
|
|
234
|
+
|
|
235
|
+
$ ./myapp.py routes
|
|
236
|
+
|
|
237
|
+
Use :mod:`Pyjoyment.Command.routes` to list application routes.
|
|
238
|
+
|
|
239
|
+
stdio
|
|
240
|
+
~~~~~
|
|
241
|
+
::
|
|
242
|
+
|
|
243
|
+
$ ./myapp.py stdio
|
|
244
|
+
|
|
245
|
+
Use :mod:`Pyjoyment.Command.stdio` to start application on the standard input
|
|
246
|
+
and output, with the protocol that the application or a plugin gives.
|
|
247
|
+
|
|
248
|
+
version
|
|
249
|
+
~~~~~~~
|
|
250
|
+
::
|
|
251
|
+
|
|
252
|
+
$ pyjo version
|
|
253
|
+
$ ./myapp.py version
|
|
254
|
+
|
|
255
|
+
Use :mod:`Pyjoyment.Command.version` to show version information for
|
|
256
|
+
available core and optional modules, very useful for debugging.
|
|
257
|
+
|
|
258
|
+
wsgi
|
|
259
|
+
~~~~
|
|
260
|
+
::
|
|
261
|
+
|
|
262
|
+
application = app.start('wsgi')
|
|
263
|
+
|
|
264
|
+
Use :mod:`Pyjoyment.Command.wsgi` to start application with WSGI backend,
|
|
265
|
+
auto detected with the ``PYJO_WSGI`` environment variable.
|
|
266
|
+
|
|
267
|
+
See also
|
|
268
|
+
--------
|
|
269
|
+
|
|
270
|
+
:mod:`Pyjoyment`, https://mojolicious.org.
|
|
271
|
+
|
|
272
|
+
Ported from `Mojolicious::Commands <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Commands.pm>`_
|
|
273
|
+
of Mojolicious 9.49.
|
|
274
|
+
|
|
275
|
+
Classes
|
|
276
|
+
-------
|
|
277
|
+
"""
|
|
278
|
+
|
|
279
|
+
# Left out from Mojolicious: the command cpanify, as uv publish uploads distributions to PyPI
|
|
280
|
+
|
|
281
|
+
import Pyjo.Exception
|
|
282
|
+
import Pyjo.GetOpt
|
|
283
|
+
import Pyjo.Loader
|
|
284
|
+
import Pyjo.Server
|
|
285
|
+
import Pyjoyment.Command
|
|
286
|
+
|
|
287
|
+
from Pyjo.Util import getopt, setenv, tablify
|
|
288
|
+
|
|
289
|
+
import errno
|
|
290
|
+
import os
|
|
291
|
+
import re
|
|
292
|
+
import socket
|
|
293
|
+
import sys
|
|
294
|
+
|
|
295
|
+
from collections.abc import Sequence
|
|
296
|
+
from typing import Any
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
class Pyjoyment_Commands(Pyjoyment.Command.object):
|
|
300
|
+
"""
|
|
301
|
+
:mod:`Pyjoyment.Commands` inherits all attributes and methods from
|
|
302
|
+
:mod:`Pyjoyment.Command` and implements the following new ones.
|
|
303
|
+
"""
|
|
304
|
+
|
|
305
|
+
hint: str = "\nSee 'APPLICATION help COMMAND' for more information on a specific command.\n"
|
|
306
|
+
"""::
|
|
307
|
+
|
|
308
|
+
hint = commands.hint
|
|
309
|
+
commands.hint = 'Foo'
|
|
310
|
+
|
|
311
|
+
Short hint shown after listing available commands.
|
|
312
|
+
"""
|
|
313
|
+
|
|
314
|
+
def __init__(self, **kwargs: Any) -> None:
|
|
315
|
+
self._message: str | None = None
|
|
316
|
+
self.namespaces: list[str] = ['Pyjoyment.Command.Author', 'Pyjoyment.Command']
|
|
317
|
+
"""::
|
|
318
|
+
|
|
319
|
+
namespaces = commands.namespaces
|
|
320
|
+
commands.namespaces = ['MyApp.Command']
|
|
321
|
+
|
|
322
|
+
Namespaces to load commands from, defaults to
|
|
323
|
+
``Pyjoyment.Command.Author`` and ``Pyjoyment.Command``. ::
|
|
324
|
+
|
|
325
|
+
# Add another namespace to load commands from
|
|
326
|
+
commands.namespaces.append('MyApp.Command')
|
|
327
|
+
"""
|
|
328
|
+
super().__init__(**kwargs)
|
|
329
|
+
|
|
330
|
+
@property
|
|
331
|
+
def message(self) -> str:
|
|
332
|
+
"""::
|
|
333
|
+
|
|
334
|
+
msg = commands.message
|
|
335
|
+
commands.message = 'Hello World!'
|
|
336
|
+
|
|
337
|
+
Short usage message shown before listing available commands.
|
|
338
|
+
"""
|
|
339
|
+
if self._message is None:
|
|
340
|
+
self._message = self.extract_usage() + '\nCommands:\n'
|
|
341
|
+
return self._message
|
|
342
|
+
|
|
343
|
+
@message.setter
|
|
344
|
+
def message(self, value: str) -> None:
|
|
345
|
+
self._message = value
|
|
346
|
+
|
|
347
|
+
@staticmethod
|
|
348
|
+
def detect() -> str | None:
|
|
349
|
+
"""::
|
|
350
|
+
|
|
351
|
+
env = commands.detect()
|
|
352
|
+
|
|
353
|
+
Try to detect environment, or return ``None`` if none could be
|
|
354
|
+
detected.
|
|
355
|
+
"""
|
|
356
|
+
# WSGI
|
|
357
|
+
# Renamed from Mojolicious: PYJO_WSGI, as WSGI has no environment variable of its own, where Mojo detects PSGI
|
|
358
|
+
# with PLACK_ENV
|
|
359
|
+
if os.environ.get('PYJO_WSGI') is not None:
|
|
360
|
+
return 'wsgi'
|
|
361
|
+
|
|
362
|
+
# Not in Mojolicious: ASGI, with PYJO_ASGI
|
|
363
|
+
if os.environ.get('PYJO_ASGI') is not None:
|
|
364
|
+
return 'asgi'
|
|
365
|
+
|
|
366
|
+
# Not in Mojolicious: an event function of AWS Lambda, whose runtime has the endpoint of its API
|
|
367
|
+
if os.environ.get('AWS_LAMBDA_RUNTIME_API') is not None:
|
|
368
|
+
return 'lambda'
|
|
369
|
+
|
|
370
|
+
# Not in Mojolicious: FastCGI, whose web server gives the application its listen socket as the file descriptor 0
|
|
371
|
+
if _fastcgi():
|
|
372
|
+
return 'fastcgi'
|
|
373
|
+
|
|
374
|
+
# CGI
|
|
375
|
+
if os.environ.get('PATH_INFO') is not None or os.environ.get('GATEWAY_INTERFACE') is not None:
|
|
376
|
+
return 'cgi'
|
|
377
|
+
|
|
378
|
+
# Nothing
|
|
379
|
+
return None
|
|
380
|
+
|
|
381
|
+
def run(self, name: str | None = None, *args: str) -> Any:
|
|
382
|
+
"""::
|
|
383
|
+
|
|
384
|
+
commands.run()
|
|
385
|
+
commands.run(*sys.argv[1:])
|
|
386
|
+
|
|
387
|
+
Load and run commands. Automatic deployment environment detection can
|
|
388
|
+
be disabled with the ``PYJO_NO_DETECT`` environment variable. A
|
|
389
|
+
detected environment, CGI, FastCGI, AWS Lambda, or WSGI and ASGI with
|
|
390
|
+
the ``PYJO_WSGI`` and ``PYJO_ASGI`` environment variables, runs its
|
|
391
|
+
command, whatever the arguments are, as a WSGI or an ASGI server and
|
|
392
|
+
AWS Lambda import the script of the application with their own
|
|
393
|
+
arguments. ::
|
|
394
|
+
|
|
395
|
+
# The WSGI application of a script, for PYJO_WSGI=1 gunicorn myapp:application
|
|
396
|
+
application = app.start()
|
|
397
|
+
"""
|
|
398
|
+
# Application loader
|
|
399
|
+
# Not in Mojolicious: the application for Pyjo.Server.load_app, which Mojo returns from the script
|
|
400
|
+
if os.environ.get('PYJO_APP_LOADER') is not None:
|
|
401
|
+
Pyjo.Server.loaded_app = self.app
|
|
402
|
+
return self.app
|
|
403
|
+
|
|
404
|
+
# Try to detect environment
|
|
405
|
+
if not os.environ.get('PYJO_NO_DETECT') and (env := self.detect()):
|
|
406
|
+
name = env
|
|
407
|
+
|
|
408
|
+
# Run command
|
|
409
|
+
arguments = list(args)
|
|
410
|
+
if name and re.fullmatch(r'\w[\w-]+', name) and (name != 'help' or arguments):
|
|
411
|
+
# Help
|
|
412
|
+
help = name == 'help'
|
|
413
|
+
if help:
|
|
414
|
+
name = arguments.pop(0)
|
|
415
|
+
saved = os.environ.get('PYJO_HELP')
|
|
416
|
+
help = bool(saved) or help
|
|
417
|
+
setenv('PYJO_HELP', '1' if help else None)
|
|
418
|
+
try:
|
|
419
|
+
name = name.replace('-', '_')
|
|
420
|
+
|
|
421
|
+
# Remove options shared by all commands before loading the command
|
|
422
|
+
_args(arguments)
|
|
423
|
+
module = None
|
|
424
|
+
for namespace in self.namespaces:
|
|
425
|
+
if module := _command(f'{namespace}.{name}', True):
|
|
426
|
+
break
|
|
427
|
+
|
|
428
|
+
# Unknown command
|
|
429
|
+
if not module:
|
|
430
|
+
raise Pyjo.Exception.new(f'Unknown command "{name}", maybe you need to install it?\n')
|
|
431
|
+
|
|
432
|
+
# Run command
|
|
433
|
+
app = self.app
|
|
434
|
+
command = module.new(app=app)
|
|
435
|
+
if help:
|
|
436
|
+
return command.help(*arguments)
|
|
437
|
+
app.plugins.emit_hook('before_command', command, arguments)
|
|
438
|
+
return command.run(*arguments)
|
|
439
|
+
finally:
|
|
440
|
+
setenv('PYJO_HELP', saved)
|
|
441
|
+
|
|
442
|
+
elif name and name not in ('help', '--help', '-h'):
|
|
443
|
+
raise Pyjo.Exception.new(f'Invalid command "{name}".\n')
|
|
444
|
+
|
|
445
|
+
# Hide list for tests
|
|
446
|
+
# Renamed from Mojolicious: PYJO_HARNESS_ACTIVE, which Pyjo.Prove sets, as prove sets HARNESS_ACTIVE
|
|
447
|
+
if os.environ.get('PYJO_HARNESS_ACTIVE', '0') not in ('', '0'):
|
|
448
|
+
return True
|
|
449
|
+
|
|
450
|
+
# Find all available commands
|
|
451
|
+
all: dict[str, str] = {}
|
|
452
|
+
for namespace in self.namespaces:
|
|
453
|
+
for module in [*Pyjo.Loader.find_modules(namespace), *Pyjo.Loader.find_packages(namespace)]:
|
|
454
|
+
if (cls := _command(module)) is not None:
|
|
455
|
+
all.setdefault(module[len(namespace) + 1 :], cls.new().description)
|
|
456
|
+
|
|
457
|
+
rows = [[' ' + re.sub(r'(?<!^)_', '-', name), all[name]] for name in sorted(all)]
|
|
458
|
+
print(self.message, tablify(rows), self.hint, sep='', end='')
|
|
459
|
+
return True
|
|
460
|
+
|
|
461
|
+
@staticmethod
|
|
462
|
+
def start_app(app: str | type, *args: str) -> Any:
|
|
463
|
+
"""::
|
|
464
|
+
|
|
465
|
+
Pyjoyment.Commands.start_app('MyApp')
|
|
466
|
+
Pyjoyment.Commands.start_app('MyApp', *sys.argv[1:])
|
|
467
|
+
|
|
468
|
+
Load application from class and start the command line interface for
|
|
469
|
+
it. Note that the options ``-h``/``--help``, ``--home`` and
|
|
470
|
+
``-m``/``--mode``, which are shared by all commands, will be parsed
|
|
471
|
+
from ``sys.argv`` when the module is imported. ::
|
|
472
|
+
|
|
473
|
+
# Always start daemon for application
|
|
474
|
+
Pyjoyment.Commands.start_app('MyApp', 'daemon', '-l', 'http://*:8080')
|
|
475
|
+
"""
|
|
476
|
+
application: Any = Pyjo.Server.new().build_app(app)
|
|
477
|
+
return application.start(*args)
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
# Command line options for PYJO_HELP, PYJO_HOME, PYJO_LOG_FORMAT and PYJO_MODE
|
|
481
|
+
def _args(args: list[str]) -> None:
|
|
482
|
+
if not Pyjoyment_Commands.detect():
|
|
483
|
+
getopt(
|
|
484
|
+
args,
|
|
485
|
+
{
|
|
486
|
+
'h|help': Pyjo.GetOpt.env('PYJO_HELP'),
|
|
487
|
+
'home=s': Pyjo.GetOpt.env('PYJO_HOME'),
|
|
488
|
+
# Not in Mojolicious: the format of the log messages of Pyjo.Log, text or JSON
|
|
489
|
+
'log-format=s': Pyjo.GetOpt.env('PYJO_LOG_FORMAT'),
|
|
490
|
+
'm|mode=s': Pyjo.GetOpt.env('PYJO_MODE'),
|
|
491
|
+
},
|
|
492
|
+
pass_through=True,
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
|
|
496
|
+
def _command(module: str, fatal: bool = False) -> type[Pyjoyment.Command.object] | None:
|
|
497
|
+
if not (e := Pyjo.Loader.load_class(module)):
|
|
498
|
+
cls = Pyjo.Loader._class(module) # pyright: ignore[reportPrivateUsage]
|
|
499
|
+
return cls if cls is not None and issubclass(cls, Pyjoyment.Command.object) else None
|
|
500
|
+
if fatal and isinstance(e, Exception):
|
|
501
|
+
raise e
|
|
502
|
+
return None
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
# Not in Mojolicious: the file descriptor 0 is a listen socket, which has no peer, as the specification of FastCGI tells
|
|
506
|
+
# an application to check
|
|
507
|
+
def _fastcgi() -> bool:
|
|
508
|
+
try:
|
|
509
|
+
fd = os.dup(0)
|
|
510
|
+
except OSError:
|
|
511
|
+
return False
|
|
512
|
+
try:
|
|
513
|
+
handle = socket.socket(fileno=fd)
|
|
514
|
+
except OSError:
|
|
515
|
+
os.close(fd)
|
|
516
|
+
return False
|
|
517
|
+
with handle:
|
|
518
|
+
try:
|
|
519
|
+
handle.getpeername()
|
|
520
|
+
except OSError as e:
|
|
521
|
+
return e.errno == errno.ENOTCONN
|
|
522
|
+
return False
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
# Do not remove options from sys.argv
|
|
526
|
+
_args(sys.argv[1:])
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
# Not in Mojolicious: script/mojo, the command line interface of Pyjoyment.HelloWorld
|
|
530
|
+
def main(argv: Sequence[str] | None = None) -> None:
|
|
531
|
+
"""::
|
|
532
|
+
|
|
533
|
+
main(['version'])
|
|
534
|
+
|
|
535
|
+
The command line interface of the ``pyjo`` script: start the command line
|
|
536
|
+
interface of :mod:`Pyjoyment.HelloWorld`.
|
|
537
|
+
"""
|
|
538
|
+
start_app('Pyjoyment.HelloWorld', *(argv or ()))
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
start_app = Pyjoyment_Commands.start_app
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
new = Pyjoyment_Commands.new
|
|
545
|
+
object = Pyjoyment_Commands
|
|
546
|
+
Commands = Pyjoyment_Commands
|