Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(75)

Delta Between Two Patch Sets: MoinMoin/util/interwiki.py

Issue 10439044: Interwiki Module Fixed
Left Patch Set: Fixed previous mistakes. Created 11 years, 9 months ago
Right Patch Set: TODO Removed :| Created 11 years, 9 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « MoinMoin/util/_tests/test_interwiki.py ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 # Copyright: 2010 MoinMoin:ThomasWaldmann 1 # Copyright: 2010 MoinMoin:ThomasWaldmann
2 # Copyright: 2010 MoinMoin:MicheleOrru 2 # Copyright: 2010 MoinMoin:MicheleOrru
3 # License: GNU GPL v2 (or any later version), see LICENSE.txt for details. 3 # License: GNU GPL v2 (or any later version), see LICENSE.txt for details.
4 4
5 """ 5 """
6 MoinMoin - interwiki support code 6 MoinMoin - interwiki support code
7 """ 7 """
8 8
9 from __future__ import absolute_import, division 9 from __future__ import absolute_import, division
10 10
11 from werkzeug import url_quote 11 from werkzeug import url_quote
12 12
13 from flask import current_app as app 13 from flask import current_app as app
14 from flask import url_for 14 from flask import url_for
15 15
16 import os.path 16 import os.path
17 17 from collections import namedtuple
18 from MoinMoin.constants.keys import CURRENT, FIELDS 18
19 from MoinMoin.constants.keys import CURRENT, FIELDS, NAME_EXACT, NAMESPACE
19 from MoinMoin.constants.contenttypes import CHARSET 20 from MoinMoin.constants.contenttypes import CHARSET
20 21
21 from MoinMoin import log 22 from MoinMoin import log
22 logging = log.getLogger(__name__) 23 logging = log.getLogger(__name__)
23 24
24 25
25 def is_local_wiki(wiki_name): 26 def is_local_wiki(wiki_name):
26 """ 27 """
27 check if <wiki_name> is THIS wiki 28 check if <wiki_name> is THIS wiki
28 """ 29 """
29 return wiki_name in [u'', u'Self', app.cfg.interwikiname, ] 30 return wiki_name in [u'', u'Self', app.cfg.interwikiname, ]
30 31
31 32
32 def is_known_wiki(wiki_name): 33 def is_known_wiki(wiki_name):
33 """ 34 """
34 check if <wiki_name> is a known wiki name 35 check if <wiki_name> is a known wiki name
35 36
36 Note: interwiki_map should have entries for the special wikinames 37 Note: interwiki_map should have entries for the special wikinames
37 denoting THIS wiki, so we do not need to check these names separately. 38 denoting THIS wiki, so we do not need to check these names separately.
38 """ 39 """
39 return wiki_name in app.cfg.interwiki_map 40 return wiki_name in app.cfg.interwiki_map
40 41
41 42
42 def get_fqname(item_name, field, namespace): 43 def get_fqname(item_name, field, namespace):
waldi 2013/06/29 14:30:10 You may want to convert this to a member of Compos
43 """ 44 """
44 Compute composite name from item_name, field, namespace 45 Compute composite name from item_name, field, namespace
45 composite name == [NAMESPACE/][@FIELD/]NAME 46 composite name == [NAMESPACE/][@FIELD/]NAME
46 """ 47 """
48 if field == NAME_EXACT:
49 field = u''
47 if field: 50 if field:
waldi 2013/06/29 14:30:10 "if field and field != NAME_EXACT:" may be faster
48 item_name = u'@{0}/{1}'.format(field, item_name) 51 item_name = u'@{0}/{1}'.format(field, item_name)
49 if namespace: 52 if namespace:
50 item_name = u'{0}/{1}'.format(namespace, item_name) 53 item_name = u'{0}/{1}'.format(namespace, item_name)
51 return item_name 54 return item_name
52 55
53 56
54 def url_for_item(item_name, wiki_name=u'', field=u'', namespace=u'', rev=CURRENT , endpoint=u'frontend.show_item', _external=False): 57 def url_for_item(item_name, wiki_name=u'', field=u'', namespace=u'', rev=CURRENT , endpoint=u'frontend.show_item', _external=False):
55 """ 58 """
56 Compute URL for some local or remote/interwiki item. 59 Compute URL for some local or remote/interwiki item.
57 60
58 For local items: 61 For local items:
59 give <rev> to get the url of some specific revision. 62 give <rev> to get the url of some specific revision.
60 give the <endpoint> to get the url of some specific view, 63 give the <endpoint> to get the url of some specific view,
61 give _external=True to compute fully specified URLs. 64 give _external=True to compute fully specified URLs.
62 65
63 For remote/interwiki items: 66 For remote/interwiki items:
64 If you just give <item_name> and <wiki_name>, a generic interwiki URL 67 If you just give <item_name> and <wiki_name>, a generic interwiki URL
65 will be built. 68 will be built.
66 If you also give <rev> and/or <endpoint>, it is assumed that remote wiki 69 If you also give <rev> and/or <endpoint>, it is assumed that remote wiki
67 URLs are built in the same way as local URLs. 70 URLs are built in the same way as local URLs.
68 Computed URLs are always fully specified. 71 Computed URLs are always fully specified.
69 """ 72 """
73 if field == NAME_EXACT:
74 field = u''
70 if is_local_wiki(wiki_name): 75 if is_local_wiki(wiki_name):
71 item_name = get_fqname(item_name, field, namespace) 76 item_name = get_fqname(item_name, field, namespace)
72 if rev is None or rev == CURRENT: 77 if rev is None or rev == CURRENT:
73 url = url_for(endpoint, item_name=item_name, _external=_external) 78 url = url_for(endpoint, item_name=item_name, _external=_external)
74 else: 79 else:
75 url = url_for(endpoint, item_name=item_name, rev=rev, _external=_ext ernal) 80 url = url_for(endpoint, item_name=item_name, rev=rev, _external=_ext ernal)
76 else: 81 else:
77 try: 82 try:
78 wiki_base_url = app.cfg.interwiki_map[wiki_name] 83 wiki_base_url = app.cfg.interwiki_map[wiki_name]
79 except KeyError, err: 84 except KeyError, err:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 Example: 116 Example:
112 namespaces_set(['ns1', 'ns1/ns2']) 117 namespaces_set(['ns1', 'ns1/ns2'])
113 url: ns1/urlalasd return: ns1, urlalasd 118 url: ns1/urlalasd return: ns1, urlalasd
114 url: ns3/urlalasd return: '', ns3/urlalasd 119 url: ns3/urlalasd return: '', ns3/urlalasd
115 url: ns2/urlalasd return: '', ns2/urlalasd 120 url: ns2/urlalasd return: '', ns2/urlalasd
116 url: ns1/ns2/urlalasd return: ns1/ns2, urlalasd 121 url: ns1/ns2/urlalasd return: ns1/ns2, urlalasd
117 param namespaces_set: set of namespaces (strings) to search 122 param namespaces_set: set of namespaces (strings) to search
118 param url: string 123 param url: string
119 returns: (namespace, url) 124 returns: (namespace, url)
120 """ 125 """
121 namespace_set = {namespace.rstrip('/') for namespace in namespaces}
ashu1461 2013/06/23 12:21:32 we need rstrip here, because the namespace name ca
122
123 namespace = u'' 126 namespace = u''
124 tokens_list = url.split('/') 127 tokens_list = url.split('/')
125 for token in tokens_list: 128 for token in tokens_list:
126 if namespace: 129 if namespace:
127 token = u'{0}/{1}'.format(namespace, token) 130 token = u'{0}/{1}'.format(namespace, token)
128 if token in namespace_set: 131 if token in namespaces:
129 namespace = token 132 namespace = token
130 else: 133 else:
131 break 134 break
132 if namespace: 135 if namespace:
133 length = len(namespace) + 1 136 length = len(namespace) + 1
134 url = url[length:] 137 url = url[length:]
135 return namespace, url 138 return namespace, url
136 139
137 140
141 class CompositeName(namedtuple('CompositeName', 'namespace, field, value')):
142 """
143 namedtuple to hold the compositename
144 """
145 @property
146 def split(self):
waldi 2013/06/29 14:30:10 Is this used? This looks like backward compatibili
147 return {NAMESPACE: self.namespace, u'field': self.field, u'item_name': s elf.value}
148
149 @property
150 def fullname(self):
151 return get_fqname(self.value, self.field, self.namespace)
152
153 def __unicode__(self):
154 return self.fullname
155
156
138 def split_fqname(url): 157 def split_fqname(url):
waldi 2013/06/29 14:30:10 You may want to convert this to a (static) member
139 """ 158 """
140 Split a composite name into namespace, field and pagename 159 Split a fully qualified url into namespace, field and pagename
141 composite name -> [NAMESPACE/][@FIELD/]NAME 160 url -> [NAMESPACE/][@FIELD/]NAME
142 param: url: the composite name to split 161 param: url: the url to split
143 returns: (namespace, field, itemname) 162 returns: a namedtuple CompositeName(namespace, field, itemname)
144 Example: 163 Example:
145 url: u'ns1/ns2/@itemid/Page' return u'ns1/ns2', u'itemid', u'Page' 164 url: u'ns1/ns2/@itemid/Page' return u'ns1/ns2', u'itemid', u'Page'
146 url: u'@revid/OtherPage' return u'', u'revid', u'OtherPage' 165 url: u'@revid/OtherPage' return u'', u'revid', u'OtherPage'
147 url: u'ns1/Page' return u'ns1', u'', u'Page' 166 url: u'ns1/Page' return u'ns1', u'', u'Page'
148 url: u'ns1/ns2/@notfield' return u'ns1/ns2', u'', u'@notfield' 167 url: u'ns1/ns2/@notfield' return u'ns1/ns2', u'', u'@notfield'
149 """ 168 """
150 namespace, url = _split_namespace(dict(app.cfg.namespace_mapping).keys(), ur l) 169 namespaces = {namespace.rstrip('/') for namespace, _ in app.cfg.namespace_ma pping}
ashu1461 2013/06/23 12:21:32 the app.cfg.namespace_mapping appears to be list o
151 field = u'' 170 namespace, url = _split_namespace(namespaces, url)
171 field = NAME_EXACT
152 if url.startswith('@'): 172 if url.startswith('@'):
153 tokens = url[1:].split('/', 1) 173 tokens = url[1:].split('/', 1)
154 if tokens[0] in FIELDS: 174 if tokens[0] in FIELDS:
155 field = tokens[0] 175 field = tokens[0]
156 url = tokens[1] 176 url = tokens[1]
157 return namespace, field, url 177 return CompositeName(namespace, field, url)
158 178
159 179
160 def split_interwiki(wikiurl): 180 def split_interwiki(wikiurl):
161 """ Split a interwiki name, into wikiname and pagename, e.g: 181 """ Split a interwiki name, into wikiname and pagename, e.g:
162 182
163 'MoinMoin/FrontPage' -> "MoinMoin", "", "", "FrontPage" 183 'MoinMoin/FrontPage' -> "MoinMoin", "", "", "FrontPage"
164 'FrontPage' -> "Self", "", "", "FrontPage" 184 'FrontPage' -> "Self", "", "", "FrontPage"
165 'MoinMoin/Page with blanks' -> "MoinMoin", "", "", "Page with blanks" 185 'MoinMoin/Page with blanks' -> "MoinMoin", "", "", "Page with blanks"
166 'MoinMoin/' -> "MoinMoin", "", "", "" 186 'MoinMoin/' -> "MoinMoin", "", "", ""
167 'MoinMoin/@Someid/SomeValue' -> "MoinMoin", "", "Someid", "SomeValue" if Som eid field exists or "MoinMoin", "", "", "Someid/SomePage" if not 187 'MoinMoin/@Someid/SomeValue' -> "MoinMoin", "", "Someid", "SomeValue" if Som eid field exists or "MoinMoin", "", "", "Someid/SomePage" if not
168 'MoinMoin/interwikins/AnyPage' -> "MoinMoin", "interwikins", "", "AnyPage" 188 'MoinMoin/interwikins/AnyPage' -> "MoinMoin", "interwikins", "", "AnyPage"
169 'ns/AnyPage' -> "Self", "ns", "", "AnyPage" if ns namespace exists or "Self" , "", "", "ns:AnyPage" if not. 189 'ns/AnyPage' -> "Self", "ns", "", "AnyPage" if ns namespace exists or "Self" , "", "", "ns:AnyPage" if not.
170 'ns1/ns2/AnyPage' -> "Self", "ns1/ns2", "", "AnyPage" if ns1/ns2 namespace e xists OR 190 'ns1/ns2/AnyPage' -> "Self", "ns1/ns2", "", "AnyPage" if ns1/ns2 namespace e xists OR
171 "Self", "ns1", "", "ns2/AnyPage" if ns1 namespace exist s OR 191 "Self", "ns1", "", "ns2/AnyPage" if ns1 namespace exist s OR
172 "Self", "", "", "ns1/ns2/AnyPage" else. 192 "Self", "", "", "ns1/ns2/AnyPage" else.
173 'MoinMoin/ns/@Somefield/AnyPage' -> "MoinMoin", "ns", "", "@Somefield/AnyPag e" if ns namespace exists and field Somefield does not OR 193 'MoinMoin/ns/@Somefield/AnyPage' -> "MoinMoin", "ns", "", "@Somefield/AnyPag e" if ns namespace exists and field Somefield does not OR
174 "MoinMoin", "ns", "Somefield", "AnyPage" if ns namespace and field Somefield exist OR 194 "MoinMoin", "ns", "Somefield", "AnyPage" if ns namespace and field Somefield exist OR
175 "MoinMoin", "", "", "ns/@Somefield/AnyPage" else. 195 "MoinMoin", "", "", "ns/@Somefield/AnyPage" else.
176 :param wikiurl: the url to split 196 :param wikiurl: the url to split
177 :rtype: tuple 197 :rtype: tuple
178 :returns: (wikiname, namespace, field, pagename) 198 :returns: (wikiname, namespace, field, pagename)
179 """ 199 """
180 #TODO Now using slash('/') as delimiter in interwiki markup instead of ':', change the moin 1.9 importer accordingly.
181 if not isinstance(wikiurl, unicode): 200 if not isinstance(wikiurl, unicode):
182 wikiurl = wikiurl.decode('utf-8') 201 wikiurl = wikiurl.decode('utf-8')
183 # Base case: no colon in wikiurl 202 # Base case: no colon in wikiurl
184 if not '/' in wikiurl: 203 if not '/' in wikiurl:
185 return u'Self', u'', u'', wikiurl 204 return u'Self', u'', NAME_EXACT, wikiurl
186 wikiname = field = namespace = u'' 205 wikiname = field = namespace = u''
187 if not wikiurl.startswith('/'): 206 if not wikiurl.startswith('/'):
188 interwiki_mapping = set() 207 interwiki_mapping = set()
189 for interwiki_name in app.cfg.interwiki_map: 208 for interwiki_name in app.cfg.interwiki_map:
190 interwiki_mapping.add(interwiki_name.split('/')[0]) 209 interwiki_mapping.add(interwiki_name.split('/')[0])
191 wikiname, item_name = _split_namespace(interwiki_mapping, wikiurl) 210 wikiname, item_name = _split_namespace(interwiki_mapping, wikiurl)
192 if wikiname: 211 if wikiname:
193 wikiurl = wikiurl[len(wikiname)+1:] 212 wikiurl = wikiurl[len(wikiname)+1:]
194 namespace, field, item_name = split_fqname(wikiurl) 213 namespace, field, item_name = split_fqname(wikiurl)
195 if not wikiname: 214 if not wikiname:
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 @staticmethod 318 @staticmethod
300 def from_file(filename): 319 def from_file(filename):
301 """ 320 """
302 Load and parse a valid interwiki map file. 321 Load and parse a valid interwiki map file.
303 """ 322 """
304 filename = os.path.expanduser(filename) 323 filename = os.path.expanduser(filename)
305 with open(filename) as f: 324 with open(filename) as f:
306 parser = InterWikiMap(f.read()) 325 parser = InterWikiMap(f.read())
307 326
308 return parser 327 return parser
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b