-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Fix Tcl inside a virtualenv on Windows (issue #93) #627
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import sys, os | ||
|
||
# Delay import _tkinter until we have set TCL_LIBRARY, | ||
# so that Tcl_FindExecutable has a chance to locate its | ||
# encoding directory. | ||
|
||
# Unfortunately, we cannot know the TCL_LIBRARY directory | ||
# if we don't know the tcl version, which we cannot find out | ||
# without import Tcl. Fortunately, Tcl will itself look in | ||
# <TCL_LIBRARY>\..\tcl<TCL_VERSION>, so anything close to | ||
# the real Tcl library will do. | ||
|
||
# Expand symbolic links on Vista | ||
try: | ||
import ctypes | ||
ctypes.windll.kernel32.GetFinalPathNameByHandleW | ||
except (ImportError, AttributeError): | ||
def convert_path(s): | ||
return s | ||
else: | ||
def convert_path(s): | ||
assert isinstance(s, str) # sys.prefix contains only bytes | ||
udir = s.decode("mbcs") | ||
hdir = ctypes.windll.kernel32.\ | ||
CreateFileW(udir, 0x80, # FILE_READ_ATTRIBUTES | ||
1, # FILE_SHARE_READ | ||
None, 3, # OPEN_EXISTING | ||
0x02000000, # FILE_FLAG_BACKUP_SEMANTICS | ||
None) | ||
if hdir == -1: | ||
# Cannot open directory, give up | ||
return s | ||
buf = ctypes.create_unicode_buffer(u"", 32768) | ||
res = ctypes.windll.kernel32.\ | ||
GetFinalPathNameByHandleW(hdir, buf, len(buf), | ||
0) # VOLUME_NAME_DOS | ||
ctypes.windll.kernel32.CloseHandle(hdir) | ||
if res == 0: | ||
# Conversion failed (e.g. network location) | ||
return s | ||
s = buf[:res].encode("mbcs") | ||
# Ignore leading \\?\ | ||
if s.startswith("\\\\?\\"): | ||
s = s[4:] | ||
if s.startswith("UNC"): | ||
s = "\\" + s[3:] | ||
return s | ||
|
||
prefix = os.path.join(sys.real_prefix,"tcl") | ||
if not os.path.exists(prefix): | ||
# devdir/../tcltk/lib | ||
prefix = os.path.join(sys.real_prefix, os.path.pardir, "tcltk", "lib") | ||
prefix = os.path.abspath(prefix) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, how important is it to support in-place development build here? Does the rest of virtualenv work in that situation (I honestly don't know, I've never tried it). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You know this is a straight copy from Python's source, ya? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only after I posted that comment :-) |
||
# if this does not exist, no further search is needed | ||
if os.path.exists(prefix): | ||
prefix = convert_path(prefix) | ||
if "TCL_LIBRARY" not in os.environ: | ||
for name in os.listdir(prefix): | ||
if name.startswith("tcl"): | ||
tcldir = os.path.join(prefix,name) | ||
if os.path.isdir(tcldir): | ||
os.environ["TCL_LIBRARY"] = tcldir | ||
# Compute TK_LIBRARY, knowing that it has the same version | ||
# as Tcl | ||
import _tkinter | ||
ver = str(_tkinter.TCL_VERSION) | ||
if "TK_LIBRARY" not in os.environ: | ||
v = os.path.join(prefix, 'tk'+ver) | ||
if os.path.exists(os.path.join(v, "tclIndex")): | ||
os.environ['TK_LIBRARY'] = v | ||
# We don't know the Tix version, so we must search the entire | ||
# directory | ||
if "TIX_LIBRARY" not in os.environ: | ||
for name in os.listdir(prefix): | ||
if name.startswith("tix"): | ||
tixdir = os.path.join(prefix,name) | ||
if os.path.isdir(tixdir): | ||
os.environ["TIX_LIBRARY"] = tixdir |
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 seems to write a new file, but never use it. How is this functionality activated?
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.
Hmm, wait. I see there's a Lib\lib-tk\FixTk.py in Python 2.7. So this fix doesn't work on Python 3 (where there's no lib-tk directory). Can it be updated to cover that as well?
Also, if this is a copy/paste and edit of the core FixTk.py, won't any changes core Python makes in later versions be lost? That doesn't sound good - I'd prefer a fix that properly monkeypatched whatever was in the core distribution, if we're going down this route at all.
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.
That's actually already the case for virtualenv's
site.py
that it has vendored / modified - it's missing functions that were introduced in 2.7 See #355But since this is for 2.X only and we already know there's no 2.8, I can't imagine that is a worry for this particular 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.
Is it meant to be for 2.x only? If so, the file should only be written on 2.x. And if it's not, the point remains for the equivalent file on 3.x - copying the file has risks. (OTOH, it may be that the 3.x version fixes this issue as it presumably supports venv...)
But yeah, it's a relatively minor point.
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 fix file also exist in Python 3, here: "C:\Python34\Lib\tkinter_fix.py"
it's simmilar content to "C:\Python27\Lib\lib-tk\FixTk.py"