wikidatum 0.3.0 → 0.3.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 78bb68e7872a77e0dc21f9904d0fd8306b4d4caa23329824d87257a91e503925
4
- data.tar.gz: 84765a7d5f3cee85b0c6ad68953f1d6e9718d068037247f8e8e7e1c4b651c51b
3
+ metadata.gz: bcaa080ee9ab979f63dbde3fc8bca7f819ffd47b0a7d463c5f34bd57e1f2a988
4
+ data.tar.gz: c0226585d7af46f01c7127b7de8ec13cc22a593f414431acd3ec11f580425b88
5
5
  SHA512:
6
- metadata.gz: 24dd512b025f3e618b46ba9b5cc280c2ef500909b7f68c666f29914b5a64e1da63729ded4e321e37461f68f6fdc1f429ec87a71684b773eacb5f25f56ee5c212
7
- data.tar.gz: e43e1b92d171667ce5af5028c56b7d5c28971ef3c3aed93f55a919088e6a990796889eb32293563191d857cf547ca685b6d571bc629a199cbbb6ab332283a731
6
+ metadata.gz: '058da6289ed70d623511a2732b3c83c4d1b574aadc8570cbceee83c23df7adf71ef34e8413783cc1c0e9173c8ea7fcbb419d01b9fd58816278614bfd2f10e83f'
7
+ data.tar.gz: 0a0220e396643884380d858b0fe4cd4ab867f5f3a7ff92ccbbc54440ac4668f490a172f7244d567b093cd753044f845ced5daae3482514fa897cb0a42234ffe6
data/CHANGELOG.md CHANGED
@@ -4,11 +4,29 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
6
 
7
+ ## Unreleased
8
+
9
+ ## 0.3.2 - 2022-12-29
10
+ ### Added
11
+
12
+ - Add support for the `commonsMedia`, `url`, and `external-id` data types.
13
+ - Add `humanized_content` method to `Wikidatum::DataType::Base` class, for easier access to a Struct, string, or nil which represents the contents of the given data type.
14
+
15
+ ## 0.3.1 - 2022-12-28
16
+ ### Added
17
+
18
+ - Add an error message when attempting to make a bot edit without authentication, as this will always trigger a 403 error from the REST API.
19
+
20
+ ### Fixed
21
+
22
+ - Fix the creation of WikibaseItem statements, the format used in the previous release was incorrect.
23
+
7
24
  ## 0.3.0 - 2022-12-27
8
25
  ### Added
9
26
 
10
27
  - Add `allow_ip_edits` argument on `Wikidatum::Client.new`. This protects users from making IP address-exposing edits if they haven't explicitly opted-in to doing that. The argument defaults to false.
11
28
  - Add code to raise errors when various types of invalid input are passed to `Wikidatum::Client#add_statement`.
29
+ - Start testing the gem on Ruby 3.2.
12
30
 
13
31
  ### Fixed
14
32
 
@@ -10,6 +10,8 @@ module Wikidatum
10
10
  STATEMENT_REGEX = /^Q?\d+\$[\w-]+$/.freeze
11
11
  VALID_RANKS = ['preferred', 'normal', 'deprecated'].freeze
12
12
  VALID_DATA_TYPES = [
13
+ 'Wikidatum::DataType::CommonsMedia',
14
+ 'Wikidatum::DataType::ExternalId',
13
15
  'Wikidatum::DataType::GlobeCoordinate',
14
16
  'Wikidatum::DataType::MonolingualText',
15
17
  'Wikidatum::DataType::NoValue',
@@ -17,7 +19,8 @@ module Wikidatum
17
19
  'Wikidatum::DataType::SomeValue',
18
20
  'Wikidatum::DataType::Time',
19
21
  'Wikidatum::DataType::WikibaseItem',
20
- 'Wikidatum::DataType::WikibaseString'
22
+ 'Wikidatum::DataType::WikibaseString',
23
+ 'Wikidatum::DataType::WikibaseUrl'
21
24
  ].freeze
22
25
 
23
26
  # @return [String] the root URL of the Wikibase instance we want to interact
@@ -110,6 +113,19 @@ module Wikidatum
110
113
  Wikidatum::Statement.marshal_load(response)
111
114
  end
112
115
 
116
+ # @!private
117
+ CONTENT_DATA_TYPES = [
118
+ 'Wikidatum::DataType::CommonsMedia',
119
+ 'Wikidatum::DataType::ExternalId',
120
+ 'Wikidatum::DataType::GlobeCoordinate',
121
+ 'Wikidatum::DataType::MonolingualText',
122
+ 'Wikidatum::DataType::Quantity',
123
+ 'Wikidatum::DataType::WikibaseString',
124
+ 'Wikidatum::DataType::Time',
125
+ 'Wikidatum::DataType::WikibaseItem',
126
+ 'Wikidatum::DataType::WikibaseUrl'
127
+ ].freeze
128
+
113
129
  # Add a statement to an item.
114
130
  #
115
131
  # NOTE: Adding references/qualifiers with `add_statement` is untested and
@@ -195,9 +211,36 @@ module Wikidatum
195
211
  # )
196
212
  # )
197
213
  #
214
+ # @example Add a URL statement.
215
+ # wikidatum_client.add_statement(
216
+ # id: 'Q123',
217
+ # property: 'P124',
218
+ # value: Wikidatum::DataType::WikibaseUrl.new(
219
+ # string: 'https://example.com'
220
+ # )
221
+ # )
222
+ #
223
+ # @example Add an External ID statement.
224
+ # wikidatum_client.add_statement(
225
+ # id: 'Q123',
226
+ # property: 'P124',
227
+ # value: Wikidatum::DataType::ExternalId.new(
228
+ # string: '123'
229
+ # )
230
+ # )
231
+ #
232
+ # @example Add a statement for an image, video, or audio file from Wikimedia Commons.
233
+ # wikidatum_client.add_statement(
234
+ # id: 'Q123',
235
+ # property: 'P124',
236
+ # value: Wikidatum::DataType::CommonsMedia.new(
237
+ # string: 'FooBar.jpg'
238
+ # )
239
+ # )
240
+ #
198
241
  # @param id [String, Integer] the ID of the item on which the statement will be added.
199
242
  # @param property [String, Integer] property ID in the format 'P123', or an integer.
200
- # @param value [Wikidatum::DataType::GlobeCoordinate, Wikidatum::DataType::MonolingualText, Wikidatum::DataType::Quantity, Wikidatum::DataType::WikibaseString, Wikidatum::DataType::Time, Wikidatum::DataType::WikibaseItem, Wikidatum::DataType::NoValue, Wikidatum::DataType::SomeValue] the value of the statement being created.
243
+ # @param value [Wikidatum::DataType::CommonsMedia, Wikidatum::DataType::ExternalId, Wikidatum::DataType::GlobeCoordinate, Wikidatum::DataType::MonolingualText, Wikidatum::DataType::Quantity, Wikidatum::DataType::WikibaseString, Wikidatum::DataType::Time, Wikidatum::DataType::WikibaseItem, Wikidatum::DataType::WikibaseUrl, Wikidatum::DataType::NoValue, Wikidatum::DataType::SomeValue] the value of the statement being created.
201
244
  # @param qualifiers [Array<Wikidatum::Qualifier>]
202
245
  # @param references [Array<Wikidatum::Reference>]
203
246
  # @param rank [String, Symbol] Valid ranks are 'preferred', 'normal', or
@@ -233,7 +276,7 @@ module Wikidatum
233
276
  type: 'somevalue'
234
277
  }
235
278
  }
