From 81bd9f70636dfa5ca5802de84704b98e2dae0872 Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Mon, 25 Sep 2017 13:32:52 -0400 Subject: [PATCH] resources Signed-off-by: Kenneth Reitz --- click_tools/resources.py | 167 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 click_tools/resources.py diff --git a/click_tools/resources.py b/click_tools/resources.py new file mode 100644 index 0000000..443a4a4 --- /dev/null +++ b/click_tools/resources.py @@ -0,0 +1,167 @@ +# -*- coding: utf-8 -*- + +""" +click-tools.resources +~~~~~~~~~~~~~~~~~~~~~ + +This module contains all the application resource features of click-tools. + +""" + + +from __future__ import absolute_import +from __future__ import with_statement + +import errno +from os import remove, removedirs +from os.path import isfile, join as path_join + +from appdirs import AppDirs + +from .utils import mkdir_p, is_collection + + +__all__ = ( + 'init', 'user', 'site', 'cache', + 'log', 'NotConfigured' +) + + +class AppDir(object): + """Application Directory object.""" + + def __init__(self, path=None): + self.path = path + self._exists = False + + if path: + self._create() + + def __repr__(self): + return '' % (self.path) + + def __getattribute__(self, name): + + if not name in ('_exists', 'path', '_create', '_raise_if_none'): + if not self._exists: + self._create() + return object.__getattribute__(self, name) + + def _raise_if_none(self): + """Raises if operations are carried out on an unconfigured AppDir.""" + if not self.path: + raise NotConfigured() + + def _create(self): + """Creates current AppDir at AppDir.path.""" + + self._raise_if_none() + if not self._exists: + mkdir_p(self.path) + self._exists = True + + def open(self, filename, mode='r'): + """Returns file object from given filename.""" + + self._raise_if_none() + fn = path_join(self.path, filename) + + return open(fn, mode) + + def write(self, filename, content, binary=False): + """Writes given content to given filename.""" + self._raise_if_none() + fn = path_join(self.path, filename) + + if binary: + flags = 'wb' + else: + flags = 'w' + + with open(fn, flags) as f: + f.write(content) + + def append(self, filename, content, binary=False): + """Appends given content to given filename.""" + + self._raise_if_none() + fn = path_join(self.path, filename) + + if binary: + flags = 'ab' + else: + flags = 'a' + + with open(fn, flags) as f: + f.write(content) + return True + + def delete(self, filename=''): + """Deletes given file or directory. If no filename is passed, current + directory is removed. + """ + self._raise_if_none() + fn = path_join(self.path, filename) + + try: + if isfile(fn): + remove(fn) + else: + removedirs(fn) + except OSError as why: + if why.errno == errno.ENOENT: + pass + else: + raise why + + def read(self, filename, binary=False): + """Returns contents of given file with AppDir. + If file doesn't exist, returns None.""" + + self._raise_if_none() + fn = path_join(self.path, filename) + + if binary: + flags = 'br' + else: + flags = 'r' + + try: + with open(fn, flags) as f: + return f.read() + except IOError: + return None + + + def sub(self, path): + """Returns AppDir instance for given subdirectory name.""" + + if is_collection(path): + path = path_join(path) + + return AppDir(path_join(self.path, path)) + + +# Module locals + +user = AppDir() +site = AppDir() +cache = AppDir() +log = AppDir() + + +def init(vendor, name): + + global user, site, cache, log + + ad = AppDirs(name, vendor) + + user.path = ad.user_data_dir + + site.path = ad.site_data_dir + cache.path = ad.user_cache_dir + log.path = ad.user_log_dir + + +class NotConfigured(IOError): + """Application configuration required. Please run resources.init() first."""