wmlinksfromhell 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wmlinksfromhell-1.0.0/API_REFERENCE.md +898 -0
- wmlinksfromhell-1.0.0/CHANGELOG.md +15 -0
- wmlinksfromhell-1.0.0/LICENSE +21 -0
- wmlinksfromhell-1.0.0/MANIFEST.in +11 -0
- wmlinksfromhell-1.0.0/PKG-INFO +373 -0
- wmlinksfromhell-1.0.0/README.md +345 -0
- wmlinksfromhell-1.0.0/examples/comments.py +20 -0
- wmlinksfromhell-1.0.0/examples/convert_links.py +12 -0
- wmlinksfromhell-1.0.0/examples/pywikibot_example.py +13 -0
- wmlinksfromhell-1.0.0/examples/select_links.py +19 -0
- wmlinksfromhell-1.0.0/examples/simple_api.py +19 -0
- wmlinksfromhell-1.0.0/examples/sitematrix.py +25 -0
- wmlinksfromhell-1.0.0/pyproject.toml +51 -0
- wmlinksfromhell-1.0.0/requirements-dev.txt +3 -0
- wmlinksfromhell-1.0.0/setup.cfg +4 -0
- wmlinksfromhell-1.0.0/tests/conftest.py +31 -0
- wmlinksfromhell-1.0.0/tests/test_cache.py +53 -0
- wmlinksfromhell-1.0.0/tests/test_comments_and_simple_api.py +112 -0
- wmlinksfromhell-1.0.0/tests/test_conversion.py +275 -0
- wmlinksfromhell-1.0.0/tests/test_destination.py +52 -0
- wmlinksfromhell-1.0.0/tests/test_interwiki.py +487 -0
- wmlinksfromhell-1.0.0/tests/test_matching.py +76 -0
- wmlinksfromhell-1.0.0/tests/test_mediawiki_link_docs.py +439 -0
- wmlinksfromhell-1.0.0/tests/test_mediawiki_url_cases.py +335 -0
- wmlinksfromhell-1.0.0/tests/test_metadata.py +732 -0
- wmlinksfromhell-1.0.0/tests/test_parser.py +64 -0
- wmlinksfromhell-1.0.0/tests/test_public_and_operations.py +207 -0
- wmlinksfromhell-1.0.0/tests/test_real_world.py +50 -0
- wmlinksfromhell-1.0.0/tests/test_resolution.py +71 -0
- wmlinksfromhell-1.0.0/tests/test_simple_api.py +155 -0
- wmlinksfromhell-1.0.0/tests/test_special_fallbacks.py +37 -0
- wmlinksfromhell-1.0.0/tests/test_transformation.py +102 -0
- wmlinksfromhell-1.0.0/tests/test_urls.py +205 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/__init__.py +73 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/cache.py +92 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/constants.py +307 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/destination.py +125 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/exceptions.py +29 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/interwiki.py +842 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/metadata.py +1175 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/models.py +165 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/nodes.py +447 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/operations.py +83 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/parser.py +186 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/pywikibot_support.py +13 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/resolver.py +266 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell/url.py +402 -0
- wmlinksfromhell-1.0.0/wmlinksfromhell.egg-info/SOURCES.txt +45 -0
|
@@ -0,0 +1,898 @@
|
|
|
1
|
+
# wmlinksfromhell API reference
|
|
2
|
+
|
|
3
|
+
This is the reference for `wmlinksfromhell 1.0.0`. For a quick start, see [README.md](README.md).
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import wmlinksfromhell
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The package-level functions are the easiest place to start. The lower-level classes are useful when you want to keep a resolver or metadata store around.
|
|
10
|
+
|
|
11
|
+
## Package functions
|
|
12
|
+
|
|
13
|
+
### `parse(text, source=None, metadata=None) -> Code`
|
|
14
|
+
|
|
15
|
+
Parse MediaWiki wikitext and return a `Code` object.
|
|
16
|
+
|
|
17
|
+
`source` can be a dbname, hostname, Wikimedia URL, `Wiki`/`WikiInfo`, Pywikibot `Site`, or Pywikibot `Page`.
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
code = wmlinksfromhell.parse(
|
|
21
|
+
'[[w:en:Apple]] and https://de.wikipedia.org/wiki/Berlin',
|
|
22
|
+
source='metawiki',
|
|
23
|
+
)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### `parse_page(page, metadata=None) -> Code`
|
|
27
|
+
|
|
28
|
+
Pywikibot convenience wrapper. It uses `page.site` as the wiki source and keeps the page itself as context.
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
code = wmlinksfromhell.parse_page(page)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Keeping the page context matters for anchors and relative links.
|
|
35
|
+
|
|
36
|
+
### `resolve(value, source=None, metadata=None) -> Result`
|
|
37
|
+
|
|
38
|
+
Resolve a value without first deciding whether it is a URL, interwiki target, or local link.
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
result = wmlinksfromhell.resolve('https://en.wikipedia.org/wiki/Apple')
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### `resolve_url(value, source=None, metadata=None) -> Result`
|
|
45
|
+
|
|
46
|
+
Resolve a URL. Wikimedia article paths, `index.php`, revisions, diffs, actions, fragments, page IDs, and protocol-relative URLs are supported.
|
|
47
|
+
|
|
48
|
+
### `resolve_interwiki(value, source=None, metadata=None) -> Result`
|
|
49
|
+
|
|
50
|
+
Resolve an interwiki or local target. A leading `:` is supported.
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
result = wmlinksfromhell.resolve_interwiki(
|
|
54
|
+
':w:en:Apple',
|
|
55
|
+
source='metawiki',
|
|
56
|
+
)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### `to_url(destination, metadata=None) -> str`
|
|
60
|
+
|
|
61
|
+
Render a `Destination` as a URL.
|
|
62
|
+
|
|
63
|
+
### `to_interwiki(destination, source=None, metadata=None) -> str`
|
|
64
|
+
|
|
65
|
+
Render a `Destination` as an interwiki target. Exact revision and diff targets use `Special:` forms when possible. If an operation cannot be represented exactly but the page title is known, the normal page interwiki target is used rather than returning an empty value.
|
|
66
|
+
|
|
67
|
+
### `to_local(destination, source=None, metadata=None) -> str`
|
|
68
|
+
|
|
69
|
+
Render a destination as a local target on the source wiki. The destination must belong to that wiki.
|
|
70
|
+
|
|
71
|
+
### `wiki(dbname, metadata=None) -> WikiInfo`
|
|
72
|
+
|
|
73
|
+
Return a wiki by database name.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
wiki = wmlinksfromhell.wiki('enwiki')
|
|
77
|
+
print(wiki.language)
|
|
78
|
+
print(wiki.hostname)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### `interwiki(dbname, metadata=None, source=None) -> InterwikiInfo`
|
|
82
|
+
|
|
83
|
+
Return the canonical interwiki identity for a wiki.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
info = wmlinksfromhell.interwiki('dewiktionary')
|
|
87
|
+
print(info.prefix) # wikt:de
|
|
88
|
+
print(info.project) # wikt
|
|
89
|
+
print(info.language) # de
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### `url(dbname, title, metadata=None, source=None) -> str`
|
|
93
|
+
|
|
94
|
+
Build a page URL directly from a dbname and title.
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
wmlinksfromhell.url('enwiki', 'Apple')
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### `link(dbname, title, label=None, metadata=None, source=None) -> str`
|
|
101
|
+
|
|
102
|
+
Build an interwiki wikilink directly.
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
wmlinksfromhell.link('enwiki', 'Apple')
|
|
106
|
+
wmlinksfromhell.link('enwiki', 'Apple', 'the fruit')
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Code
|
|
110
|
+
|
|
111
|
+
`Code` is the preferred short name for `WMCode`.
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
code = wmlinksfromhell.parse(text)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### `code.links`
|
|
118
|
+
|
|
119
|
+
The normal link selection, equivalent to `code.filter_links()`.
|
|
120
|
+
|
|
121
|
+
Links inside HTML comments are not included unless requested.
|
|
122
|
+
|
|
123
|
+
### `code.filter_links(recursive=True, predicate=None, comment_links=False, **criteria) -> list[Link]`
|
|
124
|
+
|
|
125
|
+
Select links using semantic criteria.
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
code.filter_links()
|
|
129
|
+
code.filter_links(family='wikipedia')
|
|
130
|
+
code.filter_links(project='wikipedia')
|
|
131
|
+
code.filter_links(language='en')
|
|
132
|
+
code.filter_links(dbname='enwiki')
|
|
133
|
+
code.filter_links(namespace='MediaWiki')
|
|
134
|
+
code.filter_links(title='Xtools.js')
|
|
135
|
+
code.filter_links(hostname='en.wikipedia.org')
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Boolean filters:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
code.filter_links(wikimedia_only=True)
|
|
142
|
+
code.filter_links(wiki_only=True)
|
|
143
|
+
code.filter_links(external_only=True)
|
|
144
|
+
code.filter_links(interwiki_only=True)
|
|
145
|
+
code.filter_links(local_only=True)
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`predicate` receives each `Link` and can be used for custom selection:
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
code.filter_links(
|
|
152
|
+
predicate=lambda link: link.is_wiki and link.namespace == 'MediaWiki'
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`comment_links=True` includes links inside HTML comments. `in_comment=True` can then be used to select comments only.
|
|
157
|
+
|
|
158
|
+
### `code.filter_wikilinks(...) -> list[Link]`
|
|
159
|
+
|
|
160
|
+
Like `filter_links()`, but limited to wikilink nodes.
|
|
161
|
+
|
|
162
|
+
### `code.filter_external_links(...) -> list[Link]`
|
|
163
|
+
|
|
164
|
+
Like `filter_links()`, but limited to external-link nodes.
|
|
165
|
+
|
|
166
|
+
### `code.convert(to, recursive=True, predicate=None, comment_links=False, **criteria) -> list[Link]`
|
|
167
|
+
|
|
168
|
+
Convert selected links in place. `to` is one of `url`, `interwiki`, or `local`.
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
code.convert('url', family='wikipedia', language='en')
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Only selected links are changed. Labels and surrounding wikitext are kept.
|
|
175
|
+
|
|
176
|
+
### `code.get_sections(*args, **kwargs) -> list[Code]`
|
|
177
|
+
|
|
178
|
+
Return section wrappers using the same resolver and source context.
|
|
179
|
+
|
|
180
|
+
### `code.wikicode`
|
|
181
|
+
|
|
182
|
+
The underlying `mwparserfromhell.wikicode.Wikicode` object. This is mainly useful when you need something that `wmlinksfromhell` does not expose directly.
|
|
183
|
+
|
|
184
|
+
## Link
|
|
185
|
+
|
|
186
|
+
`Link` is the preferred short name for `WMLink`.
|
|
187
|
+
|
|
188
|
+
A `Link` wraps one parsed wikilink or external link.
|
|
189
|
+
|
|
190
|
+
### Source and syntax
|
|
191
|
+
|
|
192
|
+
```python
|
|
193
|
+
link.original
|
|
194
|
+
link.raw
|
|
195
|
+
link.label
|
|
196
|
+
link.node
|
|
197
|
+
link.index
|
|
198
|
+
link.in_comment
|
|
199
|
+
link.is_wikilink
|
|
200
|
+
link.is_external_link
|
|
201
|
+
link.syntax_type
|
|
202
|
+
link.input_type
|
|
203
|
+
link.link_type
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
`syntax_type` values:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
local_wikilink
|
|
210
|
+
interwiki_wikilink
|
|
211
|
+
external_link
|
|
212
|
+
bare_url
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
`link_type` distinguishes comment links too:
|
|
216
|
+
|
|
217
|
+
```text
|
|
218
|
+
wikilink
|
|
219
|
+
external_link
|
|
220
|
+
comment_wikilink
|
|
221
|
+
comment_external_link
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Resolution
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
link.result
|
|
228
|
+
link.destination
|
|
229
|
+
link.status
|
|
230
|
+
link.reason
|
|
231
|
+
link.confidence
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Prefix information
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
link.prefix
|
|
238
|
+
link.canonical_prefix
|
|
239
|
+
link.prefix_kind
|
|
240
|
+
link.is_project_prefix
|
|
241
|
+
link.is_language_prefix
|
|
242
|
+
link.is_language_project
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Destination information
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
link.destination_type
|
|
249
|
+
link.is_wikimedia
|
|
250
|
+
link.is_self_link
|
|
251
|
+
link.family
|
|
252
|
+
link.project
|
|
253
|
+
link.language
|
|
254
|
+
link.dbname
|
|
255
|
+
link.wikiid
|
|
256
|
+
link.hostname
|
|
257
|
+
link.title
|
|
258
|
+
link.namespace
|
|
259
|
+
link.fragment
|
|
260
|
+
link.page_id
|
|
261
|
+
link.revision
|
|
262
|
+
link.diff
|
|
263
|
+
link.action
|
|
264
|
+
link.special_page
|
|
265
|
+
link.organization_name
|
|
266
|
+
link.service_name
|
|
267
|
+
link.is_standard_project
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Rendered forms
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
link.interwiki
|
|
274
|
+
link.url
|
|
275
|
+
link.canonical_interwiki
|
|
276
|
+
link.canonical_url
|
|
277
|
+
link.canonical_wikilink
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### `link.matches(**criteria) -> bool`
|
|
281
|
+
|
|
282
|
+
Compare a link with semantic fields or another representation.
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
link.matches(dbname='enwiki')
|
|
286
|
+
link.matches(family='wikipedia', language='en')
|
|
287
|
+
link.matches(namespace='MediaWiki')
|
|
288
|
+
link.matches(url='https://en.wikipedia.org/wiki/Apple')
|
|
289
|
+
link.matches(interwiki='w:en:Apple')
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
For a `Destination`:
|
|
293
|
+
|
|
294
|
+
```python
|
|
295
|
+
link.matches(destination=destination)
|
|
296
|
+
link.matches(same_page_as=destination)
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
`destination=` compares the complete destination. `same_page_as=` compares page identity without requiring fragments and other non-page state to match.
|
|
300
|
+
|
|
301
|
+
### `link.set_url() -> None`
|
|
302
|
+
|
|
303
|
+
Replace the link with its URL form. The link must have a resolved destination.
|
|
304
|
+
|
|
305
|
+
### `link.set_interwiki(source=None) -> None`
|
|
306
|
+
|
|
307
|
+
Replace the link with an interwiki form. Raises `ConversionError` when a safe representation is not possible.
|
|
308
|
+
|
|
309
|
+
### `link.set_local(source=None) -> None`
|
|
310
|
+
|
|
311
|
+
Replace the link with a local form on the source wiki.
|
|
312
|
+
|
|
313
|
+
### `link.convert(to, source=None) -> Link`
|
|
314
|
+
|
|
315
|
+
Convert one link to `url`, `interwiki`, or `local`.
|
|
316
|
+
|
|
317
|
+
### `link.refresh() -> None`
|
|
318
|
+
|
|
319
|
+
Clear the cached result for the link so it can be resolved again.
|
|
320
|
+
|
|
321
|
+
### `link.as_dict() -> dict`
|
|
322
|
+
|
|
323
|
+
Return a JSON-friendly dictionary.
|
|
324
|
+
|
|
325
|
+
## Result
|
|
326
|
+
|
|
327
|
+
`Result` is the preferred short name for `ResolutionResult`.
|
|
328
|
+
|
|
329
|
+
Useful fields:
|
|
330
|
+
|
|
331
|
+
```python
|
|
332
|
+
result.raw
|
|
333
|
+
result.syntax_type
|
|
334
|
+
result.input_type
|
|
335
|
+
result.status
|
|
336
|
+
result.reason
|
|
337
|
+
result.confidence
|
|
338
|
+
result.destination
|
|
339
|
+
result.source_wiki
|
|
340
|
+
|
|
341
|
+
result.prefix
|
|
342
|
+
result.canonical_prefix
|
|
343
|
+
result.prefix_kind
|
|
344
|
+
|
|
345
|
+
result.family
|
|
346
|
+
result.project
|
|
347
|
+
result.language
|
|
348
|
+
result.dbname
|
|
349
|
+
result.wikiid
|
|
350
|
+
result.hostname
|
|
351
|
+
result.title
|
|
352
|
+
result.namespace
|
|
353
|
+
result.fragment
|
|
354
|
+
result.page_id
|
|
355
|
+
result.revision
|
|
356
|
+
result.diff
|
|
357
|
+
result.action
|
|
358
|
+
result.special_page
|
|
359
|
+
|
|
360
|
+
result.interwiki
|
|
361
|
+
result.url
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
There are also convenience flags such as `is_wikimedia`, `is_project_prefix`, `is_language_prefix`, `is_language_project`, `is_revision`, `is_diff`, and `is_action`.
|
|
365
|
+
|
|
366
|
+
### `result.as_dict() -> dict`
|
|
367
|
+
|
|
368
|
+
Return a structured dictionary. The resolved `Destination` is included as nested data.
|
|
369
|
+
|
|
370
|
+
## Destination
|
|
371
|
+
|
|
372
|
+
`Destination` is the representation used after parsing a link. It does not depend on how the link was written.
|
|
373
|
+
|
|
374
|
+
```python
|
|
375
|
+
result = wmlinksfromhell.resolve('w:en:Apple')
|
|
376
|
+
destination = result.destination
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Fields:
|
|
380
|
+
|
|
381
|
+
```python
|
|
382
|
+
destination.destination_type
|
|
383
|
+
destination.family
|
|
384
|
+
destination.project
|
|
385
|
+
destination.language
|
|
386
|
+
destination.dbname
|
|
387
|
+
destination.wikiid
|
|
388
|
+
destination.hostname
|
|
389
|
+
destination.title
|
|
390
|
+
destination.namespace
|
|
391
|
+
destination.fragment
|
|
392
|
+
destination.page_id
|
|
393
|
+
destination.revision
|
|
394
|
+
destination.diff
|
|
395
|
+
destination.action
|
|
396
|
+
destination.special_page
|
|
397
|
+
destination.organization_name
|
|
398
|
+
destination.service_name
|
|
399
|
+
destination.query_parameters
|
|
400
|
+
destination.canonical_url
|
|
401
|
+
destination.metadata_source
|
|
402
|
+
destination.is_multilingual
|
|
403
|
+
destination.is_standard_project
|
|
404
|
+
destination.is_wikimedia_project
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Methods:
|
|
408
|
+
|
|
409
|
+
```python
|
|
410
|
+
destination.full_title
|
|
411
|
+
destination.is_revision
|
|
412
|
+
destination.is_diff
|
|
413
|
+
destination.is_action
|
|
414
|
+
destination.page_identity_key()
|
|
415
|
+
destination.identity_key()
|
|
416
|
+
destination.same_page_as(other)
|
|
417
|
+
destination.as_dict()
|
|
418
|
+
destination.as_json()
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
`page_identity_key()` leaves out fragments and other state that is not part of page identity. `identity_key()` includes the full semantic state.
|
|
422
|
+
|
|
423
|
+
## Metadata
|
|
424
|
+
|
|
425
|
+
`Metadata` is the preferred short name for `MetadataStore`.
|
|
426
|
+
|
|
427
|
+
```python
|
|
428
|
+
metadata = wmlinksfromhell.Metadata()
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
The store starts with a small bootstrap data set. Network refreshes are explicit.
|
|
432
|
+
|
|
433
|
+
### Lookups
|
|
434
|
+
|
|
435
|
+
```python
|
|
436
|
+
metadata.wiki(dbname)
|
|
437
|
+
metadata.wiki_by_dbname(dbname)
|
|
438
|
+
metadata.wiki_by_hostname(hostname)
|
|
439
|
+
metadata.wiki_for_family_language(family, language)
|
|
440
|
+
metadata.known_wiki_hosts()
|
|
441
|
+
metadata.resolve_wikimedia_hostname(hostname)
|
|
442
|
+
metadata.resolve_source(source)
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
Language helpers:
|
|
446
|
+
|
|
447
|
+
```python
|
|
448
|
+
metadata.language_name(code)
|
|
449
|
+
metadata.is_known_language(code)
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
Namespace helpers:
|
|
453
|
+
|
|
454
|
+
```python
|
|
455
|
+
metadata.namespace_names(dbname)
|
|
456
|
+
metadata.namespace_aliases(dbname)
|
|
457
|
+
metadata.is_namespace(text, source)
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Interwiki helpers:
|
|
461
|
+
|
|
462
|
+
```python
|
|
463
|
+
metadata.interwiki(dbname, source=None)
|
|
464
|
+
metadata.interwiki_map(source=None)
|
|
465
|
+
metadata.global_interwiki_entry(prefix)
|
|
466
|
+
metadata.interwiki_language_for_wiki(wiki)
|
|
467
|
+
metadata.interwiki_prefix_for_destination(destination, source=None)
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
### Load already-fetched data
|
|
471
|
+
|
|
472
|
+
```python
|
|
473
|
+
metadata.load_sitematrix(data)
|
|
474
|
+
metadata.load_interwiki_config(text)
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
These methods do not fetch anything themselves.
|
|
478
|
+
|
|
479
|
+
### Refresh data
|
|
480
|
+
|
|
481
|
+
```python
|
|
482
|
+
metadata.update()
|
|
483
|
+
metadata.refresh()
|
|
484
|
+
metadata.update_sitematrix()
|
|
485
|
+
metadata.update_interwiki_config()
|
|
486
|
+
metadata.update_wiki_metadata('enwiki')
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
`update()` refreshes the metadata normally needed by the resolver and stores it in the local cache. The other methods let you refresh individual pieces.
|
|
490
|
+
|
|
491
|
+
`update_from_network()` and `refresh_all()` are older names for compatibility.
|
|
492
|
+
|
|
493
|
+
### `MetadataCache`
|
|
494
|
+
|
|
495
|
+
`MetadataCache` stores the JSON metadata cache.
|
|
496
|
+
|
|
497
|
+
```python
|
|
498
|
+
cache = wmlinksfromhell.MetadataCache()
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Useful members:
|
|
502
|
+
|
|
503
|
+
```python
|
|
504
|
+
cache.path
|
|
505
|
+
cache.default_path()
|
|
506
|
+
cache.load()
|
|
507
|
+
cache.save(data)
|
|
508
|
+
cache.is_expired(max_age_seconds)
|
|
509
|
+
cache.clear()
|
|
510
|
+
cache.empty()
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
A corrupt or incompatible cache is discarded rather than being used as if it were valid metadata.
|
|
514
|
+
|
|
515
|
+
## Wiki
|
|
516
|
+
|
|
517
|
+
`Wiki` is the preferred short name for `WikiInfo`.
|
|
518
|
+
|
|
519
|
+
Fields:
|
|
520
|
+
|
|
521
|
+
```python
|
|
522
|
+
wiki.dbname
|
|
523
|
+
wiki.family
|
|
524
|
+
wiki.project
|
|
525
|
+
wiki.language
|
|
526
|
+
wiki.language_name
|
|
527
|
+
wiki.hostname
|
|
528
|
+
wiki.article_path
|
|
529
|
+
wiki.script_path
|
|
530
|
+
wiki.wikiid
|
|
531
|
+
wiki.sitename
|
|
532
|
+
wiki.api_url
|
|
533
|
+
wiki.metadata_source
|
|
534
|
+
wiki.site_code
|
|
535
|
+
wiki.is_multilingual
|
|
536
|
+
wiki.is_standard_project
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Helpers:
|
|
540
|
+
|
|
541
|
+
```python
|
|
542
|
+
wiki.url
|
|
543
|
+
wiki.page_url(title)
|
|
544
|
+
wiki.interwiki(title)
|
|
545
|
+
wiki.link(title)
|
|
546
|
+
wiki.main_page_url()
|
|
547
|
+
wiki.interwiki_info(metadata=None, source=None)
|
|
548
|
+
wiki.as_dict()
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
## InterwikiInfo
|
|
552
|
+
|
|
553
|
+
`InterwikiInfo` describes how a wiki is represented in an interwiki target.
|
|
554
|
+
|
|
555
|
+
Common fields:
|
|
556
|
+
|
|
557
|
+
```python
|
|
558
|
+
info.prefix
|
|
559
|
+
info.project
|
|
560
|
+
info.language
|
|
561
|
+
info.dbname
|
|
562
|
+
info.wiki
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Helpers:
|
|
566
|
+
|
|
567
|
+
```python
|
|
568
|
+
info.target(title)
|
|
569
|
+
info.url(title, metadata=None, source=None)
|
|
570
|
+
info.link(title, metadata=None, source=None)
|
|
571
|
+
info.as_dict()
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
For example:
|
|
575
|
+
|
|
576
|
+
```python
|
|
577
|
+
info = wmlinksfromhell.interwiki('dewiktionary')
|
|
578
|
+
info.target('Haus')
|
|
579
|
+
# wikt:de:Haus
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
## InterwikiMap
|
|
583
|
+
|
|
584
|
+
`InterwikiMap` contains the interwiki prefixes available to a source wiki.
|
|
585
|
+
|
|
586
|
+
```python
|
|
587
|
+
imap = metadata.interwiki_map('metawiki')
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
Members include:
|
|
591
|
+
|
|
592
|
+
```python
|
|
593
|
+
imap.entries
|
|
594
|
+
imap.family_prefixes
|
|
595
|
+
imap.single_wiki_prefixes
|
|
596
|
+
imap.service_prefixes
|
|
597
|
+
imap.chapter_prefixes
|
|
598
|
+
imap.organization_entries
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
Lookup:
|
|
602
|
+
|
|
603
|
+
```python
|
|
604
|
+
imap.get(prefix)
|
|
605
|
+
prefix in imap
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
## InterwikiEntry
|
|
609
|
+
|
|
610
|
+
An `InterwikiEntry` is one record from the interwiki configuration.
|
|
611
|
+
|
|
612
|
+
```python
|
|
613
|
+
entry.prefix
|
|
614
|
+
entry.url
|
|
615
|
+
entry.local
|
|
616
|
+
entry.trans
|
|
617
|
+
entry.language
|
|
618
|
+
entry.localinterwiki
|
|
619
|
+
entry.extralanglink
|
|
620
|
+
entry.linktext
|
|
621
|
+
entry.sitename
|
|
622
|
+
entry.wikiid
|
|
623
|
+
entry.api
|
|
624
|
+
entry.destination_dbname
|
|
625
|
+
entry.destination_type
|
|
626
|
+
entry.as_dict()
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
## Resolver
|
|
630
|
+
|
|
631
|
+
`Resolver` is the lower-level interface used by the package functions.
|
|
632
|
+
|
|
633
|
+
```python
|
|
634
|
+
resolver = wmlinksfromhell.Resolver()
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
A shared metadata store can be supplied:
|
|
638
|
+
|
|
639
|
+
```python
|
|
640
|
+
metadata = wmlinksfromhell.Metadata()
|
|
641
|
+
resolver = wmlinksfromhell.Resolver(metadata)
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
Methods:
|
|
645
|
+
|
|
646
|
+
```python
|
|
647
|
+
resolver.resolve(value, source=None, strict=False)
|
|
648
|
+
resolver.resolve_url(value, source=None, strict=False)
|
|
649
|
+
resolver.resolve_interwiki(value, source=None, strict=False)
|
|
650
|
+
resolver.to_url(destination)
|
|
651
|
+
resolver.to_interwiki(destination, source=None)
|
|
652
|
+
resolver.to_local(destination, source=None)
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
With `strict=True`, unresolved input raises `ResolutionError` instead of returning a result with an unresolved status.
|
|
656
|
+
|
|
657
|
+
## Enums
|
|
658
|
+
|
|
659
|
+
### `DestinationType`
|
|
660
|
+
|
|
661
|
+
```text
|
|
662
|
+
WIKI
|
|
663
|
+
ORGANIZATION
|
|
664
|
+
SERVICE
|
|
665
|
+
TOOL
|
|
666
|
+
SPECIAL
|
|
667
|
+
EXTERNAL
|
|
668
|
+
UNKNOWN
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
### `ResolutionStatus`
|
|
672
|
+
|
|
673
|
+
```text
|
|
674
|
+
RESOLVED
|
|
675
|
+
AMBIGUOUS
|
|
676
|
+
CONTEXT_REQUIRED
|
|
677
|
+
UNKNOWN_PREFIX
|
|
678
|
+
UNKNOWN_DESTINATION
|
|
679
|
+
METADATA_MISSING
|
|
680
|
+
EXTERNAL
|
|
681
|
+
MALFORMED
|
|
682
|
+
UNSUPPORTED
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
### `SyntaxType`
|
|
686
|
+
|
|
687
|
+
```text
|
|
688
|
+
LOCAL_WIKILINK
|
|
689
|
+
INTERWIKI_WIKILINK
|
|
690
|
+
EXTERNAL_LINK
|
|
691
|
+
BARE_URL
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
## Wikimedia prefix behaviour
|
|
695
|
+
|
|
696
|
+
The resolver understands the usual language and project shortcuts.
|
|
697
|
+
|
|
698
|
+
Examples:
|
|
699
|
+
|
|
700
|
+
```text
|
|
701
|
+
w:en:Apple
|
|
702
|
+
wikt:simple:uppercase
|
|
703
|
+
b:de:Main Page
|
|
704
|
+
q:fr:Main Page
|
|
705
|
+
c:File:Example.jpg
|
|
706
|
+
d:Q42
|
|
707
|
+
m:Main Page
|
|
708
|
+
```
|
|
709
|
+
|
|
710
|
+
Short project shortcuts can inherit the source language when switching between language-based project families. On a multilingual project, or when the shortcut names the source project family, English is used. Long project names such as `wikipedia:` and `wikibooks:` are normal interwiki entries and normally point to the English project.
|
|
711
|
+
|
|
712
|
+
Prefixes can be chained from left to right. Examples include:
|
|
713
|
+
|
|
714
|
+
```text
|
|
715
|
+
:de:q:Hauptseite
|
|
716
|
+
:m:en:About
|
|
717
|
+
:pl:w:2006
|
|
718
|
+
:w:it:b:Wiskunde
|
|
719
|
+
:ja:ja:2006
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
A leading colon also changes ordinary MediaWiki link parsing. For example, on `dewiki`:
|
|
723
|
+
|
|
724
|
+
```text
|
|
725
|
+
[[:en:Apple]]
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
is a local link whose title is `en:Apple`, while:
|
|
729
|
+
|
|
730
|
+
```text
|
|
731
|
+
[[en:Apple]]
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
is an interlanguage link to English Wikipedia.
|
|
735
|
+
|
|
736
|
+
## URL behaviour
|
|
737
|
+
|
|
738
|
+
The URL resolver handles article URLs, `index.php` forms, encoded titles, fragments, revisions, diffs, actions, page IDs, and protocol-relative URLs.
|
|
739
|
+
|
|
740
|
+
Examples:
|
|
741
|
+
|
|
742
|
+
```text
|
|
743
|
+
https://en.wikipedia.org/wiki/Apple
|
|
744
|
+
https://en.wikipedia.org/wiki/Foo%20bar
|
|
745
|
+
https://en.wikipedia.org/wiki/Apple#History
|
|
746
|
+
https://en.wikipedia.org/w/index.php?title=Apple
|
|
747
|
+
https://en.wikipedia.org/w/index.php?title=Apple&oldid=123456
|
|
748
|
+
https://en.wikipedia.org/w/index.php?title=Apple&diff=123456
|
|
749
|
+
https://en.wikipedia.org/w/index.php?title=Apple&action=edit
|
|
750
|
+
https://en.wikipedia.org/w/index.php?curid=9906
|
|
751
|
+
//en.wikipedia.org/wiki/Apple
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
Fragments are kept separately from titles. `curid` is kept as a page ID. Revision and diff information is kept in the destination rather than thrown away.
|
|
755
|
+
|
|
756
|
+
## Revisions and diffs
|
|
757
|
+
|
|
758
|
+
Where an interwiki representation exists, the resolver uses special-page targets:
|
|
759
|
+
|
|
760
|
+
```text
|
|
761
|
+
oldid=123456
|
|
762
|
+
→ w:en:Special:PermanentLink/123456
|
|
763
|
+
|
|
764
|
+
diff=123456
|
|
765
|
+
→ w:en:Special:Diff/123456
|
|
766
|
+
|
|
767
|
+
title=Apple&oldid=123&diff=124
|
|
768
|
+
→ w:en:Special:Diff/123/124
|
|
769
|
+
|
|
770
|
+
action=edit&title=Apple
|
|
771
|
+
→ w:en:Special:Edit/Apple
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
Symbolic diffs such as `prev`, `next`, and `cur` stay attached to the destination. If an operation or query parameter cannot be represented by an interwiki target but the page title is known, `to_interwiki()` uses the normal page target rather than silently losing the page.
|
|
775
|
+
|
|
776
|
+
## Local and relative links
|
|
777
|
+
|
|
778
|
+
These forms depend on source context:
|
|
779
|
+
|
|
780
|
+
```text
|
|
781
|
+
#History
|
|
782
|
+
/example
|
|
783
|
+
../example2
|
|
784
|
+
```
|
|
785
|
+
|
|
786
|
+
Without enough source information, resolution returns `CONTEXT_REQUIRED` instead of guessing.
|
|
787
|
+
|
|
788
|
+
A Pywikibot `Page` is useful here because it supplies both the wiki and page title.
|
|
789
|
+
|
|
790
|
+
## Comments
|
|
791
|
+
|
|
792
|
+
Links inside HTML comments are ignored by default:
|
|
793
|
+
|
|
794
|
+
```python
|
|
795
|
+
code.filter_links()
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
Include them with:
|
|
799
|
+
|
|
800
|
+
```python
|
|
801
|
+
code.filter_links(comment_links=True)
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
Select only comment links with:
|
|
805
|
+
|
|
806
|
+
```python
|
|
807
|
+
code.filter_links(
|
|
808
|
+
comment_links=True,
|
|
809
|
+
in_comment=True,
|
|
810
|
+
)
|
|
811
|
+
```
|
|
812
|
+
|
|
813
|
+
Comment links use the same `Link` and conversion APIs as other links.
|
|
814
|
+
|
|
815
|
+
## Conversion safety
|
|
816
|
+
|
|
817
|
+
Conversions do not intentionally throw away meaningful destination information.
|
|
818
|
+
|
|
819
|
+
For example, a URL can contain a revision, diff, action, fragment, or extra query parameters that have no exact interwiki spelling. When the page title is known, `to_interwiki()` can fall back to the normal page target; when even that would lose the destination itself, conversion raises `ConversionError`.
|
|
820
|
+
|
|
821
|
+
Category and file links are also treated carefully. A normal `[[Category:...]]` or `[[File:...]]` has MediaWiki behaviour beyond a clickable link, so it is not silently rewritten as a URL. A leading-colon form such as `[[:Category:Help]]` is an ordinary clickable link and can be converted.
|
|
822
|
+
|
|
823
|
+
## Exceptions
|
|
824
|
+
|
|
825
|
+
```python
|
|
826
|
+
wmlinksfromhell.ConversionError
|
|
827
|
+
wmlinksfromhell.MetadataMissingError
|
|
828
|
+
wmlinksfromhell.SourceResolutionError
|
|
829
|
+
wmlinksfromhell.ResolutionError
|
|
830
|
+
wmlinksfromhell.CacheError
|
|
831
|
+
wmlinksfromhell.WMLinksFromHellError
|
|
832
|
+
```
|
|
833
|
+
|
|
834
|
+
`WMLinkFromHellError` and `Error` remain as compatibility aliases for `WMLinksFromHellError`.
|
|
835
|
+
|
|
836
|
+
Normal non-strict resolution returns a `Result` with a status. Use strict mode when you want unresolved input to raise:
|
|
837
|
+
|
|
838
|
+
```python
|
|
839
|
+
result = wmlinksfromhell.resolve(value, strict=True)
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
## Compatibility names
|
|
843
|
+
|
|
844
|
+
The shorter names are preferred for new code:
|
|
845
|
+
|
|
846
|
+
```python
|
|
847
|
+
Code
|
|
848
|
+
Link
|
|
849
|
+
Wiki
|
|
850
|
+
Metadata
|
|
851
|
+
Result
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
The older/public names remain available:
|
|
855
|
+
|
|
856
|
+
```python
|
|
857
|
+
WMCode
|
|
858
|
+
WMLink
|
|
859
|
+
WikiInfo
|
|
860
|
+
MetadataStore
|
|
861
|
+
ResolutionResult
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
## Pywikibot
|
|
865
|
+
|
|
866
|
+
Pywikibot is optional.
|
|
867
|
+
|
|
868
|
+
```python
|
|
869
|
+
import pywikibot
|
|
870
|
+
import wmlinksfromhell
|
|
871
|
+
|
|
872
|
+
site = pywikibot.Site('meta', 'meta')
|
|
873
|
+
page = pywikibot.Page(site, 'Global sysops/Requests')
|
|
874
|
+
|
|
875
|
+
code = wmlinksfromhell.parse_page(page)
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
You can also pass the page to `parse()`:
|
|
879
|
+
|
|
880
|
+
```python
|
|
881
|
+
code = wmlinksfromhell.parse(
|
|
882
|
+
page.text,
|
|
883
|
+
source=page,
|
|
884
|
+
)
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
## Examples
|
|
888
|
+
|
|
889
|
+
The `examples/` directory contains small scripts for:
|
|
890
|
+
|
|
891
|
+
- the simple API
|
|
892
|
+
- selecting links
|
|
893
|
+
- converting links
|
|
894
|
+
- comment links
|
|
895
|
+
- SiteMatrix metadata
|
|
896
|
+
- Pywikibot
|
|
897
|
+
|
|
898
|
+
For installation and a quick introduction, see [README.md](README.md).
|