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 profile_listing_tiddlers(): store = Store('text', environ=environ) environ['tiddlyweb.store'] = store bag = Bag('profiler') bag.skinny = True store.get(bag) print 'filter', time() filter_string = 'select=tag:100' filters, leftovers = parse_for_filters(filter_string, environ) tiddlers = control.filter_tiddlers_from_bag(bag, filters) print 'tmp bag', time() tmp_bag = Bag('tmp_bag', tmpbag=True) tmp_bag.add_tiddlers(tiddlers) print 'output', time() print[tiddler.title for tiddler in control.get_tiddlers_from_bag(tmp_bag)] #print 'serializer', time() #serializer = Serializer('wiki', environ) #print 'wikify', time() #output = serializer.list_tiddlers(tmp_bag) print 'done', time()
def test_create_bag_policies(self): spawn(instance_dir, config, instance_module) os.chdir(instance_dir) store = Store(config['server_store'][0], config['server_store'][1], environ=self.env) bag = Bag('system') system_policy = store.get(bag).policy bag = Bag('common') common_policy = store.get(bag).policy assert system_policy.read == [] assert system_policy.write == ['R:ADMIN'] assert system_policy.create == ['R:ADMIN'] assert system_policy.manage == ['R:ADMIN'] assert system_policy.accept == ['R:ADMIN'] assert system_policy.delete == ['R:ADMIN'] assert common_policy.read == [] assert common_policy.write == [] assert common_policy.create == [] assert common_policy.manage == ['R:ADMIN'] assert common_policy.accept == [] assert common_policy.delete == [] os.chdir('..')
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_request(environ, start_response): query = environ["tiddlyweb.query"] tiddler_count = query.get("tiddlers", [default_tiddler_count])[0] store = Storage("datagenerator", {}) bag = Bag(str(tiddler_count)) bag = store.get(bag) # populate tiddlers in bag for tiddler in bag.list_tiddlers(): store.get(tiddler) return send_tiddlers(environ, start_response, bag)
def test_tiddler_get(): 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'
def test_get_tiddler_revision(): _cleanup() config = { "server_store": ["tiddlywebplugins.devstore", { "store_root": STORE_DIR }], "instance_tiddlers": { "myBag": ["%s/alpha/index.recipe" % REPO_DIR] }, "root_dir": "" } env = { "tiddlyweb.config": config } store = Store(config["server_store"][0], config["server_store"][1], env) tiddler = Tiddler("lorem") tiddler.bag = "myBag" t = store.get(tiddler) assert t.title == "lorem" assert t.bag == "myBag" assert t.revision == 1 assert t.tags == [] assert t.creator == "FND" assert t.modifier == "FND" assert len(t.created) == 14 assert len(t.modified) == 14 assert t.created == t.modified assert t.text == "lorem ipsum" tiddler = Tiddler("hello world") tiddler.bag = "myBag" tiddler.tags = ["foo", "bar"] tiddler.modifier = "FND" tiddler.text = "lorem ipsum" store.put(tiddler) tiddler = Tiddler("hello world") tiddler.bag = "myBag" t = store.get(tiddler) assert t.title == "hello world" assert t.bag == "myBag" assert t.revision == 1 assert t.tags == ["foo", "bar"] assert t.creator == "FND" assert t.modifier == "FND" assert len(t.created) == 14 assert len(t.modified) == 14 assert t.created == t.modified assert t.text == "lorem ipsum"
def test_bag_get(): store = Store('tiddlywebplugins.mappingsql', {'db_config': 'sqlite:///test.db'}, {'tiddlyweb.config': config}) bag = Bag('avox') assert len(bag.list_tiddlers()) == 0 bag = store.get(bag) assert len(bag.list_tiddlers()) == 1 assert "NONE" in bag.policy.write
def test_bag_get(): store = Store("tiddlywebplugins.mappingsql", {"db_config": "sqlite:///test.db"}, {"tiddlyweb.config": config}) bag = Bag("avox") assert len(list(store.list_bag_tiddlers(bag))) == 1 bag = store.get(bag) assert len(list(store.list_bag_tiddlers(bag))) == 1 assert "NONE" in bag.policy.write
def profile_listing_tiddlers(): store = Store('text', environ=environ) environ['tiddlyweb.store'] = store bag = Bag('profiler') bag.skinny = True store.get(bag) print 'filter', time() filter_string = 'select=tag:100' filters, leftovers = parse_for_filters(filter_string, environ) tiddlers = control.filter_tiddlers_from_bag(bag, filters) print 'tmp bag', time() tmp_bag = Bag('tmp_bag', tmpbag=True) tmp_bag.add_tiddlers(tiddlers) print 'output', time() print [tiddler.title for tiddler in control.get_tiddlers_from_bag(tmp_bag)]
def test_put_tiddler_to_store(): _cleanup() config = { "server_store": ["tiddlywebplugins.devstore", { "store_root": STORE_DIR }], "instance_tiddlers": { "myBag": ["%s/alpha/index.recipe" % REPO_DIR] }, "root_dir": "" } env = { "tiddlyweb.config": config } store = Store(config["server_store"][0], config["server_store"][1], env) tiddler = Tiddler("lorem") tiddler.bag = "myBag" store.put(tiddler) tiddler_path = os.path.join(STORE_DIR, tiddler.bag, "%s.tid" % tiddler.title) assert os.path.exists(tiddler_path) tiddler = Tiddler("foo bar") tiddler.bag = "myBag" store.put(tiddler) tiddler_path = os.path.join(STORE_DIR, "myBag", "foo%20bar.tid") assert os.path.exists(tiddler_path) assert store.get(tiddler).title == "foo bar" # XXX: testing get operation here for convenience bag = Bag("myBag") try: assert "foo bar" in [t.title for t in store.list_bag_tiddlers(bag)] except AttributeError: # TiddlyWeb 1.0 has no list_bag_tiddlers method pass tiddler = Tiddler("foo/bar") tiddler.bag = "myBag" store.put(tiddler) tiddler_path = os.path.join(STORE_DIR, "myBag", "foo%2Fbar.tid") assert os.path.exists(tiddler_path) assert store.get(tiddler).title == "foo/bar"
class TestInstance(object): def setup_method(self, module): env = { 'tiddlyweb.config': config } self.store = Store(config['server_store'][0], config['server_store'][1], environ=env) def teardown_method(self, module): os.chdir('..') rmtree(instance_dir) def test_create_tiddlywebwiki_instance(self): spawn(instance_dir, config, instance_module) contents = _get_file_contents('../%s/tiddlywebconfig.py' % instance_dir) assert "'system_plugins': ['tiddlywebwiki']" in contents assert "'twanager_plugins': ['tiddlywebwiki']" in contents def test_create_bag_policies(self): spawn(instance_dir, config, instance_module) bag = Bag('system') system_policy = self.store.get(bag).policy bag = Bag('common') common_policy = self.store.get(bag).policy assert system_policy.read == [] assert system_policy.write == ['R:ADMIN'] assert system_policy.create == ['R:ADMIN'] assert system_policy.manage == ['R:ADMIN'] assert system_policy.accept == ['R:ADMIN'] assert system_policy.delete == ['R:ADMIN'] assert common_policy.read == [] assert common_policy.write == [] assert common_policy.create == [] assert common_policy.manage == ['R:ADMIN'] assert common_policy.accept == [] assert common_policy.delete == []
def profile_listing_tiddlers(): store = Store('text', environ=environ) bag = Bag('profiler') store.get(bag) print 'filter', time() #filter_string = '[sort[modified]]' filter_string = '' tiddlers = control.filter_tiddlers_from_bag(bag, filter_string) print 'tmp bag', time() tmp_bag = Bag('tmp_bag', tmpbag=True) tmp_bag.add_tiddlers(tiddlers) #print 'output', time() #print ['.' for tiddler in control.get_tiddlers_from_bag(tmp_bag)] print 'serializer', time() serializer = Serializer('wiki', environ) print 'wikify', time() output = serializer.list_tiddlers(tmp_bag) print 'done', time()
def update_store(self): """ prepopulates/updates store contents by (re)importing instance_tiddlers """ cwd = os.getcwd() os.chdir(self.root) store = get_store(self.init_config) for package_name in self.init_config['instance_pkgstores']: source_store = Store('tiddlywebplugins.pkgstore', {'package': package_name, 'read_only': True}, {'tiddlyweb.config': self.init_config}) for bag in source_store.list_bags(): for tiddler in source_store.list_bag_tiddlers(bag): tiddler = source_store.get(tiddler) store.put(tiddler) os.chdir(cwd)
def test_get_bag_from_store(): _cleanup() config = { "server_store": ["tiddlywebplugins.devstore", {"store_root": STORE_DIR}], "instance_tiddlers": {"myBag": ["%s/alpha/index.recipe" % REPO_DIR]}, "root_dir": "", } env = {"tiddlyweb.config": config} store = Store(config["server_store"][0], config["server_store"][1], env) bag = Bag("myBag") bag = store.get(bag) assert bag.name == "myBag" actual = [tiddler.title for tiddler in bag.list_tiddlers()] expected = ["SiteTitle", "foo", "lorem"] assert sorted(actual) == sorted(expected)
def test_recipe_get_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) recipe = store.get(recipe) assert recipe.name == "foo" assert recipe.desc == "lorem ipsum"
class Store(StorageInterface): def __init__(self, store_config=None, environ=None): super(Store, self).__init__(store_config, environ) self.main_store = None self.stores = [] self._init_store() def _init_store(self): server_store = self.environ['tiddlyweb.config']['server_store'] server_store_copy = copy.deepcopy(server_store) extra_store_config = server_store[1]['extras'] main_store_config = server_store[1]['main'] self.environ['tiddlyweb.config']['server_store'] = main_store_config self.main_store = Storer(main_store_config[0], main_store_config[1], self.environ) for rule, store in extra_store_config: pattern = re.compile(rule) self.environ['tiddlyweb.config']['server_store'] = store self.environ['tiddlyweb.config']['main_store'] = self.main_store self.stores.append((pattern, Storer(store[0], store[1], self.environ))) self.environ['tiddlyweb.config']['server_store'] = server_store_copy def recipe_delete(self, recipe): self.main_store.delete(recipe) def recipe_get(self, recipe): return self.main_store.get(recipe) def recipe_put(self, recipe): self.main_store.put(recipe) def bag_delete(self, bag): store = self._determine_store(bag.name) store.delete(bag) def bag_get(self, bag): store = self._determine_store(bag.name) return store.get(bag) def bag_put(self, bag): store = self._determine_store(bag.name) store.put(bag) def tiddler_delete(self, tiddler): store = self._determine_store(tiddler.bag) store.delete(tiddler) def tiddler_get(self, tiddler): store = self._determine_store(tiddler.bag) return store.get(tiddler) def tiddler_put(self, tiddler): store = self._determine_store(tiddler.bag) store.put(tiddler) def user_delete(self, user): self.main_store.delete(user) def user_get(self, user): return self.main_store.get(user) def user_put(self, user): return self.main_store.put(user) def list_recipes(self): return self.main_store.list_recipes() def list_bags(self): bags = [] for rule, store in self.stores: bags.extend(store.list_bags()) bags.extend(self.main_store.list_bags()) return bags def list_bag_tiddlers(self, bag): store = self._determine_store(bag.name) return store.list_bag_tiddlers(bag) def list_users(self): return self.main_store.list_users() def list_tiddler_revisions(self, tiddler): store = self._determine_store(tiddler.bag) return store.list_tiddler_revisions(tiddler) def search(self, search_query): tiddlers = [] searched = False for rule, store in self.stores: try: tiddlers.extend(store.search(search_query)) searched = True except StoreMethodNotImplemented: pass # just ride right over those stores that don't search try: tiddlers.extend(self.main_store.search(search_query)) searched = True except StoreMethodNotImplemented: pass if not searched: raise StoreMethodNotImplemented return tiddlers def _determine_store(self, name): for pattern, store in self.stores: # XXX should this be search or match? if pattern.match(name): return store return self.main_store
class Store(StorageInterface): def __init__(self, store_config=None, environ=None): super(Store, self).__init__(store_config, environ) self.main_store = None self.stores = [] self._init_store() def _init_store(self): server_store = self.environ['tiddlyweb.config']['server_store'] server_store_copy = copy.deepcopy(server_store) extra_store_config = server_store[1]['extras'] main_store_config = server_store[1]['main'] self.environ['tiddlyweb.config']['server_store'] = main_store_config self.main_store = Storer(main_store_config[0], main_store_config[1], self.environ) for rule, store in extra_store_config: pattern = re.compile(rule) self.environ['tiddlyweb.config']['server_store'] = store self.environ['tiddlyweb.config']['main_store'] = self.main_store self.stores.append( (pattern, Storer(store[0], store[1], self.environ))) self.environ['tiddlyweb.config']['server_store'] = server_store_copy def recipe_delete(self, recipe): self.main_store.delete(recipe) def recipe_get(self, recipe): return self.main_store.get(recipe) def recipe_put(self, recipe): self.main_store.put(recipe) def bag_delete(self, bag): store = self._determine_store(bag.name) store.delete(bag) def bag_get(self, bag): store = self._determine_store(bag.name) return store.get(bag) def bag_put(self, bag): store = self._determine_store(bag.name) store.put(bag) def tiddler_delete(self, tiddler): store = self._determine_store(tiddler.bag) store.delete(tiddler) def tiddler_get(self, tiddler): store = self._determine_store(tiddler.bag) return store.get(tiddler) def tiddler_put(self, tiddler): store = self._determine_store(tiddler.bag) store.put(tiddler) def user_delete(self, user): self.main_store.delete(user) def user_get(self, user): return self.main_store.get(user) def user_put(self, user): return self.main_store.put(user) def list_recipes(self): return self.main_store.list_recipes() def list_bags(self): bags = [] for rule, store in self.stores: bags.extend(store.list_bags()) bags.extend(self.main_store.list_bags()) return bags def list_users(self): return self.main_store.list_users() def list_tiddler_revisions(self, tiddler): store = self._determine_store(tiddler.bag) return store.list_tiddler_revisions(tiddler) def search(self, search_query): tiddlers = [] searched = False for rule, store in self.stores: try: tiddlers.extend(store.search(search_query)) searched = True except StoreMethodNotImplemented: pass # just ride right over those stores that don't search try: tiddlers.extend(self.main_store.search(search_query)) searched = True except StoreMethodNotImplemented: pass if not searched: raise StoreMethodNotImplemented return tiddlers def _determine_store(self, name): for pattern, store in self.stores: # XXX should this be search or match? if pattern.match(name): return store return self.main_store
class Store(StorageInterface): _MC = None def __init__(self, store_config=None, environ=None): if store_config is None: store_config = {} if environ is None: environ = {} self.environ = environ self.config = environ.get("tiddlyweb.config") self._mc = self._MC if self._mc == None: try: from google.appengine.api import memcache self._MC = memcache except ImportError: import memcache try: self._MC = memcache.Client(self.config["memcache_hosts"]) except KeyError: from tiddlyweb.config import config self.config = config self._MC = memcache.Client(self.config["memcache_hosts"]) self._mc = self._MC self.cached_store = StoreBoss( self.config["cached_store"][0], self.config["cached_store"][1], environ=environ ) self.prefix = self.config["server_prefix"] self.host = self.config["server_host"]["host"] def recipe_delete(self, recipe): key = self._recipe_key(recipe) self._mc.delete(key) self.cached_store.delete(recipe) def recipe_get(self, recipe): key = self._recipe_key(recipe) cached_recipe = self._get(key) if cached_recipe: recipe = cached_recipe else: recipe = self.cached_store.get(recipe) del recipe.store self._mc.set(key, recipe) return recipe def recipe_put(self, recipe): key = self._recipe_key(recipe) self.cached_store.put(recipe) self._mc.delete(key) def bag_delete(self, bag): key = self._bag_key(bag) if self._mc.delete(key): tiddlers_in_bag = bag.list_tiddlers() for tiddler in tiddlers_in_bag: self._mc.delete_multi( [ self._tiddler_revision_key(self._create_tiddler_revision(tiddler, revision_id)) for revision_id in self.list_tiddler_revisions(tiddler) ] ) self._mc.delete_multi([self._tiddler_key(tiddler) for tiddler in tiddlers_in_bag]) self.cached_store.delete(bag) def bag_get(self, bag): if hasattr(bag, "skinny") and bag.skinny: key = self._bag_key(bag) cached_bag = self._get(key) if cached_bag: bag = cached_bag else: bag = self.cached_store.get(bag) del bag.store self._mc.set(key, bag) else: bag = self.cached_store.get(bag) del bag.store return bag def bag_put(self, bag): key = self._bag_key(bag) self.cached_store.put(bag) self._mc.delete(key) def tiddler_delete(self, tiddler): key = self._tiddler_key(tiddler) if self._mc.delete(key): self._mc.delete(self._bag_key(Bag(tiddler.bag))) self._mc.delete_multi( [ self._tiddler_revision_key(self._create_tiddler_revision(tiddler, revision_id)) for revision_id in self.list_tiddler_revisions(tiddler) ] ) self.cached_store.delete(tiddler) def tiddler_get(self, tiddler): if not tiddler.revision or tiddler.revision == 0: key = self._tiddler_key(tiddler) else: key = self._tiddler_revision_key(tiddler) cached_tiddler = self._get(key) if cached_tiddler: cached_tiddler.recipe = tiddler.recipe tiddler = cached_tiddler else: tiddler = self.cached_store.get(tiddler) del tiddler.store self._mc.set(key, tiddler) return tiddler def tiddler_put(self, tiddler): key = self._tiddler_key(tiddler) self.cached_store.put(tiddler) self._mc.delete(self._bag_key(Bag(tiddler.bag))) self._mc.delete(key) def user_delete(self, user): key = self._user_key(user) self._mc.delete(key) self.cached_store.delete(user) def user_get(self, user): key = self._user_key(user) cached_user = self._get(key) if cached_user: user = cached_user else: user = self.cached_store.get(user) del user.store self._mc.set(key, user) return user def user_put(self, user): key = self._user_key(user) self.cached_store.put(user) self._mc.delete(key) def list_recipes(self): return self.cached_store.list_recipes() def list_bags(self): return self.cached_store.list_bags() def list_users(self): return self.cached_store.list_users() def list_tiddler_revisions(self, tiddler): return self.cached_store.list_tiddler_revisions(tiddler) def search(self, search_query): return self.cached_store.search(search_query) def _create_tiddler_revision(self, tiddler, revision_id): revision = Tiddler(tiddler.title, tiddler.bag) revision.revision = revision_id return revision def _tiddler_key(self, tiddler): key = "tiddler:%s/%s" % (tiddler.bag, tiddler.title) return self._mangle(key) def _tiddler_revision_key(self, tiddler): key = "tiddler:%s/%s/%s" % (tiddler.bag, tiddler.title, tiddler.revision) return self._mangle(key) def _user_key(self, user): key = "user:%s" % user.usersign return self._mangle(key) def _bag_key(self, bag): key = "bag:%s" % bag.name return self._mangle(key) def _recipe_key(self, recipe): key = "recipe:%s" % recipe.name return self._mangle(key) def _mangle(self, key): key = "%s:%s:%s" % (self.host, self.prefix, key) return quote(key.encode("UTF-8"), safe="") def _get(self, key): object = self._mc.get(key) if object: logging.debug("cache hit for %s" % key) else: logging.debug("cache miss for %s" % key) return object
class Store(StorageInterface): def __init__(self, environ=None): logging.debug("initializing SSL Store") super(Store, self).__init__(environ) config = self.environ["tiddlyweb.config"] self.ssl_bags = config["ssl_bags"] # intentionally not providing empty fallback -- XXX: rename? real_store = config["server_store"][1]["store_module"] # XXX: rename? -- TODO: use pop method to keep config clean? self.real_store = Storage(real_store, self.environ) def recipe_delete(self, recipe): logging.debug("delete recipe %s" % recipe) self.real_store.delete(recipe) def recipe_get(self, recipe): logging.debug("get recipe %s" % recipe) return self.real_store.get(recipe) def recipe_put(self, recipe): logging.debug("put recipe %s" % recipe) self.real_store.put(recipe) def bag_delete(self, bag): logging.debug("delete bag %s" % bag) self._check_security(bag.name) self.real_store.delete(bag) def bag_get(self, bag): logging.debug("get bag %s" % bag) self._check_security(bag.name) return self.real_store.get(bag) def bag_put(self, bag): logging.debug("put bag %s" % bag) self._check_security(bag.name) self.real_store.put(bag) def tiddler_delete(self, tiddler): logging.debug("delete tiddler %s" % tiddler) self.real_store.delete(tiddler) def tiddler_get(self, tiddler): logging.debug("get tiddler %s" % tiddler) return self.real_store.get(tiddler) def tiddler_put(self, tiddler): logging.debug("put tiddler %s" % tiddler) self.real_store.put(tiddler) def user_delete(self, user): logging.debug("delete user %s" % user) self.real_store.delete(user) def user_get(self, user): logging.debug("get user %s" % user) return self.real_store.get(user) def user_put(self, user): logging.debug("put user %s" % user) self.real_store.put(user) def list_recipes(self): logging.debug("list recipes") return self.real_store.list_recipes() def list_bags(self): logging.debug("list bags") return self.real_store.list_bags() def list_users(self): logging.debug("list users") return self.real_store.list_users() def list_tiddler_revisions(self, tiddler): logging.debug("list revisions %s" % tiddler) return self.real_store.list_tiddler_revisions(tiddler) def search(self, search_query): logging.debug("search %s" % search_query) return self.real_store.search(search_query) def _check_security(self, bag_name): # TODO: rename? -- TODO: should be decorator!? protocol = self.environ.get("wsgi.url_scheme") if protocol != "https" and bag_name in self.ssl_bags: raise SecureConnectionError("secure connection required")
class Store(StorageInterface): _MC = None def __init__(self, store_config=None, environ=None): if store_config is None: store_config = {} if environ is None: environ = {} self.environ = environ self.config = environ.get('tiddlyweb.config') self._mc = self._MC if self._mc == None: try: from google.appengine.api import memcache self._MC = memcache except ImportError: import memcache try: self._MC = memcache.Client(self.config['memcache_hosts']) except KeyError: from tiddlyweb.config import config self.config = config self._MC = memcache.Client(self.config['memcache_hosts']) self._mc = self._MC self.cached_store = StoreBoss(self.config['cached_store'][0], self.config['cached_store'][1], environ=environ) self.prefix = self.config['server_prefix'] self.host = self.config['server_host']['host'] def recipe_delete(self, recipe): key = self._recipe_key(recipe) self._mc.delete(key) self.cached_store.delete(recipe) def recipe_get(self, recipe): key = self._recipe_key(recipe) cached_recipe = self._get(key) if cached_recipe: recipe = cached_recipe else: recipe = self.cached_store.get(recipe) del recipe.store self._mc.set(key, recipe) return recipe def recipe_put(self, recipe): key = self._recipe_key(recipe) self.cached_store.put(recipe) self._mc.delete(key) def bag_delete(self, bag): key = self._bag_key(bag) if self._mc.delete(key): tiddlers_in_bag = bag.list_tiddlers() for tiddler in tiddlers_in_bag: self._mc.delete_multi([ self._tiddler_revision_key( self._create_tiddler_revision(tiddler, revision_id)) for revision_id in self.list_tiddler_revisions(tiddler) ]) self._mc.delete_multi( [self._tiddler_key(tiddler) for tiddler in tiddlers_in_bag]) self.cached_store.delete(bag) def bag_get(self, bag): if (hasattr(bag, 'skinny') and bag.skinny): key = self._bag_key(bag) cached_bag = self._get(key) if cached_bag: bag = cached_bag else: bag = self.cached_store.get(bag) del bag.store self._mc.set(key, bag) else: bag = self.cached_store.get(bag) del bag.store return bag def bag_put(self, bag): key = self._bag_key(bag) self.cached_store.put(bag) self._mc.delete(key) def tiddler_delete(self, tiddler): key = self._tiddler_key(tiddler) if self._mc.delete(key): self._mc.delete(self._bag_key(Bag(tiddler.bag))) self._mc.delete_multi([ self._tiddler_revision_key( self._create_tiddler_revision(tiddler, revision_id)) for revision_id in self.list_tiddler_revisions(tiddler) ]) self.cached_store.delete(tiddler) def tiddler_get(self, tiddler): if not tiddler.revision or tiddler.revision == 0: key = self._tiddler_key(tiddler) else: key = self._tiddler_revision_key(tiddler) cached_tiddler = self._get(key) if cached_tiddler: cached_tiddler.recipe = tiddler.recipe tiddler = cached_tiddler else: tiddler = self.cached_store.get(tiddler) del tiddler.store self._mc.set(key, tiddler) return tiddler def tiddler_put(self, tiddler): key = self._tiddler_key(tiddler) self.cached_store.put(tiddler) self._mc.delete(self._bag_key(Bag(tiddler.bag))) self._mc.delete(key) def user_delete(self, user): key = self._user_key(user) self._mc.delete(key) self.cached_store.delete(user) def user_get(self, user): key = self._user_key(user) cached_user = self._get(key) if cached_user: user = cached_user else: user = self.cached_store.get(user) del user.store self._mc.set(key, user) return user def user_put(self, user): key = self._user_key(user) self.cached_store.put(user) self._mc.delete(key) def list_recipes(self): return self.cached_store.list_recipes() def list_bags(self): return self.cached_store.list_bags() def list_users(self): return self.cached_store.list_users() def list_tiddler_revisions(self, tiddler): return self.cached_store.list_tiddler_revisions(tiddler) def search(self, search_query): return self.cached_store.search(search_query) def _create_tiddler_revision(self, tiddler, revision_id): revision = Tiddler(tiddler.title, tiddler.bag) revision.revision = revision_id return revision def _tiddler_key(self, tiddler): key = 'tiddler:%s/%s' % (tiddler.bag, tiddler.title) return self._mangle(key) def _tiddler_revision_key(self, tiddler): key = 'tiddler:%s/%s/%s' % (tiddler.bag, tiddler.title, tiddler.revision) return self._mangle(key) def _user_key(self, user): key = 'user:%s' % user.usersign return self._mangle(key) def _bag_key(self, bag): key = 'bag:%s' % bag.name return self._mangle(key) def _recipe_key(self, recipe): key = 'recipe:%s' % recipe.name return self._mangle(key) def _mangle(self, key): key = '%s:%s:%s' % (self.host, self.prefix, key) return quote(key.encode('UTF-8'), safe='') def _get(self, key): object = self._mc.get(key) if object: logging.debug('cache hit for %s' % key) else: logging.debug('cache miss for %s' % key) return object
def test_tiddler_get(): 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"
class Store(StorageInterface): def __init__(self, environ=None): if environ is None: environ = {} self.environ = environ internal_store_environ = { 'tiddlyweb.config': { 'server_store': config['cached_store'], } } self.cached_store = StoreBoss('text', environ=internal_store_environ) def recipe_delete(self, recipe): key = _recipe_key(recipe) MC.delete(key) self.cached_store.delete(recipe) def recipe_get(self, recipe): key = _recipe_key(recipe) cached_recipe = _get(key) if cached_recipe: recipe = cached_recipe else: recipe = self.cached_store.get(recipe) MC.set(key, recipe) return recipe def recipe_put(self, recipe): key = _recipe_key(recipe) self.cached_store.put(recipe) MC.delete(key) def bag_delete(self, bag): key = _bag_key(bag) if MC.delete(key): MC.delete_multi([_tiddler_key(tiddler) for tiddler in bag.list_tiddlers()]) self.cached_store.delete(bag) def bag_get(self, bag): key = _bag_key(bag) cached_bag = _get(key) if cached_bag: bag = cached_bag else: bag = self.cached_store.get(bag) MC.set(key, bag) return bag def bag_put(self, bag): key = _bag_key(bag) self.cached_store.put(bag) MC.delete(key) def tiddler_delete(self, tiddler): key = _tiddler_key(tiddler) if MC.delete(key): MC.delete(_bag_key(Bag(tiddler.bag))) self.cached_store.delete(tiddler) def tiddler_get(self, tiddler): key = _tiddler_key(tiddler) if not tiddler.revision or tiddler.revision == 0: cached_tiddler = _get(key) if cached_tiddler: tiddler = cached_tiddler else: tiddler = self.cached_store.get(tiddler) MC.set(key, tiddler) else: tiddler = self.cached_store.get(tiddler) return tiddler def tiddler_put(self, tiddler): key = _tiddler_key(tiddler) self.cached_store.put(tiddler) MC.delete(_bag_key(Bag(tiddler.bag))) MC.delete(key) def user_delete(self, user): key = _user_key(user) MC.delete(key) self.cached_store.delete(user) def user_get(self, user): key = _user_key(user) cached_user = _get(key) if cached_user: user = cached_user else: user = self.cached_store.get(user) MC.set(key, user) return user def user_put(self, user): key = _user_key(user) self.cached_store.put(user) MC.delete(key) def list_recipes(self): return self.cached_store.list_recipes() def list_bags(self): return self.cached_store.list_bags() def list_users(self): return self.cached_store.list_users() def list_tiddler_revisions(self, tiddler): return self.cached_store.list_tiddler_revisions(tiddler) def search(self, search_query): return self.cached_store.search(search_query)