wikisnakker 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +26 -0
- data/.rubocop.yml +2 -0
- data/.rubocop_todo.yml +35 -0
- data/.travis.yml +9 -0
- data/CHANGES +48 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +78 -0
- data/Rakefile +14 -0
- data/bin/console +10 -0
- data/bin/setup +7 -0
- data/lib/wikisnakker.rb +3 -0
- data/lib/wikisnakker/claim.rb +27 -0
- data/lib/wikisnakker/item.rb +91 -0
- data/lib/wikisnakker/lookup.rb +92 -0
- data/lib/wikisnakker/qualifiers.rb +39 -0
- data/lib/wikisnakker/sitelink.rb +13 -0
- data/lib/wikisnakker/snak.rb +54 -0
- data/lib/wikisnakker/version.rb +3 -0
- data/wikisnakker.gemspec +32 -0
- metadata +204 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 65104af982fc1fb3b5eb4c6c50b94962968a903a
|
4
|
+
data.tar.gz: 836260223f7f6f71c5e112d4c736b0f8c83edc71
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0c11ee591b122bff4f6e28e25ac26457be3f006eb261a6a1cbf6e21b90dc7683e7d67b8c09131adfec5e80d5bbaa026f0d2d17eea8ae3177827b9b4f95968e97
|
7
|
+
data.tar.gz: 16c88b0c4931425ef01b2b7d55c2ba903972b0b3724d42f2b0b5dc3ef2b4ba17e21af79bcaae8442325f1c526480dddaede8338e5aa2ae2694d451d47c5d4c73
|
data/.gitignore
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
|
24
|
+
*.swp
|
25
|
+
|
26
|
+
*.cache
|
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2017-02-06 16:02:37 +0000 using RuboCop version 0.34.2.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 2
|
10
|
+
Metrics/AbcSize:
|
11
|
+
Max: 57
|
12
|
+
|
13
|
+
# Offense count: 1
|
14
|
+
Metrics/CyclomaticComplexity:
|
15
|
+
Max: 14
|
16
|
+
|
17
|
+
# Offense count: 20
|
18
|
+
# Configuration parameters: AllowURI, URISchemes.
|
19
|
+
Metrics/LineLength:
|
20
|
+
Max: 151
|
21
|
+
|
22
|
+
# Offense count: 3
|
23
|
+
# Configuration parameters: CountComments.
|
24
|
+
Metrics/MethodLength:
|
25
|
+
Max: 37
|
26
|
+
|
27
|
+
# Offense count: 1
|
28
|
+
Metrics/PerceivedComplexity:
|
29
|
+
Max: 8
|
30
|
+
|
31
|
+
# Offense count: 8
|
32
|
+
# Configuration parameters: Exclude.
|
33
|
+
Style/Documentation:
|
34
|
+
Exclude:
|
35
|
+
- 'lib/wikisnakker/*.rb'
|
data/.travis.yml
ADDED
data/CHANGES
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
0.9.0 2017-02-06
|
2
|
+
— Calculate data at run time via missing_method, rather than
|
3
|
+
generating singleton methods, to reduce memory usage.
|
4
|
+
|
5
|
+
0.8.0 2017-01-06
|
6
|
+
- Switch to using YAJL to parse the JSON from Wikidata. This greatly
|
7
|
+
reduces memory usage.
|
8
|
+
|
9
|
+
0.7.0 2016-09-22
|
10
|
+
|
11
|
+
- Fixed: Retrieving a deleted page (such as https://www.wikidata.org/wiki/Q21974469)
|
12
|
+
no longer causes an error. https://github.com/everypolitician/wikisnakker/pull/47
|
13
|
+
|
14
|
+
0.6.0 2016-07-18
|
15
|
+
- Switch to using `symbolize_names` option when parsing JSON to keep memory usage down.
|
16
|
+
|
17
|
+
0.5.0 2016-06-21
|
18
|
+
- Provide access to label descriptions
|
19
|
+
|
20
|
+
0.4.1 2016-05-16
|
21
|
+
- Handle lookups with no IDs
|
22
|
+
|
23
|
+
0.4.0 2016-03-29
|
24
|
+
- Add an `aliases` method
|
25
|
+
|
26
|
+
0.3.0 2016-02-29
|
27
|
+
- Stringify to the English label
|
28
|
+
|
29
|
+
0.2.1 2016-02-27
|
30
|
+
- Handle asking for a label that doesn't exist
|
31
|
+
|
32
|
+
0.2.0 2016-02-18
|
33
|
+
- Handle Wikidata's new 'external-id' type
|
34
|
+
|
35
|
+
0.1.0 2016-01-22
|
36
|
+
- Expose the qualifiers for a claim
|
37
|
+
|
38
|
+
0.0.3 2016-01-13
|
39
|
+
- Expose the claims for each item
|
40
|
+
- Add a `sitelinks` property
|
41
|
+
- Handle more imprecise date formats
|
42
|
+
|
43
|
+
0.0.2 2015-11-27
|
44
|
+
- Add ability to resolve 'url' datatype
|
45
|
+
|
46
|
+
0.0.1 2015-10-17
|
47
|
+
- initial version
|
48
|
+
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Tony Bowden
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# Wikisnakker [![Build Status](https://travis-ci.org/everypolitician/wikisnakker.svg?branch=master)](https://travis-ci.org/everypolitician/wikisnakker)
|
2
|
+
|
3
|
+
This project allows you to do bulk lookups of Wikidata items. If you want to look up large amounts of Wikidata items at once then this library should make that job considerably faster.
|
4
|
+
|
5
|
+
:warning: This project is under heavy development and is in a **very** pre-alpha state, it's not yet ready for use in production.
|
6
|
+
|
7
|
+
## Features/problems
|
8
|
+
|
9
|
+
- Many
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'wikisnakker', git: 'https://github.com/everypolitician/wikisnakker'
|
17
|
+
```
|
18
|
+
|
19
|
+
And then execute:
|
20
|
+
|
21
|
+
$ bundle
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
You can pass an array of qualifiers to `Wikisnakker::Item.find`. This will return an array of `Wikisnakker::Item` instances.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
require 'wikisnakker'
|
29
|
+
items = Wikisnakker::Item.find(['Q2', 'Q513', 'Q41225'])
|
30
|
+
items.map { |item| item.label('en') } # => ["Earth", "Mount Everest", "Big Ben"]
|
31
|
+
items.map { |item| item.P18.value } # => ["https://upload.wikimedia.org/wikipedia/commons/9/97/The_Earth_seen_from_Apollo_17.jpg", "https://upload.wikimedia.org/wikipedia/commons/e/e7/Everest_North_Face_toward_Base_Camp_Tibet_Luca_Galuzzi_2006.jpg", "https://upload.wikimedia.org/wikipedia/commons/7/78/Big-ben-1858.jpg"]
|
32
|
+
```
|
33
|
+
|
34
|
+
If you pass a string to `Wikisnakker::Item.find` then it will return a single `Wikisnakker::Item` instance:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
require 'wikisnakker'
|
38
|
+
douglas_adams = Wikisnakker::Item.find('Q42')
|
39
|
+
douglas_adams.label('en') # => "Douglas Adams"
|
40
|
+
```
|
41
|
+
|
42
|
+
Then you can lookup properties on returned items. For example `P19` is "place of birth". A `P19` is an item, so you can then call `.label()` on its return value and call further `P*` methods on it.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
cambridge = douglas_adams.P19.value
|
46
|
+
cambridge.label('en') # => "Cambridge"
|
47
|
+
```
|
48
|
+
|
49
|
+
`P569` is "date of birth" and `P570` is "date of death".
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
douglas_adams.P569.value # => "1952-03-11"
|
53
|
+
douglas_adams.P570.value # => "2001-05-11"
|
54
|
+
```
|
55
|
+
|
56
|
+
Sometimes a property will have multiple values, for example `P735`, which is "given names". In this case you can call `P735s` on the `Wikisnakker::Item` instance to get an array back:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
douglas_adams.P735s.map { |given_name| given_name.value.label('en') }
|
60
|
+
# => ["Douglas", "Noel"]
|
61
|
+
```
|
62
|
+
|
63
|
+
You can also lookup aliases in a certain language for an item:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
douglas_adams.aliases('en')
|
67
|
+
# => ["Douglas Noël Adams", "Douglas Noel Adams"]
|
68
|
+
```
|
69
|
+
|
70
|
+
## Development
|
71
|
+
|
72
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
73
|
+
|
74
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
75
|
+
|
76
|
+
## Contributing
|
77
|
+
|
78
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/everypolitician/wikisnakker.
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rubocop/rake_task'
|
5
|
+
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
7
|
+
t.libs << 'test'
|
8
|
+
t.libs << 'lib'
|
9
|
+
t.test_files = FileList['test/**/*_test.rb']
|
10
|
+
end
|
11
|
+
|
12
|
+
RuboCop::RakeTask.new
|
13
|
+
|
14
|
+
task default: :test
|
data/bin/console
ADDED
data/bin/setup
ADDED
data/lib/wikisnakker.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Wikisnakker
|
2
|
+
class Claim
|
3
|
+
def initialize(data)
|
4
|
+
@data = data
|
5
|
+
end
|
6
|
+
|
7
|
+
def value
|
8
|
+
mainsnak.value
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_s
|
12
|
+
mainsnak.value
|
13
|
+
end
|
14
|
+
|
15
|
+
def mainsnak
|
16
|
+
@_mainsnak ||= Snak.new(@data[:mainsnak])
|
17
|
+
end
|
18
|
+
|
19
|
+
def qualifiers
|
20
|
+
Qualifiers.new(@data[:qualifiers])
|
21
|
+
end
|
22
|
+
|
23
|
+
def rank
|
24
|
+
@data[:rank]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Wikisnakker
|
2
|
+
class Item
|
3
|
+
def self.find(ids)
|
4
|
+
lookup = Lookup.find(ids)
|
5
|
+
data = lookup.values.reject { |d| d[:missing] == '' }
|
6
|
+
inflated = data.map { |rd| new(rd) }
|
7
|
+
ids.is_a?(Array) ? inflated : inflated.first
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(raw)
|
11
|
+
@raw = raw
|
12
|
+
end
|
13
|
+
|
14
|
+
PROPERTY_REGEX = /^(P\d+)(s?)$/
|
15
|
+
|
16
|
+
def method_missing(method_name, *arguments, &block)
|
17
|
+
pid, plural = method_name.to_s.scan(PROPERTY_REGEX).flatten
|
18
|
+
return super unless pid
|
19
|
+
plural.empty? ? first_property(pid) : property(pid)
|
20
|
+
end
|
21
|
+
|
22
|
+
def respond_to_missing?(method_name, include_private = false)
|
23
|
+
method_name.to_s.match(PROPERTY_REGEX) || super
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](key)
|
27
|
+
__send__(key)
|
28
|
+
end
|
29
|
+
|
30
|
+
def property(pid)
|
31
|
+
# A claim's rank can be either preferred, normal or deprecated. We sort them by
|
32
|
+
# rank in reverse order because lexicographic ordering happens to work for the
|
33
|
+
# known ranks.
|
34
|
+
raw[:claims][pid.to_sym].to_a.map { |c| Claim.new(c) }.group_by(&:rank).sort.reverse.map(&:last).flatten
|
35
|
+
end
|
36
|
+
|
37
|
+
def first_property(pid)
|
38
|
+
property(pid).first
|
39
|
+
end
|
40
|
+
|
41
|
+
def id
|
42
|
+
raw[:id]
|
43
|
+
end
|
44
|
+
|
45
|
+
def labels
|
46
|
+
raw[:labels]
|
47
|
+
end
|
48
|
+
|
49
|
+
def descriptions
|
50
|
+
raw[:descriptions] || {}
|
51
|
+
end
|
52
|
+
|
53
|
+
def all_aliases
|
54
|
+
raw[:aliases]
|
55
|
+
end
|
56
|
+
|
57
|
+
def properties
|
58
|
+
raw[:claims].keys
|
59
|
+
end
|
60
|
+
|
61
|
+
def sitelinks
|
62
|
+
Hash[raw[:sitelinks].map do |key, value|
|
63
|
+
[key.to_sym, Sitelink.new(value)]
|
64
|
+
end]
|
65
|
+
end
|
66
|
+
|
67
|
+
# TODO: have an option that defaults to a different language
|
68
|
+
def to_s
|
69
|
+
labels.key?(:en) ? labels[:en][:value] : @id
|
70
|
+
end
|
71
|
+
|
72
|
+
def label(lang)
|
73
|
+
return nil unless labels.key?(lang.to_sym)
|
74
|
+
labels[lang.to_sym][:value]
|
75
|
+
end
|
76
|
+
|
77
|
+
def description(lang)
|
78
|
+
return nil unless descriptions.key?(lang.to_sym)
|
79
|
+
descriptions[lang.to_sym][:value]
|
80
|
+
end
|
81
|
+
|
82
|
+
def aliases(lang)
|
83
|
+
return [] unless all_aliases.key?(lang.to_sym)
|
84
|
+
all_aliases[lang.to_sym].map { |a| a[:value] }
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
attr_reader :raw
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'yajl'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module Wikisnakker
|
6
|
+
class Lookup
|
7
|
+
def self.find(ids)
|
8
|
+
lookup = new(ids)
|
9
|
+
property_lookup = new(lookup.properties)
|
10
|
+
lookup.populate_with(property_lookup)
|
11
|
+
lookup
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(*ids)
|
15
|
+
ids = ids.flatten.compact.uniq
|
16
|
+
@used_props = Set.new
|
17
|
+
entities = ids.each_slice(50).map do |id_slice|
|
18
|
+
get(id_slice)[:entities]
|
19
|
+
end
|
20
|
+
@entities = entities.reduce(&:merge) || {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def properties
|
24
|
+
@used_props.to_a.map { |e| "Q#{e}".to_sym }
|
25
|
+
end
|
26
|
+
|
27
|
+
def values
|
28
|
+
@values ||= @entities.values
|
29
|
+
end
|
30
|
+
|
31
|
+
def [](key)
|
32
|
+
@entities[key]
|
33
|
+
end
|
34
|
+
|
35
|
+
def populate_with(properties)
|
36
|
+
each_wikibase_entitiyid(@entities) do |entityid|
|
37
|
+
entityid[:value] = properties["Q#{entityid[:value][:"numeric-id"]}".to_sym]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def get(*ids)
|
44
|
+
query = {
|
45
|
+
action: 'wbgetentities',
|
46
|
+
ids: ids.flatten.join('|'),
|
47
|
+
format: 'json'
|
48
|
+
}
|
49
|
+
url = 'https://www.wikidata.org/w/api.php?' + URI.encode_www_form(query)
|
50
|
+
json = Yajl::Parser.parse(open(url), symbolize_keys: true)
|
51
|
+
save_wikibase_entityids(json)
|
52
|
+
json
|
53
|
+
end
|
54
|
+
|
55
|
+
# If a property is set to another Wikidata article, resolve that
|
56
|
+
# (e.g. set 'gender' to 'male' rather than 'Q6581097')
|
57
|
+
# We don't know yet what that will resolve to, and we don't want
|
58
|
+
# to look them up one by one, so keep track of any entity ids we
|
59
|
+
# encounter and then resolve them later in '#populate_with'.
|
60
|
+
def save_wikibase_entityids(json)
|
61
|
+
each_wikibase_entitiyid(json) do |entityid|
|
62
|
+
@used_props << entityid[:value][:'numeric-id']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def each_wikibase_entitiyid(obj)
|
67
|
+
recurse_proc(obj) do |result|
|
68
|
+
next unless result.is_a?(Hash) && result[:type] == 'wikibase-entityid'.freeze
|
69
|
+
yield(result)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
|
74
|
+
# Taken from the json gem.
|
75
|
+
# @see http://git.io/v4Tf7
|
76
|
+
def recurse_proc(result, &proc)
|
77
|
+
case result
|
78
|
+
when Array
|
79
|
+
result.each { |x| recurse_proc x, &proc }
|
80
|
+
proc.call result
|
81
|
+
when Hash
|
82
|
+
result.each do |x, y|
|
83
|
+
recurse_proc x, &proc
|
84
|
+
recurse_proc y, &proc
|
85
|
+
end
|
86
|
+
proc.call result
|
87
|
+
else
|
88
|
+
proc.call result
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Wikisnakker
|
2
|
+
class Qualifiers
|
3
|
+
def initialize(qualifier_snaks)
|
4
|
+
@qualifier_snaks = qualifier_snaks || {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def properties
|
8
|
+
qualifier_snaks.keys
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
__send__(key)
|
13
|
+
end
|
14
|
+
|
15
|
+
PROPERTY_REGEX = /^(P\d+)(s?)$/
|
16
|
+
|
17
|
+
def method_missing(method_name, *arguments, &block)
|
18
|
+
pid, plural = method_name.to_s.scan(PROPERTY_REGEX).flatten
|
19
|
+
return super unless pid
|
20
|
+
plural.empty? ? first_snak(pid) : snak(pid)
|
21
|
+
end
|
22
|
+
|
23
|
+
def respond_to_missing?(method_name, include_private = false)
|
24
|
+
method_name.to_s.match(PROPERTY_REGEX) || super
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def snak(pid)
|
30
|
+
qualifier_snaks[pid.to_sym].to_a.map { |c| Snak.new(c) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def first_snak(pid)
|
34
|
+
snak(pid).first
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_reader :qualifier_snaks
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module Wikisnakker
|
4
|
+
class Snak
|
5
|
+
def initialize(snak)
|
6
|
+
@snak = snak
|
7
|
+
end
|
8
|
+
|
9
|
+
# https://www.wikidata.org/wiki/Special:ListDatatypes
|
10
|
+
# https://www.wikidata.org/wiki/Help:Data_type
|
11
|
+
def value
|
12
|
+
return if %w(somevalue novalue).include?(@snak[:snaktype])
|
13
|
+
case @snak[:datatype]
|
14
|
+
when 'commonsMedia'
|
15
|
+
# https://commons.wikimedia.org/wiki/Commons:FAQ#What_are_the_strangely_named_components_in_file_paths.3F
|
16
|
+
# commons = 'https://commons.wikimedia.org/wiki/File:%s' % @snak["datavalue"]["value"]
|
17
|
+
val = @snak[:datavalue][:value].tr(' ', '_')
|
18
|
+
md5 = Digest::MD5.hexdigest val
|
19
|
+
"https://upload.wikimedia.org/wikipedia/commons/#{md5[0]}/#{md5[0..1]}/#{val}"
|
20
|
+
when 'wikibase-item'
|
21
|
+
# "Q%s" % @snak["datavalue"]["value"]["numeric-id"]
|
22
|
+
Item.new(@snak[:datavalue][:value])
|
23
|
+
when 'string'
|
24
|
+
@snak[:datavalue][:value]
|
25
|
+
when 'external-id'
|
26
|
+
@snak[:datavalue][:value]
|
27
|
+
when 'quantity'
|
28
|
+
if @snak[:datavalue][:value][:upperBound] == @snak[:datavalue][:value][:lowerBound]
|
29
|
+
@snak[:datavalue][:value][:amount].to_i
|
30
|
+
else
|
31
|
+
warn "FIXME: Unhandled 'quantity': #{@snak[:datavalue][:value]}"
|
32
|
+
end
|
33
|
+
when 'time'
|
34
|
+
case @snak[:datavalue][:value][:precision]
|
35
|
+
when 11
|
36
|
+
@snak[:datavalue][:value][:time][1..10]
|
37
|
+
when 10
|
38
|
+
@snak[:datavalue][:value][:time][1..7]
|
39
|
+
when 9
|
40
|
+
@snak[:datavalue][:value][:time][1..4]
|
41
|
+
when 7
|
42
|
+
'' # Just ignore dates with century precision
|
43
|
+
else
|
44
|
+
warn "FIXME: Unhandled 'time' precision: #{@snak[:datavalue][:value][:precision]}"
|
45
|
+
end
|
46
|
+
when 'url'
|
47
|
+
@snak[:datavalue][:value]
|
48
|
+
else
|
49
|
+
warn "FIXME: '#{@snak[:datatype]}' is not implemented yet in Wikisnakker::Snak#value. Defaulting to empty string. #{@snak[:datavalue][:value]}"
|
50
|
+
''
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/wikisnakker.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'wikisnakker/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'wikisnakker'
|
8
|
+
spec.version = Wikisnakker::VERSION
|
9
|
+
spec.authors = ['Tony Bowden']
|
10
|
+
spec.email = ['tony@mysociety.org']
|
11
|
+
spec.summary = 'Fetch Wikidata.'
|
12
|
+
spec.description = 'Turn Wikidata items into Ruby structures.'
|
13
|
+
spec.homepage = 'https://github.com/everypolitician/wikisnakker'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = 'exe'
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'require_all'
|
22
|
+
spec.add_dependency 'yajl-ruby'
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
25
|
+
spec.add_development_dependency 'rake', '~> 10.4.2'
|
26
|
+
spec.add_development_dependency 'pry', '~> 0.10.3'
|
27
|
+
spec.add_development_dependency 'minitest', '~> 5.8.2'
|
28
|
+
spec.add_development_dependency 'rubocop', '~> 0.34.2'
|
29
|
+
spec.add_development_dependency 'vcr', '~> 3.0.3'
|
30
|
+
spec.add_development_dependency 'webmock', '~> 2.3.2'
|
31
|
+
spec.add_development_dependency 'minitest-around', '~> 0.3.2'
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wikisnakker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tony Bowden
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-03-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: require_all
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: yajl-ruby
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 10.4.2
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 10.4.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.10.3
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.10.3
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 5.8.2
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 5.8.2
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.34.2
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.34.2
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: vcr
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 3.0.3
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 3.0.3
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: webmock
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 2.3.2
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 2.3.2
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: minitest-around
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 0.3.2
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 0.3.2
|
153
|
+
description: Turn Wikidata items into Ruby structures.
|
154
|
+
email:
|
155
|
+
- tony@mysociety.org
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- ".gitignore"
|
161
|
+
- ".rubocop.yml"
|
162
|
+
- ".rubocop_todo.yml"
|
163
|
+
- ".travis.yml"
|
164
|
+
- CHANGES
|
165
|
+
- Gemfile
|
166
|
+
- LICENSE.txt
|
167
|
+
- README.md
|
168
|
+
- Rakefile
|
169
|
+
- bin/console
|
170
|
+
- bin/setup
|
171
|
+
- lib/wikisnakker.rb
|
172
|
+
- lib/wikisnakker/claim.rb
|
173
|
+
- lib/wikisnakker/item.rb
|
174
|
+
- lib/wikisnakker/lookup.rb
|
175
|
+
- lib/wikisnakker/qualifiers.rb
|
176
|
+
- lib/wikisnakker/sitelink.rb
|
177
|
+
- lib/wikisnakker/snak.rb
|
178
|
+
- lib/wikisnakker/version.rb
|
179
|
+
- wikisnakker.gemspec
|
180
|
+
homepage: https://github.com/everypolitician/wikisnakker
|
181
|
+
licenses:
|
182
|
+
- MIT
|
183
|
+
metadata: {}
|
184
|
+
post_install_message:
|
185
|
+
rdoc_options: []
|
186
|
+
require_paths:
|
187
|
+
- lib
|
188
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - ">="
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: '0'
|
193
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - ">="
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
requirements: []
|
199
|
+
rubyforge_project:
|
200
|
+
rubygems_version: 2.5.2
|
201
|
+
signing_key:
|
202
|
+
specification_version: 4
|
203
|
+
summary: Fetch Wikidata.
|
204
|
+
test_files: []
|