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.
- matrx_orm-2.0.2/.env.example +11 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/PKG-INFO +2 -1
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/README.md +1 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/pyproject.toml +1 -1
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/client/postgres_connection.py +3 -2
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/config.py +5 -1
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/python_sql/db_objects.py +1 -1
- matrx_orm-2.0.2/tests/sample_project/database_registry.py +52 -0
- matrx_orm-2.0.2/tests/sample_project/run_schema_generation.py +61 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/sample_project/test_schema_generation.py +4 -1
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/uv.lock +1 -1
- matrx_orm-2.0.1/.env.example +0 -12
- matrx_orm-2.0.1/scripts/update_package.sh +0 -200
- matrx_orm-2.0.1/tests/sample_project/database_registry.py +0 -116
- matrx_orm-2.0.1/tests/sample_project/run_schema_generation.py +0 -156
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/.arman/pending/versioning/INITIAL.md +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/.github/workflows/publish.yml +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/.gitignore +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/.python-version +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/CLAUDE.md +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/MIGRATIONS.md +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/RESERVED_NAMES.md +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/docs/migrations.md +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/main.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/release.sh +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/adapters/postgresql.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/async_db_manager.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/base.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/expressions.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/extended.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/fields.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/registry.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/relations.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/signals.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/core/transaction.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/error_handling.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/exceptions.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/operations/create.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/operations/read.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/operations/update.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/python_sql/table_detailed_relationships.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/python_sql/table_typescript_relationship.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/query/builder.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/query/executor.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/columns.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/common.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/helpers/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/helpers/git_checker.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/schema.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/schema_manager.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/state.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/conftest.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_config.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_fields.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_registry.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_relations.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level1/test_state_cache.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/__init__.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/conftest.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_crud.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_manager.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/sample_project/.env.example +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/sample_project/README.md +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-2.0.1 → matrx_orm-2.0.2}/tests/schema/test_generate_schema.py +0 -0
- {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.
|
|
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.
|
|
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"
|
|
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="
|
|
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"
|
|
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
|
|
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
|
-
|
|
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
|
|
matrx_orm-2.0.1/.env.example
DELETED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/python_sql/table_detailed_relationships.py
RENAMED
|
File without changes
|
{matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/python_sql/table_typescript_relationship.py
RENAMED
|
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
|
{matrx_orm-2.0.1 → matrx_orm-2.0.2}/src/matrx_orm/schema_builder/helpers/entity_generators.py
RENAMED
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|