tai-sql 0.6.37__tar.gz → 0.7.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.
Files changed (261) hide show
  1. tai_sql-0.7.0/PKG-INFO +254 -0
  2. tai_sql-0.7.0/README.md +193 -0
  3. tai_sql-0.7.0/pyproject.toml +171 -0
  4. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/__init__.py +17 -4
  5. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/__init__.py +4 -2
  6. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_backup/main.py +28 -11
  7. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_deploy/config.py +1 -1
  8. tai_sql-0.7.0/tai_sql/cli/commands/cmd_deploy/local.py +193 -0
  9. tai_sql-0.7.0/tai_sql/cli/commands/cmd_feed/main.py +152 -0
  10. tai_sql-0.7.0/tai_sql/cli/commands/cmd_generate/funcs.py +70 -0
  11. tai_sql-0.7.0/tai_sql/cli/commands/cmd_generate/main.py +21 -0
  12. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_info/main.py +18 -7
  13. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_init/main.py +12 -2
  14. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_init/model.py +53 -8
  15. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_install/main.py +104 -52
  16. tai_sql-0.7.0/tai_sql/cli/commands/cmd_ping/main.py +63 -0
  17. tai_sql-0.7.0/tai_sql/cli/commands/cmd_pull/__init__.py +3 -0
  18. tai_sql-0.7.0/tai_sql/cli/commands/cmd_pull/funcs.py +232 -0
  19. tai_sql-0.7.0/tai_sql/cli/commands/cmd_pull/main.py +157 -0
  20. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_restore/main.py +59 -21
  21. tai_sql-0.7.0/tai_sql/cli/commands/cmd_rules/__init__.py +3 -0
  22. tai_sql-0.7.0/tai_sql/cli/commands/cmd_rules/main.py +250 -0
  23. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_schema/model.py +10 -2
  24. tai_sql-0.7.0/tai_sql/cli/commands/cmd_schema/new.py +37 -0
  25. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_schema/schemas/auth.py +9 -6
  26. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_schema/schemas/chatbot.py +1 -1
  27. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_schema/schemas/default.py +1 -1
  28. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_schema/set_default.py +32 -28
  29. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/utils/connectivity.py +25 -17
  30. tai_sql-0.7.0/tai_sql/cli/commands/utils/create.py +125 -0
  31. tai_sql-0.7.0/tai_sql/cli/errors.py +131 -0
  32. tai_sql-0.7.0/tai_sql/cli/main.py +66 -0
  33. tai_sql-0.7.0/tai_sql/cli/preamble.py +121 -0
  34. tai_sql-0.7.0/tai_sql/cli/services/__init__.py +20 -0
  35. tai_sql-0.7.0/tai_sql/connection/README.md +125 -0
  36. tai_sql-0.7.0/tai_sql/connection/__init__.py +39 -0
  37. {tai_sql-0.6.37/tai_sql/core → tai_sql-0.7.0/tai_sql/connection}/provider.py +175 -118
  38. tai_sql-0.7.0/tai_sql/connection/recipe.py +153 -0
  39. tai_sql-0.7.0/tai_sql/connection/session.py +101 -0
  40. tai_sql-0.7.0/tai_sql/connection/sources.py +110 -0
  41. tai_sql-0.7.0/tai_sql/crypto.py +61 -0
  42. tai_sql-0.7.0/tai_sql/drivers/__init__.py +35 -0
  43. tai_sql-0.7.0/tai_sql/drivers/base.py +1518 -0
  44. tai_sql-0.7.0/tai_sql/drivers/bigquery.py +703 -0
  45. tai_sql-0.7.0/tai_sql/drivers/capabilities.py +52 -0
  46. tai_sql-0.7.0/tai_sql/drivers/mysql.py +435 -0
  47. tai_sql-0.7.0/tai_sql/drivers/postgresql.py +672 -0
  48. tai_sql-0.7.0/tai_sql/drivers/sqlserver.py +467 -0
  49. tai_sql-0.7.0/tai_sql/errors/README.md +139 -0
  50. tai_sql-0.7.0/tai_sql/errors/__init__.py +45 -0
  51. tai_sql-0.7.0/tai_sql/errors/collector.py +131 -0
  52. tai_sql-0.7.0/tai_sql/errors/render.py +245 -0
  53. tai_sql-0.7.0/tai_sql/errors/types.py +192 -0
  54. tai_sql-0.7.0/tai_sql/feed/README.md +138 -0
  55. tai_sql-0.7.0/tai_sql/feed/__init__.py +34 -0
  56. tai_sql-0.7.0/tai_sql/feed/collect.py +289 -0
  57. tai_sql-0.7.0/tai_sql/feed/executor.py +402 -0
  58. tai_sql-0.7.0/tai_sql/feed/feeder.py +208 -0
  59. tai_sql-0.7.0/tai_sql/feed/plan.py +127 -0
  60. tai_sql-0.7.0/tai_sql/feed/presenter.py +103 -0
  61. tai_sql-0.7.0/tai_sql/feed/records.py +145 -0
  62. tai_sql-0.7.0/tai_sql/feed/transform.py +162 -0
  63. tai_sql-0.7.0/tai_sql/generators/base.py +181 -0
  64. tai_sql-0.7.0/tai_sql/generators/diagram/README.md +120 -0
  65. tai_sql-0.7.0/tai_sql/generators/diagram/__init__.py +93 -0
  66. tai_sql-0.7.0/tai_sql/generators/diagram/assets/README.md +26 -0
  67. tai_sql-0.7.0/tai_sql/generators/diagram/assets/cytoscape.min.js +32 -0
  68. tai_sql-0.7.0/tai_sql/generators/diagram/builder.py +306 -0
  69. tai_sql-0.7.0/tai_sql/generators/diagram/generator.py +361 -0
  70. tai_sql-0.7.0/tai_sql/generators/diagram/graphviz_render.py +545 -0
  71. tai_sql-0.7.0/tai_sql/generators/diagram/html_render.py +221 -0
  72. tai_sql-0.7.0/tai_sql/generators/diagram/layout.py +150 -0
  73. tai_sql-0.7.0/tai_sql/generators/diagram/model.py +251 -0
  74. tai_sql-0.7.0/tai_sql/generators/diagram/templates/er.html.jinja2 +1356 -0
  75. tai_sql-0.7.0/tai_sql/generators/diagram/themes.py +191 -0
  76. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/__init__.py +109 -72
  77. tai_sql-0.7.0/tai_sql/generators/python_client/calculated.py +197 -0
  78. tai_sql-0.7.0/tai_sql/generators/python_client/context.py +499 -0
  79. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/domain/dao.py.jinja2 +13 -9
  80. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/domain/dtos.py.jinja2 +28 -13
  81. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/domain/model.py.jinja2 +33 -4
  82. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/facade.py.jinja2 +2 -2
  83. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/macros/dataframe.jinja2 +9 -47
  84. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/macros/read.jinja2 +15 -6
  85. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/macros/upsert.jinja2 +54 -22
  86. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/macros/vector.jinja2 +20 -11
  87. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/macros/write.jinja2 +45 -11
  88. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/session.py.jinja2 +69 -58
  89. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/shared/utils/rls.py.jinja2 +32 -8
  90. tai_sql-0.7.0/tai_sql/generators/python_client/triggers/__init__.py +32 -0
  91. tai_sql-0.7.0/tai_sql/generators/python_client/triggers/analyzer.py +236 -0
  92. tai_sql-0.7.0/tai_sql/generators/python_client/triggers/renderer.py +204 -0
  93. tai_sql-0.7.0/tai_sql/generators/python_client/triggers/steps.py +76 -0
  94. tai_sql-0.7.0/tai_sql/generators/python_client/triggers/transformer.py +688 -0
  95. tai_sql-0.7.0/tai_sql/generators/rules/__init__.py +389 -0
  96. tai_sql-0.7.0/tai_sql/generators/rules/templates/schema.md.jinja2 +154 -0
  97. tai_sql-0.7.0/tai_sql/introspect/README.md +116 -0
  98. tai_sql-0.7.0/tai_sql/introspect/__init__.py +60 -0
  99. tai_sql-0.7.0/tai_sql/introspect/blueprint.py +265 -0
  100. tai_sql-0.7.0/tai_sql/introspect/build.py +712 -0
  101. tai_sql-0.7.0/tai_sql/introspect/defaults.py +142 -0
  102. tai_sql-0.7.0/tai_sql/introspect/naming.py +187 -0
  103. tai_sql-0.7.0/tai_sql/introspect/reader.py +107 -0
  104. tai_sql-0.7.0/tai_sql/introspect/templates/schema.py.jinja2 +97 -0
  105. tai_sql-0.7.0/tai_sql/introspect/types.py +143 -0
  106. tai_sql-0.7.0/tai_sql/introspect/writer.py +259 -0
  107. tai_sql-0.7.0/tai_sql/orm/README.md +88 -0
  108. tai_sql-0.7.0/tai_sql/orm/__init__.py +85 -0
  109. tai_sql-0.7.0/tai_sql/orm/analysis/README.md +118 -0
  110. tai_sql-0.7.0/tai_sql/orm/analysis/__init__.py +35 -0
  111. tai_sql-0.7.0/tai_sql/orm/analysis/calculated.py +152 -0
  112. tai_sql-0.7.0/tai_sql/orm/analysis/collector.py +27 -0
  113. tai_sql-0.7.0/tai_sql/orm/analysis/column_analyzer.py +296 -0
  114. tai_sql-0.7.0/tai_sql/orm/analysis/constraints.py +232 -0
  115. tai_sql-0.7.0/tai_sql/orm/analysis/hints.py +159 -0
  116. tai_sql-0.7.0/tai_sql/orm/analysis/relation_analyzer.py +315 -0
  117. tai_sql-0.7.0/tai_sql/orm/analysis/schema_analyzer.py +420 -0
  118. tai_sql-0.7.0/tai_sql/orm/declarative/README.md +135 -0
  119. tai_sql-0.7.0/tai_sql/orm/declarative/__init__.py +87 -0
  120. {tai_sql-0.6.37/tai_sql/orm → tai_sql-0.7.0/tai_sql/orm/declarative}/annotations.py +0 -56
  121. tai_sql-0.7.0/tai_sql/orm/declarative/base.py +139 -0
  122. {tai_sql-0.6.37/tai_sql/orm → tai_sql-0.7.0/tai_sql/orm/declarative}/calculated.py +55 -231
  123. {tai_sql-0.6.37/tai_sql/orm → tai_sql-0.7.0/tai_sql/orm/declarative}/columns.py +54 -169
  124. tai_sql-0.7.0/tai_sql/orm/declarative/constraints.py +163 -0
  125. tai_sql-0.7.0/tai_sql/orm/declarative/datasource.py +333 -0
  126. {tai_sql-0.6.37/tai_sql/orm → tai_sql-0.7.0/tai_sql/orm/declarative}/descriptors.py +6 -58
  127. tai_sql-0.7.0/tai_sql/orm/declarative/enumerations.py +107 -0
  128. tai_sql-0.7.0/tai_sql/orm/declarative/relations.py +108 -0
  129. tai_sql-0.7.0/tai_sql/orm/declarative/table.py +92 -0
  130. tai_sql-0.7.0/tai_sql/orm/declarative/trigger_api.py +505 -0
  131. tai_sql-0.7.0/tai_sql/orm/declarative/triggers.py +482 -0
  132. tai_sql-0.7.0/tai_sql/orm/declarative/view.py +77 -0
  133. tai_sql-0.7.0/tai_sql/orm/mapping/README.md +67 -0
  134. tai_sql-0.7.0/tai_sql/orm/mapping/__init__.py +23 -0
  135. tai_sql-0.7.0/tai_sql/orm/mapping/sqlalchemy_mapper.py +296 -0
  136. tai_sql-0.7.0/tai_sql/orm/model/README.md +97 -0
  137. tai_sql-0.7.0/tai_sql/orm/model/__init__.py +55 -0
  138. tai_sql-0.7.0/tai_sql/orm/model/column.py +158 -0
  139. tai_sql-0.7.0/tai_sql/orm/model/constraints.py +70 -0
  140. tai_sql-0.7.0/tai_sql/orm/model/entity.py +218 -0
  141. tai_sql-0.7.0/tai_sql/orm/model/enumeration.py +32 -0
  142. tai_sql-0.7.0/tai_sql/orm/model/relation.py +123 -0
  143. tai_sql-0.7.0/tai_sql/orm/model/schema.py +110 -0
  144. tai_sql-0.7.0/tai_sql/orm/model/trigger.py +59 -0
  145. tai_sql-0.7.0/tai_sql/orm/naming.py +88 -0
  146. tai_sql-0.7.0/tai_sql/orm/ordering.py +81 -0
  147. tai_sql-0.7.0/tai_sql/orm/registry.py +158 -0
  148. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/orm/types.py +15 -0
  149. tai_sql-0.7.0/tai_sql/project/README.md +71 -0
  150. tai_sql-0.7.0/tai_sql/project/__init__.py +30 -0
  151. tai_sql-0.7.0/tai_sql/project/config.py +75 -0
  152. tai_sql-0.7.0/tai_sql/project/context.py +68 -0
  153. tai_sql-0.7.0/tai_sql/project/manager.py +219 -0
  154. tai_sql-0.7.0/tai_sql/project/paths.py +149 -0
  155. tai_sql-0.7.0/tai_sql/rules/README.md +94 -0
  156. tai_sql-0.7.0/tai_sql/rules/__init__.py +91 -0
  157. tai_sql-0.7.0/tai_sql/rules/catalog.py +155 -0
  158. tai_sql-0.7.0/tai_sql/rules/installer.py +485 -0
  159. tai_sql-0.7.0/tai_sql/rules/meta.py +111 -0
  160. tai_sql-0.7.0/tai_sql/rules/service.py +129 -0
  161. tai_sql-0.7.0/tai_sql/rules/staleness.py +102 -0
  162. tai_sql-0.7.0/tai_sql/rules/static/comandos.md +277 -0
  163. tai_sql-0.7.0/tai_sql/rules/static/errores.md +189 -0
  164. tai_sql-0.7.0/tai_sql/rules/static/modelo.md +334 -0
  165. tai_sql-0.7.0/tai_sql/schema.py +437 -0
  166. tai_sql-0.7.0/tai_sql/sync/README.md +269 -0
  167. tai_sql-0.7.0/tai_sql/sync/__init__.py +136 -0
  168. tai_sql-0.7.0/tai_sql/sync/diff/__init__.py +139 -0
  169. tai_sql-0.7.0/tai_sql/sync/diff/constraints.py +263 -0
  170. tai_sql-0.7.0/tai_sql/sync/diff/indexes.py +60 -0
  171. tai_sql-0.7.0/tai_sql/sync/diff/tables.py +152 -0
  172. tai_sql-0.7.0/tai_sql/sync/diff/views.py +118 -0
  173. tai_sql-0.7.0/tai_sql/sync/executor.py +284 -0
  174. tai_sql-0.7.0/tai_sql/sync/plan/__init__.py +66 -0
  175. tai_sql-0.7.0/tai_sql/sync/plan/planner.py +555 -0
  176. tai_sql-0.7.0/tai_sql/sync/plan/statements.py +216 -0
  177. tai_sql-0.7.0/tai_sql/sync/presenter.py +263 -0
  178. tai_sql-0.7.0/tai_sql/sync/report.py +415 -0
  179. tai_sql-0.7.0/tai_sql/sync/safety.py +514 -0
  180. tai_sql-0.7.0/tai_sql/sync/state/__init__.py +53 -0
  181. tai_sql-0.7.0/tai_sql/sync/state/local.py +204 -0
  182. tai_sql-0.7.0/tai_sql/sync/state/model.py +297 -0
  183. tai_sql-0.7.0/tai_sql/sync/state/normalize.py +271 -0
  184. tai_sql-0.7.0/tai_sql/sync/state/remote.py +449 -0
  185. tai_sql-0.7.0/tai_sql/sync/synchronizer.py +211 -0
  186. tai_sql-0.6.37/PKG-INFO +0 -2484
  187. tai_sql-0.6.37/README.md +0 -2427
  188. tai_sql-0.6.37/pyproject.toml +0 -70
  189. tai_sql-0.6.37/tai_sql/cli/commands/cmd_deploy/local.py +0 -174
  190. tai_sql-0.6.37/tai_sql/cli/commands/cmd_feed/main.py +0 -103
  191. tai_sql-0.6.37/tai_sql/cli/commands/cmd_generate/funcs.py +0 -29
  192. tai_sql-0.6.37/tai_sql/cli/commands/cmd_generate/main.py +0 -24
  193. tai_sql-0.6.37/tai_sql/cli/commands/cmd_ping/main.py +0 -65
  194. tai_sql-0.6.37/tai_sql/cli/commands/cmd_roles/__init__.py +0 -1
  195. tai_sql-0.6.37/tai_sql/cli/commands/cmd_roles/main.py +0 -53
  196. tai_sql-0.6.37/tai_sql/cli/commands/cmd_schema/new.py +0 -26
  197. tai_sql-0.6.37/tai_sql/cli/commands/utils/create.py +0 -102
  198. tai_sql-0.6.37/tai_sql/cli/main.py +0 -47
  199. tai_sql-0.6.37/tai_sql/cli/services/__init__.py +0 -13
  200. tai_sql-0.6.37/tai_sql/cli/services/ddl.py +0 -961
  201. tai_sql-0.6.37/tai_sql/cli/services/drift.py +0 -674
  202. tai_sql-0.6.37/tai_sql/cli/services/feed.py +0 -849
  203. tai_sql-0.6.37/tai_sql/cli/services/keycloak.py +0 -333
  204. tai_sql-0.6.37/tai_sql/cli/services/safety.py +0 -364
  205. tai_sql-0.6.37/tai_sql/core/__init__.py +0 -12
  206. tai_sql-0.6.37/tai_sql/core/funcs.py +0 -352
  207. tai_sql-0.6.37/tai_sql/drivers/__init__.py +0 -15
  208. tai_sql-0.6.37/tai_sql/drivers/base.py +0 -422
  209. tai_sql-0.6.37/tai_sql/drivers/mysql.py +0 -328
  210. tai_sql-0.6.37/tai_sql/drivers/postgresql.py +0 -509
  211. tai_sql-0.6.37/tai_sql/drivers/sqlserver.py +0 -402
  212. tai_sql-0.6.37/tai_sql/generators/base.py +0 -136
  213. tai_sql-0.6.37/tai_sql/generators/diagram/__init__.py +0 -997
  214. tai_sql-0.6.37/tai_sql/orm/__init__.py +0 -46
  215. tai_sql-0.6.37/tai_sql/orm/base.py +0 -373
  216. tai_sql-0.6.37/tai_sql/orm/enumerations.py +0 -101
  217. tai_sql-0.6.37/tai_sql/orm/relations.py +0 -334
  218. tai_sql-0.6.37/tai_sql/orm/table.py +0 -390
  219. tai_sql-0.6.37/tai_sql/orm/triggers.py +0 -2092
  220. tai_sql-0.6.37/tai_sql/orm/view.py +0 -135
  221. tai_sql-0.6.37/tai_sql/project.py +0 -288
  222. tai_sql-0.6.37/tai_sql/schema.py +0 -304
  223. {tai_sql-0.6.37 → tai_sql-0.7.0}/LICENSE +0 -0
  224. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_backup/__init__.py +0 -0
  225. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_deploy/__init__.py +0 -0
  226. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_deploy/main.py +0 -0
  227. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_deploy/workflow.py +0 -0
  228. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_feed/__init__.py +0 -0
  229. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_generate/__init__.py +0 -0
  230. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_info/__init__.py +0 -0
  231. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_info/status.py +0 -0
  232. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_init/__init__.py +0 -0
  233. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_install/__init__.py +0 -0
  234. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_ping/__init__.py +0 -0
  235. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_restore/__init__.py +0 -0
  236. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_schema/__init__.py +0 -0
  237. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_schema/schemas/__init__.py +0 -0
  238. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/cmd_schema/schemas/base.py +0 -0
  239. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/prompts.py +0 -0
  240. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/utils/__init__.py +0 -0
  241. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/utils/github/__init__.py +0 -0
  242. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/utils/github/auth.py +0 -0
  243. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/utils/github/client.py +0 -0
  244. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/commands/utils/github/models.py +0 -0
  245. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/cli/services/backup.py +0 -0
  246. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/__init__.py +0 -0
  247. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/base.py.jinja2 +0 -0
  248. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/domain/__init__.py.jinja2 +0 -0
  249. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/macros/aggregation.jinja2 +0 -0
  250. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/macros/filters.jinja2 +0 -0
  251. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/macros/hierarchy.jinja2 +0 -0
  252. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/macros/triggers.jinja2 +0 -0
  253. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/shared/__init__.py.jinja2 +0 -0
  254. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/shared/aggregation.py.jinja2 +0 -0
  255. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/shared/context.py.jinja2 +0 -0
  256. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/shared/utils/__init__.py.jinja2 +0 -0
  257. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/shared/utils/encoders.py.jinja2 +0 -0
  258. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/shared/utils/funcs.py.jinja2 +0 -0
  259. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/shared/utils/hierarchy.py.jinja2 +0 -0
  260. {tai_sql-0.6.37 → tai_sql-0.7.0}/tai_sql/generators/python_client/templates/shared/vector.py.jinja2 +0 -0
  261. {tai_sql-0.6.37/tai_sql/orm → tai_sql-0.7.0/tai_sql/orm/declarative}/encoders.py +0 -0
