Skip to content

Commit 0b6f440

Browse files
authored
use FS URLs in multi and mount fs (#66)
* use FS URLs in multi and mount fs * docstrings * typo * fix typo * naming issue * version bump
1 parent 86b990b commit 0b6f440

12 files changed

Lines changed: 152 additions & 11 deletions

File tree

fs/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.0.8"
1+
__version__ = "2.0.9a0"

fs/appfs.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ class UserDataFS(_AppFS):
6363
"""
6464
A filesystem for per-user application data.
6565
66+
May also be opened with
67+
``open_fs('userdata://appname:author:version')``.
68+
6669
:param str appname: The name of the application.
6770
:param str author: The name of the author (used on Windows).
6871
:param str version: Optional version string, if a unique location
@@ -80,6 +83,9 @@ class UserConfigFS(_AppFS):
8083
"""
8184
A filesystem for per-user config data.
8285
86+
May also be opened with
87+
``open_fs('userconf://appname:author:version')``.
88+
8389
:param str appname: The name of the application.
8490
:param str author: The name of the author (used on Windows).
8591
:param str version: Optional version string, if a unique location
@@ -97,6 +103,9 @@ class UserCacheFS(_AppFS):
97103
"""
98104
A filesystem for per-user application cache data.
99105
106+
May also be opened with
107+
``open_fs('usercache://appname:author:version')``.
108+
100109
:param str appname: The name of the application.
101110
:param str author: The name of the author (used on Windows).
102111
:param str version: Optional version string, if a unique location
@@ -114,6 +123,9 @@ class SiteDataFS(_AppFS):
114123
"""
115124
A filesystem for application site data.
116125
126+
May also be opened with
127+
``open_fs('sitedata://appname:author:version')``.
128+
117129
:param str appname: The name of the application.
118130
:param str author: The name of the author (used on Windows).
119131
:param str version: Optional version string, if a unique location
@@ -131,6 +143,9 @@ class SiteConfigFS(_AppFS):
131143
"""
132144
A filesystem for application config data.
133145
146+
May also be opened with
147+
``open_fs('siteconf://appname:author:version')``.
148+
134149
:param str appname: The name of the application.
135150
:param str author: The name of the author (used on Windows).
136151
:param str version: Optional version string, if a unique location
@@ -148,6 +163,9 @@ class UserLogFS(_AppFS):
148163
"""
149164
A filesystem for per-user application log data.
150165
166+
May also be opened with
167+
``open_fs('userlog://appname:author:version')``.
168+
151169
:param str appname: The name of the application.
152170
:param str author: The name of the author (used on Windows).
153171
:param str version: Optional version string, if a unique location

fs/base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,7 @@ def check(self):
12041204
Check a filesystem may be used.
12051205
12061206
Will throw a :class:`~fs.errors.FilesystemClosed` if the
1207-
filesystem is closed.
1207+
filesystem is closed.
12081208
12091209
:returns: None
12101210
:raises fs.errors.FilesystemClosed: if the filesystem

fs/iotools.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ def __iter__(self):
115115
return iter(self._f)
116116

117117

118-
119118
def make_stream(name,
120119
bin_file,
121120
mode='r',

fs/mountfs.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from __future__ import print_function
33
from __future__ import unicode_literals
44

5+
from six import text_type
6+
57
from . import errors
68
from .base import FS
79
from .memoryfs import MemoryFS
@@ -67,10 +69,19 @@ def mount(self, path, fs):
6769
6870
:param path: A path within the MountFS.
6971
:type path: str
70-
:param fs: A filesystem object to mount.
72+
:param fs: A filesystem object or FS URL to mount.
7173
:type fs: :class:`~fs.base.FS`
7274
7375
"""
76+
if isinstance(fs, text_type):
77+
from .opener import open_fs
78+
fs = open_fs(fs)
79+
80+
if not isinstance(fs, FS):
81+
raise TypeError(
82+
'fs argument must be an FS object or a FS URL'
83+
)
84+
7485
if fs is self:
7586
raise ValueError('Unable to mount self')
7687
_path = forcedir(abspath(normpath(path)))

fs/multifs.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,21 @@
55
from collections import namedtuple
66
from operator import itemgetter
77

8+
from six import text_type
9+
810
from .base import FS
911
from .mode import check_writable
1012
from . import errors
13+
from .opener import open_fs
1114
from .path import abspath, normpath
1215

1316

1417
_PrioritizedFS = namedtuple(
1518
'_PrioritizedFS',
16-
['priority', 'fs']
19+
[
20+
'priority',
21+
'fs'
22+
]
1723
)
1824

1925

@@ -61,8 +67,8 @@ def add_fs(self, name, fs, write=False, priority=0):
6167
:param name: A unique name to refer to the filesystem being
6268
added.
6369
:type name: str
64-
:param fs: The filesystem to add
65-
:type fs: Filesystem
70+
:param fs: The filesystem to add.
71+
:type fs: Filesystem or FS URL.
6672
:param write: If this value is True, then the ``fs`` will be
6773
used as the writeable FS.
6874
:type write: bool
@@ -75,6 +81,14 @@ def add_fs(self, name, fs, write=False, priority=0):
7581
7682
"""
7783

84+
if isinstance(fs, text_type):
85+
fs = open_fs(fs)
86+
87+
if not isinstance(fs, FS):
88+
raise TypeError(
89+
'fs argument should be an FS object or FS URL'
90+
)
91+
7892
self._filesystems[name] = _PrioritizedFS(
7993
priority=(priority, self._sort_index),
8094
fs=fs

fs/opener/appfs.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# coding: utf-8
2+
"""Defines the MemOpener."""
3+
4+
from __future__ import absolute_import
5+
from __future__ import print_function
6+
from __future__ import unicode_literals
7+
8+
from .base import Opener
9+
from .errors import OpenerError
10+
from .. import appfs
11+
12+
13+
class AppFSOpener(Opener):
14+
15+
protocols = [
16+
'userdata',
17+
'userconf',
18+
'sitedata',
19+
'siteconf',
20+
'usercache',
21+
'userlog'
22+
]
23+
24+
_protocol_mapping = {
25+
'userdata': appfs.UserDataFS,
26+
'userconf': appfs.UserConfigFS,
27+
'sitedata': appfs.SiteDataFS,
28+
'siteconf': appfs.SiteConfigFS,
29+
'usercache': appfs.UserCacheFS,
30+
'userlog': appfs.UserLogFS
31+
}
32+
33+
def open_fs(self, fs_url, parse_result, writeable, create, cwd):
34+
fs_class = self._protocol_mapping[parse_result.protocol]
35+
36+
tokens = parse_result.resource.split(':', 3)
37+
if len(tokens) == 2:
38+
appname, author = tokens
39+
version = None
40+
elif len(tokens) == 3:
41+
appname, author, version = tokens
42+
else:
43+
raise OpenerError(
44+
'resource should be <appname>:<author> '
45+
'or <appname>:<author>:<version>'
46+
)
47+
48+
fs_instance = fs_class(
49+
appname,
50+
author=author,
51+
version=version,
52+
create=create
53+
)
54+
return fs_instance
55+

fs/wrapfs.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ def delegate_fs(self):
7070
"""
7171
return self._wrap_fs
7272

73-
7473
def appendbytes(self, path, data):
7574
self.check()
7675
_fs, _path = self.delegate_path(path)
@@ -88,7 +87,6 @@ def appendtext(self, path, text,
8887
errors=errors,
8988
newline=newline)
9089

91-
9290
def getinfo(self, path, namespaces=None):
9391
self.check()
9492
_fs, _path = self.delegate_path(path)

setup.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@
4747
'tar = fs.opener.tarfs:TarOpener',
4848
'temp = fs.opener.tempfs:TempOpener',
4949
'zip = fs.opener.zipfs:ZipOpener',
50+
51+
'userdata = fs.opener.appfs:AppFSOpener',
52+
'userconf = fs.opener.appfs:AppFSOpener',
53+
'sitedata = fs.opener.appfs:AppFSOpener',
54+
'siteconf = fs.opener.appfs:AppFSOpener',
55+
'usercache = fs.opener.appfs:AppFSOpener',
56+
'userlog = fs.opener.appfs:AppFSOpener',
5057
]},
5158
license="MIT",
5259
long_description=DESCRIPTION,

tests/test_mountfs.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,21 @@ def make_fs(self):
3030

3131
class TestMountFSBehaviours(unittest.TestCase):
3232

33+
def test_bad_mount(self):
34+
mount_fs = MountFS()
35+
with self.assertRaises(TypeError):
36+
mount_fs.mount('foo', 5)
37+
with self.assertRaises(TypeError):
38+
mount_fs.mount('foo', b'bar')
39+
3340
def test_listdir(self):
3441
mount_fs = MountFS()
3542
self.assertEqual(mount_fs.listdir('/'), [])
3643
m1 = MemoryFS()
37-
m2 = TempFS()
3844
m3 = MemoryFS()
3945
m4 = TempFS()
4046
mount_fs.mount('/m1', m1)
41-
mount_fs.mount('/m2', m2)
47+
mount_fs.mount('/m2', 'temp://')
4248
mount_fs.mount('/m3', m3)
4349
with self.assertRaises(MountError):
4450
mount_fs.mount('/m3/foo', m4)

0 commit comments

Comments
 (0)