gimme_wikidata 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 751f0e5c9d5d79ec200fa83d215aeaa247349c28
4
+ data.tar.gz: 64413f1af54686da1a196cb37b760cfb886ec7ef
5
+ SHA512:
6
+ metadata.gz: e5167aa38e3ee801094c52389687ec687e4338bcbdb6d018f9a1f2d85fe417fc9b9e14d21756bfbfcb0fa2248e03bc6da2f042b7d8964726e826c4343e573aac
7
+ data.tar.gz: d81f1e387305fb803d35d7c9929e2ef4505bbd2ecceb5841e0bc8270a32344980ce924b5c694a1d53b0260d4ddd9b02f0fab555f1203aaf21efbe7ec696f5d56
@@ -0,0 +1,18 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /Gemfile.lock
5
+ /pkg/
6
+ /spec/reports/
7
+ /tmp/
8
+
9
+ # Documentation
10
+ /doc/
11
+ /coverage/
12
+ /test/html_reports/
13
+
14
+ # Configuration
15
+ /.env
16
+
17
+ # Generated *.gem files
18
+ /*.gem
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.2
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gimme_wikidata.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Bradley Marques
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,138 @@
1
+ [![Gem Version](http://img.shields.io/gem/v/gimme_wikidata.svg?style=flat-square)](https://rubygems.org/gems/gimme_wikidata)
2
+ [![Code Climate](https://codeclimate.com/github/bradleymarques/gimme_wikidata/badges/gpa.svg)](https://codeclimate.com/github/bradleymarques/gimme_wikidata)
3
+ [![Test Coverage](https://codeclimate.com/github/bradleymarques/gimme_wikidata/badges/coverage.svg)](https://codeclimate.com/github/bradleymarques/gimme_wikidata/coverage)
4
+ [![Issue Count](https://codeclimate.com/github/bradleymarques/gimme_wikidata/badges/issue_count.svg)](https://codeclimate.com/github/bradleymarques/gimme_wikidata)
5
+ [![Inline docs](http://inch-ci.org/github/bradleymarques/gimme_wikidata.svg?branch=master)](http://inch-ci.org/github/bradleymarques/gimme_wikidata)
6
+ [![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://bradleymarques.mit-license.org)
7
+
8
+ ![alt text](https://raw.githubusercontent.com/bradleymarques/gimme_wikidata/master/img/gimme_wikidata_logo.png "Gimme Wikidata")
9
+
10
+ Search and get data from the [Wikidata](https://www.wikidata.org/wiki/Wikidata:Main_Page) open knowledge base.
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'gimme_wikidata'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install gimme_wikidata
27
+
28
+ ## Usage
29
+
30
+ ### Search Wikidata
31
+
32
+ ```ruby
33
+ search = GimmeWikidata.search('David Bowie');
34
+
35
+ search.was_successful?
36
+ => true
37
+
38
+ search.search_term
39
+ => "David Bowie"
40
+
41
+ search.results.count
42
+ => 7
43
+
44
+ search.top_result
45
+ => #<GimmeWikidata::SearchResult:0x00555df75cdaa0
46
+ @description="British musician, actor, record producer and arranger",
47
+ @id="Q5383",
48
+ @label="David Bowie",
49
+ @type=GimmeWikidata::Item>
50
+ ```
51
+
52
+ ### Get Data from Wikidata
53
+
54
+ You could use the search results above to get more data about an `Item` (identified by an `id`):
55
+
56
+ ```ruby
57
+ david_bowie = GimmeWikidata.fetch('Q5383')
58
+
59
+ david_bowie.aliases
60
+ => ["David Robert Jones", "Ziggy Stardust", "David Jones", "Bowie"]
61
+
62
+ david_bowie.print
63
+ ===================
64
+ David Bowie (Q5383)
65
+ ===================
66
+ Description British musician, actor, record producer and arranger
67
+ Aliases David Robert Jones, Ziggy Stardust, David Jones, Bowie
68
+ Claims:
69
+ instance of: human (Q5)
70
+ sex or gender: male (Q6581097)
71
+ place of birth: Brixton (Q146690)
72
+ spouse: Iman (Q256531)
73
+ spouse: Angela Bowie (Q2669959)
74
+ VIAF ID: 79021253
75
+ GND ID: 118514091
76
+ SUDOC authorities: 026748363
77
+ LCAuth ID: n81112099
78
+ BnF ID: 11893660s
79
+ discography: David Bowie discography (Q1173801)
80
+ Commons category: David Bowie
81
+ ISNI: 0000 0001 1444 8576
82
+ ISNI: 0000 0003 6858 7082
83
+ ISNI: 0000 0003 6858 7074
84
+ occupation: painter (Q1028181)
85
+ occupation: singer-songwriter (Q488205)
86
+ occupation: guitarist (Q855091)
87
+ occupation: saxophonist (Q12800682)
88
+ occupation: composer (Q36834)
89
+ occupation: film actor (Q10800557)
90
+ occupation: record producer (Q183945)
91
+ occupation: songwriter (Q753110)
92
+ occupation: actor (Q33999)
93
+ # ... etc
94
+
95
+ ```
96
+
97
+ ## Retrieving Multiple Entities
98
+
99
+ TODO: DOCUMENT
100
+
101
+ ### Publish
102
+
103
+ Please note that the GimmeWikidata gem does not currently support publishing data to Wikidata.
104
+
105
+ ### Advanced usage
106
+
107
+ ## The Data Model
108
+
109
+ The GimmeWikidata gem mirrors the main components of the [Wikidata data model](https://www.mediawiki.org/wiki/Wikibase/DataModel/Primer). Specifically, the following ideas are encapsulated in classes in this gem:
110
+
111
+ + `Entity`
112
+ + `Item`
113
+ + `Property`
114
+ + `Claim`
115
+ + `Snak`
116
+
117
+ ## Contributing
118
+
119
+ Please feel free to contribute:
120
+
121
+ + Fork the repo
122
+ + Make your own bugfix/feature branch
123
+ + Make tests for your contribution
124
+ + Submit a pull request
125
+
126
+ Alternatively, please feel free to make suggestions.
127
+
128
+ ## License
129
+
130
+ The MIT License (MIT)
131
+
132
+ Copyright (c) 2016 Bradley Marques
133
+
134
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
135
+
136
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
137
+
138
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,15 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ require 'dotenv'
5
+ Dotenv.load
6
+
7
+ Rake::TestTask.new(:test) do |t|
8
+ t.libs << 'test'
9
+ t.libs << 'lib'
10
+ t.test_files = FileList['test/**/*_test.rb']
11
+ end
12
+
13
+ puts "CODECLIMATE_REPO_TOKEN = #{ENV['CODECLIMATE_REPO_TOKEN']}"
14
+
15
+ task :default => :test
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "gimme_wikidata"
5
+
6
+ include GimmeWikidata
7
+
8
+ # You can add fixtures and/or initialization code here to make experimenting with your gem easier.
9
+
10
+ require "#{File.join(Dir.pwd, 'test', 'test_api_results', 'response_faker')}"
11
+
12
+ # You can also use a different console, if you like.
13
+ # Let's use pry:
14
+ require 'pry'
15
+ Pry.start
16
+
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,48 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gimme_wikidata/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gimme_wikidata"
8
+ spec.version = GimmeWikidata::VERSION
9
+ spec.authors = ["Bradley Marques"]
10
+ spec.email = ["bradmarxmoosepi@gmail.com"]
11
+
12
+ spec.summary = %q{Search and get data from the Wikidata open knowledge base.}
13
+ spec.description = %q{GimmeWikidata is a Ruby gem that provides an interface to search, pull (and, in future, publish) data from Wikidata. It provides a number of classes that encapsulate the data model of Wikidata.}
14
+ spec.homepage = "https://github.com/bradleymarques/gimme_wikidata"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
+ # delete this section to allow pushing this gem to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
21
+ else
22
+ raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_development_dependency 'bundler', '~> 1.10'
31
+ spec.add_development_dependency 'rake', '>= 11.1.2', '~> 11.1.2'
32
+ spec.add_development_dependency 'simplecov', '~> 0.11.2', '>= 0.11.2'
33
+ spec.add_development_dependency 'minitest-display', '>= 0.3.1', '~> 0.3.1'
34
+ spec.add_development_dependency 'minitest-reporters', '~> 1.1.9', '>= 1.1.9'
35
+ spec.add_development_dependency 'm', '>= 1.5.0', '~> 1.5.0'
36
+ spec.add_development_dependency 'pry', '~> 0.10.3', '>= 0.10.3'
37
+ spec.add_development_dependency 'rdoc', '~> 4.2.2', '>= 4.2.2'
38
+ spec.add_development_dependency 'mocha', '~> 1.1.0', '>= 1.1.0'
39
+ spec.add_development_dependency 'dotenv', '~> 2.0.2', '>= 2.0.2'
40
+ spec.add_development_dependency 'codeclimate-test-reporter', '~> 0.5.2', '>= 0.5.2'
41
+
42
+ spec.add_dependency 'httparty', '~> 0.13.7', '>= 0.13.7'
43
+ spec.add_dependency 'ruby-enum', '~> 0.5.0', '>= 0.5.0'
44
+ spec.add_dependency 'colorize', '~> 0.7.7', '>= 0.7.7'
45
+ spec.add_dependency 'json', '~> 1.8.3', '>= 1.8.3'
46
+ spec.add_dependency 'carbon_date', '~> 0.1.2', '>= 0.1.2'
47
+
48
+ end
@@ -0,0 +1,143 @@
1
+ require 'gimme_wikidata/claim'
2
+ require 'gimme_wikidata/entity'
3
+ require 'gimme_wikidata/entity_result'
4
+ require 'gimme_wikidata/extensions'
5
+ require 'gimme_wikidata/enums'
6
+ require 'gimme_wikidata/item'
7
+ require 'gimme_wikidata/parser'
8
+ require 'gimme_wikidata/printer'
9
+ require 'gimme_wikidata/property'
10
+ require 'gimme_wikidata/search'
11
+ require 'gimme_wikidata/version'
12
+ require 'gimme_wikidata/wikidata_api'
13
+
14
+ module GimmeWikidata
15
+
16
+ include SymbolizeHelper
17
+
18
+ class << self
19
+
20
+ ##
21
+ # Search Wikidata for a particular search term, and get the results.
22
+ #
23
+ # Searches the Wikidata API for a particular term and returns some SearchResults (wrapped in a Search object).
24
+ # Constructs the required search query, makes the call to the API and parses the response.
25
+ #
26
+ # * *Parameters* :
27
+ # - +search_term+ -> the search term to look for on Wikidata
28
+ # - +strict_language+ -> Should we force a restriction to the current language? See WikidataAPI::language
29
+ # - +type+ -> Either search for 'item' or 'property'. Defaults to 'item'
30
+ # - +limit+ -> The maximum number of SearchResults to return. Defaults to 50.
31
+ # - +continue+ -> Where to continue the search from. Defaults to 0.
32
+ # * *Returns* :
33
+ # - A Search object representing and containing the +SearchResults+ found
34
+ def search(search_term = 'wikidata', strict_language: false, type: 'item', limit: 50, continue: 0)
35
+ search_query = WikidataAPI.search_query(search_term, strict_language: strict_language, type: type, limit: limit, continue: continue)
36
+ response = WikidataAPI.make_call(search_query)
37
+ Parser.parse_search_response(response)
38
+ end
39
+
40
+ ##
41
+ # Fetch Entity (or Entities) from Wikidata by id (or ids)
42
+ #
43
+ # Calls either +fetch_entity+ or +fetch_entities+, so is just for convenience.
44
+ #
45
+ # * *Parameters* :
46
+ # - +ids+ -> Either a single Wikidata id or an array of them. If the former, will call +fetch_entity+; if the latter, will call +fetch_entities+
47
+ # - +props+ -> The properties to pull from Wikidata (see Props class). Defaults to +aliases+, +labels+, +descriptions+ and +claims+.
48
+ # * *Returns* :
49
+ # - An Entity in the case of a single id, and an EntityResult in the case of multiple ids
50
+ # * *Raises* :
51
+ # - +ArgumentError+ if ids are not valid Wikidata ids
52
+ def fetch(ids, props: [Props::ALIASES, Props::LABELS, Props::DESCRIPTIONS, Props::CLAIMS])
53
+ case ids.class.to_s
54
+ when 'Array'
55
+ raise ArgumentError.new 'Invalid Wikidata ids' unless valid_ids? ids
56
+ return fetch_entities(ids, props: props)
57
+ when 'String'
58
+ raise ArgumentError.new 'Invalid Wikidata id' unless valid_id? ids
59
+ return fetch_entity(ids, props: props)
60
+ else
61
+ raise ArgumentError.new 'Invalid Wikidata ids'
62
+ end
63
+ end
64
+
65
+ ##
66
+ # Fetch a single Entity from Wikidata by id
67
+ #
68
+ # * *Parameters* :
69
+ # - +id+ -> The Wikidata id of the Entity to get
70
+ # - +props+ -> The properties to pull from Wikidata (see Props class)
71
+ # * *Returns* :
72
+ # - An Entity if successful, and an EntityResponse (with error message) if unsuccessful
73
+ # * *Raises* :
74
+ # - +ArgumentError+ if ids are not valid Wikidata ids
75
+ def fetch_entity(id, props: [Props::ALIASES, Props::LABELS, Props::DESCRIPTIONS, Props::CLAIMS])
76
+ raise ArgumentError.new 'Invalid Wikidata id' unless valid_id? id
77
+ entity_result = fetch_entities([id], props: props)
78
+ return entity_result unless entity_result.was_successful?
79
+ entity_result.entities.first # Simply return the first element, since there was only 1 Entity to fetch
80
+ end
81
+
82
+ ##
83
+ # Fetch multiple Entities from Wikidata by id
84
+ #
85
+ # Makes a call to Wikidata and get the results wrapped in a +EntityResult+ object
86
+ # * *Parameters* :
87
+ # - +ids+ -> An array of Wikidata ids, such as ['Q1', 'Q2', 'P206', 'P16']
88
+ # - +props+ -> The properties to pull from Wikidata (see Props class)
89
+ # * *Returns* :
90
+ # - An EntityResult object containing Entities
91
+ # * *Raises* :
92
+ # - +ArgumentError+ if ids are not valid Wikidata ids
93
+ def fetch_entities(ids, props: [Props::ALIASES, Props::LABELS, Props::DESCRIPTIONS, Props::CLAIMS])
94
+ raise ArgumentError.new 'Invalid Wikidata ids' unless valid_ids? ids
95
+ get_query = WikidataAPI.get_entities_query(ids, props: props)
96
+ response = WikidataAPI.make_call(get_query)
97
+ entity_result = Parser.parse_entity_response(response)
98
+ entity_result.resolve_all_properties
99
+ entity_result.resolve_all_claims if props.include? Props::CLAIMS
100
+ entity_result
101
+ end
102
+
103
+ ##
104
+ # Valdiates an array of ids against Wikidata format
105
+ #
106
+ # Wikidata has ids in the form 'QN' or 'PN' where Q means 'Item', P means 'Property', and N is any number.
107
+ # * *Parameters*:
108
+ # - +ids+ -> An array of (possible) Wikidata ids to be validated, in string form
109
+ # - +type+ -> array of symbols representing entity types to check. Defaults to +[:item, :property]+
110
+ # * *Returns*:
111
+ # - boolean
112
+ def valid_ids?(ids, type = [:item, :property])
113
+ return false unless ids.is_a? Array
114
+ ids.all? { |i| valid_id?(i, type) }
115
+ end
116
+
117
+ ##
118
+ # Valdiates a single id against Wikidata format
119
+ #
120
+ # Wikidata has ids in the form 'QN' or 'PN' where Q means 'Item', P means 'Property', and N is any number.
121
+ # * *Parameters* :
122
+ # - +id+ -> A (possible) Wikidata id to be validated, as a String
123
+ # - +type+ -> array of symbols representing entity types to check. Defaults to +[:item, :property]+
124
+ # * *Returns*:
125
+ # - boolean
126
+ def valid_id?(id, type = [:item, :property])
127
+
128
+ return false unless id.is_a? String
129
+
130
+ prefix =
131
+ case type
132
+ when [:item, :property] then 'QP'
133
+ when [:item] then 'Q'
134
+ when [:property] then 'P'
135
+ else raise ArgumentError.new "type must be a subset of [:item, :property]"
136
+ end
137
+
138
+ !(/\A[#{prefix}][0-9]+\z/.match(id).nil?)
139
+ end
140
+
141
+ end
142
+
143
+ end
@@ -0,0 +1,65 @@
1
+ module GimmeWikidata
2
+
3
+ ##
4
+ # Models a Claim on Wikidata, which consists of a Property and a value
5
+ #
6
+ # Note that the value can be of any type (example: a number, a date), and is often another Item on Wikidata.
7
+ #
8
+ # For more details, please see: https://www.wikidata.org/wiki/Wikidata:Glossary#Claims_and_statements
9
+ class Claim
10
+
11
+ ##
12
+ # The Property that the Claim is about
13
+ attr_reader :property
14
+
15
+ ##
16
+ # The value that the Property is claimed to have
17
+ attr_reader :value
18
+
19
+ ##
20
+ # The type of value. Current types:
21
+ # - item
22
+ # - property
23
+ # - wikidata_time
24
+ # - external_id
25
+ # - media
26
+ # - text
27
+ # - url
28
+ # - gps_coordinates
29
+ # - quantity
30
+ attr_reader :value_type
31
+
32
+ def initialize(property = nil, value = nil, value_type = nil)
33
+ @property = property
34
+ @value = value
35
+ @value_type = value_type
36
+ end
37
+
38
+ ##
39
+ # Returns a simple hash form of the claim.
40
+ #
41
+ # Example: {sex_or_gender: "Male"}
42
+ def simplify
43
+ property = @property.label
44
+ value = simplify_value
45
+ return {property: property, value: value}
46
+ end
47
+
48
+ ##
49
+ # Simplifies the value
50
+ #
51
+ # TODO: DOCUMENT THIS FUNCTION BETTER
52
+ def simplify_value
53
+ case @value_type
54
+ when :item, :property
55
+ return "#{@value.label} (#{@value.id})"
56
+ when :carbon_date
57
+ return @value.to_s
58
+ when :external_id, :media, :text, :url, :gps_coordinates, :quantity
59
+ return @value
60
+ else
61
+ return nil # TODO: Consider throwing an exception here
62
+ end
63
+ end
64
+ end
65
+ end