plain changelog
0.94.0 (2025-12-12)
What's changed
FormFieldMissingErrorexceptions are now automatically converted to HTTP 400 Bad Request responses with a warning log instead of causing a 500 error (b38f6e5)
Upgrade instructions
- No changes required
0.93.1 (2025-12-09)
What's changed
- Added type annotation for
request.unique_idattribute to improve IDE support and type checking (23af501)
Upgrade instructions
- No changes required
0.93.0 (2025-12-04)
What's changed
- Improved type annotations across forms, HTTP handling, logging, and other core modules for better IDE support and type checking (ac1eeb0)
- Internal refactor of
TimestampSignerto use composition instead of inheritance fromSigner, maintaining the same public API (ac1eeb0)
Upgrade instructions
- No changes required
0.92.0 (2025-12-01)
What's changed
- Added
request.client_ipproperty to get the client's IP address, with support forX-Forwarded-Forheader when behind a trusted proxy (cb0bc5d) - Added
USE_X_FORWARDED_FORsetting to enable reading client IP fromX-Forwarded-Forheader (cb0bc5d) - Improved
print_eventCLI output styling with dimmed text for less visual noise (b09edfd)
Upgrade instructions
- No changes required
0.91.0 (2025-11-24)
What's changed
- Request body parsing refactored: the
request.dataattribute has been replaced withrequest.json_dataandrequest.form_datafor explicit content-type handling (90332a9) QueryDictnow has proper type annotations forget(),pop(),getlist(), and__getitem__()methods that reflect string return types (90332a9)- Forms now automatically select between
json_dataandform_databased on request content-type (90332a9) - View mixins
ObjectTemplateViewMixinremoved in favor of class inheritance for better typing -UpdateViewandDeleteViewnow inherit fromDetailView(569afd6) AppLoggercontext logging now uses acontextdict parameter instead of**kwargsfor better type checking (581b406)- Removed erroneous
AuthViewMixinexport fromplain.views(334bbb6)
Upgrade instructions
Replace
request.datawith the appropriate method:- For JSON requests: use
request.json_data(returns a dict, raisesBadRequestfor invalid JSON) - For form data: use
request.form_data(returns aQueryDict)
- For JSON requests: use
Update
app_loggercalls that pass context as kwargs to use thecontextparameter:# Before app_logger.info("Message", user_id=123, action="login") # After app_logger.info("Message", context={"user_id": 123, "action": "login"})
0.90.0 (2025-11-20)
What's changed
- Improved type annotations in
timezone.py:is_aware()andis_naive()now accept bothdatetimeandtimeobjects for more flexible type checking (a43145e) - Enhanced type annotations in view classes:
convert_value_to_response()and handler result variables now use more explicit type hints for better IDE support (dc4454e) - Fixed type errors in forms and server workers: URL field now handles bytes properly, and worker wait_fds has explicit type annotation (fc98d66)
Upgrade instructions
- No changes required
0.89.0 (2025-11-14)
What's changed
- Improved type annotations in view classes:
url_args,url_kwargs, and various template/form context dictionaries now have more specific type hints for better IDE support and type checking (83bcb95)
Upgrade instructions
- No changes required
0.88.0 (2025-11-13)
What's changed
- The
plain.formsmodule now uses explicit imports instead of wildcard imports, improving IDE autocomplete and type checking support (eff36f3)
Upgrade instructions
- No changes required
0.87.0 (2025-11-12)
What's changed
- Internal classes now use abstract base classes with
@abstractmethoddecorators instead of raisingNotImplementedError, improving type checking and IDE support (91b329a, 81b5f88, d2e2423, 61e7b5a) - Updated to latest version of
tytype checker and fixed type errors and warnings throughout the codebase (f4dbcef)
Upgrade instructions
- No changes required
0.86.2 (2025-11-11)
What's changed
- CLI color output is now enabled in CI environments by checking the
CIenvironment variable, matching the behavior of modern tools like uv (a1500f15ed)
Upgrade instructions
- No changes required
0.86.1 (2025-11-10)
What's changed
- The
plain preflightcommand now outputs to stderr only when using--format json, keeping stdout clean for JSON parsing while avoiding success messages appearing in error logs for text format (72ebee7729) - CLI color handling now follows the CLICOLOR standard with proper priority:
NO_COLOR>CLICOLOR_FORCE/FORCE_COLOR>CLICOLOR>isatty(c7fea406c5)
Upgrade instructions
- No changes required
0.86.0 (2025-11-10)
What's changed
- Log output is now split by severity level: INFO and below go to stdout, WARNING and above go to stderr for proper cloud platform log classification (52403b15ba)
- Added
LOG_STREAMsetting to customize log output behavior with options:"split"(default),"stdout", or"stderr"(52403b15ba) - Log configuration documentation expanded with detailed guidance on output streams and environment variable settings (52403b15ba)
Upgrade instructions
- No changes required (default behavior splits logs to stdout/stderr automatically, but this can be customized via
PLAIN_LOG_STREAMenvironment variable if needed)
0.85.0 (2025-11-03)
What's changed
- CLI help output now organizes commands into "Common Commands", "Core Commands", and "Package Commands" sections for better discoverability (73d3a48)
- CLI help output has been customized with improved formatting and shortcut indicators showing which commands are shortcuts (e.g.,
migrate → models migrate) (db882e6) - CSRF exception messages now include more detailed context about what was rejected and why (e.g., port mismatches, host mismatches) (9a8e09c)
- The
plain agent mdcommand now saves a combinedAGENTS.mdfile to.plain/by default when usingplain dev, making it easier to provide context to coding agents (786b7a0) - CLI help text styling has been refined with dimmed descriptions and usage prefixes for improved readability (d7f7053)
Upgrade instructions
- No changes required
0.84.1 (2025-10-31)
What's changed
- Added
license = "BSD-3-Clause"to package metadata inpyproject.toml(8477355)
Upgrade instructions
- No changes required
0.84.0 (2025-10-29)
What's changed
- The
DEFAULT_RESPONSE_HEADERSsetting now supports format string placeholders (e.g.,{request.csp_nonce}) for dynamic header values instead of requiring a callable function (5199383128) - Views can now set headers to
Noneto explicitly remove default response headers (5199383128) - Added comprehensive documentation for customizing default response headers including override, remove, and extend patterns (5199383128)
Upgrade instructions
If you have
DEFAULT_RESPONSE_HEADERSconfigured as a callable function, convert it to a dictionary with format string placeholders:# Before: def DEFAULT_RESPONSE_HEADERS(request): nonce = request.csp_nonce return { "Content-Security-Policy": f"script-src 'self' 'nonce-{nonce}'", } # After: DEFAULT_RESPONSE_HEADERS = { "Content-Security-Policy": "script-src 'self' 'nonce-{request.csp_nonce}'", }If you were overriding default headers to empty strings (
"") to remove them, change those toNoneinstead
0.83.0 (2025-10-29)
What's changed
- Added comprehensive Content Security Policy (CSP) documentation explaining how to use nonces with inline scripts and styles (784f3dd972)
- The
json_scriptutility function now accepts an optionalnonceparameter for CSP-compliant inline JSON scripts (784f3dd972)
Upgrade instructions
- Any
|json_scriptusages need to make sure the second argument is a nonce, not a custom encoder (which is now third)
0.82.0 (2025-10-29)
What's changed
- The
DEFAULT_RESPONSE_HEADERSsetting can now be a callable that accepts a request argument, enabling dynamic header generation per request (cb92905834) - Added
request.csp_noncecached property for generating Content Security Policy nonces (75071dcc70) - Simplified the preflight command by moving
plain preflight checkback toplain preflight(40c2c4560e)
Upgrade instructions
- If you use
plain preflight check, update toplain preflight(thechecksubcommand has been removed for simplicity) - If you use
plain preflight check --deploy, update toplain preflight --deploy
0.81.0 (2025-10-22)
What's changed
- Removed support for category-specific error template fallbacks like
4xx.htmland5xx.html(9513f7c4fa)
Upgrade instructions
- If you have
4xx.htmlor5xx.htmlerror templates, rename them to specific status code templates (e.g.,404.html,500.html) or remove them if you prefer the plain HTTP response fallback
0.80.0 (2025-10-22)
What's changed
- CSRF failures now raise
SuspiciousOperation(HTTP 400) instead ofPermissionDenied(HTTP 403) (ad146bde3e) - Error templates can now use category-specific fallbacks like
4xx.htmlor5xx.htmlinstead of the genericerror.html(716cfa3cfc) - Updated error template documentation with best practices for self-contained
500.htmltemplates (55cea3b522)
Upgrade instructions
- If you have a
templates/error.htmltemplate, instead create specific error templates for each status code you want to customize (e.g.,400.html,403.html,404.html,500.html). You can also create category-specific templates like4xx.htmlor5xx.htmlfor broader coverage.
0.79.0 (2025-10-22)
What's changed
- Response objects now have an
exceptionattribute that stores the exception that caused 5xx errors (0a243ba89c) - Middleware classes now use an abstract base class
HttpMiddlewarewith aprocess_request()method (b960eed6c6) - CSRF middleware now raises
PermissionDeniedinstead of rendering a customCsrfFailureView(d4b93e59b3) - The
HTTP_ERROR_VIEWSsetting has been removed (7a4e3a31f4) - Standalone
plain-changelogandplain-upgradeexecutables have been removed in favor of the built-in commands (07c3a4c540) - Standalone
plain-buildexecutable has been removed (99301ea797) - Removed automatic logging of all HTTP 400+ status codes for cleaner logs (c2769d7281)
Upgrade instructions
If you have custom middleware, inherit from
HttpMiddlewareand rename your__call__()method toprocess_request():# Before: class MyMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) return response # After: from plain.http import HttpMiddleware class MyMiddleware(HttpMiddleware): def process_request(self, request): response = self.get_response(request) return responseRemove any custom
HTTP_ERROR_VIEWSsetting from your configuration - error views are now controlled entirely by exception handlersIf you were calling
plain-changelogorplain-upgradeas standalone commands, useplain changelogorplain upgradeinsteadIf you were calling
plain-buildas a standalone command, useplain buildinstead
0.78.2 (2025-10-20)
What's changed
- Updated package metadata to use
[dependency-groups]instead of[tool.uv]for development dependencies, following PEP 735 standard (1b43a3a272)
Upgrade instructions
- No changes required
0.78.1 (2025-10-17)
What's changed
- Fixed job worker logging by using
getLoggerinstead of directly instantiatingLoggerfor the plain logger (dd675666b9)
Upgrade instructions
- No changes required
0.78.0 (2025-10-17)
What's changed
- Chores have been refactored to use abstract base classes instead of decorated functions (c4466d3c60)
- Added
SHELL_IMPORTsetting to customize what gets automatically imported inplain shell(9055f59c08) - Views that return
Nonenow raiseHttp404instead of returningResponseNotFound(5bb60016eb) - The
plain chores listcommand output formatting now matches theplain jobs listformat (4b6881a49e)
Upgrade instructions
Update any chores from decorated functions to class-based chores:
# Before: @register_chore("group") def chore_name(): """Description""" return "Done!" # After: from plain.chores import Chore, register_chore @register_chore class ChoreName(Chore): """Description""" def run(self): return "Done!"Import
Chorebase class fromplain.choreswhen creating new chores
0.77.0 (2025-10-13)
What's changed
- The
plain server --reloadnow useswatchfilesfor improved cross-platform file watching (92e95c5032) - Server reloader now watches
.env*files for changes and triggers automatic reload (92e95c5032) - HTML template additions and deletions now trigger automatic server reload when using
--reload(f2f31c288b) - Internal server worker type renamed from "gthread" to "thread" for clarity (6470748e91)
Upgrade instructions
- No changes required
0.76.0 (2025-10-12)
What's changed
- Added new
plain servercommand with built-in WSGI server (vendored gunicorn) (f9dc2867c7) - The
plain servercommand supportsWEB_CONCURRENCYenvironment variable for worker processes (0c3e8c6f32) - Simplified server startup logging to use a single consolidated log line (b1405b71f0)
- Removed
gunicornas an external dependency - server functionality is now built into plain core (cb6c2f484d) - Internal server environment variables renamed from
GUNICORN_*toPLAIN_SERVER_*(745c073123) - Removed unused server features including hooks, syslog, proxy protocol, user/group dropping, and config file loading (be0f82d92b, 10c206875b, ecf327014c, fb5a10f50b)
Upgrade instructions
- Replace any direct usage of
gunicornwith the newplain servercommand (ex.gunicorn plain.wsgi:app --workers 4becomesplain server --workers 4) - Update any deployment scripts or Procfiles that use
gunicornto useplain serverinstead - Remove
gunicornfrom your project dependencies if you added it separately (it's now built into plain) - For Heroku deployments, the
$PORTis not automatically detected - update your Procfile toweb: plain server --bind 0.0.0.0:$PORT - If you were using gunicorn configuration files, migrate the settings to
plain servercommand-line options (runplain server --helpto see available options)
0.75.0 (2025-10-10)
What's changed
- Documentation references updated from
plain-workertoplain-jobsfollowing the package rename (24219856e0)
Upgrade instructions
- No changes required
0.74.0 (2025-10-08)
What's changed
- The
plain agent requestcommand now displays request ID in the response output (4a20cfa3fc) - Request headers are now included in OpenTelemetry tracing baggage for improved observability (08a3376d06)
Upgrade instructions
- No changes required
0.73.0 (2025-10-07)
What's changed
- Internal preflight result handling updated to use
model_optionsinstead of_metafor model label retrieval (73ba469)
Upgrade instructions
- No changes required
0.72.2 (2025-10-06)
What's changed
- Improved type annotations for test client responses with new
ClientResponsewrapper class (369353f9d6) - Enhanced internal type checking for WSGI handler and request/response types (50463b00c3)
Upgrade instructions
- No changes required
0.72.1 (2025-10-02)
What's changed
- Fixed documentation examples to use the correct view attribute names (
self.userinstead ofself.request.user) (f6278d9)
Upgrade instructions
- No changes required
0.72.0 (2025-10-02)
What's changed
- Request attributes
userandsessionare no longer set directly on the request object (154ee10) - Test client now uses
plain.auth.requests.get_request_user()to retrieve user for response object when available (154ee10) - Removed
plain.auth.middleware.AuthenticationMiddlewarefrom default middleware configuration (154ee10)
Upgrade instructions
- No changes required
0.71.0 (2025-09-30)
What's changed
- Renamed
HttpRequesttoRequestthroughout the codebase for consistency and simplicity (cd46ff20) - Renamed
HttpHeaderstoRequestHeadersfor naming consistency (cd46ff20) - Renamed settings:
APP_NAME→NAME,APP_VERSION→VERSION,APP_LOG_LEVEL→LOG_LEVEL,APP_LOG_FORMAT→LOG_FORMAT,PLAIN_LOG_LEVEL→FRAMEWORK_LOG_LEVEL(4c5f2166) - Added
request.get_preferred_type()method to select the most preferred media type from Accept header (b105ba4d) - Moved helper functions in
http/request.pyto be static methods ofQueryDict(0e1b0133)
Upgrade instructions
- Replace all imports and usage of
HttpRequestwithRequest - Replace all imports and usage of
HttpHeaderswithRequestHeaders - Update any custom settings that reference
APP_NAMEtoNAME,APP_VERSIONtoVERSION,APP_LOG_LEVELtoLOG_LEVEL,APP_LOG_FORMATtoLOG_FORMAT, andPLAIN_LOG_LEVELtoFRAMEWORK_LOG_LEVEL - Configuring these settings via the
PLAIN_prefixed environment variable will need to be updated accordingly
0.70.0 (2025-09-30)
What's changed
- Added comprehensive type annotations throughout the codebase for improved IDE support and type checking (365414c)
- The
Assetclass inplain.assets.findersis now a module-level public class instead of being defined insideiter_assets()(6321765)
Upgrade instructions
- No changes required
0.69.0 (2025-09-29)
What's changed
- Model-related exceptions (
FieldDoesNotExist,FieldError,ObjectDoesNotExist,MultipleObjectsReturned,EmptyResultSet,FullResultSet) moved fromplain.exceptionstoplain.models.exceptions(1c02564) - Added
plain devalias prompt that suggests addingpas a shell alias for convenience (d913b44)
Upgrade instructions
- Replace imports of
FieldDoesNotExist,FieldError,ObjectDoesNotExist,MultipleObjectsReturned,EmptyResultSet, orFullResultSetfromplain.exceptionstoplain.models.exceptions - If you're using
ObjectDoesNotExistin views, update your import fromplain.exceptions.ObjectDoesNotExisttoplain.models.exceptions.ObjectDoesNotExist
0.68.1 (2025-09-25)
What's changed
- Preflight checks are now sorted by name for consistent ordering (cb8e160)
Upgrade instructions
- No changes required
0.68.0 (2025-09-25)
What's changed
- Major refactor of the preflight check system with new CLI commands and improved output (b0b610d461)
- Preflight checks now use descriptive IDs instead of numeric codes (cd96c97b25)
- Unified preflight error messages and hints into a single
fixfield (c7cde12149) - Added
plain-upgradeas a standalone command for upgrading Plain packages (42f2eed80c)
Upgrade instructions
- Update any uses of the
plain preflightcommand toplain preflight check, and remove the--databaseand--fail-leveloptions which no longer exist - Custom preflight checks should be class based, extending
PreflightCheckand implementing therun()method - Preflight checks need to be registered with a custom name (ex.
@register_check("app.my_custom_check")) and optionally withdeploy=Trueif it should run in only in deploy mode - Preflight results should use
PreflightResult(optionally withwarning=True) instead ofpreflight.Warningorpreflight.Error - Preflight result IDs should be descriptive strings (e.g.,
models.lazy_reference_resolution_failed) instead of numeric codes PREFLIGHT_SILENCED_CHECKSsetting has been replaced withPREFLIGHT_SILENCED_RESULTSwhich should contain a list of result IDs to silence.PREFLIGHT_SILENCED_CHECKSnow silences entire checks by name.
0.67.0 (2025-09-22)
What's changed
ALLOWED_HOSTSnow defaults to[](empty list) which allows all hosts, making it easier for development setups (d3cb7712b9)- Empty
ALLOWED_HOSTSin production now triggers a preflight error instead of a warning to ensure proper security configuration (d3cb7712b9)
Upgrade instructions
- No changes required
0.66.0 (2025-09-22)
What's changed
- Host validation moved to dedicated middleware and
ALLOWED_HOSTSsetting is now required (6a4b7be) - Changed
request.get_port()method torequest.portcached property (544f3e1) - Removed internal
request._get_full_path()method (50cdb58)
Upgrade instructions
- Add
ALLOWED_HOSTSsetting to your configuration if not already present (required for host validation) - Replace any usage of
request.get_host()withrequest.host - Replace any usage of
request.get_port()withrequest.port
0.65.1 (2025-09-22)
What's changed
- Fixed DisallowedHost exception handling in request span attributes to prevent telemetry errors (bcc0005)
- Removed cached property optimization for scheme/host to improve request processing reliability (3a52690)
Upgrade instructions
- No changes required
0.65.0 (2025-09-22)
What's changed
- Added CIDR notation support to
ALLOWED_HOSTSfor IP address range validation (c485d21)
Upgrade instructions
- No changes required
0.64.0 (2025-09-19)
What's changed
- Added
plain-buildcommand as a standalone executable (4b39ca4) - Removed
constant_time_compareutility function in favor ofhmac.compare_digest(55f3f55) - CLI now forces colors in CI environments (GitHub Actions, GitLab CI, etc.) for better output visibility (56f7d2b)
Upgrade instructions
- Replace any usage of
plain.utils.crypto.constant_time_comparewithhmac.compare_digestorsecrets.compare_digest
0.63.0 (2025-09-12)
What's changed
- Model manager attribute renamed from
objectstoquerythroughout codebase (037a239) - Simplified HTTPS redirect middleware by removing
HTTPS_REDIRECT_EXEMPT_PATHSandHTTPS_REDIRECT_HOSTsettings (d264cd3) - Database backups are now created automatically during migrations when
DEBUG=Trueunless explicitly disabled (c802307)
Upgrade instructions
- Remove any
HTTPS_REDIRECT_EXEMPT_PATHSandHTTPS_REDIRECT_HOSTsettings from your configuration - the HTTPS redirect middleware now performs a blanket redirect. For advanced redirect logic, write custom middleware.
0.62.1 (2025-09-09)
What's changed
- Added clarification about
app_logger.kvremoval to 0.62.0 changelog (106636f)
Upgrade instructions
- No changes required
0.62.0 (2025-09-09)
What's changed
- Complete rewrite of logging settings and AppLogger with improved formatters and debug capabilities (ea7c953)
- Added
app_logger.debug_mode()context manager to temporarily change log level (f535459) - Minimum Python version updated to 3.13 (d86e307)
- Removed
app_logger.kvin favor of context kwargs (ea7c953)
Upgrade instructions
- Make sure you are using Python 3.13 or higher
- Replace any
app_logger.kv.info("message", key=value)calls withapp_logger.info("message", key=value)or appropriate log level
0.61.0 (2025-09-03)
What's changed
- Added new
plain agentcommand with subcommands for coding agents includingdocs,md, andrequest(df3edbf) - Added
-coption toplain shellto execute commands and exit, similar topython -c(5e67f0b) - The
plain docs --llmfunctionality has been moved toplain agent docscommand (df3edbf) - Removed the
plain helpcommand in favor of standardplain --help(df3edbf)
Upgrade instructions
- Replace
plain docs --llmusage withplain agent docscommand - Use
plain --helpinstead ofplain helpcommand
0.60.0 (2025-08-27)
What's changed
- Added new
APP_VERSIONsetting that defaults to the project version frompyproject.toml(57fb948d46) - Updated
get_app_name_from_pyproject()toget_app_info_from_pyproject()to return both name and version (57fb948d46)
Upgrade instructions
- No changes required
0.59.0 (2025-08-22)
What's changed
- Added new
APP_NAMEsetting that defaults to the project name frompyproject.toml(1a4d60e) - Template views now validate that
get_template_names()returns a list instead of a string (428a64f) - Object views now use cached properties for
.objectand.objectsto improve performance (bd0507a) - Improved
plain upgradecommand to suggest using subagents when there are more than 3 package updates (497c30d)
Upgrade instructions
- In object views,
self.load_object()is no longer necessary asself.objectis now a cached property.
0.58.0 (2025-08-19)
What's changed
- Complete rewrite of CSRF protection using modern Sec-Fetch-Site headers and origin validation (955150800c)
- Replaced CSRF view mixin with path-based exemptions using
CSRF_EXEMPT_PATHSsetting (2a50a9154e) - Renamed
HTTPS_REDIRECT_EXEMPTtoHTTPS_REDIRECT_EXEMPT_PATHSwith leading slash requirement (b53d3bb7a7) - Agent commands now print prompts directly when running in Claude Code or Codex Sandbox environments (6eaed8ae3b)
Upgrade instructions
- Remove any usage of
CsrfExemptViewMixinandrequest.csrf_exemptand add exempt paths to theCSRF_EXEMPT_PATHSsetting instead (ex.CSRF_EXEMPT_PATHS = [r"^/api/", r"/webhooks/.*"]-- but consider first whether the view still needs CSRF exemption under the new implementation) - Replace
HTTPS_REDIRECT_EXEMPTwithHTTPS_REDIRECT_EXEMPT_PATHSand ensure patterns include leading slash (ex.[r"^/health$", r"/api/internal/.*"]) - Remove all CSRF cookie and token related settings - the new implementation doesn't use cookies or tokens (ex.
{{ csrf_input }}and{{ csrf_token }})
0.57.0 (2025-08-15)
What's changed
- The
ResponsePermanentRedirectclass has been removed; useResponseRedirectwithstatus_code=301instead (d5735ea) - The
RedirectView.permanentattribute has been replaced withstatus_codefor more flexible redirect status codes (12dda16) - Updated
RedirectViewinitialization parameters:url_namereplacespattern_name,preserve_query_paramsreplacesquery_string, and removed 410 Gone functionality (3b9ca71)
Upgrade instructions
- Replace
ResponsePermanentRedirectimports withResponseRedirectand passstatus_code=301to the constructor - Update
RedirectViewsubclasses to usestatus_code=301instead ofpermanent=True - Replace
pattern_namewithurl_namein RedirectView usage - Replace
query_string=Truewithpreserve_query_params=Truein RedirectView usage
0.56.1 (2025-07-30)
What's changed
- Improved
plain installcommand instructions to be more explicit about completing code modifications (83292225db)
Upgrade instructions
- No changes required
0.56.0 (2025-07-25)
What's changed
- Added
plain installcommand to install Plain packages with agent-assisted setup (bf1873e) - Added
--printoption to agent commands (plain installandplain upgrade) to print prompts without running the agent (9721331) - The
plain docscommand now automatically converts hyphens to dots in package names (e.g.,plain-models→plain.models) (1e3edc1) - Moved
plain-upgradefunctionality into plain core, eliminating the need for a separate package (473f9bb)
Upgrade instructions
- No changes required
0.55.0 (2025-07-22)
What's changed
- Updated URL pattern documentation examples to use
idinstead ofpkin URL kwargs (b656ee6) - Updated views documentation examples to use
idinstead ofpkfor DetailView, UpdateView, and DeleteView (b656ee6)
Upgrade instructions
- Update your URL patterns from
<int:pk>to<int:id>in your URLconf - Update view code that accesses
self.url_kwargs["pk"]to useself.url_kwargs["id"]instead - Replace any QuerySet filters using
pkwithid(e.g.,Model.query.get(pk=1)becomesModel.query.get(id=1))
0.54.1 (2025-07-20)
What's changed
- Fixed OpenTelemetry route naming to include leading slash for consistency with HTTP paths (9d77268)
Upgrade instructions
- No changes required
0.54.0 (2025-07-18)
What's changed
- Added OpenTelemetry instrumentation for HTTP requests, views, and template rendering (b0224d0418)
- Added
plain-observerpackage reference to plain README (f29ff4dafe)
Upgrade instructions
- No changes required
0.53.0 (2025-07-18)
What's changed
- Added a
pluralizefilter for Jinja templates to handle singular/plural forms (4cef9829ed) - Added
get_signed_cookie()method toHttpRequestfor retrieving and verifying signed cookies (f8796c8786) - Improved CLI error handling by using
click.UsageErrorinstead of manual error printing (88f06c5184) - Simplified preflight check success message (adffc06152)
Upgrade instructions
- No changes required
0.52.2 (2025-06-27)
What's changed
- Improved documentation for the assets subsystem: the
AssetsRouterreference in the Assets README now links directly to the source code for quicker navigation (65437e9)
Upgrade instructions
- No changes required
0.52.1 (2025-06-27)
What's changed
- Fixed
plain helpoutput on newer versions of Click by switching fromMultiCommandtoGroupwhen determining sub-commands (9482e42)
Upgrade instructions
- No changes required
0.52.0 (2025-06-26)
What's changed
- Added
plain-changelogas a standalone executable so you can view changelogs without importing the full framework (e4e7324) - Removed the runtime dependency on the
packaginglibrary by replacing it with an internal version-comparison helper (e4e7324) - Improved the error message when a package changelog cannot be found, now showing the path that was looked up (f3c82bb)
- Fixed an f-string issue that broke
plain.debug.ddon Python 3.11 (ed24276)
Upgrade instructions
- No changes required
0.51.0 (2025-06-24)
What's changed
- New
plain changelogCLI sub-command to quickly view a package’s changelog from the terminal. Supports--from/--toflags to limit the version range (50f0de7).
Upgrade instructions
- No changes required
0.50.0 (2025-06-23)
What's changed
- The URL inspection command has moved; run
plain urls listinstead of the oldplain urlscommand (6146fcb) plain preflightgains a simpler--databaseflag that enables database checks for your default database. The previous behaviour that accepted one or more database aliases has been removed (d346d81)- Settings overhaul: use a single
DATABASEsetting instead ofDATABASES/DATABASE_ROUTERS(d346d81)
Upgrade instructions
Update any scripts or documentation that call
plain urls …:- Replace
plain urls --flatwithplain urls list --flat
- Replace
If you invoke preflight checks in CI or locally:
- Replace
plain preflight --database <alias>(or multiple aliases) with the new boolean flag:plain preflight --database
- Replace
In
settings.pymigrate to the new database configuration:# Before DATABASES = { "default": { "ENGINE": "plain.backends.sqlite3", "NAME": BASE_DIR / "db.sqlite3", } } # After DATABASE = { "ENGINE": "plain.backends.sqlite3", "NAME": BASE_DIR / "db.sqlite3", }Remove any
DATABASESandDATABASE_ROUTERSsettings – they are no longer read.