matrx-orm 2.0.4__tar.gz → 2.0.6__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 (123) hide show
  1. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/PKG-INFO +2 -2
  2. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/README.md +1 -1
  3. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/pyproject.toml +1 -1
  4. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/release.sh +5 -1
  5. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/client/postgres_connection.py +17 -3
  6. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/config.py +1 -1
  7. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/migrations/table_filter.py +1 -1
  8. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/python_sql/table_detailed_relationships.py +0 -2
  9. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/__init__.py +2 -0
  10. matrx_orm-2.0.6/src/matrx_orm/schema_builder/code_handler.py +40 -0
  11. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/columns.py +0 -8
  12. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/common.py +25 -0
  13. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/helpers/git_checker.py +9 -9
  14. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/relationships.py +2 -10
  15. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/runner.py +16 -16
  16. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/schema.py +15 -12
  17. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/schema_manager.py +14 -6
  18. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/tables.py +0 -7
  19. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/views.py +0 -7
  20. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/sample_project/generate.py +5 -0
  21. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/sample_project/matrx_orm.yaml +19 -9
  22. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/uv.lock +1 -1
  23. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/.arman/pending/versioning/INITIAL.md +0 -0
  24. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/.env.example +0 -0
  25. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/.github/workflows/publish.yml +0 -0
  26. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/.gitignore +0 -0
  27. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/.python-version +0 -0
  28. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/CLAUDE.md +0 -0
  29. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/MIGRATIONS.md +0 -0
  30. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/RESERVED_NAMES.md +0 -0
  31. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/docs/migrations.md +0 -0
  32. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/main.py +0 -0
  33. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/__init__.py +0 -0
  34. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/adapters/__init__.py +0 -0
  35. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/adapters/base_adapter.py +0 -0
  36. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/adapters/postgresql.py +0 -0
  37. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/client/__init__.py +0 -0
  38. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/__init__.py +0 -0
  39. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/async_db_manager.py +0 -0
  40. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/base.py +0 -0
  41. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/expressions.py +0 -0
  42. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/extended.py +0 -0
  43. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/fields.py +0 -0
  44. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/paginator.py +0 -0
  45. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/registry.py +0 -0
  46. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/relations.py +0 -0
  47. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/signals.py +0 -0
  48. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/core/transaction.py +0 -0
  49. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/error_handling.py +0 -0
  50. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/exceptions.py +0 -0
  51. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/extended/__init__.py +0 -0
  52. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/extended/app_error_handler.py +0 -0
  53. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/middleware/__init__.py +0 -0
  54. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/middleware/base.py +0 -0
  55. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/migrations/__init__.py +0 -0
  56. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/migrations/cli.py +0 -0
  57. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/migrations/ddl.py +0 -0
  58. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/migrations/diff.py +0 -0
  59. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/migrations/executor.py +0 -0
  60. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/migrations/integration.py +0 -0
  61. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/migrations/loader.py +0 -0
  62. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/migrations/operations.py +0 -0
  63. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/migrations/state.py +0 -0
  64. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/operations/__init__.py +0 -0
  65. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/operations/create.py +0 -0
  66. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/operations/delete.py +0 -0
  67. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/operations/read.py +0 -0
  68. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/operations/update.py +0 -0
  69. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/python_sql/__init__.py +0 -0
  70. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/python_sql/db_objects.py +0 -0
  71. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
  72. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/query/__init__.py +0 -0
  73. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/query/builder.py +0 -0
  74. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/query/executor.py +0 -0
  75. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/generator.py +0 -0
  76. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/helpers/__init__.py +0 -0
  77. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
  78. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
  79. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/sql_executor/__init__.py +0 -0
  80. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/sql_executor/executor.py +0 -0
  81. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/sql_executor/queries.py +0 -0
  82. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/sql_executor/registry.py +0 -0
  83. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/sql_executor/types.py +0 -0
  84. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/sql_executor/utils.py +0 -0
  85. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/state.py +0 -0
  86. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/utils/__init__.py +0 -0
  87. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/utils/sql_utils.py +0 -0
  88. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/src/matrx_orm/utils/type_converters.py +0 -0
  89. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/__init__.py +0 -0
  90. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/conftest.py +0 -0
  91. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/__init__.py +0 -0
  92. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_config.py +0 -0
  93. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_ddl_generator.py +0 -0
  94. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_exceptions.py +0 -0
  95. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_fields.py +0 -0
  96. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_migration_diff_types.py +0 -0
  97. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_migration_loader.py +0 -0
  98. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_model_instance.py +0 -0
  99. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_model_meta.py +0 -0
  100. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_query_builder.py +0 -0
  101. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_query_executor_sql.py +0 -0
  102. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_registry.py +0 -0
  103. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_relations.py +0 -0
  104. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level1/test_state_cache.py +0 -0
  105. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/__init__.py +0 -0
  106. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/conftest.py +0 -0
  107. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/test_bulk_ops.py +0 -0
  108. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/test_cache_integration.py +0 -0
  109. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/test_crud.py +0 -0
  110. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/test_foreign_keys.py +0 -0
  111. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/test_m2m.py +0 -0
  112. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/test_manager.py +0 -0
  113. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/test_migrations_live.py +0 -0
  114. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/test_query_execution.py +0 -0
  115. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/level2/test_schema_diff.py +0 -0
  116. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/sample_project/.env.example +0 -0
  117. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/sample_project/README.md +0 -0
  118. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/sample_project/generated/.gitkeep +0 -0
  119. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/sample_project/test_schema_generation.py +0 -0
  120. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/schema/entity_tests.py +0 -0
  121. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/schema/test_base_generation.py +0 -0
  122. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/schema/test_generate_schema.py +0 -0
  123. {matrx_orm-2.0.4 → matrx_orm-2.0.6}/tests/test_model_cls_refactor.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrx-orm
