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
Pyjo/String/Unicode.py ADDED
@@ -0,0 +1,553 @@
1
+ r"""
2
+ Pyjo.String.Unicode - String of characters
3
+ ==========================================
4
+ ::
5
+
6
+ from Pyjo.String.Unicode import Unicode
7
+
8
+ # Manipulate string
9
+ string = Unicode('foo_bar_baz')
10
+ print(string.camelize())
11
+
12
+ # Or import the module, as in Google Python Style Guide
13
+
14
+ import Pyjo.String.Unicode
15
+
16
+ # Manipulate string
17
+ string = Pyjo.String.Unicode.new('foo_bar_baz')
18
+ print(string.camelize())
19
+
20
+ # Chain methods
21
+ string = Pyjo.String.Unicode.new('foo bar baz').quote()
22
+ string = string.unquote().encode('UTF-8').b64_encode('')
23
+ print(string)
24
+
25
+ # Use the alternative constructor
26
+ from Pyjo.String.Unicode import u
27
+ string = u('foobarbaz').b64_encode('').say()
28
+
29
+ :mod:`Pyjo.String.Unicode` is a :class:`str` that provides a more friendly
30
+ API for many of the functions in :mod:`Pyjo.Util`. Its counterpart for bytes
31
+ is :mod:`Pyjo.String.Bytes`, and both have every method: a method that needs
32
+ bytes encodes the string with ``UTF-8``. A method that turns a string into
33
+ another one returns a :mod:`Pyjo.String.Unicode` object, and one that makes
34
+ bytes, like :meth:`~Pyjo_String_Unicode.md5_bytes`, a
35
+ :mod:`Pyjo.String.Bytes` object. ::
36
+
37
+ # Use it as a str
38
+ string = Pyjo.String.Unicode.new('foo')
39
+ print(string.upper())
40
+
41
+ See also
42
+ --------
43
+
44
+ :mod:`Pyjoyment`, https://mojolicious.org.
45
+
46
+ Ported from `Mojo::ByteStream <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojo/ByteStream.pm>`_
47
+ of Mojolicious 9.49.
48
+
49
+ Functions
50
+ ---------
51
+ """
52
+
53
+ import Pyjo.Base
54
+ import Pyjo.Collection
55
+ import Pyjo.String.Bytes
56
+ import Pyjo.Util
57
+
58
+ import builtins
59
+ import re
60
+ import sys
61
+
62
+ from collections.abc import Callable
63
+ from typing import IO, Any, Self
64
+
65
+
66
+ type Anything = builtins.object
67
+
68
+
69
+ class Pyjo_String_Unicode(str):
70
+ """
71
+ :mod:`Pyjo.String.Unicode` inherits all methods from :class:`str` and
72
+ implements the following new ones.
73
+ """
74
+
75
+ def __new__(cls, *parts: Anything) -> Self:
76
+ return super().__new__(cls, ''.join(map(_str, parts)))
77
+
78
+ def __repr__(self) -> str:
79
+ return f'{self.__module__}.new({super().__repr__()})'
80
+
81
+ # Left out from Mojolicious: the "bool" operator, that makes every
82
+ # bytestream true, as "0" is false in Perl; a str is false only when empty
83
+
84
+ def b64_decode(self) -> 'Pyjo.String.Bytes.object':
85
+ """::
86
+
87
+ data = string.b64_decode()
88
+
89
+ Base64 decode string with :func:`Pyjo.Util.b64_decode`.
90
+ """
91
+ return Pyjo.String.Bytes.new(Pyjo.Util.b64_decode(self.to_str()))
92
+
93
+ def b64_encode(self, eol: str = '\n') -> Self:
94
+ r"""::
95
+
96
+ string = string.b64_encode()
97
+ string = string.b64_encode("\n")
98
+
99
+ Base64 encode string with :func:`Pyjo.Util.b64_encode`. ::
100
+
101
+ # "Zm9vIGJhciBiYXo="
102
+ u('foo bar baz').b64_encode('')
103
+ """
104
+ return self.new(Pyjo.Util.b64_encode(self.to_bytes(), eol))
105
+
106
+ def camelize(self) -> Self:
107
+ """::
108
+
109
+ string = string.camelize()
110
+
111
+ Camelize string with :func:`Pyjo.Util.camelize`.
112
+ """
113
+ return self.new(Pyjo.Util.camelize(self.to_str()))
114
+
115
+ def clone(self) -> Self:
116
+ """::
117
+
118
+ string2 = string.clone()
119
+
120
+ Return a new :mod:`Pyjo.String.Unicode` object cloned from this string.
121
+ """
122
+ return self.new(self.to_str())
123
+
124
+ def decamelize(self) -> Self:
125
+ """::
126
+
127
+ string = string.decamelize()
128
+
129
+ Decamelize string with :func:`Pyjo.Util.decamelize`.
130
+ """
131
+ return self.new(Pyjo.Util.decamelize(self.to_str()))
132
+
133
+ def decode(self, encoding: str = 'UTF-8', errors: str = 'strict') -> Self:
134
+ """::
135
+
136
+ string = string.decode()
137
+ string = string.decode('iso-8859-1')
138
+
139
+ Decode string of the characters 0-255, as the bytes they are, defaults
140
+ to using ``UTF-8``. ::
141
+
142
+ # "♥"
143
+ u('%E2%99%A5').url_unescape().decode()
144
+ """
145
+ # Unlike Mojolicious: invalid input raises an exception, as bytes.decode()
146
+ # does, and Mojo::ByteStream becomes undef
147
+ return self.new(self.to_str().encode('latin-1').decode(encoding, errors))
148
+
149
+ def encode(self, encoding: str = 'UTF-8', errors: str = 'strict') -> 'Pyjo.String.Bytes.object':
150
+ """::
151
+
152
+ data = string.encode()
153
+ data = string.encode('iso-8859-1')
154
+
155
+ Encode string to a :mod:`Pyjo.String.Bytes` object, defaults to using
156
+ ``UTF-8``. ::
157
+
158
+ # b"%E2%99%A5"
159
+ u('♥').encode().url_escape()
160
+ """
161
+ # Unlike Mojolicious: a character that the encoding cannot represent raises
162
+ # an exception, as str.encode() does, and Mojo replaces it
163
+ return Pyjo.String.Bytes.new(self.to_str().encode(encoding, errors))
164
+
165
+ def gunzip(self) -> 'Pyjo.String.Bytes.object':
166
+ """::
167
+
168
+ data = string.gunzip()
169
+
170
+ Uncompress string with :func:`Pyjo.Util.gunzip`.
171
+ """
172
+ return Pyjo.String.Bytes.new(Pyjo.Util.gunzip(self.to_bytes()))
173
+
174
+ def gzip(self) -> 'Pyjo.String.Bytes.object':
175
+ """::
176
+
177
+ data = string.gzip()
178
+
179
+ Compress string with :func:`Pyjo.Util.gzip`.
180
+ """
181
+ return Pyjo.String.Bytes.new(Pyjo.Util.gzip(self.to_bytes()))
182
+
183
+ def hmac_sha1_sum(self, secret: str | bytes) -> Self:
184
+ """::
185
+
186
+ string = string.hmac_sha1_sum('passw0rd')
187
+
188
+ Generate HMAC-SHA1 checksum for string with
189
+ :func:`Pyjo.Util.hmac_sha1_sum`. ::
190
+
191
+ # "7fbdc89263974a89210ea71f171c77d3f8c21471"
192
+ u('foo bar baz').hmac_sha1_sum('secr3t')
193
+ """
194
+ return self.new(Pyjo.Util.hmac_sha1_sum(self.to_bytes(), _bytes(secret)))
195
+
196
+ def html_unescape(self) -> Self:
197
+ """::
198
+
199
+ string = string.html_unescape()
200
+
201
+ Unescape all HTML entities in string with
202
+ :func:`Pyjo.Util.html_unescape`. ::
203
+
204
+ # "%3Chtml%3E"
205
+ u('&lt;html&gt;').html_unescape().url_escape()
206
+ """
207
+ return self.new(Pyjo.Util.html_unescape(self.to_str()))
208
+
209
+ def humanize_bytes(self) -> Self:
210
+ """::
211
+
212
+ string = string.humanize_bytes()
213
+
214
+ Turn number of bytes into a simplified human readable format for string
215
+ with :func:`Pyjo.Util.humanize_bytes`.
216
+ """
217
+ return self.new(Pyjo.Util.humanize_bytes(_number(self.to_str())))
218
+
219
+ def md5_bytes(self) -> 'Pyjo.String.Bytes.object':
220
+ """::
221
+
222
+ data = string.md5_bytes()
223
+
224
+ Generate binary MD5 checksum for string with :func:`Pyjo.Util.md5_bytes`.
225
+ """
226
+ return Pyjo.String.Bytes.new(Pyjo.Util.md5_bytes(self.to_bytes()))
227
+
228
+ def md5_sum(self) -> Self:
229
+ """::
230
+
231
+ string = string.md5_sum()
232
+
233
+ Generate MD5 checksum for string with :func:`Pyjo.Util.md5_sum`.
234
+ """
235
+ return self.new(Pyjo.Util.md5_sum(self.to_bytes()))
236
+
237
+ @classmethod
238
+ def new(cls, *parts: Anything) -> Self:
239
+ """::
240
+
241
+ string = Pyjo.String.Unicode.new('test123')
242
+
243
+ Construct a new :mod:`Pyjo.String.Unicode` object.
244
+ """
245
+ return cls(*parts)
246
+
247
+ def punycode_decode(self) -> Self:
248
+ """::
249
+
250
+ string = string.punycode_decode()
251
+
252
+ Punycode decode string with :func:`Pyjo.Util.punycode_decode`.
253
+ """
254
+ return self.new(Pyjo.Util.punycode_decode(self.to_str()))
255
+
256
+ def punycode_encode(self) -> Self:
257
+ """::
258
+
259
+ string = string.punycode_encode()
260
+
261
+ Punycode encode string with :func:`Pyjo.Util.punycode_encode`.
262
+ """
263
+ return self.new(Pyjo.Util.punycode_encode(self.to_str()))
264
+
265
+ def quote(self) -> Self:
266
+ """::
267
+
268
+ string = string.quote()
269
+
270
+ Quote string with :func:`Pyjo.Util.quote`.
271
+ """
272
+ return self.new(Pyjo.Util.quote(self.to_str()))
273
+
274
+ def say(self, handle: IO[str] | None = None) -> Self:
275
+ """::
276
+
277
+ string = string.say()
278
+ string = string.say(sys.stderr)
279
+
280
+ Print string to handle and append a newline, defaults to using
281
+ :data:`sys.stdout`.
282
+ """
283
+ print(self.to_str(), file=handle if handle is not None else sys.stdout)
284
+ return self
285
+
286
+ def secure_compare(self, string: str | bytes) -> bool:
287
+ """::
288
+
289
+ boolean = string.secure_compare(string2)
290
+
291
+ Compare string with :func:`Pyjo.Util.secure_compare`.
292
+ """
293
+ return Pyjo.Util.secure_compare(self.to_str(), string)
294
+
295
+ def sha1_bytes(self) -> 'Pyjo.String.Bytes.object':
296
+ """::
297
+
298
+ data = string.sha1_bytes()
299
+
300
+ Generate binary SHA1 checksum for string with
301
+ :func:`Pyjo.Util.sha1_bytes`.
302
+ """
303
+ return Pyjo.String.Bytes.new(Pyjo.Util.sha1_bytes(self.to_bytes()))
304
+
305
+ def sha1_sum(self) -> Self:
306
+ """::
307
+
308
+ string = string.sha1_sum()
309
+
310
+ Generate SHA1 checksum for string with :func:`Pyjo.Util.sha1_sum`.
311
+ """
312
+ return self.new(Pyjo.Util.sha1_sum(self.to_bytes()))
313
+
314
+ @property
315
+ def size(self) -> int:
316
+ """::
317
+
318
+ size = string.size
319
+
320
+ Size of string.
321
+ """
322
+ return len(self)
323
+
324
+ def slugify(self, allow_unicode: bool = False) -> Self:
325
+ """::
326
+
327
+ string = string.slugify()
328
+ string = string.slugify(boolean)
329
+
330
+ Generate URL slug for string with :func:`Pyjo.Util.slugify`.
331
+ """
332
+ return self.new(Pyjo.Util.slugify(self.to_str(), allow_unicode))
333
+
334
+ # Perl's split, which Mojo uses, is not str.split()
335
+ def split( # pyright: ignore[reportIncompatibleMethodOverride]
336
+ self, pattern: str | re.Pattern[str], limit: int = 0
337
+ ) -> 'Pyjo.Collection.object[Self | None]':
338
+ """::
339
+
340
+ collection = string.split(',')
341
+ collection = string.split(',', -1)
342
+
343
+ Turn string into :mod:`Pyjo.Collection` object containing
344
+ :mod:`Pyjo.String.Unicode` objects. The pattern is a regular
345
+ expression, and the fields at the end that are empty are left out,
346
+ unless the limit is negative. ::
347
+
348
+ # "One,Two,Three"
349
+ u('one,two,three').split(',').map('camelize').join(',')
350
+
351
+ # "One,Two,Three,,,"
352
+ u('one,two,three,,,').split(',', -1).map('camelize').join(',')
353
+ """
354
+ return Pyjo.Collection.object(
355
+ [None if f is None else self.new(f) for f in split(pattern, self.to_str(), limit)]
356
+ )
357
+
358
+ def tap(self, cb: Callable[..., Any] | str, *args: Any, **kwargs: Any) -> Self:
359
+ """::
360
+
361
+ string = string.tap(lambda s: ...)
362
+
363
+ Alias for :meth:`Pyjo.Base.tap`.
364
+ """
365
+ Pyjo.Base.tap(self, cb, *args, **kwargs)
366
+ return self
367
+
368
+ def term_escape(self) -> Self:
369
+ """::
370
+
371
+ string = string.term_escape()
372
+
373
+ Escape POSIX control characters in string with
374
+ :func:`Pyjo.Util.term_escape`. ::
375
+
376
+ # Print binary checksum to terminal
377
+ u('foo').sha1_bytes().term_escape().say()
378
+ """
379
+ return self.new(Pyjo.Util.term_escape(self.to_str()))
380
+
381
+ # Not in Mojolicious: the counterpart of to_str() in Pyjo.String.Mixin
382
+ def to_bytes(self) -> bytes:
383
+ """::
384
+
385
+ data = string.to_bytes()
386
+
387
+ Turn string into :class:`bytes`, encoded with ``UTF-8``.
388
+ """
389
+ return self.to_str().encode('UTF-8')
390
+
391
+ def to_str(self) -> str:
392
+ """::
393
+
394
+ string = string.to_str()
395
+
396
+ Turn string into :class:`str`.
397
+ """
398
+ return str.__str__(self)
399
+
400
+ def trim(self) -> Self:
401
+ """::
402
+
403
+ string = string.trim()
404
+
405
+ Trim whitespace characters from both ends of string with
406
+ :func:`Pyjo.Util.trim`.
407
+ """
408
+ return self.new(Pyjo.Util.trim(self.to_str()))
409
+
410
+ def unindent(self) -> Self:
411
+ """::
412
+
413
+ string = string.unindent()
414
+
415
+ Unindent string with :func:`Pyjo.Util.unindent`.
416
+ """
417
+ return self.new(Pyjo.Util.unindent(self.to_str()))
418
+
419
+ def unquote(self) -> Self:
420
+ """::
421
+
422
+ string = string.unquote()
423
+
424
+ Unquote string with :func:`Pyjo.Util.unquote`.
425
+ """
426
+ return self.new(Pyjo.Util.unquote(self.to_str()))
427
+
428
+ def url_escape(self, pattern: str | None = None) -> Self:
429
+ r"""::
430
+
431
+ string = string.url_escape()
432
+ string = string.url_escape(r'^A-Za-z0-9\-._~')
433
+
434
+ Percent encode all unsafe characters in string with
435
+ :func:`Pyjo.Util.url_escape`. ::
436
+
437
+ # b"%E2%98%83"
438
+ u('☃').encode().url_escape()
439
+ """
440
+ return self.new(Pyjo.Util.url_escape(self.to_str(), pattern))
441
+
442
+ def url_unescape(self) -> Self:
443
+ """::
444
+
445
+ string = string.url_unescape()
446
+
447
+ Decode percent encoded characters in string with
448
+ :func:`Pyjo.Util.url_unescape`. ::
449
+
450
+ # "&lt;html&gt;"
451
+ u('%3Chtml%3E').url_unescape().xml_escape()
452
+ """
453
+ return self.new(Pyjo.Util.url_unescape(self.to_str()))
454
+
455
+ # Left out from Mojolicious: with_roles, as Pyjoyment has no roles
456
+
457
+ def xml_escape(self) -> Self:
458
+ """::
459
+
460
+ string = string.xml_escape()
461
+
462
+ Escape only the characters ``&``, ``<``, ``>``, ``"`` and ``'`` in
463
+ string with :func:`Pyjo.Util.xml_escape`.
464
+ """
465
+ return self.new(Pyjo.Util.xml_escape(self.to_str()))
466
+
467
+ def xor_encode(self, key: str | bytes) -> 'Pyjo.String.Bytes.object':
468
+ """::
469
+
470
+ data = string.xor_encode(key)
471
+
472
+ XOR encode string with :func:`Pyjo.Util.xor_encode`. ::
473
+
474
+ # b"%04%0E%15B%03%1B%10"
475
+ u('foo bar').xor_encode('baz').url_escape()
476
+ """
477
+ return Pyjo.String.Bytes.new(Pyjo.Util.xor_encode(self.to_bytes(), _bytes(key)))
478
+
479
+
480
+ def u(*parts: Anything) -> Pyjo_String_Unicode:
481
+ """::
482
+
483
+ string = u('test123')
484
+
485
+ Construct a new :mod:`Pyjo.String.Unicode` object.
486
+ """
487
+ return Pyjo_String_Unicode(*parts)
488
+
489
+
490
+ # Not in Mojolicious: Perl's split, for Pyjo.String.Bytes too
491
+ def split(pattern: str | re.Pattern[str], string: str, limit: int = 0) -> list[str | None]:
492
+ """::
493
+
494
+ fields = split(',', '1,2,3')
495
+
496
+ Split string as Perl's ``split`` does: the pattern is a regular
497
+ expression, a match of no length at the beginning of the string or right
498
+ after another match makes no field, the groups of the pattern are fields
499
+ too, and the fields at the end that are empty are left out, unless the
500
+ limit is negative. A positive limit is the largest number
501
+ of fields, the pattern ``' '`` splits on whitespace after leading
502
+ whitespace, and ``'^'`` matches at the beginning of every line.
503
+ """
504
+ if pattern == ' ':
505
+ string, pattern = re.sub(r'\A\s+', '', string), r'\s+'
506
+ regex = re.compile(pattern) if isinstance(pattern, str) else pattern
507
+ if regex.pattern == '^':
508
+ regex = re.compile('^', regex.flags | re.M)
509
+ if not len(string):
510
+ return []
511
+
512
+ fields: list[str | None] = []
513
+ pos = count = 0
514
+ for m in regex.finditer(string):
515
+ if limit > 0 and count >= limit - 1:
516
+ break
517
+ if m.start() == m.end() == pos:
518
+ continue
519
+ fields.append(string[pos : m.start()])
520
+ fields.extend(m.groups())
521
+ pos = m.end()
522
+ count += 1
523
+ fields.append(string[pos:])
524
+
525
+ if limit == 0:
526
+ while len(fields) and not fields[-1]:
527
+ fields.pop()
528
+ return fields
529
+
530
+
531
+ def _bytes(value: str | bytes) -> bytes:
532
+ return value.encode('UTF-8') if isinstance(value, str) else value
533
+
534
+
535
+ def _number(string: str) -> int | float:
536
+ try:
537
+ return int(string)
538
+ except ValueError:
539
+ return float(string)
540
+
541
+
542
+ def _str(part: Anything) -> str:
543
+ if isinstance(part, (bytes, bytearray)):
544
+ try:
545
+ return bytes(part).decode('UTF-8')
546
+ except UnicodeDecodeError:
547
+ return bytes(part).decode('latin-1')
548
+ return str(part)
549
+
550
+
551
+ new = Pyjo_String_Unicode.new
552
+ object = Pyjo_String_Unicode
553
+ Unicode = Pyjo_String_Unicode
File without changes