tai_sql-0.7.0/PKG-INFO ADDED
@@ -0,0 +1,254 @@
1
+ Metadata-Version: 2.4
2
+ Name: tai-sql
3
+ Version: 0.7.0
4
+ Summary: SQL database management and code generation tool
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Keywords: sql,database,code-generation,orm,sqlalchemy
8
+ Author: MateoSaezMata
9
+ Author-email: msaez@triplealpha.in
10
+ Requires-Python: >=3.10,<4.0
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Database
18
+ Classifier: Topic :: Software Development :: Code Generators
19
+ Provides-Extra: all
20
+ Provides-Extra: backup
21
+ Provides-Extra: bigquery
22
+ Provides-Extra: deploy
23
+ Provides-Extra: diagrams
24
+ Provides-Extra: encryption
25
+ Provides-Extra: mysql
26
+ Provides-Extra: sqlserver
27
+ Provides-Extra: vectors
28
+ Requires-Dist: click (>=8.2.1,<9.0)
29
+ Requires-Dist: cryptography (>=45.0.4,<46.0) ; extra == "all"
30
+ Requires-Dist: cryptography (>=45.0.4,<46.0) ; extra == "encryption"
31
+ Requires-Dist: graphviz (>=0.20.3,<1.0) ; extra == "all"
32
+ Requires-Dist: graphviz (>=0.20.3,<1.0) ; extra == "diagrams"
33
+ Requires-Dist: inquirerpy (>=0.3.4,<0.4.0)
34
+ Requires-Dist: jinja2 (>=3.1.6,<4.0)
35
+ Requires-Dist: pgvector (>=0.3.0,<1.0) ; extra == "all"
36
+ Requires-Dist: pgvector (>=0.3.0,<1.0) ; extra == "vectors"
37
+ Requires-Dist: psycopg2-binary (>=2.9.10,<3.0)
38
+ Requires-Dist: pydantic (>=2.11.7,<3.0)
39
+ Requires-Dist: pymysql (>=1.1.1,<2.0) ; extra == "all"
40
+ Requires-Dist: pymysql (>=1.1.1,<2.0) ; extra == "mysql"
41
+ Requires-Dist: pynacl (>=1.5.0,<2.0) ; extra == "all"
42
+ Requires-Dist: pynacl (>=1.5.0,<2.0) ; extra == "deploy"
43
+ Requires-Dist: pyodbc (>=5.2.0,<6.0) ; extra == "all"
44
+ Requires-Dist: pyodbc (>=5.2.0,<6.0) ; extra == "sqlserver"
45
+ Requires-Dist: requests (>=2.32.4,<3.0) ; extra == "all"
46
+ Requires-Dist: requests (>=2.32.4,<3.0) ; extra == "deploy"
47
+ Requires-Dist: rich (>=15.0.0,<16.0.0)
48
+ Requires-Dist: sqlalchemy (>=2.0.42,<3.0)
49
+ Requires-Dist: sqlalchemy-bigquery (>=1.11.0,<2.0) ; extra == "all"
50
+ Requires-Dist: sqlalchemy-bigquery (>=1.11.0,<2.0) ; extra == "bigquery"
51
+ Requires-Dist: tai-alphi (>=2.0.1,<3.0) ; extra == "all"
52
+ Requires-Dist: tai-alphi (>=2.0.1,<3.0) ; extra == "backup"
53
+ Requires-Dist: tai-storage (>=0.1.0) ; extra == "all"
54
+ Requires-Dist: tai-storage (>=0.1.0) ; extra == "backup"
55
+ Project-URL: Documentation, https://triplealpha-innovation.github.io/tai-sql/
56
+ Project-URL: Homepage, https://www.triplealpha.in/es/
57
+ Project-URL: Issues, https://github.com/triplealpha-innovation/tai-sql/issues
58
+ Project-URL: Repository, https://github.com/triplealpha-innovation/tai-sql
59
+ Description-Content-Type: text/markdown
60
+
61
+ # tai-sql
62
+
63
+ [![PyPI](https://img.shields.io/pypi/v/tai-sql.svg)](https://pypi.org/project/tai-sql/)
64
+ [![Python](https://img.shields.io/pypi/pyversions/tai-sql.svg)](https://pypi.org/project/tai-sql/)
65
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
66
+ [![Manual](https://img.shields.io/badge/manual-github.io-blue.svg)](https://triplealpha-innovation.github.io/tai-sql/)
67
+
68
+ **Framework declarativo de Python, sobre SQLAlchemy, que gestiona el ciclo de vida completo de
69
+ una base de datos.** Declaras el modelo una vez, en un fichero Python, y a partir de ahí tai-sql
70
+ sincroniza la estructura de la base de datos, genera un cliente Python completo —modelos, DTOs y
71
+ DAOs síncronos y asíncronos— y dibuja el diagrama entidad-relación.
72
+
73
+ ```
74
+ schemas/public.py ──▶ tai-sql push ──▶ la base de datos se parece al schema
75
+ ──▶ tai-sql generate ──▶ cliente Python + diagrama ER
76
+ ──▶ tai-sql feed ──▶ datos iniciales
77
+ ◀── tai-sql pull ◀── una base de datos que ya existe
78
+ ```
79
+
80
+ Motores soportados: **PostgreSQL**, **MySQL**, **SQL Server** y **BigQuery**.
81
+
82
+ 📖 **[El manual completo está en triplealpha-innovation.github.io/tai-sql](https://triplealpha-innovation.github.io/tai-sql/)**
83
+
84
+ ---
85
+
86
+ ## Quickstart
87
+
88
+ ```bash
89
+ pip install tai-sql # PostgreSQL funciona sin extras
90
+ tai-sql init -n mi_proyecto -s public # crea el proyecto
91
+ cd mi_proyecto
92
+ export MAIN_DATABASE_URL="postgresql://user:pass@localhost:5432/mydb"
93
+ tai-sql install # instala lo que el cliente generado necesitará
94
+ ```
95
+
96
+ Edita `schemas/public.py`:
97
+
98
+ ```python
99
+ # -*- coding: utf-8 -*-
100
+ from __future__ import annotations
101
+ from tai_sql import *
102
+ from tai_sql.generators import *
103
+
104
+ datasource(provider=env('MAIN_DATABASE_URL'), schema='public', syntax='v2')
105
+
106
+ generate(
107
+ PythonClientGenerator(output_dir='database'),
108
+ ERDiagramGenerator(output_dir='diagrams', format='html'),
109
+ )
110
+
111
+
112
+ class Usuario(Table):
113
+ """Usuarios del sistema."""
114
+ __tablename__ = 'usuario'
115
+
116
+ id: col[int] = column(primary_key=True, autoincrement=True)
117
+ nombre: col[str]
118
+ email: col[str] = column(unique=True)
119
+ creado_en: col[datetime] = column(server_now=True)
120
+
121
+ posts: onetomany[Post]
122
+
123
+
124
+ class Post(Table):
125
+ """Posts publicados."""
126
+ __tablename__ = 'post'
127
+
128
+ id: col[bigint] = column(primary_key=True, autoincrement=True)
129
+ titulo: col[str]
130
+ contenido: col[text]
131
+ autor_id: col[int]
132
+
133
+ autor: manytoone[Usuario] = relation(fields=['autor_id'], references=['id'], backref='posts')
134
+ ```
135
+
136
+ ```bash
137
+ tai-sql push --dry-run --verbose # enseña el DDL sin ejecutar nada
138
+ tai-sql push # lo aplica y regenera el cliente
139
+ ```
140
+
141
+ Y a usarlo:
142
+
143
+ ```python
144
+ from database.public import public_sync_api, UsuarioCreate
145
+
146
+ usuario = public_sync_api.usuario.create(UsuarioCreate(nombre='Ana', email='ana@example.com'))
147
+ usuarios = public_sync_api.usuario.find_many(limit=10, includes=['posts'])
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Los cinco principios que explican el resto
153
+
154
+ 1. **El schema es la única fuente de verdad.** Todo lo demás —DDL, cliente, diagramas— es
155
+ derivado y desechable. Si el cliente generado no hace lo que necesitas, no se edita el
156
+ cliente: se arregla el schema y se regenera.
157
+ 2. **Mapear y después actuar.** Todo comando importa el schema, lo analiza y actúa sobre ese
158
+ mapeo. Ningún comando parsea el fichero por su cuenta.
159
+ 3. **El código generado nunca importa `tai_sql`.** tai-sql es una herramienta de desarrollo, no
160
+ una dependencia de producción: el cliente se despliega donde tai-sql no está instalado.
161
+ 4. **Modelo declarativo, sin migraciones versionadas.** No hay ficheros de migración: `push`
162
+ compara el estado declarado con el real y genera el DDL que hace falta.
163
+ 5. **Definición ≠ runtime.** El ORM de tai-sql *describe*; el comportamiento en producción vive
164
+ en el código generado.
165
+
166
+ ---
167
+
168
+ ## Qué trae
169
+
170
+ | | |
171
+ |---|---|
172
+ | **Schema declarativo** | Tablas, relaciones, vistas, enumerados, constraints e índices de varias columnas, columnas calculadas y jerarquías. Dos sintaxis, v1 y v2, y las dos se soportan |
173
+ | **Sincronización sin migraciones** | `push` compara y genera el DDL, clasificando cada operación en SAFE / WARNING / BLOCKED antes de tocar nada |
174
+ | **Cliente Python generado** | CRUD completo, filtros por tipo de columna, relaciones anidadas, agregaciones con GROUP BY, DataFrames, RLS, auditoría y transacciones, en síncrono y asíncrono |
175
+ | **Triggers transpilados** | Lógica de negocio declarada en el schema que se *inlinea* en los DAOs: sin coste en runtime |
176
+ | **Cifrado y vectores** | Columnas cifradas con Fernet, transparentes al leer, y columnas vectoriales con pgvector y búsqueda por similitud |
177
+ | **Diagrama ER** | Una página HTML interactiva, o una imagen con Graphviz |
178
+ | **Introspección** | `pull` escribe el schema de una base de datos que ya existe |
179
+ | **Reglas para asistentes de IA** | `rules install` deja en tu proyecto la documentación que un asistente necesita, incluida la derivada de tu schema |
180
+
181
+ ---
182
+
183
+ ## El manual
184
+
185
+ | Sección | Qué responde |
186
+ |---|---|
187
+ | [Instalación](https://triplealpha-innovation.github.io/tai-sql/empezar/instalacion/) | Qué instalar, y por qué son dos instalaciones y no una |
188
+ | [Tu primer proyecto](https://triplealpha-innovation.github.io/tai-sql/empezar/primer-proyecto/) | De cero a un cliente generado funcionando |
189
+ | [El schema](https://triplealpha-innovation.github.io/tai-sql/schema/) | Todo lo que se puede declarar, y cómo |
190
+ | [El CLI](https://triplealpha-innovation.github.io/tai-sql/cli/) | Qué hace cada comando, y qué puede destruir `push` |
191
+ | [El cliente generado](https://triplealpha-innovation.github.io/tai-sql/cliente/) | La API que vas a usar desde tu aplicación |
192
+ | [Referencia](https://triplealpha-innovation.github.io/tai-sql/referencia/dsl/) | Firmas del DSL, motores, extensión y catálogo de errores |
193
+
194
+ ---
195
+
196
+ ## Desarrollo
197
+
198
+ ```bash
199
+ git clone https://github.com/triplealpha-innovation/tai-sql
200
+ cd tai-sql
201
+ poetry install --all-extras # los extras no son opcionales para la suite
202
+
203
+ poetry run pytest # todo lo que el entorno permita
204
+ poetry run pytest -m "not db and not mysql" # lo que corre sin ninguna base de datos
205
+ poetry run pytest -m mysql # el ciclo completo contra MySQL
206
+ ```
207
+
208
+ Los tests marcados `db` necesitan un PostgreSQL alcanzable y se **saltan** si no lo hay; los
209
+ marcados `mysql`, un MySQL en `TAI_SQL_MYSQL_URL`. Sus schemas salen de `tests/fixtures/project/`.
210
+
211
+ El CI tiene tres workflows: `tests.yaml` ejecuta la suite en cada push y PR a `main` y `dev` —un
212
+ trabajo con PostgreSQL y otro con MySQL—, `docs.yaml` publica el manual y `publish.yaml` publica
213
+ a PyPI en push a `main`. La rama de trabajo habitual es `dev`, y la versión se bumpea a mano en
214
+ `pyproject.toml`.
215
+
216
+ ### El manual, en local
217
+
218
+ ```bash
219
+ pip install -r docs/requirements.txt
220
+ mkdocs serve # http://127.0.0.1:8000, con recarga en caliente
221
+ mkdocs build --strict # lo mismo que valida el CI
222
+ ```
223
+
224
+ El manual vive en `docs/` y es para quien **usa** tai-sql. Las reglas de diseño internas
225
+ (`.claude/rules/`) y el `README.md` de cada paquete son para quien trabaja **en** tai-sql, y no
226
+ se publican: son dos audiencias con preguntas distintas.
227
+
228
+ ### El mapa del código
229
+
230
+ | Ruta | Qué es |
231
+ |---|---|
232
+ | `tai_sql/orm/` | El mapeo, en cuatro capas: `declarative/` → `analysis/` → `model/` → `mapping/` |
233
+ | `tai_sql/sync/` | Sincronización schema ↔ BD: `state/` → `diff/` → `report.py` → `plan/` → `safety.py` → `executor.py` |
234
+ | `tai_sql/feed/` | Poblar la base de datos: recoger → planificar → aplicar en una transacción |
235
+ | `tai_sql/introspect/` | La dirección contraria: BD existente → fichero de schema |
236
+ | `tai_sql/drivers/` | Todo el SQL dialectal, más las capacidades de cada motor |
237
+ | `tai_sql/generators/` | Cliente Python, diagrama ER y reglas |
238
+ | `tai_sql/connection/` | Con qué se conecta tai-sql y cómo se conectará el cliente generado |
239
+ | `tai_sql/cli/` | El CLI de Click |
240
+ | `tai_sql/errors/` | `TaiSqlError` (mensaje + **solución** obligatoria) y su presentador |
241
+
242
+ Cada uno de esos paquetes tiene su propio `README.md` con el detalle.
243
+
244
+ ---
245
+
246
+ ## Licencia
247
+
248
+ MIT. Ver [LICENSE](LICENSE).
249
+
250
+ ---
251
+
252
+ <sub>Desarrollado por [Triple Alpha Innovation](https://www.triplealpha.in/es/) ·
253
+ [Issues](https://github.com/triplealpha-innovation/tai-sql/issues)</sub>
254
+
@@ -0,0 +1,193 @@
1
+ # tai-sql
2
+
3
+ [![PyPI](https://img.shields.io/pypi/v/tai-sql.svg)](https://pypi.org/project/tai-sql/)
4
+ [![Python](https://img.shields.io/pypi/pyversions/tai-sql.svg)](https://pypi.org/project/tai-sql/)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
6
+ [![Manual](https://img.shields.io/badge/manual-github.io-blue.svg)](https://triplealpha-innovation.github.io/tai-sql/)
7
+
8
+ **Framework declarativo de Python, sobre SQLAlchemy, que gestiona el ciclo de vida completo de
9
+ una base de datos.** Declaras el modelo una vez, en un fichero Python, y a partir de ahí tai-sql
10
+ sincroniza la estructura de la base de datos, genera un cliente Python completo —modelos, DTOs y
11
+ DAOs síncronos y asíncronos— y dibuja el diagrama entidad-relación.
12
+
13
+ ```
14
+ schemas/public.py ──▶ tai-sql push ──▶ la base de datos se parece al schema
15
+ ──▶ tai-sql generate ──▶ cliente Python + diagrama ER
16
+ ──▶ tai-sql feed ──▶ datos iniciales
17
+ ◀── tai-sql pull ◀── una base de datos que ya existe
18
+ ```
19
+
20
+ Motores soportados: **PostgreSQL**, **MySQL**, **SQL Server** y **BigQuery**.
21
+
22
+ 📖 **[El manual completo está en triplealpha-innovation.github.io/tai-sql](https://triplealpha-innovation.github.io/tai-sql/)**
23
+
24
+ ---
25
+
26
+ ## Quickstart
27
+
28
+ ```bash
29
+ pip install tai-sql # PostgreSQL funciona sin extras
30
+ tai-sql init -n mi_proyecto -s public # crea el proyecto
31
+ cd mi_proyecto
32
+ export MAIN_DATABASE_URL="postgresql://user:pass@localhost:5432/mydb"
33
+ tai-sql install # instala lo que el cliente generado necesitará
34
+ ```
35
+
36
+ Edita `schemas/public.py`:
37
+
38
+ ```python
39
+ # -*- coding: utf-8 -*-
40
+ from __future__ import annotations
41
+ from tai_sql import *
42
+ from tai_sql.generators import *
43
+
44
+ datasource(provider=env('MAIN_DATABASE_URL'), schema='public', syntax='v2')
45
+
46
+ generate(
47
+ PythonClientGenerator(output_dir='database'),
48
+ ERDiagramGenerator(output_dir='diagrams', format='html'),
49
+ )
50
+
51
+
52
+ class Usuario(Table):
53
+ """Usuarios del sistema."""
54
+ __tablename__ = 'usuario'
55
+
56
+ id: col[int] = column(primary_key=True, autoincrement=True)
57
+ nombre: col[str]
58
+ email: col[str] = column(unique=True)
59
+ creado_en: col[datetime] = column(server_now=True)
60
+
61
+ posts: onetomany[Post]
62
+
63
+
64
+ class Post(Table):
65
+ """Posts publicados."""
66
+ __tablename__ = 'post'
67
+
68
+ id: col[bigint] = column(primary_key=True, autoincrement=True)
69
+ titulo: col[str]
70
+ contenido: col[text]
71
+ autor_id: col[int]
72
+
73
+ autor: manytoone[Usuario] = relation(fields=['autor_id'], references=['id'], backref='posts')
74
+ ```
75
+
76
+ ```bash
77
+ tai-sql push --dry-run --verbose # enseña el DDL sin ejecutar nada
78
+ tai-sql push # lo aplica y regenera el cliente
79
+ ```
80
+
81
+ Y a usarlo:
82
+
83
+ ```python
84
+ from database.public import public_sync_api, UsuarioCreate
85
+
86
+ usuario = public_sync_api.usuario.create(UsuarioCreate(nombre='Ana', email='ana@example.com'))
87
+ usuarios = public_sync_api.usuario.find_many(limit=10, includes=['posts'])
88
+ ```
89
+
90
+ ---
91
+
92
+ ## Los cinco principios que explican el resto
93
+
94
+ 1. **El schema es la única fuente de verdad.** Todo lo demás —DDL, cliente, diagramas— es
95
+ derivado y desechable. Si el cliente generado no hace lo que necesitas, no se edita el
96
+ cliente: se arregla el schema y se regenera.
97
+ 2. **Mapear y después actuar.** Todo comando importa el schema, lo analiza y actúa sobre ese
98
+ mapeo. Ningún comando parsea el fichero por su cuenta.
99
+ 3. **El código generado nunca importa `tai_sql`.** tai-sql es una herramienta de desarrollo, no
100
+ una dependencia de producción: el cliente se despliega donde tai-sql no está instalado.
101
+ 4. **Modelo declarativo, sin migraciones versionadas.** No hay ficheros de migración: `push`
102
+ compara el estado declarado con el real y genera el DDL que hace falta.
103
+ 5. **Definición ≠ runtime.** El ORM de tai-sql *describe*; el comportamiento en producción vive
104
+ en el código generado.
105
+
106
+ ---
107
+
108
+ ## Qué trae
109
+
110
+ | | |
111
+ |---|---|
112
+ | **Schema declarativo** | Tablas, relaciones, vistas, enumerados, constraints e índices de varias columnas, columnas calculadas y jerarquías. Dos sintaxis, v1 y v2, y las dos se soportan |
113
+ | **Sincronización sin migraciones** | `push` compara y genera el DDL, clasificando cada operación en SAFE / WARNING / BLOCKED antes de tocar nada |
114
+ | **Cliente Python generado** | CRUD completo, filtros por tipo de columna, relaciones anidadas, agregaciones con GROUP BY, DataFrames, RLS, auditoría y transacciones, en síncrono y asíncrono |
115
+ | **Triggers transpilados** | Lógica de negocio declarada en el schema que se *inlinea* en los DAOs: sin coste en runtime |
116
+ | **Cifrado y vectores** | Columnas cifradas con Fernet, transparentes al leer, y columnas vectoriales con pgvector y búsqueda por similitud |
117
+ | **Diagrama ER** | Una página HTML interactiva, o una imagen con Graphviz |
118
+ | **Introspección** | `pull` escribe el schema de una base de datos que ya existe |
119
+ | **Reglas para asistentes de IA** | `rules install` deja en tu proyecto la documentación que un asistente necesita, incluida la derivada de tu schema |
120
+
121
+ ---
122
+
123
+ ## El manual
124
+
125
+ | Sección | Qué responde |
126
+ |---|---|
127
+ | [Instalación](https://triplealpha-innovation.github.io/tai-sql/empezar/instalacion/) | Qué instalar, y por qué son dos instalaciones y no una |
128
+ | [Tu primer proyecto](https://triplealpha-innovation.github.io/tai-sql/empezar/primer-proyecto/) | De cero a un cliente generado funcionando |
129
+ | [El schema](https://triplealpha-innovation.github.io/tai-sql/schema/) | Todo lo que se puede declarar, y cómo |
130
+ | [El CLI](https://triplealpha-innovation.github.io/tai-sql/cli/) | Qué hace cada comando, y qué puede destruir `push` |
131
+ | [El cliente generado](https://triplealpha-innovation.github.io/tai-sql/cliente/) | La API que vas a usar desde tu aplicación |
132
+ | [Referencia](https://triplealpha-innovation.github.io/tai-sql/referencia/dsl/) | Firmas del DSL, motores, extensión y catálogo de errores |
133
+
134
+ ---
135
+
136
+ ## Desarrollo
137
+
138
+ ```bash
139
+ git clone https://github.com/triplealpha-innovation/tai-sql
140
+ cd tai-sql
141
+ poetry install --all-extras # los extras no son opcionales para la suite
142
+
143
+ poetry run pytest # todo lo que el entorno permita
144
+ poetry run pytest -m "not db and not mysql" # lo que corre sin ninguna base de datos
145
+ poetry run pytest -m mysql # el ciclo completo contra MySQL
146
+ ```
147
+
148
+ Los tests marcados `db` necesitan un PostgreSQL alcanzable y se **saltan** si no lo hay; los
149
+ marcados `mysql`, un MySQL en `TAI_SQL_MYSQL_URL`. Sus schemas salen de `tests/fixtures/project/`.
150
+
151
+ El CI tiene tres workflows: `tests.yaml` ejecuta la suite en cada push y PR a `main` y `dev` —un
152
+ trabajo con PostgreSQL y otro con MySQL—, `docs.yaml` publica el manual y `publish.yaml` publica
153
+ a PyPI en push a `main`. La rama de trabajo habitual es `dev`, y la versión se bumpea a mano en
154
+ `pyproject.toml`.
155
+
156
+ ### El manual, en local
157
+
158
+ ```bash
159
+ pip install -r docs/requirements.txt
160
+ mkdocs serve # http://127.0.0.1:8000, con recarga en caliente
161
+ mkdocs build --strict # lo mismo que valida el CI
162
+ ```
163
+
164
+ El manual vive en `docs/` y es para quien **usa** tai-sql. Las reglas de diseño internas
165
+ (`.claude/rules/`) y el `README.md` de cada paquete son para quien trabaja **en** tai-sql, y no
166
+ se publican: son dos audiencias con preguntas distintas.
167
+
168
+ ### El mapa del código
169
+
170
+ | Ruta | Qué es |
171
+ |---|---|
172
+ | `tai_sql/orm/` | El mapeo, en cuatro capas: `declarative/` → `analysis/` → `model/` → `mapping/` |
173
+ | `tai_sql/sync/` | Sincronización schema ↔ BD: `state/` → `diff/` → `report.py` → `plan/` → `safety.py` → `executor.py` |
174
+ | `tai_sql/feed/` | Poblar la base de datos: recoger → planificar → aplicar en una transacción |
175
+ | `tai_sql/introspect/` | La dirección contraria: BD existente → fichero de schema |
176
+ | `tai_sql/drivers/` | Todo el SQL dialectal, más las capacidades de cada motor |
177
+ | `tai_sql/generators/` | Cliente Python, diagrama ER y reglas |
178
+ | `tai_sql/connection/` | Con qué se conecta tai-sql y cómo se conectará el cliente generado |
179
+ | `tai_sql/cli/` | El CLI de Click |
180
+ | `tai_sql/errors/` | `TaiSqlError` (mensaje + **solución** obligatoria) y su presentador |
181
+
182
+ Cada uno de esos paquetes tiene su propio `README.md` con el detalle.
183
+
184
+ ---
185
+
186
+ ## Licencia
187
+
188
+ MIT. Ver [LICENSE](LICENSE).
189
+
190
+ ---
191
+
192
+ <sub>Desarrollado por [Triple Alpha Innovation](https://www.triplealpha.in/es/) ·
193
+ [Issues](https://github.com/triplealpha-innovation/tai-sql/issues)</sub>
@@ -0,0 +1,171 @@
1
+ [project]
2
+ name = "tai-sql"
3
+ version = "0.7.0"
4
+ description = "SQL database management and code generation tool"
5
+ license = "MIT"
6
+ license-files = ["LICENSE"]
7
+ authors = [
8
+ {name = "MateoSaezMata", email = "msaez@triplealpha.in"},
9
+ {name = "PabloFernandezLamas", email = "pablo.fernandezlamas@triplealpha.in"}
10
+ ]
11
+ readme = "README.md"
12
+ requires-python = ">=3.10,<4.0"
13
+ keywords = ["sql", "database", "code-generation", "orm", "sqlalchemy"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Topic :: Database",
22
+ "Topic :: Software Development :: Code Generators",
23
+ ]
24
+
25
+ # Lo mínimo para declarar un schema y ejecutar el CLI contra PostgreSQL.
26
+ #
27
+ # `psycopg2-binary` está aquí y no en un extra, y es la única asimetría entre motores:
28
+ # moverlo rompería `pip install tai-sql` para quien ya lo usa contra PostgreSQL, que es
29
+ # el caso mayoritario. Los demás motores traen su DBAPI en su extra.
30
+ dependencies = [
31
+ "sqlalchemy>=2.0.42,<3.0",
32
+ "psycopg2-binary>=2.9.10,<3.0",
33
+ "click>=8.2.1,<9.0",
34
+ "jinja2>=3.1.6,<4.0",
35
+ "pydantic>=2.11.7,<3.0",
36
+ "inquirerpy>=0.3.4,<0.4.0",
37
+ "rich (>=15.0.0,<16.0.0)",
38
+ ]
39
+
40
+ [project.urls]
41
+ Homepage = "https://www.triplealpha.in/es/"
42
+ Documentation = "https://triplealpha-innovation.github.io/tai-sql/"
43
+ Repository = "https://github.com/triplealpha-innovation/tai-sql"
44
+ Issues = "https://github.com/triplealpha-innovation/tai-sql/issues"
45
+
46
+ # ═════════════════════════════════════════════════════════════════════════════
47
+ # Extras
48
+ # ═════════════════════════════════════════════════════════════════════════════
49
+ #
50
+ # ESTOS EXTRAS SON DE LA HERRAMIENTA, NO DEL CÓDIGO GENERADO.
51
+ #
52
+ # Hay dos `pyproject.toml` en juego y confundirlos es de donde salen las instalaciones
53
+ # que no arreglan nada:
54
+ #
55
+ # 1. **este** — lo que necesita tai-sql en la máquina de quien desarrolla, para
56
+ # conectarse, comparar el schema con la base de datos, generar y dibujar. Se instala
57
+ # con `pip install 'tai-sql[...]'`.
58
+ # 2. **el del proyecto del usuario** — lo que necesita el **cliente generado** en
59
+ # tiempo de ejecución. Lo escribe `tai-sql init` y lo resuelve `tai-sql install`
60
+ # (que analiza el schema y dice qué extras hacen falta). tai-sql **no** está
61
+ # instalado donde ese cliente se despliega: es una herramienta de desarrollo, no una
62
+ # dependencia de producción (principio 3 de `.claude/rules/00-filosofia.md`).
63
+ #
64
+ # Por eso aquí no hay ni `langchain-*` ni `sentence-transformers` ni drivers asíncronos:
65
+ # tai-sql no importa ninguno. Son del cliente generado, y viven en el otro pyproject.
66
+ #
67
+ # Cada extra dice **cuándo** hace falta. El detalle está en el README, sección
68
+ # "Instalación".
69
+ [project.optional-dependencies]
70
+
71
+ # ── Motores: el DBAPI con el que tai-sql se conecta ──────────────────────────
72
+ # Hace falta el del motor al que apunte tu `datasource(provider=...)`. Sin él, el fallo
73
+ # aparece en el primer comando que abra conexión (`tai-sql ping`) como un
74
+ # ModuleNotFoundError de SQLAlchemy que no dice qué instalar.
75
+ # PostgreSQL no necesita nada: su DBAPI es dependencia dura (ver arriba).
76
+ mysql = ["pymysql>=1.1.1,<2.0"]
77
+ sqlserver = ["pyodbc>=5.2.0,<6.0"]
78
+ # BigQuery solo lo necesita para **conectarse**: escribir el DDL y generar el cliente no,
79
+ # porque el driver renderiza los tipos de GoogleSQL él mismo.
80
+ bigquery = ["sqlalchemy-bigquery>=1.11.0,<2.0"]
81
+
82
+ # ── Features del schema: lo pide lo que declares ──────────────────────────────
83
+ # `vectors`: alguna columna `vector_column()`. Lo necesitan `push` y `feed`, que
84
+ # construyen el `MetaData` y ahí hace falta el tipo `Vector`. `generate` **no**: el
85
+ # cliente que produce define su propio tipo.
86
+ # `encryption`: alguna `column(encrypt=True)`. Lo necesitan `generate` —valida la clave
87
+ # secreta antes de emitir el cliente— y `feed`, que cifra los valores que inserta.
88
+ # `diagrams`: el schema declara `ERDiagramGenerator`. Necesita además el **binario** de
89
+ # Graphviz en el sistema (`apt install graphviz`), que pip no instala.
90
+ vectors = ["pgvector>=0.3.0,<1.0"]
91
+ encryption = ["cryptography>=45.0.4,<46.0"]
92
+ diagrams = ["graphviz>=0.20.3,<1.0"]
93
+
94
+ # ── Comandos concretos del CLI ────────────────────────────────────────────────
95
+ # `backup`: `tai-sql backup` y `tai-sql restore`.
96
+ # `deploy`: nada hoy — el comando está **desactivado a propósito** (comentado en
97
+ # `cli/main.py`). El extra se conserva para no romper a quien lo tenga instalado, pero
98
+ # instalarlo no habilita ningún comando.
99
+ backup = ["tai-storage>=0.1.0", "tai-alphi>=2.0.1,<3.0"]
100
+ deploy = ["requests>=2.32.4,<3.0", "pynacl>=1.5.0,<2.0"]
101
+
102
+ # ── Todo ──────────────────────────────────────────────────────────────────────
103
+ # La lista está duplicada porque Poetry rechaza que un extra se referencie a sí mismo
104
+ # (`tai-sql[diagrams,...]` → "listed as a dependency of itself"). Que no se
105
+ # desincronice lo comprueba `tests/test_packaging.py`, que asevera que `all` es la unión
106
+ # exacta de los extras de arriba — ya se había quedado atrás una vez.
107
+ all = [
108
+ "pymysql>=1.1.1,<2.0",
109
+ "pyodbc>=5.2.0,<6.0",
110
+ "sqlalchemy-bigquery>=1.11.0,<2.0",
111
+ "pgvector>=0.3.0,<1.0",
112
+ "cryptography>=45.0.4,<46.0",
113
+ "graphviz>=0.20.3,<1.0",
114
+ "tai-storage>=0.1.0",
115
+ "tai-alphi>=2.0.1,<3.0",
116
+ "requests>=2.32.4,<3.0",
117
+ "pynacl>=1.5.0,<2.0",
118
+ ]
119
+
120
+ [project.scripts]
121
+ tai-sql = "tai_sql.cli.main:cli"
122
+
123
+ [build-system]
124
+ # poetry-core 2 hace falta para `license = "MIT"` como expresión SPDX (PEP 639).
125
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
126
+ build-backend = "poetry.core.masonry.api"
127
+
128
+ # Para trabajar **en** tai-sql:
129
+ #
130
+ # poetry install --all-extras
131
+ #
132
+ # Los extras no son opcionales para la suite, y no se saltan: **fallan**. Sin `vectors`,
133
+ # el schema de fixtures que declara una columna vectorial no puede construir su
134
+ # `MetaData` y se cae todo lo que compare o planifique sobre él.
135
+ #
136
+ # Lo que sí se salta con elegancia es la base de datos: 111 de los 993 tests necesitan un
137
+ # PostgreSQL alcanzable y sin él se marcan como saltados. Ver `.claude/rules/tests.md`.
138
+ [dependency-groups]
139
+ dev = [
140
+ "pytest (>=8.0)",
141
+ "pytest-asyncio (>=0.24)",
142
+ # Mide qué parte del **cliente generado** ejecutan los tests. No cubre a tai-sql:
143
+ # lo que hay que poder afirmar es que el código que se despliega está probado.
144
+ # Ver `tests/_client_coverage.py`.
145
+ "coverage (>=7.0)",
146
+ # No lo importa tai-sql: lo importan el cliente generado (`as_dataframe`,
147
+ # `from_dataframe`) y `tai_storage`, que carga su submódulo `data` al importarse y
148
+ # ahí exige pandas y numpy. Sin declararlo, el CI instalaba tai-storage por el extra
149
+ # `backup` y **la colección de toda la suite se rompía** al importarlo, mientras en
150
+ # local pasaba porque pandas estaba instalado sin que nadie lo hubiera pedido.
151
+ "pandas (>=2.0,<3.0)",
152
+ # Lo mismo por el otro lado: `test_generated_runtime.py` ejercita el cliente async
153
+ # contra PostgreSQL, y su dialecto es asyncpg. Sin declararlo, esos 22 tests pasaban
154
+ # en local —donde estaba instalado— y en el CI fallaban todos con ModuleNotFoundError.
155
+ "asyncpg (>=0.30,<1.0)"
156
+ ]
157
+
158
+ [tool.pytest.ini_options]
159
+ testpaths = ["tests"]
160
+ # Sin esto, un `async def test_*` se recoge pero no se ejecuta: pytest lo marca como
161
+ # fallo con un aviso de plugin ausente.
162
+ asyncio_mode = "auto"
163
+ # Un solo event loop por sesión. El cliente generado expone su session manager async
164
+ # como singleton de módulo, así que su pool queda atado al loop del primer test: con un
165
+ # loop por test, el segundo falla con "Event loop is closed".
166
+ asyncio_default_fixture_loop_scope = "session"
167
+ asyncio_default_test_loop_scope = "session"
168
+ markers = [
169
+ "db: requiere una base de datos PostgreSQL real; se salta si no hay conexión",
170
+ "mysql: requiere un MySQL real en TAI_SQL_MYSQL_URL; se salta si no hay conexión",
171
+ ]
@@ -14,19 +14,30 @@ from sqlalchemy.types import (
14
14
  from datetime import datetime, date, time
15
15
  from typing import List, Optional
16
16
 
17
- from .project import ProjectManager as pm
18
- from .core import datasource, generate, env, connection_string, params, query
17
+ from .project import ProjectManager
18
+ from .connection import env, connection_string, params
19
+
20
+ # La instancia por defecto: el proyecto sobre el que trabaja el CLI. Antes `pm` era la
21
+ # propia clase, usada como espacio de nombres global; ahora es un objeto, y se puede
22
+ # construir otro para otro proyecto sin que se pisen.
23
+ pm = ProjectManager()
19
24
  from .orm import (
25
+ # DSL de cabecera del schema
26
+ datasource, generate, query,
20
27
  # Core ORM components
21
28
  Table, View, Enum, column, vector, vector_column, VectorColumn,
22
- relation, TriggerAPI, on_create, on_update, on_delete,
29
+ relation, unique_constraint, index_constraint,
30
+ TriggerAPI, on_create, on_update, on_delete,
23
31
  trigger_api, col, onetomany, manytoone, onetoone, get_type_registry,
24
32
  register_type, TypeDescriptor, BaseEncoder, SentenceTransformerEncoder,
25
33
  OpenAIEncoder, AzureOpenAIEncoder, GoogleEncoder,
26
34
  calculated_column,
27
35
  )
28
36
 
29
- from .drivers import postgresql, mysql, sqlserver
37
+ # Importar el paquete registra los cuatro drivers: cada módulo se inscribe en el
38
+ # `DriverRegistry` al final. Antes esta línea los enumeraba uno a uno y era **la única**
39
+ # que los registraba, así que entrar por `tai_sql.drivers` daba "driver no soportado".
40
+ from . import drivers as drivers
30
41
 
31
42
  # Exportar los elementos principales
32
43
  __all__ = [
@@ -38,6 +49,8 @@ __all__ = [
38
49
  'Table',
39
50
  'column',
40
51
  'relation',
52
+ 'unique_constraint',
53
+ 'index_constraint',
41
54
  'List',
42
55
  'Optional',
43
56
  'datetime',