tina4-python 3.13.53__tar.gz → 3.13.54__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. {tina4_python-3.13.53 → tina4_python-3.13.54}/PKG-INFO +1 -1
  2. {tina4_python-3.13.53 → tina4_python-3.13.54}/pyproject.toml +1 -1
  3. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/migration/runner.py +48 -6
  4. {tina4_python-3.13.53 → tina4_python-3.13.54}/.gitignore +0 -0
  5. {tina4_python-3.13.53 → tina4_python-3.13.54}/README.md +0 -0
  6. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/CLAUDE.md +0 -0
  7. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/HtmlElement.py +0 -0
  8. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/Testing.py +0 -0
  9. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/__init__.py +0 -0
  10. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/ai/__init__.py +0 -0
  11. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/api/__init__.py +0 -0
  12. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/auth/__init__.py +0 -0
  13. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/cache/__init__.py +0 -0
  14. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/cli/__init__.py +0 -0
  15. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/container/__init__.py +0 -0
  16. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/core/__init__.py +0 -0
  17. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/core/cache.py +0 -0
  18. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/core/constants.py +0 -0
  19. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/core/events.py +0 -0
  20. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/core/middleware.py +0 -0
  21. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/core/rate_limiter.py +0 -0
  22. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/core/request.py +0 -0
  23. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/core/response.py +0 -0
  24. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/core/router.py +0 -0
  25. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/core/server.py +0 -0
  26. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/crud/__init__.py +0 -0
  27. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/database/__init__.py +0 -0
  28. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/database/adapter.py +0 -0
  29. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/database/connection.py +0 -0
  30. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/database/firebird.py +0 -0
  31. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/database/mongodb.py +0 -0
  32. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/database/mssql.py +0 -0
  33. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/database/mysql.py +0 -0
  34. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/database/odbc.py +0 -0
  35. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/database/postgres.py +0 -0
  36. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/database/sqlite.py +0 -0
  37. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/debug/__init__.py +0 -0
  38. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/debug/error_overlay.py +0 -0
  39. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/dev_admin/__init__.py +0 -0
  40. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/dev_admin/metrics.py +0 -0
  41. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/dev_admin/plan.py +0 -0
  42. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/dev_admin/project_index.py +0 -0
  43. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/docs.py +0 -0
  44. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/docstore/__init__.py +0 -0
  45. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/dotenv/__init__.py +0 -0
  46. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/env.py +0 -0
  47. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/frond/FROND.md +0 -0
  48. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/frond/__init__.py +0 -0
  49. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/frond/engine.py +0 -0
  50. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/auth/meta.json +0 -0
  51. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/auth/src/routes/api/gallery_auth.py +0 -0
  52. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/database/meta.json +0 -0
  53. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/database/src/routes/api/gallery_db.py +0 -0
  54. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/error-overlay/meta.json +0 -0
  55. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/error-overlay/src/routes/api/gallery_crash.py +0 -0
  56. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/orm/meta.json +0 -0
  57. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/orm/src/orm/Product.py +0 -0
  58. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/orm/src/routes/api/gallery_products.py +0 -0
  59. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/queue/meta.json +0 -0
  60. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/queue/src/routes/api/gallery_queue.py +0 -0
  61. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/rest-api/meta.json +0 -0
  62. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/rest-api/src/routes/api/gallery_hello.py +0 -0
  63. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/templates/meta.json +0 -0
  64. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/templates/src/routes/gallery_page.py +0 -0
  65. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/gallery/templates/src/templates/gallery_page.twig +0 -0
  66. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/graphql/__init__.py +0 -0
  67. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/i18n/__init__.py +0 -0
  68. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/mcp/__init__.py +0 -0
  69. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/mcp/protocol.py +0 -0
  70. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/mcp/tools.py +0 -0
  71. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/messenger/__init__.py +0 -0
  72. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/migration/__init__.py +0 -0
  73. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/orm/__init__.py +0 -0
  74. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/orm/fields.py +0 -0
  75. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/orm/model.py +0 -0
  76. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/__feedback/widget.js +0 -0
  77. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/css/tina4.css +0 -0
  78. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/css/tina4.min.css +0 -0
  79. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/favicon.ico +0 -0
  80. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/images/logo.svg +0 -0
  81. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/images/tina4-logo-icon.webp +0 -0
  82. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/js/frond.js +0 -0
  83. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/js/frond.min.js +0 -0
  84. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/js/tina4-dev-admin.js +0 -0
  85. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/js/tina4-dev-admin.min.js +0 -0
  86. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/js/tina4.min.js +0 -0
  87. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/js/tina4js.min.js +0 -0
  88. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/swagger/index.html +0 -0
  89. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/public/swagger/oauth2-redirect.html +0 -0
  90. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/query_builder/__init__.py +0 -0
  91. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/queue/__init__.py +0 -0
  92. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/queue/job.py +0 -0
  93. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/queue/kafka_backend.py +0 -0
  94. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/queue/lite_backend.py +0 -0
  95. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/queue/mongo_backend.py +0 -0
  96. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/queue/rabbitmq_backend.py +0 -0
  97. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/queue_backends/__init__.py +0 -0
  98. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/queue_backends/kafka_backend.py +0 -0
  99. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/queue_backends/mongo_backend.py +0 -0
  100. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/queue_backends/rabbitmq_backend.py +0 -0
  101. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/__init__.py +0 -0
  102. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_alerts.scss +0 -0
  103. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_badges.scss +0 -0
  104. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_buttons.scss +0 -0
  105. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_cards.scss +0 -0
  106. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_forms.scss +0 -0
  107. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_grid.scss +0 -0
  108. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_modals.scss +0 -0
  109. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_nav.scss +0 -0
  110. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_reset.scss +0 -0
  111. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_tables.scss +0 -0
  112. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_typography.scss +0 -0
  113. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_utilities.scss +0 -0
  114. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/_variables.scss +0 -0
  115. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/base.scss +0 -0
  116. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/colors.scss +0 -0
  117. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/scss/tina4css/tina4.scss +0 -0
  118. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/seeder/__init__.py +0 -0
  119. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/service/__init__.py +0 -0
  120. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/session/__init__.py +0 -0
  121. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/session_handlers/__init__.py +0 -0
  122. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/session_handlers/mongodb_handler.py +0 -0
  123. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/session_handlers/redis_handler.py +0 -0
  124. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/session_handlers/valkey_handler.py +0 -0
  125. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/swagger/__init__.py +0 -0
  126. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/components/crud.twig +0 -0
  127. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/docker/distroless/Dockerfile +0 -0
  128. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/docker/poetry/Dockerfile +0 -0
  129. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/docker/python/Dockerfile +0 -0
  130. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/docker/uv/Dockerfile +0 -0
  131. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/errors/302.twig +0 -0
  132. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/errors/401.twig +0 -0
  133. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/errors/403.twig +0 -0
  134. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/errors/404.twig +0 -0
  135. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/errors/500.twig +0 -0
  136. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/errors/502.twig +0 -0
  137. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/errors/503.twig +0 -0
  138. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/errors/base.twig +0 -0
  139. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/frontend/README.md +0 -0
  140. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/templates/readme.md +0 -0
  141. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/test/__init__.py +0 -0
  142. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/test_client/__init__.py +0 -0
  143. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/af/LC_MESSAGES/messages.mo +0 -0
  144. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/af/LC_MESSAGES/messages.po +0 -0
  145. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
  146. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
  147. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/es/LC_MESSAGES/messages.mo +0 -0
  148. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/es/LC_MESSAGES/messages.po +0 -0
  149. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
  150. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
  151. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/ja/LC_MESSAGES/messages.mo +0 -0
  152. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/ja/LC_MESSAGES/messages.po +0 -0
  153. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/zh/LC_MESSAGES/messages.mo +0 -0
  154. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/translations/zh/LC_MESSAGES/messages.po +0 -0
  155. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/validator/__init__.py +0 -0
  156. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/websocket/__init__.py +0 -0
  157. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/websocket/backplane.py +0 -0
  158. {tina4_python-3.13.53 → tina4_python-3.13.54}/tina4_python/wsdl/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tina4-python
