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.
- proper-0.9.0/PKG-INFO +120 -0
- proper-0.9.0/README.md +82 -0
- proper-0.9.0/pyproject.toml +240 -0
- proper-0.9.0/setup.cfg +4 -0
- proper-0.9.0/src/proper/__init__.py +44 -0
- proper-0.9.0/src/proper/app.py +537 -0
- proper-0.9.0/src/proper/app_ws.py +221 -0
- proper-0.9.0/src/proper/auth.py +217 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/cli/__init__.prepend.py +1 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/cli/auth_cli.tt.py +57 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/config/auth.py +9 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/__init__.append.py +5 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/app_controller.prepend.py +1 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/concerns/authentication.tt.py +79 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/password_reset_controller.tt.py +77 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/session_controller.tt.py +53 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/controllers/sign_up_controller.tt.py +37 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/emails/__init__.append.py +1 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/emails/password_reset_email.py +12 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/auth/pwned.py +127 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/auth/validators.tt.py +59 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/password_reset.py +46 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/session.tt.py +36 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/forms/sign_up.py +34 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/main.append.py +1 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/models/__init__.append.py +2 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/models/concerns/authenticable.py +102 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/models/session.py +101 -0
- proper-0.9.0/src/proper/blueprints/auth/[[app_name]]/models/user.py +8 -0
- proper-0.9.0/src/proper/blueprints/channels/[[app_name]]/config/__init__.append.py +1 -0
- proper-0.9.0/src/proper/blueprints/channels/[[app_name]]/config/channels.tt.py +13 -0
- proper-0.9.0/src/proper/blueprints/controller/[[app_name]]/controllers/[[name_snake]]_controller.tt.py +101 -0
- proper-0.9.0/src/proper/blueprints/controller/[[app_name]]/controllers/__init__.append.py +1 -0
- proper-0.9.0/src/proper/blueprints/controller/[[app_name]]/forms/[[name_snake]].tt.py +12 -0
- proper-0.9.0/src/proper/blueprints/controller/[[app_name]]/router.append.py +3 -0
- proper-0.9.0/src/proper/blueprints/controller/tests/pages/test_[[name_snake]].tt.py +70 -0
- proper-0.9.0/src/proper/blueprints/email/[[app_name]]/emails/[[name_snake]]_email.tt.py +8 -0
- proper-0.9.0/src/proper/blueprints/email/[[app_name]]/emails/__init__.append.py +1 -0
- proper-0.9.0/src/proper/blueprints/i18n/[[app_name]]/controllers/app_controller.prepend.py +1 -0
- proper-0.9.0/src/proper/blueprints/model/[[app_name]]/models/[[name_snake]].tt.py +9 -0
- proper-0.9.0/src/proper/blueprints/model/[[app_name]]/models/__init__.append.py +1 -0
- proper-0.9.0/src/proper/blueprints/storage/[[app_name]]/config/storage.append.py +59 -0
- proper-0.9.0/src/proper/blueprints/storage/[[app_name]]/controllers/__init__.append.py +2 -0
- proper-0.9.0/src/proper/blueprints/storage/[[app_name]]/controllers/storage_controller.tt.py +29 -0
- proper-0.9.0/src/proper/blueprints/storage/[[app_name]]/models/__init__.append.py +1 -0
- proper-0.9.0/src/proper/blueprints/storage/[[app_name]]/models/attachment.py +9 -0
- proper-0.9.0/src/proper/cable.py +197 -0
- proper-0.9.0/src/proper/cache/__init__.py +5 -0
- proper-0.9.0/src/proper/cache/base.py +126 -0
- proper-0.9.0/src/proper/cache/jinja_ext.py +75 -0
- proper-0.9.0/src/proper/cache/keys.py +76 -0
- proper-0.9.0/src/proper/cache/redis_cache.py +120 -0
- proper-0.9.0/src/proper/cache/sqlite_cache.py +204 -0
- proper-0.9.0/src/proper/channel.py +87 -0
- proper-0.9.0/src/proper/cli/app_cli.py +152 -0
- proper-0.9.0/src/proper/cli/db_cli.py +291 -0
- proper-0.9.0/src/proper/concerns/__init__.py +5 -0
- proper-0.9.0/src/proper/concerns/concern.py +13 -0
- proper-0.9.0/src/proper/concerns/current_locale.py +38 -0
- proper-0.9.0/src/proper/concerns/current_timezone.py +34 -0
- proper-0.9.0/src/proper/concerns/origin_protection.py +83 -0
- proper-0.9.0/src/proper/concerns/rate_limiting.py +175 -0
- proper-0.9.0/src/proper/concerns/request_forgery_protection.py +123 -0
- proper-0.9.0/src/proper/config.py +121 -0
- proper-0.9.0/src/proper/constants.py +14 -0
- proper-0.9.0/src/proper/controller.py +258 -0
- proper-0.9.0/src/proper/emails/__init__.py +5 -0
- {proper-0.1.dev4/blueprints/project/db/migrations → proper-0.9.0/src/proper/emails/mailers}/__init__.py +0 -0
- proper-0.9.0/src/proper/emails/mailers/base.py +221 -0
- proper-0.9.0/src/proper/emails/mailers/console.py +49 -0
- proper-0.9.0/src/proper/emails/mailers/memory.py +25 -0
- proper-0.9.0/src/proper/emails/mailers/smtp.py +204 -0
- proper-0.9.0/src/proper/emails/message.py +207 -0
- proper-0.9.0/src/proper/emails/utils.py +81 -0
- proper-0.9.0/src/proper/error_handlers.py +142 -0
- {proper-0.1.dev4 → proper-0.9.0/src}/proper/errors.py +164 -37
- proper-0.9.0/src/proper/forms.py +269 -0
- {proper-0.1.dev4 → proper-0.9.0/src}/proper/generators/__init__.py +2 -1
- proper-0.9.0/src/proper/generators/controller.py +221 -0
- proper-0.9.0/src/proper/generators/email.py +41 -0
- proper-0.9.0/src/proper/generators/model.py +213 -0
- proper-0.9.0/src/proper/generators/resource.py +61 -0
- proper-0.9.0/src/proper/generators/seed.py +83 -0
- proper-0.9.0/src/proper/global_context.py +44 -0
- proper-0.9.0/src/proper/helpers/__init__.py +43 -0
- proper-0.9.0/src/proper/helpers/dotdict.py +71 -0
- proper-0.9.0/src/proper/helpers/html2text.py +183 -0
- proper-0.9.0/src/proper/helpers/http.py +36 -0
- proper-0.9.0/src/proper/helpers/imports.py +211 -0
- proper-0.9.0/src/proper/helpers/json_field.py +26 -0
- proper-0.9.0/src/proper/helpers/jsonplus.py +154 -0
- proper-0.9.0/src/proper/helpers/multidict.py +170 -0
- proper-0.9.0/src/proper/helpers/render.py +122 -0
- proper-0.9.0/src/proper/helpers/server.py +70 -0
- proper-0.9.0/src/proper/i18n/__init__.py +1 -0
- proper-0.9.0/src/proper/i18n/format_size.py +103 -0
- proper-0.9.0/src/proper/i18n/formatters.py +1098 -0
- proper-0.9.0/src/proper/i18n/i18n.py +330 -0
- proper-0.9.0/src/proper/i18n/reader.py +82 -0
- proper-0.9.0/src/proper/install/auth.py +51 -0
- proper-0.9.0/src/proper/install/channels.py +27 -0
- proper-0.9.0/src/proper/install/i18n.py +45 -0
- proper-0.9.0/src/proper/install/storage.py +40 -0
- proper-0.9.0/src/proper/models.py +216 -0
- proper-0.9.0/src/proper/pipeline.py +166 -0
- proper-0.9.0/src/proper/request/__init__.py +2 -0
- proper-0.9.0/src/proper/request/formparser.py +417 -0
- proper-0.9.0/src/proper/request/forwarded.py +120 -0
- proper-0.9.0/src/proper/request/headers.py +526 -0
- proper-0.9.0/src/proper/request/request.py +252 -0
- proper-0.9.0/src/proper/request/utils.py +68 -0
- proper-0.9.0/src/proper/response/__init__.py +3 -0
- proper-0.9.0/src/proper/response/cookies.py +214 -0
- proper-0.9.0/src/proper/response/file_wrapper.py +55 -0
- proper-0.9.0/src/proper/response/flash_messages.py +34 -0
- proper-0.9.0/src/proper/response/headers.py +632 -0
- proper-0.9.0/src/proper/response/response.py +295 -0
- proper-0.9.0/src/proper/router/__init__.py +2 -0
- proper-0.9.0/src/proper/router/route.py +466 -0
- proper-0.9.0/src/proper/router/router.py +783 -0
- proper-0.9.0/src/proper/seeds.py +110 -0
- proper-0.9.0/src/proper/status.py +205 -0
- proper-0.9.0/src/proper/storage/__init__.py +2 -0
- proper-0.9.0/src/proper/storage/attachment.py +360 -0
- proper-0.9.0/src/proper/storage/imageops.py +429 -0
- proper-0.9.0/src/proper/storage/services/__init__.py +3 -0
- proper-0.9.0/src/proper/storage/services/disk.py +66 -0
- proper-0.9.0/src/proper/storage/services/s3.py +74 -0
- proper-0.9.0/src/proper/storage/services/service.py +28 -0
- proper-0.9.0/src/proper/template_resolver.py +73 -0
- proper-0.9.0/src/proper/test_client.py +450 -0
- proper-0.9.0/src/proper/tools/__init__.py +11 -0
- proper-0.9.0/src/proper/tools/auth.py +54 -0
- proper-0.9.0/src/proper/tools/cable.py +28 -0
- proper-0.9.0/src/proper/tools/cache.py +30 -0
- proper-0.9.0/src/proper/tools/catalog.py +43 -0
- proper-0.9.0/src/proper/tools/db.py +49 -0
- proper-0.9.0/src/proper/tools/i18n.py +38 -0
- proper-0.9.0/src/proper/tools/mailer.py +26 -0
- proper-0.9.0/src/proper/tools/queue.py +82 -0
- proper-0.9.0/src/proper/tools/storage.py +45 -0
- proper-0.9.0/src/proper/types.py +116 -0
- proper-0.9.0/src/proper/units.py +50 -0
- proper-0.9.0/src/proper.egg-info/PKG-INFO +120 -0
- proper-0.9.0/src/proper.egg-info/SOURCES.txt +174 -0
- proper-0.9.0/src/proper.egg-info/requires.txt +19 -0
- proper-0.9.0/tests/test_app.py +176 -0
- proper-0.9.0/tests/test_auth.py +328 -0
- proper-0.9.0/tests/test_cable.py +227 -0
- proper-0.9.0/tests/test_cable_redis.py +406 -0
- proper-0.9.0/tests/test_cache.py +693 -0
- proper-0.9.0/tests/test_cache_redis.py +240 -0
- proper-0.9.0/tests/test_channel.py +217 -0
- proper-0.9.0/tests/test_controller.py +796 -0
- proper-0.9.0/tests/test_error_handlers.py +278 -0
- proper-0.9.0/tests/test_error_handling.py +553 -0
- proper-0.9.0/tests/test_forms.py +251 -0
- proper-0.9.0/tests/test_i18n.py +487 -0
- proper-0.9.0/tests/test_pipeline.py +482 -0
- proper-0.9.0/tests/test_request.py +1251 -0
- proper-0.9.0/tests/test_response.py +1221 -0
- proper-0.9.0/tests/test_route.py +658 -0
- proper-0.9.0/tests/test_router.py +1358 -0
- proper-0.9.0/tests/test_scoped_model.py +282 -0
- proper-0.9.0/tests/test_seeds.py +214 -0
- proper-0.9.0/tests/test_template_resolver.py +123 -0
- proper-0.9.0/tests/test_timestamped.py +159 -0
- proper-0.9.0/tests/test_token.py +237 -0
- proper-0.9.0/tests/test_tools.py +510 -0
- proper-0.9.0/tests/test_websocket.py +471 -0
- proper-0.1.dev4/MANIFEST.in +0 -4
- proper-0.1.dev4/MIT-LICENSE +0 -20
- proper-0.1.dev4/PKG-INFO +0 -87
- proper-0.1.dev4/README.md +0 -68
- proper-0.1.dev4/blueprints/.DS_Store +0 -0
- proper-0.1.dev4/blueprints/controller/[[ app_name ]]/controllers/[[ snake_name ]].tmpl.py +0 -9
- proper-0.1.dev4/blueprints/controller/[[ app_name ]]/controllers/__init__.append.py +0 -1
- proper-0.1.dev4/blueprints/controller/routes.tmpl.py +0 -5
- proper-0.1.dev4/blueprints/controller/template.tmpl.html.jinja +0 -6
- proper-0.1.dev4/blueprints/model/[[ app_name ]]/models/[[ snake_name ]].tmpl.py +0 -11
- proper-0.1.dev4/blueprints/model/[[ app_name ]]/models/__init__.append.py +0 -1
- proper-0.1.dev4/blueprints/project/.DS_Store +0 -0
- proper-0.1.dev4/blueprints/project/Dockerfile.tmpl +0 -15
- proper-0.1.dev4/blueprints/project/Makefile.tmpl +0 -32
- proper-0.1.dev4/blueprints/project/README.tmpl.md +0 -36
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/.DS_Store +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/__init__.py +0 -1
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/app.tmpl.py +0 -14
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__init__.py +0 -37
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/development.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/production.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/shared.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/staging.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/__pycache__/testing.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/development.tmpl.py +0 -12
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/production.py +0 -10
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/shared.tmpl.py +0 -27
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/staging.py +0 -4
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/config/testing.tmpl.py +0 -10
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/.DS_Store +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/__init__.py +0 -4
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/application.py +0 -81
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/auth.py +0 -85
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/forms/auth.tmpl.py +0 -63
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/forms/pwned.py +0 -35
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/controllers/pages.py +0 -12
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/mailers/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/mailers/__pycache__/auth.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/mailers/auth.py +0 -28
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/main.py +0 -28
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__init__.py +0 -4
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/base.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/post.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/relation.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/topic.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/__pycache__/user.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/base.py +0 -25
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/__init__.py +0 -2
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/__pycache__/authenticable.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/__pycache__/timestamped.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/authenticable.tmpl.py +0 -47
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/mixins/timestamped.py +0 -19
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/models/user.py +0 -8
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/routes.py +0 -34
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/services/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/services/__pycache__/auth_services.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/services/__pycache__/posts_services.cpython-39.pyc +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/services/auth_services.py +0 -64
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/.DS_Store +0 -0
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/auth/password_change.html.jinja +0 -51
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/auth/reset.html.jinja +0 -41
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/auth/reset_invalid.html.jinja +0 -17
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/auth/reset_sent.html.jinja +0 -20
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/auth/sign_in.html.jinja +0 -56
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/common/Button.html.jinja +0 -9
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/emails/password_reset.html.jinja +0 -14
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/layouts/application.html.jinja +0 -17
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/layouts/auth.html.jinja +0 -19
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/layouts/email.html.jinja +0 -12
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/pages/error.html.jinja +0 -22
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/pages/index.html.jinja +0 -5
- proper-0.1.dev4/blueprints/project/[[ app_name ]]/templates/pages/not_found.html.jinja +0 -24
- proper-0.1.dev4/blueprints/project/db/.DS_Store +0 -0
- proper-0.1.dev4/blueprints/project/db/migrations/script.py.mako +0 -24
- proper-0.1.dev4/blueprints/project/deploy/nginx.tmpl.conf +0 -46
- proper-0.1.dev4/blueprints/project/deploy/uwsgi.tmpl.ini +0 -23
- proper-0.1.dev4/blueprints/project/docker-compose.tmpl.yml +0 -22
- proper-0.1.dev4/blueprints/project/logs/.keep +0 -0
- proper-0.1.dev4/blueprints/project/manage.tmpl.py +0 -43
- proper-0.1.dev4/blueprints/project/requirements/dev-requirements.ini +0 -3
- proper-0.1.dev4/blueprints/project/requirements/prod-requirements.ini +0 -2
- proper-0.1.dev4/blueprints/project/requirements/requirements.ini +0 -8
- proper-0.1.dev4/blueprints/project/requirements/test-requirements.ini +0 -6
- proper-0.1.dev4/blueprints/project/setup.py +0 -1
- proper-0.1.dev4/blueprints/project/setup.tmpl.cfg +0 -47
- proper-0.1.dev4/blueprints/project/static/.DS_Store +0 -0
- proper-0.1.dev4/blueprints/project/static/.eslintrc.js +0 -38
- proper-0.1.dev4/blueprints/project/static/package.json +0 -26
- proper-0.1.dev4/blueprints/project/static/postcss.config.js +0 -12
- proper-0.1.dev4/blueprints/project/static/public/css/.keep +0 -0
- proper-0.1.dev4/blueprints/project/static/public/favicon.ico +0 -0
- proper-0.1.dev4/blueprints/project/static/public/fonts/.keep +0 -0
- proper-0.1.dev4/blueprints/project/static/public/humans.txt +0 -0
- proper-0.1.dev4/blueprints/project/static/public/images/.keep +0 -0
- proper-0.1.dev4/blueprints/project/static/public/js/.keep +0 -0
- proper-0.1.dev4/blueprints/project/static/public/robots.txt +0 -2
- proper-0.1.dev4/blueprints/project/static/public/vendor/.keep +0 -0
- proper-0.1.dev4/blueprints/project/static/src/css/_base.css +0 -4
- proper-0.1.dev4/blueprints/project/static/src/css/_buttons.css +0 -74
- proper-0.1.dev4/blueprints/project/static/src/css/_components.css +0 -12
- proper-0.1.dev4/blueprints/project/static/src/css/_forms.css +0 -100
- proper-0.1.dev4/blueprints/project/static/src/css/_utilities.css +0 -2
- proper-0.1.dev4/blueprints/project/static/src/css/email.css +0 -3
- proper-0.1.dev4/blueprints/project/static/src/css/styles.css +0 -3
- proper-0.1.dev4/blueprints/project/static/src/js/scripts.js +0 -0
- proper-0.1.dev4/blueprints/project/static/tailwind.config.tmpl.js +0 -9
- proper-0.1.dev4/blueprints/project/static/webpack.config.js +0 -16
- proper-0.1.dev4/blueprints/project/tests/conftest.py +0 -3
- proper-0.1.dev4/blueprints/project/uwsgi-dev.ini +0 -18
- proper-0.1.dev4/blueprints/project/wsgi.tmpl.py +0 -4
- proper-0.1.dev4/blueprints/resource/[[ app_name ]]/controllers/[[ snake_name ]].tmpl.py +0 -14
- proper-0.1.dev4/blueprints/resource/[[ app_name ]]/controllers/__init__.append.py +0 -1
- proper-0.1.dev4/blueprints/resource/[[ app_name ]]/templates/[[ snake_name ]]/edit.html.jinja +0 -6
- proper-0.1.dev4/blueprints/resource/[[ app_name ]]/templates/[[ snake_name ]]/index.html.jinja +0 -6
- proper-0.1.dev4/blueprints/resource/[[ app_name ]]/templates/[[ snake_name ]]/new.html.jinja +0 -6
- proper-0.1.dev4/blueprints/resource/[[ app_name ]]/templates/[[ snake_name ]]/show.html.jinja +0 -6
- proper-0.1.dev4/blueprints/resource/routes.tmpl.py +0 -5
- proper-0.1.dev4/proper/.DS_Store +0 -0
- proper-0.1.dev4/proper/__init__.py +0 -8
- proper-0.1.dev4/proper/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/__pycache__/auth.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/__pycache__/constants.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/__pycache__/errors.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/__pycache__/local.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/__pycache__/request.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/__pycache__/response.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/__pycache__/static.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/__pycache__/status.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/app/__init__.py +0 -1
- proper-0.1.dev4/proper/app/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/app/__pycache__/app.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/app/__pycache__/cli.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/app/__pycache__/cli_run.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/app/__pycache__/default_config.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/app/__pycache__/error_handlers.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/app/__pycache__/errors_mixin.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/app/__pycache__/setup_mixin.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/app/app.py +0 -99
- proper-0.1.dev4/proper/app/cli.py +0 -123
- proper-0.1.dev4/proper/app/cli_run.py +0 -52
- proper-0.1.dev4/proper/app/default_config.py +0 -37
- proper-0.1.dev4/proper/app/error_handlers.py +0 -103
- proper-0.1.dev4/proper/app/errors_mixin.py +0 -91
- proper-0.1.dev4/proper/app/setup_mixin.py +0 -170
- proper-0.1.dev4/proper/app/templates/_context.html.jinja +0 -61
- proper-0.1.dev4/proper/app/templates/_debug-styles.css +0 -100
- proper-0.1.dev4/proper/app/templates/_prism.css +0 -228
- proper-0.1.dev4/proper/app/templates/_prism.js +0 -4
- proper-0.1.dev4/proper/app/templates/debug-error.html.jinja +0 -14
- proper-0.1.dev4/proper/app/templates/debug-not-found.html.jinja +0 -61
- proper-0.1.dev4/proper/app/templates/fallback-error.html +0 -41
- proper-0.1.dev4/proper/app/templates/fallback-forbidden.html +0 -54
- proper-0.1.dev4/proper/app/templates/fallback-not-found.html +0 -42
- proper-0.1.dev4/proper/app/templates/layout.html.jinja +0 -21
- proper-0.1.dev4/proper/auth.py +0 -307
- proper-0.1.dev4/proper/cli/__init__.py +0 -33
- proper-0.1.dev4/proper/cli/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/cli/__pycache__/welcome.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/cli/welcome.py +0 -44
- proper-0.1.dev4/proper/constants.py +0 -12
- proper-0.1.dev4/proper/controller/__init__.py +0 -1
- proper-0.1.dev4/proper/controller/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/controller/__pycache__/base_channel.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/controller/__pycache__/base_controller.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/controller/base_channel.py +0 -26
- proper-0.1.dev4/proper/controller/base_controller.py +0 -71
- proper-0.1.dev4/proper/generators/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/generators/__pycache__/controller.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/generators/__pycache__/mailer.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/generators/__pycache__/model.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/generators/__pycache__/project.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/generators/__pycache__/resource.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/generators/controller.py +0 -56
- proper-0.1.dev4/proper/generators/mailer.py +0 -13
- proper-0.1.dev4/proper/generators/model.py +0 -245
- proper-0.1.dev4/proper/generators/project.py +0 -92
- proper-0.1.dev4/proper/generators/resource.py +0 -81
- proper-0.1.dev4/proper/helpers/__init__.py +0 -12
- proper-0.1.dev4/proper/helpers/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/cookies.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/digestor.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/dot.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/encoding.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/frozendict.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/headersdict.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/iterable.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/multidict.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/paginator.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/render.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/serializer.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/__pycache__/slugify.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/helpers/cookies.py +0 -161
- proper-0.1.dev4/proper/helpers/digestor.py +0 -28
- proper-0.1.dev4/proper/helpers/dot.py +0 -98
- proper-0.1.dev4/proper/helpers/encoding.py +0 -25
- proper-0.1.dev4/proper/helpers/frozendict.py +0 -56
- proper-0.1.dev4/proper/helpers/headersdict.py +0 -13
- proper-0.1.dev4/proper/helpers/iterable.py +0 -8
- proper-0.1.dev4/proper/helpers/multidict.py +0 -122
- proper-0.1.dev4/proper/helpers/paginator.py +0 -338
- proper-0.1.dev4/proper/helpers/render.py +0 -216
- proper-0.1.dev4/proper/helpers/serializer.py +0 -40
- proper-0.1.dev4/proper/helpers/slugify.py +0 -72
- proper-0.1.dev4/proper/local.py +0 -63
- proper-0.1.dev4/proper/middleware/README.md +0 -7
- proper-0.1.dev4/proper/middleware/__init__.py +0 -7
- proper-0.1.dev4/proper/middleware/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/middleware/__pycache__/dispatch.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/middleware/__pycache__/head.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/middleware/__pycache__/match.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/middleware/__pycache__/method_override.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/middleware/__pycache__/protect_from_forgery.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/middleware/__pycache__/redirect.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/middleware/__pycache__/session.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/middleware/dispatch.py +0 -46
- proper-0.1.dev4/proper/middleware/head.py +0 -19
- proper-0.1.dev4/proper/middleware/match.py +0 -18
- proper-0.1.dev4/proper/middleware/method_override.py +0 -30
- proper-0.1.dev4/proper/middleware/protect_from_forgery.py +0 -72
- proper-0.1.dev4/proper/middleware/redirect.py +0 -18
- proper-0.1.dev4/proper/middleware/session.py +0 -64
- proper-0.1.dev4/proper/parsers/__init__.py +0 -5
- proper-0.1.dev4/proper/parsers/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/parsers/__pycache__/parse_comma_separated.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/parsers/__pycache__/parse_cookies.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/parsers/__pycache__/parse_form_data.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/parsers/__pycache__/parse_http_date.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/parsers/__pycache__/parse_query_string.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/parsers/parse_comma_separated.py +0 -13
- proper-0.1.dev4/proper/parsers/parse_cookies.py +0 -25
- proper-0.1.dev4/proper/parsers/parse_form_data.py +0 -125
- proper-0.1.dev4/proper/parsers/parse_http_date.py +0 -15
- proper-0.1.dev4/proper/parsers/parse_query_string.py +0 -46
- proper-0.1.dev4/proper/request.py +0 -384
- proper-0.1.dev4/proper/response.py +0 -350
- proper-0.1.dev4/proper/router/__init__.py +0 -5
- proper-0.1.dev4/proper/router/__pycache__/__init__.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/router/__pycache__/base.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/router/__pycache__/resource.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/router/__pycache__/route.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/router/__pycache__/router.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/router/__pycache__/scope.cpython-39.pyc +0 -0
- proper-0.1.dev4/proper/router/base.py +0 -158
- proper-0.1.dev4/proper/router/resource.py +0 -118
- proper-0.1.dev4/proper/router/route.py +0 -179
- proper-0.1.dev4/proper/router/router.py +0 -117
- proper-0.1.dev4/proper/router/scope.py +0 -92
- proper-0.1.dev4/proper/static.py +0 -149
- proper-0.1.dev4/proper/status.py +0 -209
- proper-0.1.dev4/proper.egg-info/PKG-INFO +0 -87
- proper-0.1.dev4/proper.egg-info/SOURCES.txt +0 -266
- proper-0.1.dev4/proper.egg-info/entry_points.txt +0 -3
- proper-0.1.dev4/proper.egg-info/requires.txt +0 -27
- proper-0.1.dev4/setup.cfg +0 -99
- proper-0.1.dev4/setup.py +0 -5
- /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
- {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
- {proper-0.1.dev4/blueprints/project/[[ app_name ]]/services → proper-0.9.0/src/proper/cli}/__init__.py +0 -0
- /proper-0.1.dev4/blueprints/project/.well-known/.keep → /proper-0.9.0/src/proper/install/__init__.py +0 -0
- {proper-0.1.dev4 → proper-0.9.0/src}/proper.egg-info/dependency_links.txt +0 -0
- {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,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
|