proper 0.1.dev4__tar.gz → 0.9.0__tar.gz

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 (434) hide show
  1. proper-0.9.0/PKG-INFO +120 -0
  2. proper-0.9.0/README.md +82 -0
  3. proper-0.9.0/pyproject.toml +240 -0
  4. proper-0.9.0/setup.cfg +4 -0
  5. proper-0.9.0/src/proper/__init__.py +44 -0
  6. proper-0.9.0/src/proper/app.py +537 -0
  7. proper-0.9.0/src/proper/app_ws.py +221 -0
  8. proper-0.9.0/src/proper/auth.py +217 -0
  9. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/cli/__init__.prepend.py +1 -0
  10. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/cli/auth_cli.tt.py +57 -0
  11. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/config/auth.py +9 -0
  12. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/__init__.append.py +5 -0
  13. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/app_controller.prepend.py +1 -0
  14. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/concerns/authentication.tt.py +79 -0
  15. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/password_reset_controller.tt.py +77 -0
  16. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/session_controller.tt.py +53 -0
  17. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/sign_up_controller.tt.py +37 -0
  18. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/emails/__init__.append.py +1 -0
  19. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/emails/password_reset_email.py +12 -0
  20. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/auth/pwned.py +127 -0
  21. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/auth/validators.tt.py +59 -0
  22. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/password_reset.py +46 -0
  23. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/session.tt.py +36 -0
  24. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/sign_up.py +34 -0
  25. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/main.append.py +1 -0
  26. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/models/__init__.append.py +2 -0
  27. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/models/concerns/authenticable.py +102 -0
  28. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/models/session.py +101 -0
  29. proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/models/user.py +8 -0
  30. proper-0.9.0/src/proper/blueprints/channels/[[app_name]]/config/__init__.append.py +1 -0
  31. proper-0.9.0/src/proper/blueprints/channels/[[app_name]]/config/channels.tt.py +13 -0
  32. proper-0.9.0/src/proper/blueprints/controller/[[app_name]]/controllers/[[name_snake]]_controller.tt.py +101 -0
  33. proper-0.9.0/src/proper/blueprints/controller/[[app_name]]/controllers/__init__.append.py +1 -0
  34. proper-0.9.0/src/proper/blueprints/controller/[[app_name]]/forms/[[name_snake]].tt.py +12 -0
  35. proper-0.9.0/src/proper/blueprints/controller/[[app_name]]/router.append.py +3 -0
  36. proper-0.9.0/src/proper/blueprints/controller/tests/pages/test_[[name_snake]].tt.py +70 -0
  37. proper-0.9.0/src/proper/blueprints/email/[[app_name]]/emails/[[name_snake]]_email.tt.py +8 -0
  38. proper-0.9.0/src/proper/blueprints/email/[[app_name]]/emails/__init__.append.py +1 -0
  39. proper-0.9.0/src/proper/blueprints/i18n/[[app_name]]/controllers/app_controller.prepend.py +1 -0
  40. proper-0.9.0/src/proper/blueprints/model/[[app_name]]/models/[[name_snake]].tt.py +9 -0
  41. proper-0.9.0/src/proper/blueprints/model/[[app_name]]/models/__init__.append.py +1 -0
  42. proper-0.9.0/src/proper/blueprints/storage/[[app_name]]/config/storage.append.py +59 -0
  43. proper-0.9.0/src/proper/blueprints/storage/[[app_name]]/controllers/__init__.append.py +2 -0
  44. proper-0.9.0/src/proper/blueprints/storage/[[app_name]]/controllers/storage_controller.tt.py +29 -0
  45. proper-0.9.0/src/proper/blueprints/storage/[[app_name]]/models/__init__.append.py +1 -0
  46. proper-0.9.0/src/proper/blueprints/storage/[[app_name]]/models/attachment.py +9 -0
  47. proper-0.9.0/src/proper/cable.py +197 -0
  48. proper-0.9.0/src/proper/cache/__init__.py +5 -0
  49. proper-0.9.0/src/proper/cache/base.py +126 -0
  50. proper-0.9.0/src/proper/cache/jinja_ext.py +75 -0
  51. proper-0.9.0/src/proper/cache/keys.py +76 -0
  52. proper-0.9.0/src/proper/cache/redis_cache.py +120 -0
  53. proper-0.9.0/src/proper/cache/sqlite_cache.py +204 -0
  54. proper-0.9.0/src/proper/channel.py +87 -0
  55. proper-0.9.0/src/proper/cli/app_cli.py +152 -0
  56. proper-0.9.0/src/proper/cli/db_cli.py +291 -0
  57. proper-0.9.0/src/proper/concerns/__init__.py +5 -0
  58. proper-0.9.0/src/proper/concerns/concern.py +13 -0
  59. proper-0.9.0/src/proper/concerns/current_locale.py +38 -0
  60. proper-0.9.0/src/proper/concerns/current_timezone.py +34 -0
  61. proper-0.9.0/src/proper/concerns/origin_protection.py +83 -0
  62. proper-0.9.0/src/proper/concerns/rate_limiting.py +175 -0
  63. proper-0.9.0/src/proper/concerns/request_forgery_protection.py +123 -0
  64. proper-0.9.0/src/proper/config.py +121 -0
  65. proper-0.9.0/src/proper/constants.py +14 -0
  66. proper-0.9.0/src/proper/controller.py +258 -0
  67. proper-0.9.0/src/proper/emails/__init__.py +5 -0
  68. {proper-0.1.dev4/blueprints/project/db/migrations → proper-0.9.0/src/proper/emails/mailers}/__init__.py +0 -0
  69. proper-0.9.0/src/proper/emails/mailers/base.py +221 -0
  70. proper-0.9.0/src/proper/emails/mailers/console.py +49 -0
  71. proper-0.9.0/src/proper/emails/mailers/memory.py +25 -0
  72. proper-0.9.0/src/proper/emails/mailers/smtp.py +204 -0
  73. proper-0.9.0/src/proper/emails/message.py +207 -0
  74. proper-0.9.0/src/proper/emails/utils.py +81 -0
  75. proper-0.9.0/src/proper/error_handlers.py +142 -0
  76. {proper-0.1.dev4 → proper-0.9.0/src}/proper/errors.py +164 -37
  77. proper-0.9.0/src/proper/forms.py +269 -0
  78. {proper-0.1.dev4 → proper-0.9.0/src}/proper/generators/__init__.py +2 -1
  79. proper-0.9.0/src/proper/generators/controller.py +221 -0
  80. proper-0.9.0/src/proper/generators/email.py +41 -0
  81. proper-0.9.0/src/proper/generators/model.py +213 -0
  82. proper-0.9.0/src/proper/generators/resource.py +61 -0
  83. proper-0.9.0/src/proper/generators/seed.py +83 -0
  84. proper-0.9.0/src/proper/global_context.py +44 -0
  85. proper-0.9.0/src/proper/helpers/__init__.py +43 -0
  86. proper-0.9.0/src/proper/helpers/dotdict.py +71 -0
  87. proper-0.9.0/src/proper/helpers/html2text.py +183 -0
  88. proper-0.9.0/src/proper/helpers/http.py +36 -0
  89. proper-0.9.0/src/proper/helpers/imports.py +211 -0
  90. proper-0.9.0/src/proper/helpers/json_field.py +26 -0
  91. proper-0.9.0/src/proper/helpers/jsonplus.py +154 -0
  92. proper-0.9.0/src/proper/helpers/multidict.py +170 -0
  93. proper-0.9.0/src/proper/helpers/render.py +122 -0
  94. proper-0.9.0/src/proper/helpers/server.py +70 -0
  95. proper-0.9.0/src/proper/i18n/__init__.py +1 -0
  96. proper-0.9.0/src/proper/i18n/format_size.py +103 -0
  97. proper-0.9.0/src/proper/i18n/formatters.py +1098 -0
  98. proper-0.9.0/src/proper/i18n/i18n.py +330 -0
  99. proper-0.9.0/src/proper/i18n/reader.py +82 -0
  100. proper-0.9.0/src/proper/install/auth.py +51 -0
  101. proper-0.9.0/src/proper/install/channels.py +27 -0
  102. proper-0.9.0/src/proper/install/i18n.py +45 -0
  103. proper-0.9.0/src/proper/install/storage.py +40 -0
  104. proper-0.9.0/src/proper/models.py +216 -0
  105. proper-0.9.0/src/proper/pipeline.py +166 -0
  106. proper-0.9.0/src/proper/request/__init__.py +2 -0
  107. proper-0.9.0/src/proper/request/formparser.py +417 -0
  108. proper-0.9.0/src/proper/request/forwarded.py +120 -0
  109. proper-0.9.0/src/proper/request/headers.py +526 -0
  110. proper-0.9.0/src/proper/request/request.py +252 -0
  111. proper-0.9.0/src/proper/request/utils.py +68 -0
  112. proper-0.9.0/src/proper/response/__init__.py +3 -0
  113. proper-0.9.0/src/proper/response/cookies.py +214 -0
  114. proper-0.9.0/src/proper/response/file_wrapper.py +55 -0
  115. proper-0.9.0/src/proper/response/flash_messages.py +34 -0
  116. proper-0.9.0/src/proper/response/headers.py +632 -0
  117. proper-0.9.0/src/proper/response/response.py +295 -0
  118. proper-0.9.0/src/proper/router/__init__.py +2 -0
  119. proper-0.9.0/src/proper/router/route.py +466 -0
  120. proper-0.9.0/src/proper/router/router.py +783 -0
  121. proper-0.9.0/src/proper/seeds.py +110 -0
  122. proper-0.9.0/src/proper/status.py +205 -0
  123. proper-0.9.0/src/proper/storage/__init__.py +2 -0
  124. proper-0.9.0/src/proper/storage/attachment.py +360 -0
  125. proper-0.9.0/src/proper/storage/imageops.py +429 -0
  126. proper-0.9.0/src/proper/storage/services/__init__.py +3 -0
  127. proper-0.9.0/src/proper/storage/services/disk.py +66 -0
  128. proper-0.9.0/src/proper/storage/services/s3.py +74 -0
  129. proper-0.9.0/src/proper/storage/services/service.py +28 -0
  130. proper-0.9.0/src/proper/template_resolver.py +73 -0
  131. proper-0.9.0/src/proper/test_client.py +450 -0
  132. proper-0.9.0/src/proper/tools/__init__.py +11 -0
  133. proper-0.9.0/src/proper/tools/auth.py +54 -0
  134. proper-0.9.0/src/proper/tools/cable.py +28 -0
  135. proper-0.9.0/src/proper/tools/cache.py +30 -0
  136. proper-0.9.0/src/proper/tools/catalog.py +43 -0
  137. proper-0.9.0/src/proper/tools/db.py +49 -0
  138. proper-0.9.0/src/proper/tools/i18n.py +38 -0
  139. proper-0.9.0/src/proper/tools/mailer.py +26 -0
  140. proper-0.9.0/src/proper/tools/queue.py +82 -0
  141. proper-0.9.0/src/proper/tools/storage.py +45 -0
  142. proper-0.9.0/src/proper/types.py +116 -0
  143. proper-0.9.0/src/proper/units.py +50 -0
  144. proper-0.9.0/src/proper.egg-info/PKG-INFO +120 -0
  145. proper-0.9.0/src/proper.egg-info/SOURCES.txt +174 -0
  146. proper-0.9.0/src/proper.egg-info/requires.txt +19 -0
  147. proper-0.9.0/tests/test_app.py +176 -0
  148. proper-0.9.0/tests/test_auth.py +328 -0
  149. proper-0.9.0/tests/test_cable.py +227 -0
  150. proper-0.9.0/tests/test_cable_redis.py +406 -0
  151. proper-0.9.0/tests/test_cache.py +693 -0
  152. proper-0.9.0/tests/test_cache_redis.py +240 -0
  153. proper-0.9.0/tests/test_channel.py +217 -0
  154. proper-0.9.0/tests/test_controller.py +796 -0
  155. proper-0.9.0/tests/test_error_handlers.py +278 -0
  156. proper-0.9.0/tests/test_error_handling.py +553 -0
  157. proper-0.9.0/tests/test_forms.py +251 -0
  158. proper-0.9.0/tests/test_i18n.py +487 -0
  159. proper-0.9.0/tests/test_pipeline.py +482 -0
  160. proper-0.9.0/tests/test_request.py +1251 -0
  161. proper-0.9.0/tests/test_response.py +1221 -0
  162. proper-0.9.0/tests/test_route.py +658 -0
  163. proper-0.9.0/tests/test_router.py +1358 -0
  164. proper-0.9.0/tests/test_scoped_model.py +282 -0
  165. proper-0.9.0/tests/test_seeds.py +214 -0
  166. proper-0.9.0/tests/test_template_resolver.py +123 -0
  167. proper-0.9.0/tests/test_timestamped.py +159 -0
  168. proper-0.9.0/tests/test_token.py +237 -0
  169. proper-0.9.0/tests/test_tools.py +510 -0
  170. proper-0.9.0/tests/test_websocket.py +471 -0
  171. proper-0.1.dev4/MANIFEST.in +0 -4
  172. proper-0.1.dev4/MIT-LICENSE +0 -20
  173. proper-0.1.dev4/PKG-INFO +0 -87
  174. proper-0.1.dev4/README.md +0 -68
  175. proper-0.1.dev4/blueprints/.DS_Store +0 -0
  176. proper-0.1.dev4/blueprints/controller/[[ app_name ]]/controllers/[[ snake_name ]].tmpl.py +0 -9
  177. proper-0.1.dev4/blueprints/controller/[[ app_name ]]/controllers/__init__.append.py +0 -1
  178. proper-0.1.dev4/blueprints/controller/routes.tmpl.py +0 -5
  179. proper-0.1.dev4/blueprints/controller/template.tmpl.html.jinja +0 -6
  180. proper-0.1.dev4/blueprints/model/[[ app_name ]]/models/[[ snake_name ]].tmpl.py +0 -11
  181. proper-0.1.dev4/blueprints/model/[[ app_name ]]/models/__init__.append.py +0 -1
  182. proper-0.1.dev4/blueprints/project/.DS_Store +0 -0
  183. proper-0.1.dev4/blueprints/project/Dockerfile.tmpl +0 -15
  184. proper-0.1.dev4/blueprints/project/Makefile.tmpl +0 -32
  185. proper-0.1.dev4/blueprints/project/README.tmpl.md +0 -36
  186. proper-0.1.dev4/blueprints/project/[[ app_name ]]/.DS_Store +0 -0
  187. proper-0.1.dev4/blueprints/project/[[ app_name ]]/__init__.py +0 -1
  188. proper-0.1.dev4/blueprints/project/[[ app_name ]]/app.tmpl.py +0 -14
  189. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__init__.py +0 -37
  190. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/__init__.cpython-39.pyc +0 -0
  191. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/development.cpython-39.pyc +0 -0
  192. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/production.cpython-39.pyc +0 -0
  193. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/shared.cpython-39.pyc +0 -0
  194. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/staging.cpython-39.pyc +0 -0
  195. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/testing.cpython-39.pyc +0 -0
  196. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/development.tmpl.py +0 -12
  197. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/production.py +0 -10
  198. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/shared.tmpl.py +0 -27
  199. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/staging.py +0 -4
  200. proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/testing.tmpl.py +0 -10
  201. proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/.DS_Store +0 -0
  202. proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/__init__.py +0 -4
  203. proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/application.py +0 -81
  204. proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/auth.py +0 -85
  205. proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/forms/auth.tmpl.py +0 -63
  206. proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/forms/pwned.py +0 -35
  207. proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/pages.py +0 -12
  208. proper-0.1.dev4/blueprints/project/[[ app_name ]]/mailers/__pycache__/__init__.cpython-39.pyc +0 -0
  209. proper-0.1.dev4/blueprints/project/[[ app_name ]]/mailers/__pycache__/auth.cpython-39.pyc +0 -0
  210. proper-0.1.dev4/blueprints/project/[[ app_name ]]/mailers/auth.py +0 -28
  211. proper-0.1.dev4/blueprints/project/[[ app_name ]]/main.py +0 -28
  212. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__init__.py +0 -4
  213. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/__init__.cpython-39.pyc +0 -0
  214. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/base.cpython-39.pyc +0 -0
  215. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/post.cpython-39.pyc +0 -0
  216. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/relation.cpython-39.pyc +0 -0
  217. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/topic.cpython-39.pyc +0 -0
  218. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/user.cpython-39.pyc +0 -0
  219. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/base.py +0 -25
  220. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/__init__.py +0 -2
  221. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/__pycache__/__init__.cpython-39.pyc +0 -0
  222. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/__pycache__/authenticable.cpython-39.pyc +0 -0
  223. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/__pycache__/timestamped.cpython-39.pyc +0 -0
  224. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/authenticable.tmpl.py +0 -47
  225. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/timestamped.py +0 -19
  226. proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/user.py +0 -8
  227. proper-0.1.dev4/blueprints/project/[[ app_name ]]/routes.py +0 -34
  228. proper-0.1.dev4/blueprints/project/[[ app_name ]]/services/__pycache__/__init__.cpython-39.pyc +0 -0
  229. proper-0.1.dev4/blueprints/project/[[ app_name ]]/services/__pycache__/auth_services.cpython-39.pyc +0 -0
  230. proper-0.1.dev4/blueprints/project/[[ app_name ]]/services/__pycache__/posts_services.cpython-39.pyc +0 -0
  231. proper-0.1.dev4/blueprints/project/[[ app_name ]]/services/auth_services.py +0 -64
  232. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/.DS_Store +0 -0
  233. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/auth/password_change.html.jinja +0 -51
  234. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/auth/reset.html.jinja +0 -41
  235. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/auth/reset_invalid.html.jinja +0 -17
  236. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/auth/reset_sent.html.jinja +0 -20
  237. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/auth/sign_in.html.jinja +0 -56
  238. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/common/Button.html.jinja +0 -9
  239. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/emails/password_reset.html.jinja +0 -14
  240. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/layouts/application.html.jinja +0 -17
  241. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/layouts/auth.html.jinja +0 -19
  242. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/layouts/email.html.jinja +0 -12
  243. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/pages/error.html.jinja +0 -22
  244. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/pages/index.html.jinja +0 -5
  245. proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/pages/not_found.html.jinja +0 -24
  246. proper-0.1.dev4/blueprints/project/db/.DS_Store +0 -0
  247. proper-0.1.dev4/blueprints/project/db/migrations/script.py.mako +0 -24
  248. proper-0.1.dev4/blueprints/project/deploy/nginx.tmpl.conf +0 -46
  249. proper-0.1.dev4/blueprints/project/deploy/uwsgi.tmpl.ini +0 -23
  250. proper-0.1.dev4/blueprints/project/docker-compose.tmpl.yml +0 -22
  251. proper-0.1.dev4/blueprints/project/logs/.keep +0 -0
  252. proper-0.1.dev4/blueprints/project/manage.tmpl.py +0 -43
  253. proper-0.1.dev4/blueprints/project/requirements/dev-requirements.ini +0 -3
  254. proper-0.1.dev4/blueprints/project/requirements/prod-requirements.ini +0 -2
  255. proper-0.1.dev4/blueprints/project/requirements/requirements.ini +0 -8
  256. proper-0.1.dev4/blueprints/project/requirements/test-requirements.ini +0 -6
  257. proper-0.1.dev4/blueprints/project/setup.py +0 -1
  258. proper-0.1.dev4/blueprints/project/setup.tmpl.cfg +0 -47
  259. proper-0.1.dev4/blueprints/project/static/.DS_Store +0 -0
  260. proper-0.1.dev4/blueprints/project/static/.eslintrc.js +0 -38
  261. proper-0.1.dev4/blueprints/project/static/package.json +0 -26
  262. proper-0.1.dev4/blueprints/project/static/postcss.config.js +0 -12
  263. proper-0.1.dev4/blueprints/project/static/public/css/.keep +0 -0
  264. proper-0.1.dev4/blueprints/project/static/public/favicon.ico +0 -0
  265. proper-0.1.dev4/blueprints/project/static/public/fonts/.keep +0 -0
  266. proper-0.1.dev4/blueprints/project/static/public/humans.txt +0 -0
  267. proper-0.1.dev4/blueprints/project/static/public/images/.keep +0 -0
  268. proper-0.1.dev4/blueprints/project/static/public/js/.keep +0 -0
  269. proper-0.1.dev4/blueprints/project/static/public/robots.txt +0 -2
  270. proper-0.1.dev4/blueprints/project/static/public/vendor/.keep +0 -0
  271. proper-0.1.dev4/blueprints/project/static/src/css/_base.css +0 -4
  272. proper-0.1.dev4/blueprints/project/static/src/css/_buttons.css +0 -74
  273. proper-0.1.dev4/blueprints/project/static/src/css/_components.css +0 -12
  274. proper-0.1.dev4/blueprints/project/static/src/css/_forms.css +0 -100
  275. proper-0.1.dev4/blueprints/project/static/src/css/_utilities.css +0 -2
  276. proper-0.1.dev4/blueprints/project/static/src/css/email.css +0 -3
  277. proper-0.1.dev4/blueprints/project/static/src/css/styles.css +0 -3
  278. proper-0.1.dev4/blueprints/project/static/src/js/scripts.js +0 -0
  279. proper-0.1.dev4/blueprints/project/static/tailwind.config.tmpl.js +0 -9
  280. proper-0.1.dev4/blueprints/project/static/webpack.config.js +0 -16
  281. proper-0.1.dev4/blueprints/project/tests/conftest.py +0 -3
  282. proper-0.1.dev4/blueprints/project/uwsgi-dev.ini +0 -18
  283. proper-0.1.dev4/blueprints/project/wsgi.tmpl.py +0 -4
  284. proper-0.1.dev4/blueprints/resource/[[ app_name ]]/controllers/[[ snake_name ]].tmpl.py +0 -14
  285. proper-0.1.dev4/blueprints/resource/[[ app_name ]]/controllers/__init__.append.py +0 -1
  286. proper-0.1.dev4/blueprints/resource/[[ app_name ]]/templates/[[ snake_name ]]/edit.html.jinja +0 -6
  287. proper-0.1.dev4/blueprints/resource/[[ app_name ]]/templates/[[ snake_name ]]/index.html.jinja +0 -6
  288. proper-0.1.dev4/blueprints/resource/[[ app_name ]]/templates/[[ snake_name ]]/new.html.jinja +0 -6
  289. proper-0.1.dev4/blueprints/resource/[[ app_name ]]/templates/[[ snake_name ]]/show.html.jinja +0 -6
  290. proper-0.1.dev4/blueprints/resource/routes.tmpl.py +0 -5
  291. proper-0.1.dev4/proper/.DS_Store +0 -0
  292. proper-0.1.dev4/proper/__init__.py +0 -8
  293. proper-0.1.dev4/proper/__pycache__/__init__.cpython-39.pyc +0 -0
  294. proper-0.1.dev4/proper/__pycache__/auth.cpython-39.pyc +0 -0
  295. proper-0.1.dev4/proper/__pycache__/constants.cpython-39.pyc +0 -0
  296. proper-0.1.dev4/proper/__pycache__/errors.cpython-39.pyc +0 -0
  297. proper-0.1.dev4/proper/__pycache__/local.cpython-39.pyc +0 -0
  298. proper-0.1.dev4/proper/__pycache__/request.cpython-39.pyc +0 -0
  299. proper-0.1.dev4/proper/__pycache__/response.cpython-39.pyc +0 -0
  300. proper-0.1.dev4/proper/__pycache__/static.cpython-39.pyc +0 -0
  301. proper-0.1.dev4/proper/__pycache__/status.cpython-39.pyc +0 -0
  302. proper-0.1.dev4/proper/app/__init__.py +0 -1
  303. proper-0.1.dev4/proper/app/__pycache__/__init__.cpython-39.pyc +0 -0
  304. proper-0.1.dev4/proper/app/__pycache__/app.cpython-39.pyc +0 -0
  305. proper-0.1.dev4/proper/app/__pycache__/cli.cpython-39.pyc +0 -0
  306. proper-0.1.dev4/proper/app/__pycache__/cli_run.cpython-39.pyc +0 -0
  307. proper-0.1.dev4/proper/app/__pycache__/default_config.cpython-39.pyc +0 -0
  308. proper-0.1.dev4/proper/app/__pycache__/error_handlers.cpython-39.pyc +0 -0
  309. proper-0.1.dev4/proper/app/__pycache__/errors_mixin.cpython-39.pyc +0 -0
  310. proper-0.1.dev4/proper/app/__pycache__/setup_mixin.cpython-39.pyc +0 -0
  311. proper-0.1.dev4/proper/app/app.py +0 -99
  312. proper-0.1.dev4/proper/app/cli.py +0 -123
  313. proper-0.1.dev4/proper/app/cli_run.py +0 -52
  314. proper-0.1.dev4/proper/app/default_config.py +0 -37
  315. proper-0.1.dev4/proper/app/error_handlers.py +0 -103
  316. proper-0.1.dev4/proper/app/errors_mixin.py +0 -91
  317. proper-0.1.dev4/proper/app/setup_mixin.py +0 -170
  318. proper-0.1.dev4/proper/app/templates/_context.html.jinja +0 -61
  319. proper-0.1.dev4/proper/app/templates/_debug-styles.css +0 -100
  320. proper-0.1.dev4/proper/app/templates/_prism.css +0 -228
  321. proper-0.1.dev4/proper/app/templates/_prism.js +0 -4
  322. proper-0.1.dev4/proper/app/templates/debug-error.html.jinja +0 -14
  323. proper-0.1.dev4/proper/app/templates/debug-not-found.html.jinja +0 -61
  324. proper-0.1.dev4/proper/app/templates/fallback-error.html +0 -41
  325. proper-0.1.dev4/proper/app/templates/fallback-forbidden.html +0 -54
  326. proper-0.1.dev4/proper/app/templates/fallback-not-found.html +0 -42
  327. proper-0.1.dev4/proper/app/templates/layout.html.jinja +0 -21
  328. proper-0.1.dev4/proper/auth.py +0 -307
  329. proper-0.1.dev4/proper/cli/__init__.py +0 -33
  330. proper-0.1.dev4/proper/cli/__pycache__/__init__.cpython-39.pyc +0 -0
  331. proper-0.1.dev4/proper/cli/__pycache__/welcome.cpython-39.pyc +0 -0
  332. proper-0.1.dev4/proper/cli/welcome.py +0 -44
  333. proper-0.1.dev4/proper/constants.py +0 -12
  334. proper-0.1.dev4/proper/controller/__init__.py +0 -1
  335. proper-0.1.dev4/proper/controller/__pycache__/__init__.cpython-39.pyc +0 -0
  336. proper-0.1.dev4/proper/controller/__pycache__/base_channel.cpython-39.pyc +0 -0
  337. proper-0.1.dev4/proper/controller/__pycache__/base_controller.cpython-39.pyc +0 -0
  338. proper-0.1.dev4/proper/controller/base_channel.py +0 -26
  339. proper-0.1.dev4/proper/controller/base_controller.py +0 -71
  340. proper-0.1.dev4/proper/generators/__pycache__/__init__.cpython-39.pyc +0 -0
  341. proper-0.1.dev4/proper/generators/__pycache__/controller.cpython-39.pyc +0 -0
  342. proper-0.1.dev4/proper/generators/__pycache__/mailer.cpython-39.pyc +0 -0
  343. proper-0.1.dev4/proper/generators/__pycache__/model.cpython-39.pyc +0 -0
  344. proper-0.1.dev4/proper/generators/__pycache__/project.cpython-39.pyc +0 -0
  345. proper-0.1.dev4/proper/generators/__pycache__/resource.cpython-39.pyc +0 -0
  346. proper-0.1.dev4/proper/generators/controller.py +0 -56
  347. proper-0.1.dev4/proper/generators/mailer.py +0 -13
  348. proper-0.1.dev4/proper/generators/model.py +0 -245
  349. proper-0.1.dev4/proper/generators/project.py +0 -92
  350. proper-0.1.dev4/proper/generators/resource.py +0 -81
  351. proper-0.1.dev4/proper/helpers/__init__.py +0 -12
  352. proper-0.1.dev4/proper/helpers/__pycache__/__init__.cpython-39.pyc +0 -0
  353. proper-0.1.dev4/proper/helpers/__pycache__/cookies.cpython-39.pyc +0 -0
  354. proper-0.1.dev4/proper/helpers/__pycache__/digestor.cpython-39.pyc +0 -0
  355. proper-0.1.dev4/proper/helpers/__pycache__/dot.cpython-39.pyc +0 -0
  356. proper-0.1.dev4/proper/helpers/__pycache__/encoding.cpython-39.pyc +0 -0
  357. proper-0.1.dev4/proper/helpers/__pycache__/frozendict.cpython-39.pyc +0 -0
  358. proper-0.1.dev4/proper/helpers/__pycache__/headersdict.cpython-39.pyc +0 -0
  359. proper-0.1.dev4/proper/helpers/__pycache__/iterable.cpython-39.pyc +0 -0
  360. proper-0.1.dev4/proper/helpers/__pycache__/multidict.cpython-39.pyc +0 -0
  361. proper-0.1.dev4/proper/helpers/__pycache__/paginator.cpython-39.pyc +0 -0
  362. proper-0.1.dev4/proper/helpers/__pycache__/render.cpython-39.pyc +0 -0
  363. proper-0.1.dev4/proper/helpers/__pycache__/serializer.cpython-39.pyc +0 -0
  364. proper-0.1.dev4/proper/helpers/__pycache__/slugify.cpython-39.pyc +0 -0
  365. proper-0.1.dev4/proper/helpers/cookies.py +0 -161
  366. proper-0.1.dev4/proper/helpers/digestor.py +0 -28
  367. proper-0.1.dev4/proper/helpers/dot.py +0 -98
  368. proper-0.1.dev4/proper/helpers/encoding.py +0 -25
  369. proper-0.1.dev4/proper/helpers/frozendict.py +0 -56
  370. proper-0.1.dev4/proper/helpers/headersdict.py +0 -13
  371. proper-0.1.dev4/proper/helpers/iterable.py +0 -8
  372. proper-0.1.dev4/proper/helpers/multidict.py +0 -122
  373. proper-0.1.dev4/proper/helpers/paginator.py +0 -338
  374. proper-0.1.dev4/proper/helpers/render.py +0 -216
  375. proper-0.1.dev4/proper/helpers/serializer.py +0 -40
  376. proper-0.1.dev4/proper/helpers/slugify.py +0 -72
  377. proper-0.1.dev4/proper/local.py +0 -63
  378. proper-0.1.dev4/proper/middleware/README.md +0 -7
  379. proper-0.1.dev4/proper/middleware/__init__.py +0 -7
  380. proper-0.1.dev4/proper/middleware/__pycache__/__init__.cpython-39.pyc +0 -0
  381. proper-0.1.dev4/proper/middleware/__pycache__/dispatch.cpython-39.pyc +0 -0
  382. proper-0.1.dev4/proper/middleware/__pycache__/head.cpython-39.pyc +0 -0
  383. proper-0.1.dev4/proper/middleware/__pycache__/match.cpython-39.pyc +0 -0
  384. proper-0.1.dev4/proper/middleware/__pycache__/method_override.cpython-39.pyc +0 -0
  385. proper-0.1.dev4/proper/middleware/__pycache__/protect_from_forgery.cpython-39.pyc +0 -0
  386. proper-0.1.dev4/proper/middleware/__pycache__/redirect.cpython-39.pyc +0 -0
  387. proper-0.1.dev4/proper/middleware/__pycache__/session.cpython-39.pyc +0 -0
  388. proper-0.1.dev4/proper/middleware/dispatch.py +0 -46
  389. proper-0.1.dev4/proper/middleware/head.py +0 -19
  390. proper-0.1.dev4/proper/middleware/match.py +0 -18
  391. proper-0.1.dev4/proper/middleware/method_override.py +0 -30
  392. proper-0.1.dev4/proper/middleware/protect_from_forgery.py +0 -72
  393. proper-0.1.dev4/proper/middleware/redirect.py +0 -18
  394. proper-0.1.dev4/proper/middleware/session.py +0 -64
  395. proper-0.1.dev4/proper/parsers/__init__.py +0 -5
  396. proper-0.1.dev4/proper/parsers/__pycache__/__init__.cpython-39.pyc +0 -0
  397. proper-0.1.dev4/proper/parsers/__pycache__/parse_comma_separated.cpython-39.pyc +0 -0
  398. proper-0.1.dev4/proper/parsers/__pycache__/parse_cookies.cpython-39.pyc +0 -0
  399. proper-0.1.dev4/proper/parsers/__pycache__/parse_form_data.cpython-39.pyc +0 -0
  400. proper-0.1.dev4/proper/parsers/__pycache__/parse_http_date.cpython-39.pyc +0 -0
  401. proper-0.1.dev4/proper/parsers/__pycache__/parse_query_string.cpython-39.pyc +0 -0
  402. proper-0.1.dev4/proper/parsers/parse_comma_separated.py +0 -13
  403. proper-0.1.dev4/proper/parsers/parse_cookies.py +0 -25
  404. proper-0.1.dev4/proper/parsers/parse_form_data.py +0 -125
  405. proper-0.1.dev4/proper/parsers/parse_http_date.py +0 -15
  406. proper-0.1.dev4/proper/parsers/parse_query_string.py +0 -46
  407. proper-0.1.dev4/proper/request.py +0 -384
  408. proper-0.1.dev4/proper/response.py +0 -350
  409. proper-0.1.dev4/proper/router/__init__.py +0 -5
  410. proper-0.1.dev4/proper/router/__pycache__/__init__.cpython-39.pyc +0 -0
  411. proper-0.1.dev4/proper/router/__pycache__/base.cpython-39.pyc +0 -0
  412. proper-0.1.dev4/proper/router/__pycache__/resource.cpython-39.pyc +0 -0
  413. proper-0.1.dev4/proper/router/__pycache__/route.cpython-39.pyc +0 -0
  414. proper-0.1.dev4/proper/router/__pycache__/router.cpython-39.pyc +0 -0
  415. proper-0.1.dev4/proper/router/__pycache__/scope.cpython-39.pyc +0 -0
  416. proper-0.1.dev4/proper/router/base.py +0 -158
  417. proper-0.1.dev4/proper/router/resource.py +0 -118
  418. proper-0.1.dev4/proper/router/route.py +0 -179
  419. proper-0.1.dev4/proper/router/router.py +0 -117
  420. proper-0.1.dev4/proper/router/scope.py +0 -92
  421. proper-0.1.dev4/proper/static.py +0 -149
  422. proper-0.1.dev4/proper/status.py +0 -209
  423. proper-0.1.dev4/proper.egg-info/PKG-INFO +0 -87
  424. proper-0.1.dev4/proper.egg-info/SOURCES.txt +0 -266
  425. proper-0.1.dev4/proper.egg-info/entry_points.txt +0 -3
  426. proper-0.1.dev4/proper.egg-info/requires.txt +0 -27
  427. proper-0.1.dev4/setup.cfg +0 -99
  428. proper-0.1.dev4/setup.py +0 -5
  429. /proper-0.1.dev4/blueprints/project/[[ app_name ]]/mailers/__init__.py → /proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/config/__init__.append.py +0 -0
  430. {proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/forms → proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/auth}/__init__.py +0 -0
  431. {proper-0.1.dev4/blueprints/project/[[ app_name ]]/services → proper-0.9.0/src/proper/cli}/__init__.py +0 -0
  432. /proper-0.1.dev4/blueprints/project/.well-known/.keep → /proper-0.9.0/src/proper/install/__init__.py +0 -0
  433. {proper-0.1.dev4 → proper-0.9.0/src}/proper.egg-info/dependency_links.txt +0 -0
  434. {proper-0.1.dev4 → proper-0.9.0/src}/proper.egg-info/top_level.txt +0 -0
proper-0.9.0/PKG-INFO ADDED
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: proper
3
+ Version: 0.9.0
4
+ Summary: A python web framework for people who read their code
5
+ Author-email: Juan Pablo Scaletti <juanpablo@jpscaletti.com>
6
+ License-Expression: MIT
7
+ Project-URL: homepage, https://ProperProject.org/
8
+ Project-URL: repository, https://github.com/jpsca/proper
9
+ Project-URL: documentation, https://properproject.org/docs/
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Web Environment
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Typing :: Typed
17
+ Requires-Python: >=3.13
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: babel>=2.17.0
20
+ Requires-Dist: formidable>=0.19
21
+ Requires-Dist: hecto>=2.0.3
22
+ Requires-Dist: huey~=2.5.2
23
+ Requires-Dist: inflection>=0.5.1
24
+ Requires-Dist: isort~=5.0
25
+ Requires-Dist: itsdangerous~=1.1
26
+ Requires-Dist: jx>=0.11.0
27
+ Requires-Dist: markupsafe>=2.0
28
+ Requires-Dist: passlib~=1.7
29
+ Requires-Dist: peewee~=3.15
30
+ Requires-Dist: peewee-migrate<2,>=1.12.1
31
+ Requires-Dist: proper-cli~=1.2
32
+ Requires-Dist: python-dateutil~=2.9.0
33
+ Requires-Dist: python-multipart>=0.0.22
34
+ Requires-Dist: traceback-with-variables~=2.0.4
35
+ Requires-Dist: types-peewee~=3.17.7.20241017
36
+ Requires-Dist: uvicorn>=0.41.0
37
+ Requires-Dist: tzdata>=2025.3
38
+
39
+ <h1><img src="https://properproject.org/proper.svg" height="48" />
40
+ Proper Web Framework</h1>
41
+
42
+ Proper is a new Python web framework. Not another Flask clone, it's a Ruby-on-Rails clone :P.
43
+
44
+ More seriously: it isn't a clone, but it is heavily influenced by Rails in the ways that matter. Very opinionated, generator-heavy, focused on REST and server-rendered HTML, built around a fixed project structure, and packed with hardcoded batteries. You *can* swap pieces if you must, but the assumption is that you won't.
45
+
46
+ The one thing Proper does very differently: **sync above, async below**. The runtime is ASGI (you need it for performance and WebSockets), but the code you write is _synchronous_. No `async`/`await` confetti scattered across code that doesn't need concurrency.
47
+
48
+
49
+ ## Quick start
50
+
51
+ Requires [uv](https://docs.astral.sh/uv/getting-started/installation/).
52
+
53
+ ```bash
54
+ uvx proper_new myapp
55
+ cd myapp
56
+ proper g resource Post title:str body:text
57
+ proper server
58
+ ```
59
+
60
+ That's a working CRUD app with model, controller, views, routes, migrations, and tests.
61
+
62
+ Full (human-shaped) docs at [properproject.org/docs](https://properproject.org/docs).
63
+
64
+
65
+ ## Why not X?
66
+
67
+ **Why not Flask?** - Absolute freedom means absolute chaos.
68
+
69
+ **Why not Django?** - Django gives you the pieces and expects you to assemble them; Proper assembles them and gives you direction.
70
+
71
+ **Why not FastAPI?** - FastAPI is awesome, but has the opposite shape: It's all about APIs and async-first, while Proper is server-rendered and sync-first. Building a React SPA on top of a JSON backend? You might want to use it. Building HTML for humans? Try Proper.
72
+
73
+ **Why Peewee instead of SQLAlchemy?** - Smaller surface area, more readable, and ActiveRecord-style scopes fit it cleanly. SQLAlchemy is excellent but not something I want to read every day.
74
+
75
+ **Why Jx instead of Jinja?** - Server-rendered Python components with typed props and slots. See the [Jx docs](https://properproject.org/docs/jx_components/) for the case.
76
+
77
+
78
+ ## Built with AI agents in mind
79
+
80
+ Proper ships with an official skill: [properproject.org/skill.zip](https://properproject.org/skill.zip). Drop it in `~/.claude/skills/` and your agent will scaffold and edit your app the _Proper_ way (pun intended).
81
+
82
+ This isn't just an extra. Hard conventions are exactly what makes AI output legible to humans: fewer tokens to understand a project, fewer surprises in generated code, and less effort reviewing it.
83
+
84
+
85
+ ## What's in the box
86
+
87
+ - **Peewee ORM** with migrations, query helpers, and connection handling
88
+ - **Forms** — declarative, validated, ORM-integrated, with rendering helpers
89
+ - **Jx components** — server-rendered Python components, typed props, slots
90
+ - **Caching** — fragment, action, and low-level, on SQLite or Redis
91
+ - **Background tasks** via Huey, with retries, schedules, and cron syntax
92
+ - **Authentication** — sessions, password resets, rate limiting, pwned-password checks
93
+ - **File storage** — disk and S3 adapters, signed URLs, image variants
94
+ - **i18n** — locale-aware routing, translations, pluralization, date formats
95
+ - **Email** — templated transactional mail, SMTP and console mailers
96
+ - **WebSockets** — channels, broadcasts, presence
97
+
98
+
99
+ ## For the press release
100
+
101
+ > Proper is the Python web framework I built for myself after fifteen years in the trade, once I understood that hard conventions do not lock you in — they free you to focus on what's important.
102
+
103
+ (It also works for the back cover of my future biography by Walter Isaacson).
104
+
105
+
106
+ ## Status
107
+
108
+ This is 0.9, I'll call it 1.0 when I've found more bugs. Bug reports and contributions are very welcome. File them at [github.com/jpsca/proper/issues](https://github.com/jpsca/proper/issues).
109
+
110
+
111
+ ## Community
112
+
113
+ - [Discord](https://discord.gg/aWVP3F4abD)
114
+
115
+
116
+ ## License
117
+
118
+ Code: [MIT](https://github.com/jpsca/proper/blob/main/MIT-LICENSE). Documentation: [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
119
+
120
+ Made by [Juan-Pablo Scaletti](https://github.com/jpsca) in Lima, Perú.
proper-0.9.0/README.md ADDED
@@ -0,0 +1,82 @@
1
+ <h1><img src="https://properproject.org/proper.svg" height="48" />
2
+ Proper Web Framework</h1>
3
+
4
+ Proper is a new Python web framework. Not another Flask clone, it's a Ruby-on-Rails clone :P.
5
+
6
+ More seriously: it isn't a clone, but it is heavily influenced by Rails in the ways that matter. Very opinionated, generator-heavy, focused on REST and server-rendered HTML, built around a fixed project structure, and packed with hardcoded batteries. You *can* swap pieces if you must, but the assumption is that you won't.
7
+
8
+ The one thing Proper does very differently: **sync above, async below**. The runtime is ASGI (you need it for performance and WebSockets), but the code you write is _synchronous_. No `async`/`await` confetti scattered across code that doesn't need concurrency.
9
+
10
+
11
+ ## Quick start
12
+
13
+ Requires [uv](https://docs.astral.sh/uv/getting-started/installation/).
14
+
15
+ ```bash
16
+ uvx proper_new myapp
17
+ cd myapp
18
+ proper g resource Post title:str body:text
19
+ proper server
20
+ ```
21
+
22
+ That's a working CRUD app with model, controller, views, routes, migrations, and tests.
23
+
24
+ Full (human-shaped) docs at [properproject.org/docs](https://properproject.org/docs).
25
+
26
+
27
+ ## Why not X?
28
+
29
+ **Why not Flask?** - Absolute freedom means absolute chaos.
30
+
31
+ **Why not Django?** - Django gives you the pieces and expects you to assemble them; Proper assembles them and gives you direction.
32
+
33
+ **Why not FastAPI?** - FastAPI is awesome, but has the opposite shape: It's all about APIs and async-first, while Proper is server-rendered and sync-first. Building a React SPA on top of a JSON backend? You might want to use it. Building HTML for humans? Try Proper.
34
+
35
+ **Why Peewee instead of SQLAlchemy?** - Smaller surface area, more readable, and ActiveRecord-style scopes fit it cleanly. SQLAlchemy is excellent but not something I want to read every day.
36
+
37
+ **Why Jx instead of Jinja?** - Server-rendered Python components with typed props and slots. See the [Jx docs](https://properproject.org/docs/jx_components/) for the case.
38
+
39
+
40
+ ## Built with AI agents in mind
41
+
42
+ Proper ships with an official skill: [properproject.org/skill.zip](https://properproject.org/skill.zip). Drop it in `~/.claude/skills/` and your agent will scaffold and edit your app the _Proper_ way (pun intended).
43
+
44
+ This isn't just an extra. Hard conventions are exactly what makes AI output legible to humans: fewer tokens to understand a project, fewer surprises in generated code, and less effort reviewing it.
45
+
46
+
47
+ ## What's in the box
48
+
49
+ - **Peewee ORM** with migrations, query helpers, and connection handling
50
+ - **Forms** — declarative, validated, ORM-integrated, with rendering helpers
51
+ - **Jx components** — server-rendered Python components, typed props, slots
52
+ - **Caching** — fragment, action, and low-level, on SQLite or Redis
53
+ - **Background tasks** via Huey, with retries, schedules, and cron syntax
54
+ - **Authentication** — sessions, password resets, rate limiting, pwned-password checks
55
+ - **File storage** — disk and S3 adapters, signed URLs, image variants
56
+ - **i18n** — locale-aware routing, translations, pluralization, date formats
57
+ - **Email** — templated transactional mail, SMTP and console mailers
58
+ - **WebSockets** — channels, broadcasts, presence
59
+
60
+
61
+ ## For the press release
62
+
63
+ > Proper is the Python web framework I built for myself after fifteen years in the trade, once I understood that hard conventions do not lock you in — they free you to focus on what's important.
64
+
65
+ (It also works for the back cover of my future biography by Walter Isaacson).
66
+
67
+
68
+ ## Status
69
+
70
+ This is 0.9, I'll call it 1.0 when I've found more bugs. Bug reports and contributions are very welcome. File them at [github.com/jpsca/proper/issues](https://github.com/jpsca/proper/issues).
71
+
72
+
73
+ ## Community
74
+
75
+ - [Discord](https://discord.gg/aWVP3F4abD)
76
+
77
+
78
+ ## License
79
+
80
+ Code: [MIT](https://github.com/jpsca/proper/blob/main/MIT-LICENSE). Documentation: [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
81
+
82
+ Made by [Juan-Pablo Scaletti](https://github.com/jpsca) in Lima, Perú.
@@ -0,0 +1,240 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+
4
+
5
+ [project]
6
+ name = "proper"
7
+ version = "0.9.0"
8
+ description = "A python web framework for people who read their code"
9
+ authors = [
10
+ {name = "Juan Pablo Scaletti", email = "juanpablo@jpscaletti.com"},
11
+ ]
12
+ license = "MIT"
13
+ readme = "README.md"
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: Web Environment",
17
+ "Intended Audience :: Developers",
18
+ "Programming Language :: Python :: 3 :: Only",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Programming Language :: Python :: 3.14",
21
+ "Typing :: Typed",
22
+ ]
23
+ requires-python = ">=3.13"
24
+ dependencies = [
25
+ "babel >= 2.17.0",
26
+ "formidable>=0.19",
27
+ "hecto >= 2.0.3",
28
+ "huey ~= 2.5.2",
29
+ "inflection >= 0.5.1",
30
+ "isort ~= 5.0",
31
+ "itsdangerous ~= 1.1",
32
+ "jx>=0.11.0",
33
+ "markupsafe >= 2.0",
34
+ "passlib ~= 1.7",
35
+ "peewee ~= 3.15",
36
+ "peewee-migrate >=1.12.1,< 2",
37
+ "proper-cli ~= 1.2",
38
+ "python-dateutil ~= 2.9.0",
39
+ "python-multipart >= 0.0.22",
40
+ "traceback-with-variables ~= 2.0.4",
41
+ "types-peewee ~= 3.17.7.20241017",
42
+ "uvicorn >= 0.41.0",
43
+ "tzdata >= 2025.3",
44
+ ]
45
+
46
+ [project.urls]
47
+ homepage = "https://ProperProject.org/"
48
+ repository = "https://github.com/jpsca/proper"
49
+ documentation = "https://properproject.org/docs/"
50
+
51
+
52
+ [dependency-groups]
53
+ dev = [
54
+ "ipdb >= 0.13",
55
+ "pre-commit",
56
+ "pytest-asyncio>=1.3.0",
57
+ "ruff >= 0.2.0",
58
+ "tox-uv>=1.33.1",
59
+ "ty>=0.0.1a24",
60
+ ]
61
+ test = [
62
+ "pytest >= 7.2",
63
+ "pytest-cov",
64
+ # To test installable frameworks
65
+ "boto3 >= 1.35.71",
66
+ "poyo",
67
+ "pytest-smtpd",
68
+ "pyvips >= 2.0.0",
69
+ "redis >= 7.0.0",
70
+ "smtpdfix",
71
+ ]
72
+ docs = [
73
+ "writeadoc>=0.22.0",
74
+ ]
75
+
76
+ # [tool.uv.sources]
77
+ # writeadoc = { path = "../../writeadoc", editable = true }
78
+
79
+
80
+ [tool.setuptools.packages.find]
81
+ where = ["src"]
82
+
83
+ [tool.setuptools.package-data]
84
+ proper = [
85
+ "blueprints",
86
+ "core/templates",
87
+ ]
88
+ [tool.setuptools.exclude-package-data]
89
+ "*" = [
90
+ "**/__pycache__",
91
+ "*.pyc",
92
+ "*.pyo",
93
+ ]
94
+
95
+ [tool.coverage.run]
96
+ branch = true
97
+
98
+ [tool.coverage.report]
99
+ exclude_lines = [
100
+ "pragma: no cover",
101
+ "TYPE_CHECKING",
102
+ "def __repr__",
103
+ "def __str__",
104
+ "raise AssertionError",
105
+ "raise NotImplementedError",
106
+ "if __name__ == .__main__.:",
107
+ "except ImportError:",
108
+ ]
109
+ omit = [
110
+ "src/proper/blueprints/*",
111
+ "src/proper/app_test.py",
112
+ "src/proper/cli/*",
113
+ "src/proper/helpers/server.py",
114
+ ]
115
+
116
+ [tool.coverage.html]
117
+ directory = "covreport"
118
+
119
+
120
+ [tool.ty.src]
121
+ exclude = [
122
+ "**/__pycache__",
123
+ "**/tests/",
124
+ "blueprint",
125
+ "build",
126
+ "docs",
127
+ "src/proper/mail/",
128
+ "src/proper/blueprints/",
129
+ ]
130
+
131
+
132
+ [tool.pytest.ini_options]
133
+ asyncio_mode = "auto"
134
+ asyncio_default_fixture_loop_scope = "function"
135
+ addopts = "--doctest-modules --ignore=src/proper/blueprints"
136
+ filterwarnings = [
137
+ "ignore::DeprecationWarning:itsdangerous",
138
+ "ignore::DeprecationWarning:botocore",
139
+ ]
140
+
141
+
142
+ [tool.tox]
143
+ legacy_tox_ini = """
144
+ [tox]
145
+ env_list =
146
+ 3.13
147
+ 3.14
148
+
149
+ [testenv]
150
+ runner = uv-venv-lock-runner
151
+ dependency_groups =
152
+ dev
153
+ test
154
+ commands =
155
+ pytest -x src/proper tests
156
+ """
157
+
158
+ [tool.ruff]
159
+ line-length = 90
160
+ indent-width = 4
161
+ target-version = "py313"
162
+ exclude = [
163
+ ".*",
164
+ "_build",
165
+ "build",
166
+ "covreport",
167
+ "dist",
168
+ "blueprint",
169
+ "src/proper/blueprints/*",
170
+ ]
171
+ include = ["*.py"]
172
+
173
+ [tool.ruff.format]
174
+ # Like Black, use double quotes for strings.
175
+ quote-style = "double"
176
+
177
+ # Like Black, indent with spaces, rather than tabs.
178
+ indent-style = "space"
179
+
180
+ # Like Black, respect magic trailing commas.
181
+ skip-magic-trailing-comma = false
182
+
183
+ # Like Black, automatically detect the appropriate line ending.
184
+ line-ending = "auto"
185
+
186
+ # Enable auto-formatting of code examples in docstrings. Markdown,
187
+ # reStructuredText code/literal blocks and doctests are all supported.
188
+ #
189
+ # This is currently disabled by default, but it is planned for this
190
+ # to be opt-out in the future.
191
+ docstring-code-format = false
192
+
193
+ # Set the line length limit used when formatting code snippets in
194
+ # docstrings.
195
+ #
196
+ # This only has an effect when the `docstring-code-format` setting is
197
+ # enabled.
198
+ docstring-code-line-length = "dynamic"
199
+
200
+ [tool.ruff.lint]
201
+ fixable = ["ALL"]
202
+
203
+ ignore = [
204
+ # x is too complex
205
+ "C901",
206
+ # whitespace before ':'
207
+ "E203",
208
+ "E501",
209
+ # x defined from star imports
210
+ "F405",
211
+ # line break before binary operator
212
+ "W505",
213
+ "W605",
214
+ ]
215
+ select = [
216
+ # bugbear
217
+ "B",
218
+ # mccabe"", comprehensions, commas
219
+ "C",
220
+ # pycodestyle errors
221
+ "E",
222
+ # pyflakes
223
+ "F",
224
+ # logging format
225
+ "G",
226
+ # imports
227
+ "I",
228
+ # quotes
229
+ "Q",
230
+ # pycodestyle warnings
231
+ "W",
232
+ ]
233
+
234
+ [tool.ruff.lint.isort]
235
+ known-first-party = ["proper"]
236
+ known-local-folder = ["src/proper"]
237
+ no-lines-before = ["local-folder"]
238
+ relative-imports-order = "furthest-to-closest"
239
+ # Use two line after imports.
240
+ lines-after-imports = 2
proper-0.9.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,44 @@
1
+ from . import (
2
+ auth, # noqa
3
+ cache, # noqa
4
+ concerns, # noqa
5
+ constants, # noqa
6
+ errors, # noqa
7
+ forms, # noqa
8
+ helpers, # noqa
9
+ router, # noqa
10
+ status, # noqa
11
+ types, # noqa
12
+ units, # noqa
13
+ )
14
+ from .app import App # noqa
15
+ from .channel import Channel # noqa
16
+ from .concerns.concern import Concern # noqa
17
+ from .controller import Controller # noqa
18
+ from .emails import ( # noqa
19
+ BaseMailer,
20
+ EmailAlternative,
21
+ EmailAttachment,
22
+ EmailMessage,
23
+ EmailMessageDict,
24
+ SMTPMailer,
25
+ ToConsoleMailer,
26
+ ToMemoryMailer,
27
+ )
28
+ from .global_context import current # noqa
29
+ from .helpers import ( # noqa
30
+ DotDict,
31
+ JSONField,
32
+ MultiDict,
33
+ Undefined,
34
+ import_string,
35
+ make_list,
36
+ secure_filename,
37
+ show_banner,
38
+ show_welcome,
39
+ )
40
+ from .models import ProperModel, scope # noqa
41
+ from .request import Request # noqa
42
+ from .response import Response # noqa
43
+ from .router import Route, Router, ScopedRouter, StaticRoute # noqa
44
+ from .test_client import TestClient # noqa