wikidatum 0.1.0 → 0.2.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,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The Globe Coordinate type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": {
11
+ # "latitude": 52.516666666667,
12
+ # "longitude": 13.383333333333,
13
+ # "precision": 0.016666666666667,
14
+ # "globe": "http://www.wikidata.org/entity/Q2"
15
+ # },
16
+ # "type": "globecoordinate"
17
+ # }
18
+ # }
19
+ # ```
20
+ class Wikidatum::DataValueType::GlobeCoordinate
21
+ # @return [Float]
22
+ attr_reader :latitude
23
+
24
+ # @return [Float]
25
+ attr_reader :longitude
26
+
27
+ # @return [Float]
28
+ attr_reader :precision
29
+
30
+ # @return [String] A URL (usually in the same Wikibase instance) representing the given globe model (e.g. Earth).
31
+ attr_reader :globe
32
+
33
+ # @param latitude [Float]
34
+ # @param longitude [Float]
35
+ # @param precision [Float]
36
+ # @param globe [String]
37
+ # @return [void]
38
+ def initialize(latitude:, longitude:, precision:, globe:)
39
+ @latitude = latitude
40
+ @longitude = longitude
41
+ @precision = precision
42
+ @globe = globe
43
+ end
44
+
45
+ # @return [Hash]
46
+ def to_h
47
+ {
48
+ latitude: @latitude,
49
+ longitude: @longitude,
50
+ precision: @precision,
51
+ globe: @globe
52
+ }
53
+ end
54
+
55
+ # The "type" value used by Wikibase, for use when creating/updating statements.
56
+ #
57
+ # @return [String]
58
+ def wikibase_type
59
+ 'globecoordinate'
60
+ end
61
+
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
68
+ end
69
+
70
+ # @!visibility private
71
+ def self.marshal_load(data_value_json)
72
+ Wikidatum::DataValueType::Base.new(
73
+ type: :globe_coordinate,
74
+ value: new(
75
+ latitude: data_value_json['latitude'],
76
+ longitude: data_value_json['longitude'],
77
+ precision: data_value_json['precision'],
78
+ globe: data_value_json['globe']
79
+ )
80
+ )
81
+ end
82
+
83
+ # @!visibility private
84
+ def marshal_dump
85
+ {
86
+ latitude: @latitude,
87
+ longitude: @longitude,
88
+ precision: @precision,
89
+ globe: @globe
90
+ }
91
+ end
92
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The Monolingual Text type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": {
11
+ # "text": "South Pole Telescope eyes birth of first massive galaxies",
12
+ # "language": "en"
13
+ # },
14
+ # "type": "monolingualtext"
15
+ # }
16
+ # }
17
+ # ```
18
+ class Wikidatum::DataValueType::MonolingualText
19
+ # @return [String] the language code, e.g. 'en'
20
+ attr_reader :language
21
+
22
+ # @return [String]
23
+ attr_reader :text
24
+
25
+ # @param language [String]
26
+ # @param text [String]
27
+ # @return [void]
28
+ def initialize(language:, text:)
29
+ @language = language
30
+ @text = text
31
+ end
32
+
33
+ # @return [Hash]
34
+ def to_h
35
+ {
36
+ language: @language,
37
+ text: @text
38
+ }
39
+ end
40
+
41
+ # The "type" value used by Wikibase, for use when creating/updating statements.
42
+ #
43
+ # @return [String]
44
+ def wikibase_type
45
+ 'monolingualtext'
46
+ end
47
+
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
54
+ end
55
+
56
+ # @!visibility private
57
+ def self.marshal_load(data_value_json)
58
+ Wikidatum::DataValueType::Base.new(
59
+ type: :monolingual_text,
60
+ value: new(
61
+ language: data_value_json['language'],
62
+ text: data_value_json['text']
63
+ )
64
+ )
65
+ end
66
+
67
+ # @!visibility private
68
+ def marshal_dump
69
+ {
70
+ language: @language,
71
+ text: @text
72
+ }
73
+ end
74
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The NoValue type actually has no datavalue key in the blob at all. We work
6
+ # around this by just passing nil to the serializer.
7
+
8
+ # Represents "no value".
9
+ class Wikidatum::DataValueType::NoValue < Wikidatum::DataValueType::Base
10
+ # The "type" value used by Wikibase, for use when creating/updating statements.
11
+ #
12
+ # @return [String]
13
+ def wikibase_type
14
+ 'string'
15
+ end
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
+ # @!visibility private
26
+ def self.marshal_load(_data_value_json)
27
+ new(type: :no_value, value: nil)
28
+ end
29
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The Quantity type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": {
11
+ # "amount": "+10.38",
12
+ # "upperBound": "+10.375",
13
+ # "lowerBound": "+10.385",
14
+ # "unit": "http://www.wikidata.org/entity/Q712226"
15
+ # },
16
+ # "type": "quantity"
17
+ # }
18
+ # }
19
+ # ```
20
+ class Wikidatum::DataValueType::Quantity
21
+ # @return [String] A string value like "+2", usually an integer but not always.
22
+ attr_reader :amount
23
+
24
+ # @return [String, nil] upper bound, if one is defined.
25
+ attr_reader :upper_bound
26
+
27
+ # @return [String, nil] lower bound, if one is defined.
28
+ attr_reader :lower_bound
29
+
30
+ # @return [String] a URL describing the unit for this quantity, e.g. "meter", "kilometer", "pound", "chapter", "section", etc.
31
+ attr_reader :unit
32
+
33
+ # @param amount [String]
34
+ # @param upper_bound [String]
35
+ # @param lower_bound [String]
36
+ # @param unit [String]
37
+ # @return [void]
38
+ def initialize(amount:, upper_bound:, lower_bound:, unit:)
39
+ @amount = amount
40
+ @upper_bound = upper_bound
41
+ @lower_bound = lower_bound
42
+ @unit = unit
43
+ end
44
+
45
+ # @return [Hash]
46
+ def to_h
47
+ {
48
+ amount: @amount,
49
+ upper_bound: @upper_bound,
50
+ lower_bound: @lower_bound,
51
+ unit: @unit
52
+ }
53
+ end
54
+
55
+ # The "type" value used by Wikibase, for use when creating/updating statements.
56
+ #
57
+ # @return [String]
58
+ def wikibase_type
59
+ 'quantity'
60
+ end
61
+
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
+ wikibase_type
68
+ end
69
+
70
+ # @!visibility private
71
+ def self.marshal_load(data_value_json)
72
+ Wikidatum::DataValueType::Base.new(
73
+ type: :quantity,
74
+ value: new(
75
+ amount: data_value_json['amount'],
76
+ upper_bound: data_value_json['upperBound'],
77
+ lower_bound: data_value_json['lowerBound'],
78
+ unit: data_value_json['unit']
79
+ )
80
+ )
81
+ end
82
+
83
+ # @!visibility private
84
+ def marshal_dump
85
+ {
86
+ amount: @amount,
87
+ upperBound: @upper_bound,
88
+ lowerBound: @lower_bound,
89
+ unit: @unit
90
+ }
91
+ end
92
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The SomeValue type actually has no datavalue key in the blob at all. We work
6
+ # around this by just passing nil to the serializer.
7
+
8
+ # Represents a value of "unknown value".
9
+ class Wikidatum::DataValueType::SomeValue < Wikidatum::DataValueType::Base
10
+ # The "type" value used by Wikibase, for use when creating/updating statements.
11
+ #
12
+ # @return [String]
13
+ def wikibase_type
14
+ 'string'
15
+ end
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
+ # @!visibility private
26
+ def self.marshal_load(_data_value_json)
27
+ new(type: :some_value, value: nil)
28
+ end
29
+ end
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The time type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": {
11
+ # "time": "+2019-11-14T00:00:00Z",
12
+ # "timezone": 0,
13
+ # "before": 0,
14
+ # "after": 0,
15
+ # "precision": 11,
16
+ # "calendarmodel": "http://www.wikidata.org/entity/Q1985727"
17
+ # },
18
+ # "type": "time"
19
+ # }
20
+ # }
21
+ # ```
22
+ #
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
29
+ # `calendarmodel` will still work.
30
+ class Wikidatum::DataValueType::Time
31
+ # A string representing the time in a format that is very similar to ISO 8601.
32
+ #
33
+ # For example, here are what dates look like for the most common precisions:
34
+ #
35
+ # - years (9): "+2022-00-00T00:00:00Z", meaning "2022"
36
+ # - months (10): "+2022-03-00T00:00:00Z", meaning "March 2022"
37
+ # - days (11): "+2022-01-01T00:00:00Z", meaning "January 1, 2022"
38
+ #
39
+ # NOTE: Due to how precision works, it's probably not a good idea to use the
40
+ # Ruby `Date` or `Time` classes to parse these values unless it's a day-level
41
+ # precision. `Date.parse` will error if you give it a string like
42
+ # "2022-00-00", but it'll handle "2022-01-01" fine. `Time.new` will parse
43
+ # "2022-00-00" as January 1, 2022. There are various other pitfalls that make
44
+ # this generally dangerous unless you're very careful, which is why Wikidatum
45
+ # just handles the time as a string and leaves it to end-users to do what they
46
+ # like with it.
47
+ #
48
+ # @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
+ attr_reader :time
50
+
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
+ # An integer representing the precision of the date, where the integers correspond to the following:
57
+ #
58
+ # - 0: 1 Gigayear
59
+ # - 1: 100 Megayears
60
+ # - 2: 10 Megayears
61
+ # - 3: Megayear
62
+ # - 4: 100 Kiloyears
63
+ # - 5: 10 Kiloyears
64
+ # - 6: millennium
65
+ # - 7: century
66
+ # - 8: 10 years
67
+ # - 9: years
68
+ # - 10: months
69
+ # - 11: days
70
+ # - 12: hours (unused)
71
+ # - 13: minutes (unused)
72
+ # - 14: seconds (unused)
73
+ #
74
+ # Usually only 9, 10, and 11 are used in actual items, though for some items
75
+ # you'll need to handle the other cases.
76
+ #
77
+ # For example, the date August 12, 2022 (aka "2022-08-12") would have a
78
+ # precision of days (11).
79
+ #
80
+ # If the time represented is August 2022 because the value is only precise
81
+ # to the month (e.g. a person who's birth is only known to the month rather
82
+ # than the exact day) that would have a precision of months (10).
83
+ #
84
+ # If the time represented is "2022" because it's only precise to the year,
85
+ # that would have a precision of years (9).
86
+ #
87
+ # @return [Integer]
88
+ attr_reader :precision
89
+
90
+ # @return [String] a URL (usually in the same Wikibase instance) representing the given calendar model (e.g. Gregorian, Julian).
91
+ attr_reader :calendar_model
92
+
93
+ # @param time [String]
94
+ # @param time_zone [Integer]
95
+ # @param precision [Integer]
96
+ # @param calendar_model [String]
97
+ # @return [void]
98
+ def initialize(time:, time_zone:, precision:, calendar_model:)
99
+ @time = time
100
+ @time_zone = time_zone
101
+ @precision = precision
102
+ @calendar_model = calendar_model
103
+ end
104
+
105
+ # @return [Hash]
106
+ def to_h
107
+ {
108
+ time: @time,
109
+ time_zone: @time_zone,
110
+ precision: @precision,
111
+ pretty_precision: pretty_precision,
112
+ calendar_model: @calendar_model
113
+ }
114
+ end
115
+
116
+ # The "type" value used by Wikibase, for use when creating/updating statements.
117
+ #
118
+ # @return [String]
119
+ def wikibase_type
120
+ 'time'
121
+ end
122
+
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
129
+ end
130
+
131
+ # @!visibility private
132
+ def self.marshal_load(data_value_json)
133
+ Wikidatum::DataValueType::Base.new(
134
+ type: :time,
135
+ value: new(
136
+ time: data_value_json['time'],
137
+ time_zone: data_value_json['timezone'],
138
+ precision: data_value_json['precision'],
139
+ calendar_model: data_value_json['calendarmodel']
140
+ )
141
+ )
142
+ end
143
+
144
+ # @!visibility private
145
+ def marshal_dump
146
+ {
147
+ time: @time,
148
+ timezone: @time_zone,
149
+ precision: @precision,
150
+ calendarmodel: @calendar_model
151
+ }
152
+ end
153
+
154
+ PRETTY_PRECISIONS = {
155
+ 0 => :gigayear,
156
+ 1 => :'100_megayear',
157
+ 2 => :'10_megayear',
158
+ 3 => :megayear,
159
+ 4 => :'100_kiloyear',
160
+ 5 => :'10_kiloyear',
161
+ 6 => :millennium,
162
+ 7 => :century,
163
+ 8 => :decade,
164
+ 9 => :year,
165
+ 10 => :month,
166
+ 11 => :day,
167
+ 12 => :hour,
168
+ 13 => :minute,
169
+ 14 => :second
170
+ }.freeze
171
+
172
+ # Returns a symbol representation of the precision, in singular form.
173
+ #
174
+ # Possible values are `:gigayear`, `:'100_megayear'`, `:'10_megayear'`,
175
+ # `:megayear`, `:'100_kiloyear'`, `:'10_kiloyear'`, `:millennium`, `:century`,
176
+ # `:decade`, `:year`, `:month`, `:day`, `:hour`, `:minute`, and `:second`.
177
+ #
178
+ # @return [Symbol]
179
+ def pretty_precision
180
+ PRETTY_PRECISIONS[@precision]
181
+ end
182
+
183
+ # Aliases to match the name returned by the REST API.
184
+
185
+ alias timezone time_zone
186
+ alias calendarmodel calendar_model
187
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The Wikibase Entity ID type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": {
11
+ # "entity-type": "item",
12
+ # "numeric-id": 552863,
13
+ # "id": "Q552863"
14
+ # },
15
+ # "type": "wikibase-entityid"
16
+ # }
17
+ # }
18
+ # ```
19
+ class Wikidatum::DataValueType::WikibaseEntityId
20
+ # @return [String] usually "item"
21
+ attr_reader :entity_type
22
+
23
+ # @return [Integer] the integer representation of the Wikibase ID.
24
+ attr_reader :numeric_id
25
+
26
+ # @return [String] in the format "Q123".
27
+ attr_reader :id
28
+
29
+ # @param entity_type [String]
30
+ # @param numeric_id [Integer]
31
+ # @param id [String]
32
+ # @return [void]
33
+ def initialize(entity_type:, numeric_id:, id:)
34
+ @entity_type = entity_type
35
+ @numeric_id = numeric_id
36
+ @id = id
37
+ end
38
+
39
+ # @return [Hash]
40
+ def to_h
41
+ {
42
+ entity_type: @entity_type,
43
+ numeric_id: @numeric_id,
44
+ id: @id
45
+ }
46
+ end
47
+
48
+ # The "type" value used by Wikibase, for use when creating/updating statements.
49
+ #
50
+ # @return [String]
51
+ def wikibase_type
52
+ 'wikibase-entityid'
53
+ end
54
+
55
+ # The "datatype" value used by Wikibase, usually identical to wikibase_type
56
+ # but not always.
57
+ #
58
+ # @return [String]
59
+ def wikibase_datatype
60
+ 'wikibase-item' # yes, really
61
+ end
62
+
63
+ # @!visibility private
64
+ def self.marshal_load(data_value_json)
65
+ Wikidatum::DataValueType::Base.new(
66
+ type: :wikibase_entity_id,
67
+ value: new(
68
+ entity_type: data_value_json['entity-type'],
69
+ numeric_id: data_value_json['numeric-id'],
70
+ id: data_value_json['id']
71
+ )
72
+ )
73
+ end
74
+
75
+ # @!visibility private
76
+ def marshal_dump
77
+ {
78
+ 'entity-type': @entity_type,
79
+ 'numeric-id': @numeric_id,
80
+ id: @id
81
+ }
82
+ end
83
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+
5
+ # The String type datavalue JSON looks like this:
6
+ #
7
+ # ```json
8
+ # {
9
+ # "datavalue": {
10
+ # "value": "Foobar",
11
+ # "type": "string"
12
+ # }
13
+ # }
14
+ # ```
15
+ class Wikidatum::DataValueType::WikibaseString
16
+ # @return [String] the value for the string.
17
+ attr_reader :string
18
+
19
+ # @param string [String]
20
+ # @return [void]
21
+ def initialize(string:)
22
+ @string = string
23
+ end
24
+
25
+ # @return [Hash]
26
+ def to_h
27
+ {
28
+ string: @string
29
+ }
30
+ end
31
+
32
+ # The "type" value used by Wikibase, for use when creating/updating statements.
33
+ #
34
+ # @return [String]
35
+ def wikibase_type
36
+ 'string'
37
+ end
38
+
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
45
+ end
46
+
47
+ # @!visibility private
48
+ def self.marshal_load(string)
49
+ Wikidatum::DataValueType::Base.new(
50
+ type: :string,
51
+ value: new(
52
+ string: string
53
+ )
54
+ )
55
+ end
56
+
57
+ # @!visibility private
58
+ def marshal_dump
59
+ @string
60
+ end
61
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wikidatum/data_value_type/base'
4
+ require 'wikidatum/data_value_type/globe_coordinate'
5
+ require 'wikidatum/data_value_type/monolingual_text'
6
+ require 'wikidatum/data_value_type/no_value'
7
+ require 'wikidatum/data_value_type/quantity'
8
+ require 'wikidatum/data_value_type/some_value'
9
+ require 'wikidatum/data_value_type/time'
10
+ require 'wikidatum/data_value_type/wikibase_entity_id'
11
+ require 'wikidatum/data_value_type/wikibase_string'