def run(self): from zim.export.selections import AllPages, SinglePage, SubPages from zim.plugins import PluginManager from zim.config import ConfigManager notebook, page = self.build_notebook() # load plugins, needed so the the proper export functions would work from CLI config = ConfigManager(profile=notebook.profile) plugins = PluginManager(config) plugins.extend(notebook.index) plugins.extend(notebook) if page and self.opts.get('recursive'): selection = SubPages(notebook, page) elif page: selection = SinglePage(notebook, page) else: selection = AllPages(notebook) exporter = self.get_exporter(page) exporter.export(selection)
def _run_new_window(self, notebook, page): from gi.repository import GObject from zim.gui.mainwindow import MainWindow from zim.config import ConfigManager from zim.plugins import PluginManager config = ConfigManager() preferences = config.preferences['General'] preferences.setdefault('plugins', [ 'pageindex', 'pathbar', 'journal', 'insertsymbol', 'printtobrowser', 'versioncontrol', ]) # Upgrade plugin list preferences.setdefault('plugins_list_version', 'none') if preferences['plugins_list_version'] != '0.68': preferences['plugins'].extend(['pageindex', 'pathbar']) if 'calendar' in preferences['plugins']: preferences['plugins'].remove('calendar') preferences['plugins'].append('journal') config.preferences['JournalPlugin'] = config.preferences[ 'CalendarPlugin'] preferences['plugins_list_version'] = '0.68' pluginmanager = PluginManager(config) pluginmanager.extend(notebook) window = MainWindow(notebook, config, page=page, **self.get_options('geometry', 'fullscreen')) pluginmanager.extend(window) pluginmanager.extend(window.pageview) window.__pluginmanager__ = pluginmanager # HACK to allow dialogs to find it window.present() if not window.notebook.index.is_uptodate: window._uiactions.reload_index(update_only=True) # XXX else: # Start a lightweight background check of the index # put a small delay to ensure window is shown before we start def start_background_check(): notebook.index.start_background_check(notebook) return False # only run once GObject.timeout_add(500, start_background_check) return window
class WWWInterface(object): '''Class to handle the WWW interface for zim notebooks. Objects of this class are callable, so they can be used as application objects within a WSGI compatible framework. See PEP 333 for details (U{http://www.python.org/dev/peps/pep-0333/}). For basic handlers to run this interface see the "wsgiref" package in the standard library for python. ''' def __init__(self, notebook, config=None, template='Default'): '''Constructor @param notebook: a L{Notebook} object @param config: optional C{ConfigManager} object @param template: html template for zim pages ''' assert isinstance(notebook, Notebook) self.notebook = notebook self.config = config or ConfigManager(profile=notebook.profile) self.output = None if template is None: template = 'Default' if isinstance(template, basestring): from zim.templates import get_template self.template = get_template('html', template) if not self.template: raise AssertionError('Could not find html template: %s' % template) else: self.template = template self.linker_factory = partial(WWWLinker, self.notebook, self.template.resources_dir) self.dumper_factory = get_format('html').Dumper # XXX self.plugins = PluginManager(self.config) self.plugins.extend(notebook) self.plugins.extend(self) #~ self.notebook.indexer.check_and_update() def __call__(self, environ, start_response): '''Main function for handling a single request. Follows the WSGI API. @param environ: dictionary with environment variables for the request and some special variables. See the PEP for expected variables. @param start_response: a function that can be called to set the http response and headers. For example:: start_response(200, [('Content-Type', 'text/plain')]) @returns: the html page content as a list of lines ''' headerlist = [] headers = Headers(headerlist) path = environ.get('PATH_INFO', '/') try: methods = ('GET', 'HEAD') if not environ['REQUEST_METHOD'] in methods: raise WWWError('405', headers=[('Allow', ', '.join(methods))]) # cleanup path #~ print 'INPUT', path path = path.replace('\\', '/') # make it windows save isdir = path.endswith('/') parts = [p for p in path.split('/') if p and not p == '.'] if [p for p in parts if p.startswith('.')]: # exclude .. and all hidden files from possible paths raise WebPathNotValidError() path = '/' + '/'.join(parts) if isdir and not path == '/': path += '/' #~ print 'PATH', path if not path: path = '/' elif path == '/favicon.ico': path = '/+resources/favicon.ico' else: path = urllib.unquote(path) if path == '/': headers.add_header('Content-Type', 'text/html', charset='utf-8') content = self.render_index() elif path.startswith('/+docs/'): dir = self.notebook.document_root if not dir: raise WebPageNotFoundError(path) file = dir.file(path[7:]) content = [file.raw()] # Will raise FileNotFound when file does not exist headers['Content-Type'] = file.get_mimetype() elif path.startswith('/+file/'): file = self.notebook.dir.file(path[7:]) # TODO: need abstraction for getting file from top level dir ? content = [file.raw()] # Will raise FileNotFound when file does not exist headers['Content-Type'] = file.get_mimetype() elif path.startswith('/+resources/'): if self.template.resources_dir: file = self.template.resources_dir.file(path[12:]) if not file.exists(): file = data_file('pixmaps/%s' % path[12:]) else: file = data_file('pixmaps/%s' % path[12:]) if file: content = [file.raw()] # Will raise FileNotFound when file does not exist headers['Content-Type'] = file.get_mimetype() else: raise WebPageNotFoundError(path) else: # Must be a page or a namespace (html file or directory path) headers.add_header('Content-Type', 'text/html', charset='utf-8') if path.endswith('.html'): pagename = path[:-5].replace('/', ':') elif path.endswith('/'): pagename = path[:-1].replace('/', ':') else: raise WebPageNotFoundError(path) path = self.notebook.pages.lookup_from_user_input(pagename) try: page = self.notebook.get_page(path) if page.hascontent: content = self.render_page(page) elif page.haschildren: content = self.render_index(page) else: raise WebPageNotFoundError(path) except PageNotFoundError: raise WebPageNotFoundError(path) except Exception as error: headerlist = [] headers = Headers(headerlist) headers.add_header('Content-Type', 'text/plain', charset='utf-8') if isinstance(error, (WWWError, FileNotFoundError)): logger.error(error.msg) if isinstance(error, FileNotFoundError): error = WebPageNotFoundError(path) # show url path instead of file path if error.headers: for key, value in error.headers: headers.add_header(key, value) start_response(error.status, headerlist) content = unicode(error).splitlines(True) # TODO also handle template errors as special here else: # Unexpected error - maybe a bug, do not expose output on bugs # to the outside world logger.exception('Unexpected error:') start_response('500 Internal Server Error', headerlist) content = ['Internal Server Error'] if environ['REQUEST_METHOD'] == 'HEAD': return [] else: return [string.encode('utf-8') for string in content] else: start_response('200 OK', headerlist) if environ['REQUEST_METHOD'] == 'HEAD': return [] elif 'utf-8' in headers['Content-Type']: return [string.encode('utf-8') for string in content] else: return content def render_index(self, namespace=None): '''Render an index page @param namespace: the namespace L{Path} @returns: html as a list of lines ''' path = namespace or Path(':') page = createIndexPage(self.notebook, path, namespace) return self.render_page(page) def render_page(self, page): '''Render a single page from the notebook @param page: a L{Page} object @returns: html as a list of lines ''' lines = [] context = ExportTemplateContext( self.notebook, self.linker_factory, self.dumper_factory, title=page.get_title(), content=[page], home=self.notebook.get_home_page(), up=page.parent if page.parent and not page.parent.isroot else None, prevpage=self.notebook.pages.get_previous(page) if not page.isroot else None, nextpage=self.notebook.pages.get_next(page) if not page.isroot else None, links={'index': '/'}, index_generator=self.notebook.pages.walk, index_page=page, ) self.template.process(lines, context) return lines
class WWWInterface(object): '''Class to handle the WWW interface for zim notebooks. Objects of this class are callable, so they can be used as application objects within a WSGI compatible framework. See PEP 333 for details (U{http://www.python.org/dev/peps/pep-0333/}). For basic handlers to run this interface see the "wsgiref" package in the standard library for python. ''' def __init__(self, notebook, config=None, template='Default'): '''Constructor @param notebook: a L{Notebook} object @param config: optional C{ConfigManager} object @param template: html template for zim pages ''' assert isinstance(notebook, Notebook) self.notebook = notebook self.config = config or ConfigManager(profile=notebook.profile) self.output = None if isinstance(template, basestring): from zim.templates import get_template self.template = get_template('html', template) if not self.template: raise AssertionError, 'Could not find html template: %s' % template else: self.template = template self.linker = WWWLinker(self.notebook) self.template.set_linker(self.linker) self.plugins = PluginManager(self.config) self.plugins.extend(notebook.index) self.plugins.extend(notebook) self.plugins.extend(self) #~ self.notebook.index.update() def __call__(self, environ, start_response): '''Main function for handling a single request. Follows the WSGI API. @param environ: dictionary with environment variables for the request and some special variables. See the PEP for expected variables. @param start_response: a function that can be called to set the http response and headers. For example:: start_response(200, [('Content-Type', 'text/plain')]) @returns: the html page content as a list of lines ''' headerlist = [] headers = Headers(headerlist) path = environ.get('PATH_INFO', '/') try: methods = ('GET', 'HEAD') if not environ['REQUEST_METHOD'] in methods: raise WWWError('405', headers=[('Allow', ', '.join(methods))]) # cleanup path #~ print 'INPUT', path path = path.replace('\\', '/') # make it windows save isdir = path.endswith('/') parts = [p for p in path.split('/') if p and not p == '.'] if [p for p in parts if p.startswith('.')]: # exclude .. and all hidden files from possible paths raise PathNotValidError() path = '/' + '/'.join(parts) if isdir and not path == '/': path += '/' #~ print 'PATH', path if not path: path = '/' elif path == '/favicon.ico': path = '/+resources/favicon.ico' else: path = urllib.unquote(path) if path == '/': headers.add_header('Content-Type', 'text/html', charset='utf-8') content = self.render_index() elif path.startswith('/+docs/'): dir = self.notebook.document_root if not dir: raise PageNotFoundError(path) file = dir.file(path[7:]) content = [file.raw()] # Will raise FileNotFound when file does not exist headers['Content-Type'] = file.get_mimetype() elif path.startswith('/+file/'): file = self.notebook.dir.file(path[7:]) # TODO: need abstraction for getting file from top level dir ? content = [file.raw()] # Will raise FileNotFound when file does not exist headers['Content-Type'] = file.get_mimetype() elif path.startswith('/+resources/'): if self.template.resources_dir: file = self.template.resources_dir.file(path[12:]) if not file.exists(): file = data_file('pixmaps/%s' % path[12:]) else: file = data_file('pixmaps/%s' % path[12:]) if file: content = [file.raw()] # Will raise FileNotFound when file does not exist headers['Content-Type'] = file.get_mimetype() else: raise PageNotFoundError(path) else: # Must be a page or a namespace (html file or directory path) headers.add_header('Content-Type', 'text/html', charset='utf-8') if path.endswith('.html'): pagename = path[:-5].replace('/', ':') elif path.endswith('/'): pagename = path[:-1].replace('/', ':') else: raise PageNotFoundError(path) path = self.notebook.resolve_path(pagename) page = self.notebook.get_page(path) if page.hascontent: content = self.render_page(page) elif page.haschildren: content = self.render_index(page) else: raise PageNotFoundError(page) except Exception, error: headerlist = [] headers = Headers(headerlist) headers.add_header('Content-Type', 'text/plain', charset='utf-8') if isinstance(error, (WWWError, FileNotFoundError)): logger.error(error.msg) if isinstance(error, FileNotFoundError): error = PageNotFoundError(path) # show url path instead of file path if error.headers: for key, value in error.headers: headers.add_header(key, value) start_response(error.status, headerlist) content = unicode(error).splitlines(True) # TODO also handle template errors as special here else: # Unexpected error - maybe a bug, do not expose output on bugs # to the outside world logger.exception('Unexpected error:') start_response('500 Internal Server Error', headerlist) content = ['Internal Server Error'] if environ['REQUEST_METHOD'] == 'HEAD': return [] else: return [string.encode('utf-8') for string in content] else: