-
-
Notifications
You must be signed in to change notification settings - Fork 31.1k
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
bpo-29546: Set path on ImportError for from ... import #91
Conversation
Python/ceval.c
Outdated
PyErr_Format(PyExc_ImportError, "cannot import name %R", name); | ||
pkgpath = PyModule_GetFilenameObject(v); | ||
|
||
if (pkgpath == NULL || !PyUnicode_Check(pkgpath)){ |
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.
Looks like there's a missing space between the final )
and {
.
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.
Dang. Fixed.
I have not dug into the surrounding code, but the general approach LGTM. |
bd14cf2
to
d3aff79
Compare
I also just realized there's no test. |
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 a test.
Yes I realized that as well :-) Will do . |
Lib/test/test_import/__init__.py
Outdated
@@ -80,6 +80,43 @@ def test_from_import_missing_attr_raises_ImportError(self): | |||
with self.assertRaises(ImportError): | |||
from importlib import something_that_should_not_exist_anywhere | |||
|
|||
def test_from_import_missing_attr_has_name_and_path(self): | |||
""" |
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.
We don't include docstrings on tests (and we PEP 8 doesn't allow starting a docstring with a newline).
Lib/test/test_import/__init__.py
Outdated
except ImportError as e: | ||
self.assertEqual(e.name, 'os', | ||
"ImportError.name is set") | ||
self.assertIsNotNone(e.path, |
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 do an assertEqual
check using os.__file__
?
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.
Sure.
Lib/test/test_import/__init__.py
Outdated
from os import i_dont_exist | ||
except ImportError as e: | ||
self.assertEqual(e.name, 'os', | ||
"ImportError.name is set") |
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.
The custom message isn't necessary as what the test is checking is obvious (same goes for all of the other messages).
Lib/test/test_import/__init__.py
Outdated
`name` and `path` set when both are available. | ||
""" | ||
|
||
try: |
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.
Any reason you can't use with self.assertRaises()
?
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 just forgot you could access the exception after the fact with contextmanager.exception
so I indeed I can ans should use it.
Lib/test/test_import/__init__.py
Outdated
Make sure that from ... import ... raise an import error that has both | ||
`name` and `path` set when both are available. | ||
""" | ||
|
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.
Unnecessary blank line.
3f218f5
to
30a5055
Compare
Lib/test/test_import/__init__.py
Outdated
self.assertEqual(cm.exception.name, '_warning') | ||
self.assertIsNone(cm.exception.path) | ||
|
||
def test_from_import_missing_attr_path_is_cannonical(self): |
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.
Typo" cannonical" -> "canonical"
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 need to find a linter that understand both programming and english.
Lib/test/test_import/__init__.py
Outdated
def test_from_import_missing_attr_path_is_cannonical(self): | ||
with self.assertRaises(ImportError) as cm: | ||
from os.path import i_dont_exist | ||
self.assertIn(cm.exception.name, {'posixpath', 'ntpath'}) |
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.
Should there be a test for path
, even if it's just checking it isn't None
?
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 could, but that's taken care of by functions above. Here I'm just checking that it's not os.path
.
Anyway while I'm at it I will add an assertIsNotNone.
Lib/test/test_import/__init__.py
Outdated
with self.assertRaises(ImportError) as cm: | ||
from _warning import i_dont_exist | ||
self.assertEqual(cm.exception.name, '_warning') | ||
self.assertIsNone(cm.exception.path) |
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 add a comment like # _warning has no path as it's a built-in module.
? I keep forgetting why this specific case doesn't have a path. 😄
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.
Too early in the bootstrap process ?
Anyway. Done.
30a5055
to
32e42aa
Compare
Codecov Report
@@ Coverage Diff @@
## master #91 +/- ##
=========================================
Coverage ? 82.38%
=========================================
Files ? 1428
Lines ? 351163
Branches ? 0
=========================================
Hits ? 289314
Misses ? 61849
Partials ? 0 Continue to review full report at Codecov.
|
BTW, please rebase your branch so we can get rid of these Codecov comments :) |
And `path` as well when existing. See bpo-29546 This is a step toward providing better error messages in case of from-import. Barry Warsaw Proposed: cannot import name {name} from {module} ({path}) But that's probably going to trigger more discussions that filling in already existing fields.
Make sure they name and path are set in various case.
32e42aa
to
7456cfc
Compare
Oh gosh 71 was merged ? Thanks you! and done. |
LGTM! Thanks for sticking through it, @Carreau ! Please add yourself to
|
Well actually good point that's setting both name and path. Name was not set either if that matters.
Sure ! |
Thanks! As soon as Travis is green I'll merge. |
Thanks. I don't know how disturbing the migration has been from your end (and other core dev). Many kudos for having worked on the migration for so long. |
Merged! Thanks again! And I'm glad that the new workflow worked out for you! As for me, the new workflow let me review this PR throughout the day when I had time and do it entirely in the browser so I didn't have to remember to commit it when I got home (if I had to cherry-pick that would not have been the case, but I could at least merge now and cherry-pick later if need be). |
Hopping you will get the cherry-pick bot soon. Thanks for the time you've put into this. |
@Carreau the bot would be great, but at worst me or someone else can write a Python script probably to automate it locally if necessary (which reminds me, I should write that idea down over on core-workflow). |
You did python/core-workflow#8 (Bot to automatically generate cherry-picking PRs) |
Wow, I'm very pleasantly impressed at how quickly my bug/idea went to (nearly) implemented through the new workflow. Kudos! |
Happy to repay a bit for all the work you did. It's also much easier to decide to implement if a core dev have pitched in the idea, as it has more chance to be accepted. Thanks both ! |
Add location information like canonical module name where identifier cannot be found and file location if available. First iteration of this was pythongh-91
…ursion depth Reset the recursion depth in PyTasklet_BindEx and add a few asserts. This fixes issue python#91. Add a test case for the recursion depth and as test case for an assertion failure caused by this bug. https://bitbucket.org/stackless-dev/stackless/issues/91 (grafted from 1584a89fca366f66dadf3cf04f0306dd45b1372f and 380b70b1933d)
And
path
as well when existing.See bpo-29546
This is a step toward providing better error messages in case of
from-import. Barry Warsaw Proposed:
cannot import name {name} from {module} ({path})
But that's probably going to trigger more discussions that filling in
already existing fields.
I'm not familiar with C-internal of CPython, So let me know if I'm doing things wrong.