def test_example(): cfg = ordered_config_parser.OrderedRawConfigParser() cfg.readfp(StringIO("""\ [foo] # i am here to trigger bugs [input *.rst] action = rst s5-theme-url = /s5-themes/default [input *.jpg] action = copy #TODO # # this should not match foo/baz.jpg # [file /*.jpg] # action = frob # overrides! #TODO # [file /foo/index.rst] [input foo/index.rst] s5-theme-url = /s5-themes/foo """)) got = get_config.get_config(cfg, 'input', 'bar.rst') eq(got, {'action': 'rst', 's5-theme-url': '/s5-themes/default'}) got = get_config.get_config(cfg, 'input', 'foo/bar.rst') eq(got, {'action': 'rst', 's5-theme-url': '/s5-themes/default'}) got = get_config.get_config(cfg, 'input', 'foo/index.rst') eq(got, {'action': 'rst', 's5-theme-url': '/s5-themes/foo'}) got = get_config.get_config(cfg, 'input', 'foo/baz.jpg') eq(got, {'action': 'copy'}) #TODO # got = get_config.get_config(cfg, 'toplevel.jpg') # eq(got, {'action': 'frob'}) got = get_config.get_config(cfg, 'input', 'does-not-match.quux') eq(got, None)
def export(self, destination): def safe_names(names): return ( name for name in names if not (name.startswith('.') or name.startswith('_') or name.startswith('#') ) and not name.endswith('~') ) def list_input_files(path): for dirpath, dirnames, filenames in os.walk(self.path): dirnames[:] = safe_names(dirnames) if dirpath == self.root: relative_dir = '' else: assert dirpath.startswith(self.root + '/') relative_dir = dirpath[len(self.root)+1:] for filename in safe_names(filenames): yield os.path.join(relative_dir, filename) # Unordered queue of "dirty" output files, that we need to # check whether someone wants to process. There is no loop # detection -- it is highly suggested you do not create one ;) # TODO confuses input and output files! queue = set( ('input', path) for path in list_input_files(self.path) ) # TODO maybe actions can raise RequireFiles('pathname', ...), # to make them be retried later when the (output) files are # available? while queue: (type_, current) = queue.pop() log.info('Process %s: %s', type_, current) cfg = get_config.get_config( cfg=self.config, type_=type_, path=current, ) if cfg is None: log.debug('Nothing configured.') continue actions = cfg.get('action') if actions is None: log.debug('No actions.') continue # special case index.html; link points to dir itself base, ext = os.path.splitext(current) if base.endswith('/index'): base = base[:-len('/index')] navigation = navi_current.navi_mark_current( navigation=self.navigation, current='/'+base, ) for action in actions.split('\n'): l = action.split(None, 1) if not l: # pure whitespace continue action = l.pop(0) if l: (args,) = l else: args = None g = pkg_resources.iter_entry_points( 'roast.action', action, ) try: entrypoint = g.next() except StopIteration: raise RuntimeError('Unknown action: %r' % action) log.debug('Action %r(%r) at %r', action, args, entrypoint) if type_ == 'input': input_ = file( os.path.join(self.root, current), 'rb', ) elif type_ == 'output': input_ = file( os.path.join(destination, current), 'rb', ) else: raise RuntimeError() op = Operation( input=input_, path=current, src_root=self.root, dst_root=destination, config=self.config, navigation=navigation, ) fn = entrypoint.load() kwargs = dict( op=op, ) if args is not None: kwargs['args'] = args fn(**kwargs) for path in op.output_files: if path == op.path: # don't re-add itself to queue, that would lead to # an infinite loop with most actions continue queue.add(('output', path)) op.close()