Skip to content
Permalink
Browse files

Merge pull request #573 from topazproject/tim/File-Windows-backslash-…

…handling

Handle backslashes in File.dirname and File.expand_path on Windows
  • Loading branch information
alex committed Apr 6, 2013
2 parents f18bc92 + 9991756 commit 506c0b6fc6d357f08f4a06035888152d056bd024
Showing with 56 additions and 9 deletions.
  1. +28 −1 tests/objects/test_fileobject.py
  2. +28 −8 topaz/objects/fileobject.py
@@ -4,6 +4,7 @@
import pytest

from topaz.objects.fileobject import W_FileObject
from topaz.system import IS_WINDOWS

from ..base import BaseTopazTest

@@ -314,6 +315,16 @@ def test_expand_to_absolute(self, space):
with self.raises(space, "ArgumentError", "string contains null byte"):
space.execute("""return File.expand_path(".\\0.")""")

def test_expand_backslash_handling(self, space):
w_res = space.execute("""
return File.expand_path("a\\\\b")
""")
res = self.unwrap(space, w_res)
if IS_WINDOWS:
assert res == "/".join([os.getcwd().replace("\\", "/"), "a", "b"])
else:
assert res == os.path.join(os.getcwd(), "a\\b")

def test_covert_to_absolute_using_provided_base(self, space):
w_res = space.execute("""return File.expand_path("", "/tmp")""")
assert self.unwrap(space, w_res) == "/tmp"
@@ -345,7 +356,8 @@ def test_simple(self, space):
File.dirname("/home///guido//file.txt"),
File.dirname(""),
File.dirname("/"),
File.dirname("/foo/foo")
File.dirname("/foo/foo"),
File.dirname("/foo/foo//")
]
""")
assert self.unwrap(space, w_res) == [
@@ -356,4 +368,19 @@ def test_simple(self, space):
".",
"/",
"/foo",
"/foo",
]

def test_windows_backslash_handling(self, space):
w_res = space.execute("""
return [
File.dirname("a/b/c"),
File.dirname("a\\\\b\\\\//\\\\c/\\\\"),
File.dirname("\\\\"),
]
""")
res = self.unwrap(space, w_res)
if IS_WINDOWS:
assert res == ["a/b", "a\\b", "/"]
else:
assert res == ["a/b", "a\\b\\//\\c", "."]
@@ -102,18 +102,32 @@ def method_initialize(self, space, filename, w_mode=None, w_perm_or_opt=None, w_

@classdef.singleton_method("dirname", path="path")
def method_dirname(self, space, path):
if "/" not in path:
separators = ["/"]
if IS_WINDOWS:
separators.append("\\")

has_separator = False
for separator in separators:
if separator in path:
has_separator = True
break
if not has_separator:
return space.newstr_fromstr(".")
if path == "/":

if path in separators:
return space.newstr_fromstr("/")
if path.endswith("/"):

while path and path[-1] in separators:
newlen = len(path) - 1
assert newlen >= 0
path = path[:newlen]
idx = path.rfind("/")
while idx > 0 and path[idx - 1] == "/":

idx = -1
for separator in separators:
idx = max(idx, path.rfind(separator))
while idx > 0 and path[idx - 1] in separators:
idx -= 1
if idx == 0:
if idx <= 0:
return space.newstr_fromstr("/")
assert idx >= 0
return space.newstr_fromstr(path[:idx])
@@ -136,16 +150,22 @@ def method_expand_path(self, space, path, w_dir=None):
path = dir + "/" + path

items = []
if IS_WINDOWS:
path = path.replace("\\", "/")
parts = path.split("/")
for part in parts:
if part == "..":
items.pop()
elif part and part != ".":
items.append(part)

if not IS_WINDOWS:
root = "/"
else:
root = ""
if not items:
return space.newstr_fromstr("/")
return space.newstr_fromstr("/" + "/".join(items))
return space.newstr_fromstr(root)
return space.newstr_fromstr(root + "/".join(items))

@classdef.singleton_method("join")
def singleton_method_join(self, space, args_w):

0 comments on commit 506c0b6

Please sign in to comment.
You can’t perform that action at this time.