Skip to content
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

Fix 5701: avoid dev_tools/modules.py print_version failing #5705

Merged
merged 4 commits into from Jul 12, 2022
Merged

Fix 5701: avoid dev_tools/modules.py print_version failing #5705

merged 4 commits into from Jul 12, 2022

Conversation

mhucka
Copy link
Contributor

@mhucka mhucka commented Jul 9, 2022

The implementation of the command print_version in dev_tools/modules.py involves (eventually) calling the function list_modules(). That function finds modules by searching for files name setup.py, starting in the current directory. When the user runs python dev_tools/modules.py print_version, the current directory is the Cirq repo top-level directory.

list_modules() works by calling _parse_module() on every relative directory path found by locating the setup.py files recursively. When it executes with a given directory path, _parse_module() tries to exec the setup.py file found therein. The specific error comes from the fact that the top-level setup.py file, unlike all the sub-modules's setup.py files, includes imports. Specifically, these imports:

from dev_tools import modules
from dev_tools.requirements import explode

Unfortunately, the current directory (i.e., the top-level Cirq directory) is not in Python's sys.path at the time _parse_module() exec's the setup.py file there, and so the import fails with

ModuleNotFoundError: No module named 'dev_tools'

This could probably be fixed in a number of ways. One is to make _parse_module() temporarily append the current path to sys.path before attempting to exec a setup.py file. Doing so should hopefully make Python import statements inside setup.py files work as expected.

That's what this 2-line code change does.

The implementation of the command `print_version` in
`dev_tools/modules.py` involves (eventually) calling the function
`list_modules()`.  That function finds modules by searching for files
name `setup.py`, starting in the current directory. When the user runs
`python dev_tools/modules.py print_version`, the current directory is
the Cirq repo top-level directory.

`list_modules()` works by calling `_parse_module()` on every relative
directory path found by locating the `setup.py` files recursively.
When it executes with a given directory path, `_parse_module()` tries
to exec the `setup.py` file found therein. The specific error comes
from the fact that the top-level `setup.py` file, _unlike_ all the
sub-modules's `setup.py` files, includes imports.  Specifically, these
imports:
```
from dev_tools import modules
from dev_tools.requirements import explode
```

Unfortunately, the current directory (i.e., the top-level Cirq
directory) is not in Python's `sys.path` at the time `_parse_module()`
exec's the `setup.py` file there, and so the import fails with
```
ModuleNotFoundError: No module named 'dev_tools'
```

This could probably be fixed in a number of ways. One is to make
`_parse_module()` temporarily append the current path to `sys.path`
before attempting to exec a `setup.py` file. Doing so should hopefully
make Python import statements inside `setup.py` files work as
expected.

That's what this 2-line code change does.
@mhucka mhucka requested review from a team, vtomole and cduck as code owners July 9, 2022 00:57
@mhucka mhucka requested a review from mpharrigan July 9, 2022 00:57
@CirqBot CirqBot added the Size: XS <10 lines changed label Jul 9, 2022
@mhucka mhucka changed the title Fix 5701 Fix 5701: avoid dev_tools/modules.py print_version failing Jul 9, 2022
@mhucka
Copy link
Contributor Author

mhucka commented Jul 11, 2022

Incidentally, another way to avoid the error is to put "." on the PYTHONPATH environment variable prior to running python dev_tools/modules.py print_version. This is effectively how the scripts in the check subdirectory do things, via the code in check/pypath. So, another solution to this problem would be to leave modules.py unchanged, and instead change the documentation to tell users to run something like

env PYTHONPATH=. dev_tools/modules.py print_version

IMHO, the above would be more confusing to users than if dev_tools/modules.py took care of handling the issue itself, but in the event that the change I proposed in this PR have an adverse affect elsewhere, this might be another option.

@MichaelBroughton
Copy link
Collaborator

Does running ./dev_tools/pypath also get around this issue ?

@mhucka
Copy link
Contributor Author

mhucka commented Jul 11, 2022

@MichaelBroughton If I understand you correctly, you mean to do something like the following?

