-
Notifications
You must be signed in to change notification settings - Fork 328
Improvements on the @cmd.declare_command API
#448
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: master
Are you sure you want to change the base?
Conversation
|
I'll ask if we can maintain our pattern of keeping tests in |
|
Sorry, it was my bad. I'll tackle this in a few days. |
80eb0ce to
7c9f7ff
Compare
|
@JarrettSJohnson I'd like to ask, should I proceed and refactor existing commands to adhere the |
|
The first step is to refactor the |
We can address that in a separate PR, if possible. Also I think some things were accidentally deleted, perhaps during the merging process? (e.g. |
7c9f7ff to
095e961
Compare
|
The tip of branch were based on an old commit. It took me several hours to finish this git chore task. |
JarrettSJohnson
left a comment
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.
Generally looks fine to me, I was under the impression from the original PR that this would just be for extended, custom functions rather than native ones. I'm a little hesitant to change current commands just yet. I still need to play around with this first to ensure no functional changes.
| @@ -1,50 +0,0 @@ | |||
| import sys | |||
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.
Was this file intended to be removed here?
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.
Yes. Is it ok?
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 keep for now since we still have code that uses this pattern.
Me too. Except for the |
- Bio.pairwise2 has been deprecated -> Use Bio.Align.PairwiseAligner instead - SeqRecord constructor: Using a string as the sequence is deprecated -> Convert to Seq The changes are based on https://github.com/speleo3/pymol-psico/blob/ae2b92c262bc/psico/seqalign.py
|
If I remove the docs-on-comment feature will this be merged faster? |
|
Apologies. Give me until the weekend, and I'll come back to this review. My involvement with incentive and open-source comes in waves, and I'm still pretty deep in 3.2/3.3 work. |
|
I think this is important to get merged before 3.2 because otherwise will have a delay starting in the current incomplete feature awaiting 3.3. |
| @@ -1,50 +0,0 @@ | |||
| import sys | |||
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 keep for now since we still have code that uses this pattern.
| break | ||
| i += 1 | ||
| else: | ||
| i -= 3 |
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 don't think I follow this line
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.
Me neither, I just placed it here because was needed. I'd need to debug to remember exactly, but seems to me that it's related to rewind the cursor i when no doc is found.
modules/pymol/commanding.py
Outdated
|
|
||
| raise pymol.CmdException(f"Unsupported argument type {type}") | ||
|
|
||
| def parse_documentation(func): |
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 think this function probably needs its own unit test as well. The API to me is not inherently clear.
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.
It is tested integrated with declare_command on test_declare_command_arg_docs.
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 understand, but something like this probably deserves its own test too if possible. I'll make it optional, but I will likely add it later.
|
Give me some days and I'll fix according to your review. As nobody is using this yet, including me, may |
|
Sure. |
|
Hi @JarrettSJohnson! I lost the access to my old Github account. I'm using this new one for now. However I couldn't get open-source PyMOL working on pip editable (link) mode ( |
|
Does normal Also, you should just be able to run a test like: But if you run all tests, |
|
I'm on a recent Debian and installed pyqt6-dev via default repositories. No way to get PyMOL working with Qt. |
|
Hi @pslacerda1! I don't have a Debian machine available at the moment, but maybe one of these solutions will help you.
|
|
Not sure about this, unfortunately. Does the latest Incentive version also show the same issue? Also does |
|
Incentive PyMOL and pymol-open-source starts like this same. However incentive continue and works while open-source fails. |
|
No changes with the use_shaders setting, and it's up to date with master? I recently pulled in some changes to keep the graphics changes similar to Incentive. |
|
Yes, I'm synced to master. |
|
Please, provide me the hashes of your commits? What I tried? I checkout and tried to build & run master and tag v3.1.0. Master starts without anything related to GL, v3.1.0 pop up on the screen and closes instantaneously. |
|
Good and bad news: I was attempting to use the wrong Qt version. The correct is Qt5 for PyMOL 3.1 and Qt6 for PyMOL 3.2. The bad one is that I couldn't run all pytests from tests/testing/api anymore. |
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.
Pull Request Overview
This PR introduces improvements to the @cmd.declare_command API to provide better ergonomics for command declaration and type casting. The changes focus on enhancing the command declaration system with more robust type handling and documentation parsing capabilities.
- Replaced the previous test file for API helping functionality with comprehensive command declaration tests
- Enhanced the
declare_commanddecorator with improved type casting and argument handling - Added support for complex types including Optional, Union, Tuple, Enum, and generic types
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
| testing/tests/api/helping.py | Completely removed the help API test file |
| testing/tests/api/commanding.py | Added extensive tests for the new command declaration API with various type scenarios |
| modules/pymol/commanding.py | Implemented enhanced type casting system and argument documentation parsing for command declarations |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
|
|
||
| @cmd.declare_command | ||
| def func(a: Optional[int] = None): | ||
| assert a is 10 |
Copilot
AI
Oct 10, 2025
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.
Use == for value comparison instead of is. The is operator checks for object identity, not equality, and may not work reliably for integers.
| assert a is 10 | |
| assert a == 10 |
|
|
||
| def _parse_list_int(value): | ||
| return list(map(int, shlex.split(value))) | ||
| elif isinstance(type, Enum): |
Copilot
AI
Oct 10, 2025
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 condition will never be true. type is a type annotation, not an instance of Enum. Use inspect.isclass(type) and issubclass(type, Enum) to check if the type is an Enum class.
| else: | ||
| raise pymol.CmdException(f"Invalid value for enum {type.__name__}: {value}") | ||
|
|
||
| elif isinstance(type, builtins.type): |
Copilot
AI
Oct 10, 2025
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 condition is too broad and may incorrectly handle type annotations. Consider using more specific type checking logic or inspect.isclass() for better type validation.
| elif isinstance(type, builtins.type): | |
| elif inspect.isclass(type): |
| while True: | ||
| i += 1 | ||
| if tokens[i].string == "def": | ||
| while tokens[i].string == "(": |
Copilot
AI
Oct 10, 2025
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 will cause an infinite loop if the opening parenthesis is found, as the condition never changes. The logic should find the opening parenthesis and then break or continue processing.
| while tokens[i].string == "(": | |
| if tokens[i].string == "(": |
| if tokens[i].type == tokenize.NAME and tokens[i+1].string == ":": | ||
| name = tokens[i].string | ||
| name_line = tokens[i].line | ||
| i += 1 | ||
| while not (tokens[i].type == tokenize.NAME and tokens[i+1].string == ":"): |
Copilot
AI
Oct 10, 2025
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 loop may cause an IndexError when accessing tokens[i+1] if i reaches the end of the tokens list. Add bounds checking before accessing tokens[i+1].
| if tokens[i].type == tokenize.NAME and tokens[i+1].string == ":": | |
| name = tokens[i].string | |
| name_line = tokens[i].line | |
| i += 1 | |
| while not (tokens[i].type == tokenize.NAME and tokens[i+1].string == ":"): | |
| if tokens[i].type == tokenize.NAME and (i+1 < len(tokens)) and tokens[i+1].string == ":": | |
| name = tokens[i].string | |
| name_line = tokens[i].line | |
| i += 1 | |
| while not (tokens[i].type == tokenize.NAME and (i+1 < len(tokens)) and tokens[i+1].string == ":"): |
| _self.keyword[name] = [inner, 0, 0, ",", parsing.STRICT] | ||
| _self.kwhash.append(name) | ||
| _self.help_sc.append(name) | ||
| _self.keyword[name] = [inner, 0,0,',',parsing.STRICT] |
Copilot
AI
Oct 10, 2025
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.
[nitpick] Inconsistent spacing around commas. Should be [inner, 0, 0, ',', parsing.STRICT] to match Python style conventions.
| _self.keyword[name] = [inner, 0,0,',',parsing.STRICT] | |
| _self.keyword[name] = [inner, 0, 0, ',', parsing.STRICT] |



A write a bunch of tests and did my best to achieve best ergonomic API.
Only optional (
None) data is still failing in some cases.