236
- when 'Wikidatum::DataType::GlobeCoordinate', 'Wikidatum::DataType::MonolingualText', 'Wikidatum::DataType::Quantity', 'Wikidatum::DataType::WikibaseString', 'Wikidatum::DataType::Time', 'Wikidatum::DataType::WikibaseItem'
279
+ when *CONTENT_DATA_TYPES
237
280
  statement_hash = {
238
281
  property: {
239
282
  id: property
@@ -245,7 +288,15 @@ module Wikidatum
245
288
  }
246
289
  end
247
290
 
248
- body = { statement: statement_hash.merge({ qualifiers: qualifiers, references: references, rank: rank.to_s, type: 'statement' }) }
291
+ body = {
292
+ statement: statement_hash.merge(
293
+ {
294
+ qualifiers: qualifiers,
295
+ references: references,
296
+ rank: rank.to_s
297
+ }
298
+ )
299
+ }
249
300
 
250
301
  response = post_request("/entities/items/#{id}/statements", body, tags: tags, comment: comment)
251
302
 
@@ -292,6 +343,13 @@ module Wikidatum
292
343
  @allow_ip_edits
293
344
  end
294
345
 
346
+ # Is the current instance of Client editing as a bot?
347
+ #
348
+ # @return [Boolean]
349
+ def bot?
350
+ @bot
351
+ end
352
+
295
353
  private
296
354
 
297
355
  # For now this just returns the `@wikibase_url`, but in the future the API
@@ -426,13 +484,15 @@ module Wikidatum
426
484
  # Check if authentication has been provided, and then check if IP edits
427
485
  # are allowed. If neither condition returns true, raise an error.
428
486
  #
487
+ # Also check if the user is performing IP edits as a bot, which will
488
+ # always return a 403 error from the REST API, and return a specific
489
+ # error message if so.
490
+ #
429
491
  # @return [void]
430
- # @raise [DisallowedIpEditError]
492
+ # @raise [DisallowedIpEditError, DisallowedBotEditError]
431
493
  def ensure_edit_permitted!
432
- return if authenticated?
433
- return if allow_ip_edits?
434
-
435
- raise DisallowedIpEditError
494
+ raise DisallowedIpEditError if !authenticated? && !allow_ip_edits?
495
+ raise DisallowedBotEditError if !authenticated? && bot?
436
496
  end
437
497
  end
438
498
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  # For more information on the possible types that can be returned by
4
4
  # datavalues, see the official documentation:
5
- # https://doc.wikimedia.org/Wikibase/master/php/md_docs_topics_json.html#json_datavalues
5
+ # https://doc.wikimedia.org/Wikibase/master/php/docs_topics_json.html#json_datavalues
6
6
  module Wikidatum::DataType
7
7
  class Base
8
8
  # Represents the type for this instance.
@@ -11,11 +11,14 @@ module Wikidatum::DataType
11
11
  #
12
12
  # - `:no_value`: No value
13
13
  # - `:some_value`: Unknown value
14
+ # - `:commons_media`: {DataType::CommonsMedia}
15
+ # - `:external_id`: {DataType::ExternalId}
14
16
  # - `:globe_coordinate`: {DataType::GlobeCoordinate}
15
17
  # - `:monolingual_text`: {DataType::MonolingualText}
16
18
  # - `:quantity`: {DataType::Quantity}
17
19
  # - `:string`: {DataType::WikibaseString}
18
20
  # - `:time`: {DataType::Time}
21
+ # - `:url`: {DataType::WikibaseUrl}
19
22
  # - `:wikibase_item`: {DataType::WikibaseItem}
20
23
  #
21
24
  # @return [Symbol]
@@ -44,6 +47,14 @@ module Wikidatum::DataType
44
47
  }
45
48
  end
46
49
 
50
+ # Get the humanized version of the content. Depending on the given data
51
+ # type, it will return values in different formats.
52
+ #
53
+ # @return [String, DataType::GlobeCoordinate::HumanizedStruct, DataType::MonolingualText::HumanizedStruct, DataType::Quantity::HumanizedStruct, DataType::Time::HumanizedStruct, nil]
54
+ def humanized_content
55
+ @content.humanized
56
+ end
57
+
47
58
  # @!visibility private
48
59
  #
49
60
  # @param data_type [String] The value of `data-type` for the given Statement or Qualifier's property.
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_type/base'
4
+ require 'wikidatum/data_type/wikibase_string'
5
+
6
+ # Identical to the WikibaseString type, but we'll change some metadata to make
7
+ # it clear that they're technically distinct types.
8
+ class Wikidatum::DataType::CommonsMedia < Wikidatum::DataType::WikibaseString
9
+ # The "type" value used by Wikibase, for use when creating/updating statements.
10
+ #
11
+ # @return [String]
12
+ def wikibase_type
13
+ 'commonsMedia'
14
+ end
15
+
16
+ # @return [Symbol]
17
+ def self.symbolized_name
18
+ :commons_media
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_type/base'
4
+ require 'wikidatum/data_type/wikibase_string'
5
+
6
+ # Identical to the WikibaseString type, but we'll change some metadata to make
7
+ # it clear that they're technically distinct types.
8
+ class Wikidatum::DataType::ExternalId < Wikidatum::DataType::WikibaseString
9
+ # The "type" value used by Wikibase, for use when creating/updating statements.
10
+ #
11
+ # @return [String]
12
+ def wikibase_type
13
+ 'external-id'
14
+ end
15
+
16
+ # @return [Symbol]
17
+ def self.symbolized_name
18
+ :external_id
19
+ end
20
+ end
@@ -63,9 +63,19 @@ class Wikidatum::DataType::GlobeCoordinate
63
63
  'globe-coordinate'
64
64
  end
65
65
 
66
+ HumanizedStruct = Struct.new(:latitude, :longitude, :precision, :globe, keyword_init: true)
67
+
68
+ # The content of the data value object. Use this to get a more sensible
69
+ # representation of the statement's contents.
70
+ #
71
+ # @return [HumanizedStruct<latitude, longitude, precision, globe>]
72
+ def humanized
73
+ HumanizedStruct.new(to_h)
74
+ end
75
+
66
76
  # @return [Symbol]
67
77
  def self.symbolized_name
68
- :monolingual_text
78
+ :globe_coordinate
69
79
  end
70
80
 
71
81
  # @!visibility private
@@ -49,6 +49,16 @@ class Wikidatum::DataType::MonolingualText
49
49
  'monolingualtext'
50
50
  end
51
51
 
52
+ HumanizedStruct = Struct.new(:language, :text, keyword_init: true)
53
+
54
+ # The content of the data value object. Use this to get a more sensible
55
+ # representation of the statement's contents.
56
+ #
57
+ # @return [HumanizedStruct<language, text>]
58
+ def humanized
59
+ HumanizedStruct.new(to_h)
60
+ end
61
+
52
62
  # @return [Symbol]
53
63
  def self.symbolized_name
54
64
  :monolingual_text
@@ -9,11 +9,21 @@ require 'wikidatum/data_type/base'
9
9
  class Wikidatum::DataType::NoValue < Wikidatum::DataType::Base
10
10
  # The "type" value used by Wikibase, for use when creating/updating statements.
11
11
  #
12
+ # In this case, the type is a lie.
13
+ #
12
14
  # @return [String]
13
15
  def wikibase_type
14
16
  'string'
15
17
  end
16
18
 
19
+ # The content of the data value object. Use this to get a more sensible
20
+ # representation of the statement's contents.
21
+ #
22
+ # @return [nil]
23
+ def humanized
24
+ nil
25
+ end
26
+
17
27
  # @!visibility private
18
28
  def self.marshal_load(_data_value_json)
19
29
  new(type: :no_value, content: nil)
@@ -49,6 +49,16 @@ class Wikidatum::DataType::Quantity
49
49
  'quantity'
50
50
  end
51
51
 
52
+ HumanizedStruct = Struct.new(:amount, :unit, keyword_init: true)
53
+
54
+ # The content of the data value object. Use this to get a more sensible
55
+ # representation of the statement's contents.
56
+ #
57
+ # @return [HumanizedStruct<amount, unit>]
58
+ def humanized
59
+ HumanizedStruct.new(to_h)
60
+ end
61
+
52
62
  # @return [Symbol]
53
63
  def self.symbolized_name
54
64
  :quantity
@@ -9,11 +9,21 @@ require 'wikidatum/data_type/base'
9
9
  class Wikidatum::DataType::SomeValue < Wikidatum::DataType::Base
10
10
  # The "type" value used by Wikibase, for use when creating/updating statements.
11
11
  #
12
+ # In this case, the type is a lie.
13
+ #
12
14
  # @return [String]
13
15
  def wikibase_type
14
16
  'string'
15
17
  end
16
18
 
19
+ # The content of the data value object. Use this to get a more sensible
20
+ # representation of the statement's contents.
21
+ #
22
+ # @return [nil]
23
+ def humanized
24
+ nil
25
+ end
26
+
17
27
  # @!visibility private
18
28
  def self.marshal_load(_data_value_json)
19
29
  new(type: :some_value, content: nil)
@@ -109,6 +109,16 @@ class Wikidatum::DataType::Time
109
109
  'time'
110
110
  end
111
111
 
112
+ HumanizedStruct = Struct.new(:time, :precision, :calendar_model, keyword_init: true)
113
+
114
+ # The content of the data value object. Use this to get a more sensible
115
+ # representation of the statement's contents.
116
+ #
117
+ # @return [HumanizedStruct<time, precision, pretty_precision, calendar_model>]
118
+ def humanized
119
+ HumanizedStruct.new(to_h)
120
+ end
121
+
112
122
  # @return [Symbol]
113
123
  def self.symbolized_name
114
124
  :time
@@ -40,6 +40,14 @@ class Wikidatum::DataType::WikibaseItem
40
40
  'wikibase-item'
41
41
  end
42
42
 
43
+ # The content of the data value object. Use this to get a more sensible
44
+ # representation of the statement's contents.
45
+ #
46
+ # @return [String]
47
+ def humanized
48
+ @id
49
+ end
50
+
43
51
  # @return [Symbol]
44
52
  def self.symbolized_name
45
53
  :wikibase_item
@@ -57,8 +65,6 @@ class Wikidatum::DataType::WikibaseItem
57
65
 
58
66
  # @!visibility private
59
67
  def marshal_dump
60
- {
61
- id: @id
62
- }
68
+ @id
63
69
  end
64
70
  end
@@ -40,6 +40,14 @@ class Wikidatum::DataType::WikibaseString
40
40
  'string'
41
41
  end
42
42
 
43
+ # The content of the data value object. Use this to get a more sensible
44
+ # representation of the statement's contents.
45
+ #
46
+ # @return [String]
47
+ def humanized
48
+ @string
49
+ end
50
+
43
51
  # @return [Symbol]
44
52
  def self.symbolized_name
45
53
  :string
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_type/base'
4
+ require 'wikidatum/data_type/wikibase_string'
5
+
6
+ # Identical to the WikibaseString type, but we'll change some metadata to make
7
+ # it clear that they're technically distinct types.
8
+ class Wikidatum::DataType::WikibaseUrl < Wikidatum::DataType::WikibaseString
9
+ # The "type" value used by Wikibase, for use when creating/updating statements.
10
+ #
11
+ # @return [String]
12
+ def wikibase_type
13
+ 'url'
14
+ end
15
+
16
+ # @return [Symbol]
17
+ def self.symbolized_name
18
+ :url
19
+ end
20
+ end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'wikidatum/data_type/base'
4
+ require 'wikidatum/data_type/commons_media'
5
+ require 'wikidatum/data_type/external_id'
4
6
  require 'wikidatum/data_type/globe_coordinate'
