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.
Files changed (200) hide show
  1. Pyjo/App/ASGI.py +735 -0
  2. Pyjo/App/CGI.py +773 -0
  3. Pyjo/App/FastCGI.py +631 -0
  4. Pyjo/App/Lambda.py +987 -0
  5. Pyjo/App/WSGI.py +427 -0
  6. Pyjo/App/__init__.py +409 -0
  7. Pyjo/Asset/File.py +377 -0
  8. Pyjo/Asset/Memory.py +235 -0
  9. Pyjo/Asset/__init__.py +200 -0
  10. Pyjo/Base.py +215 -0
  11. Pyjo/Cache.py +119 -0
  12. Pyjo/Collection.py +570 -0
  13. Pyjo/Content/MultiPart.py +325 -0
  14. Pyjo/Content/Single.py +193 -0
  15. Pyjo/Content/__init__.py +806 -0
  16. Pyjo/Cookie/Request.py +90 -0
  17. Pyjo/Cookie/Response.py +294 -0
  18. Pyjo/Cookie/__init__.py +143 -0
  19. Pyjo/DOM/CSS.py +1019 -0
  20. Pyjo/DOM/HTML.py +550 -0
  21. Pyjo/DOM/__init__.py +1329 -0
  22. Pyjo/Date.py +294 -0
  23. Pyjo/EventEmitter.py +522 -0
  24. Pyjo/Exception.py +494 -0
  25. Pyjo/File.py +959 -0
  26. Pyjo/GetOpt.py +605 -0
  27. Pyjo/Headers.py +760 -0
  28. Pyjo/HelloWorld.py +77 -0
  29. Pyjo/Home.py +109 -0
  30. Pyjo/IOLoop/ChildProcess.py +591 -0
  31. Pyjo/IOLoop/Client.py +736 -0
  32. Pyjo/IOLoop/Datagram.py +982 -0
  33. Pyjo/IOLoop/Messages.py +664 -0
  34. Pyjo/IOLoop/Server.py +458 -0
  35. Pyjo/IOLoop/Stdio.py +446 -0
  36. Pyjo/IOLoop/Stream.py +644 -0
  37. Pyjo/IOLoop/Subprocess.py +419 -0
  38. Pyjo/IOLoop/TLS.py +360 -0
  39. Pyjo/IOLoop/__init__.py +1036 -0
  40. Pyjo/IOLoop/certs/README.md +41 -0
  41. Pyjo/IOLoop/certs/ca.crt +20 -0
  42. Pyjo/IOLoop/certs/server.crt +21 -0
  43. Pyjo/IOLoop/certs/server.key +28 -0
  44. Pyjo/JSON/Pointer.py +135 -0
  45. Pyjo/JSON/RPC.py +772 -0
  46. Pyjo/JSON/Schema.py +2506 -0
  47. Pyjo/JSON/__init__.py +573 -0
  48. Pyjo/Loader.py +342 -0
  49. Pyjo/Log.py +723 -0
  50. Pyjo/Message/Request.py +725 -0
  51. Pyjo/Message/Response.py +476 -0
  52. Pyjo/Message/__init__.py +830 -0
  53. Pyjo/Parameters.py +472 -0
  54. Pyjo/Path.py +419 -0
  55. Pyjo/Promise.py +894 -0
  56. Pyjo/Prove.py +1305 -0
  57. Pyjo/Reactor/Asyncio.py +854 -0
  58. Pyjo/Reactor/Poll.py +439 -0
  59. Pyjo/Reactor/__init__.py +525 -0
  60. Pyjo/SSE.py +119 -0
  61. Pyjo/Server/ASGI.py +486 -0
  62. Pyjo/Server/CGI.py +259 -0
  63. Pyjo/Server/Daemon.py +1007 -0
  64. Pyjo/Server/FastCGI.py +517 -0
  65. Pyjo/Server/Hot/__init__.py +687 -0
  66. Pyjo/Server/Hot/__main__.py +5 -0
  67. Pyjo/Server/Lambda.py +641 -0
  68. Pyjo/Server/Prefork.py +917 -0
  69. Pyjo/Server/Prethread.py +394 -0
  70. Pyjo/Server/Reload/Backend/Poll.py +114 -0
  71. Pyjo/Server/Reload/Backend/__init__.py +126 -0
  72. Pyjo/Server/Reload/__init__.py +482 -0
  73. Pyjo/Server/Reload/__main__.py +5 -0
  74. Pyjo/Server/Stdio.py +228 -0
  75. Pyjo/Server/WSGI.py +349 -0
  76. Pyjo/Server/__init__.py +396 -0
  77. Pyjo/String/Bytes.py +532 -0
  78. Pyjo/String/HTML.py +210 -0
  79. Pyjo/String/Mixin.py +333 -0
  80. Pyjo/String/Template.py +470 -0
  81. Pyjo/String/Unicode.py +553 -0
  82. Pyjo/String/__init__.py +0 -0
  83. Pyjo/TOML.py +232 -0
  84. Pyjo/Template.py +1290 -0
  85. Pyjo/Test/Pyjo.py +1454 -0
  86. Pyjo/Test/__init__.py +1233 -0
  87. Pyjo/Test/pytest_plugin.py +305 -0
  88. Pyjo/Transaction/HTTP.py +374 -0
  89. Pyjo/Transaction/WebSocket.py +709 -0
  90. Pyjo/Transaction/__init__.py +429 -0
  91. Pyjo/URL/Template.py +459 -0
  92. Pyjo/URL/__init__.py +651 -0
  93. Pyjo/Upload.py +139 -0
  94. Pyjo/UserAgent/CookieJar.py +391 -0
  95. Pyjo/UserAgent/Proxy.py +138 -0
  96. Pyjo/UserAgent/Server.py +239 -0
  97. Pyjo/UserAgent/Transactor.py +766 -0
  98. Pyjo/UserAgent/__init__.py +1243 -0
  99. Pyjo/Util.py +3567 -0
  100. Pyjo/WebSocket.py +332 -0
  101. Pyjo/YAML.py +1167 -0
  102. Pyjo/__init__.py +441 -0
  103. Pyjo/__main__.py +35 -0
  104. Pyjo/py.typed +0 -0
  105. Pyjoyment/Command/Author/__init__.py +20 -0
  106. Pyjoyment/Command/Author/generate/__init__.py +106 -0
  107. Pyjoyment/Command/Author/generate/app.py +299 -0
  108. Pyjoyment/Command/Author/generate/dockerfile.py +281 -0
  109. Pyjoyment/Command/Author/generate/kubernetes.py +514 -0
  110. Pyjoyment/Command/Author/generate/lambda_zip.py +372 -0
  111. Pyjoyment/Command/Author/generate/lite_app.py +113 -0
  112. Pyjoyment/Command/Author/generate/plugin.py +267 -0
  113. Pyjoyment/Command/Author/generate/pyproject.py +123 -0
  114. Pyjoyment/Command/Author/inflate.py +101 -0
  115. Pyjoyment/Command/__init__.py +332 -0
  116. Pyjoyment/Command/asgi.py +92 -0
  117. Pyjoyment/Command/cgi.py +90 -0
  118. Pyjoyment/Command/daemon.py +160 -0
  119. Pyjoyment/Command/eval.py +128 -0
  120. Pyjoyment/Command/fastcgi.py +99 -0
  121. Pyjoyment/Command/get.py +305 -0
  122. Pyjoyment/Command/lambda.py +117 -0
  123. Pyjoyment/Command/prefork.py +181 -0
  124. Pyjoyment/Command/prethread.py +126 -0
  125. Pyjoyment/Command/routes.py +133 -0
  126. Pyjoyment/Command/stdio.py +92 -0
  127. Pyjoyment/Command/version.py +141 -0
  128. Pyjoyment/Command/wsgi.py +93 -0
  129. Pyjoyment/Commands.py +546 -0
  130. Pyjoyment/Controller.py +1307 -0
  131. Pyjoyment/HelloWorld.py +56 -0
  132. Pyjoyment/Lite.py +494 -0
  133. Pyjoyment/Plugin/AllowedHosts.py +205 -0
  134. Pyjoyment/Plugin/Config.py +248 -0
  135. Pyjoyment/Plugin/DefaultHelpers.py +1202 -0
  136. Pyjoyment/Plugin/EPLRenderer.py +134 -0
  137. Pyjoyment/Plugin/EPRenderer.py +212 -0
  138. Pyjoyment/Plugin/HeaderCondition.py +98 -0
  139. Pyjoyment/Plugin/Health.py +325 -0
  140. Pyjoyment/Plugin/JSONConfig.py +172 -0
  141. Pyjoyment/Plugin/Mount.py +223 -0
  142. Pyjoyment/Plugin/PyRenderer.py +209 -0
  143. Pyjoyment/Plugin/TOMLConfig.py +141 -0
  144. Pyjoyment/Plugin/TagHelpers.py +959 -0
  145. Pyjoyment/Plugin/YAMLConfig.py +178 -0
  146. Pyjoyment/Plugin/__init__.py +80 -0
  147. Pyjoyment/Plugins.py +215 -0
  148. Pyjoyment/Renderer.py +673 -0
  149. Pyjoyment/Routes/Match.py +251 -0
  150. Pyjoyment/Routes/Pattern.py +443 -0
  151. Pyjoyment/Routes/Route.py +827 -0
  152. Pyjoyment/Routes/__init__.py +419 -0
  153. Pyjoyment/Sessions.py +255 -0
  154. Pyjoyment/Static.py +421 -0
  155. Pyjoyment/Types.py +238 -0
  156. Pyjoyment/Validator/Validation.py +395 -0
  157. Pyjoyment/Validator/__init__.py +304 -0
  158. Pyjoyment/__init__.py +1083 -0
  159. Pyjoyment/__main__.py +5 -0
  160. Pyjoyment/py.typed +0 -0
  161. Pyjoyment/resources/public/favicon.ico +0 -0
  162. Pyjoyment/resources/public/favicon.svg +345 -0
  163. Pyjoyment/resources/public/pyjo/bootstrap/LICENSE +21 -0
  164. Pyjoyment/resources/public/pyjo/bootstrap/bootstrap.bundle.min.js.map +1 -0
  165. Pyjoyment/resources/public/pyjo/bootstrap/bootstrap.css +6 -0
  166. Pyjoyment/resources/public/pyjo/bootstrap/bootstrap.js +7 -0
  167. Pyjoyment/resources/public/pyjo/bootstrap/bootstrap.min.css.map +1 -0
  168. Pyjoyment/resources/public/pyjo/failunicat.png +0 -0
  169. Pyjoyment/resources/public/pyjo/failunicat.svg +50 -0
  170. Pyjoyment/resources/public/pyjo/highlight.js/LICENSE +29 -0
  171. Pyjoyment/resources/public/pyjo/highlight.js/highlight-mojo-dark.css +56 -0
  172. Pyjoyment/resources/public/pyjo/highlight.js/highlight.min.js +1262 -0
  173. Pyjoyment/resources/public/pyjo/highlight.js/pyjoyment.min.js +1 -0
  174. Pyjoyment/resources/public/pyjo/logo-black-4x.png +0 -0
  175. Pyjoyment/resources/public/pyjo/logo-black-4x.svg +346 -0
  176. Pyjoyment/resources/public/pyjo/logo-white-2x.png +0 -0
  177. Pyjoyment/resources/public/pyjo/logo-white-2x.svg +346 -0
  178. Pyjoyment/resources/public/pyjo/logo-white-4x.png +0 -0
  179. Pyjoyment/resources/public/pyjo/logo-white-4x.svg +346 -0
  180. Pyjoyment/resources/public/pyjo/logo-white.png +0 -0
  181. Pyjoyment/resources/public/pyjo/logo-white.svg +346 -0
  182. Pyjoyment/resources/public/pyjo/logo.png +0 -0
  183. Pyjoyment/resources/public/pyjo/logo.svg +346 -0
  184. Pyjoyment/resources/public/pyjo/notfound.png +0 -0
  185. Pyjoyment/resources/public/pyjo/notfound.svg +3 -0
  186. Pyjoyment/resources/public/pyjo/nounicat.png +0 -0
  187. Pyjoyment/resources/public/pyjo/nounicat.svg +5 -0
  188. Pyjoyment/resources/public/pyjo/pinstripe-dark.png +0 -0
  189. Pyjoyment/resources/public/pyjo/pinstripe-dark.svg +4 -0
  190. Pyjoyment/resources/public/pyjo/pinstripe-light.png +0 -0
  191. Pyjoyment/resources/public/pyjo/pinstripe-light.svg +4 -0
  192. Pyjoyment/resources/public/pyjo/pyjo.css +204 -0
  193. Pyjoyment/resources/templates/pyjo/debug.html.ep +346 -0
  194. Pyjoyment/resources/templates/pyjo/exception.html.ep +32 -0
  195. Pyjoyment/resources/templates/pyjo/not_found.html.ep +45 -0
  196. pyjoyment-0.1.0.dist-info/METADATA +376 -0
  197. pyjoyment-0.1.0.dist-info/RECORD +200 -0
  198. pyjoyment-0.1.0.dist-info/WHEEL +4 -0
  199. pyjoyment-0.1.0.dist-info/entry_points.txt +8 -0
  200. pyjoyment-0.1.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,332 @@
1
+ """
2
+ Pyjoyment.Command - Command base class
3
+ ======================================
4
+ ::
5
+
6
+ # Lowercase command name, in the module Pyjoyment.Command.mycommand
7
+ from Pyjoyment.Command import Command
8
+
9
+ from Pyjo.Util import extract_usage
10
+
11
+
12
+ class Pyjoyment_Command_mycommand(Command):
13
+ # Short description
14
+ description = 'My first Pyjoyment command'
15
+
16
+ # Usage message from the synopsis of the docstring of the module
17
+ usage = extract_usage()
18
+
19
+ def run(self, *args):
20
+ # Magic here! :)
21
+ ...
22
+
23
+
24
+ object = Pyjoyment_Command_mycommand
25
+
26
+ # Or import the module, as in Google Python Style Guide
27
+
28
+ # Lowercase command name, in the module Pyjoyment.Command.mycommand
29
+ import Pyjoyment.Command
30
+
31
+ from Pyjo.Util import extract_usage
32
+
33
+
34
+ class Pyjoyment_Command_mycommand(Pyjoyment.Command.object):
35
+ # Short description
36
+ description = 'My first Pyjoyment command'
37
+
38
+ # Usage message from the synopsis of the docstring of the module
39
+ usage = extract_usage()
40
+
41
+ def run(self, *args):
42
+ # Magic here! :)
43
+ ...
44
+
45
+
46
+ object = Pyjoyment_Command_mycommand
47
+
48
+ # The synopsis in the docstring of the module
49
+ \"\"\"
50
+ Pyjoyment.Command.mycommand - My command
51
+ ========================================
52
+ ::
53
+
54
+ Usage: APPLICATION mycommand [OPTIONS]
55
+
56
+ Options:
57
+ -s, --something Does something
58
+ \"\"\"
59
+
60
+ :mod:`Pyjoyment.Command` is an abstract base class for :mod:`Pyjoyment`
61
+ commands.
62
+
63
+ See :mod:`Pyjoyment.Commands` for a list of commands that are available by
64
+ default.
65
+
66
+ See also
67
+ --------
68
+
69
+ :mod:`Pyjoyment`, https://mojolicious.org.
70
+
71
+ Ported from `Mojolicious::Command <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command.pm>`_
72
+ of Mojolicious 9.49.
73
+
74
+ Classes
75
+ -------
76
+ """
77
+
78
+ import Pyjo.Base
79
+ import Pyjo.File
80
+ import Pyjo.Loader
81
+ import Pyjo.Server
82
+ import Pyjo.Template
83
+ import Pyjo.Util
84
+
85
+ import os
86
+ import sys
87
+ import weakref
88
+
89
+ from pkgutil import extend_path
90
+ from typing import TYPE_CHECKING, Any, Self
91
+
92
+
93
+ if TYPE_CHECKING:
94
+ import Pyjoyment
95
+
96
+
97
+ class Pyjoyment_Command(Pyjo.Base.object):
98
+ """
99
+ :mod:`Pyjoyment.Command` inherits all methods from :mod:`Pyjo.Base` and
100
+ implements the following new ones.
101
+ """
102
+
103
+ description: str = 'No description'
104
+ """::
105
+
106
+ description = command.description
107
+ command.description = 'Foo'
108
+
109
+ Short description of command, used for the command list.
110
+ """
111
+
112
+ quiet: bool | None = None
113
+ """::
114
+
115
+ boolean = command.quiet
116
+ command.quiet = boolean
117
+
118
+ Limited command output.
119
+ """
120
+
121
+ usage: str = 'Usage: APPLICATION\n'
122
+ """::
123
+
124
+ usage = command.usage
125
+ command.usage = 'Foo'
126
+
127
+ Usage information for command, used for the help screen.
128
+ """
129
+
130
+ def __init__(self, **kwargs: Any) -> None:
131
+ self._app: weakref.ref[Pyjoyment.object] | None = None
132
+ self._app_ref: Pyjoyment.object | None = None
133
+ self.template: dict[str, Any] = {'vars': True}
134
+ """::
135
+
136
+ template = command.template
137
+ command.template = {'vars': True}
138
+
139
+ Attribute values passed to :mod:`Pyjo.Template` objects used to
140
+ render templates with :meth:`render_data`, defaults to activating
141
+ ``vars``.
142
+ """
143
+ for name, value in kwargs.items():
144
+ setattr(self, name, value)
145
+
146
+ @property
147
+ def app(self) -> 'Pyjoyment.object':
148
+ """::
149
+
150
+ app = command.app
151
+ command.app = Pyjoyment.new()
152
+
153
+ Application for command, defaults to a :mod:`Pyjoyment.HelloWorld`
154
+ object. Note that this attribute is weakened. ::
155
+
156
+ # Introspect
157
+ for path in command.app.renderer.paths:
158
+ print(f'Template path: {path}')
159
+ """
160
+ if self._app is not None:
161
+ if (app := self._app()) is None:
162
+ raise ReferenceError('weakly-referenced object no longer exists')
163
+ return app
164
+ if self._app_ref is None:
165
+ self._app_ref = Pyjo.Server.new().build_app('Pyjoyment.HelloWorld') # pyright: ignore[reportAttributeAccessIssue]
166
+ return self._app_ref # pyright: ignore[reportReturnType]
167
+
168
+ @app.setter
169
+ def app(self, value: 'Pyjoyment.object') -> None:
170
+ self._app = weakref.ref(value)
171
+
172
+ def chmod_file(self, path: str | os.PathLike[str], mode: int) -> Self:
173
+ """::
174
+
175
+ command = command.chmod_file('/home/sri/foo.txt', 0o644)
176
+
177
+ Change mode of a file.
178
+ """
179
+ Pyjo.File.path(path).chmod(mode)
180
+ return self._loud(f' [chmod] {path} {mode:o}')
181
+
182
+ def chmod_rel_file(self, path: str, mode: int) -> Self:
183
+ """::
184
+
185
+ command = command.chmod_rel_file('foo/foo.txt', 0o644)
186
+
187
+ Portably change mode of a file relative to the current working
188
+ directory.
189
+ """
190
+ return self.chmod_file(self.rel_file(path), mode)
191
+
192
+ def create_dir(self, path: str | os.PathLike[str]) -> Self:
193
+ """::
194
+
195
+ command = command.create_dir('/home/sri/foo/bar')
196
+
197
+ Create a directory if it does not exist already.
198
+ """
199
+ if os.path.isdir(path):
200
+ return self._loud(f' [exist] {path}')
201
+ Pyjo.File.path(path).make_path()
202
+ return self._loud(f' [mkdir] {path}')
203
+
204
+ def create_rel_dir(self, path: str) -> Self:
205
+ """::
206
+
207
+ command = command.create_rel_dir('foo/bar/baz')
208
+
209
+ Portably create a directory relative to the current working directory
210
+ if it does not exist already.
211
+ """
212
+ return self.create_dir(self.rel_file(path))
213
+
214
+ def extract_usage(self) -> str:
215
+ """::
216
+
217
+ usage = command.extract_usage()
218
+
219
+ Extract usage message from the synopsis of the docstring of the file
220
+ this method was called from with :func:`Pyjo.Util.extract_usage`.
221
+ """
222
+ return Pyjo.Util.extract_usage(sys._getframe(1).f_code.co_filename) # pyright: ignore[reportPrivateUsage]
223
+
224
+ def help(self, *args: str) -> None:
225
+ """::
226
+
227
+ command.help()
228
+
229
+ Print usage information for command.
230
+ """
231
+ print(self.usage, end='')
232
+
233
+ def rel_file(self, path: str) -> Pyjo.File.object:
234
+ """::
235
+
236
+ path = command.rel_file('foo/bar.txt')
237
+
238
+ Return a :mod:`Pyjo.File` object relative to the current working
239
+ directory.
240
+ """
241
+ return Pyjo.File.path().child(*path.split('/'))
242
+
243
+ def render_data(self, name: str, *args: Any) -> str:
244
+ """::
245
+
246
+ data = command.render_data('foo_bar')
247
+ data = command.render_data('foo_bar', *args)
248
+ data = command.render_data('foo_bar', {'foo': 'bar'})
249
+
250
+ Render a template from the ``DATA`` section of the module of the
251
+ command with :mod:`Pyjo.Loader` and :mod:`Pyjo.Template`. The template
252
+ can be configured with :attr:`template`.
253
+ """
254
+ template = Pyjo.Template.new(**self.template)
255
+ template.name = f'template {name} from DATA section'
256
+ output = template.render(str(Pyjo.Loader.data_section(type(self), name)), *args)
257
+ if isinstance(output, Exception):
258
+ raise output
259
+ return str(output)
260
+
261
+ def render_to_file(self, data: str, path: str | os.PathLike[str], *args: Any) -> Self:
262
+ """::
263
+
264
+ command = command.render_to_file('foo_bar', '/home/sri/foo.txt')
265
+ command = command.render_to_file('foo_bar', '/home/sri/foo.txt', *args)
266
+ command = command.render_to_file('foo_bar', '/home/sri/foo.txt', {'foo': 'bar'})
267
+
268
+ Render a template with :meth:`render_data` to a file if it does not
269
+ exist already, and create the directory if necessary.
270
+ """
271
+ return self.write_file(path, self.render_data(data, *args))
272
+
273
+ def render_to_rel_file(self, data: str, path: str, *args: Any) -> Self:
274
+ """::
275
+
276
+ command = command.render_to_rel_file('foo_bar', 'foo/bar.txt')
277
+ command = command.render_to_rel_file('foo_bar', 'foo/bar.txt', *args)
278
+ command = command.render_to_rel_file('foo_bar', 'foo/bar.txt', {'foo': 'bar'})
279
+
280
+ Portably render a template with :meth:`render_data` to a file relative
281
+ to the current working directory if it does not exist already, and
282
+ create the directory if necessary.
283
+ """
284
+ return self.render_to_file(data, self.rel_file(path), *args)
285
+
286
+ def run(self, *args: str) -> Any:
287
+ """::
288
+
289
+ command.run()
290
+ command.run(*sys.argv[1:])
291
+
292
+ Run command. Meant to be overloaded in a subclass.
293
+ """
294
+ raise NotImplementedError('Method "run" not implemented by subclass')
295
+
296
+ def write_file(self, path: str | os.PathLike[str], data: str | bytes) -> Self:
297
+ """::
298
+
299
+ command = command.write_file('/home/sri/foo.txt', 'Hello World!')
300
+
301
+ Write text to a file if it does not exist already, and create the
302
+ directory if necessary.
303
+ """
304
+ if os.path.isfile(path):
305
+ return self._loud(f' [exist] {path}')
306
+ self.create_dir(Pyjo.File.path(path).dirname())
307
+ Pyjo.File.path(path).spew(data)
308
+ return self._loud(f' [write] {path}')
309
+
310
+ def write_rel_file(self, path: str, data: str | bytes) -> Self:
311
+ """::
312
+
313
+ command = command.write_rel_file('foo/bar.txt', 'Hello World!')
314
+
315
+ Portably write text to a file relative to the current working
316
+ directory if it does not exist already, and create the directory if
317
+ necessary.
318
+ """
319
+ return self.write_file(self.rel_file(path), data)
320
+
321
+ def _loud(self, msg: str) -> Self:
322
+ if not self.quiet:
323
+ print(msg)
324
+ return self
325
+
326
+
327
+ # Not in Mojolicious: a namespace that other distributions can add commands to
328
+ __path__ = extend_path(__path__, __name__)
329
+
330
+ new = Pyjoyment_Command.new
331
+ object = Pyjoyment_Command
332
+ Command = Pyjoyment_Command
@@ -0,0 +1,92 @@
1
+ """
2
+ Pyjoyment.Command.asgi - ASGI command
3
+ =====================================
4
+ ::
5
+
6
+ Usage: APPLICATION asgi [OPTIONS]
7
+
8
+ application = app.start('asgi')
9
+ PYJO_ASGI=1 uvicorn 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.asgi` starts applications with the
23
+ :mod:`Pyjo.Server.ASGI` backend: it returns the ASGI application, which a
24
+ script keeps for the ASGI server that imports it. The script of an application
25
+ that ends with ``application = app.start()`` runs this command when the
26
+ ``PYJO_ASGI`` 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
+ Inspired by `Mojolicious::Command::psgi
41
+ <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/psgi.pm>`_ of Mojolicious 9.49, for ASGI.
42
+
43
+ Classes
44
+ -------
45
+ """
46
+
47
+ # Not in Mojolicious: the command of ASGI, as Pyjoyment.Command.wsgi of WSGI
48
+
49
+ import Pyjo.Server.ASGI
50
+ import Pyjoyment.Command
51
+
52
+ from Pyjo.Util import extract_usage
53
+
54
+ from typing import Any
55
+
56
+
57
+ class Pyjoyment_Command_asgi(Pyjoyment.Command.object):
58
+ """
59
+ :mod:`Pyjoyment.Command.asgi` inherits all attributes and methods from
60
+ :mod:`Pyjoyment.Command` and implements the following new ones.
61
+ """
62
+
63
+ description = 'Start application with ASGI'
64
+ """::
65
+
66
+ description = asgi.description
67
+ asgi.description = 'Foo'
68
+
69
+ Short description of this command, used for the command list.
70
+ """
71
+
72
+ usage = extract_usage()
73
+ """::
74
+
75
+ usage = asgi.usage
76
+ asgi.usage = 'Foo'
77
+
78
+ Usage information for this command, used for the help screen.
79
+ """
80
+
81
+ def run(self, *args: str) -> Any:
82
+ """::
83
+
84
+ application = asgi.run()
85
+
86
+ Run this command.
87
+ """
88
+ return Pyjo.Server.ASGI.new(app=self.app).to_asgi_app()
89
+
90
+
91
+ new = Pyjoyment_Command_asgi.new
92
+ object = Pyjoyment_Command_asgi
@@ -0,0 +1,90 @@
1
+ """
2
+ Pyjoyment.Command.cgi - CGI command
3
+ ===================================
4
+ ::
5
+
6
+ Usage: APPLICATION cgi [OPTIONS]
7
+
8
+ ./myapp.py cgi
9
+
10
+ Options:
11
+ -h, --help Show this summary of available options
12
+ --home <path> Path to home directory of your application,
13
+ defaults to the value of PYJO_HOME or
14
+ auto-detection
15
+ --log-format <name> Format of log messages, "text" or "json",
16
+ defaults to the value of PYJO_LOG_FORMAT or
17
+ "text"
18
+ -m, --mode <name> Operating mode for your application, defaults to
19
+ the value of PYJO_MODE or "development"
20
+ --nph Enable non-parsed-header mode
21
+
22
+ :mod:`Pyjoyment.Command.cgi` starts applications with the
23
+ :mod:`Pyjo.Server.CGI` backend.
24
+
25
+ This is a core command, that means it is always enabled and its code a good
26
+ example for learning to build new commands, you're welcome to fork it.
27
+
28
+ See :mod:`Pyjoyment.Commands` for a list of commands that are available by
29
+ default.
30
+
31
+ See also
32
+ --------
33
+
34
+ :mod:`Pyjoyment`, https://mojolicious.org.
35
+
36
+ Ported from `Mojolicious::Command::cgi
37
+ <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/cgi.pm>`_ of Mojolicious 9.49.
38
+
39
+ Classes
40
+ -------
41
+ """
42
+
43
+ import Pyjo.Exception
44
+ import Pyjo.Server.CGI
45
+ import Pyjoyment.Command
46
+
47
+ from Pyjo.Util import extract_usage, getopt
48
+
49
+ from typing import Any
50
+
51
+
52
+ class Pyjoyment_Command_cgi(Pyjoyment.Command.object):
53
+ """
54
+ :mod:`Pyjoyment.Command.cgi` inherits all attributes and methods from
55
+ :mod:`Pyjoyment.Command` and implements the following new ones.
56
+ """
57
+
58
+ description = 'Start application with CGI'
59
+ """::
60
+
61
+ description = cgi.description
62
+ cgi.description = 'Foo'
63
+
64
+ Short description of this command, used for the command list.
65
+ """
66
+
67
+ usage = extract_usage()
68
+ """::
69
+
70
+ usage = cgi.usage
71
+ cgi.usage = 'Foo'
72
+
73
+ Usage information for this command, used for the help screen.
74
+ """
75
+
76
+ def run(self, *args: str) -> Any:
77
+ """::
78
+
79
+ cgi.run(*sys.argv[1:])
80
+
81
+ Run this command.
82
+ """
83
+ arguments = list(args)
84
+ if not (opts := getopt(arguments, {'nph': None})):
85
+ raise Pyjo.Exception.new(self.usage)
86
+ return Pyjo.Server.CGI.new(app=self.app, nph=bool(opts.nph)).run()
87
+
88
+
89
+ new = Pyjoyment_Command_cgi.new
90
+ object = Pyjoyment_Command_cgi
@@ -0,0 +1,160 @@
1
+ """
2
+ Pyjoyment.Command.daemon - Daemon command
3
+ =========================================
4
+ ::
5
+
6
+ Usage: APPLICATION daemon [OPTIONS]
7
+
8
+ ./myapp.py daemon
9
+ ./myapp.py daemon -m production -p -l http://*:8080
10
+ ./myapp.py daemon -l http://127.0.0.1:8080 -l https://[::]:8081
11
+ ./myapp.py daemon -l 'https://*:443?cert=./server.crt&key=./server.key'
12
+ ./myapp.py daemon -l http+unix://%2Ftmp%2Fmyapp.sock
13
+ ./myapp.py daemon -l fcgi://127.0.0.1:9000
14
+ ./myapp.py daemon -l http://127.0.0.1:8080 -p 127.0.0.0/8 -p fc00::/7
15
+
16
+ Options:
17
+ -b, --backlog <size> Listen backlog size, defaults to
18
+ SOMAXCONN
19
+ -c, --clients <number> Maximum number of concurrent
20
+ connections, defaults to 1000
21
+ -h, --help Show this summary of available options
22
+ --home <path> Path to home directory of your
23
+ application, defaults to the value of
24
+ PYJO_HOME or auto-detection
25
+ -i, --inactivity-timeout <seconds> Inactivity timeout, defaults to the
26
+ value of PYJO_INACTIVITY_TIMEOUT or 30
27
+ -k, --keep-alive-timeout <seconds> Keep-alive timeout, defaults to the
28
+ value of PYJO_KEEP_ALIVE_TIMEOUT or 5
29
+ -l, --listen <location> One or more locations you want to
30
+ listen on, defaults to the value of
31
+ PYJO_LISTEN, the port of PORT or
32
+ "http://*:3000"
33
+ --log-format <name> Format of log messages, "text" or
34
+ "json", defaults to the value of
35
+ PYJO_LOG_FORMAT or "text"
36
+ -m, --mode <name> Operating mode for your application,
37
+ defaults to the value of PYJO_MODE or
38
+ "development"
39
+ -p, --proxy [<network>] Activate reverse proxy support,
40
+ defaults to the value of
41
+ PYJO_REVERSE_PROXY, optionally takes
42
+ one or more trusted proxy addresses or
43
+ networks
44
+ -r, --requests <number> Maximum number of requests per
45
+ keep-alive connection, defaults to 100
46
+ -S, --shutdown-delay <seconds> Time to keep serving after INT or TERM
47
+ before shutting down gracefully,
48
+ defaults to 0
49
+
50
+ :mod:`Pyjoyment.Command.daemon` starts applications with the
51
+ :mod:`Pyjo.Server.Daemon` backend.
52
+
53
+ An option that is not given has the value of the environment variable of
54
+ ``PYJO_`` and its name, as ``PYJO_CLIENTS`` for ``--clients``, with the
55
+ values of ``--listen`` and ``--proxy`` separated by commas, see
56
+ :mod:`Pyjo.GetOpt`, so that the environment of a container or a platform
57
+ can tune the server. ::
58
+
59
+ PYJO_CLIENTS=100 ./myapp.py daemon
60
+
61
+ This is a core command, that means it is always enabled and its code a good
62
+ example for learning to build new commands, you're welcome to fork it.
63
+
64
+ See :mod:`Pyjoyment.Commands` for a list of commands that are available by
65
+ default.
66
+
67
+ See also
68
+ --------
69
+
70
+ :mod:`Pyjoyment`, https://mojolicious.org.
71
+
72
+ Ported from `Mojolicious::Command::daemon
73
+ <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/daemon.pm>`_ of Mojolicious 9.49.
74
+
75
+ Classes
76
+ -------
77
+ """
78
+
79
+ import Pyjo.Exception
80
+ import Pyjo.Server.Daemon
81
+ import Pyjoyment.Command
82
+
83
+ from Pyjo.Util import extract_usage, getopt
84
+
85
+ from typing import Any
86
+
87
+
88
+ class Pyjoyment_Command_daemon(Pyjoyment.Command.object):
89
+ """
90
+ :mod:`Pyjoyment.Command.daemon` inherits all attributes and methods from
91
+ :mod:`Pyjoyment.Command` and implements the following new ones.
92
+ """
93
+
94
+ description = 'Start application with HTTP and WebSocket server'
95
+ """::
96
+
97
+ description = daemon.description
98
+ daemon.description = 'Foo'
99
+
100
+ Short description of this command, used for the command list.
101
+ """
102
+
103
+ usage = extract_usage()
104
+ """::
105
+
106
+ usage = daemon.usage
107
+ daemon.usage = 'Foo'
108
+
109
+ Usage information for this command, used for the help screen.
110
+ """
111
+
112
+ def build_server(self, *args: str) -> Pyjo.Server.Daemon.object:
113
+ """::
114
+
115
+ server = daemon.build_server(*sys.argv[1:])
116
+
117
+ Build :mod:`Pyjo.Server.Daemon` instance from command line arguments.
118
+ """
119
+ arguments = list(args)
120
+ daemon = Pyjo.Server.Daemon.new(app=self.app)
121
+ listen: list[str] = []
122
+ proxy: list[str] = []
123
+ # Not in Mojolicious: the options from the environment variables of their names
124
+ if not getopt(
125
+ arguments,
126
+ {
127
+ 'b|backlog=i': lambda name, value: setattr(daemon, 'backlog', value),
128
+ 'c|clients=i': lambda name, value: setattr(daemon, 'max_clients', value),
129
+ 'i|inactivity-timeout=i': lambda name, value: setattr(daemon, 'inactivity_timeout', value),
130
+ 'k|keep-alive-timeout=i': lambda name, value: setattr(daemon, 'keep_alive_timeout', value),
131
+ 'l|listen=s': listen,
132
+ 'p|proxy:s': proxy,
133
+ 'r|requests=i': lambda name, value: setattr(daemon, 'max_requests', value),
134
+ # Not in Mojolicious: the delay of the graceful shutdown, while the readiness fails
135
+ 'S|shutdown-delay=i': lambda name, value: setattr(daemon, 'shutdown_delay', value),
136
+ },
137
+ env_prefix='PYJO_',
138
+ ):
139
+ raise Pyjo.Exception.new(self.usage)
140
+
141
+ if listen:
142
+ daemon.listen = listen
143
+ if proxy:
144
+ daemon.reverse_proxy = True
145
+ if trusted := [p for p in proxy if p]:
146
+ daemon.trusted_proxies = trusted
147
+ return daemon
148
+
149
+ def run(self, *args: str) -> Any:
150
+ """::
151
+
152
+ daemon.run(*sys.argv[1:])
153
+
154
+ Run this command.
155
+ """
156
+ return self.build_server(*args).run()
157
+
158
+
159
+ new = Pyjoyment_Command_daemon.new
160
+ object = Pyjoyment_Command_daemon