3
- Version: 3.13.53
3
+ Version: 3.13.54
4
4
  Summary: Tina4 Python v3 — Zero-dependency, lightweight web framework
5
5
  Author-email: Andre van Zuydam <andrevanzuydam@gmail.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tina4-python"
3
- version = "3.13.53"
3
+ version = "3.13.54"
4
4
  description = "Tina4 Python v3 — Zero-dependency, lightweight web framework"
5
5
  authors = [
6
6
  {name = "Andre van Zuydam", email = "andrevanzuydam@gmail.com"}
@@ -192,6 +192,16 @@ def _upgrade_v2_to_v3(db, migration_folder: str | None) -> None:
192
192
  "Detected legacy v2 tina4_migration schema — performing in-place upgrade to v3"
193
193
  )
194
194
 
195
+ # A v2 table has no id generator; on Firebird, ids for rows recorded after
196
+ # the upgrade come from GEN_TINA4_MIGRATION_ID (see _record_migration), so
197
+ # make sure it exists. Fresh v3 tables get it in _create_v3_table.
198
+ if _is_firebird(db):
199
+ try:
200
+ db.execute("CREATE GENERATOR GEN_TINA4_MIGRATION_ID")
201
+ db.commit()
202
+ except Exception:
203
+ pass # Generator may already exist
204
+
195
205
  cols = _column_names(db)