3
- Version: 2.0.4
3
+ Version: 2.0.6
4
4
  Summary: Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching. Works with any PostgreSQL database.
5
5
  Project-URL: Homepage, https://github.com/armanisadeghi/matrx-orm
6
6
  Project-URL: Repository, https://github.com/armanisadeghi/matrx-orm
@@ -782,7 +782,7 @@ path = await diff.generate_migration_file("migrations/")
782
782
  When an included table has a foreign key column that references a table *outside* the migration scope, `matrx-orm` emits a `UserWarning` — the FK constraint will still be generated in the SQL, but the referenced table won't be created or managed by this migration set. Ensure it already exists in the target database.
783
783
 
784
784
  ```
785
- UserWarning: [matrx-orm] Cross-scope FK detected: 'post.author_id' references 'user',
785
+ UserWarning: [MATRX ORM] Cross-scope FK detected: 'post.author_id' references 'user',
786
786
  which is outside the current migration scope. The FK constraint will be included
787
787
  in the generated SQL, but 'user' will not be created or managed by this migration
788
788
  set. Ensure it already exists in the target database.
@@ -743,7 +743,7 @@ path = await diff.generate_migration_file("migrations/")
743
743
  When an included table has a foreign key column that references a table *outside* the migration scope, `matrx-orm` emits a `UserWarning` — the FK constraint will still be generated in the SQL, but the referenced table won't be created or managed by this migration set. Ensure it already exists in the target database.
744
744
 
745
745
  ```
746
- UserWarning: [matrx-orm] Cross-scope FK detected: 'post.author_id' references 'user',
746
+ UserWarning: [MATRX ORM] Cross-scope FK detected: 'post.author_id' references 'user',
747
747
  which is outside the current migration scope. The FK constraint will be included
748
748
  in the generated SQL, but 'user' will not be created or managed by this migration
749
749
  set. Ensure it already exists in the target database.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "matrx-orm"
3
- version = "2.0.4"
3
+ version = "2.0.6"
4
4
  description = "Async-first PostgreSQL ORM with bidirectional migrations, schema introspection, many-to-many relationships, and built-in state caching. Works with any PostgreSQL database."
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -78,7 +78,9 @@ ok "Commit amended"
78
78
  # ── Push commit ─────────────────────────────────────────────────────────────
79
79
 
80
80
  info "Pushing to $REMOTE/$BRANCH..."
81
+ echo ""
81
82
  git push "$REMOTE" "$BRANCH"
83
+ echo ""
82
84
  ok "Pushed to $REMOTE/$BRANCH"
83
85
 
84
86
  # ── Tag and push tag ───────────────────────────────────────────────────────
@@ -88,7 +90,9 @@ git tag "$NEW_TAG"
88
90
  ok "Tag created"
89
91
 
90
92
  info "Pushing tag $NEW_TAG..."
93
+ echo ""
91
94
  git push "$REMOTE" "$NEW_TAG"
95
+ echo ""
92
96
  ok "Tag pushed"
93
97
 
