Edward, not sure if you're following this thread, but the fix turned out to be entangled with a lot of @<file> stuff, so I don't want to push it without your inspection.
Repeating the basic problem: for an @<file> node there is some parent path in effect at the point where you reach the node, based on the location of the .leo file and any relevant @path directives. For determination of the full path to the target file, the @<file> node can either extend the parent path with a relative path (simplest case, just the filename), or discard the parent path with an absolute path of its own. The problem arises when the @<file> introduces a Windows drive specific \absolute\path without specifying the drive. In that case the drive should come from the original parent path.
I think the diff below does that ok. It might do it in more places than was needed to fix the original problem, but I don't think it does it in any places where it shouldn't.
Also, I think the same issue would affect the scanning of @path directives, this diff doesn't address that, although the fix_windows_absolute() method it introduces could probably be used for that application also. Here's the diff:
if name:
+ name = g.fix_windows_absolute(self, p, name)
name = g.os_path_finalize_join(path,name)
return name
#@+node:ekr.20091211111443.6265: *3* c.doBatchOperations & helpers
# Yes, this is correct. All os_path_x functions return Unicode strings.
return g.toUnicode(path)
+#@+node:tbrown.20100805110001.18803: *3* fix_windows_absolute
+def fix_windows_absolute(c, p, path):
+ """According to os.path.isabs(), in Windows, "\\foo\\bar.leo" is
+ an absolute path, but resolving it depends of the python process's
+ current directory. See http://bugs.python.org/issue1669539. So in
+ cases where we seem to be dealing with an "absolute" path of this
+ kind in Windows, we need to prepend the drive letter based on any
+ relevant @path directives and the location of the .leo file.
+ """
+
+ import platform
+
+ if not path or platform.system() != 'Windows' or path[0] != "\\":
+ return path
+
+ if len(path) > 1 and path[1] == "\\":
+ return path # don't mess with "\\server\share" style paths
+
+ # need drive letter from parent path
+ parent_path = c.getNodePath(p)
+
+ if not 'A' <= parent_path[0].upper() <= 'Z':
+ return path # because this state is not anticipated / understood
+
+ # this should take into account any @path directives, and, in the
+ # absence of any absolute path components, the starting point defined
+ # by the location of the .leo file
+ drive_letter = parent_path[:2]
+
+ g.es(path + " -> " + drive_letter + path)
+
+ return drive_letter + path # "E:" + "\some\thing"
#@+node:ekr.20031218072017.3151: ** Scanning... (leoGlobals.py)
#@+node:ekr.20031218072017.3156: *3* scanError
# It is dubious to bump the Tangle error count here, but it really doesn't hurt.
Edward, not sure if you're following this thread, but the fix turned out to be entangled with a lot of @<file> stuff, so I don't want to push it without your inspection.
Repeating the basic problem: for an @<file> node there is some parent path in effect at the point where you reach the node, based on the location of the .leo file and any relevant @path directives. For determination of the full path to the target file, the @<file> node can either extend the parent path with a relative path (simplest case, just the filename), or discard the parent path with an absolute path of its own. The problem arises when the @<file> introduces a Windows drive specific \absolute\path without specifying the drive. In that case the drive should come from the original parent path.
I think the diff below does that ok. It might do it in more places than was needed to fix the original problem, but I don't think it does it in any places where it shouldn't.
Also, I think the same issue would affect the scanning of @path directives, this diff doesn't address that, although the fix_windows_ absolute( ) method it introduces could probably be used for that application also. Here's the diff:
=== modified file 'leo/core/ leoAtFile. py' leoAtFile. py 2010-08-03 22:26:10 +0000 leoAtFile. py 2010-08-05 22:24:42 +0000
fileName = None
--- leo/core/
+++ leo/core/
@@ -688,6 +688,8 @@
else:
+ fileName = g.fix_windows_ absolute( self.c, root, fileName) +node:ekr. 20100224050618. 11547: *5* at.isFileLike
at.targetFil eName = root.atFileNode Name()
at. targetFileName = root.atFileNode Name() absolute( at.c, root, at.targetFileName)
at.initWriteI vars(root, at.targetFileNa me,
nosentine ls = nosentinels, thinFile = thinFile,
scriptWri te = scriptWrite, toString = toString) Name() absolute( c, p, fn) finalize_ join(path, fn)
g. trace(' can not happen: not an @<file> node:', g.callers( 4)) and_parents( ):
+
return fileName
#@
def isFileLike (self,s):
@@ -2815,7 +2817,10 @@
else:
+
+ at.targetFileName = g.fix_windows_
#@-<< set at.targetFileName >>
+
@@ -5166,7 +5171,9 @@
else:
fn = p.anyAtFileNode
if fn:
+ fn = g.fix_windows_
path = g.os_path_
+
else:
for p2 in p.self_
=== modified file 'leo/core/ leoCommands. py' leoCommands. py 2010-08-01 17:16:51 +0000 leoCommands. py 2010-08-05 22:59:13 +0000
--- leo/core/
+++ leo/core/
@@ -559,6 +559,7 @@
if name: break
if name: absolute( self, p, name) finalize_ join(path, name) +node:ekr. 20091211111443. 6265: *3* c.doBatchOperations & helpers
+ name = g.fix_windows_
name = g.os_path_
return name
#@
=== modified file 'leo/core/ leoGlobals. py' leoGlobals. py 2010-07-31 12:00:58 +0000 leoGlobals. py 2010-08-05 22:52:47 +0000 dirname( name) isabs(theDir) : absolute( c,p,theDir) exists( theDir) :
default_ dir = theDir
--- leo/core/
+++ leo/core/
@@ -936,6 +936,9 @@
if name:
theDir = g.os_path_
if theDir and g.os_path_
+
+ theDir = g.fix_windows_
+
if g.os_path_
else:
@@ -3603,6 +3606,38 @@
# Yes, this is correct. All os_path_x functions return Unicode strings. tbrown. 20100805110001. 18803: *3* fix_windows_ absolute absolute( c, p, path): bugs.python. org/issue166953 9. So in path[0] .upper( ) <= 'Z': ekr.20031218072 017.3151: ** Scanning... (leoGlobals.py) ekr.20031218072 017.3156: *3* scanError
return g.toUnicode(path)
+#@+node:
+def fix_windows_
+ """According to os.path.isabs(), in Windows, "\\foo\\bar.leo" is
+ an absolute path, but resolving it depends of the python process's
+ current directory. See http://
+ cases where we seem to be dealing with an "absolute" path of this
+ kind in Windows, we need to prepend the drive letter based on any
+ relevant @path directives and the location of the .leo file.
+ """
+
+ import platform
+
+ if not path or platform.system() != 'Windows' or path[0] != "\\":
+ return path
+
+ if len(path) > 1 and path[1] == "\\":
+ return path # don't mess with "\\server\share" style paths
+
+ # need drive letter from parent path
+ parent_path = c.getNodePath(p)
+
+ if not 'A' <= parent_
+ return path # because this state is not anticipated / understood
+
+ # this should take into account any @path directives, and, in the
+ # absence of any absolute path components, the starting point defined
+ # by the location of the .leo file
+ drive_letter = parent_path[:2]
+
+ g.es(path + " -> " + drive_letter + path)
+
+ return drive_letter + path # "E:" + "\some\thing"
#@+node:
#@+node:
# It is dubious to bump the Tangle error count here, but it really doesn't hurt.