196
206
 
197
207
  if "migration_id" not in cols:
@@ -331,6 +341,27 @@ def _normalize_quotes(sql: str) -> str:
331
341
  return _SMART_QUOTE_RE.sub(lambda m: _SMART_QUOTES[m.group(0)], sql)
332
342
 
333
343
 
344
+ _SET_TERM_RE = re.compile(r"^SET\s+TERM\s+(\S+)$", re.IGNORECASE)
345
+
346
+
347
+ def _parse_set_term(statement: str) -> str | None:
348
+ """Return the new terminator from a ``SET TERM <new> <current>`` directive.
349
+
350
+ ``SET TERM`` is a script-level directive (recognised by isql and other
351
+ InterBase/Firebird tooling, not run by the engine) that changes the
352
+ terminator separating statements. Recognising it lets a statement whose own
353
+ body contains the default ``;`` terminator — a trigger, stored procedure or
354
+ ``EXECUTE BLOCK`` — be kept intact rather than split on those inner ``;``.
355
+ The terminator may be more than one character (e.g. ``!!``).
356
+
357
+ :param statement: A single, already-stripped statement.
358
+ :returns: The new terminator, or ``None`` when *statement* is not a
359
+ ``SET TERM`` directive.
360
+ """
361
+ match = _SET_TERM_RE.match(statement.strip())
362
+ return match.group(1) if match else None
363
+
364
+
334
365
  def _split_statements(sql: str, delimiter: str = ";") -> list[str]:
335
366
  """Split SQL into individual statements with a single-pass, quote- and
336
367
  comment-aware scanner.
@@ -356,6 +387,10 @@ def _split_statements(sql: str, delimiter: str = ";") -> list[str]:
356
387
  a delimiter or comment, so it is preserved untouched.
357
388
  - The **delimiter** ends a statement only when reached outside all of the
358
389
  above. Empty statements are dropped; each kept statement is trimmed.
390
+ - A **SET TERM directive** (``SET TERM <new> <current>``) switches the active
391
+ terminator and is consumed, never emitted, so a statement whose own body
392
+ contains the default terminator survives as one. Multi-character
393
+ terminators (e.g. ``!!``) are supported.
359
394
 
360
395
  Smart/curly quotes are normalized to straight ASCII first. Mirrors the
361
396
  tina4-php ``Migration::splitStatements`` scanner for cross-framework parity.
@@ -367,7 +402,6 @@ def _split_statements(sql: str, delimiter: str = ";") -> list[str]:
367
402
  statements: list[str] = []
368
403
  current: list[str] = []
369
404
  n = len(sql)
370
- dlen = len(delimiter)
371
405
  i = 0
372
406
  in_dollar_block = False
373
407
  in_slash_block = False
@@ -448,20 +482,28 @@ def _split_statements(sql: str, delimiter: str = ";") -> list[str]:
448
482
  i += 1
449
483
  continue
450
484
 
451
- # Statement delimiter — only reached outside blocks/comments/strings.
485
+ # Statement delimiter — only reached outside blocks/comments/strings. A
486
+ # SET TERM directive switches the active terminator and is consumed
487
+ # (never emitted); any other completed statement is collected.
452
488
  if delimiter and sql.startswith(delimiter, i):
489
+ i += len(delimiter)
453
490
  stmt = "".join(current).strip()
454
- if stmt:
455
- statements.append(stmt)
456
491
  current = []
457
- i += dlen
492
+ if stmt:
493
+ new_term = _parse_set_term(stmt)
494
+ if new_term is not None:
495
+ delimiter = new_term
496
+ else:
497
+ statements.append(stmt)
458
498
  continue
459
499
 
460
500
  current.append(ch)
461
501
  i += 1
462
502
 
503
+ # Trailing statement (may not end with a delimiter). A trailing SET TERM
504
+ # directive is a no-op — consume it, don't emit it.
463
505
  stmt = "".join(current).strip()
464
- if stmt:
506
+ if stmt and _parse_set_term(stmt) is None:
465
507
  statements.append(stmt)
466
508
  return statements
467
509
 
File without changes