From f092bb5d8da55a8bacd1dd99bf1d5aa1d666b0d6 Mon Sep 17 00:00:00 2001 From: fitermay Date: Tue, 12 Apr 2016 20:42:56 -0400 Subject: [PATCH 1/5] --Fix translation of 'bdist' paths inside of eggs on windows --- python/helpers/pydev/pydevd_file_utils.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/python/helpers/pydev/pydevd_file_utils.py b/python/helpers/pydev/pydevd_file_utils.py index 2e63f4b26569..531fb2bae240 100644 --- a/python/helpers/pydev/pydevd_file_utils.py +++ b/python/helpers/pydev/pydevd_file_utils.py @@ -366,11 +366,11 @@ def get_abs_path_real_path_and_base_from_frame(frame): except: #This one is just internal (so, does not need any kind of client-server translation) f = frame.f_code.co_filename - if f is not None and f.startswith('build/bdist.'): + if f is not None and f.startswith (('build/bdist.','build\\bdist.')): # files from eggs in Python 2.7 have paths like build/bdist.linux-x86_64/egg/ f = frame.f_globals['__file__'] - if f.endswith('.pyc'): - f = f[:-1] + if f is not None and f.endswith('.pyc'): + f = f[:-1] ret = get_abs_path_real_path_and_base_from_file(f) # Also cache based on the frame.f_code.co_filename (if we had it inside build/bdist it can make a difference). NORM_PATHS_AND_BASE_CONTAINER[frame.f_code.co_filename] = ret From 8c33b3c9c15d840d3b7c70bafd9cdfc1280d20db Mon Sep 17 00:00:00 2001 From: fitermay Date: Tue, 12 Apr 2016 21:06:09 -0400 Subject: [PATCH 2/5] --Fix issue with breakpoints not being hit on windows inside .zip and .egg files with upper case letters in module names (the windows file system is not case sensetive but .zip filesystem is) --Fix issue with breakpoints not being hit on windows inside .zip and .egg files with upper case letters in module names (the windows file system is not case sensetive but .zip filesystem is) fix win norm case --- python/helpers/pydev/pydevd_file_utils.py | 6 ++++-- .../debugger/PyLocalPositionConverter.java | 17 +++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/python/helpers/pydev/pydevd_file_utils.py b/python/helpers/pydev/pydevd_file_utils.py index 531fb2bae240..fff2cc4d5937 100644 --- a/python/helpers/pydev/pydevd_file_utils.py +++ b/python/helpers/pydev/pydevd_file_utils.py @@ -143,7 +143,7 @@ def _NormPaths(filename): def _NormPath(filename, normpath): - r = normcase(normpath(filename)) + r = normpath(filename) #cache it for fast access later ind = r.find('.zip') if ind == -1: @@ -156,7 +156,9 @@ def _NormPath(filename, normpath): inner_path = r[ind:] if inner_path.startswith('/') or inner_path.startswith('\\'): inner_path = inner_path[1:] - r = join(zip_path, inner_path) + r = join(normcase(zip_path), inner_path) + else: + r = normcase(r) return r diff --git a/python/src/com/jetbrains/python/debugger/PyLocalPositionConverter.java b/python/src/com/jetbrains/python/debugger/PyLocalPositionConverter.java index e071549a44c6..1afaec0a7179 100644 --- a/python/src/com/jetbrains/python/debugger/PyLocalPositionConverter.java +++ b/python/src/com/jetbrains/python/debugger/PyLocalPositionConverter.java @@ -47,7 +47,7 @@ public class PyLocalPositionConverter implements PyPositionConverter { return null; } if (SystemInfo.isWindows) { - file = file.toLowerCase(); + file = winNormCase(file); } return super.normalize(file); } @@ -64,7 +64,7 @@ public class PyLocalPositionConverter implements PyPositionConverter { return null; } if (SystemInfo.isWindows && isWindowsPath(file)) { - file = file.toLowerCase(); + file = winNormCase(file); } return super.normalize(file); } @@ -165,6 +165,19 @@ public class PyLocalPositionConverter implements PyPositionConverter { } } + private static String winNormCase(String file) { + int ind = -1; + for (String ext : EGG_EXTENSIONS) { + ind = file.indexOf(ext); + if (ind != -1) break; + } + if (ind != -1) { + return file.substring(0, ind + 4).toLowerCase() + file.substring(ind + 4); + } + else { + return file.toLowerCase(); + } + } @Nullable protected static XSourcePosition createXSourcePosition(@Nullable VirtualFile vFile, int line) { if (vFile != null) { From 085e06c5ab4453081d044919109493f27be9e0f4 Mon Sep 17 00:00:00 2001 From: fitermay Date: Tue, 12 Apr 2016 21:40:28 -0400 Subject: [PATCH 3/5] --Handle normalization of short pathnames on windows --Handle normalization of short pathnames on windows --fix 'unicode' --- python/helpers/pydev/pydevd_file_utils.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/python/helpers/pydev/pydevd_file_utils.py b/python/helpers/pydev/pydevd_file_utils.py index fff2cc4d5937..d0237d224745 100644 --- a/python/helpers/pydev/pydevd_file_utils.py +++ b/python/helpers/pydev/pydevd_file_utils.py @@ -46,6 +46,7 @@ from _pydev_bundle._pydev_filesystem_encoding import getfilesystemencoding import os.path import sys import traceback +import types os_normcase = os.path.normcase basename = os.path.basename @@ -72,11 +73,31 @@ PATHS_FROM_ECLIPSE_TO_PYTHON = [] normcase = os_normcase # May be rebound on set_ide_os - +import types +str_to_unicode = types.UnicodeType +def convert_to_long_pathname(filename): + return filename +if os.name == 'nt': + try: + import ctypes + except ImportError: + pass + else: + def convert_to_long_pathname(filename): + buf = ctypes.create_unicode_buffer(260) + GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW + rv = GetLongPathName(str_to_unicode(filename), buf , 260) + if rv == 0 or rv > 260: + return filename + else: + return buf.value.encode(getfilesystemencoding()) def norm_case(filename): # `normcase` doesn't lower case on Python 2 for non-English locale, but Java side does it, # so we should do it manually + if '~' in filename: + filename = convert_to_long_pathname(filename) + filename = os_normcase(filename) enc = getfilesystemencoding() if IS_PY3K or enc is None or enc.lower() == "utf-8": From e95982ce7053261628a04bcc39cdc4796ac47f79 Mon Sep 17 00:00:00 2001 From: fitermay Date: Wed, 13 Apr 2016 14:48:55 -0400 Subject: [PATCH 4/5] --test for windows egg breakpoints --- python/testData/debug/test_winegg.py | 8 ++++ python/testData/debug/wintestegg-0.1.egg | Bin 0 -> 2129 bytes .../env/python/PythonDebuggerTest.java | 44 ++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 python/testData/debug/test_winegg.py create mode 100644 python/testData/debug/wintestegg-0.1.egg diff --git a/python/testData/debug/test_winegg.py b/python/testData/debug/test_winegg.py new file mode 100644 index 000000000000..092aed5176fe --- /dev/null +++ b/python/testData/debug/test_winegg.py @@ -0,0 +1,8 @@ +from eggxample import MIXED_case, lower_case + +x = lower_case.add(7, 9) +print(x) + +x = MIXED_case.add(7, 10) +print(x) + diff --git a/python/testData/debug/wintestegg-0.1.egg b/python/testData/debug/wintestegg-0.1.egg new file mode 100644 index 0000000000000000000000000000000000000000..068e05ca747fdb98fcf9bd5140067449d1e9c58d GIT binary patch literal 2129 zcmWIWW@Zs#U|`^2NGm zLJRLI{8Dw^zSFt<)AP5ReHCsz$~k8#_$_StWwu!JYyMw7{D11+4h(kJu@&T&zIf@E z!Go{6*~OfK59>5mhhJg?m-b$ZdRyv>(xW~|=Z>J;T+JTblU$o|Ews{L~R zs%y{!_StujnLI%EaRIRyvO7!i3*vK9%TjYdF7@{HU+-~7_k`zD^oUv0x=4ftsE-MV zQ6i=)vp}~vF)j5mik28)O7NBmQr7?~Hw0pFAWltBuSm=-$Vt`D$uCbWicd}~PSq=@ z^!D@(_VDq%xZ*pgi=-(R=O-%rQys&>PSi8CfK8Eu%s`X)oq z&3?mL$1?`WnwuJ!R~%L|w_j?aew8nW`-BWqgy9c8U(X0v7s^6U=(YA_?4gHZ_&|l; z$FDsFrJdx4o@8XN2QWo|lPZW71!6?ni;vID%PfhH2c|q`q#y^SsWbZe4-$ZiK?M*f zk6_gV4wG)niAX6bvH_H$Hn4dd@n=?PcN58G#-BJk`_G>_t<%|mU3-PjLxxq`PoDMH zJnOlYd1e%k5i8J5j7%cnvIKj93UnA4Y-I`-n}J>uA(}0n0W- zl%teU$cA7meGrDE<2EE2*%bUv@c`DK2&bUrNn}GnPC?Jg2&XK?Z3v1}u;mwoDQ&<~ kAK?_F+=K2A^xT6mVmB@$fX-lL1F7Q%!Z*N>^JfL|0Ecji*#H0l literal 0 HcmV?d00001 diff --git a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java index d883defa7b82..7db21fe94f89 100644 --- a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java +++ b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java @@ -539,6 +539,50 @@ public class PythonDebuggerTest extends PyEnvTestCase { }); } + + public void testWinEggDebug() throws Exception { + if (!SystemInfo.isWindows) + { + return; // Only needs to run on windows + } + runPythonTest(new PyDebuggerTask("/debug", "test_winegg.py") { + @Override + public void before() throws Exception { + String egg = getFilePath("wintestegg-0.1.egg"); + toggleBreakpointInEgg(egg, "eggxample/lower_case.py", 2); + toggleBreakpointInEgg(egg, "eggxample/MIXED_case.py", 2); + + PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(getRunConfiguration().getSdkHome()); + if (flavor != null) { + flavor.initPythonPath(Lists.newArrayList(egg), getRunConfiguration().getEnvs()); + } + else { + getRunConfiguration().getEnvs().put("PYTHONPATH", egg); + } + } + + @Override + public void testing() throws Exception { + waitForPause(); + eval("ret").hasValue("16"); + resume(); + + waitForPause(); + eval("ret").hasValue("17"); + resume(); + } + + @NotNull + @Override + public Set getTags() { + return ImmutableSet.of("-jython"); //TODO: fix that for Jython if anybody needs it + } + + + }); + } + + public void testStepOverConditionalBreakpoint() throws Exception { runPythonTest(new PyDebuggerTask("/debug", "test_stepOverCondition.py") { @Override From fe7c47d68869ac1e5f2f8b3a6a789a1f131ebeca Mon Sep 17 00:00:00 2001 From: fitermay Date: Wed, 13 Apr 2016 15:28:26 -0400 Subject: [PATCH 5/5] --test for short path to long windows pathname normalization in pydev debugger --- python/testData/debug/long_name_win_test.py | 3 ++ .../env/python/PythonDebuggerTest.java | 40 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 python/testData/debug/long_name_win_test.py diff --git a/python/testData/debug/long_name_win_test.py b/python/testData/debug/long_name_win_test.py new file mode 100644 index 000000000000..e61b3fcbeaf7 --- /dev/null +++ b/python/testData/debug/long_name_win_test.py @@ -0,0 +1,3 @@ +##intentionally named differently so that so that short name won't clash with other files +x = 5 + 5 +print (x) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java index 7db21fe94f89..2d6364a70f88 100644 --- a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java +++ b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java @@ -4,6 +4,8 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; import com.intellij.xdebugger.XDebuggerTestUtil; @@ -23,6 +25,7 @@ import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; import com.jetbrains.python.sdkTools.SdkCreationType; import org.jetbrains.annotations.NotNull; +import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -582,6 +585,43 @@ public class PythonDebuggerTest extends PyEnvTestCase { }); } + public void testWinLongName() throws Exception { + if (!SystemInfo.isWindows) + { + return; // Only needs to run on windows + } + runPythonTest(new PyDebuggerTask("/debug", "long_n~1.py") { + @Override + public void before() throws Exception { + + String scriptPath = getScriptPath(); + String longPath = FileUtil + .toSystemDependentName((new File(scriptPath).getCanonicalPath())); + LocalFileSystem.getInstance().refreshAndFindFileByPath(longPath); + toggleBreakpoint(longPath, 2); + + + } + + @Override + public void testing() throws Exception { + waitForPause(); + eval("x").hasValue("10"); + resume(); + + } + + @NotNull + @Override + public Set getTags() { + return ImmutableSet.of("-jython"); //TODO: fix that for Jython if anybody needs it + } + + + }); + } + + public void testStepOverConditionalBreakpoint() throws Exception { runPythonTest(new PyDebuggerTask("/debug", "test_stepOverCondition.py") {