Skip to content

Commit c268644

Browse files
author
Mehdi
committed
better describing of table
1 parent 9470f5c commit c268644

File tree

1 file changed

+33
-14
lines changed

1 file changed

+33
-14
lines changed

sqlmypy.py

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,26 +115,45 @@ def add_model_init_hook(ctx: ClassDefContext) -> None:
115115
if not (isinstance(stmt, AssignmentStmt) and len(stmt.lvalues) == 1 and isinstance(stmt.lvalues[0], NameExpr)):
116116
continue
117117

118+
# We currently only handle setting __tablename__ as a class attribute, and not through a property.
118119
if stmt.lvalues[0].name == "__tablename__" and isinstance(stmt.rvalue, StrExpr):
119120
ctx.cls.info.metadata.setdefault('sqlalchemy', {})['tablename'] = stmt.rvalue.value
120121

121122
if isinstance(stmt.rvalue, CallExpr) and stmt.rvalue.callee.fullname == COLUMN_NAME:
122-
colname = stmt.lvalues[0].name
123-
has_explicit_colname = stmt.rvalue
124-
ctx.cls.info.metadata.setdefault('sqlalchemy', {}).setdefault('columns', []).append(colname)
123+
# Save columns. The name of a column on the db side can be different from the one inside the SA model.
124+
sa_column_name = stmt.lvalues[0].name
125+
126+
db_column_name = None # type: Optional[str]
127+
if 'name' in stmt.rvalue.arg_names:
128+
name_str_expr = stmt.rvalue.args[stmt.rvalue.arg_names.index('name')]
129+
assert isinstance(name_str_expr, StrExpr)
130+
db_column_name = name_str_expr.value
131+
else:
132+
if len(stmt.rvalue.args) >= 1 and isinstance(stmt.rvalue.args[0], StrExpr):
133+
db_column_name = stmt.rvalue.args[0].value
134+
135+
ctx.cls.info.metadata.setdefault('sqlalchemy', {}).setdefault('columns', []).append(
136+
{"sa_name": sa_column_name, "db_name": db_column_name or sa_column_name}
137+
)
138+
139+
# Save foreign keys.
125140
for arg in stmt.rvalue.args:
126141
if isinstance(arg, CallExpr) and arg.callee.fullname == FOREIGN_KEY_NAME and len(arg.args) >= 1:
127142
fk = arg.args[0]
128143
if isinstance(fk, StrExpr):
129-
*_, parent_table, parent_col = fk.value.split(".")
130-
ctx.cls.info.metadata.setdefault('sqlalchemy', {}).setdefault('foreign_keys', {})[colname] = {
131-
"column": parent_col,
132-
"table": parent_table
144+
*r, parent_table_name, parent_db_col_name = fk.value.split(".")
145+
assert len(r) <= 1
146+
ctx.cls.info.metadata.setdefault('sqlalchemy', {}).setdefault('foreign_keys',
147+
{})[sa_column_name] = {
148+
"db_name": parent_db_col_name,
149+
"table_name": parent_table_name,
150+
"schema": r[0] if r else None
133151
}
134152
elif isinstance(fk, MemberExpr):
135-
ctx.cls.info.metadata.setdefault('sqlalchemy', {}).setdefault('foreign_keys', {})[colname] = {
136-
"column": fk.name,
137-
"model": fk.expr.fullname
153+
ctx.cls.info.metadata.setdefault('sqlalchemy', {}).setdefault('foreign_keys',
154+
{})[sa_column_name] = {
155+
"sa_name": fk.name,
156+
"model_fullname": fk.expr.fullname
138157
}
139158

140159
# Also add a selection of auto-generated attributes.
@@ -414,10 +433,10 @@ class User(Base):
414433
# We really need to add this to TypeChecker API
415434
def parse_bool(expr: Expression) -> Optional[bool]:
416435
if isinstance(expr, NameExpr):
417-
if expr.fullname == 'builtins.True':
418-
return True
419-
if expr.fullname == 'builtins.False':
420-
return False
436+
if expr.fullname == 'builtins.True':
437+
return True
438+
if expr.fullname == 'builtins.False':
439+
return False
421440
return None
422441

423442

0 commit comments

Comments
 (0)