-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add more metadata and try to guess if relationship is iterable #74
base: master
Are you sure you want to change the base?
Conversation
mehdigmira
commented
Feb 10, 2019
- Add stuff to metadata: table name, columns, foreign keys
- Try to guess is a relationship is iterable
6c726f8
to
605a997
Compare
Is this ready for review, or it is still a WIP? |
I wanted to know first If the logic implemented is something you would consider putting into the plugin, before going any further. |
@ilevkivskyi This can be reviewed |
@ilevkivskyi Any news on this ? |
I just returned from vacation, will take a look at this later this week. Sorry for a delay! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! Generally looks good, I have some mostly minor comments.
continue | ||
|
||
# We currently only handle setting __tablename__ as a class attribute, and not through a property. | ||
if stmt.lvalues[0].name == "__tablename__" and isinstance(stmt.rvalue, StrExpr): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can also support constants like:
NAME: Final = 'users'
class User(Base):
__tablename__ = NAME
...
No need to this in this PR, but may worth leaving a TODO and/or a follow-up issue.
db_column_name = None # type: Optional[str] | ||
if 'name' in stmt.rvalue.arg_names: | ||
name_str_expr = stmt.rvalue.args[stmt.rvalue.arg_names.index('name')] | ||
assert isinstance(name_str_expr, StrExpr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is unsafe, it will crash mypy if someone passes name=
as a variable or function call.
Please also add a test for this.
|
||
# Save foreign keys. | ||
for arg in stmt.rvalue.args: | ||
if (isinstance(arg, CallExpr) and isinstance(arg.callee, NameExpr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use RefExpr
instead of NameExpr
?
if stmt.lvalues[0].name == "__tablename__" and isinstance(stmt.rvalue, StrExpr): | ||
ctx.cls.info.metadata.setdefault('sqlalchemy', {})['table_name'] = stmt.rvalue.value | ||
|
||
if (isinstance(stmt.rvalue, CallExpr) and isinstance(stmt.rvalue.callee, NameExpr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would factor out everything you add on this line and below in a helper function with a docstring explaining what we do here, e.g. process_field_assignment()
.
fk = arg.args[0] | ||
if isinstance(fk, StrExpr): | ||
*r, parent_table_name, parent_db_col_name = fk.value.split(".") | ||
assert len(r) <= 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this is not safe, we should never crash on bad user input.
@@ -369,10 +466,18 @@ class User(Base): | |||
# Something complex, stay silent for now. | |||
new_arg = AnyType(TypeOfAny.special_form) | |||
|
|||
# use private api | |||
current_model = ctx.api.scope.active_class() # type: ignore # type: TypeInfo |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put # type: ignore
at the end, after type comment, otherwise the type comment will be ignored.
reveal_type(child.parent) # E: Revealed type is 'main.Parent*' | ||
reveal_type(parent.children) # E: Revealed type is 'main.Child*' | ||
|
||
[out] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add newline at the end of file.
@@ -280,3 +280,93 @@ class M2(M1): | |||
Base = declarative_base(cls=(M1, M2)) # E: Not able to calculate MRO for declarative base | |||
reveal_type(Base) # E: Revealed type is 'Any' | |||
[out] | |||
|
|||
[case testRelationshipIsGuessed] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have tests where schema
is not None
?
secondaryjoin = get_argument_by_name(ctx, 'secondaryjoin') | ||
|
||
if secondaryjoin is not None: | ||
return True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please add a test for this?
|
||
reveal_type(child.parent) # E: Revealed type is 'main.Parent*' | ||
reveal_type(parent.children) # E: Revealed type is 'typing.Iterable*[main.Child]' | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for empty lines before [out]
.
@ilevkivskyi Is this project still maintained ? Would you merge this if i make the requested changes and rebase this ? |
Mehdi seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |