Skip to content

Commit dcf54ce

Browse files
authored
Win fix (#269)
* check for readlink * no test symlink * capital I * handle lack of readlink * winfix * readlink on windows * case insensitive fix * debug * fix for FileExpected * correct error * fix for file expected * fix name conflict * close tempfiles * fix ftp test * exclude test from windows * version bump
1 parent 183affb commit dcf54ce

File tree

10 files changed

+99
-67
lines changed

10 files changed

+99
-67
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

8+
## [2.4.3] - 2019-02-23
9+
10+
### Fixed
11+
12+
- Fixed broken "case_insensitive" check
13+
- Fixed Windows test fails
14+
815
## [2.4.2] - 2019-02-22
916

1017
### Fixed

appveyor.yml

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,25 @@ environment:
55
# The list here is complete (excluding Python 2.6, which
66
# isn't covered by this document) at the time of writing.
77

8-
- PYTHON: "C:\\Python27"
9-
- PYTHON: "C:\\Python33"
10-
- PYTHON: "C:\\Python34"
11-
- PYTHON: "C:\\Python35"
12-
- PYTHON: "C:\\Python27-x64"
13-
- PYTHON: "C:\\Python33-x64"
14-
DISTUTILS_USE_SDK: "1"
15-
- PYTHON: "C:\\Python34-x64"
16-
DISTUTILS_USE_SDK: "1"
17-
- PYTHON: "C:\\Python35-x64"
8+
# - PYTHON: "C:\\Python27"
9+
# - PYTHON: "C:\\Python33"
10+
# - PYTHON: "C:\\Python34"
11+
# - PYTHON: "C:\\Python35"
12+
# - PYTHON: "C:\\Python27-x64"
13+
# - PYTHON: "C:\\Python33-x64"
14+
# DISTUTILS_USE_SDK: "1"
15+
# - PYTHON: "C:\\Python34-x64"
16+
# DISTUTILS_USE_SDK: "1"
17+
# - PYTHON: "C:\\Python35-x64"
1818
- PYTHON: "C:\\Python36-x64"
19+
- PYTHON: "C:\\Python37-x64"
1920

2021
install:
2122
# We need wheel installed to build wheels
22-
- "%PYTHON%\\python.exe -m pip install nose pyftpdlib mock"
23+
- "%PYTHON%\\python.exe -m pip install nose psutil pyftpdlib mock"
2324
- "%PYTHON%\\python.exe setup.py install"
2425

2526
build: off
2627

2728
test_script:
28-
- "%PYTHON%\\python.exe -m nose tests"
29+
- "%PYTHON%\\python.exe -m nose tests -v"

fs/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Version, used in module and setup.py.
22
"""
3-
__version__ = "2.4.2"
3+
__version__ = "2.4.3"

fs/osfs.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
from .permissions import Permissions
4848
from .error_tools import convert_os_errors
4949
from .mode import Mode, validate_open_mode
50-
from .errors import NoURL
50+
from .errors import FileExpected, NoURL
5151

5252
if False: # typing.TYPE_CHECKING
5353
from typing import (
@@ -134,7 +134,7 @@ def __init__(
134134
raise errors.CreateFailed("root path does not exist")
135135

136136
_meta = self._meta = {
137-
"case_insensitive": os.path.normcase("Aa") != "aa",
137+
"case_insensitive": os.path.normcase("Aa") == "aa",
138138
"network": False,
139139
"read_only": False,
140140
"supports_rename": True,
@@ -245,12 +245,17 @@ def _get_type_from_stat(cls, _stat):
245245

246246
def _gettarget(self, sys_path):
247247
# type: (Text) -> Optional[Text]
248-
try:
249-
target = os.readlink(fsencode(sys_path))
250-
except OSError:
251-
return None
252-
else:
253-
return target
248+
if hasattr(os, "readlink"):
249+
try:
250+
if _WINDOWS_PLATFORM: # pragma: no cover
251+
target = os.readlink(sys_path)
252+
else:
253+
target = os.readlink(fsencode(sys_path))
254+
except OSError:
255+
pass
256+
else:
257+
return target
258+
return None
254259

255260
def _make_link_info(self, sys_path):
256261
# type: (Text) -> Dict[Text, object]
@@ -328,6 +333,8 @@ def openbin(self, path, mode="r", buffering=-1, **options):
328333
_mode.validate_bin()
329334
self.check()
330335
_path = self.validatepath(path)
336+
if _path == "/":
337+
raise errors.FileExpected(path)
331338
sys_path = self._to_sys_path(_path)
332339
with convert_os_errors("openbin", path):
333340
if six.PY2 and _mode.exclusive:
@@ -454,7 +461,12 @@ def _scandir(self, path, namespaces=None):
454461
self.check()
455462
namespaces = namespaces or ()
456463
_path = self.validatepath(path)
457-
sys_path = self._to_sys_path(_path)
464+
if _WINDOWS_PLATFORM:
465+
sys_path = os.path.join(
466+
self._root_path, path.lstrip("/").replace("/", os.sep)
467+
)
468+
else:
469+
sys_path = self._to_sys_path(_path)
458470
with convert_os_errors("scandir", path, directory=True):
459471
for dir_entry in scandir(sys_path):
460472
info = {
@@ -595,6 +607,8 @@ def open(
595607
validate_open_mode(mode)
596608
self.check()
597609
_path = self.validatepath(path)
610+
if _path == "/":
611+
raise FileExpected(path)
598612
sys_path = self._to_sys_path(_path)
599613
with convert_os_errors("open", path):
600614
if six.PY2 and _mode.exclusive:

tests/test_archives.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,9 +86,10 @@ def test_getinfo(self):
8686
except errors.NoSysPath:
8787
pass
8888
else:
89-
self.assertEqual(
90-
top.permissions.mode, stat.S_IMODE(os.stat(source_syspath).st_mode)
91-
)
89+
if top.has_namespace("access"):
90+
self.assertEqual(
91+
top.permissions.mode, stat.S_IMODE(os.stat(source_syspath).st_mode)
92+
)
9293

9394
self.assertEqual(top.get("details", "type"), ResourceType.file)
9495

tests/test_encoding.py

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,43 +12,48 @@
1212
from fs.osfs import OSFS
1313

1414

15-
@unittest.skipIf(platform.system() == "Darwin", "Bad unicode not possible on OSX")
16-
class TestEncoding(unittest.TestCase):
17-
18-
TEST_FILENAME = b"foo\xb1bar"
19-
TEST_FILENAME_UNICODE = fs.fsdecode(TEST_FILENAME)
20-
21-
def setUp(self):
22-
dir_path = self.dir_path = tempfile.mkdtemp()
23-
if six.PY2:
24-
with open(os.path.join(dir_path, self.TEST_FILENAME), "wb") as f:
25-
f.write(b"baz")
26-
else:
27-
with open(os.path.join(dir_path, self.TEST_FILENAME_UNICODE), "wb") as f:
28-
f.write(b"baz")
29-
30-
def tearDown(self):
31-
shutil.rmtree(self.dir_path)
32-
33-
def test_open(self):
34-
with OSFS(self.dir_path) as test_fs:
35-
self.assertTrue(test_fs.exists(self.TEST_FILENAME_UNICODE))
36-
self.assertTrue(test_fs.isfile(self.TEST_FILENAME_UNICODE))
37-
self.assertFalse(test_fs.isdir(self.TEST_FILENAME_UNICODE))
38-
with test_fs.open(self.TEST_FILENAME_UNICODE, "rb") as f:
39-
self.assertEqual(f.read(), b"baz")
40-
self.assertEqual(test_fs.readtext(self.TEST_FILENAME_UNICODE), "baz")
41-
test_fs.remove(self.TEST_FILENAME_UNICODE)
42-
self.assertFalse(test_fs.exists(self.TEST_FILENAME_UNICODE))
43-
44-
def test_listdir(self):
45-
with OSFS(self.dir_path) as test_fs:
46-
dirlist = test_fs.listdir("/")
47-
self.assertEqual(dirlist, [self.TEST_FILENAME_UNICODE])
48-
self.assertEqual(test_fs.readtext(dirlist[0]), "baz")
49-
50-
def test_scandir(self):
51-
with OSFS(self.dir_path) as test_fs:
52-
for info in test_fs.scandir("/"):
53-
self.assertIsInstance(info.name, six.text_type)
54-
self.assertEqual(info.name, self.TEST_FILENAME_UNICODE)
15+
if platform.system() != "Windows":
16+
17+
@unittest.skipIf(platform.system() == "Darwin", "Bad unicode not possible on OSX")
18+
class TestEncoding(unittest.TestCase):
19+
20+
TEST_FILENAME = b"foo\xb1bar"
21+
# fsdecode throws error on Windows
22+
TEST_FILENAME_UNICODE = fs.fsdecode(TEST_FILENAME)
23+
24+
def setUp(self):
25+
dir_path = self.dir_path = tempfile.mkdtemp()
26+
if six.PY2:
27+
with open(os.path.join(dir_path, self.TEST_FILENAME), "wb") as f:
28+
f.write(b"baz")
29+
else:
30+
with open(
31+
os.path.join(dir_path, self.TEST_FILENAME_UNICODE), "wb"
32+
) as f:
33+
f.write(b"baz")
34+
35+
def tearDown(self):
36+
shutil.rmtree(self.dir_path)
37+
38+
def test_open(self):
39+
with OSFS(self.dir_path) as test_fs:
40+
self.assertTrue(test_fs.exists(self.TEST_FILENAME_UNICODE))
41+
self.assertTrue(test_fs.isfile(self.TEST_FILENAME_UNICODE))
42+
self.assertFalse(test_fs.isdir(self.TEST_FILENAME_UNICODE))
43+
with test_fs.open(self.TEST_FILENAME_UNICODE, "rb") as f:
44+
self.assertEqual(f.read(), b"baz")
45+
self.assertEqual(test_fs.readtext(self.TEST_FILENAME_UNICODE), "baz")
46+
test_fs.remove(self.TEST_FILENAME_UNICODE)
47+
self.assertFalse(test_fs.exists(self.TEST_FILENAME_UNICODE))
48+
49+
def test_listdir(self):
50+
with OSFS(self.dir_path) as test_fs:
51+
dirlist = test_fs.listdir("/")
52+
self.assertEqual(dirlist, [self.TEST_FILENAME_UNICODE])
53+
self.assertEqual(test_fs.readtext(dirlist[0]), "baz")
54+
55+
def test_scandir(self):
56+
with OSFS(self.dir_path) as test_fs:
57+
for info in test_fs.scandir("/"):
58+
self.assertIsInstance(info.name, six.text_type)
59+
self.assertEqual(info.name, self.TEST_FILENAME_UNICODE)

tests/test_ftpfs.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from fs import errors
2626
from fs.opener import open_fs
2727
from fs.ftpfs import FTPFS, ftp_errors
28+
from fs.path import join
2829
from fs.subfs import SubFS
2930
from fs.test import FSTestCases
3031

@@ -200,7 +201,7 @@ def test_opener_path(self):
200201

201202
def test_create(self):
202203

203-
directory = os.path.join("home", self.user, "test", "directory")
204+
directory = join("home", self.user, "test", "directory")
204205
base = "ftp://user:1234@{}:{}/foo".format(self.server.host, self.server.port)
205206
url = "{}/{}".format(base, directory)
206207

@@ -215,7 +216,7 @@ def test_create(self):
215216
# Open the base filesystem and check the subdirectory exists
216217
with open_fs(base) as ftp_fs:
217218
self.assertTrue(ftp_fs.isdir(directory))
218-
self.assertTrue(ftp_fs.isfile(os.path.join(directory, "foo")))
219+
self.assertTrue(ftp_fs.isfile(join(directory, "foo")))
219220

220221
# Open without `create` and check the file exists
221222
with open_fs(url) as ftp_fs:

tests/test_osfs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def test_unicode_paths(self):
115115
finally:
116116
shutil.rmtree(dir_path)
117117

118+
@unittest.skipIf(not hasattr(os, "symlink"), "No symlink support")
118119
def test_symlinks(self):
119120
with open(self._get_real_path("foo"), "wb") as f:
120121
f.write(b"foobar")

tests/test_tarfs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
class TestWriteReadTarFS(unittest.TestCase):
2727
def setUp(self):
2828
fh, self._temp_path = tempfile.mkstemp()
29+
os.close(fh)
2930

3031
def tearDown(self):
3132
os.remove(self._temp_path)

tests/test_zipfs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
class TestWriteReadZipFS(unittest.TestCase):
2323
def setUp(self):
2424
fh, self._temp_path = tempfile.mkstemp()
25+
os.close(fh)
2526

2627
def tearDown(self):
2728
os.remove(self._temp_path)

0 commit comments

Comments
 (0)