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,41 @@
1
+ # The default certificate for TLS servers
2
+
3
+ The certificate and key that a TLS server of `Pyjo.IOLoop.Server` uses when
4
+ it is given none, as `lib/Mojo/IOLoop/resources` in Mojolicious. They are not
5
+ secret and are meant for development only.
6
+
7
+ | Files | Certificate |
8
+ | -------------------------- | ------------------------------------------------- |
9
+ | `ca.crt` | The CA that signs the server, `Pyjoyment Test CA` |
10
+ | `server.crt`, `server.key` | `localhost` and `127.0.0.1`, for a server |
11
+
12
+ The key of the CA is not kept, so the certificate is made again with a new
13
+ CA. They are RSA 2048 keys, valid for a hundred years, made with OpenSSL 3 in
14
+ a temporary directory, from the root of the repository:
15
+
16
+ ```sh
17
+ certs=$PWD/Pyjo/IOLoop/certs
18
+ cd "$(mktemp -d)"
19
+
20
+ openssl req -x509 -newkey rsa:2048 -nodes -days 36500 \
21
+ -keyout ca.key -out ca.crt -subj '/O=Pyjoyment/CN=Pyjoyment Test CA' \
22
+ -addext 'basicConstraints=critical,CA:TRUE' \
23
+ -addext 'keyUsage=critical,keyCertSign,cRLSign' \
24
+ -addext 'subjectKeyIdentifier=hash'
25
+
26
+ openssl req -newkey rsa:2048 -nodes -keyout server.key -out server.csr -subj '/O=Pyjoyment/CN=localhost'
27
+ printf 'basicConstraints=critical,CA:FALSE\nkeyUsage=critical,digitalSignature,keyEncipherment\nextendedKeyUsage=serverAuth\nsubjectAltName=DNS:localhost,IP:127.0.0.1\nsubjectKeyIdentifier=hash\nauthorityKeyIdentifier=keyid\n' > server.ext
28
+ openssl x509 -req -days 36500 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
29
+ -out server.crt -extfile server.ext
30
+
31
+ openssl verify -CAfile ca.crt server.crt
32
+ ```
33
+
34
+ Then copy the certificates and the key into `Pyjo/IOLoop/certs`, readable by
35
+ everyone, and delete the temporary directory, the key of the CA with it:
36
+
37
+ ```sh
38
+ chmod 644 server.key
39
+ cp ca.crt server.crt server.key "$certs/"
40
+ cd "$certs" && rm -rf "$OLDPWD"
41
+ ```
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDUzCCAjugAwIBAgIUGusTwLea9+WoMwFTwdUZ02xRYGowDQYJKoZIhvcNAQEL
3
+ BQAwMDESMBAGA1UECgwJUHlqb3ltZW50MRowGAYDVQQDDBFQeWpveW1lbnQgVGVz
4
+ dCBDQTAgFw0yNjEwMTMyMzAwNTVaGA8yMTI2MDkxOTIzMDA1NVowMDESMBAGA1UE
5
+ CgwJUHlqb3ltZW50MRowGAYDVQQDDBFQeWpveW1lbnQgVGVzdCBDQTCCASIwDQYJ
6
+ KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaawIuyilsP0nJF4w9L4TCfgyg/MEib
7
+ c0vRmzGHU25FwPd3DXLxxXvp8LAbLraV7y0ML2pBDLPnAGlZeiwj80gnjU7Xa6cz
8
+ uf530qau29XUY2wL1DdZ8glbfXFssF5tzday6QNCBNHrmKhAM4AfHZCF8ZQba65p
9
+ x5XO3VRuayYu4hzvbNgV/0/CbQdfLu7iQk+RepzBjhELwYOnSddXqMVEKMHJ1T1n
10
+ G8qBP1lhZ1RZCo6sPRG/Ctsb865QrhXR/Yy3Z4PR1kMxQuWOmegDqkvFZ2eflg+6
11
+ Tg803GIVLyD/iHNqI1Bmpra9yFAYdfDKJMKR+xi7bViUlRnaKCsuoeECAwEAAaNj
12
+ MGEwHwYDVR0jBBgwFoAU1sNAQ516BAG2T7eAeEWnmQElItAwDwYDVR0TAQH/BAUw
13
+ AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNbDQEOdegQBtk+3gHhFp5kB
14
+ JSLQMA0GCSqGSIb3DQEBCwUAA4IBAQBE/R+rlDJ8rk9NEnWbqVIDQLuguj6jf+rJ
15
+ fALdS4puNhuyz0MHEI8VtdWyQ/LgG9gIUBtmGcmK1rA00URw9CNyYoMXARgSEerb
16
+ M8u4I6nQX8jB2HtF2HTzwfy3VC41KpB2yGpMZGZ4wdrAOU1OF5XkV0s73leX1ID4
17
+ iRViAJFJCusHrxZvGhy4+a+wloqHWcZulnRZ9WnwhO6dYGmNvB9hMQepBEUPchzm
18
+ w48PwIRgzODHbpYed1Umm3DBuHJ9qnYaoiDHwubhFpnmmc0WLQ3OqAfAGrAfi8YJ
19
+ HzMQVY4dpV2VcoHx/CLLA1c0yS/sZhRcSmyrPVZd4fTEgc7l1ZZO
20
+ -----END CERTIFICATE-----
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDezCCAmOgAwIBAgIUExWjIj2Z0yG9TTigOtVSxDE6hQYwDQYJKoZIhvcNAQEL
3
+ BQAwMDESMBAGA1UECgwJUHlqb3ltZW50MRowGAYDVQQDDBFQeWpveW1lbnQgVGVz
4
+ dCBDQTAgFw0yNjEwMTMyMzAwNTVaGA8yMTI2MDkxOTIzMDA1NVowKDESMBAGA1UE
5
+ CgwJUHlqb3ltZW50MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEB
6
+ AQUAA4IBDwAwggEKAoIBAQC1kmztQGuxRLp20syf7WuJ7tGplv0IWPsLysmsCi9T
7
+ ptQyA7EMLhXcWia67yKU0nm9h2H1oIELv0+x2+9W0zU68ZVgUuzIdeRZfBUGmaKf
8
+ WGyr5nChOgQuRVtTPUpY2jEOo/hfTUMblp5HsyfLstT0BpO6DmK3mBHDhhvxNDia
9
+ o9aVB+YUrCINoBExKpgCnMdWb7Tstiwfd17RecdK0Jbo6T3QgCETHsZxP/8xvAoo
10
+ BVGZKXedDqANIgbx+l/t/ElxtMaTUg2zDryZGtNPETLm9jtqDNHX2X4lRtiUDn0e
11
+ +UFvf2G0pjzCnF+oU3BHfEg0DjoiRrpN27ga4OdEevRZAgMBAAGjgZIwgY8wDAYD
12
+ VR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEw
13
+ GgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMB0GA1UdDgQWBBS6+cOKqM8zZjgn
14
+ fa9eXgRCq0BzwzAfBgNVHSMEGDAWgBTWw0BDnXoEAbZPt4B4RaeZASUi0DANBgkq
15
+ hkiG9w0BAQsFAAOCAQEAXaP1PCz+XjDRouw6iVOegiL/nVBn84Hq66WC4VBQWhBn
16
+ vtJC87Y6w62Mt/bB9CCWWwCwE2nIUWh96a52fKC6zkeX1hLWhYQJUtBD4Grpxe3r
17
+ aTgcocHhQLV8kkxBPoEMQuBNFEc8rGVIy8St0GIVwan4YiL/GBOMswDQeSt7iKGt
18
+ tTrGhBTryxK1dvZIm9XpIl9MaiwRu1MmF4prQtMvaXxFwZBu8KN2GG5whzuMOgZx
19
+ lrz6fcaBKe3htygARqRD8qCvQBStLwJX6KVvl/0uRwkC45n67hp9dcGSr+Qp8uCe
20
+ l2zWle6Nw9rlF36Hv/VRYo6yWQQt/xot6XQAEoXAVw==
21
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1kmztQGuxRLp2
3
+ 0syf7WuJ7tGplv0IWPsLysmsCi9TptQyA7EMLhXcWia67yKU0nm9h2H1oIELv0+x
4
+ 2+9W0zU68ZVgUuzIdeRZfBUGmaKfWGyr5nChOgQuRVtTPUpY2jEOo/hfTUMblp5H
5
+ syfLstT0BpO6DmK3mBHDhhvxNDiao9aVB+YUrCINoBExKpgCnMdWb7Tstiwfd17R
6
+ ecdK0Jbo6T3QgCETHsZxP/8xvAooBVGZKXedDqANIgbx+l/t/ElxtMaTUg2zDryZ
7
+ GtNPETLm9jtqDNHX2X4lRtiUDn0e+UFvf2G0pjzCnF+oU3BHfEg0DjoiRrpN27ga
8
+ 4OdEevRZAgMBAAECggEADMsSfvR0Kg81QqhHZ+jM9BDmR6hWb4NCfAIXq9YjX8Xg
9
+ S15YeAraujYFZtQw1/LNBlo+wBVlJkheY4IjNtdGl768F0d8fMLWuincmuSSEV9j
10
+ 98gyrR92+jIjlUW7Im/MN1N9DWz2kp/uCtAAGLGC4OdCOyCmmrg9nyzItPnol5ef
11
+ hFTxxLhES2QbYV2KHZ9+7DfIL1K2HM7FDLfdX8u2w7pXOMcfFw1Ul4S58nrQYULf
12
+ nyDXrYYU+awcGYGsW2EYesS+AAI4h2Gd0Yse0wtqcOCYZrjhDpTB9aZ1gYS8VPsj
13
+ /TwTWMWhyAmBwrAZ55jPR9cAds5RuRaeG5UtINWAoQKBgQDcMmqtZJdXRxeEh7P9
14
+ IDGlsewTkOppHQBpjGVp+PrD6JOTqJgBH1hRkvX/jblviqORqmG5AWGnoJYeqpOw
15
+ 5nzalZrQKha6rdJ5h8GMwTwoO/Wgm+zHWWB25rdRMXIAkNALXG/E25ln66bZjDEQ
16
+ I/pTI0qorX2qnNtzP4hCQHna4QKBgQDTGEO//kiyX488VpXW5VnBZPDvZ63+gmCt
17
+ 4MJWFvlg6NYQ4RICi7LLjoc71HM1uyVXPBJ7LhPhaMrtYT3froM+1ClG2OAKaNTw
18
+ XRNtyEl61YXMEQvTHKcVJqgirFb1ozkBm46Xyl3f2xumYP+FBBULthVfnNa5wEUJ
19
+ vXEKTbKAeQKBgQCue3jSmuHdc+TrzIhQLKGKlZjmzC8jSarY+DooJfW3JWVDXRXN
20
+ 1eOrCBPMA6aL/0SrmWJEMhcKuBIcjLfpNkp6/o8lIiTOmgws5uj0uu4LR6/UK5oN
21
+ QQJSVXGvccnPLvDb/8xFJmnB0hZtTkxWaNvj4xQ24vqwJgkyooY7UVH9oQKBgFGl
22
+ XO7xZyS2mSv5QVMwuhp29ElkjIOX4dTezcuGb0XwSHuW0eRyK+FXay7U6QqrK7Il
23
+ 5fAGzmGsqnBN4CSX1uOCI8TnNSBRk6q0FUOs596+n1VicnRg7K7dmMJwbeHsE6xv
24
+ giNrfguLL5KWib3k6k7xSisE+ng1yX4O653Ul2nhAoGAYl9SDnK4lZHqVsMIMO2D
25
+ 4V+SFPpoAHFYKGM2kbRPvsWPja5WkDE0rMh50FkeDSZgkmI9/tGYkNi7d3GiM1T5
26
+ pg2u6dPfP5kqzMHOWe6twDh/OWAXduxfiEp54GrKL1jbfr1XniKFWqqKTCeGCUU4
27
+ QbxC3HkS17GyLy/r4Uo6+zg=
28
+ -----END PRIVATE KEY-----
Pyjo/JSON/Pointer.py ADDED
@@ -0,0 +1,135 @@
1
+ """
2
+ Pyjo.JSON.Pointer - JSON Pointers
3
+ =================================
4
+ ::
5
+
6
+ from Pyjo.JSON.Pointer import Pointer
7
+
8
+ pointer = Pointer({'foo': [23, 'bar']})
9
+ print(pointer.get('/foo/1'))
10
+ if pointer.contains('/foo'):
11
+ print('Contains "/foo".')
12
+
13
+ # Or import the module, as in Google Python Style Guide
14
+
15
+ import Pyjo.JSON.Pointer
16
+
17
+ pointer = Pyjo.JSON.Pointer.new({'foo': [23, 'bar']})
18
+ print(pointer.get('/foo/1'))
19
+ if pointer.contains('/foo'):
20
+ print('Contains "/foo".')
21
+
22
+ :mod:`Pyjo.JSON.Pointer` is an implementation of :rfc:`6901`.
23
+
24
+ See also
25
+ --------
26
+
27
+ :mod:`Pyjoyment`, https://mojolicious.org.
28
+
29
+ Ported from `Mojo::JSON::Pointer <https://github.com/mojolicious/mojo/blob/v9.49/lib/Mojo/JSON/Pointer.pm>`_
30
+ of Mojolicious 9.49.
31
+
32
+ Classes
33
+ -------
34
+ """
35
+
36
+ import Pyjo.Base
37
+
38
+ import re
39
+
40
+ from typing import Any, cast
41
+
42
+
43
+ class Pyjo_JSON_Pointer(Pyjo.Base.object):
44
+ """
45
+ :mod:`Pyjo.JSON.Pointer` inherits all methods from :mod:`Pyjo.Base` and
46
+ implements the following new ones.
47
+ """
48
+
49
+ def __init__(self, data: Any = None) -> None:
50
+ """::
51
+
52
+ pointer = Pyjo.JSON.Pointer.new()
53
+ pointer = Pyjo.JSON.Pointer.new({'foo': 'bar'})
54
+
55
+ Build new :mod:`Pyjo.JSON.Pointer` object.
56
+ """
57
+ self.data: Any = data
58
+ """::
59
+
60
+ data = pointer.data
61
+ pointer.data = {'foo': 'bar'}
62
+
63
+ Data structure to be processed.
64
+ """
65
+
66
+ def contains(self, pointer: str) -> bool:
67
+ """::
68
+
69
+ boolean = pointer.contains('/foo/1')
70
+
71
+ Check if :attr:`data` contains a value that can be identified with the
72
+ given JSON Pointer. ::
73
+
74
+ # True
75
+ Pyjo.JSON.Pointer.new('just a string').contains('')
76
+ Pyjo.JSON.Pointer.new({'♥': 'pyjoyment'}).contains('/♥')
77
+ Pyjo.JSON.Pointer.new({'foo': 'bar', 'baz': [4, 5]}).contains('/foo')
78
+ Pyjo.JSON.Pointer.new({'foo': 'bar', 'baz': [4, 5]}).contains('/baz/1')
79
+
80
+ # False
81
+ Pyjo.JSON.Pointer.new({'♥': 'pyjoyment'}).contains('/☃')
82
+ Pyjo.JSON.Pointer.new({'foo': 'bar', 'baz': [4, 5]}).contains('/bar')
83
+ Pyjo.JSON.Pointer.new({'foo': 'bar', 'baz': [4, 5]}).contains('/baz/9')
84
+ """
85
+ return self._pointer(False, pointer) is not None
86
+
87
+ def get(self, pointer: str) -> Any:
88
+ """::
89
+
90
+ value = pointer.get('/foo/bar')
91
+
92
+ Extract value from :attr:`data` identified by the given JSON Pointer. ::
93
+
94
+ # "just a string"
95
+ Pyjo.JSON.Pointer.new('just a string').get('')
96
+
97
+ # "pyjoyment"
98
+ Pyjo.JSON.Pointer.new({'♥': 'pyjoyment'}).get('/♥')
99
+
100
+ # "bar"
101
+ Pyjo.JSON.Pointer.new({'foo': 'bar', 'baz': [4, 5, 6]}).get('/foo')
102
+
103
+ # 4
104
+ Pyjo.JSON.Pointer.new({'foo': 'bar', 'baz': [4, 5, 6]}).get('/baz/0')
105
+
106
+ # 6
107
+ Pyjo.JSON.Pointer.new({'foo': 'bar', 'baz': [4, 5, 6]}).get('/baz/2')
108
+ """
109
+ return self._pointer(True, pointer)
110
+
111
+ def _pointer(self, get: bool, pointer: str) -> Any:
112
+ data: Any = self.data
113
+ if not pointer.startswith('/'):
114
+ return None if len(pointer) else data if get else True
115
+ for p in pointer[1:].split('/'):
116
+ p = p.replace('~1', '/').replace('~0', '~')
117
+
118
+ # Hash
119
+ if isinstance(data, dict) and p in data:
120
+ data = cast(dict[str, Any], data)[p]
121
+
122
+ # Array
123
+ elif isinstance(data, (list, tuple)) and re.fullmatch(r'[0-9]+', p) and len(cast(list[Any], data)) > int(p):
124
+ data = cast(list[Any], data)[int(p)]
125
+
126
+ # Nothing
127
+ else:
128
+ return None
129
+
130
+ return data if get else True
131
+
132
+
133
+ new = Pyjo_JSON_Pointer.new
134
+ object = Pyjo_JSON_Pointer
135
+ Pointer = Pyjo_JSON_Pointer