5
7
  require 'wikidatum/data_type/monolingual_text'
6
8
  require 'wikidatum/data_type/no_value'
@@ -9,3 +11,4 @@ require 'wikidatum/data_type/some_value'
9
11
  require 'wikidatum/data_type/time'
10
12
  require 'wikidatum/data_type/wikibase_item'
11
13
  require 'wikidatum/data_type/wikibase_string'
14
+ require 'wikidatum/data_type/wikibase_url'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wikidatum
4
- VERSION = '0.3.0'
4
+ VERSION = '0.3.2'
5
5
  end
data/lib/wikidatum.rb CHANGED
@@ -24,6 +24,15 @@ module Wikidatum
24
24
  end
25
25
  end
26
26
 
27
+ # If the Wikidatum::Client is set to mark their edits as belonging to a bot,
28
+ # they must be authenticated as a bot user. We will disallow these edits
29
+ # as long as they're not authenticated as a specific user.
30
+ class DisallowedBotEditError < Error
31
+ def message
32
+ 'No authentication provided, but attempted to edit as a bot. You cannot make edits as a bot unless you have authenticated as a user with the Bot flag.'
33
+ end
34
+ end
35
+
27
36
  # rubocop:disable Naming/ConstantName
28
37
 
29
38
  # These language codes are not enforced, you can pass whatever language code
@@ -56,9 +65,10 @@ module Wikidatum
56
65
  end
57
66
 
58
67
  module DataType
59
- # TODO: Add commonsMedia and url to the possible types.
60
68
  # rubocop:disable Lint/SymbolConversion
61
69
  DATA_TYPES = {
70
+ 'commonsMedia': 'Wikidatum::DataType::CommonsMedia',
71
+ 'external-id': 'Wikidatum::DataType::ExternalId',
62
72
  'globe-coordinate': 'Wikidatum::DataType::GlobeCoordinate',
63
73
  'monolingualtext': 'Wikidatum::DataType::MonolingualText',
64
74
  'novalue': 'Wikidatum::DataType::NoValue',
@@ -66,6 +76,7 @@ module Wikidatum
66
76
  'somevalue': 'Wikidatum::DataType::SomeValue',
67
77
  'string': 'Wikidatum::DataType::WikibaseString',
68
78
  'time': 'Wikidatum::DataType::Time',
79
+ 'url': 'Wikidatum::DataType::WikibaseUrl',
69
80
  'wikibase-item': 'Wikidatum::DataType::WikibaseItem'
70
81
  }.freeze
71
82
  # rubocop:enable Lint/SymbolConversion
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wikidatum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Connor Shea
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-12-28 00:00:00.000000000 Z
11
+ date: 2022-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -40,6 +40,8 @@ files:
40
40
  - lib/wikidatum/client.rb
41
41
  - lib/wikidatum/data_type.rb
42
42
  - lib/wikidatum/data_type/base.rb
43
+ - lib/wikidatum/data_type/commons_media.rb
44
+ - lib/wikidatum/data_type/external_id.rb
43
45
  - lib/wikidatum/data_type/globe_coordinate.rb
44
46
  - lib/wikidatum/data_type/monolingual_text.rb
45
47
  - lib/wikidatum/data_type/no_value.rb
@@ -48,6 +50,7 @@ files:
48
50
  - lib/wikidatum/data_type/time.rb
49
51
  - lib/wikidatum/data_type/wikibase_item.rb
50
52
  - lib/wikidatum/data_type/wikibase_string.rb
53
+ - lib/wikidatum/data_type/wikibase_url.rb
51
54
  - lib/wikidatum/item.rb
52
55
  - lib/wikidatum/qualifier.rb
53
56
  - lib/wikidatum/reference.rb