def test_tiddler_full_create(): """ Confirm we can populate a tiddler at create time. """ tiddler = Tiddler('test tiddler') tiddler.modifier = '*****@*****.**' tiddler.text = test_tiddler_text tiddler.tags = ['foo', 'bar'] tiddler.bag = u'bagone' assert type(tiddler) == Tiddler, \ 'Tiddler returns a Tiddler' assert tiddler.title == 'test tiddler', \ 'tiddler title should be test tiddler, got %s' \ % tiddler.title assert tiddler.modifier == '*****@*****.**', \ 'tiddler modifier should [email protected], got %s' \ % tiddler.modifier assert tiddler.text == test_tiddler_text, \ 'tiddler content is correct' assert tiddler.tags == ['foo', 'bar'], \ 'tiddler tags are correct' assert tiddler.bag == 'bagone', \ 'tiddler has a bag of bagone' assert tiddler.revision is None, \ 'tiddler revision is None' assert tiddler.creator == '*****@*****.**'
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 test_refresh_urls(): """ register a url after the server has been started, and then refresh them """ store = setup_store() urls_init(config) setup_web() http = httplib2.Http() tiddler = Tiddler('bar', 'foo') tiddler.text = 'foo bar' store.put(tiddler) #check that no url exists yet response = http.request('http://test_domain:8001/foo')[0] assert response.status == 404 url(['/foo', '/bags/foo/tiddlers/bar']) #resfresh the currently loaded set of urls response = http.request('http://test_domain:8001/urls/refresh')[0] assert response.status == 200 #now check it was loaded successfully response = http.request('http://test_domain:8001/foo')[0] assert response.status == 200
def establish_user_auth(config, store, host, username): user = User(username) mapping_username = '******' % username mapping_tiddler = Tiddler(mapping_username, 'MAPUSER') mapping_tiddler.fields['mapped_user'] = username try: store.delete(user) except StoreError: pass try: store.delete(mapping_tiddler) except IOError: pass user.add_role('MEMBER') user.note = '{}' store.put(user) ensure_bag('MAPUSER', store) store.put(mapping_tiddler) stamp = datetime.utcnow().strftime('%Y%m%d%H') csrf = gen_nonce(username, host, stamp, config['secret']) cookie = make_cookie('tiddlyweb_user', mapping_username, mac_key=config['secret'], httponly=False) return cookie, csrf
def test_delete_gets_revisions(): """this relies on the previous test""" removed = Tiddler('tiddler1', 'holder') store.delete(removed) revision = Tiddler('tiddler1', 'holder') revision.revision = 2 py.test.raises(NoTiddlerError, 'store.get(revision)')
def test_post_existing(): """ overwrite an existing tiddler """ store = setup_store() setup_web() http = httplib2.Http() #pre-add a tiddler tiddler = Tiddler('HelloWorld', 'foo') tiddler.text = 'Hi There' store.put(tiddler) response = http.request('http://test_domain:8001/bags/foo/tiddlers', method='POST', headers={'Content-type': 'application/x-www-form-urlencoded'}, body='title=HelloWorld&text=Changed%20Text')[0] assert response.status == 204 #now check the tiddler is in the store and has been overwritten tiddler = Tiddler('HelloWorld', 'foo') try: store.get(tiddler) except NoTiddlerError: raise AssertionError('tiddler was not put into store') assert tiddler.title == 'HelloWorld' assert tiddler.text == 'Changed Text' assert tiddler.tags == []
def test_readable_tiddlers_by_bag(): bagone = Bag('cdentread') bagone.policy.read = ['cdent'] store.put(bagone) bagtwo = Bag('fndread') bagtwo.policy.read = ['fnd'] store.put(bagtwo) bagthree = Bag('allread') store.put(bagthree) count = 0 tiddlers = [] for bag in ['cdent', 'fnd', 'all', 'cdent', 'fnd', 'all', 'notreal']: count += 1 tiddler = Tiddler('tiddler%s' % count, '%sread' % bag) tiddler.text = 'narf' tiddlers.append(tiddler) usersign = {'name': 'cdent', 'roles': []} readable = list(readable_tiddlers_by_bag(store, tiddlers, usersign)) assert (['tiddler1', 'tiddler3', 'tiddler4', 'tiddler6', 'tiddler7'] == [tiddler.title for tiddler in readable]) usersign = {'name': 'fnd', 'roles': []} readable = list(readable_tiddlers_by_bag(store, tiddlers, usersign)) assert (['tiddler2', 'tiddler3', 'tiddler5', 'tiddler6', 'tiddler7'] == [tiddler.title for tiddler in readable]) usersign = {'name': 'GUEST', 'roles': []} readable = list(readable_tiddlers_by_bag(store, tiddlers, usersign)) assert (['tiddler3', 'tiddler6', 'tiddler7'] == [tiddler.title for tiddler in readable])
def test_simple(): bag = Bag('MAGICUSER') store.put(bag) extractor = Extractor() userinfo = {'name': 'cdent', 'roles': ['HELLO']} more_info = extractor.extract_more_info(environ, userinfo) assert 'modifier' in more_info assert 'name' in more_info assert 'roles' in more_info assert 'tags' in more_info assert 'fields' in more_info assert 'modified' in more_info assert more_info['tags'] == [] assert more_info['fields'] == {} assert more_info['roles'] == ['HELLO'] tiddler = Tiddler('cdent', 'MAGICUSER') tiddler.fields['roles'] = "GOODBYE CHRISTMAS EASTER ADMIN" tiddler.tags = ['monkey', 'hello', 'barney'] tiddler.fields['spaces'] = "one two three" store.put(tiddler) more_info = extractor.extract_more_info(environ, userinfo) assert more_info['tags'] == ['monkey', 'hello', 'barney'] assert len(more_info['roles']) == 5 for role in ['HELLO', 'GOODBYE', 'CHRISTMAS', 'EASTER', 'ADMIN']: assert role in more_info['roles'] assert more_info['fields']['spaces'] == 'one two three'
def handler(environ, start_response): input = environ['tiddlyweb.query'] store = environ['tiddlyweb.store'] # deal with python cgi packaging for field in input: if field in SKIP_FIELDS: continue input[field] = input[field][0] # need this to come in on the form input tiddler_title = input['tiddler_title'] del input['tiddler_title'] tiddler = Tiddler(tiddler_title, TARGET_BAG) # XXX is this the bag you want? try: tiddler.text = input['text'] del input['text'] except KeyError: tiddler.text = '' tiddler.fields = input store.put(tiddler) url = '/' # XXX replace with real url raise HTTP302(url)
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_cascade(): bag = Bag(u'holder') store.put(bag) tiddler = Tiddler(u'one', u'holder') tiddler.text = u'text' tiddler.tags = [u'tag'] tiddler.fields = {u'fieldone': u'valueone'} store.put(tiddler) def count_em(count, message): text_count = store.storage.session.query(sText).count() tag_count = store.storage.session.query(sTag).count() tiddler_count = store.storage.session.query(sTiddler).count() revision_count = store.storage.session.query(sRevision).count() field_count = store.storage.session.query(sField).count() store.storage.session.commit() message = ('%s, but got: text: %s, tag: %s, tiddler: %s, ' 'revision: %s, field: %s') % (message, text_count, tag_count, tiddler_count, revision_count, field_count) assert (text_count == tag_count == tiddler_count == revision_count == field_count == count), message count_em(1, '1 row for the tiddler everywhere') store.delete(tiddler) count_em(0, '0 rows for the tiddler everywhere')
def test_space_link(): tiddler = Tiddler('HouseHold', 'cdent_public') store.put(tiddler) http = httplib2.Http() urls = [ ('http://cdent.0.0.0.0:8080/recipes/cdent_public/tiddlers/HouseHold', '"/#%5B%5BHouseHold%5D%5D"'), ('http://cdent.0.0.0.0:8080/bags/cdent_public/tiddlers/HouseHold', '"http://cdent.0.0.0.0:8080/#%5B%5BHouseHold%5D%5D"'), ('http://cdent.0.0.0.0:8080/HouseHold', '"/#%5B%5BHouseHold%5D%5D"'), ('http://0.0.0.0:8080/bags/cdent_public/tiddlers/HouseHold', '!"http://cdent.0.0.0.0:8080/#%5B%5BHouseHold%5D%5D"'), ] for url, expected in urls: response, content = http.request(url, method='GET') assert response['status'] == '200' if expected.startswith('!'): expected == expected[1:] assert expected not in content, content else: assert expected in content, content url = 'http://0.0.0.0:8080/bags/tiddlyspace/tiddlers/Backstage' response, content = http.request(url, method='GET') assert response['status'] == '200' assert '/#%5B%5BBackstage%5D%5D' not in content, content tiddler = Tiddler('ServerSettings', 'cdent_public') tiddler.text = 'index: HouseHold\n' store.put(tiddler) for url, expected in urls[:3]: response, content = http.request(url, method='GET') assert response['status'] == '200' assert expected not in content, content
def test_tiddler_limit_field(): store = Store('tiddlywebplugins.mappingsql', {'db_config': 'sqlite:///test.db'}, {'tiddlyweb.config': config}) tiddler = Tiddler('monkey', 'avox') tiddler = store.get(tiddler) assert tiddler.fields['field_one'] == 'fat' assert 'field_three' not in tiddler.fields assert 'field_two' not in tiddler.fields store = Store('tiddlywebplugins.mappingsql', {'db_config': 'sqlite:///test.db'}, { 'tiddlyweb.config': config, 'tiddlyweb.usersign': {'name': 'zow'} }) tiddler = Tiddler('monkey', 'avox') tiddler = store.get(tiddler) assert tiddler.fields['field_one'] == 'fat' assert 'field_three' in tiddler.fields assert 'field_two' in tiddler.fields store = Store('tiddlywebplugins.mappingsql', {'db_config': 'sqlite:///test.db'}, { 'tiddlyweb.config': config, 'tiddlyweb.usersign': {'name': u'GUEST'} }) tiddler = Tiddler('monkey', 'avox') tiddler = store.get(tiddler) assert tiddler.fields['field_one'] == 'fat' assert 'field_three' not in tiddler.fields assert 'field_two' not in tiddler.fields
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] #tiddler_name = unicode(urllib.unquote(tiddler_name), 'utf-8') #bag_name = unicode(urllib.unquote(bag_name), 'utf-8') #recipe_name = unicode(urllib.unquote(recipe_name), 'utf-8') 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 = control.determine_tiddler_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_tiddler_edit(environ, start_response): usersign = environ['tiddlyweb.usersign'] store = environ['tiddlyweb.store'] title = environ['tiddlyweb.query'].get('title', [''])[0] bag_name = environ['tiddlyweb.query'].get('bag', [''])[0] username = usersign['name'] if not 'MEMBER' in usersign['roles']: raise HTTP404('bad edit') if not title and not bag_name: tiddler = get_profile(store, usersign, username) page_title = 'Edit Profile' return_url = '%s/home' % server_base_url(environ) elif not title: tiddler = Tiddler('', bag_name) page_title = 'Edit New Tiddler' return_url = '' else: tiddler = Tiddler(title, bag_name) page_title = 'Edit %s' % title return_url = tiddler_url(environ, tiddler) try: tiddler = store.get(tiddler) except StoreError: pass bag = Bag(tiddler.bag) bag = store.get(bag) bag.policy.allows(usersign, 'write') data = {} data['tiddler'] = tiddler data['return_url'] = return_url data['title'] = page_title return send_template(environ, 'profile_edit.html', data)
def test_get_profile_html(): response, content = http.request('http://0.0.0.0:8080/profiles/cdent') # the lack of a profile tiddler indicates you don't want to # participate assert response['status'] == '404', content tiddler = Tiddler('profile', 'cdent_public') tiddler.text = '#Hello There\n[[monkey]]' tiddler.type = 'text/x-markdown' tiddler.modifier = 'cdent' store.put(tiddler) response, content = http.request('http://0.0.0.0:8080/profiles/cdent') assert response['status'] == '200', content assert 'Hello There' in content assert 'http://cdent.0.0.0.0:8080/profile' in content assert '<li><a href="http://cdent.0.0.0.0:8080/profile">profile</a></li>' in content assert '<base href="http://cdent.0.0.0.0:8080/"' in content assert '<p><a class="wikilink" href="monkey">monkey</a></p>' in content response, content = http.request( 'http://cdent.0.0.0.0:8080/profiles/cdent') assert response['status'] == '404', content assert 'No profiles at this host' in content response, content = http.request('http://0.0.0.0:8080/profiles/notexist') assert response['status'] == '404', content assert 'Profile not found for notexist' in content
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 = control.determine_tiddler_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_email_tiddler(store, userpage): try: tiddler = Tiddler("email", userpage) tiddler = store.get(tiddler) except NoTiddlerError: tiddler.text = "" return tiddler.text
def add(self, tiddler): """ Add a reference to the :py:class:`tiddler <tiddlyweb.model.tiddler.Tiddler>` to the container, updating the digest and modified information. If the tiddler has recently been deleted, resulting in a :py:class:`StoreError <tiddlyweb.store.StoreError>`, don't add it. """ if not tiddler.store and self.store: try: tiddler = self.store.get(tiddler) except StoreError as exc: LOGGER.debug( 'tried to add missing tiddler to collection: %s, %s', tiddler, exc) return if not self.store.environ['tiddlyweb.config'].get( 'collections.use_memory', False): reference = Tiddler(tiddler.title, tiddler.bag) if tiddler.revision: reference.revision = tiddler.revision if tiddler.recipe: reference.recipe = tiddler.recipe self._container.append(reference) else: self._container.append(tiddler) else: self._container.append(tiddler) self._update_digest(tiddler) modified_string = str(tiddler.modified) modified_string = modified_string.ljust(14, '0') if modified_string > self.modified: self.modified = modified_string
def test_tiddler_url(): tiddler = Tiddler('foobar') tiddler.bag = 'zoom' url = tiddler_url(environ, tiddler) assert url == 'http://our_test_domain:8001/bags/zoom/tiddlers/foobar' tiddler.recipe = 'car' url = tiddler_url(environ, tiddler, container='recipes') assert url == 'http://our_test_domain:8001/recipes/car/tiddlers/foobar' url = tiddler_url(environ, tiddler, container='recipes', full=False) assert url == '/recipes/car/tiddlers/foobar' config['server_prefix'] = '/sleep' url = tiddler_url(environ, tiddler, container='recipes', full=False) assert url == '/sleep/recipes/car/tiddlers/foobar' url = tiddler_url(environ, tiddler) assert url == 'http://our_test_domain:8001/sleep/bags/zoom/tiddlers/foobar' tiddler.fields['_canonical_uri'] = 'http://example.com' url = tiddler_url(environ, tiddler) assert url == 'http://our_test_domain:8001/sleep/bags/zoom/tiddlers/foobar'
def test_get_profile_html(): response, content = http.request('http://0.0.0.0:8080/profiles/cdent') # the lack of a profile tiddler indicates you don't want to # participate assert response['status'] == '404', content tiddler = Tiddler('profile', 'cdent_public') tiddler.text = '!Hello There' tiddler.modifier = 'cdent' store.put(tiddler) response, content = http.request('http://0.0.0.0:8080/profiles/cdent') assert response['status'] == '200', content assert 'Hello There' in content assert '/cdent_public/tiddlers/profile' in content response, content = http.request( 'http://cdent.0.0.0.0:8080/profiles/cdent') assert response['status'] == '404', content assert 'No profiles at this host' in content response, content = http.request('http://0.0.0.0:8080/profiles/notexist') assert response['status'] == '404', content assert 'Profile not found for notexist' in content
def test_call_jsonp(): """ test that we can get some stuff as JSONP """ tiddler = Tiddler('public') tiddler.bag = 'foo_public' tiddler.text = 'some text' store.put(tiddler) user_cookie = get_auth('foo', 'foobar') callback = 'callback' response, content = http.request('http://foo.0.0.0.0:8080/bags/' 'foo_public/tiddlers/public?callback=%s' % callback, method='GET', headers={ 'Cookie': 'tiddlyweb_user="******"' % user_cookie, 'Accept': 'application/json' }) assert response['status'] == '200' assert content.startswith('%s(' % callback) assert content[-1:] == ')' response, content = http.request('http://0.0.0.0:8080/bags/' 'foo_public/tiddlers/public?callback=%s' % callback, method='GET', headers={ 'Cookie': 'tiddlyweb_user="******"' % user_cookie, 'Accept': 'application/json' }) assert response['status'] == '200' assert content.startswith('%s(' % callback) assert content[-1:] == ')'
def test_search_html(): response, content = http.request('http://0.0.0.0:8080/search?q=monkeys') assert response['status'] == '200', content assert 'http://fnd.0.0.0.0:8080/One%20Two' in content assert 'http://cdent.0.0.0.0:8080/three%20two%20one' in content assert '<a class="space" href="http://fnd.0.0.0.0:8080/">' in content assert '<img alt="space icon" src="http://fnd.0.0.0.0:8080/SiteIcon"/>' in content tiddler = store.get(Tiddler('One Two', 'fnd_public')) tiddler.modifier = 'cowboy' store.put(tiddler) response, content = http.request('http://0.0.0.0:8080/search?q=monkeys') assert response['status'] == '200', content assert '<a class="modifier" href="http://fnd.0.0.0.0:8080/">' not in content assert '<a class="modifier" href="http://cowboy.0.0.0.0:8080/">' in content # tiddlers that do not come from a space should show the default tiddlyspace site icon. tiddler = Tiddler('commoner', 'common') tiddler.text = 'I want to live like common people.' store.put(tiddler) response, content = http.request('http://0.0.0.0:8080/search?q=title:commoner') assert response['status'] == '200', content assert '<img alt="space icon" src="http://0.0.0.0:8080/SiteIcon"/>' in content
def _send_tiddler_revisions(environ, start_response, tiddler): """ Push the list of tiddler revisions out the network. """ store = environ['tiddlyweb.store'] title = 'Revisions of Tiddler %s' % tiddler.title title = environ['tiddlyweb.query'].get('title', [title])[0] container = 'recipes' if tiddler.recipe else 'bags' if environ['tiddlyweb.filters']: tiddlers = Tiddlers(title=title) else: tiddlers = Tiddlers(title=title, store=store) tiddlers.is_revisions = True tiddlers.link = '%s/revisions' % web.tiddler_url(environ, tiddler, container=container, full=False) recipe = tiddler.recipe try: for revision in store.list_tiddler_revisions(tiddler): tmp_tiddler = Tiddler(title=tiddler.title, bag=tiddler.bag) tmp_tiddler.revision = revision if recipe: tmp_tiddler.recipe = recipe tiddlers.add(tmp_tiddler) except NoTiddlerError, exc: # If a tiddler is not present in the store. raise HTTP404('tiddler %s not found, %s' % (tiddler.title, exc))
def mapper(atom_field_name, tiddler, default): logging.debug( "atom-custom:: doing a mapping on field %s \n atom-custom::with tiddler %s \n atom-custom::and config %s" % (atom_field_name, tiddler, mappings)) tid = Tiddler(tiddler['title'], tiddler['bag']) tid = serializer.as_tiddler(tid, tiddler) try: tid.recipe = tiddler['recipe'] except KeyError: pass if atom_field_name in mappings: val = mappings[atom_field_name] if atom_field_name == 'link' or atom_field_name == 'id' and val.startswith( "/"): sh = config['server_host'] val = u"%s://%s%s" % (sh['scheme'], sh['host'], val) wikified = "http://%s" % wikitext_to_wikklyhtml( baseurl, '', val[7:], self.environ, tiddler=tid, wikiwords=False) else: wikified = wikitext_to_wikklyhtml(baseurl, '', val, self.environ, tiddler=tid, wikiwords=False) return cgi.escape(wikified).decode("utf-8") else: return default
def test_put_with_slash(): tiddler1 = Tiddler('He is 5 and 1/2', 'bagone') store.put(tiddler1) tiddler2 = Tiddler('He is 5 and 1/2', 'bagone') store.get(tiddler2) assert tiddler1.title == tiddler2.title
def test_no_bag_for_tiddler(): tiddler = Tiddler('testnobag') tiddler.text = 'no bag here' tiddler.bag = u'no bag of this name' with py.test.raises(NoBagError): store.put(tiddler)
def migrate_bags(source, target, bags=None): print "migrate bags" if bags: bags = [Bag(bag) for bag in bags] else: bags = source.list_bags() for bag in bags: bag = source.get(bag) try: tiddlers = bag.list_tiddlers() except AttributeError: tiddlers = source.list_bag_tiddlers(bag) target.put(bag) for tiddler in tiddlers: for revision_id in reversed( source.list_tiddler_revisions(tiddler)): tiddler_revision = Tiddler(tiddler.title, tiddler.bag) tiddler_revision.revision = revision_id tiddler_revision = source.get(tiddler_revision) print "putting tiddler %s:%s in bag %s" % ( tiddler_revision.title.encode('utf-8'), tiddler_revision.revision, tiddler_revision.bag.encode('utf-8')) tiddler_revision.revision = None target.put(tiddler_revision)
def get_email_tiddler(store, userpage): try: tiddler = Tiddler('email', userpage) tiddler = store.get(tiddler) except NoTiddlerError: tiddler.text = '' return tiddler.text
def submit(environ, start_response): """ Take POSTed input, put it in a Tiddler and save it into the store, and redirect back to the user page. """ user = environ['tiddlyweb.usersign']['name'] if user == 'GUEST': raise UserRequiredError, 'real user required to twote' recent_recipe = _check_recipe('recent', environ, user) all_recipe = _check_recipe('all', environ, user) tiddler = _make_tiddler(environ, user) bag = control.determine_bag_for_tiddler(all_recipe, tiddler) tiddler.bag = bag.name store = environ['tiddlyweb.store'] original_title = tiddler.title tester_tiddler = Tiddler(original_title, bag=bag.name) addendum = 2 while 1: try: tester_tiddler = store.get(tester_tiddler) new_title = '%s-%s' % (original_title, addendum) tiddler.title = new_title tester_tiddler.title = new_title addendum += 1 except NoTiddlerError: store.put(tiddler) break raise HTTP302, '%s/twoter/%s' % (server_base_url(environ), urllib.quote(user))
def test_normal_output(): tiddler = Tiddler('not svg thing', 'fake') tiddler.text = '!Hi' serializer.object = tiddler output = serializer.to_string() assert '!Hi</pre>' in output
def test_search_unique(): bag = Bag('bag1') store.put(bag) tiddler1 = Tiddler('tiddler1', 'bag1') tiddler1.text = 'catsdogshouses' store.put(tiddler1) tiddler2 = Tiddler('tiddler2', 'bag1') tiddler2.text = 'housesdogscats' store.put(tiddler2) tiddlers = list(search(config, 'catsdogshouses')) assert len(tiddlers) == 1 assert tiddlers[0]['id'] == 'bag1:tiddler1' tiddlers = list(search(config, 'housesdogscats')) assert len(tiddlers) == 1 assert tiddlers[0]['id'] == 'bag1:tiddler2' store.delete(tiddler1) tiddlers = list(search(config, 'catsdogshouses')) assert len(tiddlers) == 0 tiddlers = list(search(config, 'housesdogscats')) assert len(tiddlers) == 1 assert tiddlers[0]['id'] == 'bag1:tiddler2' store.delete(tiddler2) tiddlers = list(search(config, 'housesdogscats')) assert len(tiddlers) == 0
def test_field_composed_filter(): """ Add a field to a tiddler and then make sure we can filter for it. """ tiddler1 = Tiddler('one') tiddler1.fields = {'status': 'hot'} tiddler2 = Tiddler('two') tiddler2.fields = {'status': 'cold'} tiddler3 = Tiddler('three') found_tiddlers = filter('select=status:hot', [tiddler1, tiddler2, tiddler3]) assert [tiddler.title for tiddler in found_tiddlers] == ['one'] found_tiddlers = filter('select=status:!hot', [tiddler1, tiddler2, tiddler3]) assert [tiddler.title for tiddler in found_tiddlers] == ['two', 'three'] found_tiddlers = filter('select=status:cold', [tiddler1, tiddler2, tiddler3]) assert [tiddler.title for tiddler in found_tiddlers] == ['two'] found_tiddlers = filter('select=barnabas:monkey', [tiddler1, tiddler2, tiddler3]) assert [tiddler.title for tiddler in found_tiddlers] == [] found_tiddlers = filter('select=barnabas:!monkey', [tiddler1, tiddler2, tiddler3]) assert [tiddler.title for tiddler in found_tiddlers] == ['one', 'two', 'three']
def setup_testdata(): testdata = [ {"title":u"Whiskers","tags":["I wRiTe lIke A fIvE yEaR oLd","Kitty","pet","lolcat"],"fields":{"read":"no","badfield":"z"}}, {"title":u"Fred","tags":["dog","pet"],"fields":{"badfield":"xt"}}, {"title":u"Chris","tags":["cat","animal","bogof"],"fields":{"badfield":"ks"}}, {"title":u"Martin","tags":["fish","lion"],"fields":{"badfield":"zs"}}, {"title":u"Jerm","tags":["monkey"],"fields":{"badfield":"z"}}, {"title":u"Paul","tags":["dinosaurs rule","tiger"],"fields":{"badfield":"z"}}, {"title":u"Ben","tags":["cAt","i love my cat"],"fields":{"badfield":"z"}}, {"title":u"Andrew","tags":["Pet","Animal","kitty","ToysRUs"],"fields":{"badfield":"z","foo":"yes"}} ] tiddlers = [] for tid in testdata: tiddler = Tiddler(tid["title"],"tmp") tiddler.fields = tid["fields"] tiddler.tags = tid["tags"] tiddlers.append(tiddler) bag = Bag("tmp") try: store.delete(bag)#delete any existing one except NoBagError: pass store.put(bag) for tiddler in tiddlers: store.put(tiddler)
def test_subscribe_bad_atom(): # setup setup(store) empty = Tiddler("bags/osmosoft_private/bad", "subscriptions.daily") empty.text = """[email protected] [email protected] """ twhost = environ["tiddlyweb.config"]["server_host"]["host"] expected = ( u"""note you can subscribe to this feed via atom feed <%s/test/bags/osmosoft_private/bad.atom> one <two> Saint_Barth\xe9lemy <three> """ % twhost ) # run email = mailer.make_digest_email( empty, environ ) # now since there was no changes to the store you would expect no email # verify assert email["body"] == expected
def test_tiddler_url(): tiddler = Tiddler('foobar') tiddler.bag = 'zoom' url = tiddler_url(environ, tiddler) assert url == 'http://our_test_domain:8001/bags/zoom/tiddlers/foobar' tiddler.recipe = 'car' url = tiddler_url(environ, tiddler, container='recipes') assert url == 'http://our_test_domain:8001/recipes/car/tiddlers/foobar' url = tiddler_url(environ, tiddler, container='recipes', full=False) assert url == '/recipes/car/tiddlers/foobar' config['server_prefix'] = '/sleep' url = tiddler_url(environ, tiddler, container='recipes', full=False) assert url == '/sleep/recipes/car/tiddlers/foobar' url = tiddler_url(environ, tiddler) assert url == 'http://our_test_domain:8001/sleep/bags/zoom/tiddlers/foobar' tiddler.fields['_canonical_uri'] = 'http://example.com' url = tiddler_url(environ, tiddler) # we decided url is always local #assert url == 'http://example.com' assert url == 'http://our_test_domain:8001/sleep/bags/zoom/tiddlers/foobar'
def _process_choices(environ, start_response, form): store = environ['tiddlyweb.store'] user = environ['tiddlyweb.usersign'] tmp_bag = form['tmp_bag'][0] bag = form['target_bag'][0] if bag: bag = Bag(bag) try: bag.skinny = True bag = store.get(bag) except NoBagError: return _send_wimport(environ, start_response, 'chosen bag does not exist') else: bag = form['new_bag'][0] bag = _make_bag(environ, bag) try: bag.policy.allows(user, 'write') except (ForbiddenError, UserRequiredError): return _send_wimport(environ, start_response, 'you may not write to that bag') tiddler_titles = form['tiddler'] for title in tiddler_titles: tiddler = Tiddler(title.decode('utf-8', 'ignore'), tmp_bag) tiddler = store.get(tiddler) tiddler.bag = bag.name store.put(tiddler) tmp_bag = Bag(tmp_bag) store.delete(tmp_bag) bagurl = bag_url(environ, bag) + '/tiddlers' raise HTTP302(bagurl)
def manage_gym(environ, start_response): store = environ['tiddlyweb.store'] gym = get_route_value(environ, 'gym') routes_bag = store.get(Bag('%s_climbs' % gym)) news_bag = Bag('%s_news' % gym) # Bail out if we are not allowed to manage. routes_bag.policy.allows(environ['tiddlyweb.usersign'], 'manage') gym_tiddler = store.get(Tiddler(gym, GYMS_BAG)) try: latest_news = [tiddler for tiddler in filter_tiddlers( store.list_bag_tiddlers(news_bag), 'sort=-modified;limit=1', environ)][0] latest_news = store.get(latest_news) news_html = render_wikitext(latest_news, environ) latest_news.fields['html'] = news_html except IndexError: latest_news = Tiddler('tmp') latest_news.fields['html'] = '<p>No News</p>' routes = _get_gym_routes(environ, gym) return send_template(environ, 'manage_gym.html', { 'title': 'Manage %s' % gym, 'gym_tiddler': gym_tiddler, 'latest_news': latest_news, 'routes': routes})
def test_web_front(): bag = Bag('bagone') store.put(bag) tiddler = Tiddler('tiddlerone', 'bagone') tiddler.text = "I am NotYou@cdent, http://burningchrome.com/" store.put(tiddler) http = httplib2.Http() response, content = http.request('http://0.0.0.0:8080/bags/bagone/tiddlers/tiddlerone/frontlinks.html') assert response['status'] == '200', content assert '<a href="/recipes/cdent_public/tiddlers/NotYou">NotYou</a>' in content, content bag = Bag('cdent_public') store.put(bag) tiddler = Tiddler('NotYou', 'cdent_public') tiddler.text = 'as BigPoo is' store.put(tiddler) response, content = http.request('http://0.0.0.0:8080/bags/cdent_public/tiddlers/NotYou/frontlinks') assert '<a href="/bags/cdent_public/tiddlers/BigPoo">BigPoo</a>' in content, content response, content = http.request('http://0.0.0.0:8080/bags/cdent_public/tiddlers/NotYou/backlinks') assert '<a href="/bags/barney/tiddlers/hello">hello</a>' in content assert '<a href="/bags/bagone/tiddlers/tiddlerone">tiddlerone</a>' in content # Use web delete, not store delete as web delete instantiates the tiddler #store.delete(Tiddler('hello', 'barney')) response, content = http.request('http://0.0.0.0:8080/bags/barney/tiddlers/hello', method='DELETE') assert response['status'] == '204' response, content = http.request('http://0.0.0.0:8080/bags/cdent_public/tiddlers/NotYou/backlinks') assert '<a href="/bags/barney/tiddlers/hello">hello</a>' not in content
def add(self, tiddler): """ Add a reference to the tiddler to the container, updating the digest and modified information. """ self._update_digest(tiddler) if self.store: reference = Tiddler(tiddler.title, tiddler.bag) if tiddler.revision: reference.revision = tiddler.revision if tiddler.recipe: reference.recipe = tiddler.recipe self._container.append(reference) else: self._container.append(tiddler) try: modified_string = str(tiddler.modified) modified_string = modified_string.ljust(14, '0') if modified_string > self.modified: self.modified = modified_string except AttributeError: pass
def test_parsing(): """ Incomplete testing of parsing the filter string as part of the query string parsing, leaving the rest of the query string intact. """ string = 'slag=absolute;foo=;select=tag:systemConfig;select=tag:blog;fat=1;sort=-modified;limit=0,10;select=title:monkey' filters, leftovers = parse_for_filters(string) assert len(filters) == 5 assert leftovers == 'slag=absolute;foo=;fat=1' text_filters = [] for filter, text, environ in filters: text_filters.append(text) assert len(text_filters) == 5 assert text_filters[0][1] == 'tag:systemConfig' assert text_filters[1][1] == 'tag:blog' assert text_filters[2][1] == '-modified' assert text_filters[3][1] == '0,10' tiddlers = [Tiddler('a'), Tiddler('monkey')] tiddlers[1].tags = ['systemConfig', 'blog'] tiddlers = list(recursive_filter(filters, tiddlers)) assert len(tiddlers) == 1 assert tiddlers[0].title == 'monkey'
def test_simple_spacelink(): tiddler = Tiddler('test') tiddler.text = '# Hi\nVisit @cdent for more info.' output = render(tiddler, environ) assert '<a href="http://cdent.tiddlyspace.org:8080/">@cdent</a>' in output
def test_hash(): bag = Bag('one') store.put(bag) tiddler = Tiddler('hi', 'one') tiddler.text = 'fancy' store.put(tiddler) tiddler = store.get(tiddler) assert '_hash' in tiddler.fields response, content = http.request( 'http://0.0.0.0:8080/bags/one/tiddlers/hi.json', method='GET') assert response['status'] == '200' info = simplejson.loads(content) assert info['fields']['_hash'] == tiddler.fields['_hash'] info['text'] = 'not fancy' body = simplejson.dumps(info) response, content = http.request( 'http://0.0.0.0:8080/bags/one/tiddlers/hi', headers={'Content-type': 'application/json'}, body=body, method='PUT') assert response['status'] == '204' tiddler = Tiddler('hi', 'one') tiddler = store.get(tiddler) assert tiddler.text == info['text'] assert tiddler.fields['_hash'] != info['fields']['_hash']
def test_space_server_settings_index(): http = httplib2.Http() response, content = http.request('http://foo.0.0.0.0:8080/') assert response['status'] == '200' assert 'TiddlyWiki' in content tiddler = Tiddler('ServerSettings', 'foo_public') tiddler.text = 'index: MySPA\n' store.put(tiddler) http = httplib2.Http() response, content = http.request('http://foo.0.0.0.0:8080/') assert response['status'] == '404' tiddler = Tiddler('MySPA', 'foo_public') tiddler.text = '<html><h1>Hello!</h1></html>' tiddler.type = 'text/html' store.put(tiddler) http = httplib2.Http() response, content = http.request('http://foo.0.0.0.0:8080/') assert response['status'] == '200' assert '<h1>Hello!</h1>' in content assert 'TiddlyWiki' not in content assert 'TiddlyWeb' not in content
def test_determine_tiddler_from_recipe(): """ Work out what bag a provided tiddler is in, when we have no knowledge of the bag, but we do have a recipe. """ short_recipe = Recipe(name='foobar') short_recipe.set_recipe([ [bagone, ''], [bagfour, 'select=tag:tagone'] ]) bag = control.determine_tiddler_bag_from_recipe(short_recipe, tiddlers[0]) assert bag.name == bagfour.name, 'bag name should be bagfour, is %s' % bag.name short_recipe.set_recipe([ [bagone, ''], [bagfour, 'select=tag:tagthree'] ]) bag = control.determine_tiddler_bag_from_recipe(short_recipe, tiddlers[0]) assert bag.name == bagone.name, 'bag name should be bagone, is %s' % bag.name lonely_tiddler = Tiddler('lonely') lonely_tiddler.bag = 'lonelybag' py.test.raises(NoBagError, 'bag = control.determine_tiddler_bag_from_recipe(short_recipe, lonely_tiddler)')
def test_tiddler_put(): store_root = os.path.join(TMPDIR, "test_store") bag = Bag("alpha") tiddler = Tiddler("Foo", bag.name) tiddler.text = "lorem ipsum\ndolor sit amet" tiddler.tags = ["foo", "bar"] STORE.put(bag) bag_dir = os.path.join(store_root, "bags", "alpha") assert os.path.isdir(bag_dir) assert os.path.isdir(os.path.join(bag_dir, "tiddlers")) STORE.put(tiddler) tiddler_file = os.path.join(bag_dir, "tiddlers", "Foo") assert os.path.isfile(tiddler_file) assert len(tiddler.revision) == 40 with open(tiddler_file) as fh: contents = fh.read() assert "tags: foo bar" in contents assert tiddler.text in contents info = run("git", "log", "-n1", "--format=%ae %ce: %s", cwd=store_root) assert info.strip() == "[email protected] [email protected]: tiddler put"
def test_float_field(): tiddler = Tiddler('foo', 'bar') tiddler.fields['float'] = 100.5 serializer = Serializer('text') serializer.object = tiddler assert '100.5' in '%s' % serializer
def _process_tiddler_revisions(self, feed, tiddler, link, do_revisions): try: from tiddlywebplugins.differ import compare_tiddlers except ImportError: self._add_item(feed, tiddler, link, tiddler.title, 'unable to diff without tiddlywebplugins.differ') try: depth = int(do_revisions) except ValueError: depth = 1 store = self.environ['tiddlyweb.store'] revision_ids = store.list_tiddler_revisions(tiddler) while depth >= 0: try: rev_older = Tiddler(tiddler.title, tiddler.bag) rev_older.revision = revision_ids[depth + 1] rev_older = store.get(rev_older) except IndexError: depth -= 1 continue rev_current = Tiddler(tiddler.title, tiddler.bag) rev_current.revision = revision_ids[depth] rev_current = store.get(rev_current) if binary_tiddler(tiddler): self._add_item(feed, tiddler, link, tiddler.title, 'Binary Content') else: title = '%s comparing version %s to %s' % (tiddler.title, rev_older.revision, rev_current.revision) self._add_item(feed, rev_current, link, title, '<pre>' + compare_tiddlers(rev_older, rev_current) + '</pre>') depth -= 1
def test_emoji_title(): """ We expect this to fail because we're using a) old mysql b) without the utf8mb4 encoding type. See: https://github.com/TiddlySpace/tiddlyspace/issues/1033 The fix is to use mysql 5.5 or beyond. """ # emoji smiley of some sort title = '\xF0\x9F\x98\x97'.decode('utf-8') store.put(Bag(title)) tiddler = Tiddler(title, title) tiddler.text = u'some stuff and zomg %s' % title tiddler.tags = [title] tiddler.fields[title] = title store.put(tiddler) tiddler2 = store.get(Tiddler(title, title)) assert tiddler2.title == title assert tiddler2.text == tiddler.text assert tiddler2.tags == tiddler.tags assert tiddler2.tags[0] == title assert tiddler2.fields[title] == tiddler.fields[title] assert tiddler2.fields[title] == title
def test_hash(): bag = Bag('one') store.put(bag) tiddler = Tiddler('hi', 'one') tiddler.text = 'fancy' store.put(tiddler) tiddler = store.get(tiddler) assert '_hash' in tiddler.fields response, content = http.request('http://0.0.0.0:8080/bags/one/tiddlers/hi.json', method='GET') assert response['status'] == '200' info = simplejson.loads(content) assert info['fields']['_hash'] == tiddler.fields['_hash'] info['text'] = 'not fancy' body = simplejson.dumps(info) response, content = http.request('http://0.0.0.0:8080/bags/one/tiddlers/hi', headers={'Content-type': 'application/json'}, body=body, method='PUT') assert response['status'] == '204' tiddler = Tiddler('hi', 'one') tiddler = store.get(tiddler) assert tiddler.text == info['text'] assert tiddler.fields['_hash'] != info['fields']['_hash']
def test_simple_magic(): bag = Bag('MAGICUSER') store.put(bag) extractor = Extractor() userinfo = {'name': 'cdent', 'roles': ['HELLO']} more_info = extractor.extract_more_info(environ, userinfo) assert 'modifier' in more_info assert 'name' in more_info assert 'roles' in more_info assert 'tags' in more_info assert 'fields' in more_info assert 'modified' in more_info assert more_info['tags'] == [] assert more_info['fields'] == {} assert more_info['roles'] == ['HELLO'] tiddler = Tiddler('cdent', 'MAGICUSER') tiddler.fields['roles'] = "GOODBYE CHRISTMAS EASTER ADMIN" tiddler.tags = ['monkey', 'hello', 'barney'] tiddler.fields['spaces'] = "one two three" store.put(tiddler) more_info = extractor.extract_more_info(environ, userinfo) assert sorted(more_info['tags']) == [u'barney', u'hello', u'monkey'] assert len(more_info['roles']) == 5 for role in ['HELLO', 'GOODBYE', 'CHRISTMAS', 'EASTER', 'ADMIN']: assert role in more_info['roles'] assert more_info['fields']['spaces'] == 'one two three'
def _send_tiddler_revisions(environ, start_response, tiddler): """ Push the list of tiddler revisions out the network. """ store = environ['tiddlyweb.store'] title = 'Revisions of Tiddler %s' % tiddler.title title = environ['tiddlyweb.query'].get('title', [title])[0] container = 'recipes' if tiddler.recipe else 'bags' if environ['tiddlyweb.filters']: tiddlers = Tiddlers(title=title) else: tiddlers = Tiddlers(title=title, store=store) tiddlers.is_revisions = True tiddlers.link = '%s/revisions' % web.tiddler_url( environ, tiddler, container=container, full=False) recipe = tiddler.recipe try: for revision in store.list_tiddler_revisions(tiddler): tmp_tiddler = Tiddler(title=tiddler.title, bag=tiddler.bag) tmp_tiddler.revision = revision if recipe: tmp_tiddler.recipe = recipe tiddlers.add(tmp_tiddler) except NoTiddlerError, exc: # If a tiddler is not present in the store. raise HTTP404('tiddler %s not found, %s' % (tiddler.title, exc))
def _create_tiddlers(self, tiddlers): """ Figure out the content to be pushed into the wiki and calculate the title. """ kept_tiddlers = [] window_title = None candidate_title = None candidate_subtitle = None markup_tiddlers = MARKUPS.keys() found_markup_tiddlers = {} for tiddler in tiddlers: kept_tiddlers.append(tiddler) tiddler_title = tiddler.title if tiddler_title == 'WindowTitle': window_title = tiddler.text if tiddler_title == 'SiteTitle': candidate_title = tiddler.text if tiddler_title == 'SiteSubtitle': candidate_subtitle = tiddler.text if tiddler_title in markup_tiddlers: found_markup_tiddlers[tiddler_title] = tiddler.text if len(kept_tiddlers) == 1: default_tiddler = Tiddler('DefaultTiddlers', '_virtual') default_tiddler.text = '[[' + tiddler.title + ']]' kept_tiddlers.append(default_tiddler) # From the several options for title, choose one. title = self._determine_title(window_title, candidate_title, candidate_subtitle) return kept_tiddlers, title, found_markup_tiddlers
def from_special(uri, handle, mime=None): """ Import a binary or pseudo binary tiddler. If a mime is provided, set the type of the tiddler to that. Otherwise use the type determined by the URL handler. If a meta file is present and has a type, it will be used. This code is inspired by @bengillies bimport. """ title = _get_title_from_uri(uri) if mime: content_type = mime else: content_type = handle.headers['content-type'].split(';')[0] data = handle.read() meta_uri = '%s.meta' % uri try: meta_content = _get_url(meta_uri) tiddler = _from_text(title, meta_content + '\n\n') except (HTTPError, URLError, IOError, OSError): tiddler = Tiddler(title) if not tiddler.type and content_type: tiddler.type = content_type if pseudo_binary(tiddler.type): data = data.decode('utf-8', 'ignore') tiddler.text = data return tiddler