matrx-orm 2.0.1__tar.gz → 2.0.2__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 (125) hide show
  1. matrx_orm-2.0.2/.env.example +11 -0
  2. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/PKG-INFO +2 -1
  3. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/README.md +1 -0
  4. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/pyproject.toml +1 -1
  5. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/client/postgres_connection.py +3 -2
  6. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/config.py +5 -1
  7. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/python_sql/db_objects.py +1 -1
  8. matrx_orm-2.0.2/tests/sample_project/database_registry.py +52 -0
  9. matrx_orm-2.0.2/tests/sample_project/run_schema_generation.py +61 -0
  10. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/sample_project/test_schema_generation.py +4 -1
  11. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/uv.lock +1 -1
  12. matrx_orm-2.0.1/.env.example +0 -12
  13. matrx_orm-2.0.1/scripts/update_package.sh +0 -200
  14. matrx_orm-2.0.1/tests/sample_project/database_registry.py +0 -116
  15. matrx_orm-2.0.1/tests/sample_project/run_schema_generation.py +0 -156
  16. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/.arman/pending/versioning/INITIAL.md +0 -0
  17. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/.github/workflows/publish.yml +0 -0
  18. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/.gitignore +0 -0
  19. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/.python-version +0 -0
  20. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/CLAUDE.md +0 -0
  21. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/MIGRATIONS.md +0 -0
  22. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/RESERVED_NAMES.md +0 -0
  23. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/docs/migrations.md +0 -0
  24. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/main.py +0 -0
  25. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/release.sh +0 -0
  26. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/__init__.py +0 -0
  27. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/adapters/__init__.py +0 -0
  28. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/adapters/base_adapter.py +0 -0
  29. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/adapters/postgresql.py +0 -0
  30. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/client/__init__.py +0 -0
  31. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/__init__.py +0 -0
  32. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/async_db_manager.py +0 -0
  33. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/base.py +0 -0
  34. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/expressions.py +0 -0
  35. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/extended.py +0 -0
  36. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/fields.py +0 -0
  37. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/paginator.py +0 -0
  38. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/registry.py +0 -0
  39. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/relations.py +0 -0
  40. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/signals.py +0 -0
  41. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/transaction.py +0 -0
  42. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/error_handling.py +0 -0
  43. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/exceptions.py +0 -0
  44. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/extended/__init__.py +0 -0
  45. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/extended/app_error_handler.py +0 -0
  46. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/middleware/__init__.py +0 -0
  47. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/middleware/base.py +0 -0
  48. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/__init__.py +0 -0
  49. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/cli.py +0 -0
  50. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/ddl.py +0 -0
  51. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/diff.py +0 -0
  52. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/executor.py +0 -0
  53. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/integration.py +0 -0
  54. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/loader.py +0 -0
  55. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/operations.py +0 -0
  56. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/state.py +0 -0
  57. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/table_filter.py +0 -0
  58. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/operations/__init__.py +0 -0
  59. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/operations/create.py +0 -0
  60. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/operations/delete.py +0 -0
  61. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/operations/read.py +0 -0
  62. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/operations/update.py +0 -0
  63. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/python_sql/__init__.py +0 -0
  64. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
  65. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
  66. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/query/__init__.py +0 -0
  67. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/query/builder.py +0 -0
  68. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/query/executor.py +0 -0
  69. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/__init__.py +0 -0
  70. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/columns.py +0 -0
  71. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/common.py +0 -0
  72. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/generator.py +0 -0
  73. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/helpers/__init__.py +0 -0
  74. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
  75. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
  76. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
  77. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/relationships.py +0 -0
  78. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/schema.py +0 -0
  79. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/schema_manager.py +0 -0
  80. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/tables.py +0 -0
  81. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/views.py +0 -0
  82. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/__init__.py +0 -0
  83. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/executor.py +0 -0
  84. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/queries.py +0 -0
  85. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/registry.py +0 -0
  86. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/types.py +0 -0
  87. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/utils.py +0 -0
  88. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/state.py +0 -0
  89. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/utils/__init__.py +0 -0
  90. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/utils/sql_utils.py +0 -0
  91. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/utils/type_converters.py +0 -0
  92. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/__init__.py +0 -0
  93. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/conftest.py +0 -0
  94. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/__init__.py +0 -0
  95. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_config.py +0 -0
  96. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_ddl_generator.py +0 -0
  97. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_exceptions.py +0 -0
  98. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_fields.py +0 -0
  99. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_migration_diff_types.py +0 -0
  100. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_migration_loader.py +0 -0
  101. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_model_instance.py +0 -0
  102. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_model_meta.py +0 -0
  103. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_query_builder.py +0 -0
  104. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_query_executor_sql.py +0 -0
  105. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_registry.py +0 -0
  106. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_relations.py +0 -0
  107. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_state_cache.py +0 -0
  108. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/__init__.py +0 -0
  109. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/conftest.py +0 -0
  110. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_bulk_ops.py +0 -0
  111. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_cache_integration.py +0 -0
  112. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_crud.py +0 -0
  113. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_foreign_keys.py +0 -0
  114. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_m2m.py +0 -0
  115. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_manager.py +0 -0
  116. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_migrations_live.py +0 -0
  117. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_query_execution.py +0 -0
  118. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_schema_diff.py +0 -0
  119. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/sample_project/.env.example +0 -0
  120. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/sample_project/README.md +0 -0
  121. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/sample_project/generated/.gitkeep +0 -0
  122. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/schema/entity_tests.py +0 -0
  123. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/schema/test_base_generation.py +0 -0
  124. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/schema/test_generate_schema.py +0 -0
  125. {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/test_model_cls_refactor.py +0 -0
@@ -0,0 +1,11 @@
1
+ BASE_DIR=enter_your_base_directory_here
2
+ ADMIN_PYTHON_ROOT=enter_your_python_root_directory_here
3
+ ADMIN_TS_ROOT=enter_your_ts_root_directory_here
4
+
5
+ SUPABASE_MATRX_URL=supabase_host_url
6
+ DB_HOST=host
7
+ DB_NAME=postgres
8
+ DB_PORT=6543
9
+ DB_USER=user
10
+ DB_PASS=password
11
+ SUPABASE_MATRX_JWT_SECRET=secret
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: matrx-orm
3
- Version: 2.0.1
3
+ Version: 2.0.2
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
@@ -1833,6 +1833,7 @@ When you run the schema builder against a database that has `vector(n)` columns,
1833
1833
 
1834
1834
  | Version | Highlights |
1835
1835
  |---|---|
1836
+ | **v2.0.2** | Patch release |
1836
1837
  | **v2.0.0** | pgvector support: `VectorField(dimensions=n)` with serialization/validation; `VectorDistance` expression; `.nearest(column, vector, metric)` query builder method; automatic null guard; `_vector_distance` in results; asyncpg codec auto-registered on pool init; `IndexDef` extended with `vector_ops` / `index_params` for HNSW & IVFFlat DDL; schema builder recognises `vector(n)` columns |
1837
1838
  | **v1.9.0** | Schema builder externalization: app-specific entity/field overrides removed from the ORM package and moved to `DatabaseProjectConfig` (`entity_overrides`, `field_overrides`); new `get_schema_builder_overrides()` accessor; `sql_executor/queries.py` reduced to generic TypedDicts + empty registry with a `register_query()` helper; all hardcoded project-name defaults removed from public APIs |
1838
1839
  | **v1.9.0** | Cross-schema & multi-database FK support: `ForeignKey(to_schema='auth')` for same-database cross-schema FKs (e.g. `auth.users`); `ForeignKey(to_db='other_project')` for cross-database routing; `ForeignKeyReference` gains `to_db`/`to_schema`; `_unfetchable` now emits a `UserWarning` instead of silently returning `None`; `Users` stub removes `_unfetchable = True` so `auth.users` fetches work out of the box; introspection SQL captures referenced schema via `pg_namespace`; schema builder emits `to_schema` in generated code; `DatabaseProjectConfig.additional_schemas` replaces hardcoded `["auth"]` everywhere |
@@ -1795,6 +1795,7 @@ When you run the schema builder against a database that has `vector(n)` columns,
1795
1795
 
1796
1796
  | Version | Highlights |
1797
1797
  |---|---|
1798
+ | **v2.0.2** | Patch release |
1798
1799
  | **v2.0.0** | pgvector support: `VectorField(dimensions=n)` with serialization/validation; `VectorDistance` expression; `.nearest(column, vector, metric)` query builder method; automatic null guard; `_vector_distance` in results; asyncpg codec auto-registered on pool init; `IndexDef` extended with `vector_ops` / `index_params` for HNSW & IVFFlat DDL; schema builder recognises `vector(n)` columns |
1799
1800
  | **v1.9.0** | Schema builder externalization: app-specific entity/field overrides removed from the ORM package and moved to `DatabaseProjectConfig` (`entity_overrides`, `field_overrides`); new `get_schema_builder_overrides()` accessor; `sql_executor/queries.py` reduced to generic TypedDicts + empty registry with a `register_query()` helper; all hardcoded project-name defaults removed from public APIs |
1800
1801
  | **v1.9.0** | Cross-schema & multi-database FK support: `ForeignKey(to_schema='auth')` for same-database cross-schema FKs (e.g. `auth.users`); `ForeignKey(to_db='other_project')` for cross-database routing; `ForeignKeyReference` gains `to_db`/`to_schema`; `_unfetchable` now emits a `UserWarning` instead of silently returning `None`; `Users` stub removes `_unfetchable = True` so `auth.users` fetches work out of the box; introspection SQL captures referenced schema via `pg_namespace`; schema builder emits `to_schema` in generated code; `DatabaseProjectConfig.additional_schemas` replaces hardcoded `["auth"]` everywhere |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "matrx-orm"
3
- version = "2.0.1"
3
+ version = "2.0.2"
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" }
@@ -21,6 +21,7 @@ def init_connection_details(config_name):
21
21
 
22
22
  db_host = config.get("host")
23
23
  db_port = config.get("port")
24
+ db_protocol = config.get("protocol", "postgresql")
24
25
  db_name = config.get("database_name")
25
26
  db_user = config.get("user")
26
27
  db_password = config.get("password")
@@ -29,9 +30,9 @@ def init_connection_details(config_name):
29
30
  raise ValueError(
30
31
  f"Incomplete database configuration for '{config_name}'. " "Please check your environment variables or settings.")
31
32
 
32
- connection_string = f"postgresql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}"
33
+ connection_string = f"{db_protocol}://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}"
33
34
 
34
- vcprint(f"\n[Matrx ORM] Connection String:\n{connection_string}\n", color="green")
35
+ vcprint(f"\n[Matrx ORM] Connection String:\n{connection_string}\n", color="yellow")
35
36
 
36
37
  connection_pools[config_name] = ConnectionPool(
37
38
  connection_string,
@@ -17,6 +17,7 @@ class DatabaseProjectConfig:
17
17
  user: str
18
18
  password: str
19
19
 
20
+ protocol: str = "postgresql"
20
21
  alias: str = ""
21
22
  manager_config_overrides: Dict = field(default_factory=dict)
22
23
 
@@ -69,6 +70,7 @@ class DatabaseRegistry:
69
70
  if not all(required_fields):
70
71
  missing = []
71
72
  if not config.host: missing.append("host")
73
+ if not config.protocol: missing.append("protocol")
72
74
  if not config.alias: missing.append("alias")
73
75
  if not config.port: missing.append("port")
74
76
  if not config.database_name: missing.append("database_name")
@@ -87,6 +89,7 @@ class DatabaseRegistry:
87
89
  return {
88
90
  "host": config.host,
89
91
  "port": config.port,
92
+ "protocol": config.protocol,
90
93
  "database_name": config.database_name,
91
94
  "user": config.user,
92
95
  "password": config.password,
@@ -111,6 +114,7 @@ class DatabaseRegistry:
111
114
  all_configs[config_name] = {
112
115
  "host": config.host,
113
116
  "port": config.port,
117
+ "protocol": config.protocol,
114
118
  "database_name": config.database_name,
115
119
  "user": config.user,
116
120
  "password": config.password,
@@ -159,7 +163,7 @@ def register_database(config: DatabaseProjectConfig) -> None:
159
163
 
160
164
  def get_connection_string(config_name: str) -> str:
161
165
  config = get_database_config(config_name)
162
- connection_string = f"postgresql://{config['user']}:{redact_string(config['password'])}@{config['host']}:{config['port']}/{config['database_name']}"
166
+ connection_string = f"{config['protocol']}://{config['user']}:{redact_string(config['password'])}@{config['host']}:{config['port']}/{config['database_name']}"
163
167
  return connection_string
164
168
 
165
169
 
@@ -184,7 +184,7 @@ def get_db_objects(schema, database_project):
184
184
  tuple: (processed_objects, full_relationships, full_junction_analysis, all_enum_base_types)
185
185
  where all_enum_base_types is a set of base types that have enum labels
186
186
  """
187
- if info:
187
+ if debug:
188
188
  print("get_db_objects called with", database_project)
189
189
 
190
190
  # Retrieve the raw database objects
@@ -0,0 +1,52 @@
1
+ from dotenv import load_dotenv
2
+
3
+ load_dotenv()
4
+
5
+ from matrx_utils.conf import settings, NotConfiguredError
6
+ from matrx_utils import vcprint
7
+ from matrx_orm import DatabaseProjectConfig, register_database
8
+ from matrx_orm.core.config import DatabaseConfigError
9
+
10
+ # ---------------------------------------------------------------------------
11
+ # Primary database — Supabase (MY_MATRX project: viyklljfdhtidwecakwx)
12
+ #
13
+ # additional_schemas=["auth"] makes the ORM and schema builder aware of the
14
+ # auth schema — auth.users FKs resolve via fetch_fk() without _unfetchable.
15
+ # ---------------------------------------------------------------------------
16
+ try:
17
+ primary_config = DatabaseProjectConfig(
18
+ name="primary",
19
+ alias="primary",
20
+ host=settings.PRIMARY_DB_HOST,
21
+ port=settings.PRIMARY_DB_PORT,
22
+ protocol=settings.PRIMARY_DB_PROTOCOL,
23
+ database_name=settings.PRIMARY_DB_NAME,
24
+ user=settings.PRIMARY_DB_USER,
25
+ password=settings.PRIMARY_DB_PASSWORD,
26
+ additional_schemas=["auth"],
27
+ )
28
+ register_database(primary_config)
29
+ except (AttributeError, NotConfiguredError, DatabaseConfigError) as e:
30
+ vcprint(f"[sample_project] primary database not registered — missing env vars: {e}", color="yellow")
31
+
32
+ # ---------------------------------------------------------------------------
33
+ # Secondary database — Supabase (MATRX_DM project: deayzgwvqfdeskkdwudy)
34
+ #
35
+ # No cross-database FK relationships configured yet.
36
+ # To add one later: ForeignKey(Users, to_column="id", to_db="primary")
37
+ # ---------------------------------------------------------------------------
38
+ try:
39
+ secondary_config = DatabaseProjectConfig(
40
+ name="secondary",
41
+ alias="secondary",
42
+ host=settings.SECONDARY_DB_HOST,
43
+ port=settings.SECONDARY_DB_PORT,
44
+ protocol=settings.SECONDARY_DB_PROTOCOL,
45
+ database_name=settings.SECONDARY_DB_NAME,
46
+ user=settings.SECONDARY_DB_USER,
47
+ password=settings.SECONDARY_DB_PASSWORD,
48
+ additional_schemas=[],
49
+ )
50
+ register_database(secondary_config)
51
+ except (AttributeError, NotConfiguredError, DatabaseConfigError) as e:
52
+ vcprint(f"[sample_project] secondary database not registered — missing env vars: {e}", color="yellow")
@@ -0,0 +1,61 @@
1
+ import sys
2
+ from pathlib import Path
3
+
4
+ # Put this directory on the path so `import database_registry` works directly,
5
+ # and put the src/ dir on the path so matrx_orm is importable without installing.
6
+ _here = Path(__file__).parent.resolve()
7
+ sys.path.insert(0, str(_here))
8
+ sys.path.insert(0, str(_here.parent.parent / "src"))
9
+
10
+ import database_registry # noqa: E402 — registers primary + secondary databases
11
+
12
+ from matrx_utils import clear_terminal, vcprint # noqa: E402
13
+ from matrx_orm.schema_builder import SchemaManager # noqa: E402
14
+
15
+ clear_terminal()
16
+
17
+ # ---------------------------------------------------------------------------
18
+ # Primary database — run this block to generate from the primary Supabase DB
19
+ # ---------------------------------------------------------------------------
20
+ schema = "public"
21
+ database_project = "primary"
22
+ additional_schemas = ["auth"]
23
+ save_direct = False # set True to write directly to ADMIN_PYTHON_ROOT
24
+
25
+ schema_manager = SchemaManager(
26
+ schema=schema,
27
+ database_project=database_project,
28
+ additional_schemas=additional_schemas,
29
+ save_direct=save_direct,
30
+ )
31
+ schema_manager.initialize()
32
+
33
+ matrx_schema_entry = schema_manager.schema.generate_schema_files()
34
+ matrx_models = schema_manager.schema.generate_models()
35
+
36
+ analysis = schema_manager.analyze_schema()
37
+ vcprint(
38
+ data=analysis,
39
+ title="Schema Analysis — primary",
40
+ pretty=True,
41
+ verbose=False,
42
+ color="yellow",
43
+ )
44
+
45
+ schema_manager.schema.code_handler.print_all_batched()
46
+
47
+ # ---------------------------------------------------------------------------
48
+ # Secondary database — uncomment to also generate from the secondary DB
49
+ # ---------------------------------------------------------------------------
50
+ # schema_manager_2 = SchemaManager(
51
+ # schema="public",
52
+ # database_project="secondary",
53
+ # additional_schemas=[],
54
+ # save_direct=False,
55
+ # )
56
+ # schema_manager_2.initialize()
57
+ # schema_manager_2.schema.generate_schema_files()
58
+ # schema_manager_2.schema.generate_models()
59
+ # analysis_2 = schema_manager_2.analyze_schema()
60
+ # vcprint(data=analysis_2, title="Schema Analysis — secondary", pretty=True, verbose=False, color="cyan")
61
+ # schema_manager_2.schema.code_handler.print_all_batched()
@@ -45,7 +45,10 @@ pytestmark = pytest.mark.schema
45
45
  @pytest.fixture(scope="session", autouse=True)
46
46
  def register_sample_databases():
47
47
  """Register primary and secondary databases for the test session."""
48
- from tests.sample_project.database_registry import setup_databases
48
+ import sys
49
+ from pathlib import Path
50
+ sys.path.insert(0, str(Path(__file__).parent))
51
+ from database_registry import setup_databases
49
52
  setup_databases()
50
53
 
51
54
 
@@ -266,7 +266,7 @@ wheels = [
266
266
 
267
267
  [[package]]
268
268
  name = "matrx-orm"
269
- version = "1.6.4"
269
+ version = "2.0.1"
270
270
  source = { editable = "." }
271
271
  dependencies = [
272
272
  { name = "asyncpg" },
@@ -1,12 +0,0 @@
1
- BASE_DIR=D:/work/matrx/matrx-orm
2
-
3
- SUPABASE_MATRX_URL=supabase_host_url
4
- DB_HOST=host
5
- DB_NAME=postgres
6
- DB_PORT=6543
7
- DB_USER=user
8
- DB_PASS=password
9
- SUPABASE_MATRX_JWT_SECRET=secret
10
-
11
- ADMIN_PYTHON_ROOT=D:/work/matrx/matrx-orm/temp/python-app
12
- ADMIN_TS_ROOT=D:/work/matrx/matrx-orm/temp/ts-app
@@ -1,200 +0,0 @@
1
- #!/usr/bin/env bash
2
- # update_package.sh — Bump version, update README, commit, tag, and push.
3
- #
4
- # Usage (run from anywhere inside the repo):
5
- # ./scripts/update_package.sh # patch bump 1.2.3 → 1.2.4 (default)
6
- # ./scripts/update_package.sh --patch # patch bump 1.2.3 → 1.2.4
7
- # ./scripts/update_package.sh --minor # minor bump 1.2.3 → 1.3.0
8
- # ./scripts/update_package.sh --major # major bump 1.2.3 → 2.0.0
9
- # ./scripts/update_package.sh --message "fix: something" # custom commit message
10
- # ./scripts/update_package.sh --minor --message "feat: new stuff"
11
- # ./scripts/update_package.sh --dry-run # preview changes without committing
12
-
13
- set -euo pipefail
14
-
15
- # ── Resolve repo root ────────────────────────────────────────────────────────
16
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
17
- REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
18
- cd "$REPO_ROOT"
19
-
20
- PYPROJECT="pyproject.toml"
21
- README="README.md"
22
- REMOTE="origin"
23
- BRANCH="main"
24
-
25
- # ── Colors ───────────────────────────────────────────────────────────────────
26
- RED='\033[0;31m'
27
- GREEN='\033[0;32m'
28
- YELLOW='\033[1;33m'
29
- CYAN='\033[0;36m'
30
- BOLD='\033[1m'
31
- NC='\033[0m'
32
-
33
- info() { echo -e "${CYAN}[INFO]${NC} $*"; }
34
- ok() { echo -e "${GREEN}[OK]${NC} $*"; }
35
- warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
36
- fail() { echo -e "${RED}[FAIL]${NC} $*" >&2; exit 1; }
37
- preview() { echo -e "${YELLOW}[DRY]${NC} $*"; }
38
-
39
- # ── Parse flags ──────────────────────────────────────────────────────────────
40
- BUMP_TYPE="patch"
41
- CUSTOM_MESSAGE=""
42
- DRY_RUN=false
43
-
44
- while [[ $# -gt 0 ]]; do
45
- case "$1" in
46
- --patch) BUMP_TYPE="patch"; shift ;;
47
- --minor) BUMP_TYPE="minor"; shift ;;
48
- --major) BUMP_TYPE="major"; shift ;;
49
- --message|-m)
50
- [[ -n "${2:-}" ]] || fail "--message requires an argument."
51
- CUSTOM_MESSAGE="$2"; shift 2 ;;
52
- --dry-run) DRY_RUN=true; shift ;;
53
- -h|--help)
54
- grep '^#' "$0" | head -20 | sed 's/^# \?//'
55
- exit 0 ;;
56
- *) fail "Unknown flag: $1. Use --patch, --minor, --major, --message, or --dry-run." ;;
57
- esac
58
- done
59
-
60
- # ── Pre-flight checks ────────────────────────────────────────────────────────
61
- [[ -f "$PYPROJECT" ]] || fail "$PYPROJECT not found. Cannot continue."
62
- [[ -f "$README" ]] || fail "$README not found. Cannot continue."
63
-
64
- CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
65
- [[ "$CURRENT_BRANCH" == "$BRANCH" ]] \
66
- || fail "Not on '$BRANCH' branch (currently on '$CURRENT_BRANCH'). Switch first."
67
-
68
- if [[ -n "$(git diff --cached --name-only)" ]]; then
69
- fail "Staged but uncommitted changes detected. Commit or unstage them first."
70
- fi
71
-
72
- if [[ -n "$(git diff --name-only HEAD)" ]]; then
73
- warn "Unstaged changes in tracked files — they will be committed with the version bump."
74
- fi
75
-
76
- # ── Read current version ─────────────────────────────────────────────────────
77
- CURRENT_VERSION=$(grep '^version = ' "$PYPROJECT" | sed 's/version = "\(.*\)"/\1/')
78
- [[ -n "$CURRENT_VERSION" ]] || fail "Could not read version from $PYPROJECT."
79
-
80
- IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_VERSION"
81
-
82
- # ── Calculate new version ────────────────────────────────────────────────────
83
- case "$BUMP_TYPE" in
84
- patch) NEW_VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))" ;;
85
- minor) NEW_VERSION="${MAJOR}.$((MINOR + 1)).0" ;;
86
- major) NEW_VERSION="$((MAJOR + 1)).0.0" ;;
87
- esac
88
-
89
- NEW_TAG="v${NEW_VERSION}"
90
-
91
- # ── Check tag doesn't already exist ─────────────────────────────────────────
92
- if git rev-parse "$NEW_TAG" &>/dev/null; then
93
- fail "Tag $NEW_TAG already exists. Resolve manually or choose a different bump type."
94
- fi
95
-
96
- # ── Build commit message ─────────────────────────────────────────────────────
97
- if [[ -n "$CUSTOM_MESSAGE" ]]; then
98
- COMMIT_MSG="$CUSTOM_MESSAGE"
99
- else
100
- case "$BUMP_TYPE" in
101
- patch) COMMIT_MSG="chore: release v${NEW_VERSION}" ;;
102
- minor) COMMIT_MSG="chore: release v${NEW_VERSION}" ;;
103
- major) COMMIT_MSG="chore: release v${NEW_VERSION}" ;;
104
- esac
105
- fi
106
-
107
- # ── Preview ──────────────────────────────────────────────────────────────────
108
- echo ""
109
- echo -e "${BOLD} matrx-orm release${NC}"
110
- echo -e " ─────────────────────────────────────────────"
111
- echo -e " Bump type : ${CYAN}${BUMP_TYPE}${NC}"
112
- echo -e " Old version: ${YELLOW}${CURRENT_VERSION}${NC}"
113
- echo -e " New version: ${GREEN}${NEW_VERSION}${NC}"
114
- echo -e " Tag : ${GREEN}${NEW_TAG}${NC}"
115
- echo -e " Commit msg : ${CYAN}${COMMIT_MSG}${NC}"
116
- $DRY_RUN && echo -e " Mode : ${YELLOW}DRY RUN — nothing will be changed${NC}"
117
- echo -e " ─────────────────────────────────────────────"
118
- echo ""
119
-
120
- if $DRY_RUN; then
121
- preview "Would update version in $PYPROJECT: $CURRENT_VERSION → $NEW_VERSION"
122
- preview "Would prepend entry in $README version history table"
123
- preview "Would commit: '$COMMIT_MSG'"
124
- preview "Would create tag: $NEW_TAG"
125
- preview "Would push: git push $REMOTE $BRANCH --tags"
126
- echo ""
127
- preview "Dry run complete. No changes made."
128
- echo ""
129
- exit 0
130
- fi
131
-
132
- # ── Update pyproject.toml ────────────────────────────────────────────────────
133
- info "Bumping version in $PYPROJECT..."
134
- sed -i "s/^version = \"${CURRENT_VERSION}\"/version = \"${NEW_VERSION}\"/" "$PYPROJECT"
135
-
136
- # Verify the change landed
137
- WRITTEN_VERSION=$(grep '^version = ' "$PYPROJECT" | sed 's/version = "\(.*\)"/\1/')
138
- [[ "$WRITTEN_VERSION" == "$NEW_VERSION" ]] \
139
- || fail "Version write failed — $PYPROJECT still shows $WRITTEN_VERSION."
140
- ok "pyproject.toml → $NEW_VERSION"
141
-
142
- # ── Update README version history table ──────────────────────────────────────
143
- info "Inserting v${NEW_VERSION} entry in $README..."
144
-
145
- # Build the new row; use a placeholder message unless --message was given.
146
- if [[ -n "$CUSTOM_MESSAGE" ]]; then
147
- README_ENTRY="| **v${NEW_VERSION}** | ${CUSTOM_MESSAGE} |"
148
- else
149
- case "$BUMP_TYPE" in
150
- patch) README_ENTRY="| **v${NEW_VERSION}** | Patch release |" ;;
151
- minor) README_ENTRY="| **v${NEW_VERSION}** | Minor release |" ;;
152
- major) README_ENTRY="| **v${NEW_VERSION}** | Major release |" ;;
153
- esac
154
- fi
155
-
156
- # Insert the new row immediately after the "| Version | Highlights |" header row.
157
- # The table looks like:
158
- # | Version | Highlights |
159
- # |---|---|
160
- # | **v1.4.3** | ... | ← insert here
161
- ESCAPED_ENTRY=$(printf '%s\n' "$README_ENTRY" | sed 's/[\/&]/\\&/g')
162
- sed -i "/^| Version | Highlights |/{
163
- n # skip the separator row
164
- n # now on the first data row
165
- i\\${ESCAPED_ENTRY}
166
- }" "$README"
167
-
168
- ok "README.md → added $NEW_VERSION to version history"
169
-
170
- # ── Commit ───────────────────────────────────────────────────────────────────
171
- info "Staging changed files..."
172
- git add "$PYPROJECT" "$README"
173
-
174
- # Also stage any unstaged tracked changes the user already had
175
- git add -u
176
-
177
- info "Committing..."
178
- git commit -m "$COMMIT_MSG"
179
- ok "Committed: '$COMMIT_MSG'"
180
-
181
- # ── Tag ──────────────────────────────────────────────────────────────────────
182
- info "Creating tag $NEW_TAG..."
183
- git tag "$NEW_TAG"
184
- ok "Tag $NEW_TAG created"
185
-
186
- # ── Push ─────────────────────────────────────────────────────────────────────
187
- info "Pushing commits and tag to $REMOTE/$BRANCH..."
188
- git push "$REMOTE" "$BRANCH" --tags
189
- ok "Pushed to $REMOTE/$BRANCH with tag $NEW_TAG"
190
-
191
- # ── Done ─────────────────────────────────────────────────────────────────────
192
- echo ""
193
- echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
194
- echo -e "${GREEN} Released matrx-orm ${NEW_VERSION}${NC}"
195
- echo -e "${GREEN} GitHub Actions will now build and publish to PyPI.${NC}"
196
- echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
197
- echo ""
198
- echo -e " Monitor : ${CYAN}https://github.com/armanisadeghi/matrx-orm/actions${NC}"
199
- echo -e " Install : ${CYAN}uv add matrx-orm@${NEW_VERSION}${NC}"
200
- echo ""
@@ -1,116 +0,0 @@
1
- """
2
- Sample Project — Database Registry
3
- ===================================
4
- This file demonstrates how to configure matrx-orm for a real-world multi-database
5
- setup. It registers:
6
-
7
- 1. ``primary`` — Main Supabase project (public schema + auth schema).
8
- All application tables live here. auth.users is automatically
9
- reachable because ``additional_schemas=["auth"]`` is set.
10
-
11
- 2. ``secondary`` — A second Supabase project (or any remote Postgres database).
12
- No cross-database relationships are declared yet; it is
13
- registered so you can run queries and schema generation
14
- against it independently.
15
-
16
- How to use
17
- ----------
18
- Import this module once at application startup before any model or query code runs:
19
-
20
- from tests.sample_project.database_registry import setup_databases
21
- setup_databases()
22
-
23
- The setup_databases() call is idempotent — matrx-orm silently skips duplicate
24
- registrations, so it is safe to call from multiple entry points.
25
-
26
- Environment variables
27
- ---------------------
28
- All credentials are read from the environment (or from .env via python-dotenv).
29
- Copy .env.example → .env and fill in the real passwords before running.
30
-
31
- Supabase connection notes
32
- -------------------------
33
- - Host format: db.<project-ref>.supabase.co
34
- - Port: 5432 (direct connection, not the pooler)
35
- - User: postgres
36
- - Database name: postgres
37
- - Password: the "Database Password" from Supabase → Settings → Database
38
- - SSL is required and handled automatically by matrx-orm's connection pool.
39
- """
40
-
41
- import os
42
- from pathlib import Path
43
-
44
- # ---------------------------------------------------------------------------
45
- # Load .env from this directory (if present)
46
- # ---------------------------------------------------------------------------
47
- try:
48
- from dotenv import load_dotenv
49
- _env_path = Path(__file__).parent / ".env"
50
- if _env_path.exists():
51
- load_dotenv(_env_path)
52
- except ImportError:
53
- # python-dotenv is optional — set env vars directly in your shell or CI
54
- pass
55
-
56
- from matrx_orm import DatabaseProjectConfig, register_database
57
-
58
-
59
- def setup_databases() -> None:
60
- """Register all database connections with matrx-orm."""
61
-
62
- # ------------------------------------------------------------------
63
- # 1. Primary database — main Supabase project (MY_MATRX)
64
- #
65
- # additional_schemas=["auth"] makes the auth schema visible to:
66
- # - Schema builder (generates auth.users stub model)
67
- # - ForeignKey resolution (fetch_fk on user_id columns works without
68
- # _unfetchable = True)
69
- # ------------------------------------------------------------------
70
- primary_password = os.environ.get("PRIMARY_DB_PASSWORD", "")
71
- if primary_password:
72
- primary_config = DatabaseProjectConfig(
73
- name="primary",
74
- alias="primary",
75
- host=os.environ.get("PRIMARY_DB_HOST", "db.viyklljfdhtidwecakwx.supabase.co"),
76
- port=os.environ.get("PRIMARY_DB_PORT", "5432"),
77
- database_name=os.environ.get("PRIMARY_DB_NAME", "postgres"),
78
- user=os.environ.get("PRIMARY_DB_USER", "postgres"),
79
- password=primary_password,
80
- additional_schemas=["auth"], # exposes auth.users and other auth.* tables
81
- )
82
- register_database(primary_config)
83
- else:
84
- print("[sample_project] PRIMARY_DB_PASSWORD not set — skipping primary database registration.")
85
-
86
- # ------------------------------------------------------------------
87
- # 2. Secondary database — second Supabase project (MATRX_DM)
88
- #
89
- # No additional_schemas declared — only the public schema is introspected.
90
- # No cross-database ForeignKey relationships are configured here yet.
91
- # To add cross-database FK fetching later, use:
92
- # user_id = ForeignKey(Users, to_column="id", to_db="primary")
93
- # ------------------------------------------------------------------
94
- secondary_password = os.environ.get("SECONDARY_DB_PASSWORD", "")
95
- if secondary_password:
96
- secondary_config = DatabaseProjectConfig(
97
- name="secondary",
98
- alias="secondary",
99
- host=os.environ.get("SECONDARY_DB_HOST", "db.deayzgwvqfdeskkdwudy.supabase.co"),
100
- port=os.environ.get("SECONDARY_DB_PORT", "5432"),
101
- database_name=os.environ.get("SECONDARY_DB_NAME", "postgres"),
102
- user=os.environ.get("SECONDARY_DB_USER", "postgres"),
103
- password=secondary_password,
104
- additional_schemas=[], # public schema only for now
105
- )
106
- register_database(secondary_config)
107
- else:
108
- print("[sample_project] SECONDARY_DB_PASSWORD not set — skipping secondary database registration.")
109
-
110
-
111
- # Run when imported directly for quick validation
112
- if __name__ == "__main__":
113
- setup_databases()
114
- print("Database registry configured successfully.")
115
- print(" primary → db.viyklljfdhtidwecakwx.supabase.co (auth schema enabled)")
116
- print(" secondary → db.deayzgwvqfdeskkdwudy.supabase.co (public schema only)")
@@ -1,156 +0,0 @@
1
- """
2
- Sample Project — Schema Generation Runner
3
- ==========================================
4
- Demonstrates the full schema generation workflow against real databases.
5
-
6
- Run from the repository root:
7
-
8
- python tests/sample_project/run_schema_generation.py
9
-
10
- Or run a specific database only:
11
-
12
- python tests/sample_project/run_schema_generation.py --db primary
13
- python tests/sample_project/run_schema_generation.py --db secondary
14
-
15
- What this script does
16
- ---------------------
17
- For each configured database it:
18
- 1. Registers the database config (reads credentials from .env)
19
- 2. Initialises SchemaManager — introspects tables, views, columns, FK/IFK/M2M
20
- 3. Generates Python model + manager files → generated/<db_name>/models/
21
- 4. Generates JSON schema files → generated/<db_name>/schema/
22
- 5. Prints a summary analysis to stdout
23
-
24
- The ``generated/`` directory is gitignored — it is safe to delete and regenerate
25
- at any time.
26
-
27
- Typical output structure
28
- ------------------------
29
- tests/sample_project/
30
- ├── generated/
31
- │ ├── primary/
32
- │ │ ├── models/ ← Python Model + Manager files
33
- │ │ └── schema/ ← JSON schema files
34
- │ └── secondary/
35
- │ ├── models/
36
- │ └── schema/
37
- """
38
-
39
- import argparse
40
- import sys
41
- import os
42
- from pathlib import Path
43
-
44
- # Allow running from the repo root without installing the package
45
- sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))
46
-
47
- # Register databases first
48
- from tests.sample_project.database_registry import setup_databases # noqa: E402
49
-
50
- setup_databases()
51
-
52
- from matrx_orm.schema_builder.schema_manager import SchemaManager # noqa: E402
53
-
54
- # Output base directory — gitignored
55
- OUTPUT_BASE = Path(__file__).parent / "generated"
56
-
57
- DATABASES = {
58
- "primary": {
59
- "database_project": "primary",
60
- "schema": "public",
61
- "additional_schemas": ["auth"],
62
- "description": "Main Supabase project (public + auth schemas)",
63
- },
64
- "secondary": {
65
- "database_project": "secondary",
66
- "schema": "public",
67
- "additional_schemas": [],
68
- "description": "Second Supabase project (public schema only)",
69
- },
70
- }
71
-
72
-
73
- def run_generation(db_name: str, cfg: dict) -> dict:
74
- """Run full schema generation for one database. Returns a summary dict."""
75
- output_dir = OUTPUT_BASE / db_name
76
- output_dir.mkdir(parents=True, exist_ok=True)
77
-
78
- print(f"\n{'='*60}")
79
- print(f" Database: {db_name}")
80
- print(f" {cfg['description']}")
81
- print(f" Output: {output_dir}")
82
- print(f"{'='*60}")
83
-
84
- print(f"\n[{db_name}] Initialising SchemaManager...")
85
- sm = SchemaManager(
86
- schema=cfg["schema"],
87
- database_project=cfg["database_project"],
88
- additional_schemas=cfg["additional_schemas"],
89
- save_direct=False,
90
- )
91
- sm.initialize()
92
-
93
- table_count = len(sm.schema.tables) if hasattr(sm.schema, "tables") else "?"
94
- view_count = len(sm.schema.views) if hasattr(sm.schema, "views") else "?"
95
- print(f"[{db_name}] Introspected {table_count} tables, {view_count} views.")
96
-
97
- print(f"[{db_name}] Generating schema files...")
98
- schema_entry = sm.schema.generate_schema_files()
99
-
100
- print(f"[{db_name}] Generating Python model + manager files...")
101
- models = sm.schema.generate_models()
102
-
103
- print(f"[{db_name}] Running schema analysis...")
104
- analysis = sm.analyze_schema()
105
-
106
- summary = {
107
- "db": db_name,
108
- "tables": table_count,
109
- "views": view_count,
110
- "analysis": analysis,
111
- }
112
-
113
- print(f"[{db_name}] Done.")
114
- return summary
115
-
116
-
117
- def main() -> None:
118
- parser = argparse.ArgumentParser(
119
- description="matrx-orm sample project — schema generation runner"
120
- )
121
- parser.add_argument(
122
- "--db",
123
- choices=list(DATABASES.keys()) + ["all"],
124
- default="all",
125
- help="Which database to generate (default: all)",
126
- )
127
- args = parser.parse_args()
128
-
129
- target_dbs = list(DATABASES.items()) if args.db == "all" else [(args.db, DATABASES[args.db])]
130
-
131
- results = []
132
- errors = []
133
-
134
- for db_name, cfg in target_dbs:
135
- try:
136
- summary = run_generation(db_name, cfg)
137
- results.append(summary)
138
- except Exception as exc:
139
- print(f"\n[{db_name}] ERROR: {exc}")
140
- errors.append((db_name, exc))
141
-
142
- # Final summary
143
- print(f"\n{'='*60}")
144
- print(" Schema Generation Complete")
145
- print(f"{'='*60}")
146
- for r in results:
147
- print(f" {r['db']:12s} {r['tables']} tables, {r['views']} views")
148
- for db_name, exc in errors:
149
- print(f" {db_name:12s} FAILED: {exc}")
150
-
151
- if errors:
152
- sys.exit(1)
153
-
154
-
155
- if __name__ == "__main__":
156
- main()
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