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,267 @@
1
+ """
2
+ Pyjoyment.Command.Author.generate.plugin - Plugin generator command
3
+ ===================================================================
4
+ ::
5
+
6
+ Usage: APPLICATION generate plugin [OPTIONS] [NAME]
7
+
8
+ pyjo generate plugin
9
+ pyjo generate plugin AliceSearch
10
+ pyjo generate plugin -f MyApp.Ext.Test
11
+
12
+ Options:
13
+ -f, --full Do not prepend "Pyjoyment.Plugin."
14
+ -h, --help Show this summary of available options
15
+
16
+ :mod:`Pyjoyment.Command.Author.generate.plugin` generates directory structures
17
+ for fully functional :mod:`Pyjoyment` plugins: a distribution with
18
+ ``pyproject.toml``, which builds with hatchling, and a test, which
19
+ ``uv run python -m Pyjo.Prove -l -r t`` runs, as does ``uv run pytest``,
20
+ with pytest of the dependency group ``dev``. The module of a plugin is in the
21
+ namespace ``Pyjoyment.Plugin``, which the distribution adds to without the
22
+ ``__init__.py`` files of the namespace. ``AGENTS.md``, which ``CLAUDE.md``
23
+ imports, tells a coding agent how the plugin is made, tested and built, and
24
+ where the skills of Pyjoyment are.
25
+
26
+ This is a core command, that means it is always enabled and its code a good
27
+ example for learning to build new commands, you're welcome to fork it.
28
+
29
+ See :mod:`Pyjoyment.Commands` for a list of commands that are available by
30
+ default.
31
+
32
+ See also
33
+ --------
34
+
35
+ :mod:`Pyjoyment`, https://mojolicious.org.
36
+
37
+ Ported from `Mojolicious::Command::Author::generate::plugin
38
+ <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/Author/generate/plugin.pm>`_ of
39
+ Mojolicious 9.49.
40
+
41
+ Classes
42
+ -------
43
+ """
44
+
45
+ import Pyjo.Exception
46
+ import Pyjoyment.Command
47
+
48
+ from Pyjo.Util import class_to_path, extract_usage, getopt
49
+ from Pyjoyment.Command.Author.generate.pyproject import _requirement # pyright: ignore[reportPrivateUsage]
50
+
51
+
52
+ class Pyjoyment_Command_Author_generate_plugin(Pyjoyment.Command.object):
53
+ """
54
+ :mod:`Pyjoyment.Command.Author.generate.plugin` inherits all attributes and
55
+ methods from :mod:`Pyjoyment.Command` and implements the following new
56
+ ones.
57
+ """
58
+
59
+ description = 'Generate Pyjoyment plugin directory structure'
60
+ """::
61
+
62
+ description = plugin.description
63
+ plugin.description = 'Foo'
64
+
65
+ Short description of this command, used for the command list.
66
+ """
67
+
68
+ usage = extract_usage()
69
+ """::
70
+
71
+ usage = plugin.usage
72
+ plugin.usage = 'Foo'
73
+
74
+ Usage information for this command, used for the help screen.
75
+ """
76
+
77
+ def run(self, *args: str) -> None:
78
+ """::
79
+
80
+ plugin.run(*sys.argv[1:])
81
+
82
+ Run this command.
83
+ """
84
+ arguments = list(args)
85
+ if not (opts := getopt(arguments, {'f|full': None})):
86
+ raise Pyjo.Exception.new(self.usage)
87
+
88
+ # Class
89
+ name = arguments[0] if arguments else 'MyPlugin'
90
+ class_ = name if opts.full else f'Pyjoyment.Plugin.{name}'
91
+ dir = '-'.join(class_.split('.'))
92
+ app = class_to_path(class_)
93
+ title = f'{class_} - Pyjoyment Plugin'
94
+ self.render_to_rel_file(
95
+ 'class',
96
+ f'{dir}/{app}',
97
+ {
98
+ 'alias': class_.rsplit('.', 1)[-1],
99
+ 'class_': class_,
100
+ 'identifier': class_.replace('.', '_'),
101
+ 'name': name,
102
+ 'title': title,
103
+ },
104
+ )
105
+
106
+ # Test
107
+ # Renamed from Mojolicious: t/basic.py, where Mojo has t/basic.t
108
+ self.render_to_rel_file('test', f'{dir}/t/basic.py', {'name': name})
109
+
110
+ # Makefile
111
+ # Renamed from Mojolicious: pyproject.toml, where Mojo has Makefile.PL
112
+ self.render_to_rel_file(
113
+ 'pyproject', f'{dir}/pyproject.toml', {'dir': dir, 'path': app, 'requirement': _requirement()}
114
+ )
115
+
116
+ # Not in Mojolicious: the guide of the coding agents, AGENTS.md, which CLAUDE.md imports for Claude Code
117
+ self.render_to_rel_file('agents', f'{dir}/AGENTS.md', {'class_': class_, 'dir': dir, 'name': name, 'path': app})
118
+ self.render_to_rel_file('claude', f'{dir}/CLAUDE.md')
119
+
120
+
121
+ new = Pyjoyment_Command_Author_generate_plugin.new
122
+ object = Pyjoyment_Command_Author_generate_plugin
123
+
124
+ __DATA__ = r'''
125
+ @@ class
126
+ """
127
+ <%= title %>
128
+ <%= '=' * len(title) %>
129
+ ::
130
+
131
+ # Pyjoyment
132
+ app.plugin('<%= name %>')
133
+
134
+ # Pyjoyment.Lite
135
+ plugin('<%= name %>')
136
+
137
+ :mod:`<%= class_ %>` is a :mod:`Pyjoyment` plugin.
138
+
139
+ See also
140
+ --------
141
+
142
+ :mod:`Pyjoyment`, https://mojolicious.org.
143
+
144
+ Classes
145
+ -------
146
+ """
147
+
148
+ import Pyjoyment.Plugin
149
+
150
+
151
+ __version__ = '0.1.0'
152
+
153
+
154
+ class <%= identifier %>(Pyjoyment.Plugin.object):
155
+ """
156
+ :mod:`<%= class_ %>` inherits all methods from
157
+ :mod:`Pyjoyment.Plugin` and implements the following new ones.
158
+ """
159
+
160
+ def register(self, app, conf):
161
+ """::
162
+
163
+ plugin.register(Pyjoyment.new(), {})
164
+
165
+ Register plugin in :mod:`Pyjoyment` application.
166
+ """
167
+
168
+
169
+ object = <%= identifier %>
170
+ % if alias != identifier:
171
+ <%= alias %> = <%= identifier %>
172
+ % end
173
+
174
+ @@ test
175
+ from Pyjo.Test import *
176
+ from Pyjoyment.Lite import *
177
+
178
+ import Pyjo.Test.Pyjo
179
+
180
+
181
+ plugin('<%= name %>')
182
+
183
+
184
+ @get('/')
185
+ def index(c):
186
+ c.render(text='Hello Pyjo!')
187
+
188
+
189
+ t = Pyjo.Test.Pyjo.new()
190
+ t.get_ok('/').status_is(200).content_is('Hello Pyjo!')
191
+
192
+ done_testing()
193
+
194
+ @@ pyproject
195
+ [build-system]
196
+ requires = ["hatchling"]
197
+ build-backend = "hatchling.build"
198
+
199
+ [project]
200
+ name = "<%= dir %>"
201
+ dynamic = ["version"]
202
+ authors = [{ name = "A Good Programmer", email = "nospam@example.com" }]
203
+ requires-python = ">=3.12"
204
+ dependencies = ["<%= requirement %>"]
205
+
206
+ [tool.hatch.version]
207
+ path = "<%= path %>"
208
+
209
+ [tool.hatch.build.targets.wheel]
210
+ only-include = ["<%= path %>"]
211
+
212
+ [dependency-groups]
213
+ dev = ["pytest>=9", "pytest-xdist>=3"]
214
+
215
+ [tool.pytest.ini_options]
216
+ testpaths = ["t"]
217
+ pythonpath = ["."]
218
+
219
+ @@ agents
220
+ # <%= dir %>
221
+
222
+ A plugin of [Pyjoyment](https://pyjoyment.readthedocs.io/), the port of
223
+ Mojolicious to Python, made with `pyjo generate plugin`, a distribution of its
224
+ own. This file says how it is made, tested and built, for whoever changes it,
225
+ a coding agent too.
226
+
227
+ ## Layout
228
+
229
+ - `<%= path %>`: the plugin `<%= class_ %>`, whose `register` adds its
230
+ helpers, hooks and routes to an application, as `plugin('<%= name %>')`.
231
+ - `t/basic.py`: its test, with an application of `Pyjoyment.Lite`.
232
+ - `pyproject.toml`: the distribution, whose wheel has only the module, as the
233
+ packages of the namespace are the ones of Pyjoyment.
234
+
235
+ ## Commands
236
+
237
+ ```sh
238
+ uv run python -m Pyjo.Prove -l -r t # the tests
239
+ uv run pytest # the tests with pytest
240
+ uv build # the wheel and the sdist in dist/
241
+ ```
242
+
243
+ ## Conventions
244
+
245
+ - The directories of the namespace have no `__init__.py`, which would
246
+ replace the packages of Pyjoyment.
247
+ - `register` runs once, at the start of the application, and what the
248
+ requests share is made there; nothing in a helper or a hook blocks the
249
+ event loop, as `time.sleep` or `requests`.
250
+ - A change comes with a test in `t/`, where `Pyjo.Test.Pyjo` requests an
251
+ application without a server.
252
+
253
+ ## Skills
254
+
255
+ The plugin of Claude Code for Pyjoyment has skills of its idioms, of plugins
256
+ and distributions, of the tests and of the templates:
257
+
258
+ ```sh
259
+ claude plugin install pyjoyment --marketplace dex4er/Pyjoyment
260
+ ```
261
+
262
+ Other agents read their files, the `SKILL.md` of each skill, in
263
+ https://github.com/dex4er/Pyjoyment/tree/main/plugins/pyjoyment/skills.
264
+
265
+ @@ claude
266
+ @AGENTS.md
267
+ '''
@@ -0,0 +1,123 @@
1
+ """
2
+ Pyjoyment.Command.Author.generate.pyproject - pyproject.toml generator command
3
+ ==============================================================================
4
+ ::
5
+
6
+ Usage: APPLICATION generate pyproject [OPTIONS]
7
+
8
+ ./myapp.py generate pyproject
9
+ pyjo generate pyproject
10
+
11
+ Options:
12
+ -h, --help Show this summary of available options
13
+
14
+ :mod:`Pyjoyment.Command.Author.generate.pyproject` generates
15
+ ``pyproject.toml`` files for applications, with their dependencies and no
16
+ build system, as ``uv init --app`` does, so that ``uv sync`` installs the
17
+ dependencies without the application. The name of the project is the one of
18
+ the current directory, and where it has a directory ``t``, the dependency
19
+ group ``dev`` has pytest and pytest-xdist, which ``uv sync`` installs and
20
+ ``generate dockerfile`` leaves out, ``testpaths`` of pytest names ``t`` and
21
+ ``pythonpath`` the current directory, so that ``uv run pytest`` runs its test
22
+ scripts with :mod:`Pyjo.Test.pytest_plugin`, and its tests find the
23
+ application.
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::Author::generate::makefile
37
+ <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/Author/generate/makefile.pm>`_ of
38
+ Mojolicious 9.49.
39
+
40
+ Classes
41
+ -------
42
+ """
43
+
44
+ # Renamed from Mojolicious: generate pyproject, where Mojo has generate makefile, as the dependencies of a project of
45
+ # Python are in pyproject.toml, which uv reads
46
+
47
+ import Pyjo.File
48
+ import Pyjoyment.Command
49
+
50
+ from Pyjo.Util import extract_usage
51
+ from Pyjoyment.Command.version import _version # pyright: ignore[reportPrivateUsage]
52
+
53
+ import os
54
+ import re
55
+
56
+
57
+ class Pyjoyment_Command_Author_generate_pyproject(Pyjoyment.Command.object):
58
+ """
59
+ :mod:`Pyjoyment.Command.Author.generate.pyproject` inherits all attributes
60
+ and methods from :mod:`Pyjoyment.Command` and implements the following new
61
+ ones.
62
+ """
63
+
64
+ description = 'Generate "pyproject.toml"'
65
+ """::
66
+
67
+ description = pyproject.description
68
+ pyproject.description = 'Foo'
69
+
70
+ Short description of this command, used for the command list.
71
+ """
72
+
73
+ usage = extract_usage()
74
+ """::
75
+
76
+ usage = pyproject.usage
77
+ pyproject.usage = 'Foo'
78
+
79
+ Usage information for this command, used for the help screen.
80
+ """
81
+
82
+ def run(self, *args: str) -> None:
83
+ """::
84
+
85
+ pyproject.run(*sys.argv[1:])
86
+
87
+ Run this command.
88
+ """
89
+ # Not in Mojolicious: the name of the project, which Makefile.PL of Mojo leaves out
90
+ name = re.sub(r'[^A-Za-z0-9._-]+', '-', Pyjo.File.path().to_abs().basename()).strip('-._') or 'myapp'
91
+ # Not in Mojolicious: testpaths of pytest for the test scripts in t
92
+ tests = os.path.isdir('t')
93
+ self.render_to_rel_file(
94
+ 'pyproject', 'pyproject.toml', {'name': name, 'requirement': _requirement(), 'tests': tests}
95
+ )
96
+
97
+
98
+ # Not in Mojolicious: the requirement of the dependency on Pyjoyment, with the version that generates the files
99
+ def _requirement() -> str:
100
+ version = _version()
101
+ return 'Pyjoyment' if version == 'n/a' else f'Pyjoyment>={version}'
102
+
103
+
104
+ new = Pyjoyment_Command_Author_generate_pyproject.new
105
+ object = Pyjoyment_Command_Author_generate_pyproject
106
+
107
+ __DATA__ = r"""
108
+ @@ pyproject
109
+ [project]
110
+ name = "<%= name %>"
111
+ version = "0.1.0"
112
+ requires-python = ">=3.12"
113
+ dependencies = ["<%= requirement %>"]
114
+ % if tests:
115
+
116
+ [dependency-groups]
117
+ dev = ["pytest>=9", "pytest-xdist>=3"]
118
+
119
+ [tool.pytest.ini_options]
120
+ testpaths = ["t"]
121
+ pythonpath = ["."]
122
+ % end
123
+ """
@@ -0,0 +1,101 @@
1
+ """
2
+ Pyjoyment.Command.Author.inflate - Inflate command
3
+ ==================================================
4
+ ::
5
+
6
+ Usage: APPLICATION inflate [OPTIONS]
7
+
8
+ ./myapp.py inflate
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
+
21
+ :mod:`Pyjoyment.Command.Author.inflate` turns templates and static files
22
+ embedded in the ``DATA`` sections of your application into real files.
23
+
24
+ This is a core command, that means it is always enabled and its code a good
25
+ example for learning to build new commands, you're welcome to fork it.
26
+
27
+ See :mod:`Pyjoyment.Commands` for a list of commands that are available by
28
+ default.
29
+
30
+ See also
31
+ --------
32
+
33
+ :mod:`Pyjoyment`, https://mojolicious.org.
34
+
35
+ Ported from `Mojolicious::Command::Author::inflate
36
+ <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojolicious/Command/Author/inflate.pm>`_ of Mojolicious 9.49.
37
+
38
+ Classes
39
+ -------
40
+ """
41
+
42
+ import Pyjoyment.Command
43
+
44
+ from Pyjo.Loader import data_section, file_is_binary
45
+ from Pyjo.Util import encode, extract_usage
46
+
47
+ import re
48
+
49
+ from typing import Any
50
+
51
+
52
+ class Pyjoyment_Command_Author_inflate(Pyjoyment.Command.object):
53
+ """
54
+ :mod:`Pyjoyment.Command.Author.inflate` inherits all attributes and methods
55
+ from :mod:`Pyjoyment.Command` and implements the following new ones.
56
+ """
57
+
58
+ description = 'Inflate embedded files to real files'
59
+ """::
60
+
61
+ description = inflate.description
62
+ inflate.description = 'Foo'
63
+
64
+ Short description of this command, used for the command list.
65
+ """
66
+
67
+ usage = extract_usage()
68
+ """::
69
+
70
+ usage = inflate.usage
71
+ inflate.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
+ inflate.run(*sys.argv[1:])
80
+
81
+ Run this command.
82
+ """
83
+ # Find all embedded files
84
+ all: dict[str, bytes] = {}
85
+ app: Any = self.app
86
+ for cls in [*app.renderer.classes, *app.static.classes]:
87
+ files: Any = data_section(cls) or {}
88
+ for name in files:
89
+ data = data_section(cls, name)
90
+ if not file_is_binary(cls, name):
91
+ data = encode('UTF-8', str(data))
92
+ all[name] = data if isinstance(data, bytes) else b''
93
+
94
+ # Turn them into real files
95
+ for name in (name for name in all if re.search(r'\.\w+$', name)):
96
+ prefix = 'templates' if re.search(r'\.\w+\.\w+$', name) else 'public'
97
+ self.write_file(self.rel_file(f'{prefix}/{name}'), all[name])
98
+
99
+
100
+ new = Pyjoyment_Command_Author_inflate.new
101
+ object = Pyjoyment_Command_Author_inflate