def load(cls, name, parent_dir=None): """ Loads a Python site template from a Python source file. Ensures that the loaded module has a `render()` function. The template will be searched for in the statigen templates directory or relative to the *parent_dir*. """ parent_dir = parent_dir or os.getcwd() templates_dir = path.join(path.dir(__file__), 'templates') def find_template(): for dirname in [parent_dir, templates_dir]: for choice in [name, name + '.py', path.join(name, 'site-template.py')]: filename = path.join(dirname, choice) if path.isfile(filename): return filename filename = find_template() if not filename: # TODO: Proper exception type raise ValueError('Template not found: {!r}'.format(name)) with open(filename) as fp: code = fp.read() module = types.ModuleType(path.base(name)) module.__file__ = filename six.exec_(compile(code, filename, 'exec'), vars(module)) if not callable(getattr(module, 'render', None)): # TODO: Proper exception type raise ValueError('Template {!r} has no render() function or render is not callable'.format(name)) return cls(module)
def main(argv=None, prog=None): parser = get_argument_parser(prog) args = parser.parse_args(argv) if not args.config and path.isfile('.statigen.toml'): args.config = '.statigen.toml' if args.config: with open(args.config) as fp: config = toml.load(fp) else: config = {} config = Config(config) if args.build_directory: config['statigen.buildDirectory'] = args.build_directory if args.template: config['statigen.template'] = args.template site_template = PythonSiteTemplate.load(config.get('statigen.template', 'default/docs')) context = Context( config = config, site_template = site_template, content_loader = import_class(config.get('contentLoader', __name__ + '.MarkdownTomlContentLoader'))(), content_renderer = import_class(config.get('contentRenderer', __name__ + '.MarkdownJinjaContentRenderer'))(), template_renderer = import_class(config.get('templateRenderer', __name__ + '.JinjaTemplateRenderer'))() ) site_template.render(context) if args.open: import webbrowser webbrowser.open(path.join(config['statigen.buildDirectory'], 'index.html')) if args.watch: import time, threading import watchdog.events, watchdog.observers build_dir = path.abs(config['statigen.buildDirectory']) changed = threading.Event() class Handler(watchdog.events.FileSystemEventHandler): def on_any_event(self, event): rel = path.rel(path.abs(event.src_path), build_dir) if not path.issub(rel): # Not an event in the build directory changed.set() observer = watchdog.observers.Observer() observer.schedule(Handler(), path=config['statigen.contentDirectory'], recursive=True) observer.schedule(Handler(), path=context.site_template.get_main_directory(context), recursive=True) observer.schedule(Handler(), path=context.project_directory, recursive=True) observer.start() try: while True: if changed.is_set(): print() print('File changed, rebuilding ...') print() site_template.render(context) changed.clear() time.sleep(0.1) finally: observer.stop() observer.join()
def load_content_from_directory(self, directory): if not path.isabs(directory): content_directory = self.config['statigen.contentDirectory'] directory = path.join(content_directory, directory) result = [] for content in self.content_loader.load_content_from_directory(self, directory): self.site_template.content_loaded(self, content) result.append(content) return result
def render_template(self, context, template, vars): paths = [] paths.append(path.join(context.project_directory, 'templates')) paths.append(context.get_template_directory()) loader = jinja2.FileSystemLoader(paths) env = jinja2.Environment(loader=loader) template = env.get_template(template) context.template_vars = vars return template.render(vars)
def copy(self, url, source): """ Copy the file or directory *source* from the site templates main directory so that it is available from the specified URL. """ if path.isabs(source): choices = [source] else: parent_dirs = [self.site_template.get_main_directory(self)] parent_dirs += [self.project_directory] choices = [path.join(x, source) for x in parent_dirs] target = self.url_to_abs_filename(url, False) print('copying {} ==> {} ({})'.format(source, target, url)) for current in choices: if path.exists(current): print(' from {}'.format(current)) copy_tree(current, target)
def find_template(): for dirname in [parent_dir, templates_dir]: for choice in [name, name + '.py', path.join(name, 'site-template.py')]: filename = path.join(dirname, choice) if path.isfile(filename): return filename
def get_template_directory(self, context): directory = getattr(self.module, 'template_directory', None) if directory is None: directory = path.join(path.dir(self.module.__file__), 'templates') return directory
def load_content_from_directory(self, context, directory): for filename in os.listdir(directory): if filename.endswith('.md'): name = filename[:-3] filename = path.join(directory, filename) yield self._load_file(context, filename, name)