mediawiki-gateway 0.2.6 → 0.3.0
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.
- data/README +14 -5
- data/Rakefile +3 -2
- data/doc/classes/MediaWiki.html +16 -14
- data/doc/classes/MediaWiki/Gateway.html +381 -328
- data/doc/created.rid +1 -1
- data/doc/files/README.html +37 -10
- data/doc/files/lib/media_wiki/gateway_rb.html +1 -1
- data/doc/files/lib/media_wiki/utils_rb.html +1 -1
- data/lib/media_wiki.rb +1 -1
- data/lib/media_wiki/gateway.rb +49 -26
- data/mediawiki-gateway.gemspec +13 -8
- data/spec/fake_media_wiki/app.rb +3 -1
- data/spec/gateway_spec.rb +22 -13
- data/spec/spec_helper.rb +16 -0
- data/spec/utils_spec.rb +1 -1
- metadata +23 -7
data/doc/created.rid
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
Thu, 13 Jan 2011 14:03:28 +1100
|
data/doc/files/README.html
CHANGED
@@ -56,7 +56,7 @@
|
|
56
56
|
</tr>
|
57
57
|
<tr class="top-aligned-row">
|
58
58
|
<td><strong>Last Update:</strong></td>
|
59
|
-
<td>
|
59
|
+
<td>Thu Jan 13 14:03:08 +1100 2011</td>
|
60
60
|
</tr>
|
61
61
|
</table>
|
62
62
|
</div>
|
@@ -70,16 +70,40 @@
|
|
70
70
|
|
71
71
|
<div id="description">
|
72
72
|
<h1><a href="../classes/MediaWiki/Gateway.html">MediaWiki::Gateway</a></h1>
|
73
|
-
<
|
74
|
-
Ruby framework for MediaWiki API
|
73
|
+
<p>
|
74
|
+
A Ruby framework for <a href="../classes/MediaWiki.html">MediaWiki</a> API
|
75
|
+
manipulation. Features out of the box:
|
76
|
+
</p>
|
77
|
+
<ul>
|
78
|
+
<li>Simple, elegant syntax for common operations
|
75
79
|
|
76
|
-
|
77
|
-
|
78
|
-
|
80
|
+
</li>
|
81
|
+
<li>Handles login, edit, move etc tokens for you
|
82
|
+
|
83
|
+
</li>
|
84
|
+
<li>Support for maxlag detection and automated retries on 503
|
85
|
+
|
86
|
+
</li>
|
87
|
+
<li>Integrated logging
|
88
|
+
|
89
|
+
</li>
|
90
|
+
<li>Tested up to <a href="../classes/MediaWiki.html">MediaWiki</a> 1.16
|
91
|
+
|
92
|
+
</li>
|
93
|
+
</ul>
|
94
|
+
<p>
|
95
|
+
Gem: <a
|
96
|
+
href="http://rubygems.org/gems/mediawiki-gateway">rubygems.org/gems/mediawiki-gateway</a>
|
97
|
+
RDoc: <a
|
98
|
+
href="http://rubydoc.info/gems/mediawiki-gateway">rubydoc.info/gems/mediawiki-gateway</a>
|
99
|
+
Git: <a
|
100
|
+
href="https://github.com/jpatokal/mediawiki-gateway">github.com/jpatokal/mediawiki-gateway</a>
|
101
|
+
</p>
|
79
102
|
<h2>Example</h2>
|
103
|
+
<p>
|
104
|
+
Simple page creation script:
|
105
|
+
</p>
|
80
106
|
<pre>
|
81
|
-
Simple page creation script:
|
82
|
-
|
83
107
|
require 'media_wiki'
|
84
108
|
mw = MediaWiki::Gateway.new('http://my-wiki.example/w/api.php')
|
85
109
|
mw.login('RubyBot', 'pa$$w0rd')
|
@@ -87,8 +111,11 @@
|
|
87
111
|
</pre>
|
88
112
|
<h2>Credits</h2>
|
89
113
|
<p>
|
90
|
-
|
91
|
-
|
114
|
+
Maintained by Jani Patokallio.
|
115
|
+
</p>
|
116
|
+
<p>
|
117
|
+
Thanks to John Carney, Mike Williams, Daniel Heath and the rest of the
|
118
|
+
Lonely Planet Atlas team.
|
92
119
|
</p>
|
93
120
|
|
94
121
|
</div>
|
data/lib/media_wiki.rb
CHANGED
data/lib/media_wiki/gateway.rb
CHANGED
@@ -5,18 +5,33 @@ require 'rexml/document'
|
|
5
5
|
require 'uri'
|
6
6
|
|
7
7
|
module MediaWiki
|
8
|
-
|
8
|
+
|
9
9
|
class Gateway
|
10
|
-
|
11
|
-
|
10
|
+
attr_reader :log
|
11
|
+
|
12
12
|
# Set up a MediaWiki::Gateway for a given MediaWiki installation
|
13
13
|
#
|
14
14
|
# [url] Path to API of target MediaWiki (eg. "http://en.wikipedia.org/w/api.php")
|
15
|
-
# [
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
# [options] Hash of options
|
16
|
+
#
|
17
|
+
# Options:
|
18
|
+
# [:limit] Maximum number of results returned per search (see http://www.mediawiki.org/wiki/API:Query_-_Lists#Limits), defaults to the MediaWiki default of 500.
|
19
|
+
# [:loglevel] Log level to use, defaults to Logger::WARN. Set to Logger::DEBUG to dump every request and response to the log.
|
20
|
+
# [:maxlag] Maximum allowed server lag (see http://www.mediawiki.org/wiki/Manual:Maxlag_parameter), defaults to 5 seconds.
|
21
|
+
# [:retry_count] Number of times to try before giving up if MediaWiki returns 503 Service Unavailable, defaults to 3 (original request plus two retries).
|
22
|
+
# [:retry_delay] Seconds to wait before retry if MediaWiki returns 503 Service Unavailable, defaults to 10 seconds.
|
23
|
+
def initialize(url, options={})
|
24
|
+
default_options = {
|
25
|
+
:limit => 500,
|
26
|
+
:loglevel => Logger::WARN,
|
27
|
+
:maxlag => 5,
|
28
|
+
:retry_count => 3,
|
29
|
+
:retry_delay => 10
|
30
|
+
}
|
31
|
+
@options = default_options.merge(options)
|
19
32
|
@wiki_url = url
|
33
|
+
@log = Logger.new(STDERR)
|
34
|
+
@log.level = @options[:loglevel]
|
20
35
|
@headers = { "User-Agent" => "MediaWiki::Gateway/#{MediaWiki::VERSION}" }
|
21
36
|
@cookies = {}
|
22
37
|
end
|
@@ -58,9 +73,9 @@ module MediaWiki
|
|
58
73
|
# [options] Hash of additional options
|
59
74
|
#
|
60
75
|
# Options:
|
61
|
-
# * [linkbase] supply a String to prefix all internal (relative) links with. '/wiki/' is assumed to be the base of a relative link
|
62
|
-
# * [noeditsections] strips all edit-links if set to +true+
|
63
|
-
# * [noimages] strips all +img+ tags from the rendered text if set to +true+
|
76
|
+
# * [:linkbase] supply a String to prefix all internal (relative) links with. '/wiki/' is assumed to be the base of a relative link
|
77
|
+
# * [:noeditsections] strips all edit-links if set to +true+
|
78
|
+
# * [:noimages] strips all +img+ tags from the rendered text if set to +true+
|
64
79
|
#
|
65
80
|
# Returns rendered page as string, or nil if the page does not exist
|
66
81
|
def render(page_title, options = {})
|
@@ -96,9 +111,9 @@ module MediaWiki
|
|
96
111
|
# [options] Hash of additional options
|
97
112
|
#
|
98
113
|
# Options:
|
99
|
-
# * [overwrite] Allow overwriting existing pages
|
100
|
-
# * [summary] Edit summary for history, string
|
101
|
-
# * [token] Use this existing edit token instead requesting a new one (useful for bulk loads)
|
114
|
+
# * [:overwrite] Allow overwriting existing pages
|
115
|
+
# * [:summary] Edit summary for history, string
|
116
|
+
# * [:token] Use this existing edit token instead requesting a new one (useful for bulk loads)
|
102
117
|
def create(title, content, options={})
|
103
118
|
form_data = {'action' => 'edit', 'title' => title, 'text' => content, 'summary' => (options[:summary] || ""), 'token' => get_token('edit', title)}
|
104
119
|
form_data['createonly'] = "" unless options[:overwrite]
|
@@ -112,12 +127,12 @@ module MediaWiki
|
|
112
127
|
# [options] Hash of additional options
|
113
128
|
#
|
114
129
|
# Options:
|
115
|
-
# * [movesubpages] Move associated subpages
|
116
|
-
# * [movetalk] Move associated talkpages
|
117
|
-
# * [noredirect] Do not create a redirect page from old name. Requires the 'suppressredirect' user right, otherwise MW will silently ignore the option and create the redirect anyway.
|
118
|
-
# * [reason] Reason for move
|
119
|
-
# * [watch] Add page and any redirect to watchlist
|
120
|
-
# * [unwatch] Remove page and any redirect from watchlist
|
130
|
+
# * [:movesubpages] Move associated subpages
|
131
|
+
# * [:movetalk] Move associated talkpages
|
132
|
+
# * [:noredirect] Do not create a redirect page from old name. Requires the 'suppressredirect' user right, otherwise MW will silently ignore the option and create the redirect anyway.
|
133
|
+
# * [:reason] Reason for move
|
134
|
+
# * [:watch] Add page and any redirect to watchlist
|
135
|
+
# * [:unwatch] Remove page and any redirect from watchlist
|
121
136
|
def move(from, to, options={})
|
122
137
|
valid_options = %w(movesubpages movetalk noredirect reason watch unwatch)
|
123
138
|
options.keys.each{|opt| raise ArgumentError.new("Unknown option '#{opt}'") unless valid_options.include?(opt.to_s)}
|
@@ -166,7 +181,7 @@ module MediaWiki
|
|
166
181
|
'list' => 'allpages',
|
167
182
|
'apfrom' => apfrom,
|
168
183
|
'apprefix' => key,
|
169
|
-
'aplimit' =>
|
184
|
+
'aplimit' => @options[:limit],
|
170
185
|
'apnamespace' => namespace}
|
171
186
|
res = make_api_request(form_data)
|
172
187
|
apfrom = res.elements['query-continue'] ? res.elements['query-continue/allpages'].attributes['apfrom'] : nil
|
@@ -190,7 +205,7 @@ module MediaWiki
|
|
190
205
|
'list' => 'backlinks',
|
191
206
|
'bltitle' => title,
|
192
207
|
'blfilterredir' => filter,
|
193
|
-
'bllimit' =>
|
208
|
+
'bllimit' => @options[:limit] }
|
194
209
|
form_data['blcontinue'] = blcontinue if blcontinue
|
195
210
|
res = make_api_request(form_data)
|
196
211
|
blcontinue = res.elements['query-continue'] ? res.elements['query-continue/backlinks'].attributes['blcontinue'] : nil
|
@@ -448,10 +463,18 @@ module MediaWiki
|
|
448
463
|
# [form_data] hash or string of attributes to post
|
449
464
|
#
|
450
465
|
# Returns XML document
|
451
|
-
def make_api_request(form_data)
|
452
|
-
|
453
|
-
|
454
|
-
|
466
|
+
def make_api_request(form_data, retry_count=1)
|
467
|
+
if form_data.kind_of? Hash
|
468
|
+
form_data['format'] = 'xml'
|
469
|
+
form_data['maxlag'] = @options[:maxlag]
|
470
|
+
end
|
471
|
+
log.debug("REQ: #{form_data.inspect}, #{@cookies.inspect}")
|
472
|
+
RestClient.post(@wiki_url, form_data, @headers.merge({:cookies => @cookies})) do |response, &block|
|
473
|
+
if response.code == 503 and retry_count < @options[:retry_count]
|
474
|
+
log.warn("503 Service Unavailable: #{response.body}. Retry in #{@options[:retry_delay]} seconds.")
|
475
|
+
sleep @options[:retry_delay]
|
476
|
+
make_api_request(form_data, retry_count + 1)
|
477
|
+
end
|
455
478
|
# Check response for errors and return XML
|
456
479
|
raise "API error, bad response: #{response}" unless response.code >= 200 and response.code < 300
|
457
480
|
doc = get_response(response.dup)
|
@@ -478,7 +501,7 @@ module MediaWiki
|
|
478
501
|
rescue REXML::ParseException => e
|
479
502
|
raise "Response is not XML. Are you sure you are pointing to api.php?"
|
480
503
|
end
|
481
|
-
|
504
|
+
log.debug("RES: #{doc}")
|
482
505
|
raise "Response does not contain Mediawiki API XML: #{res}" unless [ "api", "mediawiki" ].include? doc.name
|
483
506
|
if doc.elements["error"]
|
484
507
|
code = doc.elements["error"].attributes["code"]
|
data/mediawiki-gateway.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{mediawiki-gateway}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jani Patokallio"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-01-13}
|
13
13
|
s.description = %q{}
|
14
14
|
s.email = %q{jpatokal@iki.fi}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -58,6 +58,7 @@ Gem::Specification.new do |s|
|
|
58
58
|
"spec/fake_media_wiki/query_handling.rb",
|
59
59
|
"spec/gateway_spec.rb",
|
60
60
|
"spec/import-test-data.xml",
|
61
|
+
"spec/spec_helper.rb",
|
61
62
|
"spec/utils_spec.rb"
|
62
63
|
]
|
63
64
|
s.homepage = %q{http://github.com/jpatokal/mediawiki-gateway}
|
@@ -69,6 +70,7 @@ Gem::Specification.new do |s|
|
|
69
70
|
"spec/fake_media_wiki/app.rb",
|
70
71
|
"spec/fake_media_wiki/query_handling.rb",
|
71
72
|
"spec/gateway_spec.rb",
|
73
|
+
"spec/spec_helper.rb",
|
72
74
|
"spec/utils_spec.rb"
|
73
75
|
]
|
74
76
|
|
@@ -78,20 +80,23 @@ Gem::Specification.new do |s|
|
|
78
80
|
|
79
81
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
80
82
|
s.add_runtime_dependency(%q<rest-client>, [">= 0"])
|
81
|
-
s.add_development_dependency(%q<sham_rack>, [">= 0"])
|
82
|
-
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
83
83
|
s.add_development_dependency(%q<activesupport>, [">= 0"])
|
84
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
85
|
+
s.add_development_dependency(%q<sham_rack>, [">= 0"])
|
86
|
+
s.add_development_dependency(%q<rr>, [">= 0"])
|
84
87
|
else
|
85
88
|
s.add_dependency(%q<rest-client>, [">= 0"])
|
86
|
-
s.add_dependency(%q<sham_rack>, [">= 0"])
|
87
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
88
89
|
s.add_dependency(%q<activesupport>, [">= 0"])
|
90
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
91
|
+
s.add_dependency(%q<sham_rack>, [">= 0"])
|
92
|
+
s.add_dependency(%q<rr>, [">= 0"])
|
89
93
|
end
|
90
94
|
else
|
91
95
|
s.add_dependency(%q<rest-client>, [">= 0"])
|
92
|
-
s.add_dependency(%q<sham_rack>, [">= 0"])
|
93
|
-
s.add_dependency(%q<jeweler>, [">= 0"])
|
94
96
|
s.add_dependency(%q<activesupport>, [">= 0"])
|
97
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
98
|
+
s.add_dependency(%q<sham_rack>, [">= 0"])
|
99
|
+
s.add_dependency(%q<rr>, [">= 0"])
|
95
100
|
end
|
96
101
|
end
|
97
102
|
|
data/spec/fake_media_wiki/app.rb
CHANGED
@@ -57,9 +57,11 @@ module FakeMediaWiki
|
|
57
57
|
def logged_in(username)
|
58
58
|
@logged_in_users.include?(username)
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
post "/w/api.php" do
|
62
62
|
begin
|
63
|
+
halt(503, "Maxlag exceeded") if params[:maxlag].to_i < 0
|
64
|
+
|
63
65
|
@token = ApiToken.new(params)
|
64
66
|
action = params[:action]
|
65
67
|
if respond_to?(action)
|
data/spec/gateway_spec.rb
CHANGED
@@ -1,17 +1,8 @@
|
|
1
|
-
require '
|
2
|
-
if ActiveSupport::VERSION::MAJOR >= 3
|
3
|
-
# :nodoc: Rails 3: #to_xml is defined in ActiveModel::Serializers::Xml
|
4
|
-
require 'active_model'
|
5
|
-
Hash.send(:include, ActiveModel::Serializers::Xml)
|
6
|
-
else
|
7
|
-
# :nodoc: Rails 2.3.x: Hash#to_xml is defined in active_support
|
8
|
-
require 'active_support'
|
9
|
-
end
|
10
|
-
require 'sham_rack'
|
1
|
+
require 'spec_helper'
|
11
2
|
|
12
|
-
|
3
|
+
# Kickstart fake media wiki app
|
4
|
+
require 'sham_rack'
|
13
5
|
require 'spec/fake_media_wiki/app'
|
14
|
-
|
15
6
|
$fake_media_wiki = FakeMediaWiki::App.new
|
16
7
|
ShamRack.mount($fake_media_wiki, 'dummy-wiki.example')
|
17
8
|
|
@@ -192,6 +183,25 @@ describe MediaWiki::Gateway do
|
|
192
183
|
|
193
184
|
end
|
194
185
|
|
186
|
+
describe "when wiki returns 503" do
|
187
|
+
|
188
|
+
before do
|
189
|
+
@log = Object.new
|
190
|
+
stub(@log).debug { }
|
191
|
+
stub(@log).warn { }
|
192
|
+
@fail_gateway = MediaWiki::Gateway.new('http://dummy-wiki.example/w/api.php', {:maxlag => -1, :retry_delay => 0})
|
193
|
+
stub(@fail_gateway).log { @log }
|
194
|
+
end
|
195
|
+
|
196
|
+
it "should retry twice and fail" do
|
197
|
+
lambda {
|
198
|
+
@fail_gateway.get("")
|
199
|
+
}.should raise_error
|
200
|
+
@log.should have_received.warn("503 Service Unavailable: Maxlag exceeded. Retry in 0 seconds.").times(2)
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
195
205
|
end
|
196
206
|
|
197
207
|
describe "#render" do
|
@@ -330,7 +340,6 @@ describe MediaWiki::Gateway do
|
|
330
340
|
describe "when uploading a new file" do
|
331
341
|
|
332
342
|
before do
|
333
|
-
pending "stubbing broken in mysterious ways"
|
334
343
|
stub(File).new(anything) { "SAMPLEIMAGEDATA" }
|
335
344
|
@page = @gateway.upload("some/path/sample_image.jpg")
|
336
345
|
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'media_wiki'
|
2
|
+
|
3
|
+
require 'rr'
|
4
|
+
Spec::Runner.configure do |config|
|
5
|
+
config.mock_with RR::Adapters::Rspec
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'active_support/version'
|
9
|
+
if ActiveSupport::VERSION::MAJOR >= 3
|
10
|
+
# :nodoc: Rails 3: #to_xml is defined in ActiveModel::Serializers::Xml
|
11
|
+
require 'active_model'
|
12
|
+
Hash.send(:include, ActiveModel::Serializers::Xml)
|
13
|
+
else
|
14
|
+
# :nodoc: Rails 2.3.x: Hash#to_xml is defined in active_support
|
15
|
+
require 'active_support'
|
16
|
+
end
|
data/spec/utils_spec.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mediawiki-gateway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jani Patokallio
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2011-01-13 00:00:00 +11:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
|
-
name:
|
36
|
+
name: activesupport
|
37
37
|
prerelease: false
|
38
38
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
@@ -61,7 +61,7 @@ dependencies:
|
|
61
61
|
type: :development
|
62
62
|
version_requirements: *id003
|
63
63
|
- !ruby/object:Gem::Dependency
|
64
|
-
name:
|
64
|
+
name: sham_rack
|
65
65
|
prerelease: false
|
66
66
|
requirement: &id004 !ruby/object:Gem::Requirement
|
67
67
|
none: false
|
@@ -74,6 +74,20 @@ dependencies:
|
|
74
74
|
version: "0"
|
75
75
|
type: :development
|
76
76
|
version_requirements: *id004
|
77
|
+
- !ruby/object:Gem::Dependency
|
78
|
+
name: rr
|
79
|
+
prerelease: false
|
80
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
type: :development
|
90
|
+
version_requirements: *id005
|
77
91
|
description: ""
|
78
92
|
email: jpatokal@iki.fi
|
79
93
|
executables: []
|
@@ -125,6 +139,7 @@ files:
|
|
125
139
|
- spec/fake_media_wiki/query_handling.rb
|
126
140
|
- spec/gateway_spec.rb
|
127
141
|
- spec/import-test-data.xml
|
142
|
+
- spec/spec_helper.rb
|
128
143
|
- spec/utils_spec.rb
|
129
144
|
has_rdoc: true
|
130
145
|
homepage: http://github.com/jpatokal/mediawiki-gateway
|
@@ -165,4 +180,5 @@ test_files:
|
|
165
180
|
- spec/fake_media_wiki/app.rb
|
166
181
|
- spec/fake_media_wiki/query_handling.rb
|
167
182
|
- spec/gateway_spec.rb
|
183
|
+
- spec/spec_helper.rb
|
168
184
|
- spec/utils_spec.rb
|