piccolo 1.13.1__tar.gz → 1.15.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.
- {piccolo-1.13.1 → piccolo-1.15.0}/PKG-INFO +1 -1
- piccolo-1.15.0/piccolo/__init__.py +1 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/tables.py +6 -2
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/base.py +3 -3
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/engine/base.py +7 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/engine/postgres.py +7 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/base.py +6 -17
- piccolo-1.15.0/piccolo/query/methods/refresh.py +186 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/select.py +4 -1
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/querystring.py +1 -1
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/table.py +8 -2
- piccolo-1.15.0/piccolo/utils/encoding.py +74 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo.egg-info/PKG-INFO +1 -1
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/user/test_tables.py +12 -4
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/m2m/test_m2m.py +7 -0
- piccolo-1.15.0/tests/table/test_refresh.py +297 -0
- piccolo-1.13.1/piccolo/__init__.py +0 -1
- piccolo-1.13.1/piccolo/query/methods/refresh.py +0 -105
- piccolo-1.13.1/piccolo/utils/encoding.py +0 -33
- piccolo-1.13.1/tests/table/test_refresh.py +0 -87
- {piccolo-1.13.1 → piccolo-1.15.0}/LICENSE +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/README.md +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/app/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/app/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/app/commands/new.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/app/commands/show_all.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/app/commands/templates/piccolo_app.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/app/commands/templates/tables.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/app/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/new.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/README.md.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/_blacksheep_app.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/_esmerald_app.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/_fastapi_app.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/_lilya_app.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/_litestar_app.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/_starlette_app.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/app.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/conftest.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/__init__.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/_blacksheep_endpoints.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/_esmerald_endpoints.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/_lilya_endpoints.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/_litestar_endpoints.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/_starlette_endpoints.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/endpoints.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/piccolo_app.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/piccolo_migrations/README.md +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/tables.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/templates/base.html.jinja_raw +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/home/templates/home.html.jinja_raw +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/main.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/piccolo_conf.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/piccolo_conf_test.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/requirements.txt.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/static/favicon.ico +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/commands/templates/app/static/main.css +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/asgi/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/fixtures/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/fixtures/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/fixtures/commands/dump.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/fixtures/commands/load.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/fixtures/commands/shared.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/fixtures/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/meta/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/meta/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/meta/commands/version.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/meta/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/auto/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/auto/diffable_table.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/auto/migration_manager.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/auto/operations.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/auto/schema_differ.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/auto/schema_snapshot.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/auto/serialisation.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/auto/serialisation_legacy.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/commands/backwards.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/commands/base.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/commands/check.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/commands/clean.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/commands/forwards.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/commands/new.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/commands/templates/migration.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/migrations/tables.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/playground/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/playground/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/playground/commands/run.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/playground/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/project/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/project/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/project/commands/new.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/project/commands/templates/piccolo_conf.py.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/project/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/schema/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/schema/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/schema/commands/exceptions.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/schema/commands/generate.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/schema/commands/graph.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/schema/commands/templates/graphviz.dot.jinja +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/schema/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/shell/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/shell/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/shell/commands/run.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/shell/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/sql_shell/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/sql_shell/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/sql_shell/commands/run.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/sql_shell/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/tester/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/tester/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/tester/commands/run.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/tester/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/commands/change_password.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/commands/change_permissions.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/commands/create.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/commands/list.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/piccolo_migrations/2019-11-14T21-52-21.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/piccolo_migrations/2020-06-11T21-38-55.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/piccolo_migrations/2021-04-30T16-14-15.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/apps/user/piccolo_migrations/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/choices.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/column_types.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/combination.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/defaults/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/defaults/base.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/defaults/date.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/defaults/interval.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/defaults/time.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/defaults/timestamp.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/defaults/timestamptz.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/defaults/uuid.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/indexes.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/m2m.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/operators/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/operators/base.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/operators/comparison.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/operators/math.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/operators/string.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/readable.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/columns/reference.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/conf/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/conf/apps.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/custom_types.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/engine/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/engine/cockroach.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/engine/exceptions.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/engine/finder.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/engine/sqlite.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/main.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/py.typed +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/functions/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/functions/aggregate.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/functions/base.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/functions/datetime.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/functions/math.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/functions/string.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/functions/type_conversion.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/alter.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/count.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/create.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/create_index.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/delete.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/drop_index.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/exists.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/indexes.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/insert.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/objects.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/raw.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/table_exists.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/methods/update.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/mixins.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/query/proxy.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/schema.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/table_reflection.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/testing/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/testing/model_builder.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/testing/random_builder.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/dictionary.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/graphlib/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/graphlib/_graphlib.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/lazy_loader.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/list.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/naming.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/objects.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/printing.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/pydantic.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/repr.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/sql_values.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/sync.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo/utils/warnings.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo.egg-info/SOURCES.txt +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo.egg-info/dependency_links.txt +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo.egg-info/entry_points.txt +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo.egg-info/requires.txt +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/piccolo.egg-info/top_level.txt +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/profiling/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/profiling/run_profile.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/pyproject.toml +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/setup.cfg +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/setup.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/app/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/app/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/app/commands/test_new.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/app/commands/test_show_all.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/asgi/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/asgi/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/asgi/commands/test_new.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/fixtures/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/fixtures/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/fixtures/commands/test_dump_load.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/fixtures/commands/test_shared.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/meta/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/meta/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/meta/commands/test_version.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/auto/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/auto/integration/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/auto/integration/test_migrations.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/auto/test_diffable_table.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/auto/test_migration_manager.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/auto/test_schema_differ.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/auto/test_schema_snapshot.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/auto/test_serialisation.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/commands/test_base.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/commands/test_check.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/commands/test_clean.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/commands/test_forwards_backwards.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/commands/test_migrations/2020-03-31T20-38-22.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/commands/test_migrations/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/commands/test_new.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/migrations/test_migration.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/project/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/project/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/project/commands/test_new.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/schema/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/shell/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/shell/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/shell/commands/test_run.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/sql_shell/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/sql_shell/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/sql_shell/commands/test_run.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/tester/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/user/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/user/commands/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/user/commands/test_change_password.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/user/commands/test_change_permissions.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/user/commands/test_create.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/apps/user/commands/test_list.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/m2m/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/m2m/base.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/m2m/test_m2m_schema.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_array.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_base.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_bigint.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_boolean.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_bytea.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_choices.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_combination.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_date.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_db_column_name.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_defaults.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_double_precision.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_get_sql_value.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_interval.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_json.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_jsonb.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_numeric.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_primary_key.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_readable.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_real.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_reference.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_reserved_column_names.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_smallint.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_time.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_timestamp.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_timestamptz.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_uuid.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/columns/test_varchar.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/conf/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/conf/example.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/conf/test_apps.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/engine/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/engine/test_extra_nodes.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/engine/test_logging.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/engine/test_nested_transaction.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/engine/test_pool.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/engine/test_transaction.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/engine/test_version_parsing.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/example_apps/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/example_apps/mega/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/example_apps/mega/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/example_apps/mega/piccolo_migrations/2021-09-20T21-23-25-698988.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/example_apps/mega/piccolo_migrations/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/example_apps/mega/tables.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/example_apps/music/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/example_apps/music/piccolo_app.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/example_apps/music/tables.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/example_apps/music/tables_detailed.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/functions/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/functions/base.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/functions/test_datetime.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/functions/test_functions.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/functions/test_math.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/functions/test_string.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/functions/test_type_conversion.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/mixins/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/mixins/test_columns_delegate.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/mixins/test_order_by_delegate.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/test_await.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/test_camelcase.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/test_freeze.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/test_gather.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/test_querystring.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/query/test_slots.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/instance/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/instance/test_create.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/instance/test_get_related.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/instance/test_get_related_readable.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/instance/test_instantiate.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/instance/test_remove.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/instance/test_save.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/instance/test_to_dict.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_all_columns.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_alter.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_batch.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_callback.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_constructor.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_count.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_create.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_create_db_tables.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_create_table_class.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_delete.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_drop_db_tables.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_exists.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_from_dict.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_indexes.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_inheritance.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_insert.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_join.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_join_on.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_metaclass.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_objects.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_output.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_raw.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_ref.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_repr.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_select.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_str.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_table_exists.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/table/test_update.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/test_main.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/test_schema.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/testing/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/testing/test_model_builder.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/testing/test_random_builder.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/__init__.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_dictionary.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_encoding.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_lazy_loader.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_list.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_naming.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_printing.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_pydantic.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_sql_values.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_sync.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_table_reflection.py +0 -0
- {piccolo-1.13.1 → piccolo-1.15.0}/tests/utils/test_warnings.py +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
__VERSION__ = "1.15.0"
|
@@ -91,10 +91,14 @@ class BaseUser(Table, tablename="piccolo_user"):
|
|
91
91
|
raise ValueError("A password must be provided.")
|
92
92
|
|
93
93
|
if len(password) < cls._min_password_length:
|
94
|
-
raise ValueError(
|
94
|
+
raise ValueError(
|
95
|
+
f"The password is too short. (min {cls._min_password_length})"
|
96
|
+
)
|
95
97
|
|
96
98
|
if len(password) > cls._max_password_length:
|
97
|
-
raise ValueError(
|
99
|
+
raise ValueError(
|
100
|
+
f"The password is too long. (max {cls._max_password_length})"
|
101
|
+
)
|
98
102
|
|
99
103
|
if password.startswith("pbkdf2_sha256"):
|
100
104
|
logger.warning(
|
@@ -250,11 +250,11 @@ class ColumnMeta:
|
|
250
250
|
|
251
251
|
if self.call_chain:
|
252
252
|
column_name = (
|
253
|
-
"
|
253
|
+
".".join(
|
254
254
|
t.cast(str, i._meta.db_column_name)
|
255
255
|
for i in self.call_chain
|
256
256
|
)
|
257
|
-
+ f"
|
257
|
+
+ f".{column_name}"
|
258
258
|
)
|
259
259
|
|
260
260
|
return column_name
|
@@ -291,7 +291,7 @@ class ColumnMeta:
|
|
291
291
|
'band$manager.name'
|
292
292
|
|
293
293
|
>>> Band.manager.name._meta.get_full_name(with_alias=True)
|
294
|
-
'band$manager.name AS "manager
|
294
|
+
'band$manager.name AS "manager.name"'
|
295
295
|
|
296
296
|
:param include_quotes:
|
297
297
|
If you're using the name in a SQL query, each component needs to be
|
@@ -132,6 +132,13 @@ class Engine(t.Generic[TransactionClass], metaclass=ABCMeta):
|
|
132
132
|
):
|
133
133
|
pass
|
134
134
|
|
135
|
+
def transform_response_to_dicts(self, results) -> t.List[t.Dict]:
|
136
|
+
"""
|
137
|
+
If the database adapter returns something other than a list of
|
138
|
+
dictionaries, it should perform the transformation here.
|
139
|
+
"""
|
140
|
+
return results
|
141
|
+
|
135
142
|
@abstractmethod
|
136
143
|
async def run_ddl(self, ddl: str, in_pool: bool = True):
|
137
144
|
pass
|
@@ -579,6 +579,13 @@ class PostgresEngine(Engine[PostgresTransaction]):
|
|
579
579
|
|
580
580
|
return response
|
581
581
|
|
582
|
+
def transform_response_to_dicts(self, results) -> t.List[t.Dict]:
|
583
|
+
"""
|
584
|
+
asyncpg returns a special Record object, so we need to convert it to
|
585
|
+
a dict.
|
586
|
+
"""
|
587
|
+
return [dict(i) for i in results]
|
588
|
+
|
582
589
|
def atomic(self) -> Atomic:
|
583
590
|
return Atomic(engine=self)
|
584
591
|
|
@@ -45,20 +45,11 @@ class Query(t.Generic[TableInstance, QueryResponseType]):
|
|
45
45
|
raise ValueError("Engine isn't defined.")
|
46
46
|
|
47
47
|
async def _process_results(self, results) -> QueryResponseType:
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
# directly into zip without calling `values` on it. This can
|
54
|
-
# save us hundreds of microseconds, depending on the number of
|
55
|
-
# results.
|
56
|
-
raw = [dict(zip(keys, i)) for i in results]
|
57
|
-
else:
|
58
|
-
# SQLite returns a list of dictionaries.
|
59
|
-
raw = [dict(zip(keys, i.values())) for i in results]
|
60
|
-
else:
|
61
|
-
raw = []
|
48
|
+
raw = (
|
49
|
+
self.table._meta.db.transform_response_to_dicts(results)
|
50
|
+
if results
|
51
|
+
else []
|
52
|
+
)
|
62
53
|
|
63
54
|
if hasattr(self, "_raw_response_callback"):
|
64
55
|
self._raw_response_callback(raw)
|
@@ -88,9 +79,7 @@ class Query(t.Generic[TableInstance, QueryResponseType]):
|
|
88
79
|
if column._alias is not None:
|
89
80
|
json_column_names.append(column._alias)
|
90
81
|
elif len(column._meta.call_chain) > 0:
|
91
|
-
json_column_names.append(
|
92
|
-
column._meta.get_default_alias().replace("$", ".")
|
93
|
-
)
|
82
|
+
json_column_names.append(column._meta.get_default_alias())
|
94
83
|
else:
|
95
84
|
json_column_names.append(column._meta.name)
|
96
85
|
|
@@ -0,0 +1,186 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import typing as t
|
4
|
+
|
5
|
+
from piccolo.utils.encoding import JSONDict
|
6
|
+
from piccolo.utils.sync import run_sync
|
7
|
+
|
8
|
+
if t.TYPE_CHECKING: # pragma: no cover
|
9
|
+
from piccolo.columns import Column
|
10
|
+
from piccolo.table import Table
|
11
|
+
|
12
|
+
|
13
|
+
class Refresh:
|
14
|
+
"""
|
15
|
+
Used to refresh :class:`Table <piccolo.table.Table>` instances with the
|
16
|
+
latest data data from the database. Accessible via
|
17
|
+
:meth:`refresh <piccolo.table.Table.refresh>`.
|
18
|
+
|
19
|
+
:param instance:
|
20
|
+
The instance to refresh.
|
21
|
+
:param columns:
|
22
|
+
Which columns to refresh - it not specified, then all columns are
|
23
|
+
refreshed.
|
24
|
+
:param load_json:
|
25
|
+
Whether to load ``JSON`` / ``JSONB`` columns as objects, instead of
|
26
|
+
just a string.
|
27
|
+
|
28
|
+
"""
|
29
|
+
|
30
|
+
def __init__(
|
31
|
+
self,
|
32
|
+
instance: Table,
|
33
|
+
columns: t.Optional[t.Sequence[Column]] = None,
|
34
|
+
load_json: bool = False,
|
35
|
+
):
|
36
|
+
self.instance = instance
|
37
|
+
|
38
|
+
if columns:
|
39
|
+
for column in columns:
|
40
|
+
if len(column._meta.call_chain) > 0:
|
41
|
+
raise ValueError(
|
42
|
+
"We can't currently selectively refresh certain "
|
43
|
+
"columns on child objects (e.g. Concert.band_1.name). "
|
44
|
+
"Please just specify top level columns (e.g. "
|
45
|
+
"Concert.band_1), and the entire child object will be "
|
46
|
+
"refreshed."
|
47
|
+
)
|
48
|
+
|
49
|
+
self.columns = columns
|
50
|
+
self.load_json = load_json
|
51
|
+
|
52
|
+
@property
|
53
|
+
def _columns(self) -> t.Sequence[Column]:
|
54
|
+
"""
|
55
|
+
Works out which columns the user wants to refresh.
|
56
|
+
"""
|
57
|
+
if self.columns:
|
58
|
+
return self.columns
|
59
|
+
|
60
|
+
return [
|
61
|
+
i for i in self.instance._meta.columns if not i._meta.primary_key
|
62
|
+
]
|
63
|
+
|
64
|
+
def _get_columns(self, instance: Table, columns: t.Sequence[Column]):
|
65
|
+
"""
|
66
|
+
If `prefetch` was used on the object, for example::
|
67
|
+
|
68
|
+
>>> await Band.objects(Band.manager)
|
69
|
+
|
70
|
+
We should also update the prefetched object.
|
71
|
+
|
72
|
+
It works multiple level deep. If we refresh this::
|
73
|
+
|
74
|
+
>>> await Album.objects(Album.band.manager).first()
|
75
|
+
|
76
|
+
It will update the nested `band` object, and also the `manager`
|
77
|
+
object.
|
78
|
+
|
79
|
+
"""
|
80
|
+
from piccolo.columns.column_types import ForeignKey
|
81
|
+
from piccolo.table import Table
|
82
|
+
|
83
|
+
select_columns = []
|
84
|
+
|
85
|
+
for column in columns:
|
86
|
+
if isinstance(column, ForeignKey) and isinstance(
|
87
|
+
(child_instance := getattr(instance, column._meta.name)),
|
88
|
+
Table,
|
89
|
+
):
|
90
|
+
select_columns.extend(
|
91
|
+
self._get_columns(
|
92
|
+
child_instance,
|
93
|
+
# Fetch all columns (even the primary key, just in
|
94
|
+
# case the foreign key now references a different row).
|
95
|
+
column.all_columns(),
|
96
|
+
)
|
97
|
+
)
|
98
|
+
else:
|
99
|
+
select_columns.append(column)
|
100
|
+
|
101
|
+
return select_columns
|
102
|
+
|
103
|
+
def _update_instance(self, instance: Table, data_dict: t.Dict):
|
104
|
+
"""
|
105
|
+
Update the table instance. It is called recursively, if the instance
|
106
|
+
has child instances.
|
107
|
+
"""
|
108
|
+
for key, value in data_dict.items():
|
109
|
+
if isinstance(value, dict) and not isinstance(value, JSONDict):
|
110
|
+
# If the value is a dict, then it's a child instance.
|
111
|
+
if all(i is None for i in value.values()):
|
112
|
+
# If all values in the nested object are None, then we can
|
113
|
+
# safely assume that the object itself is null, as the
|
114
|
+
# primary key value must be null.
|
115
|
+
setattr(instance, key, None)
|
116
|
+
else:
|
117
|
+
self._update_instance(getattr(instance, key), value)
|
118
|
+
else:
|
119
|
+
setattr(instance, key, value)
|
120
|
+
|
121
|
+
async def run(
|
122
|
+
self, in_pool: bool = True, node: t.Optional[str] = None
|
123
|
+
) -> Table:
|
124
|
+
"""
|
125
|
+
Run it asynchronously. For example::
|
126
|
+
|
127
|
+
await my_instance.refresh().run()
|
128
|
+
|
129
|
+
# or for convenience:
|
130
|
+
await my_instance.refresh()
|
131
|
+
|
132
|
+
Modifies the instance in place, but also returns it as a convenience.
|
133
|
+
|
134
|
+
"""
|
135
|
+
instance = self.instance
|
136
|
+
|
137
|
+
if not instance._exists_in_db:
|
138
|
+
raise ValueError("The instance doesn't exist in the database.")
|
139
|
+
|
140
|
+
pk_column = instance._meta.primary_key
|
141
|
+
|
142
|
+
primary_key_value = getattr(instance, pk_column._meta.name, None)
|
143
|
+
|
144
|
+
if primary_key_value is None:
|
145
|
+
raise ValueError("The instance's primary key value isn't defined.")
|
146
|
+
|
147
|
+
columns = self._columns
|
148
|
+
if not columns:
|
149
|
+
raise ValueError("No columns to fetch.")
|
150
|
+
|
151
|
+
select_columns = self._get_columns(
|
152
|
+
instance=self.instance, columns=columns
|
153
|
+
)
|
154
|
+
|
155
|
+
data_dict = (
|
156
|
+
await instance.__class__.select(*select_columns)
|
157
|
+
.where(pk_column == primary_key_value)
|
158
|
+
.output(nested=True, load_json=self.load_json)
|
159
|
+
.first()
|
160
|
+
.run(node=node, in_pool=in_pool)
|
161
|
+
)
|
162
|
+
|
163
|
+
if data_dict is None:
|
164
|
+
raise ValueError(
|
165
|
+
"The object doesn't exist in the database any more."
|
166
|
+
)
|
167
|
+
|
168
|
+
self._update_instance(instance=instance, data_dict=data_dict)
|
169
|
+
|
170
|
+
return instance
|
171
|
+
|
172
|
+
def __await__(self):
|
173
|
+
"""
|
174
|
+
If the user doesn't explicity call :meth:`run`, proxy to it as a
|
175
|
+
convenience.
|
176
|
+
"""
|
177
|
+
return self.run().__await__()
|
178
|
+
|
179
|
+
def run_sync(self, *args, **kwargs) -> Table:
|
180
|
+
"""
|
181
|
+
Run it synchronously. For example::
|
182
|
+
|
183
|
+
my_instance.refresh().run_sync()
|
184
|
+
|
185
|
+
"""
|
186
|
+
return run_sync(self.run(*args, **kwargs))
|
@@ -406,6 +406,9 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
406
406
|
def output(self: Self, *, load_json: bool, as_list: bool) -> SelectJSON: # type: ignore # noqa: E501
|
407
407
|
...
|
408
408
|
|
409
|
+
@t.overload
|
410
|
+
def output(self: Self, *, load_json: bool, nested: bool) -> Self: ...
|
411
|
+
|
409
412
|
@t.overload
|
410
413
|
def output(self: Self, *, nested: bool) -> Self: ...
|
411
414
|
|
@@ -574,7 +577,7 @@ class Select(Query[TableInstance, t.List[t.Dict[str, t.Any]]]):
|
|
574
577
|
query += "{}"
|
575
578
|
args.append(distinct.querystring)
|
576
579
|
|
577
|
-
columns_str = ", ".join("{}" for
|
580
|
+
columns_str = ", ".join("{}" for _ in select_strings)
|
578
581
|
query += f" {columns_str} FROM {self.table._meta.get_formatted_tablename()}" # noqa: E501
|
579
582
|
args.extend(select_strings)
|
580
583
|
|
@@ -246,7 +246,7 @@ class QueryString(Selectable):
|
|
246
246
|
self, engine_type: str, with_alias: bool = True
|
247
247
|
) -> QueryString:
|
248
248
|
if with_alias and self._alias:
|
249
|
-
return QueryString("{} AS " + self._alias, self)
|
249
|
+
return QueryString("{} AS " + f'"{self._alias}"', self)
|
250
250
|
else:
|
251
251
|
return self
|
252
252
|
|
@@ -541,7 +541,9 @@ class Table(metaclass=TableMetaclass):
|
|
541
541
|
)
|
542
542
|
|
543
543
|
def refresh(
|
544
|
-
self,
|
544
|
+
self,
|
545
|
+
columns: t.Optional[t.Sequence[Column]] = None,
|
546
|
+
load_json: bool = False,
|
545
547
|
) -> Refresh:
|
546
548
|
"""
|
547
549
|
Used to fetch the latest data for this instance from the database.
|
@@ -551,6 +553,10 @@ class Table(metaclass=TableMetaclass):
|
|
551
553
|
If you only want to refresh certain columns, specify them here.
|
552
554
|
Otherwise all columns are refreshed.
|
553
555
|
|
556
|
+
:param load_json:
|
557
|
+
Whether to load ``JSON`` / ``JSONB`` columns as objects, instead of
|
558
|
+
just a string.
|
559
|
+
|
554
560
|
Example usage::
|
555
561
|
|
556
562
|
# Get an instance from the database.
|
@@ -564,7 +570,7 @@ class Table(metaclass=TableMetaclass):
|
|
564
570
|
instance.refresh().run_sync()
|
565
571
|
|
566
572
|
"""
|
567
|
-
return Refresh(instance=self, columns=columns)
|
573
|
+
return Refresh(instance=self, columns=columns, load_json=load_json)
|
568
574
|
|
569
575
|
@t.overload
|
570
576
|
def get_related(
|
@@ -0,0 +1,74 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import typing as t
|
4
|
+
|
5
|
+
try:
|
6
|
+
import orjson
|
7
|
+
|
8
|
+
ORJSON = True
|
9
|
+
except ImportError:
|
10
|
+
import json
|
11
|
+
|
12
|
+
ORJSON = False
|
13
|
+
|
14
|
+
|
15
|
+
def dump_json(data: t.Any, pretty: bool = False) -> str:
|
16
|
+
if ORJSON:
|
17
|
+
orjson_params: t.Dict[str, t.Any] = {"default": str}
|
18
|
+
if pretty:
|
19
|
+
orjson_params["option"] = (
|
20
|
+
orjson.OPT_INDENT_2 | orjson.OPT_APPEND_NEWLINE # type: ignore
|
21
|
+
)
|
22
|
+
return orjson.dumps(data, **orjson_params).decode( # type: ignore
|
23
|
+
"utf8"
|
24
|
+
)
|
25
|
+
else:
|
26
|
+
params: t.Dict[str, t.Any] = {"default": str}
|
27
|
+
if pretty:
|
28
|
+
params["indent"] = 2
|
29
|
+
return json.dumps(data, **params) # type: ignore
|
30
|
+
|
31
|
+
|
32
|
+
class JSONDict(dict):
|
33
|
+
"""
|
34
|
+
Once we have parsed a JSON string into a dictionary, we can't distinguish
|
35
|
+
it from other dictionaries.
|
36
|
+
|
37
|
+
Sometimes we might want to - for example::
|
38
|
+
|
39
|
+
>>> await Album.select(
|
40
|
+
... Album.all_columns(),
|
41
|
+
... Album.recording_studio.all_columns()
|
42
|
+
... ).output(
|
43
|
+
... nested=True,
|
44
|
+
... load_json=True
|
45
|
+
... )
|
46
|
+
|
47
|
+
[{
|
48
|
+
'id': 1,
|
49
|
+
'band': 1,
|
50
|
+
'name': 'Awesome album 1',
|
51
|
+
'recorded_at': {
|
52
|
+
'id': 1,
|
53
|
+
'facilities': {'restaurant': True, 'mixing_desk': True},
|
54
|
+
'name': 'Abbey Road'
|
55
|
+
},
|
56
|
+
'release_date': datetime.date(2021, 1, 1)
|
57
|
+
}]
|
58
|
+
|
59
|
+
Facilities could be mistaken for a table.
|
60
|
+
|
61
|
+
"""
|
62
|
+
|
63
|
+
...
|
64
|
+
|
65
|
+
|
66
|
+
def load_json(data: str) -> t.Any:
|
67
|
+
response = (
|
68
|
+
orjson.loads(data) if ORJSON else json.loads(data) # type: ignore
|
69
|
+
)
|
70
|
+
|
71
|
+
if isinstance(response, dict):
|
72
|
+
return JSONDict(**response)
|
73
|
+
|
74
|
+
return response
|
@@ -109,7 +109,7 @@ class TestLogin(TestCase):
|
|
109
109
|
BaseUser.update_password_sync(username, malicious_password)
|
110
110
|
self.assertEqual(
|
111
111
|
manager.exception.__str__(),
|
112
|
-
"The password is too long.",
|
112
|
+
f"The password is too long. (max {BaseUser._max_password_length})",
|
113
113
|
)
|
114
114
|
|
115
115
|
# Test short passwords
|
@@ -118,7 +118,10 @@ class TestLogin(TestCase):
|
|
118
118
|
BaseUser.update_password_sync(username, short_password)
|
119
119
|
self.assertEqual(
|
120
120
|
manager.exception.__str__(),
|
121
|
-
|
121
|
+
(
|
122
|
+
"The password is too short. (min "
|
123
|
+
f"{BaseUser._min_password_length})"
|
124
|
+
),
|
122
125
|
)
|
123
126
|
|
124
127
|
# Test no password
|
@@ -205,7 +208,11 @@ class TestCreateUser(TestCase):
|
|
205
208
|
BaseUser.create_user_sync(username="bob", password="abc")
|
206
209
|
|
207
210
|
self.assertEqual(
|
208
|
-
manager.exception.__str__(),
|
211
|
+
manager.exception.__str__(),
|
212
|
+
(
|
213
|
+
"The password is too short. (min "
|
214
|
+
f"{BaseUser._min_password_length})"
|
215
|
+
),
|
209
216
|
)
|
210
217
|
|
211
218
|
def test_long_password_error(self):
|
@@ -216,7 +223,8 @@ class TestCreateUser(TestCase):
|
|
216
223
|
)
|
217
224
|
|
218
225
|
self.assertEqual(
|
219
|
-
manager.exception.__str__(),
|
226
|
+
manager.exception.__str__(),
|
227
|
+
f"The password is too long. (max {BaseUser._max_password_length})",
|
220
228
|
)
|
221
229
|
|
222
230
|
def test_no_username_error(self):
|
@@ -4,6 +4,7 @@ import decimal
|
|
4
4
|
import uuid
|
5
5
|
from unittest import TestCase
|
6
6
|
|
7
|
+
from piccolo.utils.encoding import JSONDict
|
7
8
|
from tests.base import engines_skip
|
8
9
|
|
9
10
|
try:
|
@@ -376,6 +377,9 @@ class TestM2MComplexSchema(TestCase):
|
|
376
377
|
|
377
378
|
if isinstance(column, UUID):
|
378
379
|
self.assertIn(type(returned_value), (uuid.UUID, asyncpgUUID))
|
380
|
+
elif isinstance(column, (JSON, JSONB)):
|
381
|
+
self.assertEqual(type(returned_value), JSONDict)
|
382
|
+
self.assertEqual(original_value, returned_value)
|
379
383
|
else:
|
380
384
|
self.assertEqual(
|
381
385
|
type(original_value),
|
@@ -401,6 +405,9 @@ class TestM2MComplexSchema(TestCase):
|
|
401
405
|
if isinstance(column, UUID):
|
402
406
|
self.assertIn(type(returned_value), (uuid.UUID, asyncpgUUID))
|
403
407
|
self.assertEqual(str(original_value), str(returned_value))
|
408
|
+
elif isinstance(column, (JSON, JSONB)):
|
409
|
+
self.assertEqual(type(returned_value), JSONDict)
|
410
|
+
self.assertEqual(original_value, returned_value)
|
404
411
|
else:
|
405
412
|
self.assertEqual(
|
406
413
|
type(original_value),
|