def test_non_recursive_locate(): fs = FileSystem() files = fs.locate(path=abspath(join(dirname(__file__), "files_to_locate")), match="*.txt", recursive=False) assert files assert isinstance(files, list) assert len(files) == 1 assert split(files[0])[-1] == "test.txt"
def __init__(self, parser=None, fs=None): self.parser = parser if not self.parser: self.parser = optparse.OptionParser(usage=self.get_help(), description=__doc__, version=version) self.fs = fs if not self.fs: self.fs = FileSystem()
class SpongeData(object): fs = FileSystem() @classmethod def get_file(cls, name): this_path = cls.fs.dirname(__file__) return cls.fs.join(this_path, name)
class ImageHandler(object): exposed = True should_cache = False cache_path = None fs = FileSystem() def __init__(self, cache_at=None): if not isinstance(cache_at, (basestring, type(None))): raise TypeError, 'The path given to ImageHandler ' \ 'to cache must be a string, got %s' % repr(cache_at) if cache_at: self.should_cache = True self.cache_path = cache_at if not self.fs.exists(cache_at): raise InvalidCachePath, \ 'The given path (%s) does not exist, ' \ 'so that ImageHandler can not save ' \ 'cache files there.' % cache_at def get_cache_path(self, path): return self.fs.join(self.cache_path, path.lstrip('/')) def __call__(self, *args, **kw): if len(args) < 1: cherrypy.response.status = 404 return "not found" path = "/".join(args) image = jpeg(path=path) cache_full_path = None if self.should_cache: cache_full_path = self.get_cache_path(path) if self.fs.exists(cache_full_path): return static.serve_file(cache_full_path, 'image/jpeg') if len(args) >= 3 and args[0] == 'crop': proportion = re.match(r'(?P<width>\d+)x(?P<height>\d+)', args[1]) if proportion: width = int(proportion.group('width')) height = int(proportion.group('height')) image = picture(path="/".join(args[2:]), width=width, height=height) if self.should_cache: dir_path = self.fs.dirname(cache_full_path) self.fs.mkdir(dir_path) img_file = self.fs.open_raw(cache_full_path, 'w') img_file.write(image) img_file.close() return image
def test_load_file(): this_path = split(__file__)[0] relative_path = join(this_path, 'module', 'to', 'load', 'some_file.py') module_path = FileSystem.current_dir(relative_path) ClassToLoad = ClassLoader(module_path).load('ClassInsideFile') assert_equals(ClassToLoad.__name__, 'ClassInsideFile') assert hasattr(ClassToLoad, 'param'), \ '%r should have the attribute "param"' % ClassToLoad assert_equals(ClassToLoad.param, 'ParamFromClass')
def update_authorized_keys(cls): temp_filename = "/tmp/hacklab.%s.keys" % unicode(uuid.uuid4()) temp_file = FileSystem.open(temp_filename, 'w') session = meta.get_session() users = session.query(cls).all() data = [] for user in users: for key in user.keys: row = ENTRY_TEMPLATE.substitute({'repos': user.username, 'key': key.data}) data.append(row) temp_file.write("\n".join(data)) temp_file.close() shutil.copy(temp_filename, os.path.expanduser('~/.ssh/authorized_keys')) os.remove(temp_filename)
class Bob(object): """Sponge Bob is the responsible for managing the user's application and its modules.""" ACTIONS = [ ('create', '<projectname> - creates a new project, which means creating a new folder in current directory, named projectname' ), ('go', 'start the cherrypy server using the configuration file settings.yml in current directory.' ), ('start', '<projectname> executes both bob create and bob go'), ] def __init__(self, parser=None, fs=None): self.parser = parser if not self.parser: self.parser = optparse.OptionParser(usage=self.get_help(), description=__doc__, version=version) self.fs = fs if not self.fs: self.fs = FileSystem() def get_help(self): actions = "\n".join(["%s %s" % (k, v) for k, v in self.ACTIONS]) usage = "\n %s \n\nTo use type %%prog [options]" \ " or %%prog -h (--help) for help with" \ " the available options\n\nACTIONS:\n\n%s" % (self.__doc__, actions) return usage def exit(self, code=1): raise SystemExit(code) def run(self): accepted = [a[0] for a in self.ACTIONS] options, args = self.parser.parse_args() error_msg = '\nBob got a error when %s.\n %s\n' if not args: msg = '\nmissing argument, choose one in %s\n' sys.stderr.write(msg % ", ".join(accepted)) self.exit() if args[0] not in accepted: msg = '\n%s is an invalid argument, choose one in %s\n' sys.stderr.write(msg % (args[0], ", ".join(accepted))) self.exit() return getattr(self, args[0])(*args[1:]) def configure(self): current_full_path = self.fs.current_dir() full_path = self.fs.current_dir("settings.yml") raw_yaml = self.fs.open(full_path, 'r').read() orig_dict = yaml.load(raw_yaml) validator = ConfigValidator(orig_dict) config = SpongeConfig(cherrypy.config, validator) config.setup_all(current_full_path) def go(self): self.configure() cherrypy.quickstart() def create(self, project_name=None): if not project_name: error_msg = 'missing project name, try ' \ 'something like "bob create foobar"' sys.stderr.write("\n%s\n" % error_msg) self.exit() path = self.fs.current_dir(project_name) if self.fs.exists(path): error_msg = 'The path "%s" already exists. ' \ 'Maybe you could choose another ' \ 'name for your project ?' % path sys.stderr.write("\n%s\n" % error_msg) self.exit() self.fs.mkdir(path) cfg = self.fs.open(self.fs.join(path, 'settings.yml'), 'w') cdict = basic_config.copy() media_path = self.fs.join('media') cdict['application']['static']['/media'] = media_path controller_path = self.fs.join('app', 'controllers.py') cdict['application']['path'] = controller_path image_path = self.fs.join('media', 'img') cdict['application']['image-dir'] = image_path template_path = self.fs.join('templates') cdict['application']['template-dir'] = template_path yml_data = self.fix_yml(yaml.dump(cdict, indent=True)) cfg.write(yml_data) cfg.close() zip_file = SpongeData.get_file('project.zip') self.fs.extract_zip(zip_file, path) def fix_yml(self, yml): yml = re.sub('[ ]+{', '{', yml) pattern1 = r'(?P<spc>[ ]+)(?P<pre>[^{]+)[{](?P<cnt>[^}]+)[}]' replacement1 = r'\g<spc>\g<pre>\n \g<spc>\g<cnt>' yml = re.sub(pattern1, replacement1, yml) pattern2 = r'(?P<spc>[ ]+)(?P<pre>[^,]+)[,][ ]*' replacement2 = r'\g<spc>\g<pre>\n \g<spc>' yml = re.sub(pattern2, replacement2, yml) return yml def start(self, project_name=None): self.create(project_name) self.fs.pushd(project_name) self.go() def get_file_path(self): return __file__
class Bob(object): """Sponge Bob is the responsible for managing the user's application and its modules.""" ACTIONS = [ ('create', '<projectname> - creates a new project, which means creating a new folder in current directory, named projectname'), ('go', 'start the cherrypy server using the configuration file settings.yml in current directory.'), ('start', '<projectname> executes both bob create and bob go'), ] def __init__(self, parser=None, fs=None): self.parser = parser if not self.parser: self.parser = optparse.OptionParser(usage=self.get_help(), description=__doc__, version=version) self.fs = fs if not self.fs: self.fs = FileSystem() def get_help(self): actions = "\n".join(["%s %s" % (k, v) for k, v in self.ACTIONS]) usage = "\n %s \n\nTo use type %%prog [options]" \ " or %%prog -h (--help) for help with" \ " the available options\n\nACTIONS:\n\n%s" % (self.__doc__, actions) return usage def exit(self, code=1): raise SystemExit(code) def run(self): accepted = [a[0] for a in self.ACTIONS] options, args = self.parser.parse_args() error_msg = '\nBob got a error when %s.\n %s\n' if not args: msg = '\nmissing argument, choose one in %s\n' sys.stderr.write(msg % ", ".join(accepted)) self.exit() if args[0] not in accepted: msg = '\n%s is an invalid argument, choose one in %s\n' sys.stderr.write(msg % (args[0], ", ".join(accepted))) self.exit() return getattr(self, args[0])(*args[1:]) def configure(self): current_full_path = self.fs.current_dir() full_path = self.fs.current_dir("settings.yml") raw_yaml = self.fs.open(full_path, 'r').read() orig_dict = yaml.load(raw_yaml) validator = ConfigValidator(orig_dict) config = SpongeConfig(cherrypy.config, validator) config.setup_all(current_full_path) def go(self): self.configure() cherrypy.quickstart() def create(self, project_name=None): if not project_name: error_msg = 'missing project name, try ' \ 'something like "bob create foobar"' sys.stderr.write("\n%s\n" % error_msg) self.exit() path = self.fs.current_dir(project_name) if self.fs.exists(path): error_msg = 'The path "%s" already exists. ' \ 'Maybe you could choose another ' \ 'name for your project ?' % path sys.stderr.write("\n%s\n" % error_msg) self.exit() self.fs.mkdir(path) cfg = self.fs.open(self.fs.join(path, 'settings.yml'), 'w') cdict = basic_config.copy() media_path = self.fs.join('media') cdict['application']['static']['/media'] = media_path controller_path = self.fs.join('app', 'controllers.py') cdict['application']['path'] = controller_path image_path = self.fs.join('media', 'img') cdict['application']['image-dir'] = image_path template_path = self.fs.join('templates') cdict['application']['template-dir'] = template_path yml_data = self.fix_yml(yaml.dump(cdict, indent=True)) cfg.write(yml_data) cfg.close() zip_file = SpongeData.get_file('project.zip') self.fs.extract_zip(zip_file, path) def fix_yml(self, yml): yml = re.sub('[ ]+{', '{', yml) pattern1 = r'(?P<spc>[ ]+)(?P<pre>[^{]+)[{](?P<cnt>[^}]+)[}]' replacement1 = r'\g<spc>\g<pre>\n \g<spc>\g<cnt>' yml = re.sub(pattern1, replacement1, yml) pattern2 = r'(?P<spc>[ ]+)(?P<pre>[^,]+)[,][ ]*' replacement2 = r'\g<spc>\g<pre>\n \g<spc>' yml = re.sub(pattern2, replacement2, yml) return yml def start(self, project_name=None): self.create(project_name) self.fs.pushd(project_name) self.go() def get_file_path(self): return __file__
class SpongeConfig(object): fs = FileSystem() def __init__(self, config_dict, validator): if not isinstance(config_dict, dict): raise TypeError, 'SpongeConfig parameter 1 must be a dict, ' \ 'got %s.' % repr(config_dict) if not isinstance(validator, ConfigValidator): raise TypeError, 'SpongeConfig parameter 2 must be a ' \ 'ConfigValidator, got %s.' % repr(validator) self.d = config_dict self.validator = validator def set_setting(self, key, value): self.d[key] = value def setup_all(self, current_full_path): sys.path.append(os.getcwd()) if not isinstance(current_full_path, basestring): raise TypeError, 'SpongeConfig.setup_all takes a string, ' \ 'got %s.' % repr(current_full_path) if not os.path.isabs(current_full_path): raise TypeError, 'SpongeConfig.setup_all takes a absolute ' \ 'path, got %s.' % current_full_path cdict = self.validator.cdict sponge_root = self.fs.abspath(current_full_path) self.set_setting('server.socket_port', int(cdict['port'])) self.set_setting('server.socket_host', cdict['host']) self.set_setting('tools.sessions.on', True) self.set_setting('tools.sessions.timeout', 60) self.set_setting('tools.encode.on', True) self.set_setting('tools.encode.encoding', 'utf-8') self.set_setting('tools.trailing_slash.on', True) self.set_setting('sponge', cdict) self.set_setting('sponge.root', sponge_root) self.set_setting('engine.autoreload_on', cdict['autoreload']) if 'extra' in cdict: self.set_setting('sponge.extra', cdict['extra']) application = self.validator.cdict['application'] if 'boot' in application and \ isinstance(application['boot'], dict): path = application['boot']['path'] call = application['boot']['callable'] cloader = ClassLoader(path) function = getattr(cloader.get_module(), call) apply(function) template_dir = application['template-dir'] template_path = self.fs.join(current_full_path, template_dir) self.set_setting('template.dir', template_path) image_dir = application['image-dir'] image_path = self.fs.join(current_full_path, image_dir) self.set_setting('image.dir', image_path) adir = application['path'] application_path = self.fs.join(current_full_path, adir) cloader = ClassLoader(application_path) meta_conf = {} static = application.get('static') or {} for media_url, media_dir in static.items(): media_path = self.fs.join(current_full_path, media_dir) meta_conf[media_url] = { 'tools.staticdir.on': True, 'tools.staticdir.dir': media_path } classes = application.get('classes') or {} conf = meta_conf.copy() routed = False for classname, mountpoint in classes.items(): try: cls = cloader.load(classname) except Exception, e: format_str = classname, application_path, unicode(e) sys.stderr.write('\nSponge could not find the class %s ' \ 'at %s, verify if your settings.yml ' \ 'is configured as well\n%s\n' % \ (format_str)) raise SystemExit(1) fallback = lambda: cherrypy.tree.mount( root=cls(), config=conf, script_name=mountpoint) msg = '\nWARNING: The class %s has no routes\n' % cls.__name__ if not hasattr(cls, '__routes__'): sys.stderr.write(msg) fallback() continue if not isinstance(cls.__routes__, list): fallback() continue routed = True dispatcher = cherrypy.dispatch.RoutesDispatcher() for k, v in cls.__routes__: if k is None: k = "%s.%s" % (cls.__name__, v['method']) part1 = mountpoint.rstrip('/') part2 = v['route'].lstrip('/') new_route = "/".join([part1, part2]) dispatcher.connect(name=k, route=new_route, controller=cls(), action=v['method']) conf[mountpoint] = {'request.dispatch': dispatcher} if routed: cherrypy.tree.mount(root=None, config=conf)
def test_open_raw_abspath(): fs = FileSystem() assert fs.open_raw(abspath('./tests/functional/data/some.txt'), 'r').read() == 'some text here!\n'
def test_abspath(): fs = FileSystem() p = fs.abspath(".") p2 = abspath(".") assert p == p2
def test_open_non_abspath(): fs = FileSystem() assert fs.open('tests/functional/data/some.txt', 'r').read() == 'some text here!\n'
def test_current_dir_with_join(): fs = FileSystem() got = fs.current_dir("etc") expected = join(abspath("."), "etc") assert_equals(got, expected)
def test_dirname(): fs = FileSystem() p = fs.dirname(fs.abspath(".")) p2 = dirname(abspath(".")) assert p == p2, "Expected:\n%r\nGot:\n%r" % (p2, p)
def test_join(): fs = FileSystem() p = fs.join(fs.abspath("."), "test") p2 = join(abspath("."), "test") assert p == p2, "Expected:\n%r\nGot:\n%r" % (p2, p)
def test_current_dir_without_join(): fs = FileSystem() got = fs.current_dir() expected = abspath(".") assert_equals(got, expected)