94
98
  # ── Done ────────────────────────────────────────────────────────────────────
@@ -102,8 +106,8 @@ echo ""
102
106
  echo ""
103
107
  echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
104
108
  echo -e " Monitor: ${CYAN}https://github.com/armanisadeghi/matrx-orm/actions${NC}"
105
- echo -e " Update: ${CYAN}uv add matrx-orm==${NEW_VERSION}${NC}"
106
109
  echo ""
110
+ echo -e " Update: ${CYAN}uv add matrx-orm==${NEW_VERSION}${NC}"
107
111
  echo -e " --> Not Available Yet? Speed up indexing: ${CYAN}pip index versions matrx-orm${NC}"
108
112
  echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
109
113
  echo ""
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import os
3
3
  from typing import Any, Dict, List
4
+ from urllib.parse import quote_plus
4
5
 
5
6
  from psycopg_pool import ConnectionPool
6
7
  from psycopg.rows import dict_row
@@ -30,7 +31,13 @@ def init_connection_details(config_name):
30
31
  raise ValueError(
31
32
  f"Incomplete database configuration for '{config_name}'. " "Please check your environment variables or settings.")
32
33
 
33
- connection_string = f"{db_protocol}://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}"
34
+ # URL-encode user and password so special characters (#, $, @, etc.)
35
+ # don't corrupt the URI — this is the root cause of auth failures when
36
+ # passwords contain symbols.
37
+ connection_string = (
38
+ f"{db_protocol}://{quote_plus(db_user)}:{quote_plus(db_password)}"
39
+ f"@{db_host}:{db_port}/{db_name}"
40
+ )
34
41
  redacted = f"{db_protocol}://{db_user}:****@{db_host}:{db_port}/{db_name}"
35
42
 
36
43
  vcprint(f"\n[Matrx ORM] Connection String:\n{redacted}\n", color="yellow")
@@ -39,8 +46,10 @@ def init_connection_details(config_name):
39
46
  connection_string,
40
47
  min_size=1,
41
48
  max_size=10,
42
- kwargs={"sslmode": "require"}
49
+ kwargs={"sslmode": "require"},
50
+ open=False,
43
51
  )
52
+ connection_pools[config_name].open(wait=True)
44
53
 
45
54
 
46
55
  def get_postgres_connection(
@@ -61,7 +70,12 @@ def execute_sql_query(query, params=None, database_project="this_will_cause_erro
61
70
  if params and isinstance(params, dict):
62
71
  query, params = sql_param_to_psycopg2(query, params)
63
72
  cur.execute(query, params)
64
- return cur.fetchall()
73
+ results = cur.fetchall()
74
+ conn.commit()
75
+ return results
76
+ except Exception:
77
+ conn.rollback()
78
+ raise
65
79
  finally:
66
80
  connection_pools[database_project].putconn(conn)
67
81
 
@@ -186,7 +186,7 @@ def register_database_from_env(
186
186
  _REQUIRED = ["HOST", "PORT", "NAME", "USER", "PASSWORD"]
187
187
  _OPTIONAL = {"PROTOCOL": "postgresql"}
188
188
 
189
- vcprint(f"[matrx-orm] Registering database '{name}'...", color="cyan")
189
+ vcprint(name, f"\n[MATRX ORM] Registering database", color="cyan")
190
190
 
191
191
  missing: list[str] = []
192
192
  resolved: dict[str, str] = {}
@@ -114,7 +114,7 @@ class TableFilter:
114
114
  continue
115
115
  seen.add(key)
116
116
  warnings.warn(
117
- f"[matrx-orm] Cross-scope FK detected: "
117
+ f"[MATRX ORM] Cross-scope FK detected: "
118
118
  f"'{table_name}.{col_name}' references '{ref_table}', "
119
119
  f"which is outside the current migration scope. "
120
120
  f"The FK constraint will be included in the generated SQL, "
@@ -18,8 +18,6 @@ def get_table_relationships(schema, database_project):
18
18
  List of dictionaries with table relationship data including relationship types.
19
19
  """
20
20
 
21
- print("get_table_relationships called with", database_project)
22
-
23
21
  query = """
24
22
  WITH fk_info AS (
25
23
  SELECT
@@ -3,6 +3,7 @@
3
3
  from matrx_orm.schema_builder import helpers
4
4
  from matrx_orm.schema_builder.common import (
5
5
  DEBUG_CONFIG,
6
+ OutputConfig,
6
7
  )
7
8
  from matrx_orm.schema_builder.generator import (
8
9
  get_schema_structure,
@@ -25,6 +26,7 @@ __all__ = [
25
26
  "ADMIN_PYTHON_ROOT",
26
27
  "ADMIN_TS_ROOT",
27
28
  "DEBUG_CONFIG",
29
+ "OutputConfig",
28
30
  "schema_builder_verbose",
29
31
  "SchemaManager",
30
32
  "run_schema_generation",
@@ -0,0 +1,40 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+
5
+ from matrx_utils.file_handling.specific_handlers.code_handler import CodeHandler
6
+
7
+ from matrx_orm.schema_builder.common import OutputConfig
8
+
9
+
10
+ class SchemaCodeHandler(CodeHandler):
11
+ """
12
+ Thin subclass of CodeHandler that gates file writes based on OutputConfig.
13
+
14
+ - generate_and_save_code_from_object: skipped when the file extension is
15
+ .py (python=False) or .ts (typescript=False).
16
+ - write_to_json: skipped when json=False.
17
+
18
+ Everything else — including the temp/direct routing — is handled by the
19
+ parent class exactly as before.
20
+ """
21
+
22
+ def __init__(self, output_config: OutputConfig):
23
+ super().__init__(save_direct=output_config.save_direct)
24
+ self.output_config = output_config
25
+
26
+ def generate_and_save_code_from_object(self, config_obj, main_code, additional_code=None):
27
+ temp_path: str = config_obj.get("temp_path", "")
28
+ ext = os.path.splitext(temp_path)[-1].lower()
29
+
30
+ if ext == ".py" and not self.output_config.python:
31
+ return
32
+ if ext == ".ts" and not self.output_config.typescript:
33
+ return
34
+
35
+ super().generate_and_save_code_from_object(config_obj, main_code, additional_code)
36
+
37
+ def write_to_json(self, path, data, root="temp", clean=True):
38
+ if not self.output_config.json:
39
+ return
40
+ super().write_to_json(path, data, root=root, clean=clean)
@@ -119,14 +119,6 @@ class Column:
119
119
 
120
120
  self.initialize_code_generation()
121
121
 
122
- vcprint(
123
- self.to_dict(),
124
- title="Column initialized",
125
- pretty=True,
126
- verbose=self.verbose,
127
- color="cyan",
128
- )
129
-
130
122
  if self.enum_labels:
131
123
  self.has_enum_labels = True
132
124
  vcprint(
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+ from dataclasses import dataclass, field
1
3
  from matrx_utils import DataTransformer
2
4
  import os
3
5
  import dotenv
@@ -13,6 +15,29 @@ ADMIN_TS_ROOT = os.getenv("ADMIN_TS_ROOT", "")
13
15
 
14
16
  dt_utils = DataTransformer()
15
17
 
18
+ @dataclass
19
+ class OutputConfig:
20
+ """
21
+ Controls which file types are written during schema generation and whether
22
+ output goes directly to the project roots (save_direct) or to the temp dir.
23
+
24
+ All three type flags default to True — set any to False to skip that output.
25
+ """
26
+ save_direct: bool = False
27
+ python: bool = True
28
+ typescript: bool = True
29
+ json: bool = True
30
+
31
+ @classmethod
32
+ def from_dict(cls, d: dict) -> OutputConfig:
33
+ return cls(
34
+ save_direct=bool(d.get("save_direct", False)),
35
+ python=bool(d.get("python", True)),
36
+ typescript=bool(d.get("typescript", True)),
37
+ json=bool(d.get("json", True)),
38
+ )
39
+
40
+
16
41
  # Central debug configuration for the entire schema builder.
17
42
  # Values can be overridden at runtime by run_schema_generation() from the yaml
18
43
  # debug section, or by setting env vars MATRX_DEBUG, MATRX_VERBOSE, MATRX_INFO.
@@ -25,18 +25,18 @@ def check_git_status(save_direct: bool, python_root: str = "", ts_root: str = ""
25
25
 
26
26
  if not save_direct:
27
27
  vcprint(
28
- "[MATRX GIT CHECKER] save_direct is False - skipping git checks",
28
+ "[MATRX ORM GIT CHECKER] save_direct is False - skipping git checks",
29
29
  color="green",
30
30
  )
31
31
  return True
32
32
 
33
- vcprint("\n[MATRX GIT CHECKER] Checking git repository status...", color="yellow")
34
- vcprint(f"[MATRX GIT CHECKER] Python root: {python_root}", color="green")
35
- vcprint(f"[MATRX GIT CHECKER] TypeScript root: {ts_root}", color="green")
33
+ vcprint("\n[MATRX ORM GIT CHECKER] Checking git repository status...\n", color="yellow")
34
+ vcprint(f"[MATRX ORM GIT CHECKER] Python root: {python_root}", color="green")
35
+ vcprint(f"[MATRX ORM GIT CHECKER] TypeScript root: {ts_root}", color="green")
36
36
  print()
37
37
 
38
38
  for root_name, root_path in roots_to_check:
39
- vcprint(f"\n[MATRX GIT CHECKER] Checking {root_name}...", color="yellow")
39
+ vcprint(f"\n[MATRX ORM GIT CHECKER] Checking {root_name}...", color="yellow")
40
40
 
41
41
  # Skip if path is not set
42
42
  if not root_path:
@@ -51,7 +51,7 @@ def check_git_status(save_direct: bool, python_root: str = "", ts_root: str = ""
51
51
  try:
52
52
  # Try to initialize repo object
53
53
  repo = Repo(root_path)
54
- vcprint("- Git repository found! ✓", color="green")
54
+ vcprint("- [MATRX ORM GIT CHECKER] Git repository found! ✓", color="green")
55
55
  vcprint("- Checking git status...\n", color="green")
56
56
 
57
57
  # Check if there are uncommitted changes
@@ -83,15 +83,15 @@ def check_git_status(save_direct: bool, python_root: str = "", ts_root: str = ""
83
83
 
84
84
  if has_issues:
85
85
  vcprint(
86
- "\n[MATRX GIT CHECKER] Error: Cannot proceed with save_direct=True\n",
86
+ "\n[MATRX ORM GIT CHECKER] Error: Cannot proceed with save_direct=True\n",
87
87
  color="red",
88
88
  )
89
89
  vcprint(
90
- "[MATRX GIT CHECKER] Your Options:\n --> Option 1: Commit or stash your changes first.\n --> Option 2: Set save_direct=False.\n --> Option 3: Change your environmental variables to point to a different or temporary directory.\n",
90
+ "[MATRX ORM GIT CHECKER] Your Options:\n --> Option 1: Commit or stash your changes first.\n --> Option 2: Set save_direct=False.\n --> Option 3: Change your environmental variables to point to a different or temporary directory.\n",
91
91
  color="red",
92
92
  )
93
93
  sys.exit(1)
94
94
  else:
95
- vcprint("\n[MATRX GIT CHECKER] All checks passed ✓", color="green")
95
+ vcprint("\n[MATRX ORM GIT CHECKER] All checks passed ✓", color="green")
96
96
 
97
97
  return True
@@ -35,14 +35,6 @@ class Relationship:
35
35
  self.debug = DEBUG_CONFIG["debug"]
36
36
  self.info = DEBUG_CONFIG["info"]
37
37
 
38
- vcprint(
39
- self.to_dict(),
40
- title="Relationship initialized",
41
- pretty=True,
42
- verbose=self.verbose,
43
- color="yellow",
44
- )
45
-
46
38
  def __repr__(self):
47
39
  return f"<Relationship {self.constraint_name}: {self.column} -> {self.foreign_column}>"
48
40
 
@@ -51,8 +43,8 @@ class Relationship:
51
43
  "constraint_name": self.constraint_name,
52
44
  "column": self.column,
53
45
  "foreign_column": self.foreign_column,
54
- "target_table": self.target_table,
55
- "source_table": self.source_table,
46
+ "target_table": repr(self.target_table) if self.target_table is not None else None,
47
+ "source_table": repr(self.source_table) if self.source_table is not None else None,
56
48
  "frontend_column": self.frontend_column,
57
49
  "frontend_foreign_column": self.frontend_foreign_column,
58
50
  "frontend_target_table": self.frontend_target_table,
@@ -17,7 +17,7 @@ from dotenv import load_dotenv
17
17
  from matrx_utils import vcprint
18
18
 
19
19
  from matrx_orm.core.config import register_database_from_env, DatabaseConfigError
20
- from matrx_orm.schema_builder.common import DEBUG_CONFIG
20
+ from matrx_orm.schema_builder.common import DEBUG_CONFIG, OutputConfig
21
21
  from matrx_orm.schema_builder.helpers.git_checker import check_git_status
22
22
  from matrx_orm.schema_builder.schema_manager import SchemaManager
23
23
 
@@ -54,7 +54,7 @@ def run_schema_generation(config_path: str | Path = "matrx_orm.yaml") -> None:
54
54
  f"Create a matrx_orm.yaml file next to your generate.py script."
55
55
  )
56
56
 
57
- vcprint(f"[matrx-orm] Loading config: {config_path}", color="cyan")
57
+ vcprint(config_path, f"[MATRX ORM] Loading config", color="cyan")
58
58
 
59
59
  # Load .env from the same directory as the config file
60
60
  env_file = config_path.parent / ".env"
@@ -74,11 +74,10 @@ def run_schema_generation(config_path: str | Path = "matrx_orm.yaml") -> None:
74
74
  DEBUG_CONFIG["verbose"] = bool(debug_cfg.get("verbose", False))
75
75
 
76
76
  # -------------------------------------------------------------------------
77
- # Output directories + save_direct
77
+ # Output config resolves paths, type flags, and save_direct
78
78
  # -------------------------------------------------------------------------
79
79
  output_cfg = cfg.get("output", {})
80
80
  base = config_path.parent
81
- save_direct = bool(output_cfg.get("save_direct", False))
82
81
 
83
82
  python_root = ""
84
83
  ts_root = ""
@@ -91,24 +90,26 @@ def run_schema_generation(config_path: str | Path = "matrx_orm.yaml") -> None:
91
90
  ts_root = str((base / output_cfg["typescript_root"]).resolve())
92
91
  os.environ["ADMIN_TS_ROOT"] = ts_root
93
92
 
93
+ output_config = OutputConfig.from_dict(output_cfg)
94
+
94
95
  # -------------------------------------------------------------------------
95
96
  # Git safety check — must run before any generation when save_direct=True
96
97
  # -------------------------------------------------------------------------
97
- check_git_status(save_direct, python_root=python_root, ts_root=ts_root)
98
+ check_git_status(output_config.save_direct, python_root=python_root, ts_root=ts_root)
98
99
 
99
100
  # -------------------------------------------------------------------------
100
101
  # Register databases
101
102
  # -------------------------------------------------------------------------
102
103
  databases = cfg.get("databases", [])
103
104
  if not databases:
104
- vcprint("[matrx-orm] No databases defined in matrx_orm.yaml — nothing to do.", color="yellow")
105
+ vcprint("[MATRX ORM] No databases defined in matrx_orm.yaml — nothing to do.", color="yellow")
105
106
  return
106
107
 
107
108
  for db in databases:
108
109
  name = db.get("name")
109
110
  prefix = db.get("env_prefix")
110
111
  if not name or not prefix:
111
- vcprint(f"[matrx-orm] Skipping database entry missing 'name' or 'env_prefix': {db}", color="yellow")
112
+ vcprint(f"[MATRX ORM] Skipping database entry missing 'name' or 'env_prefix': {db}", color="yellow")
112
113
  continue
113
114
 
114
115
  register_database_from_env(
@@ -122,39 +123,38 @@ def run_schema_generation(config_path: str | Path = "matrx_orm.yaml") -> None:
122
123
  # -------------------------------------------------------------------------
123
124
  generate_list = cfg.get("generate", [])
124
125
  if not generate_list:
125
- vcprint("[matrx-orm] No entries in 'generate' — databases registered but nothing generated.", color="yellow")
126
+ vcprint("[MATRX ORM] No entries in 'generate' — databases registered but nothing generated.", color="yellow")
126
127
  return
127
128
 
128
129
  for entry in generate_list:
129
130
  db_name = entry.get("database")
130
131
  schema = entry.get("schema", "public")
131
132
 
132
- vcprint(
133
- f"[matrx-orm] Generating schema for database='{db_name}' schema='{schema}'",
134
- color="cyan",
135
- )
133
+ vcprint(f"[MATRX ORM] Generating schema... \n\n- Database: '{db_name}'\n- Schema: '{schema}'", verbose=DEBUG_CONFIG["verbose"], color="cyan")
136
134
 
137
135
  try:
138
136
  manager = SchemaManager(
139
137
  schema=schema,
140
138
  database_project=db_name,
141
- save_direct=save_direct,
139
+ output_config=output_config,
142
140
  )
143
141
  manager.initialize()
144
142
  manager.schema.generate_schema_files()
145
143
  manager.schema.generate_models()
146
144
  vcprint(
147
- f"[matrx-orm] Done — database='{db_name}' schema='{schema}'",
145
+ f"[MATRX ORM] Done — database='{db_name}' schema='{schema}'\n",
148
146
  color="green",
149
147
  )
148
+
149
+ manager.schema.code_handler.print_all_batched()
150
150
  except DatabaseConfigError as e:
151
151
  vcprint(
152
- f"[matrx-orm] Skipping '{db_name}': {e}",
152
+ f"[MATRX ORM] Skipping '{db_name}': {e}",
153
153
  color="red",
154
154
  )
155
155
  except Exception as e:
156
156
  vcprint(
157
- f"[matrx-orm] Error generating '{db_name}': {e}",
157
+ f"[MATRX ORM] Error generating '{db_name}': {e}",
158
158
  color="red",
159
159
  )
160
160
  raise
@@ -6,9 +6,9 @@ from matrx_orm.schema_builder.helpers import (
6
6
  generate_complete_main_hooks_file,
7
7
  generate_multiple_entities,
8
8
  )
9
- from matrx_utils.file_handling.specific_handlers.code_handler import CodeHandler
10
9
  from matrx_orm import get_code_config, get_schema_builder_overrides
11
- from matrx_orm.schema_builder.common import DEBUG_CONFIG, dt_utils
10
+ from matrx_orm.schema_builder.code_handler import SchemaCodeHandler
11
+ from matrx_orm.schema_builder.common import DEBUG_CONFIG, OutputConfig, dt_utils
12
12
  import re
13
13
 
14
14
 
@@ -25,10 +25,13 @@ class Schema:
25
25
  self,
26
26
  name="public",
27
27
  database_project=None,
28
- save_direct=False,
28
+ output_config: OutputConfig = None,
29
29
  ):
30
+ if output_config is None:
31
+ output_config = OutputConfig()
30
32
  self.utils = dt_utils
31
- self.code_handler = CodeHandler(save_direct=save_direct)
33
+ self.output_config = output_config
34
+ self.code_handler = SchemaCodeHandler(output_config)
32
35
  self.name = name
33
36
  self.database_project = database_project
34
37
  self.tables = {}
@@ -37,7 +40,7 @@ class Schema:
37
40
  self.verbose = DEBUG_CONFIG["verbose"]
38
41
  self.debug = DEBUG_CONFIG["debug"]
39
42
  self.info = DEBUG_CONFIG["info"]
40
- self.save_direct = save_direct
43
+ self.save_direct = output_config.save_direct
41
44
  self.initialized = False
42
45
  self._include_tables: set[str] | None = None
43
46
  self._exclude_tables: set[str] | None = None
@@ -91,13 +94,13 @@ class Schema:
91
94
  view.initialize_code_generation()
92
95
 
93
96
  self.initialized = True
94
- vcprint(
95
- self.to_dict(),
96
- title="Schema started",
97
- pretty=True,
98
- verbose=self.verbose,
99
- color="cyan",
100
- )
97
+ # vcprint(
98
+ # self.to_dict(),
99
+ # title="Schema started",
100
+ # pretty=True,
101
+ # verbose=self.verbose,
102
+ # color="cyan",
103
+ # )
101
104
 
102
105
  # Method to get file location based on the code version (schema or types)
103
106
  def get_file_location(self, code_version):
@@ -1,7 +1,7 @@
1
1
  from datetime import datetime
2
2
  from matrx_utils import vcprint
3
3
 
4
- from matrx_orm.schema_builder.common import DEBUG_CONFIG, dt_utils
4
+ from matrx_orm.schema_builder.common import DEBUG_CONFIG, OutputConfig, dt_utils
5
5
  from matrx_orm.schema_builder.generator import get_relationship_data_model_types
6
6
  from matrx_orm.python_sql.db_objects import get_db_objects
7
7
  from matrx_orm.schema_builder.relationships import Relationship
@@ -17,6 +17,7 @@ class SchemaManager:
17
17
  schema="public",
18
18
  database_project=None,
19
19
  additional_schemas=None,
20
+ output_config: OutputConfig = None,
20
21
  save_direct=False,
21
22
  include_tables=None,
22
23
  exclude_tables=None,
@@ -40,12 +41,19 @@ class SchemaManager:
40
41
  "SchemaManager accepts either 'include_tables' or 'exclude_tables', not both."
41
42
  )
42
43
 
43
- # Ensure utils and Schema are properly imported or defined
44
- self.utils = dt_utils # Define or import `utils` properly
44
+ # Resolve output_config explicit object wins; bare save_direct is the
45
+ # legacy fallback so existing call sites don't break.
46
+ if output_config is None:
47
+ output_config = OutputConfig(save_direct=save_direct)
48
+ self.output_config = output_config
49
+
50
+ self.utils = dt_utils
45
51
  self.database = database
46
52
  self.schema = Schema(
47
- name=schema, database_project=database_project, save_direct=save_direct
48
- ) # Define or import `Schema`
53
+ name=schema,
54
+ database_project=database_project,
55
+ output_config=output_config,
56
+ )
49
57
  self.additional_schemas = additional_schemas
50
58
  self.database_project = database_project
51
59
  self.processed_objects = None
@@ -55,7 +63,7 @@ class SchemaManager:
55
63
  self.overview_analysis = None
56
64
  self.frontend_full_relationships = []
57
65
  self.initialized = False
58
- self.save_direct = save_direct
66
+ self.save_direct = output_config.save_direct
59
67
  self.verbose = DEBUG_CONFIG["verbose"]
60
68
  self.debug = DEBUG_CONFIG["debug"]
61
69
  self.info = DEBUG_CONFIG["info"]
@@ -114,13 +114,6 @@ class Table:
114
114
  vcprint(
115
115
  self.junction_analysis_ts, pretty=True, verbose=self.verbose, color="blue"
116
116
  )
117
- vcprint(
118
- self.to_dict(),
119
- title="Table initialized",
120
- pretty=True,
121
- verbose=self.verbose,
122
- color="cyan",
123
- )
124
117
 
125
118
  def pre_initialize(self):
126
119
  if self.pre_initialized:
@@ -40,13 +40,6 @@ class View:
40
40
  self.name_title = self.utils.to_title_case(self.name)
41
41
 
42
42
  self.unique_name_lookups = None
43
- vcprint(
44
- self.to_dict(),
45
- title="View initialized",
46
- pretty=True,
47
- verbose=self.verbose,
48
- color="cyan",
49
- )
50
43
 
51
44
  def __repr__(self):
52
45
  return f"<View name={self.name}>"
@@ -1,3 +1,8 @@
1
1
  from matrx_orm.schema_builder import run_schema_generation
2
+ from matrx_utils import clear_terminal
3
+
4
+
5
+ clear_terminal()
6
+
2
7
 
3
8
  run_schema_generation("matrx_orm.yaml")
@@ -10,10 +10,16 @@
10
10
  output:
11
11
  python_root: generated/python
12
12
  typescript_root: generated/typescript
13
- # save_direct: false — set to true to write directly to the roots above.
14
- # When true, matrx-orm will refuse to run if either
15
- # root has uncommitted git changes (safety guard).
16
- save_direct: false
13
+
14
+ # save_direct: write directly to the roots above instead of the temp dir.
15
+ # When true, matrx-orm will refuse to run if either root has uncommitted
16
+ # git changes (safety guard).
17
+ save_direct: true
18
+
19
+ # Set any of these to false to skip generating that file type entirely.
20
+ python: true
21
+ typescript: true
22
+ json: true
17
23
 
18
24
  # =============================================================================
19
25
  # Databases
@@ -33,6 +39,8 @@ databases:
33
39
 
34
40
  - name: secondary
35
41
  env_prefix: SECONDARY_DB
42
+ additional_schemas:
43
+ - auth
36
44
 
37
45
  # =============================================================================
38
46
  # Schema generation
@@ -44,14 +52,16 @@ generate:
44
52
  - database: primary
45
53
  schema: public
46
54
 
55
+
47
56
  # Uncomment to also generate from the secondary database:
48
- # - database: secondary
49
- # schema: public
57
+ - database: secondary
58
+ schema: public
50
59
 
51
60
  # =============================================================================
52
61
  # Debug
53
62
  # =============================================================================
54
63
  debug:
55
- info: false
56
- verbose: false
57
- debug: false
64
+ info: true
65
+ debug: true
66
+ verbose: true
67
+
@@ -266,7 +266,7 @@ wheels = [
266
266
 
267
267
  [[package]]
268
268
  name = "matrx-orm"
269
- version = "2.0.2"
269
+ version = "2.0.4"
270
270
  source = { editable = "." }
271
271
  dependencies = [
272
272
  { name = "asyncpg" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes