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/doc/created.rid CHANGED
@@ -1 +1 @@
1
- Mon, 13 Dec 2010 14:34:22 +1100
1
+ Thu, 13 Jan 2011 14:03:28 +1100
@@ -56,7 +56,7 @@
56
56
  </tr>
57
57
  <tr class="top-aligned-row">
58
58
  <td><strong>Last Update:</strong></td>
59
- <td>Fri Nov 26 10:40:15 +1100 2010</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
- <pre>
74
- Ruby framework for MediaWiki API manipulation
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
- Gem: http://rubygems.org/gems/mediawiki-gateway
77
- RDoc: http://rubydoc.info/gems/mediawiki-gateway
78
- </pre>
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
- Thanks to John Carney, Mike Williams, Dan Heath and the rest of the Lonely
91
- Planet Atlas team.
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>
@@ -56,7 +56,7 @@
56
56
  </tr>
57
57
  <tr class="top-aligned-row">
58
58
  <td><strong>Last Update:</strong></td>
59
- <td>Mon Dec 13 14:32:14 +1100 2010</td>
59
+ <td>Thu Jan 13 13:54:09 +1100 2011</td>
60
60
  </tr>
61
61
  </table>
62
62
  </div>
@@ -56,7 +56,7 @@
56
56
  </tr>
57
57
  <tr class="top-aligned-row">
58
58
  <td><strong>Last Update:</strong></td>
59
- <td>Mon Dec 13 13:38:27 +1100 2010</td>
59
+ <td>Thu Jan 13 11:10:57 +1100 2011</td>
60
60
  </tr>
61
61
  </table>
62
62
  </div>
data/lib/media_wiki.rb CHANGED
@@ -3,5 +3,5 @@ require File.dirname(__FILE__) + '/media_wiki/utils'
3
3
  require File.dirname(__FILE__) + '/media_wiki/gateway'
4
4
 
5
5
  module MediaWiki
6
- VERSION = "0.2.6"
6
+ VERSION = "0.3.0"
7
7
  end
@@ -5,18 +5,33 @@ require 'rexml/document'
5
5
  require 'uri'
6
6
 
7
7
  module MediaWiki
8
-
8
+
9
9
  class Gateway
10
- API_MAX_LIMIT = 500
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
- # [loglevel] Log level to use (optional, defaults to Logger::WARN)
16
- def initialize(url, loglevel = Logger::WARN)
17
- @log = Logger.new(STDERR)
18
- @log.level = loglevel
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' => API_MAX_LIMIT,
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' => API_MAX_LIMIT }
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
- form_data['format'] = 'xml' if form_data.kind_of? Hash
453
- @log.debug("REQ: #{form_data.inspect}, #{@cookies.inspect}")
454
- RestClient.post(@wiki_url, form_data, @headers.merge({:cookies => @cookies})) do |response, &block|
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
- @log.debug("RES: #{doc}")
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"]
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{mediawiki-gateway}
8
- s.version = "0.2.6"
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{2010-12-30}
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
 
@@ -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 'active_support/version'
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
- require 'media_wiki'
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
@@ -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
@@ -1,4 +1,4 @@
1
- require 'media_wiki'
1
+ require 'spec_helper'
2
2
 
3
3
  describe MediaWiki do
4
4
 
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: 27
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
9
- - 6
10
- version: 0.2.6
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: 2010-12-30 00:00:00 +11:00
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: sham_rack
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: activesupport
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