./dev_tools/pytpath
python dev_tools/modules.py print_version

Unfortunately, no, that can't work, because what pypath does is set some environment variables, and that won't affect the parent shell's environment (i.e., the shell running the command). However, one could do something close to it, which is

source dev_tools/pypath
python dev_tools/modules.py print_version

and that does work. (It's worth mentioning that it will only work if the user is running a Bash/sh/Bourne-derived shell, and not a shell derived from csh, but since elsewhere Cirq seems to assume Bash/sh, it wouldn't be a new requirement.)

To be honest, the proposed 2-line patch seems simpler and less prone to user errors or unexpected shell behaviors, but maybe there are other reasons to go this route of using pypath.

@mpharrigan
Copy link
Collaborator

another unrelated problem I just noticed trying to figure out what the heck this tool is supposed to do is that if you don't provide a subcommand it fails with a bad error message instead of displaying a help message with subcommand info

Copy link
Collaborator

@mpharrigan mpharrigan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks harmless and fixes a clearly broken script

@mpharrigan
Copy link
Collaborator

Is anyone using devtools/modules.py print_version? Is it supposed to be a part of the release process. I suggest either:

  1. add this command to the documentation for cutting a release
    OR
  2. remove the code if no one is using it

@mhucka
Copy link
Contributor Author

mhucka commented Jul 11, 2022

@mpharrigan Regarding the behavior when not giving it a subcommand, I encountered that too, and fixed this in PR #5702, which was merged earlier today.

@mpharrigan
Copy link
Collaborator

ah, I'm behind

@mhucka
Copy link
Contributor Author

mhucka commented Jul 11, 2022

Is anyone using devtools/modules.py print_version?

Apart from the docs mentioning its use I did a quick recursive find+grep just now, and don't see anything using "print_version" per se except the test cases for modules.py. (However, the "list" function of modules.py is used by dev_tools/pypath, so probably modules.py serves a useful function overall.)

dev_tools/modules.py Outdated Show resolved Hide resolved
As pointed out by @pavoljuhas, it's better to put the current
directory first, in case the user's PYTHONPATH includes another Cirq
working tree. Prepending it will make sure that sys.path searches the
current repository first.
Copy link
Collaborator

@pavoljuhas pavoljuhas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@pavoljuhas pavoljuhas added the automerge Tells CirqBot to sync and merge this PR. (If it's running.) label Jul 12, 2022
@CirqBot CirqBot added the front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. label Jul 12, 2022
@CirqBot CirqBot merged commit e80b14b into quantumlib:master Jul 12, 2022
@CirqBot CirqBot removed automerge Tells CirqBot to sync and merge this PR. (If it's running.) front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. labels Jul 12, 2022
rht pushed a commit to rht/Cirq that referenced this pull request May 1, 2023
…lib#5705)

The implementation of the command `print_version` in `dev_tools/modules.py` involves (eventually) calling the function `list_modules()`.  That function finds modules by searching for files name `setup.py`, starting in the current directory. When the user runs `python dev_tools/modules.py print_version`, the current directory is the Cirq repo top-level directory.

`list_modules()` works by calling `_parse_module()` on every relative directory path found by locating the `setup.py` files recursively.  When it executes with a given directory path, `_parse_module()` tries to exec the `setup.py` file found therein. The specific error comes from the fact that the top-level `setup.py` file, _unlike_ all the sub-modules's `setup.py` files, includes imports.  Specifically, these imports:
```
from dev_tools import modules
from dev_tools.requirements import explode
```

Unfortunately, the current directory (i.e., the top-level Cirq directory) is not in Python's `sys.path` at the time `_parse_module()` exec's the `setup.py` file there, and so the import fails with
```
ModuleNotFoundError: No module named 'dev_tools'
```

This could probably be fixed in a number of ways. One is to make `_parse_module()` temporarily append the current path to `sys.path` before attempting to exec a `setup.py` file. Doing so should hopefully make Python import statements inside `setup.py` files work as expected.

That's what this 2-line code change does.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Size: XS <10 lines changed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants