Left: | ||
Right: |
LEFT | RIGHT |
---|---|
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 Loading... | |
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 Loading... | |
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 |
LEFT | RIGHT |