fastapi-startkit 0.44.0__tar.gz → 0.45.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.
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/PKG-INFO +1 -1
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/pyproject.toml +1 -1
- fastapi_startkit-0.45.0/src/fastapi_startkit/fastapi/testing/__init__.py +8 -0
- fastapi_startkit-0.45.0/src/fastapi_startkit/fastapi/testing/assertable_json.py +332 -0
- fastapi_startkit-0.45.0/src/fastapi_startkit/fastapi/testing/test_case.py +35 -0
- fastapi_startkit-0.45.0/src/fastapi_startkit/fastapi/testing/test_response.py +102 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/model.py +4 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/PostgresGrammar.py +6 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/registry.py +3 -0
- fastapi_startkit-0.45.0/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/fastapi/SKILL.md +149 -0
- fastapi_startkit-0.45.0/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/inertia/SKILL.md +333 -0
- fastapi_startkit-0.44.0/src/fastapi_startkit/fastapi/testing/__init__.py +0 -3
- fastapi_startkit-0.44.0/src/fastapi_startkit/fastapi/testing/test_case.py +0 -31
- fastapi_startkit-0.44.0/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/fastapi/SKILL.md +0 -109
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/.DS_Store +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/agent.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/audio.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/audio_factory.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/config.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/decorators.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/document.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/image.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/image_factory.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/providers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/providers/ai_provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/ai/response.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/application.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/auth.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/channels.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/config.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/drivers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/drivers/log_driver.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/drivers/reverb_driver.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/event.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/helpers.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/manager.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/reverb/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/reverb/channel_manager.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/reverb/connection.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/reverb/server.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/stubs/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/broadcasting/stubs/channels.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/carbon/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/carbon/carbon.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/config/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/config/app.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/Configuration.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/config.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/helpers.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/providers/ConfigurationProvider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/configuration/providers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/application.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/can_override_config.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/can_override_default_options.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/command.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/console/publish_command.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/container/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/container/container.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/environment/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/environment/environment.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/exceptions/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/exceptions/exceptions.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/exceptions/handler.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/AI.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/AI.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Cache.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Config.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Config.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Dump.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Dump.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Facade.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Gate.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Gate.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Hash.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Hash.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Loader.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Loader.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Mail.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Mail.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Notification.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Notification.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Queue.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Queue.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/RateLimiter.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/RateLimiter.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Request.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Request.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Response.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Response.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Session.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Session.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Url.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Url.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/View.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/View.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Vite.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/Vite.pyi +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/facades/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/commands/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/commands/serve_command.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/config/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/config/fastapi.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/exceptions.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/providers/fastapi_provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/requests/model.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/fastapi/routers/router.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/helpers/app.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/helpers/dataclass.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/constant.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/context.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/inertia.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/middleware.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/props/props.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/inertia/provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/jsonapi/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/jsonapi/response.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/loader/Loader.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/loader/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/ChannelFactory.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/BaseChannel.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/DailyChannel.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/MultiBaseChannel.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/SingleChannel.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/SlackChannel.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/StackChannel.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/SyslogChannel.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/TerminalChannel.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/channels/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/config/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/config/channels.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/config/logging.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/BaseDriver.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/LogSingleDriver.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/LogSlackDriver.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/LogSyslogDriver.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/LogTerminalDriver.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/drivers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/factory.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/file.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/handler.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/listeners.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/logger.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/managers/LoggingManager.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/managers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/providers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/logging/providers/log_provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/collection/Collection.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/collection/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/DBMigrateCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/DBSeedCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MakeMigrationCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MakeModelCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MakeModelDocstringCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MakeObserverCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MakeSeedCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MigrateFreshCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MigrateRefreshCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MigrateResetCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MigrateRollbackCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/MigrateStatusCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/ShellCommand.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/stubs/create_migration.stub +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/stubs/create_seed.stub +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/stubs/model.stub +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/stubs/observer.stub +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/commands/stubs/table_migration.stub +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/config/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/config/config.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/config/database.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/connection.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/factory.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/manager.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/mysql_connection.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/postgres_connection.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/connections/sqlite_connection.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/exceptions.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/expressions/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/expressions/expressions.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/facades/DB.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/facades/Schema.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/facades/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/factory/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/factory/factory.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/helpers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/helpers/misc.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/migrations/Migration.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/migrations/Migrator.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/migrations/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/MigrationModel.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/attribute.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/builder.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/caster.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/fields.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/observer.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/pivot.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/registry.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/relationship.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/observers/ObservesEvents.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/observers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/pagination/BasePaginator.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/pagination/LengthAwarePaginator.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/pagination/SimplePaginator.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/pagination/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/providers/DatabaseProvider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/providers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/EagerLoadMixin.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/EagerRelation.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/BaseGrammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/MSSQLGrammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/MySQLGrammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/SQLiteGrammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/grammars/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/processors/MSSQLPostProcessor.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/processors/MySQLPostProcessor.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/processors/PostgresPostProcessor.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/processors/SQLitePostProcessor.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/processors/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/query/support.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/BaseRelationship.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/BelongsTo.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/BelongsToMany.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/HasMany.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/HasManyThrough.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/HasOne.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/HasOneThrough.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/MorphMany.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/MorphOne.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/MorphTo.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/MorphToMany.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/relationships/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/Blueprint.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/Column.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/ColumnDiff.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/Constraint.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/ForeignKeyConstraint.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/Index.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/Table.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/TableDiff.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/MSSQLPlatform.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/MySQLPlatform.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/Platform.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/PostgresPlatform.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/SQLitePlatform.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/platforms/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/schema/schema.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/seeds/Seeder.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/seeds/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/stubs/create-migration.html +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/stubs/table-migration.html +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/testing/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/testing/transaction.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/.gitignore +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/CACHEDIR.TAG +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/README.md +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/v/cache/lastfailed +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/.pytest_cache/v/cache/nodeids +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/config/database.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/config.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/exceptions.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/factories/Factory.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/factories/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/schema/Schema.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/BaseScope.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/SoftDeleteScope.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/SoftDeletesMixin.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/UUIDPrimaryKeyMixin.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/UUIDPrimaryKeyScope.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/scopes/scope.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/testing/BaseTestCaseSelectGrammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/testing/Database.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/testing/TestCase.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/testing/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/User.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/connections/test_base_connections.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/eagers/test_eager.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/models/test_models.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/builder/test_mssql_query_builder.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/builder/test_mssql_query_builder_relationships.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_delete_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_insert_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_qmark.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_select_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/grammar/test_mssql_update_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/schema/test_mssql_schema_builder.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mssql/schema/test_mssql_schema_builder_alter.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_mysql_builder_transaction.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_query_builder.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_query_builder_scopes.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/builder/test_transactions.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/connections/test_mysql_connection_selects.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_delete_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_insert_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_qmark.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_select_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/grammar/test_mysql_update_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/model/test_accessors_and_mutators.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/model/test_model.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_belongs_to_many.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_has_many_through.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_has_one_through.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/relationships/test_relationships.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/schema/test_mysql_schema_builder.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/schema/test_mysql_schema_builder_alter.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_can_use_global_scopes.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_can_use_scopes.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/mysql/scopes/test_soft_delete.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/builder/test_postgres_query_builder.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/builder/test_postgres_transaction.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_delete_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_insert_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_select_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/grammar/test_update_grammar.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/relationships/test_postgres_relationships.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/schema/test_postgres_schema_builder.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/postgres/schema/test_postgres_schema_builder_alter.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/scopes/test_default_global_scopes.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/seeds/test_seeds.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm.backup/tests/utils.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/argument.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/prompt.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/protocol.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/providers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/providers/mcp_provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/request.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/resource.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/response.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/server.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/mcp/tool.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/process/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/process/exception.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/process/fake.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/process/process.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/process/result.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/providers/Provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/providers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/providers/app_provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/adapters/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/adapters/base.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/adapters/claude.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/adapters/gemini.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/commands/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/commands/skills.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/parser.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/database/SKILL.md +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/config/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/config/storage.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/data/mime.types +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/drivers/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/drivers/fake.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/drivers/local.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/drivers/s3.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/file.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/filestream.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/helper.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/providers/provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/storage/storage.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/support/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/support/collection.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/support/string.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/support/uri.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/testing/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/testing/test_case.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/utils/structures.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/__init__.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/config/vite.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/exceptions.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/providers/provider.py +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/package.json +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/resources/css/app.css +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/resources/js/app.ts +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/templates/index.html +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/tsconfig.json +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/stubs/vite.config.ts +0 -0
- {fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/vite/vite.py +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from fastapi_startkit.fastapi.testing.assertable_json import (
|
|
2
|
+
AssertableJson,
|
|
3
|
+
assert_json_structure,
|
|
4
|
+
)
|
|
5
|
+
from fastapi_startkit.fastapi.testing.test_case import HttpTestCase
|
|
6
|
+
from fastapi_startkit.fastapi.testing.test_response import TestResponse
|
|
7
|
+
|
|
8
|
+
__all__ = ["HttpTestCase", "TestResponse", "AssertableJson", "assert_json_structure"]
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
"""Fluent JSON assertions for HTTP tests.
|
|
2
|
+
|
|
3
|
+
Provides :class:`AssertableJson`, a chainable wrapper around a decoded JSON
|
|
4
|
+
body (``dict``/``list``).
|
|
5
|
+
|
|
6
|
+
Example::
|
|
7
|
+
|
|
8
|
+
response.assert_json(lambda json: (
|
|
9
|
+
json.where("id", 1)
|
|
10
|
+
.where("name", "Bedu")
|
|
11
|
+
.where("active", lambda v: v is True)
|
|
12
|
+
.has("profile", lambda profile: (
|
|
13
|
+
profile.where("email", "a@b.com").etc()
|
|
14
|
+
))
|
|
15
|
+
.etc()
|
|
16
|
+
))
|
|
17
|
+
|
|
18
|
+
Every ``where``/``has`` call records an interaction with the touched key.
|
|
19
|
+
When an assertion scope closes, :meth:`AssertableJson._verify` asserts that
|
|
20
|
+
every property of an object was interacted with — unless :meth:`etc` was
|
|
21
|
+
called to acknowledge the remaining keys. This catches unexpected or extra
|
|
22
|
+
keys in responses.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
from typing import Any, Callable, Union
|
|
28
|
+
|
|
29
|
+
# A sentinel distinguishing "argument not provided" from an explicit ``None``.
|
|
30
|
+
_MISSING = object()
|
|
31
|
+
|
|
32
|
+
# Mapping of friendly type names to the Python types that satisfy them.
|
|
33
|
+
# ``bool`` is intentionally excluded from the numeric types because in Python
|
|
34
|
+
# ``bool`` is a subclass of ``int`` and JSON keeps the two concepts distinct.
|
|
35
|
+
_JSON_TYPES: dict[str, Callable[[Any], bool]] = {
|
|
36
|
+
"string": lambda v: isinstance(v, str),
|
|
37
|
+
"integer": lambda v: isinstance(v, int) and not isinstance(v, bool),
|
|
38
|
+
"double": lambda v: isinstance(v, float),
|
|
39
|
+
"number": lambda v: isinstance(v, (int, float)) and not isinstance(v, bool),
|
|
40
|
+
"boolean": lambda v: isinstance(v, bool),
|
|
41
|
+
"array": lambda v: isinstance(v, list),
|
|
42
|
+
"object": lambda v: isinstance(v, dict),
|
|
43
|
+
"null": lambda v: v is None,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class AssertableJson:
|
|
48
|
+
"""A chainable, scope-aware assertion helper for decoded JSON bodies."""
|
|
49
|
+
|
|
50
|
+
def __init__(self, data: Any, path: str = "") -> None:
|
|
51
|
+
self._data = data
|
|
52
|
+
self._path = path
|
|
53
|
+
self._interacted: set[str] = set()
|
|
54
|
+
|
|
55
|
+
# ------------------------------------------------------------------ #
|
|
56
|
+
# Internal helpers
|
|
57
|
+
# ------------------------------------------------------------------ #
|
|
58
|
+
def _full(self, key: Any) -> str:
|
|
59
|
+
"""Return the absolute dot-path to ``key`` for error messages."""
|
|
60
|
+
return f"{self._path}.{key}" if self._path else str(key)
|
|
61
|
+
|
|
62
|
+
@staticmethod
|
|
63
|
+
def _step(node: Any, seg: str) -> tuple[bool, Any]:
|
|
64
|
+
"""Descend one segment into a dict key or a list index."""
|
|
65
|
+
if isinstance(node, dict) and seg in node:
|
|
66
|
+
return True, node[seg]
|
|
67
|
+
if isinstance(node, list) and seg.lstrip("-").isdigit():
|
|
68
|
+
index = int(seg)
|
|
69
|
+
if -len(node) <= index < len(node):
|
|
70
|
+
return True, node[index]
|
|
71
|
+
return False, None
|
|
72
|
+
|
|
73
|
+
def _exists(self, key: Any) -> bool:
|
|
74
|
+
node = self._data
|
|
75
|
+
for seg in str(key).split("."):
|
|
76
|
+
found, node = self._step(node, seg)
|
|
77
|
+
if not found:
|
|
78
|
+
return False
|
|
79
|
+
return True
|
|
80
|
+
|
|
81
|
+
def _get(self, key: Any) -> Any:
|
|
82
|
+
"""Resolve a (possibly dotted) ``key`` or raise with the full path."""
|
|
83
|
+
node = self._data
|
|
84
|
+
for seg in str(key).split("."):
|
|
85
|
+
found, node = self._step(node, seg)
|
|
86
|
+
assert found, f"Property [{self._full(key)}] does not exist."
|
|
87
|
+
return node
|
|
88
|
+
|
|
89
|
+
def _record(self, key: Any) -> None:
|
|
90
|
+
"""Track that the top-level segment of ``key`` was interacted with."""
|
|
91
|
+
self._interacted.add(str(key).split(".")[0])
|
|
92
|
+
|
|
93
|
+
# ------------------------------------------------------------------ #
|
|
94
|
+
# Matching — where family
|
|
95
|
+
# ------------------------------------------------------------------ #
|
|
96
|
+
def where(self, key: str, expected: Union[Any, Callable[[Any], bool]]) -> "AssertableJson":
|
|
97
|
+
"""Assert that ``key`` matches ``expected``.
|
|
98
|
+
|
|
99
|
+
``expected`` may be a literal value, or a callable predicate that
|
|
100
|
+
receives the actual value and returns a truthy result.
|
|
101
|
+
"""
|
|
102
|
+
self._record(key)
|
|
103
|
+
actual = self._get(key)
|
|
104
|
+
if callable(expected):
|
|
105
|
+
assert expected(actual), f"Property [{self._full(key)}] was unexpected value [{actual!r}]."
|
|
106
|
+
else:
|
|
107
|
+
assert actual == expected, (
|
|
108
|
+
f"Property [{self._full(key)}] does not match. Expected [{expected!r}], got [{actual!r}]."
|
|
109
|
+
)
|
|
110
|
+
return self
|
|
111
|
+
|
|
112
|
+
def where_not(self, key: str, expected: Union[Any, Callable[[Any], bool]]) -> "AssertableJson":
|
|
113
|
+
"""Assert that ``key`` does NOT match ``expected`` (value or predicate)."""
|
|
114
|
+
self._record(key)
|
|
115
|
+
actual = self._get(key)
|
|
116
|
+
if callable(expected):
|
|
117
|
+
assert not expected(actual), (
|
|
118
|
+
f"Property [{self._full(key)}] was not expected to pass the "
|
|
119
|
+
f"given predicate but did (value [{actual!r}])."
|
|
120
|
+
)
|
|
121
|
+
else:
|
|
122
|
+
assert actual != expected, f"Property [{self._full(key)}] was not expected to equal [{expected!r}] but did."
|
|
123
|
+
return self
|
|
124
|
+
|
|
125
|
+
def where_all(self, bindings: dict) -> "AssertableJson":
|
|
126
|
+
"""Assert each ``{key: expected}`` pair via :meth:`where`."""
|
|
127
|
+
for key, expected in bindings.items():
|
|
128
|
+
self.where(key, expected)
|
|
129
|
+
return self
|
|
130
|
+
|
|
131
|
+
def where_all_type(self, bindings: dict) -> "AssertableJson":
|
|
132
|
+
"""Assert each ``{key: type}`` pair via :meth:`where_type`."""
|
|
133
|
+
for key, expected in bindings.items():
|
|
134
|
+
self.where_type(key, expected)
|
|
135
|
+
return self
|
|
136
|
+
|
|
137
|
+
def where_type(self, key: str, expected: Union[str, list[str]]) -> "AssertableJson":
|
|
138
|
+
"""Assert that ``key`` is one of the given JSON type name(s).
|
|
139
|
+
|
|
140
|
+
Accepts a single name (``"string"``), a pipe form (``"string|null"``)
|
|
141
|
+
or a list (``["string", "null"]``). Supported names: string, integer,
|
|
142
|
+
double, number, boolean, array, object, null.
|
|
143
|
+
"""
|
|
144
|
+
self._record(key)
|
|
145
|
+
actual = self._get(key)
|
|
146
|
+
if isinstance(expected, str):
|
|
147
|
+
names = expected.split("|")
|
|
148
|
+
else:
|
|
149
|
+
names = list(expected)
|
|
150
|
+
for name in names:
|
|
151
|
+
if name not in _JSON_TYPES:
|
|
152
|
+
raise ValueError(f"Unknown JSON type [{name}] for [{self._full(key)}].")
|
|
153
|
+
assert any(_JSON_TYPES[name](actual) for name in names), (
|
|
154
|
+
f"Property [{self._full(key)}] is not of expected type [{'|'.join(names)}]; got value [{actual!r}]."
|
|
155
|
+
)
|
|
156
|
+
return self
|
|
157
|
+
|
|
158
|
+
# ------------------------------------------------------------------ #
|
|
159
|
+
# Presence — has family
|
|
160
|
+
# ------------------------------------------------------------------ #
|
|
161
|
+
def has(
|
|
162
|
+
self,
|
|
163
|
+
key: str,
|
|
164
|
+
length: Any = _MISSING,
|
|
165
|
+
callback: Callable[["AssertableJson"], Any] = _MISSING,
|
|
166
|
+
) -> "AssertableJson":
|
|
167
|
+
"""Assert that ``key`` exists, optionally its length and/or a scope.
|
|
168
|
+
|
|
169
|
+
Supports the shorthands:
|
|
170
|
+
|
|
171
|
+
* ``has("key")`` — just assert presence.
|
|
172
|
+
* ``has("key", 3)`` — assert it is a sized collection of length 3.
|
|
173
|
+
* ``has("key", callback)`` — scope into ``key`` and run nested asserts.
|
|
174
|
+
* ``has("key", 3, callback)`` — both length and a nested scope.
|
|
175
|
+
"""
|
|
176
|
+
self._record(key)
|
|
177
|
+
value = self._get(key)
|
|
178
|
+
|
|
179
|
+
# ``has("key", callback)`` shorthand: length slot holds the callback.
|
|
180
|
+
if callable(length):
|
|
181
|
+
callback = length
|
|
182
|
+
length = _MISSING
|
|
183
|
+
|
|
184
|
+
if length is not _MISSING:
|
|
185
|
+
assert isinstance(value, (list, dict, str)), f"Property [{self._full(key)}] is not countable."
|
|
186
|
+
assert len(value) == length, (
|
|
187
|
+
f"Property [{self._full(key)}] does not have the expected size. "
|
|
188
|
+
f"Expected [{length}], got [{len(value)}]."
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
if callback is not _MISSING:
|
|
192
|
+
child = AssertableJson(value, self._full(key))
|
|
193
|
+
callback(child)
|
|
194
|
+
child._verify()
|
|
195
|
+
|
|
196
|
+
return self
|
|
197
|
+
|
|
198
|
+
def has_all(self, *keys: str) -> "AssertableJson":
|
|
199
|
+
"""Assert that every key in ``keys`` exists. Accepts a list or varargs."""
|
|
200
|
+
for key in self._flatten(keys):
|
|
201
|
+
assert self._exists(key), f"Property [{self._full(key)}] does not exist."
|
|
202
|
+
self._record(key)
|
|
203
|
+
return self
|
|
204
|
+
|
|
205
|
+
def has_any(self, *keys: str) -> "AssertableJson":
|
|
206
|
+
"""Assert that at least one key in ``keys`` exists."""
|
|
207
|
+
keys = self._flatten(keys)
|
|
208
|
+
for key in keys:
|
|
209
|
+
self._record(key)
|
|
210
|
+
assert any(self._exists(key) for key in keys), (
|
|
211
|
+
f"None of the expected properties [{', '.join(map(self._full, keys))}] exist."
|
|
212
|
+
)
|
|
213
|
+
return self
|
|
214
|
+
|
|
215
|
+
def missing(self, key: str) -> "AssertableJson":
|
|
216
|
+
"""Assert that ``key`` is absent from the current scope."""
|
|
217
|
+
assert not self._exists(key), f"Property [{self._full(key)}] was expected to be missing but exists."
|
|
218
|
+
return self
|
|
219
|
+
|
|
220
|
+
def missing_all(self, *keys: str) -> "AssertableJson":
|
|
221
|
+
"""Assert that none of ``keys`` exist."""
|
|
222
|
+
for key in self._flatten(keys):
|
|
223
|
+
self.missing(key)
|
|
224
|
+
return self
|
|
225
|
+
|
|
226
|
+
def count(self, key: str, length: int) -> "AssertableJson":
|
|
227
|
+
"""Assert that the collection at ``key`` has exactly ``length`` items."""
|
|
228
|
+
return self.has(key, length)
|
|
229
|
+
|
|
230
|
+
@staticmethod
|
|
231
|
+
def _flatten(keys: tuple) -> tuple:
|
|
232
|
+
"""Allow both ``has_all("a", "b")`` and ``has_all(["a", "b"])``."""
|
|
233
|
+
if len(keys) == 1 and isinstance(keys[0], (list, tuple)):
|
|
234
|
+
return tuple(keys[0])
|
|
235
|
+
return keys
|
|
236
|
+
|
|
237
|
+
# ------------------------------------------------------------------ #
|
|
238
|
+
# Traversal — first / each
|
|
239
|
+
# ------------------------------------------------------------------ #
|
|
240
|
+
def first(self, callback: Callable[["AssertableJson"], Any]) -> "AssertableJson":
|
|
241
|
+
"""Scope into the first child element and run ``callback`` against it."""
|
|
242
|
+
assert self._data, f"Cannot scope into the first element of empty [{self._path or 'root'}]."
|
|
243
|
+
if isinstance(self._data, list):
|
|
244
|
+
key, value = 0, self._data[0]
|
|
245
|
+
else:
|
|
246
|
+
key, value = next(iter(self._data.items()))
|
|
247
|
+
child = AssertableJson(value, self._full(key))
|
|
248
|
+
callback(child)
|
|
249
|
+
child._verify()
|
|
250
|
+
self._record(key)
|
|
251
|
+
return self
|
|
252
|
+
|
|
253
|
+
def each(self, callback: Callable[["AssertableJson"], Any]) -> "AssertableJson":
|
|
254
|
+
"""Run ``callback`` against every child element in its own scope."""
|
|
255
|
+
if isinstance(self._data, list):
|
|
256
|
+
items = list(enumerate(self._data))
|
|
257
|
+
elif isinstance(self._data, dict):
|
|
258
|
+
items = list(self._data.items())
|
|
259
|
+
else:
|
|
260
|
+
raise AssertionError(f"Property [{self._path or 'root'}] is not iterable for each().")
|
|
261
|
+
for key, value in items:
|
|
262
|
+
child = AssertableJson(value, self._full(key))
|
|
263
|
+
callback(child)
|
|
264
|
+
child._verify()
|
|
265
|
+
self._record(key)
|
|
266
|
+
return self
|
|
267
|
+
|
|
268
|
+
# ------------------------------------------------------------------ #
|
|
269
|
+
# Interaction control
|
|
270
|
+
# ------------------------------------------------------------------ #
|
|
271
|
+
def etc(self) -> "AssertableJson":
|
|
272
|
+
"""Acknowledge any remaining, un-asserted keys in this scope."""
|
|
273
|
+
if isinstance(self._data, dict):
|
|
274
|
+
self._interacted.update(self._data.keys())
|
|
275
|
+
return self
|
|
276
|
+
|
|
277
|
+
def _verify(self) -> None:
|
|
278
|
+
"""Assert every object property was interacted with (or ``etc``'d)."""
|
|
279
|
+
if isinstance(self._data, dict):
|
|
280
|
+
extra = set(self._data.keys()) - self._interacted
|
|
281
|
+
assert not extra, (
|
|
282
|
+
f"Unexpected properties were found at [{self._path or 'root'}]: "
|
|
283
|
+
f"{sorted(extra)}. Interact with them or call .etc()."
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
# ------------------------------------------------------------------ #
|
|
287
|
+
# Phase-2 / TODO — explicit stubs.
|
|
288
|
+
# ------------------------------------------------------------------ #
|
|
289
|
+
def where_contains(self, key: str, expected: Any) -> "AssertableJson": # pragma: no cover
|
|
290
|
+
"""TODO(phase-2): assert the collection at ``key`` contains ``expected``."""
|
|
291
|
+
raise NotImplementedError("where_contains is planned for phase 2.")
|
|
292
|
+
|
|
293
|
+
def count_between(self, key: str, minimum: int, maximum: int) -> "AssertableJson": # pragma: no cover
|
|
294
|
+
"""TODO(phase-2): assert the size of ``key`` is within [min, max]."""
|
|
295
|
+
raise NotImplementedError("count_between is planned for phase 2.")
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def assert_json_structure(structure: Any, data: Any, path: str = "root") -> None:
|
|
299
|
+
"""Assert that ``data`` contains the keys described by ``structure``.
|
|
300
|
+
|
|
301
|
+
``structure`` may be:
|
|
302
|
+
|
|
303
|
+
* a list of leaf key names, e.g. ``["name", "sport"]`` — each must exist
|
|
304
|
+
on the object ``data``;
|
|
305
|
+
* a dict mapping a key to a nested structure, e.g.
|
|
306
|
+
``{"teams": ["name", "sport"]}``;
|
|
307
|
+
* a ``"*"`` key whose value is applied to every element of a list, e.g.
|
|
308
|
+
``{"teams": {"*": ["name", "sport"]}}``.
|
|
309
|
+
|
|
310
|
+
A leaf may map to ``None`` in dict form to assert presence only.
|
|
311
|
+
"""
|
|
312
|
+
if isinstance(structure, list):
|
|
313
|
+
for value in structure:
|
|
314
|
+
if isinstance(value, (list, dict)):
|
|
315
|
+
assert_json_structure(value, data, path)
|
|
316
|
+
else:
|
|
317
|
+
assert isinstance(data, dict) and value in data, f"Missing key [{value}] at [{path}]."
|
|
318
|
+
return
|
|
319
|
+
|
|
320
|
+
if isinstance(structure, dict):
|
|
321
|
+
for key, value in structure.items():
|
|
322
|
+
if key == "*":
|
|
323
|
+
assert isinstance(data, list), f"Expected a list at [{path}]."
|
|
324
|
+
for index, item in enumerate(data):
|
|
325
|
+
assert_json_structure(value, item, f"{path}.{index}")
|
|
326
|
+
else:
|
|
327
|
+
assert isinstance(data, dict) and key in data, f"Missing key [{key}] at [{path}]."
|
|
328
|
+
if value is not None:
|
|
329
|
+
assert_json_structure(value, data[key], f"{path}.{key}")
|
|
330
|
+
return
|
|
331
|
+
|
|
332
|
+
raise TypeError(f"Invalid structure node at [{path}]: {structure!r}")
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from abc import ABC
|
|
2
|
+
|
|
3
|
+
from fastapi_startkit.fastapi.testing.test_response import TestResponse
|
|
4
|
+
from fastapi_startkit.testing import TestCase
|
|
5
|
+
from httpx import AsyncClient, ASGITransport
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class HttpTestCase(TestCase, ABC):
|
|
9
|
+
client: AsyncClient
|
|
10
|
+
|
|
11
|
+
async def asyncSetUp(self):
|
|
12
|
+
await super().asyncSetUp()
|
|
13
|
+
self._client_ctx = AsyncClient(
|
|
14
|
+
transport=ASGITransport(app=self.get_application().fastapi), base_url="http://test"
|
|
15
|
+
)
|
|
16
|
+
self.client = await self._client_ctx.__aenter__()
|
|
17
|
+
|
|
18
|
+
async def asyncTearDown(self):
|
|
19
|
+
await self._client_ctx.__aexit__(None, None, None)
|
|
20
|
+
await super().asyncTearDown()
|
|
21
|
+
|
|
22
|
+
async def get(self, url, **kwargs) -> TestResponse:
|
|
23
|
+
return TestResponse(await self.client.get(url, **kwargs))
|
|
24
|
+
|
|
25
|
+
async def post(self, url, **kwargs) -> TestResponse:
|
|
26
|
+
return TestResponse(await self.client.post(url, **kwargs))
|
|
27
|
+
|
|
28
|
+
async def put(self, url, **kwargs) -> TestResponse:
|
|
29
|
+
return TestResponse(await self.client.put(url, **kwargs))
|
|
30
|
+
|
|
31
|
+
async def patch(self, url, **kwargs) -> TestResponse:
|
|
32
|
+
return TestResponse(await self.client.patch(url, **kwargs))
|
|
33
|
+
|
|
34
|
+
async def delete(self, url, **kwargs) -> TestResponse:
|
|
35
|
+
return TestResponse(await self.client.delete(url, **kwargs))
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""A thin, chainable wrapper around ``httpx.Response`` for HTTP tests.
|
|
2
|
+
|
|
3
|
+
:class:`TestResponse` adds assertion helpers
|
|
4
|
+
(``assert_status``, ``assert_ok``, ``assert_json``) while transparently
|
|
5
|
+
delegating every other attribute/method to the underlying ``httpx.Response``
|
|
6
|
+
via ``__getattr__``. Existing tests that read ``response.status_code`` or call
|
|
7
|
+
``response.json()`` continue to work unchanged.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from typing import Any, Callable, Optional
|
|
13
|
+
|
|
14
|
+
from httpx import Response
|
|
15
|
+
|
|
16
|
+
from fastapi_startkit.fastapi.testing.assertable_json import (
|
|
17
|
+
AssertableJson,
|
|
18
|
+
assert_json_structure,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TestResponse:
|
|
23
|
+
"""Wraps an ``httpx.Response`` and adds fluent assertion helpers."""
|
|
24
|
+
|
|
25
|
+
# Prevent pytest from trying to collect this as a test class.
|
|
26
|
+
__test__ = False
|
|
27
|
+
|
|
28
|
+
def __init__(self, response: Response) -> None:
|
|
29
|
+
self._response = response
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def response(self) -> Response:
|
|
33
|
+
"""Access the underlying ``httpx.Response`` directly."""
|
|
34
|
+
return self._response
|
|
35
|
+
|
|
36
|
+
def __getattr__(self, name: str) -> Any:
|
|
37
|
+
# Only called when ``name`` is not found on this wrapper, so this
|
|
38
|
+
# transparently forwards status_code, headers, json(), text, etc.
|
|
39
|
+
return getattr(self._response, name)
|
|
40
|
+
|
|
41
|
+
def __repr__(self) -> str: # pragma: no cover - cosmetic
|
|
42
|
+
return f"<TestResponse {self._response.status_code} {self._response.url}>"
|
|
43
|
+
|
|
44
|
+
# ------------------------------------------------------------------ #
|
|
45
|
+
# Status assertions
|
|
46
|
+
# ------------------------------------------------------------------ #
|
|
47
|
+
def assert_status(self, code: int) -> "TestResponse":
|
|
48
|
+
"""Assert the response has the given HTTP status code."""
|
|
49
|
+
actual = self._response.status_code
|
|
50
|
+
assert actual == code, f"Expected status code [{code}] but received [{actual}]. Body: {self._response.text}"
|
|
51
|
+
return self
|
|
52
|
+
|
|
53
|
+
def assert_ok(self) -> "TestResponse":
|
|
54
|
+
"""Assert the response status code is 200 OK."""
|
|
55
|
+
return self.assert_status(200)
|
|
56
|
+
|
|
57
|
+
def assert_created(self) -> "TestResponse":
|
|
58
|
+
"""Assert the response status code is 201 Created."""
|
|
59
|
+
return self.assert_status(201)
|
|
60
|
+
|
|
61
|
+
def assert_no_content(self) -> "TestResponse":
|
|
62
|
+
"""Assert the response status code is 204 No Content."""
|
|
63
|
+
return self.assert_status(204)
|
|
64
|
+
|
|
65
|
+
# ------------------------------------------------------------------ #
|
|
66
|
+
# JSON assertions
|
|
67
|
+
# ------------------------------------------------------------------ #
|
|
68
|
+
def assert_json(
|
|
69
|
+
self,
|
|
70
|
+
callback: Optional[Callable[[AssertableJson], Any]] = None,
|
|
71
|
+
*,
|
|
72
|
+
exact: Any = None,
|
|
73
|
+
) -> "TestResponse":
|
|
74
|
+
"""Assert against the JSON body.
|
|
75
|
+
|
|
76
|
+
* ``assert_json(lambda j: j.where(...))`` — run fluent assertions; the
|
|
77
|
+
strict interaction model is enforced (unexpected keys fail unless
|
|
78
|
+
``etc()`` is called).
|
|
79
|
+
* ``assert_json(exact={...})`` — assert the decoded body equals
|
|
80
|
+
``exact`` exactly.
|
|
81
|
+
"""
|
|
82
|
+
body = self._response.json()
|
|
83
|
+
if callback is not None:
|
|
84
|
+
fluent = AssertableJson(body)
|
|
85
|
+
callback(fluent)
|
|
86
|
+
fluent._verify()
|
|
87
|
+
if exact is not None:
|
|
88
|
+
assert body == exact, f"JSON body does not match exactly.\nExpected: {exact!r}\nActual: {body!r}"
|
|
89
|
+
return self
|
|
90
|
+
|
|
91
|
+
def assert_json_structure(self, structure: Any) -> "TestResponse":
|
|
92
|
+
"""Assert the JSON body has the given key structure.
|
|
93
|
+
|
|
94
|
+
Use a ``"*"`` key to apply a nested structure to every element of a
|
|
95
|
+
list::
|
|
96
|
+
|
|
97
|
+
response.assert_json_structure({
|
|
98
|
+
"teams": {"*": ["name", "sport"]},
|
|
99
|
+
})
|
|
100
|
+
"""
|
|
101
|
+
assert_json_structure(structure, self._response.json())
|
|
102
|
+
return self
|
{fastapi_startkit-0.44.0 → fastapi_startkit-0.45.0}/src/fastapi_startkit/masoniteorm/models/model.py
RENAMED
|
@@ -316,6 +316,10 @@ class Model(Attribute, Relationship, ObservesEvents):
|
|
|
316
316
|
|
|
317
317
|
return instance
|
|
318
318
|
|
|
319
|
+
@classmethod
|
|
320
|
+
async def insert(cls, values: dict | list) -> int | None:
|
|
321
|
+
return await cls.query().insert(values)
|
|
322
|
+
|
|
319
323
|
async def update(self, attributes: dict) -> bool:
|
|
320
324
|
if not self._exists:
|
|
321
325
|
return False
|
|
@@ -50,6 +50,12 @@ class PostgresGrammar(BaseGrammar):
|
|
|
50
50
|
def delete_format(self):
|
|
51
51
|
return "DELETE FROM {table} {wheres}"
|
|
52
52
|
|
|
53
|
+
def insert_format(self):
|
|
54
|
+
return "INSERT INTO {table} ({columns}) VALUES ({values})"
|
|
55
|
+
|
|
56
|
+
def bulk_insert_format(self):
|
|
57
|
+
return "INSERT INTO {table} ({columns}) VALUES {values}"
|
|
58
|
+
|
|
53
59
|
def aggregate_string_with_alias(self):
|
|
54
60
|
return "{aggregate_function}({column}) AS {alias}"
|
|
55
61
|
|
fastapi_startkit-0.45.0/src/fastapi_startkit/skills/stubs/.ai/fastapi-startkit/fastapi/SKILL.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fastapi-startkit
|
|
3
|
+
description: Routing, controllers, ORM, requests, resources, and action pattern for fastapi-startkit applications.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fastapi's Routing
|
|
7
|
+
|
|
8
|
+
### Fastapi Startkit's Router
|
|
9
|
+
```python
|
|
10
|
+
# routes/web.py
|
|
11
|
+
from fastapi_startkit.fastapi import Router
|
|
12
|
+
|
|
13
|
+
router = Router()
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
and register routes explicitly, for example
|
|
17
|
+
```python
|
|
18
|
+
router.get("/users", users_controller.index)
|
|
19
|
+
router.post("/users", users_controller.store)
|
|
20
|
+
router.get("/users/{user_id}", users_controller.show)
|
|
21
|
+
router.put("/users/{user_id}", users_controller.update)
|
|
22
|
+
router.patch("/users/{user_id}", users_controller.update)
|
|
23
|
+
router.delete("/users/{user_id}", users_controller.destroy)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Resourceful controllers
|
|
27
|
+
|
|
28
|
+
Prefer `router.resource()` to register the seven standard CRUD routes in one
|
|
29
|
+
call. It maps to a **resourceful controller** with these methods:
|
|
30
|
+
|
|
31
|
+
| Method | Verb & URI | Purpose |
|
|
32
|
+
|-----------|-----------------------------|----------------------------------|
|
|
33
|
+
| `index` | GET `/users` | List the collection |
|
|
34
|
+
| `create` | GET `/users/create` | Show the "new" form |
|
|
35
|
+
| `store` | POST `/users` | Persist a new record |
|
|
36
|
+
| `show` | GET `/users/{user}` | Show a single record |
|
|
37
|
+
| `edit` | GET `/users/{user}/edit` | Show the "edit" form |
|
|
38
|
+
| `update` | PUT/PATCH `/users/{user}` | Persist changes to a record |
|
|
39
|
+
| `destroy` | DELETE `/users/{user}` | Delete a record |
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
# routes/web.py
|
|
43
|
+
router.resource("users", users_controller)
|
|
44
|
+
|
|
45
|
+
# subset / exclusions
|
|
46
|
+
router.resource("users", users_controller, only=['index', 'show'])
|
|
47
|
+
router.resource("users", users_controller, excepts=['create', 'edit'])
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
A full resourceful controller mirrors those seven methods exactly:
|
|
51
|
+
```python
|
|
52
|
+
# app/http/controllers/users_controller.py
|
|
53
|
+
from fastapi_startkit.jsonapi import JsonResource
|
|
54
|
+
|
|
55
|
+
from app.models import User
|
|
56
|
+
from app.http.requests.user_store_request import UserStoreRequest
|
|
57
|
+
|
|
58
|
+
async def index():
|
|
59
|
+
users = await User.all()
|
|
60
|
+
return JsonResource.collection(users)
|
|
61
|
+
|
|
62
|
+
async def create():
|
|
63
|
+
# render/return the "create" form payload
|
|
64
|
+
...
|
|
65
|
+
|
|
66
|
+
async def store(request: UserStoreRequest):
|
|
67
|
+
user = await User.create(request.model_dump())
|
|
68
|
+
return JsonResource(user)
|
|
69
|
+
|
|
70
|
+
async def show(user: int):
|
|
71
|
+
return JsonResource(await User.find_or_fail(user))
|
|
72
|
+
|
|
73
|
+
async def edit(user: int):
|
|
74
|
+
# render/return the "edit" form payload for the record
|
|
75
|
+
return JsonResource(await User.find_or_fail(user))
|
|
76
|
+
|
|
77
|
+
async def update(user: int, request: UserStoreRequest):
|
|
78
|
+
record = await User.find_or_fail(user)
|
|
79
|
+
await record.update(request.model_dump())
|
|
80
|
+
return JsonResource(record)
|
|
81
|
+
|
|
82
|
+
async def destroy(user: int):
|
|
83
|
+
record = await User.find_or_fail(user)
|
|
84
|
+
await record.delete()
|
|
85
|
+
return JsonResource(record)
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## ORM
|
|
89
|
+
```python
|
|
90
|
+
# app/models/user.py
|
|
91
|
+
from fastapi_startkit.masoniteorm import Model
|
|
92
|
+
|
|
93
|
+
class User(Model):
|
|
94
|
+
id: int
|
|
95
|
+
name: str
|
|
96
|
+
email: str
|
|
97
|
+
metadata: dict
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
and use the orm as:
|
|
101
|
+
```python
|
|
102
|
+
# app/http/controllers/users_controller.py
|
|
103
|
+
from app.models import User
|
|
104
|
+
|
|
105
|
+
async def store(request: UserStoreRequest):
|
|
106
|
+
user = User.create(request.model_dump())
|
|
107
|
+
...
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
the `UserStoreRequest` will look like:
|
|
111
|
+
```python
|
|
112
|
+
# app/http/requests/user_store_request.py
|
|
113
|
+
from pydantic import BaseModel
|
|
114
|
+
|
|
115
|
+
class UserStoreRequest(BaseModel):
|
|
116
|
+
name: str
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
and use JsonApiResource to return JSON response from the controller:
|
|
120
|
+
```python
|
|
121
|
+
from fastapi_startkit.jsonapi import JsonResource
|
|
122
|
+
|
|
123
|
+
# app/http/controllers/users_controller.py
|
|
124
|
+
from app.models import User
|
|
125
|
+
|
|
126
|
+
async def store(request: UserStoreRequest):
|
|
127
|
+
user = User.create(request.model_dump())
|
|
128
|
+
return JsonResource(user)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Architecture
|
|
132
|
+
|
|
133
|
+
use the action pattern to write complex logic.
|
|
134
|
+
```python
|
|
135
|
+
# app/actions/user_actions.py
|
|
136
|
+
from app.models import User
|
|
137
|
+
|
|
138
|
+
class UserStoreAction:
|
|
139
|
+
def __init__(self, request: UserStoreRequest):
|
|
140
|
+
self.request = request
|
|
141
|
+
|
|
142
|
+
@staticmethod
|
|
143
|
+
def prepare(request: UserStoreRequest) -> 'UserStoreAction':
|
|
144
|
+
return UserStoreAction(request)
|
|
145
|
+
|
|
146
|
+
def handle(self) -> JsonResource[User]:
|
|
147
|
+
user = User.create(self.request.model_dump())
|
|
148
|
+
return JsonResource(user)
|
|
149
|
+
```
|