Commit f37f20eb by willmcgugan

Added new appdirfs module

parent db7cbe5e
"""
fs.appdirfs
===========
A collection of filesystems that map to application specific locations.
These classes abstract away the different requirements for user data across platforms,
which vary in their conventions. They are all subclasses of :class:`fs.osfs.OSFS`,
all that differs from `OSFS` is the constructor which detects the appropriate
location given the name of the application, author name and other parameters.
Uses `appdirs` (https://github.com/ActiveState/appdirs), written by Trent Mick and Sridhar Ratnakumar <trentm at gmail com; github at srid name>
"""
from fs.osfs import OSFS
from fs.appdirs import AppDirs
__all__ = ['UserDataFS',
'SiteDataFS',
'UserCacheFS',
'UserLogFS']
class UserDataFS(OSFS):
"""A filesystem for per-user application data."""
def __init__(self, appname, appauthor=None, version=None, roaming=False, create=True):
"""
:param appname: the name of the application
:param appauthor: the name of the author (used on Windows)
:param version: optional version string, if a unique location per version of the application is required
:param roaming: if True, use a *roaming* profile on Windows, see http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx
:param create: if True (the default) the directory will be created if it does not exist
"""
app_dirs = AppDirs(appname, appauthor, version, roaming)
super(self.__class__, self).__init__(app_dirs.user_data_dir, create=create)
class SiteDataFS(OSFS):
"""A filesystem for application site data."""
def __init__(self, appname, appauthor=None, version=None, roaming=False, create=True):
"""
:param appname: the name of the application
:param appauthor: the name of the author (not used on linux)
:param version: optional version string, if a unique location per version of the application is required
:param roaming: if True, use a *roaming* profile on Windows, see http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx
:param create: if True (the default) the directory will be created if it does not exist
"""
app_dirs = AppDirs(appname, appauthor, version, roaming)
super(self.__class__, self).__init__(app_dirs.site_data_dir, create=create)
class UserCacheFS(OSFS):
"""A filesystem for per-user application cache data."""
def __init__(self, appname, appauthor=None, version=None, roaming=False, create=True):
"""
:param appname: the name of the application
:param appauthor: the name of the author (not used on linux)
:param version: optional version string, if a unique location per version of the application is required
:param roaming: if True, use a *roaming* profile on Windows, see http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx
:param create: if True (the default) the directory will be created if it does not exist
"""
app_dirs = AppDirs(appname, appauthor, version, roaming)
super(self.__class__, self).__init__(app_dirs.user_cache_dir, create=create)
class UserLogFS(OSFS):
"""A filesystem for per-user application log data."""
def __init__(self, appname, appauthor=None, version=None, roaming=False, create=True):
"""
:param appname: the name of the application
:param appauthor: the name of the author (not used on linux)
:param version: optional version string, if a unique location per version of the application is required
:param roaming: if True, use a *roaming* profile on Windows, see http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx
:param create: if True (the default) the directory will be created if it does not exist
"""
app_dirs = AppDirs(appname, appauthor, version, roaming)
super(self.__class__, self).__init__(app_dirs.user_log_dir, create=create)
if __name__ == "__main__":
udfs = UserDataFS('sexytime', appauthor='pyfs')
print udfs
udfs2 = UserDataFS('sexytime2', appauthor='pyfs', create=False)
print udfs2
\ No newline at end of file
This diff is collapsed. Click to expand it.
#!/usr/bin/env python #!/usr/bin/env python
from fs.opener import opener
from fs.commands.runner import Command from fs.commands.runner import Command
import sys import sys
......
#!/usr/bin/env python #!/usr/bin/env python
from fs.utils import copyfile, copyfile_non_atomic
from fs.opener import opener
from fs.utils import copyfile, copyfile_non_atomic, copystructure
from fs.path import pathjoin, iswildcard from fs.path import pathjoin, iswildcard
from fs.errors import FSError
from fs.commands.runner import Command from fs.commands.runner import Command
import sys import sys
import Queue as queue import Queue as queue
...@@ -184,7 +181,7 @@ Copy SOURCE to DESTINATION""" ...@@ -184,7 +181,7 @@ Copy SOURCE to DESTINATION"""
for thread in threads: for thread in threads:
thread.join() thread.join()
complete = True complete = True
if not any_error(): if not self.any_error():
self.post_actions() self.post_actions()
dst_fs.close() dst_fs.close()
...@@ -254,4 +251,3 @@ def run(): ...@@ -254,4 +251,3 @@ def run():
if __name__ == "__main__": if __name__ == "__main__":
sys.exit(run()) sys.exit(run())
\ No newline at end of file
#!/usr/bin/env python #!/usr/bin/env python
from fs.errors import ResourceNotFoundError
from fs.opener import opener
from fs.commands.runner import Command from fs.commands.runner import Command
import sys import sys
from datetime import datetime from datetime import datetime
......
#!/usr/bin/env python #!/usr/bin/env python
from fs.opener import opener
from fs.commands.runner import Command from fs.commands.runner import Command
import sys import sys
...@@ -14,7 +12,7 @@ Make a directory""" ...@@ -14,7 +12,7 @@ Make a directory"""
def do_run(self, options, args): def do_run(self, options, args):
for fs_url in args: for fs_url in args:
fs, path = self.open_fs(fs_url, create_dir=True) self.open_fs(fs_url, create_dir=True)
def run(): def run():
return FSMkdir().run() return FSMkdir().run()
......
#!/usr/bin/env python #!/usr/bin/env python
from fs.opener import opener
from fs.commands.runner import Command from fs.commands.runner import Command
import sys import sys
import platform import platform
import os import os
import os.path import os.path
import time
platform = platform.system() platform = platform.system()
......
...@@ -646,6 +646,83 @@ example: ...@@ -646,6 +646,83 @@ example:
fs = HTTPFS('http://' + dirname) fs = HTTPFS('http://' + dirname)
return fs, resourcename return fs, resourcename
class UserDataOpener(Opener):
names = ['appuserdata']
desc = """Opens a filesystem for a per-user application directory.
The 'domain' should be in the form <author name>:<application name>.<version> (the author name and version are optional).
example:
* appuserdata://myapplication
* appuserdata://examplesoft:myapplication
* appuserdata://anotherapp.1.1
* appuserdata://examplesoft:anotherapp.1.3"""
FSClass = 'UserDataFS'
@classmethod
def get_fs(cls, registry, fs_name, fs_name_params, fs_path, writeable, create_dir):
import fs.appdirfs
fs_class = getattr(fs.appdirfs, cls.FSClass)
if ':' in fs_path:
appauthor, appname = fs_path.split(':', 1)
else:
appauthor = None
appname = fs_path
if '.' in appname:
appname, appversion = appname.split('.', 1)
else:
appversion = None
fs = fs_class(appname, appauthor=appauthor, version=appversion, create=create_dir)
return fs, ''
class SiteDataOpener(UserDataOpener):
names = ['appsitedata']
desc = """Opens a filesystem for an application site data directory.
The 'domain' should be in the form <author name>:<application name>.<version> (the author name and version are optional).
example:
* appsitedata://myapplication
* appsitedata://examplesoft:myapplication
* appsitedata://anotherapp.1.1
* appsitedata://examplesoft:anotherapp.1.3"""
FSClass = 'SiteDataFS'
class UserCacheOpener(UserDataOpener):
names = ['appusercache']
desc = """Opens a filesystem for an per-user application cache directory.
The 'domain' should be in the form <author name>:<application name>.<version> (the author name and version are optional).
example:
* appusercache://myapplication
* appusercache://examplesoft:myapplication
* appusercache://anotherapp.1.1
* appusercache://examplesoft:anotherapp.1.3"""
FSClass = 'UserCacheFS'
class UserLogOpener(UserDataOpener):
names = ['appuserlog']
desc = """Opens a filesystem for an application site data directory.
The 'domain' should be in the form <author name>:<application name>.<version> (the author name and version are optional).
example:
* appuserlog://myapplication
* appuserlog://examplesoft:myapplication
* appuserlog://anotherapp.1.1
* appuserlog://examplesoft:anotherapp.1.3"""
FSClass = 'UserLogFS'
opener = OpenerRegistry([OSFSOpener, opener = OpenerRegistry([OSFSOpener,
ZipOpener, ZipOpener,
...@@ -659,6 +736,10 @@ opener = OpenerRegistry([OSFSOpener, ...@@ -659,6 +736,10 @@ opener = OpenerRegistry([OSFSOpener,
TahoeOpener, TahoeOpener,
DavOpener, DavOpener,
HTTPOpener, HTTPOpener,
UserDataOpener,
SiteDataOpener,
UserCacheOpener,
UserLogOpener
]) ])
fsopen = opener.open fsopen = opener.open
......
...@@ -308,13 +308,13 @@ class FSTestCases(object): ...@@ -308,13 +308,13 @@ class FSTestCases(object):
if "c" in files: if "c" in files:
break break
assert found_a, "breadth search order was wrong" assert found_a, "breadth search order was wrong"
# When searching deth-first, deep entries come first # When searching depth-first, deep entries come first
found_c = False found_c = False
for _,files in self.fs.walk(search="depth"): for _,files in self.fs.walk(search="depth"):
if "c" in files: if "c" in files:
found_c = True found_c = True
if "a.txt" in files: if "a.txt" in files:
break break
assert found_c, "depth search order was wrong: " + str(list(self.fs.walk(search="depth"))) assert found_c, "depth search order was wrong: " + str(list(self.fs.walk(search="depth")))
def test_walk_wildcard(self): def test_walk_wildcard(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment