Skip to content

Commit df6c17f

Browse files
committed
improvements
1 parent 60e45b0 commit df6c17f

File tree

3 files changed

+56
-32
lines changed

3 files changed

+56
-32
lines changed

environment.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ channels:
55
dependencies:
66
- python==3.8
77
- fsspec==0.8.4
8+
# optional
89
- requests
9-
- jupyter
10+
- s3fs
11+
- jupyter
1012
- ipython
1113
- pytest
1214
- pylint

upath/core.py

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,52 @@
44
import urllib
55
import re
66

7-
from fsspec.registry import filesystem
7+
from fsspec.core import url_to_fs
8+
from fsspec.registry import filesystem, get_filesystem_class
89

910
from upath.errors import NotDirectoryError
1011

1112

12-
def argument_upath_self_to_filepath(func):
13-
'''if arguments are passed to the wrapped function, and if the first
14-
argument is a UniversalPath instance, that argument is replaced with
15-
the UniversalPath's path attribute
16-
'''
17-
def wrapper(*args, **kwargs):
18-
if args:
19-
args = list(args)
20-
first_arg = args.pop(0)
21-
if not kwargs.get('path'):
22-
if isinstance(first_arg, UniversalPath):
23-
first_arg = first_arg.path
24-
args.insert(0, first_arg)
25-
args = tuple(args)
26-
return func(*args, **kwargs)
27-
return wrapper
13+
2814

2915

3016
class _FSSpecAccessor:
3117

3218
def __init__(self, parsed_url, *args, **kwargs):
3319
self._url = parsed_url
34-
#from fsspec.registry import _registry
35-
36-
self._fs = filesystem(self._url.scheme, **kwargs)
20+
cls = get_filesystem_class(self._url.scheme)
21+
url_kwargs = cls._get_kwargs_from_urls(urllib.parse.urlunparse(self._url))
22+
url_kwargs.update(kwargs)
23+
self._fs = cls(**url_kwargs)
24+
25+
def argument_upath_self_to_filepath(self, func):
26+
'''if arguments are passed to the wrapped function, and if the first
27+
argument is a UniversalPath instance, that argument is replaced with
28+
the UniversalPath's path attribute
29+
'''
30+
def wrapper(*args, **kwargs):
31+
if args:
32+
args = list(args)
33+
first_arg = args.pop(0)
34+
if not kwargs.get('path'):
35+
if isinstance(first_arg, UniversalPath):
36+
first_arg = first_arg.path
37+
if not self._fs.root_marker and first_arg.startswith('/'):
38+
first_arg = first_arg[1:]
39+
args.insert(0, first_arg)
40+
args = tuple(args)
41+
else:
42+
if not self._fs.root_marker and kwargs['path'].startswith('/'):
43+
kwargs['path'] = kwargs['path'][1:]
44+
return func(*args, **kwargs)
45+
return wrapper
3746

3847
def __getattribute__(self, item):
3948
class_attrs = ['_url', '_fs']
4049
if item in class_attrs:
4150
x = super().__getattribute__(item)
4251
return x
43-
class_methods =['__init__', '__getattribute__']
52+
class_methods =['__init__', '__getattribute__', 'argument_upath_self_to_filepath']
4453
if item in class_methods:
4554
return lambda *args, **kwargs: getattr(_FSSpecAccessor, item)(self, *args, **kwargs)
4655
if item == '__class__':
@@ -50,7 +59,7 @@ def __getattribute__(self, item):
5059
if fs is not None:
5160
method = getattr(fs, item, None)
5261
if method:
53-
return lambda *args, **kwargs: argument_upath_self_to_filepath(method)(*args, **kwargs)
62+
return lambda *args, **kwargs: self.argument_upath_self_to_filepath(method)(*args, **kwargs)
5463
else:
5564
raise NotImplementedError(f'{fs.protocol} filesystem has not attribute {item}')
5665

@@ -76,7 +85,7 @@ def __new__(cls, *args, **kwargs):
7685
else:
7786
cls = UniversalPath
7887
cls._url = parsed_url
79-
kwargs['_url'] = parsed_url
88+
#kwargs['_url'] = parsed_url
8089
cls._kwargs = kwargs
8190
new_args.insert(0, parsed_url.path)
8291
args = tuple(new_args)
@@ -104,8 +113,11 @@ class UniversalPath(Path, PureUniversalPath):
104113

105114
def _init(self, *args, template=None, **kwargs):
106115
self._closed = False
107-
if not self._root and self._parts[0] == '/':
108-
self._root = self._parts.pop(0)
116+
if not self._root:
117+
if not self._parts:
118+
self._root = '/'
119+
elif self._parts[0] == '/':
120+
self._root = self._parts.pop(0)
109121
if getattr(self, '_str', None):
110122
delattr(self, '_str')
111123

@@ -182,7 +194,8 @@ def iterdir(self):
182194
# Yielding a path object for these makes little sense
183195
continue
184196
# only want the path name with iterdir
185-
name = re.sub(f'^{self.path}/', '', name)
197+
sp = self.path
198+
name = re.sub(f'^({sp}|{sp[1:]})/', '', name)
186199
yield self._make_child_relpath(name)
187200
if self._closed:
188201
self._raise_closed()
@@ -211,7 +224,11 @@ def is_file(self):
211224

212225
def glob(self, pattern):
213226
path = self.joinpath(pattern)
214-
return self._accessor.glob(self, path=path)
227+
for name in self._accessor.glob(self, path=path.path):
228+
sp = self.path
229+
name = re.sub(f'^({sp}|{sp[1:]})/', '', name)
230+
name = name.split(self._flavour.sep)
231+
yield self._make_child(self._parts + name)
215232

216233
def rename(self, target):
217234
# can be implimented, but may be tricky

upath/tests/test_core.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,16 @@ def test_expanduser(self, mock_base):
4545
mock_base.expanduser()
4646

4747
def test_glob(self, mock_base, pathlib_base):
48-
mock_glob = mock_base.glob('**/*.txt')
49-
path_glob = pathlib_base.glob('**/*.txt')
48+
mock_glob = list(mock_base.glob('**.txt'))
49+
path_glob = list(pathlib_base.glob('**/*.txt'))
5050

51-
for m, p in zip(mock_glob, path_glob):
52-
assert m.path == str(p)
51+
print(mock_glob)
52+
print(path_glob)
53+
54+
assert len(mock_glob) == len(path_glob)
55+
assert all(map(lambda m: m.path in [str(p) for p in path_glob], mock_glob))
56+
# for m, p in zip(mock_glob, path_glob):
57+
# assert m.path == str(p)
5358

5459
def test_group(self, mock_base):
5560
with pytest.raises(NotImplementedError):

0 commit comments

Comments
 (0)