def test_json_recipe(): """ JSON serializer roundtrips. """ recipe = Recipe('other') recipe.set_recipe([['bagbuzz', '']]) recipe.policy.manage = ['a'] recipe.policy.read = ['b'] recipe.policy.create = ['c'] recipe.policy.delete = ['d'] recipe.policy.owner = 'e' serializer = Serializer('json') serializer.object = recipe string = serializer.to_string() other_recipe = Recipe('other') serializer.object = other_recipe serializer.from_string(string) assert recipe == other_recipe serializer.object = other_recipe other_string = serializer.to_string() assert string == other_string
def compare_tiddlers(rev1, rev2, format=None): """ compare two Tiddler instances """ serializer = Serializer("text") serializer.object = rev1 rev1 = serializer.to_string() serializer.object = rev2 rev2 = serializer.to_string() return diff(rev1, rev2, format)
def send_entity(environ, start_response, entity): """ Send a bag or recipe out HTTP, first serializing to the correct type. """ username = environ['tiddlyweb.usersign']['name'] try: serialize_type, mime_type = get_serialize_type(environ) serializer = Serializer(serialize_type, environ) serializer.object = entity content = serializer.to_string() except NoSerializationError: raise HTTP415('Content type %s not supported' % mime_type) etag_string = '"%s"' % (sha(_entity_etag(entity) + encode_name(username) + encode_name(mime_type)).hexdigest()) start_response("200 OK", [('Content-Type', mime_type), ('ETag', etag_string), ('Vary', 'Accept')]) if isinstance(content, basestring): return [content] else: return content
def _get_tiddler_content(environ, tiddler): """ Extract the content of the tiddler, either straight up if the content is not considered text, or serialized if it is """ config = environ['tiddlyweb.config'] default_serializer = config['default_serializer'] default_serialize_type = config['serializers'][default_serializer][0] serialize_type, mime_type = web.get_serialize_type(environ) extension = environ.get('tiddlyweb.extension') if not renderable(tiddler, environ): if (serialize_type == default_serialize_type or mime_type.startswith(tiddler.type) or extension == 'html'): mime_type = tiddler.type content = tiddler.text return content, mime_type serializer = Serializer(serialize_type, environ) serializer.object = tiddler try: content = serializer.to_string() except (TiddlerFormatError, NoSerializationError), exc: raise HTTP415(exc)
def test_generated_txt_string(): serializer = Serializer('text') serializer.object = tiddler string = serializer.to_string() assert string == expected_string assert '%s' % serializer == expected_string
def send_entity(environ, start_response, entity): """ Send a bag or recipe out HTTP, first serializing to the correct type. If the incoming etag matches, raise 304. """ etag_string = entity_etag(environ, entity) incoming_etag = environ.get('HTTP_IF_NONE_MATCH', None) if incoming_etag: if incoming_etag == etag_string: raise HTTP304(incoming_etag) try: serialize_type, mime_type = get_serialize_type(environ) serializer = Serializer(serialize_type, environ) serializer.object = entity content = serializer.to_string() except NoSerializationError: raise HTTP415('Content type %s not supported' % mime_type) start_response("200 OK", [('Content-Type', mime_type), ('Cache-Control', 'no-cache'), ('ETag', etag_string), ('Vary', 'Accept')]) if isinstance(content, basestring): return [content] else: return content
def get(environ, start_response): """ Get a representation in some serialization of a bag (the bag itself not the tiddlers within). """ bag_name = _determine_bag_name(environ) bag_name = web.handle_extension(environ, bag_name) bag = _get_bag(environ, bag_name, True) bag.policy.allows(environ['tiddlyweb.usersign'], 'manage') try: serialize_type, mime_type = web.get_serialize_type(environ) serializer = Serializer(serialize_type, environ) serializer.object = bag content = serializer.to_string() except NoSerializationError: raise HTTP415('Content type not supported: %s' % mime_type) start_response("200 Ok", [('Content-Type', mime_type), ('Vary', 'Accept')]) return [content]
def send_entity(environ, start_response, entity): """ Send a :py:class:`bag <tiddlyweb.model.bag.Bag>` or :py:class:`recipe <tiddlyweb.model.recipe.Recipe>` out over HTTP, first :py:class:`serializing <tiddlyweb.serializer.Serializer>` to the correct type. If an incoming ``Etag`` validates, raise a ``304`` response. """ etag_string = entity_etag(environ, entity) check_incoming_etag(environ, etag_string) try: serialize_type, mime_type = get_serialize_type(environ) serializer = Serializer(serialize_type, environ) serializer.object = entity content = serializer.to_string() except NoSerializationError: raise HTTP415('Content type %s not supported' % mime_type) start_response("200 OK", [('Content-Type', mime_type), ('Cache-Control', 'no-cache'), ('ETag', etag_string), ('Vary', 'Accept')]) if isinstance(content, basestring): return [content] else: return content
def post_request(environ, start_response): length = int(environ["CONTENT_LENGTH"]) post_content = environ["wsgi.input"].read(length) serializer = Serializer("json") # TODO: use content-type to determine serialization rev = Tiddler("untitled") # N.B.: Serializations need not contain title. serializer.object = rev serializer.from_string(post_content.decode("utf-8")) query = environ["tiddlyweb.query"] store = environ["tiddlyweb.store"] rev1_id = query.get("rev1", [None])[0] rev2_id = query.get("rev2", [None])[0] try: if not rev1_id: rev1 = rev rev2 = _get_tiddler(rev2_id, store) elif not rev2_id: rev1 = _get_tiddler(rev1_id, store) rev2 = rev else: raise HTTP400("ambiguous request") except AttributeError: raise HTTP400("missing revision parameter") format = query.get("format", [None])[0] content = compare_tiddlers(rev1, rev2, format) return _generate_response(content, environ, start_response)
def test_bag_to_html(): serializer = Serializer("html") serializer.object = bagfour html = serializer.to_string() assert html == expected_bag_html
def _process_request_body(environ, tiddler): """ Read request body to set tiddler content. If a serializer exists for the content type, use it, otherwise treat the content as binary or pseudo-binary tiddler. """ length, content_type = content_length_and_type(environ) content = read_request_body(environ, length) try: try: serialize_type = get_serialize_type(environ)[0] serializer = Serializer(serialize_type, environ) # Short circuit de-serialization attempt to avoid # decoding content multiple times. if hasattr(serializer.serialization, 'as_tiddler'): serializer.object = tiddler try: serializer.from_string(content.decode('utf-8')) except TiddlerFormatError as exc: raise HTTP400('unable to put tiddler: %s' % exc) else: raise NoSerializationError() except NoSerializationError: tiddler.type = content_type if pseudo_binary(tiddler.type): tiddler.text = content.decode('utf-8') else: tiddler.text = content except UnicodeDecodeError as exc: raise HTTP400('unable to decode tiddler, utf-8 expected: %s' % exc)
def _get_tiddler_content(environ, tiddler): """ Extract the content of the tiddler, either straight up if the content is not considered text, or serialized if it is. """ config = environ['tiddlyweb.config'] default_serializer = config['default_serializer'] default_serialize_type = config['serializers'][default_serializer][0] serialize_type, mime_type = get_serialize_type(environ) extension = environ.get('tiddlyweb.extension') serialized = False # If this is a tiddler with a CANONICAL_URI_FIELD redirect # there unless we are requesting a json form if (CANONICAL_URI_FIELD in tiddler.fields and not CANONICAL_URI_PASS_TYPE in mime_type): raise HTTP302(tiddler.fields[CANONICAL_URI_FIELD]) if not renderable(tiddler, environ): if (serialize_type == default_serialize_type or mime_type.startswith(tiddler.type) or extension == 'html'): mime_type = tiddler.type content = tiddler.text return content, mime_type, serialized serializer = Serializer(serialize_type, environ) serializer.object = tiddler try: content = serializer.to_string() serialized = True except (TiddlerFormatError, NoSerializationError) as exc: raise HTTP415(exc) return content, mime_type, serialized
def send_entity(environ, start_response, entity): """ Send a bag or recipe out HTTP, first serializing to the correct type. """ username = environ['tiddlyweb.usersign']['name'] try: serialize_type, mime_type = get_serialize_type(environ) serializer = Serializer(serialize_type, environ) serializer.object = entity content = serializer.to_string() except NoSerializationError: raise HTTP415('Content type %s not supported' % mime_type) etag_string = '"%s"' % (sha( _entity_etag(entity) + encode_name(username) + encode_name(mime_type)).hexdigest()) start_response("200 OK", [('Content-Type', mime_type), ('ETag', etag_string), ('Vary', 'Accept')]) if isinstance(content, basestring): return [content] else: return content
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 test_bad_string_raises(): serializer = Serializer('text') foobar = Tiddler('foobar') serializer.object = foobar with pytest.raises(TiddlerFormatError): serializer.from_string(bad_string)
def test_generated_text(): serializer = Serializer("text") serializer.object = recipe string = serializer.to_string() assert string == expected_string assert "%s" % serializer == expected_string
def test_html_attribute_escape_with_bag(): tiddler = Tiddler('escape "double" quotes in tiddler field values') tiddler.bag = 'foo "bar" baz' tiddler.modifier = 'Chris "sensei" Dent' tiddler.tags = ["foo", 'xxx "yyy" zzz'] tiddler.fields["custom"] = u"""lorem 'ipsum' dolor "sit" amet""" tiddler.text = '' serializer = Serializer('tiddlywebwiki.serialization', environ) serializer.object = tiddler string = serializer.to_string() assert ('title="escape "double" quotes in tiddler field values"' in string) assert ('server.title="escape "double" quotes in tiddler ' 'field values"' in string) assert 'bag="foo "bar" baz"' in string assert 'server.workspace="bags/foo "bar" baz"' in string assert 'modifier="Chris "sensei" Dent"' in string assert 'creator="Chris "sensei" Dent"' in string assert 'tags="foo [[xxx "yyy" zzz]]"' in string assert '''custom="lorem 'ipsum' dolor "sit" amet"''' in string # single tiddler's browse link is that tiddler in its bag assert ('you may still <a href="/bags/foo%20%22bar%22%20baz/tiddlers/' 'escape%20%22double%22%20quotes%20in%20tiddler%20field%20' 'values">browse' in string)
def import_plugin(bag, url): """ Import one plugin, at svn url, into bag, retrieving both the .js and .js.meta files. If there is no meta file, then set title and tags to something appropriate before de-serializing. """ meta_url = "%s.meta" % url plugin_content = get_url(url) try: meta_content = _get_url(meta_url) except HTTPError: meta_content = "title: %s\ntags: systemConfig\n" % _strip_extension(url, ".js").split("/")[-1] title = [line for line in meta_content.split("\n") if line.startswith("title:")][0] title = title.split(":", 1)[1].lstrip().rstrip() tiddler_meta = "\n".join([line for line in meta_content.split("\n") if not line.startswith("title:")]) tiddler_meta.rstrip() tiddler_text = "%s\n\n%s" % (tiddler_meta, plugin_content) tiddler = Tiddler(title, bag) serializer = Serializer("text") serializer.object = tiddler serializer.from_string(tiddler_text) _store().put(tiddler)
def put(environ, start_response): """ Put a bag to the server, meaning the description and policy of the bag, if policy allows. """ bag_name = web.get_route_value(environ, 'bag_name') bag_name = web.handle_extension(environ, bag_name) bag = Bag(bag_name) store = environ['tiddlyweb.store'] length = environ['CONTENT_LENGTH'] usersign = environ['tiddlyweb.usersign'] try: bag = store.get(bag) bag.policy.allows(usersign, 'manage') except NoBagError: create_policy_check(environ, 'bag', usersign) try: serialize_type = web.get_serialize_type(environ)[0] serializer = Serializer(serialize_type, environ) serializer.object = bag content = environ['wsgi.input'].read(int(length)) serializer.from_string(content.decode('utf-8')) bag.policy.owner = usersign['name'] _validate_bag(environ, bag) store.put(bag) except BagFormatError, exc: raise HTTP400('unable to put bag: %s' % exc)
def _get_tiddler_content(environ, tiddler): """ Extract the content of the tiddler, either straight up if the content is not considered text, or serialized if it is. """ config = environ['tiddlyweb.config'] default_serializer = config['default_serializer'] default_serialize_type = config['serializers'][default_serializer][0] serialize_type, mime_type, accept = get_serialize_type(environ, accept_type=True) extension = environ.get('tiddlyweb.extension') serialized = False # If this is a tiddler with a CANONICAL_URI_FIELD redirect # there unless we are requesting a json form if (CANONICAL_URI_FIELD in tiddler.fields and CANONICAL_URI_PASS_TYPE not in mime_type): raise HTTP302(tiddler.fields[CANONICAL_URI_FIELD]) if not renderable(tiddler, environ): if (serialize_type == default_serialize_type or accept.startswith(tiddler.type) or extension == 'html'): mime_type = tiddler.type content = tiddler.text return content, mime_type, serialized serializer = Serializer(serialize_type, environ) serializer.object = tiddler try: content = serializer.to_string() serialized = True except (TiddlerFormatError, NoSerializationError) as exc: raise HTTP415(exc) return content, mime_type, serialized
def put(environ, start_response): """ Put a bag to the server, meaning the description and policy of the bag, if policy allows. """ bag_name = web.get_route_value(environ, 'bag_name') bag_name = web.handle_extension(environ, bag_name) bag = Bag(bag_name) store = environ['tiddlyweb.store'] length, _ = web.content_length_and_type(environ) usersign = environ['tiddlyweb.usersign'] try: bag = store.get(bag) bag.policy.allows(usersign, 'manage') except NoBagError: create_policy_check(environ, 'bag', usersign) try: serialize_type = web.get_serialize_type(environ)[0] serializer = Serializer(serialize_type, environ) serializer.object = bag content = web.read_request_body(environ, length) serializer.from_string(content.decode('utf-8')) bag.policy.owner = usersign['name'] _validate_bag(environ, bag) store.put(bag) except BagFormatError, exc: raise HTTP400('unable to put bag: %s' % exc)
def put(environ, start_response): """ Put a bag to the server, meaning the description and policy of the bag, if policy allows. """ bag_name = _determine_bag_name(environ) bag_name = web.handle_extension(environ, bag_name) bag = Bag(bag_name) store = environ["tiddlyweb.store"] length = environ["CONTENT_LENGTH"] usersign = environ["tiddlyweb.usersign"] try: bag = store.get(bag) bag.policy.allows(usersign, "manage") except NoBagError: create_policy_check(environ, "bag", usersign) try: serialize_type = web.get_serialize_type(environ)[0] serializer = Serializer(serialize_type, environ) serializer.object = bag content = environ["wsgi.input"].read(int(length)) serializer.from_string(content.decode("utf-8")) bag.policy.owner = usersign["name"] _validate_bag(environ, bag) store.put(bag) except BagFormatError, exc: raise HTTP400("unable to put bag: %s" % exc)
def test_generated_text(): serializer = Serializer('text') serializer.object = recipe string = serializer.to_string() assert string == expected_string assert '%s' % serializer == expected_string
def test_tiddler_from_json(): serializer = Serializer('json') tiddler = Tiddler('test tiddler') serializer.object = tiddler serializer.from_string(expected_json_string) assert tiddler.title == 'test tiddler' assert tiddler.text == "Hello, I'm the content."
def test_generated_html(): serializer = Serializer('html') recipe.desc = 'Courage of Bags' serializer.object = recipe string = serializer.to_string() assert expected_html_string in string assert expected_html_string in '%s' % serializer
def test_tiddler_fields_as_text(): tiddler = Tiddler('feebles', bag='bag0') tiddler = store.get(tiddler) serializer = Serializer('text') serializer.object = tiddler text_of_tiddler = serializer.to_string() assert 'field1: value1\n' in text_of_tiddler assert 'field2: value2\n' in text_of_tiddler
def test_unicode_tiddler_to_csv(): expected_string = 'title,text,modified,created,modifier,creator,revision,bag,tags,two\r\nbar,Lorem Ipsum Dolor Sit \xe2\x99\xa5,20120202000000,20120202000000,alice,alice,0,,[[foo baz]] biz bix,2\r\n' serializer = Serializer('tiddlywebplugins.csv', environ=environ) tiddler = [t for t in tiddlers if t.title == 'bar'][0] serializer.object = tiddler string = serializer.to_string() assert string == expected_string
def test_tiddler_to_csv(): expected_string = 'title,text,modified,created,modifier,creator,revision,bag,tags,one\r\nfoo,Hello There!,20120202000000,20120202000000,bob,bob,0,,foo bar baz,1\r\n' serializer = Serializer('tiddlywebplugins.csv', environ=environ) tiddler = [t for t in tiddlers if t.title == 'foo'][0] serializer.object = tiddler string = serializer.to_string() assert string == expected_string
def test_generated_html(): serializer = Serializer("html") recipe.desc = "Courage of Bags" serializer.object = recipe string = serializer.to_string() assert expected_html_string in string assert expected_html_string in "%s" % serializer
def test_server_etag(): tiddler = Tiddler('Foo', 'Alpha') serializer = Serializer('tiddlywebwiki.serialization', environ) serializer.object = tiddler string = serializer.to_string() tiddler = _extract_tiddler('Foo', string) assert r'''server.etag=""Alpha/Foo/''' in tiddler
def process_tid_tiddler(tiddler, content): """ Deserialize a tid. """ serializer = Serializer("text") serializer.object = tiddler serializer.from_string(content) return tiddler
def test_generated_json_string(): serializer = Serializer('json') serializer.object = tiddler string = serializer.to_string() info = simplejson.loads(string) assert info['title'] == 'test tiddler' assert info['text'] == "Hello, I'm the content."
def test_generated_json_string(): serializer = Serializer("json") serializer.object = tiddler string = serializer.to_string() info = simplejson.loads(string) assert info["title"] == "test tiddler" assert info["text"] == "Hello, I'm the content."
def test_tiddler_html_encode(): serializer = Serializer('html') tiddler = Tiddler('jeremy found a bug') tiddler.bag = u'foo' tiddler.text = u'"Hello." I\'m > than 5 & < you.' serializer.object = tiddler string = serializer.to_string() assert '"Hello." I\'m > than 5 & < you.' in string
def _put(entity, content, serialization): """ Put entity to store, by serializing content using the named serialization. """ serializer = Serializer(serialization) serializer.object = entity serializer.from_string(content) _store().put(entity)
def test_tiddler_fields_as_json(): tiddler = Tiddler('feebles', bag='bag0') tiddler = store.get(tiddler) serializer = Serializer('json') serializer.object = tiddler json_string = serializer.to_string() tiddler_info = simplejson.loads(json_string) assert tiddler_info['fields']['field1'] == 'value1' assert tiddler_info['fields']['field2'] == 'value2' assert tiddler_info['bag'] == 'bag0' tiddler = Tiddler('new feebles', bag='bag0') serializer.object = tiddler serializer.from_string(json_string) assert tiddler.fields['field1'] == 'value1' assert tiddler.fields['field2'] == 'value2' assert tiddler.bag == 'bag0'
def test_tiddler_fields_as_html(): tiddler = Tiddler('feebles', bag='bag0') tiddler = store.get(tiddler) serializer = Serializer('html') serializer.object = tiddler wiki_string = serializer.to_string() assert 'field1="value1"' in wiki_string assert 'field2="value2"' in wiki_string assert 'title="feebles"' in wiki_string
def save_tiddler(store, tiddler): title = tiddler['title'] bag = tiddler['bag'] tiddler_json = simplejson.dumps(tiddler) tid = Tiddler(title) s = Serializer('json') s.object = tid s.from_string(tiddler_json) tid.bag = bag store.put(tid)
def test_generate_json(): serializer = Serializer('json') bagfour.desc = 'a tasty little bag' bagfour.policy.manage = ['NONE'] serializer.object = bagfour string = serializer.to_string() json = simplejson.loads(string) assert json['policy']['manage'] == ['NONE'] assert json['desc'] == 'a tasty little bag'
def test_wrong_class(): class Foo(object): pass foo = Foo() serializer = Serializer('text') serializer.object = foo string = 'haha' py.test.raises(AttributeError, 'serializer.to_string()') py.test.raises(AttributeError, 'serializer.from_string(string)')
def _from_text(title, content): """ Generates a tiddler from an RFC822-style string This corresponds to TiddlyWeb's text serialization of TiddlerS. """ tiddler = Tiddler(title) serializer = Serializer('text') serializer.object = tiddler serializer.from_string(content) return tiddler
def test_generated_text(): serializer = Serializer('text') serializer.object = recipe string = serializer.to_string() assert string == expected_string, \ 'serialized recipe looks like we expect. should be %s, got %s' \ % (expected_string, string) assert '%s' % serializer == expected_string, \ 'serializer goes to string as expected_string'
def test_simple_recipe(): recipe = Recipe('other') recipe.set_recipe([('bagbuzz', '')]) recipe.policy.manage = ['a'] recipe.policy.read = ['b'] recipe.policy.create = ['c'] recipe.policy.delete = ['d'] recipe.policy.owner = 'e' serializer = Serializer('text') serializer.object = recipe string = serializer.to_string() new_recipe = Recipe('other') serializer.object = new_recipe serializer.from_string(string) assert recipe == new_recipe, 'recipe and new_recipe have equality' recipe = Recipe('other') recipe.set_recipe([('bagboom', '')]) assert recipe != new_recipe, 'modified recipe not equal new_recipe'
def test_json_to_bag(): serializer = Serializer('json') json_string = simplejson.dumps(dict(policy=dict(read=['user1'], manage=['NONE']), desc='simply the best')) newbag = Bag('bagho') serializer.object = newbag serializer.from_string(json_string) assert newbag.name == 'bagho' assert newbag.policy.read == ['user1'] assert newbag.policy.manage == ['NONE'] assert newbag.desc == 'simply the best'
def test_generated_json_string(): serializer = Serializer('json', environ={'tiddlyweb.config': config}) serializer.object = tiddler string = serializer.to_string() info = simplejson.loads(string) assert info['title'] == 'test tiddler' assert info['text'] == "Hello, I'm the content." assert info['uri'] == '%s://%s:%s/bags/snoop/tiddlers/test%%20tiddler' % ( config['server_host']['scheme'], config['server_host']['host'], config['server_host']['port'])
def test_old_text(): """ Send in text without a description and make sure we are able to accept it. """ recipe = Recipe('other') serializer = Serializer('text') serializer.object = recipe serializer.from_string(no_desc) output = serializer.to_string() assert output == expected_string
def test_content_type(): tiddler = Tiddler('Foo', 'Alpha') serializer = Serializer('tiddlywebwiki.serialization', environ) serializer.object = tiddler string = serializer.to_string() tiddler = _extract_tiddler('Foo', string) assert r'''server.content-type=""''' in tiddler tiddler = Tiddler('_Foo', 'Alpha') tiddler.type = 'None' # possible weirdness in the text serialization and some stores serializer = Serializer('tiddlywebwiki.serialization', environ) serializer.object = tiddler string = serializer.to_string() tiddler = _extract_tiddler('_Foo', string) assert r'''server.content-type=""''' in tiddler tiddler = Tiddler('Bar', 'Bravo') tiddler.type = 'text/x-custom' tiddler.text = 'lorem ipsum dolor sit amet' serializer = Serializer('tiddlywebwiki.serialization', environ) serializer.object = tiddler string = serializer.to_string() tiddler = _extract_tiddler('Bar', string) assert r'''server.content-type="text/x-custom"''' in tiddler assert r'''<pre>lorem ipsum dolor sit amet</pre>''' in tiddler tiddler = Tiddler('Baz', 'Charlie') tiddler.type = 'application/x-custom' tiddler.text = 'lorem ipsum dolor sit amet' serializer = Serializer('tiddlywebwiki.serialization', environ) serializer.object = tiddler string = serializer.to_string() tiddler = _extract_tiddler('Baz', string) tiddler_text = tiddler.split("<pre>", 1)[1].split("</pre>", 1)[0].strip() assert r'''server.content-type="application/x-custom"''' in tiddler