Skip to content

Instantly share code, notes, and snippets.

@psd
Created December 7, 2009 15:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save psd/250854 to your computer and use it in GitHub Desktop.
Save psd/250854 to your computer and use it in GitHub Desktop.
XML TiddlyWeb serializer
"""
XML TiddlyWeb serializer.
"""
from tiddlywebplugins.simplerizer import Simplerization as SerializationInterface
from tiddlywebplugins.xml.marshaller import dumps, loads
__version__ = "0.1"
def init(config):
# register serializer
content_type = "text/xml"
config["extension_types"]["xml"] = content_type
config["serializers"][content_type] = [__name__, "text/xml; charset=UTF-8"]
class Serialization(SerializationInterface):
"""Access TiddlyWeb resources using the XML representation."""
def dump(self, object):
"""Dump a dictionary object to a XML string."""
return dumps(object)
def load(self, input_string):
"""Load a dictionary object from a XML string."""
return loads(input_string)
simple tiddlyweb.xml twinstance
$twanager server
ERROR: ImportError: No module named marshal
addrole: Add a role to an existing user. <username> [role] [role] [role]
adduser: Add or update a user to the database: <username> <password> [[role] [role] ...]
bag: Create or update a bag with the json text on stdin: <bag>
imwiki: Import tiddlers from a Tiddlywiki document into a bag: <bag> <filename>
info: Display info about TiddlyWeb.
lbags: List all the bags on the system.
lrecipes: List all the recipes on the system.
ltiddlers: List all the tiddlers on the system. [<bag> <bag> <bag>] to limit.
lusers: List all the users on the system
recipe: Create or update a recipe with the recipe text on stdin: <recipe>
server: Start the server using config settings. Provide <host name or IP number> <port> to override.
tiddler: Import a single tiddler into an existing bag from stdin: <bag> <tiddler>
twimport: Import one or more plugins, tiddlers or recipes in Cook format: <bag> <URI>
update: Update all instance_tiddlers in the current instance.
usage: List this help
userpass: Change the password of an existing user. <username> <password>
"""
adjusts module path to account for virtual namespace
This is required primarily for testing.
"""
import sys
import os
VIRTUAL_NAMESPACE = "tiddlywebplugins"
local_package = os.path.abspath(VIRTUAL_NAMESPACE)
sys.modules[VIRTUAL_NAMESPACE].__dict__["__path__"].insert(0, local_package)
"""
Specialization of pyxml's marshaling to apply
more document style markup and handle Unicode.
"""
from __future__ import absolute_import
import os
os.environ['PY_USE_XMLPLUS'] = '1'
from xml.marshal import generic
class Marshaller(generic.Marshaller):
tag_unicode = 'unicode'
def m_unicode(self, value, dict):
name = self.tag_unicode
L = ['<' + name + '>']
s = value.encode('utf-8')
if '&' in s or '>' in s or '<' in s:
s = s.replace('&', '&amp;')
s = s.replace('<', '&lt;')
s = s.replace('>', '&gt;')
L.append(s)
L.append('</' + name + '>')
return L
class Unmarshaller(generic.Unmarshaller):
def __init__(self):
self.unmarshal_meth['unicode'] = ('um_start_unicode','um_end_unicode')
generic.Unmarshaller.__init__(self)
um_start_unicode = generic.Unmarshaller.um_start_generic
def um_end_unicode(self, name):
ds = self.data_stack
ds[-1] = ''.join(ds[-1])
self.accumulating_chars = 0
def dumps(input_string):
return Marshaller().dumps(input_string)
def loads(object):
return Unmarshaller().loads(object)
"""
TiddlyWeb serializer base class.
"""
from tiddlyweb.model.bag import Bag
from tiddlyweb.model.policy import Policy
from tiddlyweb.serializations import SerializationInterface
__version__ = "0.1"
class Simplerization(SerializationInterface):
"""Access TiddlyWeb resources using a generic representation."""
def dump(self, object):
"""Dumps a dictionary object to a string."""
raise NoSerializationError
def load(self, input_string):
"""Loads a dictionary object from a string."""
raise NoSerializationError
def __init__(self, environ=None):
SerializationInterface.__init__(self, environ)
self._bag_perms_cache = {}
def list_recipes(self, recipes):
"""Creates representation of a list of recipe names."""
return self.dump([recipe.name for recipe in recipes])
def list_bags(self, bags):
"""Creates representation of a list of bag names."""
return self.dump([bag.name for bag in bags])
def list_tiddlers(self, bag):
"""Creates representation of the list of tiddlers in a bag."""
return self.dump([self._tiddler_dict(tiddler) for
tiddler in bag.gen_tiddlers()])
def recipe_as(self, recipe):
"""Creates representation of a recipe."""
policy_dict = self._get_policy(recipe)
info = dict(desc=recipe.desc, policy=policy_dict, recipe=recipe.get_recipe())
return self.dump(info)
def tiddler_as(self, tiddler):
tiddler_dict = self._tiddler_dict(tiddler)
if (tiddler.type and tiddler.type != 'None' and not
tiddler.type.startswith('text/')):
tiddler_dict['text'] = b64encode(tiddler.text)
else:
tiddler_dict['text'] = tiddler.text
return self.dump(tiddler_dict)
def bag_as(self, bag):
"""Creates representation of a bag."""
policy_dict = self._get_policy(bag)
info = dict(desc=bag.desc, policy=policy_dict)
return self.dump(info)
def as_recipe(self, recipe, input_string):
"""Creates a recipe from representation."""
info = self.load(input_string)
recipe.set_recipe(info.get('recipe', []))
recipe.desc = info.get('desc', '')
self._set_policy(info, recipe)
return recipe
def as_bag(self, bag, input_string):
"""Creates a bag from a representation."""
info = self.load(input_string)
bag.desc = info.get('desc', '')
self._set_policy(info, bag)
return bag
def as_tiddler(self, tiddler, input_string):
"""Creates a tiddler from a representation."""
dict_from_input = self.load(input_string)
accepted_keys = ['created', 'modified', 'modifier', 'tags', 'fields',
'text', 'type']
for key, value in dict_from_input.iteritems():
if value is not None and key in accepted_keys:
setattr(tiddler, key, value)
if (tiddler.type and tiddler.type != 'None' and not
tiddler.type.startswith('text/')):
tiddler.text = b64decode(tiddler.text)
return tiddler
def _get_policy(self, object):
"""Generates a policy dictionary for an object."""
policy = object.policy
policy_dict = {}
for key in Policy.attributes:
policy_dict[key] = getattr(policy, key)
return policy_dict
def _set_policy(self, info, object):
"""Applies a policy dictionary to an object."""
if info.get('policy', {}):
object.policy = Policy()
for key, value in info['policy'].object():
object.policy.__setattr__(key, value)
def _tiddler_dict(self, tiddler):
"""
Creates a dictionary of header tiddler fields and values
under the control of the query_string option 'fat' which
when '1' also includes the tiddler content.
"""
unwanted_keys = ['text', 'store']
wanted_keys = [attribute for attribute in tiddler.slots if
attribute not in unwanted_keys]
wanted_info = {}
for attribute in wanted_keys:
wanted_info[attribute] = getattr(tiddler, attribute, None)
wanted_info['permissions'] = self._tiddler_permissions(tiddler)
try:
fat = self.environ['tiddlyweb.query'].get('fat', [None])[0]
if fat:
wanted_info['text'] = tiddler.text
except KeyError:
pass # tiddlyweb.query is not there
return dict(wanted_info)
def _tiddler_permissions(self, tiddler):
"""
Makes a list of the permissions the current user has
to access this tiddler.
"""
def _read_bag_perms(environ, tiddler):
"""
Reads the permissions for the bag containing
this tiddler.
"""
perms = []
if 'tiddlyweb.usersign' in environ:
store = tiddler.store
if store:
bag = Bag(tiddler.bag)
bag.skinny = True
bag = store.get(bag)
perms = bag.policy.user_perms(
environ['tiddlyweb.usersign'])
return perms
bag_name = tiddler.bag
perms = []
if len(self._bag_perms_cache):
if bag_name in self._bag_perms_cache:
perms = self._bag_perms_cache[bag_name]
else:
perms = _read_bag_perms(self.environ, tiddler)
self._bag_perms_cache[bag_name] = perms
return perms
# A basic configuration.
# Run 'pydoc tiddlyweb.config' for details on configuration items.
import mangler
config = {
'system_plugins': ['tiddlywebwiki', 'tiddlywebplugins.status', 'differ', 'tiddlywebplugins.xml'],
'secret': '2bb70de5a2817098b4431b2abd6d2cafb7ebd0f3',
'twanager_plugins': ['tiddlywebwiki']
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment