matrx-orm 2.0.2__tar.gz → 2.0.4__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 → matrx_orm-2.0.4}/PKG-INFO +2 -1
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/pyproject.toml +2 -1
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/release.sh +7 -2
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/__init__.py +2 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/client/postgres_connection.py +2 -1
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/config.py +82 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/python_sql/db_objects.py +4 -3
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/python_sql/table_detailed_relationships.py +4 -4
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/python_sql/table_typescript_relationship.py +5 -3
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/__init__.py +4 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/common.py +6 -6
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/helpers/__init__.py +2 -5
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/helpers/git_checker.py +15 -11
- matrx_orm-2.0.4/src/matrx_orm/schema_builder/runner.py +160 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/schema_manager.py +4 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/sample_project/.env.example +10 -5
- matrx_orm-2.0.4/tests/sample_project/generate.py +3 -0
- matrx_orm-2.0.4/tests/sample_project/matrx_orm.yaml +57 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/uv.lock +67 -1
- matrx_orm-2.0.2/tests/sample_project/database_registry.py +0 -52
- matrx_orm-2.0.2/tests/sample_project/run_schema_generation.py +0 -61
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/.arman/pending/versioning/INITIAL.md +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/.env.example +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/.github/workflows/publish.yml +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/.gitignore +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/.python-version +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/CLAUDE.md +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/MIGRATIONS.md +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/README.md +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/RESERVED_NAMES.md +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/docs/migrations.md +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/main.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/adapters/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/adapters/base_adapter.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/adapters/postgresql.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/client/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/async_db_manager.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/base.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/expressions.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/extended.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/fields.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/paginator.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/registry.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/relations.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/signals.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/core/transaction.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/error_handling.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/exceptions.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/extended/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/extended/app_error_handler.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/middleware/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/middleware/base.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/migrations/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/migrations/cli.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/migrations/ddl.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/migrations/diff.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/migrations/executor.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/migrations/integration.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/migrations/loader.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/migrations/operations.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/migrations/state.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/migrations/table_filter.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/operations/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/operations/create.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/operations/delete.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/operations/read.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/operations/update.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/python_sql/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/query/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/query/builder.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/query/executor.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/columns.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/generator.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/helpers/base_generators.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/helpers/entity_generators.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/relationships.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/schema.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/tables.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/schema_builder/views.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/sql_executor/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/sql_executor/executor.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/sql_executor/queries.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/sql_executor/registry.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/sql_executor/types.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/sql_executor/utils.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/state.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/utils/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/utils/sql_utils.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/utils/type_converters.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/conftest.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_config.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_ddl_generator.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_exceptions.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_fields.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_migration_diff_types.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_migration_loader.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_model_instance.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_model_meta.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_query_builder.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_query_executor_sql.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_registry.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_relations.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level1/test_state_cache.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/__init__.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/conftest.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/test_bulk_ops.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/test_cache_integration.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/test_crud.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/test_foreign_keys.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/test_m2m.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/test_manager.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/test_migrations_live.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/test_query_execution.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/level2/test_schema_diff.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/sample_project/README.md +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/sample_project/generated/.gitkeep +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/sample_project/test_schema_generation.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/schema/entity_tests.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/schema/test_base_generation.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/tests/schema/test_generate_schema.py +0 -0
- {matrx_orm-2.0.2 → matrx_orm-2.0.4}/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.
|
|
3
|
+
Version: 2.0.4
|
|
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
|
|
@@ -31,6 +31,7 @@ Requires-Dist: gitpython>=3.1.40
|
|
|
31
31
|
Requires-Dist: matrx-utils>=1.0.4
|
|
32
32
|
Requires-Dist: psycopg-pool>=3.2.5
|
|
33
33
|
Requires-Dist: psycopg[binary]>=3.2.5
|
|
34
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
34
35
|
Provides-Extra: dev
|
|
35
36
|
Requires-Dist: pytest-asyncio>=1.0; extra == 'dev'
|
|
36
37
|
Requires-Dist: pytest>=9.0; extra == 'dev'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "matrx-orm"
|
|
3
|
-
version = "2.0.
|
|
3
|
+
version = "2.0.4"
|
|
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" }
|
|
@@ -45,6 +45,7 @@ dependencies = [
|
|
|
45
45
|
"psycopg[binary]>=3.2.5",
|
|
46
46
|
"psycopg-pool>=3.2.5",
|
|
47
47
|
"matrx-utils>=1.0.4",
|
|
48
|
+
"pyyaml>=6.0.3",
|
|
48
49
|
]
|
|
49
50
|
|
|
50
51
|
[project.optional-dependencies]
|
|
@@ -67,7 +67,7 @@ echo ""
|
|
|
67
67
|
# ── Update pyproject.toml and amend the commit ─────────────────────────────
|
|
68
68
|
|
|
69
69
|
info "Updating $PYPROJECT to version $NEW_VERSION..."
|
|
70
|
-
sed -i "s/^version = \"$CURRENT_VERSION\"/version = \"$NEW_VERSION\"/" "$PYPROJECT"
|
|
70
|
+
sed -i '' "s/^version = \"$CURRENT_VERSION\"/version = \"$NEW_VERSION\"/" "$PYPROJECT"
|
|
71
71
|
ok "Version updated in $PYPROJECT"
|
|
72
72
|
|
|
73
73
|
info "Amending last commit to include version bump..."
|
|
@@ -99,6 +99,11 @@ echo -e "${GREEN} Released matrx-orm $NEW_VERSION${NC}"
|
|
|
99
99
|
echo -e "${GREEN} GitHub Actions will now build and publish to PyPI.${NC}"
|
|
100
100
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
101
101
|
echo ""
|
|
102
|
+
echo ""
|
|
103
|
+
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
102
104
|
echo -e " Monitor: ${CYAN}https://github.com/armanisadeghi/matrx-orm/actions${NC}"
|
|
103
|
-
echo -e " Update: ${CYAN}uv add matrx-orm
|
|
105
|
+
echo -e " Update: ${CYAN}uv add matrx-orm==${NEW_VERSION}${NC}"
|
|
106
|
+
echo ""
|
|
107
|
+
echo -e " --> Not Available Yet? Speed up indexing: ${CYAN}pip index versions matrx-orm${NC}"
|
|
108
|
+
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
104
109
|
echo ""
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from .core.config import (
|
|
2
2
|
DatabaseProjectConfig,
|
|
3
3
|
register_database,
|
|
4
|
+
register_database_from_env,
|
|
4
5
|
get_database_config,
|
|
5
6
|
get_connection_string,
|
|
6
7
|
get_manager_config,
|
|
@@ -131,6 +132,7 @@ from .migrations import (
|
|
|
131
132
|
__all__ = [
|
|
132
133
|
"DatabaseProjectConfig",
|
|
133
134
|
"register_database",
|
|
135
|
+
"register_database_from_env",
|
|
134
136
|
"get_database_config",
|
|
135
137
|
"get_connection_string",
|
|
136
138
|
"get_manager_config",
|
|
@@ -31,8 +31,9 @@ def init_connection_details(config_name):
|
|
|
31
31
|
f"Incomplete database configuration for '{config_name}'. " "Please check your environment variables or settings.")
|
|
32
32
|
|
|
33
33
|
connection_string = f"{db_protocol}://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}"
|
|
34
|
+
redacted = f"{db_protocol}://{db_user}:****@{db_host}:{db_port}/{db_name}"
|
|
34
35
|
|
|
35
|
-
vcprint(f"\n[Matrx ORM] Connection String:\n{
|
|
36
|
+
vcprint(f"\n[Matrx ORM] Connection String:\n{redacted}\n", color="yellow")
|
|
36
37
|
|
|
37
38
|
connection_pools[config_name] = ConnectionPool(
|
|
38
39
|
connection_string,
|
|
@@ -161,6 +161,88 @@ def register_database(config: DatabaseProjectConfig) -> None:
|
|
|
161
161
|
registry.register(config)
|
|
162
162
|
|
|
163
163
|
|
|
164
|
+
def register_database_from_env(
|
|
165
|
+
name: str,
|
|
166
|
+
env_prefix: str,
|
|
167
|
+
alias: str = "",
|
|
168
|
+
additional_schemas: list = None,
|
|
169
|
+
entity_overrides: Dict = None,
|
|
170
|
+
field_overrides: Dict = None,
|
|
171
|
+
manager_config_overrides: Dict = None,
|
|
172
|
+
) -> bool:
|
|
173
|
+
"""
|
|
174
|
+
Read database connection details from environment variables, validate them,
|
|
175
|
+
and register the database. Prints colored diagnostics for missing or defaulted vars.
|
|
176
|
+
|
|
177
|
+
Required env vars (using env_prefix, e.g. "PRIMARY_DB"):
|
|
178
|
+
{env_prefix}_HOST, {env_prefix}_PORT, {env_prefix}_NAME,
|
|
179
|
+
{env_prefix}_USER, {env_prefix}_PASSWORD
|
|
180
|
+
|
|
181
|
+
Optional env vars:
|
|
182
|
+
{env_prefix}_PROTOCOL — defaults to "postgresql"
|
|
183
|
+
|
|
184
|
+
Returns True if registration succeeded, False otherwise.
|
|
185
|
+
"""
|
|
186
|
+
_REQUIRED = ["HOST", "PORT", "NAME", "USER", "PASSWORD"]
|
|
187
|
+
_OPTIONAL = {"PROTOCOL": "postgresql"}
|
|
188
|
+
|
|
189
|
+
vcprint(f"[matrx-orm] Registering database '{name}'...", color="cyan")
|
|
190
|
+
|
|
191
|
+
missing: list[str] = []
|
|
192
|
+
resolved: dict[str, str] = {}
|
|
193
|
+
|
|
194
|
+
for key in _REQUIRED:
|
|
195
|
+
env_var = f"{env_prefix}_{key}"
|
|
196
|
+
val = os.environ.get(env_var, "").strip()
|
|
197
|
+
if val:
|
|
198
|
+
resolved[key] = val
|
|
199
|
+
else:
|
|
200
|
+
missing.append(env_var)
|
|
201
|
+
|
|
202
|
+
for key, default in _OPTIONAL.items():
|
|
203
|
+
env_var = f"{env_prefix}_{key}"
|
|
204
|
+
val = os.environ.get(env_var, "").strip()
|
|
205
|
+
if val:
|
|
206
|
+
resolved[key] = val
|
|
207
|
+
else:
|
|
208
|
+
resolved[key] = default
|
|
209
|
+
vcprint(
|
|
210
|
+
f" '{env_var}' not set — using default: '{default}'",
|
|
211
|
+
color="yellow",
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
if missing:
|
|
215
|
+
vcprint(
|
|
216
|
+
f" Database '{name}' NOT registered — missing required env vars:",
|
|
217
|
+
color="red",
|
|
218
|
+
)
|
|
219
|
+
for var in missing:
|
|
220
|
+
vcprint(f" • {var}", color="red")
|
|
221
|
+
return False
|
|
222
|
+
|
|
223
|
+
try:
|
|
224
|
+
config = DatabaseProjectConfig(
|
|
225
|
+
name=name,
|
|
226
|
+
alias=alias or name,
|
|
227
|
+
host=resolved["HOST"],
|
|
228
|
+
port=resolved["PORT"],
|
|
229
|
+
protocol=resolved["PROTOCOL"],
|
|
230
|
+
database_name=resolved["NAME"],
|
|
231
|
+
user=resolved["USER"],
|
|
232
|
+
password=resolved["PASSWORD"],
|
|
233
|
+
additional_schemas=additional_schemas or [],
|
|
234
|
+
entity_overrides=entity_overrides or {},
|
|
235
|
+
field_overrides=field_overrides or {},
|
|
236
|
+
manager_config_overrides=manager_config_overrides or {},
|
|
237
|
+
)
|
|
238
|
+
registry.register(config)
|
|
239
|
+
vcprint(f" Database '{name}' registered successfully.", color="green")
|
|
240
|
+
return True
|
|
241
|
+
except DatabaseConfigError as e:
|
|
242
|
+
vcprint(f" Database '{name}' registration failed: {e}", color="red")
|
|
243
|
+
return False
|
|
244
|
+
|
|
245
|
+
|
|
164
246
|
def get_connection_string(config_name: str) -> str:
|
|
165
247
|
config = get_database_config(config_name)
|
|
166
248
|
connection_string = f"{config['protocol']}://{config['user']}:{redact_string(config['password'])}@{config['host']}:{config['port']}/{config['database_name']}"
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
from matrx_orm.client.postgres_connection import execute_sql_query
|
|
2
2
|
from collections import defaultdict
|
|
3
3
|
from matrx_orm.python_sql.table_typescript_relationship import get_ts_object
|
|
4
|
+
from matrx_orm.schema_builder.common import DEBUG_CONFIG
|
|
4
5
|
|
|
5
|
-
verbose =
|
|
6
|
-
debug =
|
|
7
|
-
info =
|
|
6
|
+
verbose = DEBUG_CONFIG["verbose"]
|
|
7
|
+
debug = DEBUG_CONFIG["debug"]
|
|
8
|
+
info = DEBUG_CONFIG["info"]
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
def get_full_db_objects(schema, database_project):
|
{matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/python_sql/table_detailed_relationships.py
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
from matrx_orm.client.postgres_connection import execute_sql_query
|
|
2
|
+
from matrx_orm.schema_builder.common import DEBUG_CONFIG
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
info = True
|
|
4
|
+
verbose = DEBUG_CONFIG["verbose"]
|
|
5
|
+
debug = DEBUG_CONFIG["debug"]
|
|
6
|
+
info = DEBUG_CONFIG["info"]
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def get_table_relationships(schema, database_project):
|
{matrx_orm-2.0.2 → matrx_orm-2.0.4}/src/matrx_orm/python_sql/table_typescript_relationship.py
RENAMED
|
@@ -4,9 +4,11 @@ from matrx_orm.python_sql.table_detailed_relationships import (
|
|
|
4
4
|
analyze_relationships,
|
|
5
5
|
)
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
from matrx_orm.schema_builder.common import DEBUG_CONFIG
|
|
8
|
+
|
|
9
|
+
verbose = DEBUG_CONFIG["verbose"]
|
|
10
|
+
debug = DEBUG_CONFIG["debug"]
|
|
11
|
+
info = DEBUG_CONFIG["info"]
|
|
10
12
|
|
|
11
13
|
|
|
12
14
|
def transform_relationships_for_typescript(relationships_data, junction_analysis):
|
|
@@ -16,6 +16,9 @@ from matrx_orm.schema_builder.helpers import (
|
|
|
16
16
|
from matrx_orm.schema_builder.schema_manager import (
|
|
17
17
|
SchemaManager,
|
|
18
18
|
)
|
|
19
|
+
from matrx_orm.schema_builder.runner import (
|
|
20
|
+
run_schema_generation,
|
|
21
|
+
)
|
|
19
22
|
|
|
20
23
|
|
|
21
24
|
__all__ = [
|
|
@@ -24,6 +27,7 @@ __all__ = [
|
|
|
24
27
|
"DEBUG_CONFIG",
|
|
25
28
|
"schema_builder_verbose",
|
|
26
29
|
"SchemaManager",
|
|
30
|
+
"run_schema_generation",
|
|
27
31
|
"check_git_status",
|
|
28
32
|
"get_schema_structure",
|
|
29
33
|
"generate_dto_and_manager",
|
|
@@ -13,14 +13,14 @@ ADMIN_TS_ROOT = os.getenv("ADMIN_TS_ROOT", "")
|
|
|
13
13
|
|
|
14
14
|
dt_utils = DataTransformer()
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
# Central debug configuration for the entire schema builder.
|
|
17
|
+
# Values can be overridden at runtime by run_schema_generation() from the yaml
|
|
18
|
+
# debug section, or by setting env vars MATRX_DEBUG, MATRX_VERBOSE, MATRX_INFO.
|
|
19
19
|
DEBUG_CONFIG = {
|
|
20
20
|
"tables": [],
|
|
21
21
|
"columns": [],
|
|
22
22
|
"base_type": [],
|
|
23
|
-
"info":
|
|
24
|
-
"debug":
|
|
25
|
-
"verbose":
|
|
23
|
+
"info": os.getenv("MATRX_INFO", "").lower() in ("1", "true"),
|
|
24
|
+
"debug": os.getenv("MATRX_DEBUG", "").lower() in ("1", "true"),
|
|
25
|
+
"verbose": os.getenv("MATRX_VERBOSE", "").lower() in ("1", "true"),
|
|
26
26
|
}
|
|
@@ -15,11 +15,8 @@ from matrx_orm.schema_builder.helpers.entity_generators import (
|
|
|
15
15
|
generate_typescript_entity,
|
|
16
16
|
)
|
|
17
17
|
|
|
18
|
-
from matrx_orm.schema_builder.
|
|
19
|
-
|
|
20
|
-
ADMIN_TS_ROOT,
|
|
21
|
-
check_git_status,
|
|
22
|
-
)
|
|
18
|
+
from matrx_orm.schema_builder.common import ADMIN_PYTHON_ROOT, ADMIN_TS_ROOT
|
|
19
|
+
from matrx_orm.schema_builder.helpers.git_checker import check_git_status
|
|
23
20
|
from matrx_orm.schema_builder.helpers.base_generators import (
|
|
24
21
|
generate_active_methods,
|
|
25
22
|
generate_active_relation_methods,
|
|
@@ -2,18 +2,24 @@ import os
|
|
|
2
2
|
import sys
|
|
3
3
|
from git import Repo, GitCommandError, InvalidGitRepositoryError
|
|
4
4
|
from matrx_utils import vcprint
|
|
5
|
-
from matrx_orm.schema_builder.common import ADMIN_PYTHON_ROOT, ADMIN_TS_ROOT
|
|
6
5
|
|
|
7
6
|
|
|
8
|
-
def check_git_status(save_direct):
|
|
7
|
+
def check_git_status(save_direct: bool, python_root: str = "", ts_root: str = "") -> bool:
|
|
9
8
|
"""
|
|
10
|
-
Check if
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
Check if python_root and ts_root are git repositories with no uncommitted
|
|
10
|
+
changes before allowing a save_direct write that could overwrite live files.
|
|
11
|
+
|
|
12
|
+
Falls back to ADMIN_PYTHON_ROOT / ADMIN_TS_ROOT env vars when the caller
|
|
13
|
+
doesn't supply explicit paths (backward-compat).
|
|
14
|
+
|
|
15
|
+
Returns True if safe to proceed, exits with code 1 if not.
|
|
13
16
|
"""
|
|
17
|
+
python_root = python_root or os.getenv("ADMIN_PYTHON_ROOT", "")
|
|
18
|
+
ts_root = ts_root or os.getenv("ADMIN_TS_ROOT", "")
|
|
19
|
+
|
|
14
20
|
roots_to_check = [
|
|
15
|
-
("
|
|
16
|
-
("
|
|
21
|
+
("Python root", python_root),
|
|
22
|
+
("TypeScript root", ts_root),
|
|
17
23
|
]
|
|
18
24
|
has_issues = False
|
|
19
25
|
|
|
@@ -25,10 +31,8 @@ def check_git_status(save_direct):
|
|
|
25
31
|
return True
|
|
26
32
|
|
|
27
33
|
vcprint("\n[MATRX GIT CHECKER] Checking git repository status...", color="yellow")
|
|
28
|
-
vcprint(
|
|
29
|
-
|
|
30
|
-
)
|
|
31
|
-
vcprint(f"[MATRX GIT CHECKER] ADMIN_TS_ROOT: {ADMIN_TS_ROOT}", color="green")
|
|
34
|
+
vcprint(f"[MATRX GIT CHECKER] Python root: {python_root}", color="green")
|
|
35
|
+
vcprint(f"[MATRX GIT CHECKER] TypeScript root: {ts_root}", color="green")
|
|
32
36
|
print()
|
|
33
37
|
|
|
34
38
|
for root_name, root_path in roots_to_check:
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""
|
|
2
|
+
run_schema_generation() — the single entry point for yaml-driven reverse migrations.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
from matrx_orm.schema_builder import run_schema_generation
|
|
6
|
+
run_schema_generation("matrx_orm.yaml")
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
from dotenv import load_dotenv
|
|
17
|
+
from matrx_utils import vcprint
|
|
18
|
+
|
|
19
|
+
from matrx_orm.core.config import register_database_from_env, DatabaseConfigError
|
|
20
|
+
from matrx_orm.schema_builder.common import DEBUG_CONFIG
|
|
21
|
+
from matrx_orm.schema_builder.helpers.git_checker import check_git_status
|
|
22
|
+
from matrx_orm.schema_builder.schema_manager import SchemaManager
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _load_yaml(path: Path) -> dict[str, Any]:
|
|
26
|
+
try:
|
|
27
|
+
import yaml
|
|
28
|
+
except ImportError:
|
|
29
|
+
raise ImportError(
|
|
30
|
+
"PyYAML is required for yaml-based configuration. "
|
|
31
|
+
"Install it with: pip install pyyaml"
|
|
32
|
+
)
|
|
33
|
+
with open(path) as f:
|
|
34
|
+
return yaml.safe_load(f) or {}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def run_schema_generation(config_path: str | Path = "matrx_orm.yaml") -> None:
|
|
38
|
+
"""
|
|
39
|
+
Read a matrx_orm.yaml config file, register all databases, apply debug
|
|
40
|
+
settings, then run reverse-migration schema generation for each entry in
|
|
41
|
+
the ``generate`` list.
|
|
42
|
+
|
|
43
|
+
The config file is looked up relative to the calling script's directory
|
|
44
|
+
(i.e. the directory that contains generate.py), so users never need to
|
|
45
|
+
think about working-directory quirks.
|
|
46
|
+
"""
|
|
47
|
+
# Resolve config path relative to the caller's file location
|
|
48
|
+
caller_dir = Path(sys.argv[0]).parent.resolve()
|
|
49
|
+
config_path = (caller_dir / config_path).resolve()
|
|
50
|
+
|
|
51
|
+
if not config_path.exists():
|
|
52
|
+
raise FileNotFoundError(
|
|
53
|
+
f"matrx-orm config not found: {config_path}\n"
|
|
54
|
+
f"Create a matrx_orm.yaml file next to your generate.py script."
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
vcprint(f"[matrx-orm] Loading config: {config_path}", color="cyan")
|
|
58
|
+
|
|
59
|
+
# Load .env from the same directory as the config file
|
|
60
|
+
env_file = config_path.parent / ".env"
|
|
61
|
+
if env_file.exists():
|
|
62
|
+
load_dotenv(env_file)
|
|
63
|
+
else:
|
|
64
|
+
load_dotenv() # fallback to default search
|
|
65
|
+
|
|
66
|
+
cfg = _load_yaml(config_path)
|
|
67
|
+
|
|
68
|
+
# -------------------------------------------------------------------------
|
|
69
|
+
# Debug settings
|
|
70
|
+
# -------------------------------------------------------------------------
|
|
71
|
+
debug_cfg = cfg.get("debug", {})
|
|
72
|
+
DEBUG_CONFIG["info"] = bool(debug_cfg.get("info", False))
|
|
73
|
+
DEBUG_CONFIG["debug"] = bool(debug_cfg.get("debug", False))
|
|
74
|
+
DEBUG_CONFIG["verbose"] = bool(debug_cfg.get("verbose", False))
|
|
75
|
+
|
|
76
|
+
# -------------------------------------------------------------------------
|
|
77
|
+
# Output directories + save_direct
|
|
78
|
+
# -------------------------------------------------------------------------
|
|
79
|
+
output_cfg = cfg.get("output", {})
|
|
80
|
+
base = config_path.parent
|
|
81
|
+
save_direct = bool(output_cfg.get("save_direct", False))
|
|
82
|
+
|
|
83
|
+
python_root = ""
|
|
84
|
+
ts_root = ""
|
|
85
|
+
|
|
86
|
+
if "python_root" in output_cfg:
|
|
87
|
+
python_root = str((base / output_cfg["python_root"]).resolve())
|
|
88
|
+
os.environ["ADMIN_PYTHON_ROOT"] = python_root
|
|
89
|
+
|
|
90
|
+
if "typescript_root" in output_cfg:
|
|
91
|
+
ts_root = str((base / output_cfg["typescript_root"]).resolve())
|
|
92
|
+
os.environ["ADMIN_TS_ROOT"] = ts_root
|
|
93
|
+
|
|
94
|
+
# -------------------------------------------------------------------------
|
|
95
|
+
# Git safety check — must run before any generation when save_direct=True
|
|
96
|
+
# -------------------------------------------------------------------------
|
|
97
|
+
check_git_status(save_direct, python_root=python_root, ts_root=ts_root)
|
|
98
|
+
|
|
99
|
+
# -------------------------------------------------------------------------
|
|
100
|
+
# Register databases
|
|
101
|
+
# -------------------------------------------------------------------------
|
|
102
|
+
databases = cfg.get("databases", [])
|
|
103
|
+
if not databases:
|
|
104
|
+
vcprint("[matrx-orm] No databases defined in matrx_orm.yaml — nothing to do.", color="yellow")
|
|
105
|
+
return
|
|
106
|
+
|
|
107
|
+
for db in databases:
|
|
108
|
+
name = db.get("name")
|
|
109
|
+
prefix = db.get("env_prefix")
|
|
110
|
+
if not name or not prefix:
|
|
111
|
+
vcprint(f"[matrx-orm] Skipping database entry missing 'name' or 'env_prefix': {db}", color="yellow")
|
|
112
|
+
continue
|
|
113
|
+
|
|
114
|
+
register_database_from_env(
|
|
115
|
+
name=name,
|
|
116
|
+
env_prefix=prefix,
|
|
117
|
+
additional_schemas=db.get("additional_schemas", []),
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# -------------------------------------------------------------------------
|
|
121
|
+
# Run generation for each configured target
|
|
122
|
+
# -------------------------------------------------------------------------
|
|
123
|
+
generate_list = cfg.get("generate", [])
|
|
124
|
+
if not generate_list:
|
|
125
|
+
vcprint("[matrx-orm] No entries in 'generate' — databases registered but nothing generated.", color="yellow")
|
|
126
|
+
return
|
|
127
|
+
|
|
128
|
+
for entry in generate_list:
|
|
129
|
+
db_name = entry.get("database")
|
|
130
|
+
schema = entry.get("schema", "public")
|
|
131
|
+
|
|
132
|
+
vcprint(
|
|
133
|
+
f"[matrx-orm] Generating schema for database='{db_name}' schema='{schema}'",
|
|
134
|
+
color="cyan",
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
manager = SchemaManager(
|
|
139
|
+
schema=schema,
|
|
140
|
+
database_project=db_name,
|
|
141
|
+
save_direct=save_direct,
|
|
142
|
+
)
|
|
143
|
+
manager.initialize()
|
|
144
|
+
manager.schema.generate_schema_files()
|
|
145
|
+
manager.schema.generate_models()
|
|
146
|
+
vcprint(
|
|
147
|
+
f"[matrx-orm] Done — database='{db_name}' schema='{schema}'",
|
|
148
|
+
color="green",
|
|
149
|
+
)
|
|
150
|
+
except DatabaseConfigError as e:
|
|
151
|
+
vcprint(
|
|
152
|
+
f"[matrx-orm] Skipping '{db_name}': {e}",
|
|
153
|
+
color="red",
|
|
154
|
+
)
|
|
155
|
+
except Exception as e:
|
|
156
|
+
vcprint(
|
|
157
|
+
f"[matrx-orm] Error generating '{db_name}': {e}",
|
|
158
|
+
color="red",
|
|
159
|
+
)
|
|
160
|
+
raise
|
|
@@ -66,6 +66,10 @@ class SchemaManager:
|
|
|
66
66
|
set(exclude_tables) if exclude_tables is not None else None
|
|
67
67
|
)
|
|
68
68
|
|
|
69
|
+
vcprint(self.schema, title=f"SCHEMA MANAGER] with schema", verbose=self.verbose, color="blue")
|
|
70
|
+
vcprint(self.database_project, title=f"SCHEMA MANAGER] with database project", verbose=self.verbose, color="blue")
|
|
71
|
+
vcprint(self.additional_schemas, title=f"SCHEMA MANAGER] with additional schemas", verbose=self.verbose, color="blue")
|
|
72
|
+
|
|
69
73
|
# Propagate filter to the Schema so generate_models() can apply it at
|
|
70
74
|
# write-time without touching any loading or relationship logic.
|
|
71
75
|
self.schema._include_tables = self._include_tables
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
# ============================================================
|
|
2
|
-
# matrx-orm Sample Project — Environment
|
|
2
|
+
# matrx-orm Sample Project — Environment Variables
|
|
3
3
|
# ============================================================
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
BASE_DIR=enter_your_base_directory_here
|
|
6
|
+
ADMIN_PYTHON_ROOT=enter_your_python_root_here
|
|
7
|
+
ADMIN_TS_ROOT=enter_your_typescript_root_here
|
|
8
|
+
|
|
6
9
|
|
|
7
10
|
# --- Primary database (e.g. your main Supabase project) ---
|
|
8
|
-
PRIMARY_DB_HOST=
|
|
11
|
+
PRIMARY_DB_HOST=enter_your_primary_db_host_here
|
|
9
12
|
PRIMARY_DB_PORT=5432
|
|
13
|
+
PRIMARY_DB_PROTOCOL=postgresql
|
|
10
14
|
PRIMARY_DB_NAME=postgres
|
|
11
15
|
PRIMARY_DB_USER=postgres
|
|
12
16
|
PRIMARY_DB_PASSWORD=your-database-password-here
|
|
13
17
|
|
|
14
18
|
# --- Secondary database (e.g. a second Supabase project or remote Postgres) ---
|
|
15
|
-
SECONDARY_DB_HOST=
|
|
19
|
+
SECONDARY_DB_HOST=enter_your_secondary_db_host_here
|
|
16
20
|
SECONDARY_DB_PORT=5432
|
|
21
|
+
SECONDARY_DB_PROTOCOL=postgresql
|
|
17
22
|
SECONDARY_DB_NAME=postgres
|
|
18
23
|
SECONDARY_DB_USER=postgres
|
|
19
24
|
SECONDARY_DB_PASSWORD=your-database-password-here
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# matrx-orm configuration
|
|
3
|
+
# =============================================================================
|
|
4
|
+
#
|
|
5
|
+
# This file drives reverse-migration schema generation.
|
|
6
|
+
# Run: python generate.py
|
|
7
|
+
#
|
|
8
|
+
# Output directories for generated files.
|
|
9
|
+
# Use absolute paths or paths relative to this config file.
|
|
10
|
+
output:
|
|
11
|
+
python_root: generated/python
|
|
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
|
|
17
|
+
|
|
18
|
+
# =============================================================================
|
|
19
|
+
# Databases
|
|
20
|
+
# =============================================================================
|
|
21
|
+
# Add as many databases as you need. Each entry needs a unique name.
|
|
22
|
+
# The env_prefix tells matrx-orm which environment variables hold the
|
|
23
|
+
# connection details. For a prefix of "PRIMARY_DB" it reads:
|
|
24
|
+
# PRIMARY_DB_HOST, PRIMARY_DB_PORT, PRIMARY_DB_NAME,
|
|
25
|
+
# PRIMARY_DB_USER, PRIMARY_DB_PASSWORD
|
|
26
|
+
# PRIMARY_DB_PROTOCOL (optional, defaults to "postgresql")
|
|
27
|
+
#
|
|
28
|
+
databases:
|
|
29
|
+
- name: primary
|
|
30
|
+
env_prefix: PRIMARY_DB
|
|
31
|
+
additional_schemas:
|
|
32
|
+
- auth
|
|
33
|
+
|
|
34
|
+
- name: secondary
|
|
35
|
+
env_prefix: SECONDARY_DB
|
|
36
|
+
|
|
37
|
+
# =============================================================================
|
|
38
|
+
# Schema generation
|
|
39
|
+
# =============================================================================
|
|
40
|
+
# Each entry below triggers one reverse-migration run.
|
|
41
|
+
# database must match a name defined in the databases section above.
|
|
42
|
+
#
|
|
43
|
+
generate:
|
|
44
|
+
- database: primary
|
|
45
|
+
schema: public
|
|
46
|
+
|
|
47
|
+
# Uncomment to also generate from the secondary database:
|
|
48
|
+
# - database: secondary
|
|
49
|
+
# schema: public
|
|
50
|
+
|
|
51
|
+
# =============================================================================
|
|
52
|
+
# Debug
|
|
53
|
+
# =============================================================================
|
|
54
|
+
debug:
|
|
55
|
+
info: false
|
|
56
|
+
verbose: false
|
|
57
|
+
debug: false
|