def test_index_query_in_recipe(): config['indexer'] = 'test.indexernot' bag = Bag('noop') store.put(bag) tiddler = Tiddler('dwell', 'noop') store.put(tiddler) recipe = Recipe('coolio') recipe.set_recipe([('noop', ''), ('fwoop', '')]) recipe.store = store tiddler = Tiddler('swell') py.test.raises(ImportError, 'determine_bag_from_recipe(recipe, tiddler, environ)') config['indexer'] = 'test.indexer' bag = determine_bag_from_recipe(recipe, tiddler, environ) assert bag.name == 'fwoop' tiddler = Tiddler('dwell') bag = determine_bag_from_recipe(recipe, tiddler, environ) assert bag.name == 'noop' tiddler = Tiddler('carnaby') # nowhere py.test.raises(NoBagError, 'determine_bag_from_recipe(recipe, tiddler, environ)')
def test_index_query_in_recipe(): config['indexer'] = 'test.indexernot' bag = Bag('noop') store.put(bag) tiddler = Tiddler('dwell', 'noop') store.put(tiddler) recipe = Recipe('coolio') recipe.set_recipe([('noop', u''), ('fwoop', u'')]) recipe.store = store tiddler = Tiddler('swell') py.test.raises(ImportError, 'determine_bag_from_recipe(recipe, tiddler, environ)') config['indexer'] = 'test.indexer' bag = determine_bag_from_recipe(recipe, tiddler, environ) assert bag.name == 'fwoop' tiddler = Tiddler('dwell') bag = determine_bag_from_recipe(recipe, tiddler, environ) assert bag.name == 'noop' tiddler = Tiddler('carnaby') # nowhere py.test.raises(NoBagError, 'determine_bag_from_recipe(recipe, tiddler, environ)')
def _determine_tiddler(environ): """ Inspect the environment to determine which tiddler from which bag will provide content for the page named in the URL. If the page exists, and we have permission to read the bag in which it is stored, the return the tiddler. If we do not have permission, a login interface will be shown. If the tiddler does not exist, an empty tiddler with stub text will be returned. """ user = environ['tiddlyweb.usersign'] config = environ['tiddlyweb.config'] store = environ['tiddlyweb.store'] recipe = Recipe(_get_recipe(config)) recipe = store.get(recipe) recipe.policy.allows(user, 'read') tiddler_name = environ['wsgiorg.routing_args'][1]['tiddler_name'] tiddler_name = urllib.unquote(tiddler_name) tiddler_name = unicode(tiddler_name, 'utf-8') tiddler = Tiddler(tiddler_name) try: bag = control.determine_bag_from_recipe(recipe, tiddler, environ) bag.policy.allows(user, 'read') tiddler.bag = bag.name tiddler = store.get(tiddler) except NoBagError, exc: # Apparently the tiddler doesn't exist, let's fill in an empty one # then. tiddler.text = 'That Page does not yet exist.' tiddler.type = 'text/x-markdown'
def get(environ, start_response): """ Using query parameters, determine the current tiddler and produce an editor for it. """ usersign = environ["tiddlyweb.usersign"] try: tiddler_name = environ["tiddlyweb.query"].get("tiddler", [""])[0] recipe_name = environ["tiddlyweb.query"].get("recipe", [""])[0] bag_name = environ["tiddlyweb.query"].get("bag", [""])[0] except (KeyError, IndexError): raise HTTP400("tiddler, recipe and bag query strings required") store = environ["tiddlyweb.store"] tiddler = Tiddler(tiddler_name) if bag_name: tiddler.bag = bag_name else: recipe = Recipe(recipe_name) try: recipe = store.get(recipe) tiddler.bag = determine_bag_from_recipe(recipe, tiddler).name tiddler.recipe = recipe.name except NoRecipeError, exc: raise HTTP404("unable to edit %s, recipe %s not found: %s" % (tiddler.title, recipe_name, exc)) except NoBagError, exc: raise HTTP404("unable to edit %s: %s" % (tiddler.title, exc))
def _get_status_tiddler(self, environ, status): """ Load up the tiddler associated with the current status. If the tiddler is not present in the recipe, load up the tiddler with title 'default'. If that tiddler is not present, use DEFAULT_TEXT. """ try: tiddler = Tiddler(status) store = environ['tiddlyweb.store'] recipe_name = environ['tiddlyweb.config'].get('prettyerror.recipe', '_errors') recipe = Recipe(recipe_name) recipe = store.get(recipe) bag = determine_bag_from_recipe(recipe, tiddler, environ) tiddler.bag = bag.name tiddler = store.get(tiddler) except (NoRecipeError, NoBagError): if status == 'default': tiddler.text = DEFAULT_TEXT else: tiddler = self._get_status_tiddler(environ, 'default') except (NoTiddlerError): # If there is no default tiddler we get recursion error. tiddler = self._get_status_tiddler(environ, 'default') except: # Deal with failures early in the stack tiddler.text = DEFAULT_TEXT return tiddler
def get_bag_from_recipe(environ, recipe_name, tiddler): """ Check recipe policy, determine which bag this tiddler ought to come from, and check that bag's policy too. Raises StoreError and PermissionsError. """ store = environ['tiddlyweb.store'] recipe = store.get(Recipe(recipe_name)) recipe.policy.allows(environ['tiddlyweb.usersign'], 'read') bag = determine_bag_from_recipe(recipe, tiddler, environ) bag = store.get(Bag(bag.name)) bag.policy.allows(environ['tiddlyweb.usersign'], 'read') return bag
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ if template_data == None: template_data = {} template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = { 'HtmlCss': ['/bags/common/tiddlers/profile.css'], 'HtmlJavascript': [] } # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe( recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: urls = tiddler.text.strip().rstrip().split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
def recipe_tiddler_uri_keys(environ): """ We have a tiddler in a recipe URI, provide the tiddler and the bag tiddler key for all the bags in the recipe. """ store = environ['tiddlyweb.store'] recipe_name = get_route_value(environ, 'recipe_name') tiddler_title = get_route_value(environ, 'tiddler_name') recipe = store.get(Recipe(recipe_name)) tiddler = Tiddler(tiddler_title) bag = determine_bag_from_recipe(recipe, tiddler, environ) tiddler.bag = bag.name return [recipe_key(recipe_name), tiddler_key(tiddler)] + [ bag_key(bag) for bag, _ in recipe.get_recipe()]
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ if template_data == None: template_data = {} template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = { 'HtmlCss': ['/bags/common/tiddlers/profile.css'], 'HtmlJavascript': []} # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe(recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: urls = tiddler.text.strip().rstrip().split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
def comp(environ, start_response): usersign = environ['tiddlyweb.usersign'] store = environ['tiddlyweb.store'] recipe_name = get_route_value(environ, 'recipe_name') tiddler = Tiddler('app') recipe = Recipe(recipe_name) try: recipe = store.get(recipe) recipe.policy.allows(usersign, 'read') except NoRecipeError as exc: raise HTTP404('unable to find recipe %s' % recipe_name) try: bag = determine_bag_from_recipe(recipe, tiddler, environ) except NoBagError as exc: raise HTTP404('%s not found via bag, %s' % (tiddler.title, exc)) tiddler.bag = bag.name return _send_tiddler(environ, start_response, tiddler)
def _process_for_transclusion(output, tiddler, environ): """ Process the output for transclusions. """ if 'twikified.seen_titles' in environ: seen_titles = environ['twikified.seen_titles'] else: seen_titles = [] parser = html5lib.HTMLParser( tree=html5lib.treebuilders.getTreeBuilder("dom")) output = output.decode('utf-8', 'replace') try: dom = parser.parse('<div>' + output + '</div>') spans = dom.getElementsByTagName('span') for span in spans: for attribute in span.attributes.keys(): if attribute == 'tiddler': attr = span.attributes[attribute] interior_title = attr.value try: span_class = span.attributes['class'].value if span_class.startswith('@'): interior_recipe = span_class[1:] + '_public' else: interior_recipe = '' except KeyError: interior_recipe = '' title_semaphore = '%s:%s' % (interior_title, interior_recipe) if title_semaphore not in seen_titles: seen_titles.append(title_semaphore) interior_tiddler = Tiddler(interior_title) try: store = environ['tiddlyweb.store'] if interior_recipe: recipe = store.get(Recipe(interior_recipe)) interior_tiddler.recipe = interior_recipe interior_tiddler.bag = ( determine_bag_from_recipe( recipe, interior_tiddler, environ).name) else: if tiddler.recipe: interior_tiddler.recipe = tiddler.recipe recipe = store.get(Recipe(tiddler.recipe)) interior_tiddler.bag = ( determine_bag_from_recipe( recipe, interior_tiddler, environ).name) else: interior_tiddler.bag = tiddler.bag interior_bag = store.get(Bag(interior_tiddler.bag)) interior_bag.policy.allows( environ['tiddlyweb.usersign'], 'read') interior_tiddler = store.get(interior_tiddler) except (StoreError, PermissionsError): continue if renderable(interior_tiddler, environ): environ['twikified.seen_titles'] = seen_titles interior_content = render_wikitext( interior_tiddler, environ) interior_dom = parser.parse('<div>' + interior_content + '</div>') span.appendChild( interior_dom.getElementsByTagName( 'div')[0]) output = dom.getElementsByTagName('div')[0].toxml() except ExpatError, exc: # If expat couldn't process the output, we need to make it # unicode as what came over the socket was utf-8 but expat # needs that in the first place. LOGGER.warn('got expat error: %s:%s %s', tiddler.bag, tiddler.title, exc) output = output.decode('utf-8', 'replace')
title_semaphore = '%s:%s' % (interior_title, interior_bag) if title_semaphore not in seen_titles: seen_titles.append(title_semaphore) interior_tiddler = Tiddler(interior_title) try: store = environ['tiddlyweb.store'] if interior_bag: public_bag = store.get(Bag(interior_bag)) public_bag.policy.allows( environ['tiddlyweb.usersign'], 'read') interior_tiddler.bag = interior_bag else: if tiddler.recipe: interior_tiddler.recipe = tiddler.recipe recipe = store.get(Recipe(tiddler.recipe)) interior_tiddler.bag = determine_bag_from_recipe( recipe, interior_tiddler, environ).name else: interior_tiddler.bag = tiddler.bag interior_tiddler = store.get(interior_tiddler) except (StoreError, PermissionsError): continue if renderable(interior_tiddler, environ): interior_content = render(interior_tiddler, environ, seen_titles) interior_dom = parser.parse('<div>' + interior_content + '</div>') span.appendChild(interior_dom.getElementsByTagName('div')[0]) output = dom.getElementsByTagName('div')[0].toxml() except ExpatError, exc:
for link in links: if is_link(link): # external link continue else: container, title = link.split(':', 1) if not title: # plain space link continue elif title: if container != bag_name: if container.endswith('_public'): try: recipe = Recipe(container) recipe = store.get(recipe) tiddler = Tiddler(title) tiddler.recipe = container bag = determine_bag_from_recipe(recipe, tiddler, environ) tiddler.bag = bag.name except StoreError, exc: tiddler = Tiddler(title, bag_name) tiddler.recipe = container else: tiddler = Tiddler(title, container) else: tiddler = Tiddler(title, bag_name) try: tiddler = store.get(tiddler) except StoreError: tiddler.store = store if _is_readable(environ, tiddler): tiddlers.add(tiddler)
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ default_css_tiddler = '/bags/common/tiddlers/profile.css' if template_data is None: template_data = {} html_template_prefix = environ['tiddlyweb.space_settings']['htmltemplate'] if html_template_prefix: default_css_tiddler = ('/bags/common/tiddlers/%s.css' % html_template_prefix) html_template_prefix += '/' try: name = html_template_prefix + template_name template = get_template(environ, name) except TemplateNotFound: template = get_template(environ, template_name) else: template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = {'HtmlCss': [], 'HtmlJavascript': []} if not html_template_prefix or template_name in CUSTOMIZABLES: linked_resources['HtmlCss'] = [default_css_tiddler] # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe( recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: url_content = tiddler.text.strip() if url_content: urls = url_content.split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
def _process_for_transclusion(output, tiddler, environ): """ Process the output for transclusions. """ if 'twikified.seen_titles' in environ: seen_titles = environ['twikified.seen_titles'] else: seen_titles = [] parser = html5lib.HTMLParser( tree=html5lib.treebuilders.getTreeBuilder("dom")) output = output.decode('utf-8', 'replace') try: dom = parser.parse('<div>' + output + '</div>') spans = dom.getElementsByTagName('span') for span in spans: for attribute in span.attributes.keys(): if attribute == 'tiddler': attr = span.attributes[attribute] interior_title = attr.value try: span_class = span.attributes['class'].value if span_class.startswith('@'): interior_recipe = span_class[1:] + '_public' else: interior_recipe = '' except KeyError: interior_recipe = '' title_semaphore = '%s:%s' % (interior_title, interior_recipe) if title_semaphore not in seen_titles: seen_titles.append(title_semaphore) interior_tiddler = Tiddler(interior_title) try: store = environ['tiddlyweb.store'] if interior_recipe: recipe = store.get(Recipe(interior_recipe)) interior_tiddler.recipe = interior_recipe interior_tiddler.bag = ( determine_bag_from_recipe( recipe, interior_tiddler, environ).name) else: if tiddler.recipe: interior_tiddler.recipe = tiddler.recipe recipe = store.get(Recipe(tiddler.recipe)) interior_tiddler.bag = ( determine_bag_from_recipe( recipe, interior_tiddler, environ).name) else: interior_tiddler.bag = tiddler.bag interior_bag = store.get(Bag(interior_tiddler.bag)) interior_bag.policy.allows( environ['tiddlyweb.usersign'], 'read') interior_tiddler = store.get(interior_tiddler) except (StoreError, PermissionsError): continue if renderable(interior_tiddler, environ): environ['twikified.seen_titles'] = seen_titles interior_content = render_wikitext( interior_tiddler, environ) interior_dom = parser.parse('<div>' + interior_content + '</div>') span.appendChild( interior_dom.getElementsByTagName('div')[0]) output = dom.getElementsByTagName('div')[0].toxml() except ExpatError, exc: # If expat couldn't process the output, we need to make it # unicode as what came over the socket was utf-8 but expat # needs that in the first place. LOGGER.warn('got expat error: %s:%s %s', tiddler.bag, tiddler.title, exc) output = output.decode('utf-8', 'replace')
def send_template(environ, template_name, template_data=None): """ Set some defaults for a template and send the output. """ default_css_tiddler = '/bags/common/tiddlers/profile.css' if template_data is None: template_data = {} html_template_prefix = environ['tiddlyweb.space_settings']['htmltemplate'] if html_template_prefix: default_css_tiddler = ('/bags/common/tiddlers/%s.css' % html_template_prefix) html_template_prefix += '/' try: name = html_template_prefix + template_name template = get_template(environ, name) except TemplateNotFound: template = get_template(environ, template_name) else: template = get_template(environ, template_name) store = environ['tiddlyweb.store'] linked_resources = { 'HtmlCss': [], 'HtmlJavascript': []} if not html_template_prefix or template_name in CUSTOMIZABLES: linked_resources['HtmlCss'] = [default_css_tiddler] # Load CSS and JavaScript overrides. current_space = determine_space(environ, determine_host(environ)[0]) if current_space: recipe_name = determine_space_recipe(environ, current_space) try: recipe = store.get(Recipe(recipe_name)) for title in linked_resources: try: tiddler = Tiddler(title) bag = control.determine_bag_from_recipe(recipe, tiddler, environ) tiddler.bag = bag.name try: tiddler = store.get(tiddler) if 'Javascript' in title: url_content = tiddler.text.strip() if url_content: urls = url_content.split('\n') linked_resources[title] = urls else: url = '/bags/%s/tiddlers/%s' % (encode_name( tiddler.bag), title) linked_resources[title] = [url] except StoreError: continue except StoreError: pass except StoreError: pass template_defaults = { 'original_server_host': original_server_host_url(environ), 'css': linked_resources['HtmlCss'], 'js': linked_resources['HtmlJavascript'], 'server_host': server_base_url(environ), } template_defaults.update(template_data) return template.generate(template_defaults)
title_semaphore = '%s:%s' % (interior_title, interior_bag) if title_semaphore not in seen_titles: seen_titles.append(title_semaphore) interior_tiddler = Tiddler(interior_title) try: store = environ['tiddlyweb.store'] if interior_bag: public_bag = store.get(Bag(interior_bag)) public_bag.policy.allows( environ['tiddlyweb.usersign'], 'read') interior_tiddler.bag = interior_bag else: if tiddler.recipe: interior_tiddler.recipe = tiddler.recipe recipe = store.get(Recipe(tiddler.recipe)) interior_tiddler.bag = determine_bag_from_recipe( recipe, interior_tiddler, environ).name else: interior_tiddler.bag = tiddler.bag interior_tiddler = store.get(interior_tiddler) except (StoreError, PermissionsError): continue if renderable(interior_tiddler, environ): interior_content = render(interior_tiddler, environ, seen_titles) interior_dom = parser.parse('<div>' + interior_content + '</div>') span.appendChild( interior_dom.getElementsByTagName('div')[0]) output = dom.getElementsByTagName('div')[0].toxml()