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,181 @@
1
+ """
2
+ Pyjoyment.Command.prefork - Pre-fork command
3
+ ============================================
4
+ ::
5
+
6
+ Usage: APPLICATION prefork [OPTIONS]
7
+
8
+ ./myapp.py prefork
9
+ ./myapp.py prefork -m production -p -l http://*:8080
10
+ ./myapp.py prefork -l http://127.0.0.1:8080 -l https://[::]:8081
11
+ ./myapp.py prefork -l 'https://*:443?cert=./server.crt&key=./server.key'
12
+ ./myapp.py prefork -l http+unix://%2Ftmp%2Fmyapp.sock -w 12
13
+ ./myapp.py prefork -l fcgi://127.0.0.1:9000
14
+ ./myapp.py prefork -l http://127.0.0.1:8080 -p 127.0.0.0/8 -p fc00::/7
15
+
16
+ Options:
17
+ -a, --accepts <number> Number of connections for workers to
18
+ accept, defaults to 10000
19
+ -b, --backlog <size> Listen backlog size, defaults to
20
+ SOMAXCONN
21
+ -c, --clients <number> Maximum number of concurrent
22
+ connections, defaults to 1000
23
+ -G, --graceful-timeout <seconds> Graceful timeout, defaults to 25.
24
+ -I, --heartbeat-interval <seconds> Heartbeat interval, defaults to 5
25
+ -H, --heartbeat-timeout <seconds> Heartbeat timeout, defaults to 50
26
+ -h, --help Show this summary of available options
27
+ --home <path> Path to home directory of your
28
+ application, defaults to the value of
29
+ PYJO_HOME or auto-detection
30
+ -i, --inactivity-timeout <seconds> Inactivity timeout, defaults to the
31
+ value of PYJO_INACTIVITY_TIMEOUT or 30
32
+ -k, --keep-alive-timeout <seconds> Keep-alive timeout, defaults to the
33
+ value of PYJO_KEEP_ALIVE_TIMEOUT or 5
34
+ -l, --listen <location> One or more locations you want to
35
+ listen on, defaults to the value of
36
+ PYJO_LISTEN, the port of PORT or
37
+ "http://*:3000"
38
+ --log-format <name> Format of log messages, "text" or
39
+ "json", defaults to the value of
40
+ PYJO_LOG_FORMAT or "text"
41
+ -m, --mode <name> Operating mode for your application,
42
+ defaults to the value of PYJO_MODE or
43
+ "development"
44
+ -P, --pid-file <path> Path to process id file, defaults to
45
+ "prefork.pid" in a temporary directory
46
+ -p, --proxy [<network>] Activate reverse proxy support,
47
+ defaults to the value of
48
+ PYJO_REVERSE_PROXY, optionally takes
49
+ one or more trusted proxy addresses or
50
+ networks
51
+ -r, --requests <number> Maximum number of requests per
52
+ keep-alive connection, defaults to 100
53
+ -S, --shutdown-delay <seconds> Time to keep serving after INT or TERM
54
+ before shutting down gracefully,
55
+ defaults to 0
56
+ -s, --spare <number> Temporarily spawn up to this number of
57
+ additional workers, defaults to 2
58
+ -w, --workers <number> Number of workers, defaults to 4
59
+
60
+ :mod:`Pyjoyment.Command.prefork` starts applications with the
61
+ :mod:`Pyjo.Server.Prefork` backend.
62
+
63
+ An option that is not given has the value of the environment variable of
64
+ ``PYJO_`` and its name, as ``PYJO_WORKERS`` for ``--workers``, with the
65
+ values of ``--listen`` and ``--proxy`` separated by commas, see
66
+ :mod:`Pyjo.GetOpt`, so that the environment of a container or a platform
67
+ can tune the server. ::
68
+
69
+ PYJO_GRACEFUL_TIMEOUT=8 PYJO_WORKERS=2 ./myapp.py prefork
70
+
71
+ This is a core command, that means it is always enabled and its code a good
72
+ example for learning to build new commands, you're welcome to fork it.
73
+
74
+ See :mod:`Pyjoyment.Commands` for a list of commands that are available by
75
+ default.
76
+
77
+ See also
78
+ --------
79
+
80
+ :mod:`Pyjoyment`, https://mojolicious.org.
81
+
82
+ Ported from `Mojolicious::Command::prefork
83
+ <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/prefork.pm>`_ of Mojolicious 9.49.
84
+
85
+ Classes
86
+ -------
87
+ """
88
+
89
+ import Pyjo.Exception
90
+ import Pyjo.Server.Prefork
91
+ import Pyjoyment.Command
92
+
93
+ from Pyjo.Util import extract_usage, getopt
94
+
95
+ from typing import Any
96
+
97
+
98
+ class Pyjoyment_Command_prefork(Pyjoyment.Command.object):
99
+ """
100
+ :mod:`Pyjoyment.Command.prefork` inherits all attributes and methods from
101
+ :mod:`Pyjoyment.Command` and implements the following new ones.
102
+ """
103
+
104
+ description = 'Start application with pre-forking HTTP and WebSocket server'
105
+ """::
106
+
107
+ description = prefork.description
108
+ prefork.description = 'Foo'
109
+
110
+ Short description of this command, used for the command list.
111
+ """
112
+
113
+ usage = extract_usage()
114
+ """::
115
+
116
+ usage = prefork.usage
117
+ prefork.usage = 'Foo'
118
+
119
+ Usage information for this command, used for the help screen.
120
+ """
121
+
122
+ # Not in Mojolicious: the class of the server, which Pyjoyment.Command.prethread replaces
123
+ _server: type[Pyjo.Server.Prefork.object] = Pyjo.Server.Prefork.object
124
+
125
+ def build_server(self, *args: str) -> Pyjo.Server.Prefork.object:
126
+ """::
127
+
128
+ server = prefork.build_server(*sys.argv[1:])
129
+
130
+ Build :mod:`Pyjo.Server.Prefork` instance from command line arguments.
131
+ """
132
+ arguments = list(args)
133
+ prefork = self._server.new(app=self.app)
134
+ listen: list[str] = []
135
+ proxy: list[str] = []
136
+ # Not in Mojolicious: the options from the environment variables of their names
137
+ if not getopt(
138
+ arguments,
139
+ {
140
+ 'a|accepts=i': lambda name, value: setattr(prefork, 'accepts', value),
141
+ 'b|backlog=i': lambda name, value: setattr(prefork, 'backlog', value),
142
+ 'c|clients=i': lambda name, value: setattr(prefork, 'max_clients', value),
143
+ # Unlike Mojolicious: the graceful timeout defaults to 25 seconds, as Pyjo.Server.Prefork has it
144
+ 'G|graceful-timeout=i': lambda name, value: setattr(prefork, 'graceful_timeout', value),
145
+ 'I|heartbeat-interval=i': lambda name, value: setattr(prefork, 'heartbeat_interval', value),
146
+ 'H|heartbeat-timeout=i': lambda name, value: setattr(prefork, 'heartbeat_timeout', value),
147
+ 'i|inactivity-timeout=i': lambda name, value: setattr(prefork, 'inactivity_timeout', value),
148
+ 'k|keep-alive-timeout=i': lambda name, value: setattr(prefork, 'keep_alive_timeout', value),
149
+ 'l|listen=s': listen,
150
+ 'P|pid-file=s': lambda name, value: setattr(prefork, 'pid_file', value),
151
+ 'p|proxy:s': proxy,
152
+ 'r|requests=i': lambda name, value: setattr(prefork, 'max_requests', value),
153
+ # Not in Mojolicious: the delay of the graceful shutdown, while the readiness fails
154
+ 'S|shutdown-delay=i': lambda name, value: setattr(prefork, 'shutdown_delay', value),
155
+ 's|spare=i': lambda name, value: setattr(prefork, 'spare', value),
156
+ 'w|workers=i': lambda name, value: setattr(prefork, 'workers', value),
157
+ },
158
+ env_prefix='PYJO_',
159
+ ):
160
+ raise Pyjo.Exception.new(self.usage)
161
+
162
+ if listen:
163
+ prefork.listen = listen
164
+ if proxy:
165
+ prefork.reverse_proxy = True
166
+ if trusted := [p for p in proxy if p]:
167
+ prefork.trusted_proxies = trusted
168
+ return prefork
169
+
170
+ def run(self, *args: str) -> Any:
171
+ """::
172
+
173
+ prefork.run(*sys.argv[1:])
174
+
175
+ Run this command.
176
+ """
177
+ return self.build_server(*args).run()
178
+
179
+
180
+ new = Pyjoyment_Command_prefork.new
181
+ object = Pyjoyment_Command_prefork
@@ -0,0 +1,126 @@
1
+ """
2
+ Pyjoyment.Command.prethread - Pre-thread command
3
+ ================================================
4
+ ::
5
+
6
+ Usage: APPLICATION prethread [OPTIONS]
7
+
8
+ ./myapp.py prethread
9
+ ./myapp.py prethread -m production -p -l http://*:8080
10
+ ./myapp.py prethread -l http://127.0.0.1:8080 -l https://[::]:8081
11
+ ./myapp.py prethread -l 'https://*:443?cert=./server.crt&key=./server.key'
12
+ ./myapp.py prethread -l http+unix://%2Ftmp%2Fmyapp.sock -w 12
13
+ ./myapp.py prethread -l fcgi://127.0.0.1:9000
14
+ ./myapp.py prethread -l http://127.0.0.1:8080 -p 127.0.0.0/8 -p fc00::/7
15
+
16
+ Options:
17
+ -a, --accepts <number> Number of connections for workers to
18
+ accept, defaults to 10000
19
+ -b, --backlog <size> Listen backlog size, defaults to
20
+ SOMAXCONN
21
+ -c, --clients <number> Maximum number of concurrent
22
+ connections, defaults to 1000
23
+ -G, --graceful-timeout <seconds> Graceful timeout, defaults to 25.
24
+ -I, --heartbeat-interval <seconds> Heartbeat interval, defaults to 5
25
+ -H, --heartbeat-timeout <seconds> Heartbeat timeout, defaults to 50
26
+ -h, --help Show this summary of available options
27
+ --home <path> Path to home directory of your
28
+ application, defaults to the value of
29
+ PYJO_HOME or auto-detection
30
+ -i, --inactivity-timeout <seconds> Inactivity timeout, defaults to the
31
+ value of PYJO_INACTIVITY_TIMEOUT or 30
32
+ -k, --keep-alive-timeout <seconds> Keep-alive timeout, defaults to the
33
+ value of PYJO_KEEP_ALIVE_TIMEOUT or 5
34
+ -l, --listen <location> One or more locations you want to
35
+ listen on, defaults to the value of
36
+ PYJO_LISTEN, the port of PORT or
37
+ "http://*:3000"
38
+ --log-format <name> Format of log messages, "text" or
39
+ "json", defaults to the value of
40
+ PYJO_LOG_FORMAT or "text"
41
+ -m, --mode <name> Operating mode for your application,
42
+ defaults to the value of PYJO_MODE or
43
+ "development"
44
+ -P, --pid-file <path> Path to process id file, defaults to
45
+ "prethread.pid" in a temporary
46
+ directory
47
+ -p, --proxy [<network>] Activate reverse proxy support,
48
+ defaults to the value of
49
+ PYJO_REVERSE_PROXY, optionally takes
50
+ one or more trusted proxy addresses or
51
+ networks
52
+ -r, --requests <number> Maximum number of requests per
53
+ keep-alive connection, defaults to 100
54
+ -S, --shutdown-delay <seconds> Time to keep serving after INT or TERM
55
+ before shutting down gracefully,
56
+ defaults to 0
57
+ -s, --spare <number> Temporarily spawn up to this number of
58
+ additional workers, defaults to 2
59
+ -w, --workers <number> Number of workers, defaults to 4
60
+
61
+ :mod:`Pyjoyment.Command.prethread` starts applications with the
62
+ :mod:`Pyjo.Server.Prethread` backend, with the options of
63
+ :mod:`Pyjoyment.Command.prefork`.
64
+
65
+ An option that is not given has the value of the environment variable of
66
+ ``PYJO_`` and its name, as ``PYJO_WORKERS`` for ``--workers``, with the
67
+ values of ``--listen`` and ``--proxy`` separated by commas, see
68
+ :mod:`Pyjo.GetOpt`, so that the environment of a container or a platform
69
+ can tune the server. ::
70
+
71
+ PYJO_GRACEFUL_TIMEOUT=8 PYJO_WORKERS=2 ./myapp.py prethread
72
+
73
+ This is a core command, that means it is always enabled and its code a good
74
+ example for learning to build new commands, you're welcome to fork it.
75
+
76
+ See :mod:`Pyjoyment.Commands` for a list of commands that are available by
77
+ default.
78
+
79
+ See also
80
+ --------
81
+
82
+ :mod:`Pyjo.Server.Prethread`, :mod:`Pyjoyment`, https://mojolicious.org.
83
+
84
+ It has no counterpart in Mojolicious; it is inspired by
85
+ :mod:`Pyjoyment.Command.prefork`, the counterpart of `Mojolicious::Command::prefork
86
+ <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/prefork.pm>`_.
87
+
88
+ Classes
89
+ -------
90
+ """
91
+
92
+ import Pyjo.Server.Prethread
93
+ import Pyjoyment.Command.prefork
94
+
95
+ from Pyjo.Util import extract_usage
96
+
97
+
98
+ class Pyjoyment_Command_prethread(Pyjoyment.Command.prefork.object):
99
+ """
100
+ :mod:`Pyjoyment.Command.prethread` inherits all attributes and methods from
101
+ :mod:`Pyjoyment.Command.prefork` and implements the following new ones.
102
+ """
103
+
104
+ description = 'Start application with pre-threading HTTP and WebSocket server'
105
+ """::
106
+
107
+ description = prethread.description
108
+ prethread.description = 'Foo'
109
+
110
+ Short description of this command, used for the command list.
111
+ """
112
+
113
+ usage = extract_usage()
114
+ """::
115
+
116
+ usage = prethread.usage
117
+ prethread.usage = 'Foo'
118
+
119
+ Usage information for this command, used for the help screen.
120
+ """
121
+
122
+ _server = Pyjo.Server.Prethread.object
123
+
124
+
125
+ new = Pyjoyment_Command_prethread.new
126
+ object = Pyjoyment_Command_prethread
@@ -0,0 +1,133 @@
1
+ """
2
+ Pyjoyment.Command.routes - Routes command
3
+ =========================================
4
+ ::
5
+
6
+ Usage: APPLICATION routes [OPTIONS]
7
+
8
+ ./myapp.py routes
9
+ ./myapp.py routes -v
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
+ -v, --verbose Print additional details about routes, flags
22
+ indicate C=Conditions, P=Partial, U=Under and
23
+ W=WebSocket
24
+
25
+ :mod:`Pyjoyment.Command.routes` lists all your application routes.
26
+
27
+ This is a core command, that means it is always enabled and its code a good
28
+ example for learning to build new commands, you're welcome to fork it.
29
+
30
+ See :mod:`Pyjoyment.Commands` for a list of commands that are available by
31
+ default.
32
+
33
+ See also
34
+ --------
35
+
36
+ :mod:`Pyjoyment`, https://mojolicious.org.
37
+
38
+ Ported from `Mojolicious::Command::routes
39
+ <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/routes.pm>`_ of Mojolicious 9.49.
40
+
41
+ Classes
42
+ -------
43
+ """
44
+
45
+ import Pyjo.Exception
46
+ import Pyjoyment.Command
47
+ import Pyjoyment.Routes.Route
48
+
49
+ from Pyjo.Util import extract_usage, getopt, tablify
50
+
51
+ from typing import Any
52
+
53
+
54
+ class Pyjoyment_Command_routes(Pyjoyment.Command.object):
55
+ """
56
+ :mod:`Pyjoyment.Command.routes` inherits all attributes and methods from
57
+ :mod:`Pyjoyment.Command` and implements the following new ones.
58
+ """
59
+
60
+ description = 'Show available routes'
61
+ """::
62
+
63
+ description = routes.description
64
+ routes.description = 'Foo'
65
+
66
+ Short description of this command, used for the command list.
67
+ """
68
+
69
+ usage = extract_usage()
70
+ """::
71
+
72
+ usage = routes.usage
73
+ routes.usage = 'Foo'
74
+
75
+ Usage information for this command, used for the help screen.
76
+ """
77
+
78
+ def run(self, *args: str) -> None:
79
+ """::
80
+
81
+ routes.run(*sys.argv[1:])
82
+
83
+ Run this command.
84
+ """
85
+ arguments = list(args)
86
+ if not (opts := getopt(arguments, {'v|verbose': None})):
87
+ raise Pyjo.Exception.new(self.usage)
88
+
89
+ rows: list[list[str]] = []
90
+ for route in self.app.routes.children:
91
+ _walk(route, 0, rows, bool(opts.verbose))
92
+ print(tablify(rows), end='')
93
+
94
+
95
+ def _walk(route: Pyjoyment.Routes.Route.object, depth: int, rows: list[list[str]], verbose: bool) -> None:
96
+ # Pattern
97
+ prefix = ''
98
+ if i := depth * 2:
99
+ prefix += ' ' * i + '+'
100
+ row = [prefix + (route.pattern.unparsed or '/')]
101
+ rows.append(row)
102
+
103
+ # Flags
104
+ flags: list[str] = []
105
+ flags.append('C' if route.requires() else '.')
106
+ flags.append('P' if (partial := route.partial) else '.')
107
+ flags.append('U' if route.inline else '.')
108
+ flags.append('W' if route.is_websocket else '.')
109
+ if verbose:
110
+ row.append(''.join(flags))
111
+
112
+ # Methods
113
+ methods: Any = route.methods()
114
+ row.append(','.join(methods).upper() if methods else '*')
115
+
116
+ # Name
117
+ name = route.name or ''
118
+ row.append(f'"{name}"' if route.has_custom_name else name)
119
+
120
+ # Regex (verbose)
121
+ pattern = route.pattern
122
+ pattern.match('/', route.is_endpoint and not partial)
123
+ if verbose:
124
+ row.append(pattern.regex.pattern if pattern.regex is not None else '')
125
+
126
+ depth += 1
127
+ for child in route.children:
128
+ _walk(child, depth, rows, verbose)
129
+ depth -= 1
130
+
131
+
132
+ new = Pyjoyment_Command_routes.new
133
+ object = Pyjoyment_Command_routes
@@ -0,0 +1,92 @@
1
+ """
2
+ Pyjoyment.Command.stdio - Standard input and output command
3
+ ===========================================================
4
+ ::
5
+
6
+ Usage: APPLICATION stdio [OPTIONS]
7
+
8
+ ./myapp.py stdio
9
+ ./myapp.py stdio -m production
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.stdio` starts applications with the
23
+ :mod:`Pyjo.Server.Stdio` backend, which serves the protocol that the
24
+ application or a plugin gives with a subscriber of its event ``stream`` on
25
+ the standard input and output. It is not detected, as a pipe on the standard
26
+ input is too common to mean it.
27
+
28
+ This is a core command, that means it is always enabled and its code a good
29
+ example for learning to build new commands, you're welcome to fork it.
30
+
31
+ See :mod:`Pyjoyment.Commands` for a list of commands that are available by
32
+ default.
33
+
34
+ See also
35
+ --------
36
+
37
+ :mod:`Pyjoyment`, https://mojolicious.org.
38
+
39
+ It has no counterpart in Mojolicious.
40
+
41
+ Classes
42
+ -------
43
+ """
44
+
45
+ import Pyjo.Exception
46
+ import Pyjo.Server.Stdio
47
+ import Pyjoyment.Command
48
+
49
+ from Pyjo.Util import extract_usage, getopt
50
+
51
+ from typing import Any
52
+
53
+
54
+ class Pyjoyment_Command_stdio(Pyjoyment.Command.object):
55
+ """
56
+ :mod:`Pyjoyment.Command.stdio` inherits all attributes and methods from
57
+ :mod:`Pyjoyment.Command` and implements the following new ones.
58
+ """
59
+
60
+ description = 'Start application on standard input and output'
61
+ """::
62
+
63
+ description = stdio.description
64
+ stdio.description = 'Foo'
65
+
66
+ Short description of this command, used for the command list.
67
+ """
68
+
69
+ usage = extract_usage()
70
+ """::
71
+
72
+ usage = stdio.usage
73
+ stdio.usage = 'Foo'
74
+
75
+ Usage information for this command, used for the help screen.
76
+ """
77
+
78
+ def run(self, *args: str) -> Any:
79
+ """::
80
+
81
+ stdio.run(*sys.argv[1:])
82
+
83
+ Run this command.
84
+ """
85
+ arguments = list(args)
86
+ if not getopt(arguments, {}) or len(arguments):
87
+ raise Pyjo.Exception.new(self.usage)
88
+ return Pyjo.Server.Stdio.new(app=self.app).run()
89
+
90
+
91
+ new = Pyjoyment_Command_stdio.new
92
+ object = Pyjoyment_Command_stdio
@@ -0,0 +1,141 @@
1
+ """
2
+ Pyjoyment.Command.version - Version command
3
+ ===========================================
4
+ ::
5
+
6
+ Usage: APPLICATION version [OPTIONS]
7
+
8
+ pyjo version
9
+
10
+ Options:
11
+ -h, --help Show this summary of available options
12
+
13
+ :mod:`Pyjoyment.Command.version` shows version information for
14
+ available core and optional modules.
15
+
16
+ This is a core command, that means it is always enabled and its code a good
17
+ example for learning to build new commands, you're welcome to fork it.
18
+
19
+ See :mod:`Pyjoyment.Commands` for a list of commands that are available by
20
+ default.
21
+
22
+ See also
23
+ --------
24
+
25
+ :mod:`Pyjoyment`, https://mojolicious.org.
26
+
27
+ Ported from `Mojolicious::Command::version
28
+ <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/version.pm>`_ of Mojolicious 9.49.
29
+
30
+ Classes
31
+ -------
32
+ """
33
+
34
+ import Pyjo.IOLoop.Client
35
+ import Pyjo.IOLoop.TLS
36
+ import Pyjo.Reactor
37
+ import Pyjoyment.Command
38
+
39
+ from Pyjo.Util import extract_usage
40
+
41
+ import importlib.metadata
42
+ import platform
43
+ import re
44
+ import ssl
45
+ import sys
46
+ import tomllib
47
+
48
+ from pathlib import Path
49
+ from typing import Any
50
+
51
+
52
+ class Pyjoyment_Command_version(Pyjoyment.Command.object):
53
+ """
54
+ :mod:`Pyjoyment.Command.version` inherits all attributes and methods from
55
+ :mod:`Pyjoyment.Command` and implements the following new ones.
56
+ """
57
+
58
+ description = 'Show versions of available modules'
59
+ """::
60
+
61
+ description = version.description
62
+ version.description = 'Foo'
63
+
64
+ Short description of this command, used for the command list.
65
+ """
66
+
67
+ usage = extract_usage()
68
+ """::
69
+
70
+ usage = version.usage
71
+ version.usage = 'Foo'
72
+
73
+ Usage information for this command, used for the help screen.
74
+ """
75
+
76
+ def run(self, *args: str) -> None:
77
+ """::
78
+
79
+ version.run(*sys.argv[1:])
80
+
81
+ Run this command.
82
+ """
83
+ # Unlike Mojolicious: the counterparts of the optional modules of Perl that Mojo shows, which Python has in its
84
+ # standard library, and which Pyjoyment can turn off
85
+ reactor = Pyjo.Reactor.detect()
86
+ nnr = 'getaddrinfo in a thread' if Pyjo.IOLoop.Client.object.can_nnr() else 'n/a'
87
+ socks = 'Pyjo.IOLoop.Client' if Pyjo.IOLoop.Client.object.can_socks() else 'n/a'
88
+ tls = ssl.OPENSSL_VERSION if Pyjo.IOLoop.TLS.object.can_tls() else 'n/a'
89
+ current = _version()
90
+
91
+ print(f"""CORE
92
+ Python ({platform.python_version()}, {sys.platform})
93
+ Pyjoyment ({current})
94
+
95
+ OPTIONAL
96
+ Reactor ({reactor})
97
+ NNR ({nnr})
98
+ SOCKS5 ({socks})
99
+ TLS ({tls})
100
+ """)
101
+
102
+ # Check latest version on PyPI
103
+ # Unlike Mojolicious: the JSON API of PyPI, where Mojo asks MetaCPAN
104
+ try:
105
+ ua = self.app.ua
106
+ ua.max_redirects = 10
107
+ ua.proxy.detect()
108
+ latest = str(ua.get('https://pypi.org/pypi/Pyjoyment/json').result.json()['info']['version'])
109
+ except Exception:
110
+ return
111
+
112
+ msg = 'This version is up to date, have fun!'
113
+ if _numbers(latest) < _numbers(current):
114
+ msg = 'Thanks for testing a development release, you are awesome!'
115
+ if _numbers(latest) > _numbers(current):
116
+ msg = f'You might want to update your Pyjoyment to {latest}!'
117
+ print(msg)
118
+
119
+
120
+ # The numbers of a version, which compare as the versions do
121
+ def _numbers(version: str) -> tuple[int, ...]:
122
+ return tuple(int(number) for number in re.findall(r'\d+', version))
123
+
124
+
125
+ # Not in Mojolicious: the version of the distribution, from its metadata, or from the pyproject.toml of a checkout of
126
+ # its source, as Python has no $VERSION of a module
127
+ def _version() -> str:
128
+ try:
129
+ return importlib.metadata.version('Pyjoyment')
130
+ except importlib.metadata.PackageNotFoundError:
131
+ pass
132
+ pyproject = Path(__file__).resolve().parents[2] / 'pyproject.toml'
133
+ try:
134
+ project: Any = tomllib.loads(pyproject.read_text(encoding='utf-8')).get('project', {})
135
+ except (OSError, tomllib.TOMLDecodeError):
136
+ return 'n/a'
137
+ return str(project['version']) if project.get('name') == 'Pyjoyment' and 'version' in project else 'n/a'
138
+
139
+
140
+ new = Pyjoyment_Command_version.new
141
+ object = Pyjoyment_Command_version