-
-
Notifications
You must be signed in to change notification settings - Fork 268
Refactor CommandLine
command registration
#1611
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
base: main
Are you sure you want to change the base?
Conversation
5d7b091
to
e1d6454
Compare
My bad with the type hints, should be green now. |
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.
OK, this is sqla-tester setting up my work on behalf of zzzeek to try to get revision 369059e of this pull request into gerrit so we can run tests and reviews and stuff
New Gerrit review created for change 369059e: https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718 |
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.
OK well, the movement of methods and all is fine, but the goal of the PR here means that it's not that simple.
the goal is "make it easier for third parties to subclass CommandLine". This does some initial structure for that, but it doesnt do all these other things:
- document any of these methods. how would I know what _register_command does?
- make it clear which methods are safe - why are these methods underscored if they are now "public" ?
- provide an example in the docs how to subclass CommandLine
- provide any unit tests to ensure that a user-custom CommandLine implementation continues to work, otherrwise there's nothing to prevent someone changing CommandLine again here in some arbitrary way
- whether or not this is backwards compatible with someone who already did their own
CommandLine._generate_args
should be established also, it looks like that's maintained here
overall I like making CommandLine subclassable but that's public API, and it has to be done as a public API which means: 1. docs 2. proper conventions 3. API stability 4. tests
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.
Federico Caselli (CaselIT) wrote:
code review left on gerrit
View this in Gerrit at https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718
alembic/config.py
Outdated
self.parser = parser | ||
|
||
def _register_command(self, fn: Any) -> None: | ||
fn, positional, kwarg, help_text = self._parse_command_from_function(fn) |
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.
Federico Caselli (CaselIT) wrote:
we could avoid returning the fn here, since it's what we provide as argument
View this in Gerrit at https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718
alembic/config.py
Outdated
if ( | ||
arg == "revisions" | ||
or fn in self._POSITIONAL_TRANSLATIONS | ||
and self._POSITIONAL_TRANSLATIONS[fn][arg] == "revisions" |
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.
Federico Caselli (CaselIT) wrote:
we have already handle _POSITIONAL_TRANSLATIONS so I don't think we need this or part
View this in Gerrit at https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718
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.
True, I've removed this.
alembic/config.py
Outdated
fn.__name__, help=" ".join(help_text) | ||
subparser.add_argument( | ||
"revisions", | ||
nargs="+", |
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.
Federico Caselli (CaselIT) wrote:
let's parametrize this using a dict.
we could rename _POSITIONAL_HELP
and make it a dict of dicts that with the kwargs for the add_argument
View this in Gerrit at https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718
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.
Good idea, we now have _POSITIONAL_OPTS for this.
alembic/util/compat.py
Outdated
@@ -55,9 +56,9 @@ def close(self) -> None: | |||
def importlib_metadata_get(group: str) -> Sequence[EntryPoint]: | |||
ep = importlib_metadata.entry_points() | |||
if hasattr(ep, "select"): | |||
return ep.select(group=group) | |||
return cast(Sequence[EntryPoint], ep.select(group=group)) |
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.
Federico Caselli (CaselIT) wrote:
strange that this is now needed
View this in Gerrit at https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718
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.
Yeah I though I had to fix this now, but turns out I was running different python + mypy versions than CI. Reverted this.
@zzzeek Thanks for your thoughtful comments! In this PR I actively avoided doing all the "public interface" work that you mentioned in points 1-4. To be honest, I was intially going to stop at that, but I fully agree that the new interface eventually has to be public to be of any real value. Regarding point 5 though: yes, the changes to Given that you've approved this already - I take it you'd be fine with merging this and following up with the "public API" parts later on? |
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.
OK, this is sqla-tester setting up my work on behalf of CaselIT to try to get revision ed96df2 of this pull request into gerrit so we can run tests and reviews and stuff
Patchset ed96df2 added to existing Gerrit review https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718 |
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.
OK, this is sqla-tester setting up my work on behalf of CaselIT to try to get revision 3006935 of this pull request into gerrit so we can run tests and reviews and stuff
Patchset 3006935 added to existing Gerrit review https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718 |
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.
Federico Caselli (CaselIT) wrote:
code review left on gerrit
View this in Gerrit at https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718
- alembic/util/compat.py (line 59): Done
subparser.set_defaults(cmd=(fn, positional, kwarg)) | ||
) | ||
) | ||
|
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.
Federico Caselli (CaselIT) wrote:
Done
View this in Gerrit at https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718
for arg in kwarg: | ||
if arg in self._KWARGS_OPTS: | ||
kwarg_opt = self._KWARGS_OPTS[arg] | ||
args, opts = kwarg_opt[0:-1], kwarg_opt[-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.
Federico Caselli (CaselIT) wrote:
Done
View this in Gerrit at https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718
subparser.add_argument(*args, **opts) # type:ignore | ||
|
||
for arg in positional: | ||
if arg in self._POSITIONAL_OPTS: |
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.
Federico Caselli (CaselIT) wrote:
Done
View this in Gerrit at https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/5718
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.
hi my comment is not linkable so reiterating here, this patch has good ideas but they need to be presented as stable API that isn't going to change
my comment is below. at the very least this needs something with public methods, perhaps a UserDefinedCommandLine
subclass? with docstrings, and a bit of a test to make sure we dont accidentally change that API - otherwise the submitter here is better off vendoring their own changes locally since they are essentially private:
OK well, the movement of methods and all is fine, but the goal of the PR here means that it's not that simple.
the goal is "make it easier for third parties to subclass CommandLine". This does some initial structure for that, but it doesnt do all these other things:
document any of these methods. how would I know what _register_command does?
make it clear which methods are safe - why are these methods underscored if they are now "public" ?
provide an example in the docs how to subclass CommandLine
provide any unit tests to ensure that a user-custom CommandLine implementation continues to work, otherrwise there's nothing to prevent someone changing CommandLine again here in some arbitrary way
whether or not this is backwards compatible with someone who already did their own CommandLine._generate_args should be established also, it looks like that's maintained here
overall I like making CommandLine subclassable but that's public API, and it has to be done as a public API which means: 1. docs 2. proper conventions 3. API stability 4. tests
no, sorry, I dont know how "approve" got in there. as mentioned, this PR so far serves your immediate use case, but nobody else's since it's not documented, and there's no way to prevent someone from changing this API in the future which would break your code also without tests for API stability |
literally, do this:
that's it! |
but also make sure the old |
Fixes: #1610
Refactors
CommandLine
internals so that it's easier to plug custom commands into the cli, in addition to the builtinsalembic.command
.No public interface changes whatsoever.
The topic was somewhat discussed here #1456
Description
The point from the linked discussion still applies - this does not enable any kind of plugin system, one would still need to have their own subclass of
CommandLine
and call it from their own script. However, the implementation of such a subclass should be much cleaner now. I would expect it to look like so:Checklist
This pull request is:
must include a complete example of the issue. one line code fixes without an
issue and demonstration will not be accepted.
Fixes: #<issue number>
in the commit messageThis is purely internal refactoring, so no new tests are required. For extra confidence I:
tox
locally;alembic --help
before and after this change and made sure there was no diff.Have a nice day!