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,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
|