wikidatum 0.2.0 → 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.
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ # For more information on the possible types that can be returned by
4
+ # datavalues, see the official documentation:
5
+ # https://doc.wikimedia.org/Wikibase/master/php/md_docs_topics_json.html#json_datavalues
6
+ module Wikidatum::DataType
7
+ class Base
8
+ # Represents the type for this instance.
9
+ #
10
+ # Possible values for the `type` attribute are:
11
+ #
12
+ # - `:no_value`: No value
13
+ # - `:some_value`: Unknown value
14
+ # - `:globe_coordinate`: {DataType::GlobeCoordinate}
15
+ # - `:monolingual_text`: {DataType::MonolingualText}
16
+ # - `:quantity`: {DataType::Quantity}
17
+ # - `:string`: {DataType::WikibaseString}
18
+ # - `:time`: {DataType::Time}
19
+ # - `:wikibase_item`: {DataType::WikibaseItem}
20
+ #
21
+ # @return [Symbol]
22
+ attr_reader :type
23
+
24
+ # The value of the "content" attribute in the response.
25
+ #
26
+ # If the `type` is `novalue` or `somevalue`, this returns `nil`.
27
+ #
28
+ # @return [DataType::GlobeCoordinate, DataType::MonolingualText, DataType::Quantity, DataType::WikibaseString, DataType::Time, DataType::WikibaseItem, nil]
29
+ attr_reader :content
30
+
31
+ # @param type [Symbol]
32
+ # @param content [DataType::GlobeCoordinate, DataType::MonolingualText, DataType::Quantity, DataType::WikibaseString, DataType::Time, DataType::WikibaseItem, nil] nil if type is no_value or some_value
33
+ # @return [void]
34
+ def initialize(type:, content:)
35
+ @type = type
36
+ @content = content
37
+ end
38
+
39
+ # @return [Hash]
40
+ def to_h
41
+ {
42
+ type: @type,
43
+ content: @content&.to_h
44
+ }
45
+ end
46
+
47
+ # @!visibility private
48
+ #
49
+ # @param data_type [String] The value of `data-type` for the given Statement or Qualifier's property.
50
+ # @param data_value_json [Hash] The `content` part of value object.
51
+ # @return [Wikidatum::DataType::Base] An instance of Base.
52
+ def self.marshal_load(data_type, data_value_json)
53
+ unless Wikidatum::DataType::DATA_TYPES.keys.include?(data_type.to_sym)
54
+ puts "WARNING: Unsupported data type (#{data_type})"
55
+ return nil
56
+ end
57
+
58
+ Object.const_get(Wikidatum::DataType::DATA_TYPES[data_type.to_sym]).marshal_load(data_value_json)
59
+ end
60
+ end
61
+ end
@@ -1,23 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'wikidatum/data_value_type/base'
3
+ require 'wikidatum/data_type/base'
4
4
 
5
- # The Globe Coordinate type datavalue JSON looks like this:
5
+ # The Globe Coordinate type JSON looks like this:
6
6
  #
7
7
  # ```json
8
8
  # {
9
- # "datavalue": {
10
- # "value": {
11
- # "latitude": 52.516666666667,
12
- # "longitude": 13.383333333333,
13
- # "precision": 0.016666666666667,
9
+ # "property": {
10
+ # "id": "P740",
11
+ # "data-type": "globe-coordinate"
12
+ # },
13
+ # "value": {
14
+ # "type": "value",
15
+ # "content": {
16
+ # "latitude": 38.8977,
17
+ # "longitude": -77.0365,
18
+ # "precision": 0.0001,
14
19
  # "globe": "http://www.wikidata.org/entity/Q2"
15
- # },
16
- # "type": "globecoordinate"
20
+ # }
17
21
  # }
18
22
  # }
19
23
  # ```
20
- class Wikidatum::DataValueType::GlobeCoordinate
24
+ class Wikidatum::DataType::GlobeCoordinate
21
25
  # @return [Float]
22
26
  attr_reader :latitude
23
27
 
@@ -56,22 +60,19 @@ class Wikidatum::DataValueType::GlobeCoordinate
56
60
  #
57
61
  # @return [String]
58
62
  def wikibase_type
59
- 'globecoordinate'
63
+ 'globe-coordinate'
60
64
  end
61
65
 
62
- # The "datatype" value used by Wikibase, usually identical to wikibase_type
63
- # but not always.
64
- #
65
- # @return [String]
66
- def wikibase_datatype
67
- 'globe-coordinate' # yes, really
66
+ # @return [Symbol]
67
+ def self.symbolized_name
68
+ :monolingual_text
68
69
  end
69
70
 
70
71
  # @!visibility private
71
72
  def self.marshal_load(data_value_json)
72
- Wikidatum::DataValueType::Base.new(
73
- type: :globe_coordinate,
74
- value: new(
73
+ Wikidatum::DataType::Base.new(
74
+ type: symbolized_name,
75
+ content: new(
75
76
  latitude: data_value_json['latitude'],
76
77
  longitude: data_value_json['longitude'],
77
78
  precision: data_value_json['precision'],
@@ -1,21 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'wikidatum/data_value_type/base'
3
+ require 'wikidatum/data_type/base'
4
4
 
5
- # The Monolingual Text type datavalue JSON looks like this:
5
+ # The Monolingual Text type JSON looks like this:
6
6
  #
7
7
  # ```json
8
8
  # {
9
- # "datavalue": {
10
- # "value": {
11
- # "text": "South Pole Telescope eyes birth of first massive galaxies",
12
- # "language": "en"
13
- # },
14
- # "type": "monolingualtext"
9
+ # "property": {
10
+ # "id": "P13432",
11
+ # "data-type": "monolingualtext"
12
+ # },
13
+ # "value": {
14
+ # "type": "value",
15
+ # "content": {
16
+ # "text": "foo",
17
+ # "language": "en-gb"
18
+ # }
15
19
  # }
16
20
  # }
17
21
  # ```
18
- class Wikidatum::DataValueType::MonolingualText
22
+ class Wikidatum::DataType::MonolingualText
19
23
  # @return [String] the language code, e.g. 'en'
20
24
  attr_reader :language
21
25
 
@@ -45,19 +49,16 @@ class Wikidatum::DataValueType::MonolingualText
45
49
  'monolingualtext'
46
50
  end
47
51
 
48
- # The "datatype" value used by Wikibase, usually identical to wikibase_type
49
- # but not always.
50
- #
51
- # @return [String]
52
- def wikibase_datatype
53
- wikibase_type
52
+ # @return [Symbol]
53
+ def self.symbolized_name
54
+ :monolingual_text
54
55
  end
55
56
 
56
57
  # @!visibility private
57
58
  def self.marshal_load(data_value_json)
58
- Wikidatum::DataValueType::Base.new(
59
- type: :monolingual_text,
60
- value: new(
59
+ Wikidatum::DataType::Base.new(
60
+ type: symbolized_name,
61
+ content: new(
61
62
  language: data_value_json['language'],
62
63
  text: data_value_json['text']
63
64
  )
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'wikidatum/data_value_type/base'
3
+ require 'wikidatum/data_type/base'
4
4
 
5
5
  # The NoValue type actually has no datavalue key in the blob at all. We work
6
6
  # around this by just passing nil to the serializer.
7
7
 
8
8
  # Represents "no value".
9
- class Wikidatum::DataValueType::NoValue < Wikidatum::DataValueType::Base
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
12
  # @return [String]
@@ -14,16 +14,8 @@ class Wikidatum::DataValueType::NoValue < Wikidatum::DataValueType::Base
14
14
  'string'
15
15
  end
16
16
 
17
- # The "datatype" value used by Wikibase, usually identical to wikibase_type
18
- # but not always.
19
- #
20
- # @return [String]
21
- def wikibase_datatype
22
- wikibase_type
23
- end
24
-
25
17
  # @!visibility private
26
18
  def self.marshal_load(_data_value_json)
27
- new(type: :no_value, value: nil)
19
+ new(type: :no_value, content: nil)
28
20
  end
29
21
  end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_type/base'
4
+
5
+ # The Quantity type JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "property": {
10
+ # "id": "P937",
11
+ # "data-type": "quantity"
12
+ # },
13
+ # "value": {
14
+ # "type": "value",
15
+ # "content": {
16
+ # "amount": "+15",
17
+ # "unit": "1"
18
+ # }
19
+ # }
20
+ # }
21
+ # ```
22
+ class Wikidatum::DataType::Quantity
23
+ # @return [String] A string value like "+2", usually an integer but not always.
24
+ attr_reader :amount
25
+
26
+ # @return [String] a URL describing the unit for this quantity, e.g. "meter", "kilometer", "pound", "chapter", "section", etc.
27
+ attr_reader :unit
28
+
29
+ # @param amount [String]
30
+ # @param unit [String]
31
+ # @return [void]
32
+ def initialize(amount:, unit:)
33
+ @amount = amount
34
+ @unit = unit
35
+ end
36
+
37
+ # @return [Hash]
38
+ def to_h
39
+ {
40
+ amount: @amount,
41
+ unit: @unit
42
+ }
43
+ end
44
+
45
+ # The "type" value used by Wikibase, for use when creating/updating statements.
46
+ #
47
+ # @return [String]
48
+ def wikibase_type
49
+ 'quantity'
50
+ end
51
+
52
+ # @return [Symbol]
53
+ def self.symbolized_name
54
+ :quantity
55
+ end
56
+
57
+ # @!visibility private
58
+ def self.marshal_load(data_value_json)
59
+ Wikidatum::DataType::Base.new(
60
+ type: symbolized_name,
61
+ content: new(
62
+ amount: data_value_json['amount'],
63
+ unit: data_value_json['unit']
64
+ )
65
+ )
66
+ end
67
+
68
+ # @!visibility private
69
+ def marshal_dump
70
+ {
71
+ amount: @amount,
72
+ unit: @unit
73
+ }
74
+ end
75
+ end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'wikidatum/data_value_type/base'
3
+ require 'wikidatum/data_type/base'
4
4
 
5
5
  # The SomeValue type actually has no datavalue key in the blob at all. We work
6
6
  # around this by just passing nil to the serializer.
7
7
 
8
8
  # Represents a value of "unknown value".
9
- class Wikidatum::DataValueType::SomeValue < Wikidatum::DataValueType::Base
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
12
  # @return [String]
@@ -14,16 +14,8 @@ class Wikidatum::DataValueType::SomeValue < Wikidatum::DataValueType::Base
14
14
  'string'
15
15
  end
16
16
 
17
- # The "datatype" value used by Wikibase, usually identical to wikibase_type
18
- # but not always.
19
- #
20
- # @return [String]
21
- def wikibase_datatype
22
- wikibase_type
23
- end
24
-
25
17
  # @!visibility private
26
18
  def self.marshal_load(_data_value_json)
27
- new(type: :some_value, value: nil)
19
+ new(type: :some_value, content: nil)
28
20
  end
29
21
  end
@@ -1,33 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'wikidatum/data_value_type/base'
3
+ require 'wikidatum/data_type/base'
4
4
 
5
- # The time type datavalue JSON looks like this:
5
+ # The time type JSON looks like this:
6
6
  #
7
7
  # ```json
8
8
  # {
9
- # "datavalue": {
10
- # "value": {
9
+ # "property": {
10
+ # "id": "P761",
11
+ # "data-type": "time"
12
+ # },
13
+ # "value": {
14
+ # "type": "value",
15
+ # "content": {
11
16
  # "time": "+2019-11-14T00:00:00Z",
12
- # "timezone": 0,
13
- # "before": 0,
14
- # "after": 0,
15
17
  # "precision": 11,
16
18
  # "calendarmodel": "http://www.wikidata.org/entity/Q1985727"
17
- # },
18
- # "type": "time"
19
+ # }
19
20
  # }
20
21
  # }
21
22
  # ```
22
23
  #
23
- # We do not include before and after because the documentation states that
24
- # they're unused and "may be removed in the future".
25
- #
26
- # NOTE: For consistency with Ruby snake_case attribute names, `timezone` from
27
- # the API is represented as `time_zone` and `calendarmodel` is
28
- # `calendar_model`. However, we expose aliases so `timezone` and
24
+ # NOTE: For consistency with Ruby snake_case attribute names, `calendarmodel`
25
+ # in the API is `calendar_model`. However, we expose an alias so
29
26
  # `calendarmodel` will still work.
30
- class Wikidatum::DataValueType::Time
27
+ class Wikidatum::DataType::Time
31
28
  # A string representing the time in a format that is very similar to ISO 8601.
32
29
  #
33
30
  # For example, here are what dates look like for the most common precisions:
@@ -48,11 +45,6 @@ class Wikidatum::DataValueType::Time
48
45
  # @return [String] the time value, in a format like "+2022-01-01T00:00:00Z", though how this should be interpreted depends on the precision.
49
46
  attr_reader :time
50
47
 
51
- # @return [Integer] an integer for the offset (in minutes) from UTC. 0 means
52
- # UTC, will currently always be 0 but the Wikibase backend may change that
53
- # in the future.
54
- attr_reader :time_zone
55
-
56
48
  # An integer representing the precision of the date, where the integers correspond to the following:
57
49
  #
58
50
  # - 0: 1 Gigayear
@@ -91,13 +83,11 @@ class Wikidatum::DataValueType::Time
91
83
  attr_reader :calendar_model
92
84
 
93
85
  # @param time [String]
94
- # @param time_zone [Integer]
95
86
  # @param precision [Integer]
96
87
  # @param calendar_model [String]
97
88
  # @return [void]
98
- def initialize(time:, time_zone:, precision:, calendar_model:)
89
+ def initialize(time:, precision:, calendar_model:)
99
90
  @time = time
100
- @time_zone = time_zone
101
91
  @precision = precision
102
92
  @calendar_model = calendar_model
103
93
  end
@@ -106,7 +96,6 @@ class Wikidatum::DataValueType::Time
106
96
  def to_h
107
97
  {
108
98
  time: @time,
109
- time_zone: @time_zone,
110
99
  precision: @precision,
111
100
  pretty_precision: pretty_precision,
112
101
  calendar_model: @calendar_model
@@ -120,21 +109,17 @@ class Wikidatum::DataValueType::Time
120
109
  'time'
121
110
  end
122
111
 
123
- # The "datatype" value used by Wikibase, usually identical to wikibase_type
124
- # but not always.
125
- #
126
- # @return [String]
127
- def wikibase_datatype
128
- wikibase_type
112
+ # @return [Symbol]
113
+ def self.symbolized_name
114
+ :time
129
115
  end
130
116
 
131
117
  # @!visibility private
132
118
  def self.marshal_load(data_value_json)
133
- Wikidatum::DataValueType::Base.new(
134
- type: :time,
135
- value: new(
119
+ Wikidatum::DataType::Base.new(
120
+ type: symbolized_name,
121
+ content: new(
136
122
  time: data_value_json['time'],
137
- time_zone: data_value_json['timezone'],
138
123
  precision: data_value_json['precision'],
139
124
  calendar_model: data_value_json['calendarmodel']
140
125
  )
@@ -145,7 +130,6 @@ class Wikidatum::DataValueType::Time
145
130
  def marshal_dump
146
131
  {
147
132
  time: @time,
148
- timezone: @time_zone,
149
133
  precision: @precision,
150
134
  calendarmodel: @calendar_model
151
135
  }
@@ -182,6 +166,5 @@ class Wikidatum::DataValueType::Time
182
166
 
183
167
  # Aliases to match the name returned by the REST API.
184
168
 
185
- alias timezone time_zone
186
169
  alias calendarmodel calendar_model
187
170
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_type/base'
4
+
5
+ # The Wikibase Item type JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "property": {
10
+ # "id": "P963",
11
+ # "data-type": "wikibase-item"
12
+ # },
13
+ # "value": {
14
+ # "type": "value",
15
+ # "content": "Q524026"
16
+ # }
17
+ # }
18
+ # ```
19
+ class Wikidatum::DataType::WikibaseItem
20
+ # @return [String] in the format "Q123".
21
+ attr_reader :id
22
+
23
+ # @param id [String]
24
+ # @return [void]
25
+ def initialize(id:)
26
+ @id = id
27
+ end
28
+
29
+ # @return [Hash]
30
+ def to_h
31
+ {
32
+ id: @id
33
+ }
34
+ end
35
+
36
+ # The "type" value used by Wikibase, for use when creating/updating statements.
37
+ #
38
+ # @return [String]
39
+ def wikibase_type
40
+ 'wikibase-item'
41
+ end
42
+
43
+ # @return [Symbol]
44
+ def self.symbolized_name
45
+ :wikibase_item
46
+ end
47
+
48
+ # @!visibility private
49
+ def self.marshal_load(id)
50
+ Wikidatum::DataType::Base.new(
51
+ type: symbolized_name,
52
+ content: new(
53
+ id: id
54
+ )
55
+ )
56
+ end
57
+
58
+ # @!visibility private
59
+ def marshal_dump
60
+ {
61
+ id: @id
62
+ }
63
+ end
64
+ end
@@ -1,18 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'wikidatum/data_value_type/base'
3
+ require 'wikidatum/data_type/base'
4
4
 
5
- # The String type datavalue JSON looks like this:
5
+ # The String type JSON looks like this:
6
6
  #
7
7
  # ```json
8
8
  # {
9
- # "datavalue": {
10
- # "value": "Foobar",
11
- # "type": "string"
9
+ # "property": {
10
+ # "id": "P143",
11
+ # "data-type": "string"
12
+ # },
13
+ # "value": {
14
+ # "type": "value",
15
+ # "content": "foo"
12
16
  # }
13
17
  # }
14
18
  # ```
15
- class Wikidatum::DataValueType::WikibaseString
19
+ class Wikidatum::DataType::WikibaseString
16
20
  # @return [String] the value for the string.
17
21
  attr_reader :string
18
22
 
@@ -36,19 +40,16 @@ class Wikidatum::DataValueType::WikibaseString
36
40
  'string'
37
41
  end
38
42
 
39
- # The "datatype" value used by Wikibase, usually identical to wikibase_type
40
- # but not always.
41
- #
42
- # @return [String]
43
- def wikibase_datatype
44
- wikibase_type
43
+ # @return [Symbol]
44
+ def self.symbolized_name
45
+ :string
45
46
  end
46
47
 
47
48
  # @!visibility private
48
49
  def self.marshal_load(string)
49
- Wikidatum::DataValueType::Base.new(
50
- type: :string,
51
- value: new(
50
+ Wikidatum::DataType::Base.new(
51
+ type: symbolized_name,
52
+ content: new(
52
53
  string: string
53
54
  )
54
55
  )
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_type/base'
4
+ require 'wikidatum/data_type/globe_coordinate'
5
+ require 'wikidatum/data_type/monolingual_text'
6
+ require 'wikidatum/data_type/no_value'
7
+ require 'wikidatum/data_type/quantity'
8
+ require 'wikidatum/data_type/some_value'
9
+ require 'wikidatum/data_type/time'
10
+ require 'wikidatum/data_type/wikibase_item'
11
+ require 'wikidatum/data_type/wikibase_string'
@@ -186,8 +186,8 @@ class Wikidatum::Item
186
186
  statements = item_json['statements'].to_a.flat_map do |_property_id, st_arr|
187
187
  st_arr.map { |statement| Wikidatum::Statement.marshal_load(statement) }
188
188
  end
189
- sitelinks = item_json['sitelinks'].to_a.map do |_name, sitelink|
190
- Wikidatum::Sitelink.new(site: sitelink['site'], title: sitelink['title'], badges: sitelink['badges'])
189
+ sitelinks = item_json['sitelinks'].to_a.map do |site, sitelink|
190
+ Wikidatum::Sitelink.new(site: site, title: sitelink['title'], badges: sitelink['badges'])
191
191
  end
192
192
 
193
193
  Wikidatum::Item.new(
@@ -1,7 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'wikidatum/snak'
3
+ class Wikidatum::Qualifier
4
+ # @return [String] ID of the property for this Qualifier, in the format 'P123'.
5
+ attr_reader :property_id
4
6
 
5
- # Wikidatum::Qualifier is actually just an alias for snak, because qualifiers
6
- # are effectively just snaks.
7
- Wikidatum::Qualifier = Wikidatum::Snak
7
+ # @return [String]
8
+ attr_reader :data_type
9
+
10
+ # For more information on the possible types that can be returned by
11
+ # datavalues, see the official documentation:
12
+ # https://doc.wikimedia.org/Wikibase/master/php/md_docs_topics_json.html#json_datavalues
13
+ #
14
+ # @return [Wikidatum::DataType::Base] the value of the statement, can take various forms
15
+ attr_reader :value
16
+
17
+ # @!visibility private
18
+ # @param property_id [String] ID of the property for this Qualifier, in the format 'P123'.
19
+ # @param data_type [String]
20
+ # @param value [DataType::GlobeCoordinate, DataType::MonolingualText, DataType::Quantity, DataType::WikibaseString, DataType::Time, DataType::WikibaseItem, DataType::NoValue, DataType::SomeValue]
21
+ def initialize(property_id:, data_type:, value:)
22
+ @property_id = property_id
23
+ @data_type = data_type
24
+ @value = value
25
+ end
26
+
27
+ # @return [Hash]
28
+ def to_h
29
+ {
30
+ property_id: @property_id,
31
+ data_type: @data_type,
32
+ value: @value.to_h
33
+ }
34
+ end
35
+
36
+ # @return [String]
37
+ def inspect
38
+ "<Wikidatum::Qualifier property_id=#{@property_id.inspect} data_type=#{@data_type.inspect} value=#{@value.inspect}>"
39
+ end
40
+
41
+ # @!visibility private
42
+ #
43
+ # This takes in the JSON blob (as a hash) that is output for a given
44
+ # qualifier the API and turns it into an actual instance of a Qualifier.
45
+ #
46
+ # @param qualifier_json [Hash]
47
+ # @return [Wikidatum::Qualifier]
48
+ def self.marshal_load(qualifier_json)
49
+ Wikidatum::Qualifier.new(
50
+ property_id: qualifier_json.dig('property', 'id'),
51
+ data_type: qualifier_json.dig('property', 'data-type'),
52
+ value: Wikidatum::Utils.ingest_snak(qualifier_json)
53
+ )
54
+ end
55
+ end