Mercurial > moin > 2.0
changeset 2218:6a798f444129
Added basic composite name support to MoinMoin.items
author | Ashutosh Singla <ashu1461@gmail.com> |
---|---|
date | Sun, 30 Jun 2013 02:53:51 +0530 |
parents | 431815d4f4a6 |
children | 16ce58503062 |
files | MoinMoin/constants/keys.py MoinMoin/items/__init__.py |
diffstat | 2 files changed, 78 insertions(+), 50 deletions(-) [+] |
line wrap: on
line diff
--- a/MoinMoin/constants/keys.py Sun Jun 30 02:23:16 2013 +0530 +++ b/MoinMoin/constants/keys.py Sun Jun 30 02:53:51 2013 +0530 @@ -116,5 +116,11 @@ # Values that FIELD can take in the composite name: [NAMESPACE/][@FIELD/]NAME FIELDS = [ - ITEMID, REVID, TAGS, USERID, ITEMLINKS, ITEMTRANSCLUSIONS, + NAME_EXACT, ITEMID, REVID, TAGS, USERID, ITEMLINKS, ITEMTRANSCLUSIONS ] +# Fields that can be used as a unique identifier. +UFIELDS = [ + NAME_EXACT, ITEMID, REVID, +] +# Unique fields that are stored as list. +UFIELDS_TYPELIST = [NAME_EXACT, ]
--- a/MoinMoin/items/__init__.py Sun Jun 30 02:23:16 2013 +0530 +++ b/MoinMoin/items/__init__.py Sun Jun 30 02:53:51 2013 +0530 @@ -41,14 +41,15 @@ from MoinMoin.i18n import L_ from MoinMoin.themes import render_template from MoinMoin.util.mime import Type -from MoinMoin.util.interwiki import url_for_item +from MoinMoin.util.interwiki import url_for_item, split_fqname, get_fqname from MoinMoin.util.registry import RegistryBase from MoinMoin.util.clock import timed from MoinMoin.forms import RequiredText, OptionalText, JSON, Tags from MoinMoin.constants.keys import ( NAME, NAME_OLD, NAME_EXACT, WIKINAME, MTIME, ITEMTYPE, CONTENTTYPE, SIZE, ACTION, ADDRESS, HOSTNAME, USERID, COMMENT, - HASH_ALGORITHM, ITEMID, REVID, DATAID, CURRENT, PARENTID + HASH_ALGORITHM, ITEMID, REVID, DATAID, CURRENT, PARENTID, NAMESPACE, + UFIELDS_TYPELIST ) from MoinMoin.constants.contenttypes import CHARSET, CONTENTTYPE_NONEXISTENT from MoinMoin.constants.itemtypes import ( @@ -109,13 +110,17 @@ self.data = StringIO('') self.revid = None if self.item: - self.meta[NAME] = [self.item.name] + self.meta[NAMESPACE] = item.fqname.namespace + if item.fqname.field in UFIELDS_TYPELIST: + self.meta[item.fqname.field] = [item.fqname.value] + else: + self.meta[item.fqname.field] = item.fqname.value class DummyItem(object): """ if we have no stored Item, we use this dummy """ - def __init__(self, name): - self.name = name + def __init__(self, fqname): + self.fqname = fqname def list_revisions(self): return [] # same as an empty Item @@ -124,7 +129,7 @@ return True -def get_storage_revision(name, itemtype=None, contenttype=None, rev_id=CURRENT, item=None): +def get_storage_revision(fqname, itemtype=None, contenttype=None, rev_id=CURRENT, item=None): """ Get a storage Revision. @@ -144,18 +149,21 @@ :itemtype and :contenttype are used when creating a DummyRev, where metadata is not available from the storage. """ + query = {fqname.field: fqname.value, NAMESPACE: fqname.namespace} + rev_id = fqname.value if fqname.field == REVID else rev_id if 1: # try: if item is None: - item = flaskg.storage[name] + item = flaskg.storage.get_item(**query) else: - name = item.name + if item.fqname: + fqname = item.fqname if not item: # except NoSuchItemError: - logging.debug("No such item: {0!r}".format(name)) - item = DummyItem(name) + logging.debug("No such item: {0!r}".format(fqname)) + item = DummyItem(fqname) rev = DummyRev(item, itemtype, contenttype) - logging.debug("Item {0!r}, created dummy revision with contenttype {1!r}".format(name, contenttype)) + logging.debug("Item {0!r}, created dummy revision with contenttype {1!r}".format(fqname, contenttype)) else: - logging.debug("Got item: {0!r}".format(name)) + logging.debug("Got item: {0!r}".format(fqname)) try: rev = item.get_revision(rev_id) except KeyError: # NoSuchRevisionError: @@ -163,10 +171,10 @@ rev = item.get_revision(CURRENT) # fall back to current revision # XXX add some message about invalid revision except KeyError: # NoSuchRevisionError: - logging.debug("Item {0!r} has no revisions.".format(name)) + logging.debug("Item {0!r} has no revisions.".format(fqname)) rev = DummyRev(item, itemtype, contenttype) - logging.debug("Item {0!r}, created dummy revision with contenttype {1!r}".format(name, contenttype)) - logging.debug("Got item {0!r}, revision: {1!r}".format(name, rev_id)) + logging.debug("Item {0!r}, created dummy revision with contenttype {1!r}".format(fqname, contenttype)) + logging.debug("Got item {0!r}, revision: {1!r}".format(fqname, rev_id)) return rev @@ -275,7 +283,8 @@ previously created Content instance is assigned to its content property. """ - rev = get_storage_revision(name, itemtype, contenttype, rev_id, item) + fqname = split_fqname(name) + rev = get_storage_revision(fqname, itemtype, contenttype, rev_id, item) contenttype = rev.meta.get(CONTENTTYPE) or contenttype logging.debug("Item {0!r}, got contenttype {1!r} from revision meta".format(name, contenttype)) #logging.debug("Item %r, rev meta dict: %r" % (name, dict(rev.meta))) @@ -287,15 +296,14 @@ itemtype = rev.meta.get(ITEMTYPE) or itemtype or ITEMTYPE_DEFAULT logging.debug("Item {0!r}, got itemtype {1!r} from revision meta".format(name, itemtype)) - item = item_registry.get(itemtype, name, rev=rev, content=content) + item = item_registry.get(itemtype, fqname, rev=rev, content=content) logging.debug("Item class {0!r} handles {1!r}".format(item.__class__, itemtype)) content.item = item - return item - def __init__(self, name, rev=None, content=None): - self.name = name + def __init__(self, fqname, rev=None, content=None): + self.fqname = fqname self.rev = rev self.content = content @@ -303,6 +311,19 @@ return self.rev.meta meta = property(fget=get_meta) + @property + def name(self): + """ + returns the page name if known else extract name from meta. + """ + if self.fqname.field == NAME_EXACT: + return self.fqname.value + else: + try: + return self.meta.get(NAME)[0] + except: #except AnyError + return u'' + # XXX Backward compatibility, remove soon @property def contenttype(self): @@ -316,7 +337,7 @@ kill_keys = [ # shall not get copied from old rev to new rev NAME_OLD, # are automatically implanted when saving - ITEMID, REVID, DATAID, + REVID, DATAID, HASH_ALGORITHM, SIZE, COMMENT, @@ -458,7 +479,8 @@ def _save(self, meta, data=None, name=None, action=u'SAVE', contenttype_guessed=None, comment=None, overwrite=False, delete=False): backend = flaskg.storage - storage_item = backend[self.name] + query = {self.fqname.field: self.fqname.value, NAMESPACE: self.fqname.namespace} + storage_item = backend.get_item(**query) try: currentrev = storage_item.get_revision(CURRENT) rev_id = currentrev.revid @@ -469,26 +491,26 @@ contenttype_current = None meta = dict(meta) # we may get a read-only dict-like, copy it - # we store the previous (if different) and current item name into revision metadata # this is useful for rename history and backends that use item uids internally - if name is None: - name = self.name - oldname = meta.get(NAME) - if oldname: - if not isinstance(oldname, list): - oldname = [oldname] - if delete or name not in oldname: # this is a delete or rename - meta[NAME_OLD] = oldname[:] - try: - oldname.remove(self.name) - except ValueError: - pass - if not delete: - oldname.append(name) - meta[NAME] = oldname - else: - meta[NAME] = [name] + if self.fqname.field == NAME_EXACT: + if name is None: + name = self.fqname.value + oldname = meta.get(NAME) + if oldname: + if not isinstance(oldname, list): + oldname = [oldname] + if delete or name not in oldname: # this is a delete or rename + meta[NAME_OLD] = oldname[:] + try: + oldname.remove(self.name) + except ValueError: + pass + if not delete: + oldname.append(name) + meta[NAME] = oldname + else: + meta[NAME] = [name] if comment is not None: meta[COMMENT] = unicode(comment) @@ -510,7 +532,6 @@ if isinstance(data, str): data = StringIO(data) - newrev = storage_item.store_revision(meta, data, overwrite=overwrite, action=unicode(action), contenttype_current=contenttype_current, @@ -576,7 +597,8 @@ if direct_relname not in added_dir_relnames: added_dir_relnames.add(direct_relname) direct_fullname = prefix + direct_relname - direct_rev = get_storage_revision(direct_fullname) + fqname = split_fqname(direct_fullname) + direct_rev = get_storage_revision(fqname) dirs.append(IndexEntry(direct_relname, direct_fullname, direct_rev.meta)) else: files.append(IndexEntry(relname, fullname, rev.meta)) @@ -669,7 +691,7 @@ rev_ids = [] item_templates = self.content.get_templates(self.contenttype) return render_template('modify_select_template.html', - item_name=self.name, + item_name=self.fqname.fullname, itemtype=self.itemtype, rev=self.rev, contenttype=self.contenttype, @@ -685,7 +707,7 @@ show_navigation = False # TODO first_rev = last_rev = None # TODO return render_template(self.show_template, - item=self, item_name=self.name, + item=self, item_name=self.fqname.fullname, rev=self.rev, contenttype=self.contenttype, first_rev_id=first_rev, @@ -700,7 +722,7 @@ if method in ['GET', 'HEAD']: if isinstance(self.content, NonExistentContent): return render_template('modify_select_contenttype.html', - item_name=self.name, + item_name=self.fqname.fullname, itemtype=self.itemtype, group_names=content_registry.group_names, groups=content_registry.groups, @@ -734,9 +756,9 @@ except AccessDenied: abort(403) else: - return redirect(url_for_item(self.name)) + return redirect(url_for_item(**self.fqname.split)) return render_template(self.modify_template, - item_name=self.name, + item_name=self.fqname.fullname, rows_meta=str(ROWS_META), cols=str(COLS), form=form, search_form=None, @@ -775,7 +797,7 @@ content = self._select_itemtype() else: content = render_template('show_nonexistent.html', - item_name=self.name, + item_name=self.fqname.fullname, ) return Response(content, 404) @@ -787,7 +809,7 @@ def _select_itemtype(self): return render_template('modify_select_itemtype.html', - item_name=self.name, + item_name=self.fqname.fullname, itemtypes=item_registry.shown_entries, )