def test_recipe_etag(): """ Explicitly test recipe_etag method (not used by the core code). """ recipe1 = Recipe('foo') recipe1.desc = 'desc' recipe2 = Recipe('foo') recipe2.desc = 'desc' assert recipe_etag(environ, recipe1) == recipe_etag(environ, recipe2)
def _create_recipe(environ): """Take the form input and turn it into a recipe.""" # get bag_names before we flatten because it will be a list bag_names = environ['tiddlyweb.query'].get('bags', []) query_data = _flatten_form_data(environ['tiddlyweb.query']) store = environ['tiddlyweb.store'] try: new_recipe_name = query_data['recipe_name'] if _recipe_exists(store, new_recipe_name): raise HTTP409('That recipe may not be created.') new_recipe = Recipe(new_recipe_name) username = environ['tiddlyweb.usersign']['name'] new_recipe.policy.owner = username new_recipe.policy.manage = [username] new_recipe.desc = query_data.get('recipe_desc', '') privacy = query_data['privacy'] new_recipe.policy.read = _policy_form_to_entry(username, privacy) bag_list = [] if query_data.get('autowiki', 0): bag_list.extend(AUTOWIKI_BAGS) # don't worry about default content bag yet bag_list.extend(bag_names) recipe_list = [[bag_name, ''] for bag_name in bag_list] new_recipe.set_recipe(recipe_list) store.put(new_recipe) except KeyError, exc: raise HTTP400('something went wrong processing for: %s' % exc)
def test_store_recipe(): recipe_in = Recipe('recipeone') recipe_in.desc = 'recipe description' store.put(recipe_in) recipe_out = store.get(Recipe('recipeone')) assert recipe_out.name == recipe_in.name
def test_recipe_bad_filter_400(): recipe = Recipe("badfilter") recipe.desc = u"hello" recipe.set_recipe([("bag8", "select=error:5")]) store.put(recipe) http = httplib2.Http() response, content = http.request("http://our_test_domain:8001/recipes/badfilter/tiddlers") assert response["status"] == "400", content
def test_recipe_bad_filter_400(): recipe = Recipe('badfilter') recipe.desc = u'hello' recipe.set_recipe([('bag8', 'select=error:5')]) store.put(recipe) response, content = http.requestU( 'http://our_test_domain:8001/recipes/badfilter/tiddlers') assert response['status'] == '400', content
def test_recipe_has_description(): """ Confirm a recipe can set and use a description. """ recipe = Recipe('hasbeen', desc='monkey puzzle') assert recipe.name == 'hasbeen' assert recipe.desc == 'monkey puzzle' recipe.desc = 'collapsing sideburns' assert recipe.desc == 'collapsing sideburns'
def test_recipe_no_recipe(): """ make a sure a recipe that is stored without a recipe is retrievable """ recipe = Recipe('testrecipe2') recipe.desc = 'I enjoy being stored' store.put(recipe) stored_recipe = Recipe('testrecipe2') stored_recipe = store.get(stored_recipe) assert stored_recipe.desc == recipe.desc
def test_recipe_put(): """ put a recipe to disk and make sure it is there. """ recipe = Recipe('testrecipe') recipe.desc = 'I enjoy being stored' recipe.set_recipe(recipe_list_string) store.put(recipe) if type(store.storage) != tiddlyweb.stores.text.Store: py.test.skip('skipping this test for non-text store') assert os.path.exists(expected_stored_filename)
def test_recipe_delete(): recipe = Recipe('deleteme') recipe.desc = 'delete me please' store.put(recipe) stored_recipe = Recipe('deleteme') stored_recipe = store.get(stored_recipe) assert stored_recipe.desc == 'delete me please' deleted_recipe = Recipe('deleteme') store.delete(deleted_recipe) py.test.raises(NoRecipeError, 'store.get(deleted_recipe)') py.test.raises(NoRecipeError, 'store.delete(deleted_recipe)')
def test_get_recipe_dot_name(): """ Effectively return an entity with a dot in the name. """ recipe = Recipe("long.gif") recipe.desc = u"hello" store.put(recipe) http = httplib2.Http() response, content = http.request("http://our_test_domain:8001/recipes/long.gif", method="GET") assert response["status"] == "200" store.delete(recipe)
def test_recipe_delete(): recipe = Recipe("deleteme") recipe.desc = "delete me please" store.put(recipe) stored_recipe = Recipe("deleteme") stored_recipe = store.get(stored_recipe) assert stored_recipe.desc == "delete me please" deleted_recipe = Recipe("deleteme") store.delete(deleted_recipe) py.test.raises(NoRecipeError, "store.get(deleted_recipe)") py.test.raises(NoRecipeError, "store.delete(deleted_recipe)")
def test_store_recipe(): recipe = Recipe('recipe1') recipe.desc = 'recipe 1 desc' recipe.set_recipe([ ['bag1', ''] ]) store.put(recipe) assert os.path.exists('store/recipe1.recipe') loaded_recipe = Recipe('recipe1') loaded_recipe = store.get(loaded_recipe) assert loaded_recipe.desc == recipe.desc
def test_get_recipe_dot_name(): """ Effectively return an entity with a dot in the name. """ recipe = Recipe('long.gif') recipe.desc = u'hello' store.put(recipe) response, content = http.requestU( 'http://our_test_domain:8001/recipes/long.gif', method='GET') assert response['status'] == '200' store.delete(recipe)
def test_recipe_delete(): recipe = Recipe('deleteme') recipe.desc = 'delete me please' store.put(recipe) stored_recipe = Recipe('deleteme') stored_recipe = store.get(stored_recipe) assert stored_recipe.desc == 'delete me please' deleted_recipe = Recipe('deleteme') store.delete(deleted_recipe) with py.test.raises(NoRecipeError): store.get(deleted_recipe) with py.test.raises(NoRecipeError): store.delete(deleted_recipe)
def test_recipes(): store.put(Bag('alpha')) store.put(Bag('beta')) tiddler = Tiddler('steak', 'alpha') tiddler.text = 'rare' store.put(tiddler) tiddler = Tiddler('liver', 'beta') tiddler.text = 'icky' store.put(tiddler) tiddler = Tiddler('steak', 'beta') tiddler.text = 'medium' store.put(tiddler) recipec = Recipe('cow') recipec.desc = 'a meaty melange' recipec.policy.accept.append('cdent') recipec.set_recipe([ ('alpha', 'select=tag:systemConfig'), ('beta', '')]) store.put(recipec) recipes = list(store.list_recipes()) assert len(recipes) == 1 reciped = store.get(recipes[0]) assert reciped.name == recipec.name assert reciped.desc == recipec.desc recipe_list = reciped.get_recipe() assert recipe_list[0] == ['alpha', 'select=tag:systemConfig'] assert recipe_list[1] == ['beta', ''] tiddlers = list(get_tiddlers_from_recipe(reciped, environ=environ)) assert len(tiddlers) == 2 for tiddler in tiddlers: assert tiddler.bag == 'beta' if tiddler.title == 'alpha': tiddler = store.get(tiddler) assert tiddler.text == 'medium' store.delete(reciped) recipes = list(store.list_recipes()) assert len(recipes) == 0
def post_createrecipe(environ, start_response): user = get_user_object(environ) store = environ['tiddlyweb.store'] recipe_name = environ['tiddlyweb.query'].get('recipe', [''])[0] bag_name = environ['tiddlyweb.query'].get('bag', [''])[0] publicity = environ['tiddlyweb.query'].get('publicity', [''])[0] description = environ['tiddlyweb.query'].get('description', [''])[0] if not bag_name or not recipe_name: raise HTTP400('missing data') recipe = Recipe(recipe_name) bag = Bag(bag_name) try: recipe = store.get(recipe) raise HTTP400('recipe exists') except NoRecipeError: pass try: bag.skinny = True bag = store.get(bag) try: bag.policy.allows(user, 'read') except (UserRequiredError, ForbiddenError): raise HTTP400('bag not readable') except NoBagError: bag.policy.owner = user['name'] for constraint in ['read', 'write', 'create', 'delete', 'manage']: setattr(bag.policy, constraint, [user['name']]) store.put(bag) if publicity == 'private': recipe.policy.read = [user['name']] else: recipe.policy.read = [] recipe.policy.manage = [user['name']] recipe.policy.owner = user['name'] recipe.desc = description recipe.set_recipe([ ('system', ''), (bag.name, ''), ]) store.put(recipe) raise HTTP303('%s/home' % server_base_url(environ))
def post_createrecipe(environ, start_response): user = get_user_object(environ) store = environ['tiddlyweb.store'] recipe_name = environ['tiddlyweb.query'].get('recipe', [''])[0] bag_name = environ['tiddlyweb.query'].get('bag', [''])[0] publicity = environ['tiddlyweb.query'].get('publicity', [''])[0] description = environ['tiddlyweb.query'].get('description', [''])[0] if not bag_name or not recipe_name: raise HTTP400('missing data') recipe = Recipe(recipe_name) bag = Bag(bag_name) try: recipe = store.get(recipe) raise HTTP400('recipe exists') except NoRecipeError: pass try: bag = store.get(bag) try: bag.policy.allows(user, 'read') except (UserRequiredError, ForbiddenError): raise HTTP400('bag not readable') except NoBagError: bag.policy.owner = user['name'] for constraint in ['read', 'write', 'create', 'delete', 'manage']: setattr(bag.policy, constraint, [user['name']]) store.put(bag) if publicity == 'private': recipe.policy.read = [user['name']] else: recipe.policy.read = [] recipe.policy.manage = [user['name']] recipe.policy.owner = user['name'] recipe.desc = description recipe.set_recipe([ ('system', ''), (bag.name, ''), ]) store.put(recipe) raise HTTP303('%s/home' % server_base_url(environ))
def test_recipe_put(): """ put a recipe to disk and make sure it is there. """ recipe = Recipe('testrecipe') recipe.desc = 'I enjoy being stored' recipe.set_recipe(recipe_list_string) store.put(recipe) if type(store.storage) != tiddlyweb.stores.text.Store: py.test.skip('skipping this test for non-text store') assert os.path.exists(expected_stored_filename) with open(expected_stored_filename) as f: content = f.read() if sys.version_info[0] < 3: assert content == expected_stored_content
def _check_recipe(name, environ, user): """ Get the user's recipes, create them if required. """ store = environ['tiddlyweb.store'] recipe_name = '%s-%s' % (user, name) recipe_name = recipe_name.replace('.', '_') try: recipe = Recipe(recipe_name) recipe = store.get(recipe) except NoRecipeError: bag = _check_bag('all', environ, user) recipe.set_recipe([ [u'TiddlyWeb', u''], [unicode(bag.name), unicode(_filter_string(name))], ]) recipe.desc = '%s twotes for %s' % (name, user) store.put(recipe) return recipe
def test_recipe_put(): """ put a recipe to disk and make sure it is there. """ recipe = Recipe("testrecipe") recipe.desc = "I enjoy being stored" recipe.set_recipe(recipe_list_string) store.put(recipe) if type(store.storage) != tiddlyweb.stores.text.Store: py.test.skip("skipping this test for non-text store") assert os.path.exists(expected_stored_filename) with open(expected_stored_filename) as f: content = f.read() if sys.version_info[0] < 3: assert content == expected_stored_content
def test_recipe_put(): """ put a recipe to disk and make sure it is there. """ recipe = Recipe('testrecipe') recipe.desc = 'I enjoy being stored' recipe.set_recipe(recipe_list_string) store.put(recipe) assert os.path.exists(expected_stored_filename), \ 'path %s should be created' \ % expected_stored_filename f = file(expected_stored_filename) content = f.read() assert content == expected_stored_content, \ 'stored content should be %s, got %s' \ % (expected_stored_content, content)
def patch_recipe(environ, start_response): """ PATCH a single recipe, which must exists, with format similar to what follows. Resetting recipe (the whole thing!), desc, or any policy constraint. {"recipe": [["testbag", "limit=1"]], "desc": "oh hi", "policy": {"read": ["frank"], "vroom": ["frank"], "write": ["ANY"]}} """ store = environ['tiddlyweb.store'] length, content_type = content_length_and_type(environ) if content_type != 'application/json': raise HTTP415('application/json required') recipe_name = get_route_value(environ, 'recipe_name') recipe = Recipe(recipe_name) try: recipe = store.get(recipe) except NoRecipeError: raise HTTP409('Unable to patch non-existent recipe') data = _read_input(environ, length) try: for key, value in data.iteritems(): if key == 'desc': recipe.desc = value elif key == 'policy': for constraint, rules in value.iteritems(): if constraint in Policy.attributes: setattr(recipe.policy, constraint, rules) elif key == 'recipe': recipe.set_recipe(value) except AttributeError, exc: raise HTTP400('Malformed recipe info: %s' % exc)
def post_createrecipe(environ, start_response): user = get_user_object(environ) store = environ["tiddlyweb.store"] recipe_name = environ["tiddlyweb.query"].get("recipe", [""])[0] bag_name = environ["tiddlyweb.query"].get("bag", [""])[0] publicity = environ["tiddlyweb.query"].get("publicity", [""])[0] description = environ["tiddlyweb.query"].get("description", [""])[0] if not bag_name or not recipe_name: raise HTTP400("missing data") recipe = Recipe(recipe_name) bag = Bag(bag_name) try: recipe = store.get(recipe) raise HTTP400("recipe exists") except NoRecipeError: pass try: bag = store.get(bag) try: bag.policy.allows(user, "read") except (UserRequiredError, ForbiddenError): raise HTTP400("bag not readable") except NoBagError: bag.policy.owner = user["name"] for constraint in ["read", "write", "create", "delete", "manage"]: setattr(bag.policy, constraint, [user["name"]]) store.put(bag) if publicity == "private": recipe.policy.read = [user["name"]] else: recipe.policy.read = [] recipe.policy.manage = [user["name"]] recipe.policy.owner = user["name"] recipe.desc = description recipe.set_recipe([("system", ""), (bag.name, "")]) store.put(recipe) raise HTTP303("%s/home" % server_base_url(environ))
def test_recipe_delete_from_store(): _cleanup() config = { "server_store": ["tiddlywebplugins.devstore", { "store_root": STORE_DIR }], "instance_tiddlers": {}, "root_dir": "" } env = { "tiddlyweb.config": config } store = Store(config["server_store"][0], config["server_store"][1], env) name = "foo" recipe = Recipe(name) recipe.desc = "lorem ipsum" store.put(recipe) recipe = Recipe(name) store.delete(recipe) recipe = Recipe(name) raises(NoRecipeError, "store.get(recipe)")
def test_recipe_put(): """ put a recipe to disk and make sure it is there. """ recipe = Recipe("testrecipe") recipe.desc = "I enjoy being stored" recipe.set_recipe(recipe_list_string) store.put(recipe) if type(store.storage) != tiddlyweb.stores.text.Store: py.test.skip("skipping this test for non-text store") assert os.path.exists(expected_stored_filename), "path %s should be created" % expected_stored_filename f = file(expected_stored_filename) content = f.read() assert content == expected_stored_content, "stored content should be %s, got %s" % ( expected_stored_content, content, )
def test_recipe_put(): """ put a recipe to disk and make sure it is there. """ recipe = Recipe('testrecipe') recipe.desc = 'I enjoy being stored' recipe.set_recipe(recipe_list_string) store.put(recipe) if type(store.storage) != tiddlyweb.stores.text.Store: py.test.skip('skipping this test for non-text store') assert os.path.exists(expected_stored_filename), \ 'path %s should be created' \ % expected_stored_filename f = file(expected_stored_filename) content = f.read() assert content == expected_stored_content, \ 'stored content should be %s, got %s' \ % (expected_stored_content, content)
def test_serialization(): _cleanup() config = { "server_store": ["tiddlywebplugins.devstore", { "store_root": STORE_DIR }], "instance_tiddlers": {}, "root_dir": "" } env = { "tiddlyweb.config": config } store = Store(config["server_store"][0], config["server_store"][1], env) name = "foo" recipe = Recipe(name) recipe.desc = "lorem ipsum" store.put(recipe) f = open("%s.recipe" % os.path.join(STORE_DIR, name)) actual = f.read() f.close() expected = """desc: lorem ipsum policy: {"read": [], "create": [], "manage": [], "accept": [], "write": [], "owner": null, "delete": []} """ assert actual == expected
def test_simple_get(): response, content = http.request("http://our_test_domain:8001/bags/place/tiddlers/one") assert response["status"] == "200" assert "etag" in response etag = response["etag"] response, content = http.request( "http://our_test_domain:8001/bags/place/tiddlers/one", headers={"If-None-Match": etag} ) assert response["status"] == "304" tiddler = Tiddler("one", "place") tiddler.text = "bye" store.put(tiddler) response, content = http.request( "http://our_test_domain:8001/bags/place/tiddlers/one", headers={"If-None-Match": etag} ) response, content = http.request("http://our_test_domain:8001/bags/place/tiddlers/one") assert response["status"] == "200" assert "etag" in response etag = response["etag"] response, content = http.request( "http://our_test_domain:8001/bags/place/tiddlers/one", headers={"If-None-Match": etag} ) assert response["status"] == "304" response, content = http.request( "http://our_test_domain:8001/bags/place/tiddlers/one", headers={"If-None-Match": etag, "Accept": "application/json"}, ) assert response["status"] == "200" response, content = http.request("http://our_test_domain:8001/bags/place/tiddlers") assert response["status"] == "200" etag = response["etag"] tiddler = Tiddler("one", "place") tiddler.text = "cow" store.put(tiddler) response, content = http.request("http://our_test_domain:8001/bags/place/tiddlers", headers={"If-None-Match": etag}) assert response["status"] == "200" assert response["etag"] != etag etag = response["etag"] response, content = http.request("http://our_test_domain:8001/bags/place/tiddlers", headers={"If-None-Match": etag}) assert response["status"] == "304" assert response["etag"] == etag response, content = http.request("http://our_test_domain:8001/bags/place/tiddlers?select=title:two") assert response["status"] == "200" etag = response["etag"] tiddler = Tiddler("one", "place") tiddler.text = "cow" store.put(tiddler) response, content = http.request( "http://our_test_domain:8001/bags/place/tiddlers?select=title:two", headers={"If-None-Match": etag} ) # this is a deep match hit, matching because it was the 'one' # tiddler that changed, not 'two' assert response["status"] == "304" assert response["etag"] == etag tiddler = Tiddler("two", "place") tiddler.text = "thief" store.put(tiddler) response, content = http.request( "http://our_test_domain:8001/bags/place/tiddlers?select=title:two", headers={"If-None-Match": etag} ) assert response["status"] == "200" # total etag miss assert response["etag"] != etag etag = response["etag"] response, content = http.request( "http://our_test_domain:8001/bags/place/tiddlers?select=title:two", headers={"If-None-Match": etag} ) assert response["status"] == "304" assert response["etag"] == etag response, content = http.request("http://our_test_domain:8001/search?q=two") assert response["status"] == "200" etag = response["etag"] tiddler = Tiddler("one", "place") tiddler.text = "cow" store.put(tiddler) response, content = http.request("http://our_test_domain:8001/search?q=two", headers={"If-None-Match": etag}) # this is a deep match hit, matching because it was the 'one' # tiddler that changed, not 'two' assert response["status"] == "304" assert response["etag"] == etag # cause a 200 to refresh cache response, content = http.request("http://our_test_domain:8001/search?q=two") assert response["status"] == "200" response, content = http.request("http://our_test_domain:8001/search?q=two", headers={"If-None-Match": etag}) # this is a cached match hit, matching because it was the 'one' # tiddler that changed, not 'two' assert response["status"] == "304" assert response["etag"] == etag # try a recipe response, content = http.request("http://our_test_domain:8001/recipes/plaice/tiddlers/two") assert response["status"] == "200" # total etag miss assert response["etag"] != etag etag = response["etag"] response, content = http.request( "http://our_test_domain:8001/recipes/plaice/tiddlers/two", headers={"If-None-Match": etag} ) assert response["status"] == "304" response, content = http.request("http://our_test_domain:8001/recipes/plaice/tiddlers") assert response["status"] == "200" # total etag miss etag = response["etag"] response, content = http.request( "http://our_test_domain:8001/recipes/plaice/tiddlers", headers={"If-None-Match": etag} ) assert response["status"] == "304" assert response["etag"] == etag response, content = http.request("http://our_test_domain:8001/recipes/plaice") assert response["status"] == "200" # total etag miss etag = response["etag"] response, content = http.request("http://our_test_domain:8001/recipes/plaice", headers={"If-None-Match": etag}) assert response["status"] == "304" assert response["etag"] == etag recipe = Recipe("plaice") recipe.desc = "oh how now" store.put(recipe) # changing desc changes etag response, content = http.request("http://our_test_domain:8001/recipes/plaice", headers={"If-None-Match": etag}) assert response["status"] == "200" # miss assert response["etag"] != etag # etag is different because desc changeD response, content = http.request("http://our_test_domain:8001/recipes") assert response["status"] == "200" # total etag miss etag = response["etag"] response, content = http.request("http://our_test_domain:8001/recipes", headers={"If-None-Match": etag}) assert response["status"] == "304" assert response["etag"] == etag recipe = Recipe("plaice") recipe.desc = "oh how now" store.put(recipe) response, content = http.request("http://our_test_domain:8001/recipes") assert response["status"] == "200" # total etag miss etag = response["etag"]
def new_wiki(environ, start_response): username = environ['tiddlyweb.usersign']['name'] if username == 'GUEST': raise UserRequiredError store = environ['tiddlyweb.store'] length = environ['CONTENT_LENGTH'] content = environ['wsgi.input'].read(int(length)) wikiname = cgi.parse_qs(content).get('wikiname', [''])[0] perms = cgi.parse_qs(content).get('perms', [''])[0] if wikiname: bag = Bag(wikiname) try: bag = store.get(bag) raise HTTP409('The bag already exists') except NoBagError: bag.desc = 'hello' bag.policy.owner = username bag.policy.manage = [username] if perms == 'closed': bag.policy.read = [username] bag.policy.write = [username] bag.policy.create = [username] bag.policy.delete = [username] if perms == 'authrw': bag.policy.read = ['ANY'] bag.policy.write = ['ANY'] bag.policy.create = ['ANY'] bag.policy.delete = ['ANY'] if perms == 'read': bag.policy.write = [username] bag.policy.create = [username] bag.policy.delete = [username] if perms == 'authw': bag.policy.write = ['ANY'] bag.policy.create = ['ANY'] bag.policy.delete = ['ANY'] store.put(bag) recipe = Recipe(wikiname) try: recipe = store.get(recipe) raise HTTP409('That recipe already exists') except NoRecipeError: recipe.desc = 'hello' recipe.policy.owner = username recipe.policy.manage = [username] recipe.set_recipe([[TIDDLYWEB_BAG, ''], [bag.name, '']]) store.put(recipe) user = User(username) note = '' try: user = store.get(user) note = user.note except NoUserError: pass note += '%s\n' % wikiname user.note = note store.put(user) raise HTTP302('%s/spowt/%s' % (server_base_url(environ), urllib.quote(username))) else: raise HTTP409('Missing form data')
def new_wiki(environ, start_response): username = environ['tiddlyweb.usersign']['name'] if username == 'GUEST': raise UserRequiredError store = environ['tiddlyweb.store'] wikiname = environ['tiddlyweb.query'].get('wikiname', [''])[0] perms = environ['tiddlyweb.query'].get('perms', [''])[0] if wikiname: bag = Bag(wikiname) try: bag = store.get(bag) raise HTTP409('The bag already exists') except NoBagError: bag.desc = 'hello' bag.policy.owner = username bag.policy.manage = [username] if perms == 'closed': bag.policy.read = [username] bag.policy.write = [username] bag.policy.create = [username] bag.policy.delete = [username] if perms == 'authrw': bag.policy.read = ['ANY'] bag.policy.write = ['ANY'] bag.policy.create = ['ANY'] bag.policy.delete = ['ANY'] if perms == 'read': bag.policy.write = [username] bag.policy.create = [username] bag.policy.delete = [username] if perms == 'authw': bag.policy.write = ['ANY'] bag.policy.create = ['ANY'] bag.policy.delete = ['ANY'] store.put(bag) recipe = Recipe(wikiname) try: reicpe = store.get(recipe) raise HTTP409('That recipe already exists') except NoRecipeError: recipe.desc = 'hello' recipe.policy.owner = username recipe.policy.manage = [username] recipe.set_recipe([[TIDDLYWEB_BAG, ''], [bag.name, '']]) store.put(recipe) user = User(username) note = '' try: user = store.get(user) note = user.note if not note: note = '' except NoUserError: pass note += '%s\n' % wikiname user.note = note store.put(user) raise HTTP302('%s/spowt2/%s' % (server_base_url(environ), urllib.quote(username))) else: raise HTTP409('Missing form data')