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: Set __file__ constant when using eval_file (#1300) #3233

Merged
merged 13 commits into from
Sep 9, 2021

Conversation

Skylion007
Copy link
Collaborator

@Skylion007 Skylion007 commented Sep 1, 2021

Description

Closes #1300 by setting the __file__ constant when running eval_file.

Suggested changelog entry:

* Sets __file__ constant when running eval_file in an embedded interpreter.

@Skylion007 Skylion007 requested review from rwgk and henryiii September 1, 2021 18:58
@Skylion007 Skylion007 changed the title Set __file__ constant when using eval_file bugfix(#1300) Set __file__ constant when using eval_file Sep 1, 2021
@@ -3,5 +3,7 @@

import test_cmake_build

__file__ # Test this is properly set
Copy link
Collaborator

Choose a reason for hiding this comment

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

What do you think about making this slightly stronger (and look more like a test)? E.g.

assert isinstance(__file__, str)  # Test this is properly set.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I knew it!

isinstance(__file__, str) == False on Python2

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh, because it is unicode even on Python 2? — I think that counts as a bug, too!
Although not a surprising one given how pybind11 works internally. I think in that case we want to keep the test as is (isinstance str), but encode in the C++ code.
Give me a moment to look around a bit what the expections are for file with Python 2.

Copy link
Collaborator

Choose a reason for hiding this comment

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

A bit random, but this looks very similar:

https://github.com/pypa/pip/pull/1538/files

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe more pragmatically: guard the new C++ code with #ifdef for Python 3, and the test with not env.PY2.
I.e. we're simply leaving Python 2 behind (instead of going through hoops for something that is practically dead already).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't like that because it should be defined in Python 2, the previous code was checking for NameError.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

A bit random, but this looks very similar:

https://github.com/pypa/pip/pull/1538/files

Nah, this is same code snippit is suppose to be done in the Python2 side to convert file to the appropriate format.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm good with either:

  • status quo for Python 2 (carry forward existing shortcoming),
  • or fixing properly.
    For the latter, is there a Python C API for sys.getfilesystemencoding()? If not we have to import, getattr, call.

@Skylion007 Skylion007 changed the title bugfix(#1300) Set __file__ constant when using eval_file fix: Set __file__ constant when using eval_file (#1300) Sep 1, 2021
@@ -3,5 +3,10 @@

import test_cmake_build

from .. import env

if env.PY3:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Without the matching guard in C++ we are as much creating a problem as we are solving one.

@Skylion007
Copy link
Collaborator Author

@rwgk Can you investigate fixing the encoding then for Python2, not familiar with searching the CPython documentation.

@@ -136,6 +136,14 @@ object eval_file(str fname, object global = globals(), object local = object())
pybind11_fail("File \"" + fname_str + "\" could not be opened!");
}

// Python2 API requires this to be encoded to filesystemencoding.
Copy link
Collaborator

@rwgk rwgk Sep 1, 2021

Choose a reason for hiding this comment

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

This looks great.
I see the env.PY3 is giving us trouble. There is another easy trick, JIC there isn't a better one:

if str is not bytes:  # Python 2 is not supported.

(We'll find that easily when we clear out Python 2 with the firehose in a few months.)

@Skylion007
Copy link
Collaborator Author

Looks like a flake.

Copy link
Collaborator

@rwgk rwgk left a comment

Choose a reason for hiding this comment

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

Cool! Thanks for picking this up.

@rwgk
Copy link
Collaborator

rwgk commented Sep 1, 2021

Looks like a flake.

Yep, download issue. Seeing that a lot.

@Skylion007
Copy link
Collaborator Author

Actually, after thinking it over, I am tempted to just leave the global file in Python2 (as UTF-8 bytes) because there is chance it could be right (if the filesystem encoding is UTF-8), and it shouldn't break any previous code because any code that required file had to set it byitself with the global dict and this code snippit will not interfere with that path. @henryiii Is there an easy way to encode to the getfilesystemencoding ? I know there is a C-API for codecs which makes this easier.

@rwgk Going to revert to the bytes method for now as it will usually be correct, if someone wants to fix it they can.

Copy link
Collaborator

@henryiii henryiii left a comment

Choose a reason for hiding this comment

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

I’m not very worried about Python 2 support, as long as it doesn’t regress for now, I’m fine with it. AFAICT, this just means that __file__ wasn't previously available, but now it is - but on Python 2, it might be misencoded if not unicode.

It is possible that an invalid unicode sequence could show up here, but if something really bad happens, Python 2 users can just set __file__ manually.

@henryiii
Copy link
Collaborator

henryiii commented Sep 9, 2021

(I'd also be okay to leave it unset on Python 2 at this stage)

@rwgk
Copy link
Collaborator

rwgk commented Sep 9, 2021

(I'd also be okay to leave it unset on Python 2 at this stage)

I think that really is the best, because ...

but if something really bad happens, Python users can just set file manually.
(I read this as "Python 2 users")

nobody wants to mess with Python 2 changes anymore. Just leaving everything as-is as much as possible is sure to be the least disruptive.

@Skylion007 Skylion007 merged commit 4c6bee3 into pybind:master Sep 9, 2021
@Skylion007 Skylion007 deleted the set_file_in_eval branch September 9, 2021 18:06
@github-actions github-actions bot added the needs changelog Possibly needs a changelog entry label Sep 9, 2021
@henryiii henryiii removed the needs changelog Possibly needs a changelog entry label Sep 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Setting __file__ in eval_file
3 participants