watson-api-client 0.0.2 → 0.0.3

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -14
  3. data/lib/watson-api-client.rb +161 -121
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bf43a7c4e5b1a840e5e59c752434155f9a1704e4
4
- data.tar.gz: ac7cf313d8948c803dba69ac10121a6618027a48
3
+ metadata.gz: 5fec45c50b850da9cd802179d152e89d98891076
4
+ data.tar.gz: 773b646ed640000c56789f6d07083274b1e40ded
5
5
  SHA512:
6
- metadata.gz: edbe184d558657b75a05a7852f64b99554dbfaeab16176c9d25621ed275dd92c4988c358c83db440ed3bd63188483894711ce76db40e1d7eed3764b54d7a548f
7
- data.tar.gz: d084db495948621d638cda6289c31e5200aaefdb1a2cc3660b4c7ad9c0763848a16c8afcb5be8f13ea5c668a4c8fc4cecff7a6e4003fa0f1e92c4d61929a53eb
6
+ metadata.gz: 28a9d5c4e20a7eb5bf088a1a075883165958dd4df037e5d3d1268fcc0eafbef9efa10b23e916ce50164262b0efe47272368b66112818a3936da788e1ba6b056d
7
+ data.tar.gz: 8a17361402286dffe07a2c34724ba537c68fe37b1aeb528b0111b2164293d7a4c109b478039af3f072aebfe425a1546b2eb7bcc40890035eeb49550c55e57695
data/README.md CHANGED
@@ -102,29 +102,31 @@ Next, let's use 'Personality Insights'.
102
102
  The class name, the method name, and the argument setting rules are the same as that of the case of 'Relationship Extraction' almost.
103
103
  The rest-client and the watson-api-client judge which of path, query, header, body each argument is used for automatically.
104
104
 
105
- ###Visual Recognition example
105
+ More
106
+ -------
107
+ The documents which 'watson-api-client' referred to have changed in [February 2016](https://github.com/suchowan/watson-api-client/issues/1).
106
108
 
107
- Last, let's use 'Visual Recognition'.
108
109
 
109
- service = WatsonAPIClient::VisualRecognition.new(:user=>"xxxxxx",
110
- :password=>"yyyyy",
111
- :verify_ssl=>OpenSSL::SSL::VERIFY_NONE)
112
- result = service.recognizeLabelsService(
113
- 'img_File' => open('image.jpg','rb')
114
- )
115
- p JSON.parse(result.body)
110
+ (1) The JSON file which held the list of APIs emptied.
116
111
 
117
- It seems that the image file must be on the local file system.
112
+ (2) The version of Swagger which describes API specifications went up from 1.2 to 2.0.
118
113
 
119
- More
120
- -------
121
- At present this gem is an α version and only the normal behavior of RelationshipExtraction, PersonalityInsights and VisualRecognition are confirmed.
114
+
115
+ They may be linked to the release of the IBM Watson for Japanese language.
116
+
117
+ The new version 0.0.3 corresponding to them was released provisionally.
118
+ Concerning about (1) in the version 0.0.3, the locations of JSON files which describe API specification are acquired from contents of web pages for human using regular expressions.
119
+
120
+ Essentially, as well as former versions, the location of the API documents should be readable with JSON file.
121
+ I will request to the IBM to revive the JSON file which held the list of APIs.
122
+
123
+ At present this gem is an alpha version and only the normal behavior of RelationshipExtraction and PersonalityInsights are confirmed.
122
124
  It is welcome when you can cooperate with the confirmation of other various functions.
123
125
 
124
126
 
125
127
  Credits
126
128
  -------
127
- Copyright (c) 2015 [Takashi SUGA](http://hosi.org/TakashiSuga.ttl)
129
+ Copyright (c) 2015-2016 [Takashi SUGA](http://hosi.org/TakashiSuga.ttl)
128
130
 
129
131
 
130
132
  Legal
@@ -1,121 +1,161 @@
1
- require 'json'
2
- require 'openssl'
3
- require 'open-uri'
4
- require 'rest-client'
5
- require 'pp' if __FILE__ == $PROGRAM_NAME
6
-
7
- class WatsonAPIClient
8
-
9
- VERSION = '0.0.2'
10
-
11
- class << self
12
- def listings(apis)
13
- methods = {}
14
- digest = {}
15
- apis['apis'].each do |api|
16
- api['operations'].each do |operation|
17
- body = nil
18
- (operation['parameters']||[]).each do |parameter|
19
- next unless parameter['paramType'] == 'body'
20
- body = parameter['name']
21
- break
22
- end
23
- nickname = operation['nickname'].sub(/(.)/) {$1.downcase}
24
- methods[nickname] = {'path'=>api['path'], 'operation'=>operation, 'body'=>body}
25
- digest[nickname] = {'method'=>operation['method'], 'path'=>api['path'], 'summary'=>operation['summary']}
26
- end
27
- end
28
- {'apis'=>apis, 'methods'=>methods, 'digest'=>digest}
29
- end
30
- private :listings
31
- end
32
-
33
- api_docs = {
34
- :base => 'https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/apis/',
35
- :path => 'listings/api-docs.json',
36
- :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE
37
- }
38
- JSON.parse(ENV['WATSON_API_DOCS'] || '{}').each_pair do |key, value|
39
- api_docs[key.to_sym] = value
40
- end
41
-
42
- Services = JSON.parse(ENV['VCAP_SERVICES'] || '{}')
43
- Base = api_docs.delete(:base)
44
- path = api_docs.delete(:path)
45
- Options = api_docs
46
- listings = JSON.parse(open(Base + path, Options).read)
47
-
48
- listings['apis'].each do |list|
49
- module_eval %Q{
50
- class #{('-'+list['path']).gsub(/[-_\/]+(.)/) {$1.upcase}} < self
51
- Service = superclass::Services['#{list['path'].sub(/^[-_\/]+/,'').gsub(/-/, '_')}']
52
- RawDoc = "#{Base + listings['basePath'] + list['path']}"
53
-
54
- class << self
55
- alias :_const_missing :const_missing
56
-
57
- def const_missing(constant)
58
- if constant == :API
59
- const_set(:API, listings(JSON.parse(open(RawDoc, superclass::Options).read)))
60
- else
61
- _const_missing(constant)
62
- end
63
- end
64
- end
65
- pp [self, 'See ' + RawDoc, API['digest']] if '#{__FILE__}' == '#{$PROGRAM_NAME}'
66
- end
67
- }
68
- end
69
-
70
- # All subclass constructors use following hash parameter -
71
- #
72
- # @param [Hash] options See following..
73
- # @option options [String] :url API URL (default: the url described in listings or VCAP_SERVICES)
74
- # @option options [String] :user USER ID (default: the username described in VCAP_SERVICES)
75
- # @option options [String] :password USER Password (default: the password described in VCAP_SERVICES)
76
- # @option options [Object] other_options Other options are passed to RestClient::Resource.new[http://www.rubydoc.info/gems/rest-client/RestClient/Resource] as it is.
77
- #
78
- # @note VCAP_SERVICES[http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/getting_started/gs-bluemix.shtml#vcapViewing] is IBM Bluemix™ environment variable.
79
- #
80
- def initialize(options={})
81
- self.class::API['methods'].each_pair do |method, definition|
82
- self.class.module_eval %Q{define_method("#{method}",
83
- Proc.new {|options={}| rest_access_#{definition['body'] ? 'with' : 'without'}_body("#{method}", options)}
84
- )} unless respond_to?(method)
85
- end
86
- credential = self.class::Service ? self.class::Service.first['credentials'] : {}
87
- if options[:url]
88
- @url = options.delete(:url)
89
- elsif credential['url']
90
- @url = credential['url']
91
- else
92
- @url = self.class::API['apis']['basePath']
93
- @url += self.class::API['apis']['resourcePath'] unless @url.index(self.class::API['apis']['resourcePath'])
94
- end
95
- @options = {:user=>credential['username'], :password=>credential['password']}.merge(options)
96
- @service = RestClient::Resource.new(@url, @options)
97
- end
98
-
99
- private
100
-
101
- def rest_access_without_body(method, options={})
102
- path, access = swagger_info(method, options)
103
- @service[path].send(access, options)
104
- end
105
-
106
- def rest_access_with_body(method, options={})
107
- path, access = swagger_info(method, options)
108
- body = options.delete(self.class::API['methods'][method.to_s]['body'])
109
- @service[path].send(access, body, options)
110
- end
111
-
112
- def swagger_info(method, options)
113
- spec = self.class::API['methods'][method.to_s]
114
- lacked = []
115
- spec['operation']['parameters'].each do |parameter|
116
- lacked << parameter['name'] if parameter['required'] && !options[parameter['name']]
117
- end
118
- raise ArgumentError, "Parameter(s) '#{lacked.join(', ')}' required, see #{self.class::RawDoc}." unless lacked.empty?
119
- [spec['path'].gsub(/\{(.+?)\}/) {options.delete($1)}, spec['operation']['method'].downcase]
120
- end
121
- end
1
+ require 'json'
2
+ require 'openssl'
3
+ require 'open-uri'
4
+ require 'rest-client'
5
+ require 'pp' if __FILE__ == $PROGRAM_NAME
6
+
7
+ class WatsonAPIClient
8
+
9
+ VERSION = '0.0.3'
10
+
11
+ class << self
12
+
13
+ private
14
+
15
+ def retrieve_doc(doc_urls)
16
+ apis = {}
17
+
18
+ # Watson API Explorer
19
+ host1 = doc_urls[:doc_base1][/^https?:\/\/[^\/]+/]
20
+ open(doc_urls[:doc_base1], Options, &:read).scan(/<p>\s*<a href="\/(.+?)".*?>\s*(.+?)\s*<\/a><\/p>/i) do
21
+ api = {'path'=>doc_urls[:doc_base1] + $1, 'title'=>$2.sub(/\s*\(.+?\)$/,'')}
22
+ open(api['path'], Options, &:read).scan(/url:\s*'(.+?)'/) do
23
+ api['path'] = host1 + $1
24
+ end
25
+ apis[api['title']] = api
26
+ end
27
+
28
+ # Watson Developercloud
29
+ host2 = doc_urls[:doc_base2][/^https?:\/\/[^\/]+/]
30
+ open(doc_urls[:doc_base2], Options, &:read).scan(/<li>\s*<img src=.+?>\s*<h2><a href="(.+?)".*?>\s*(.+?)\s*<\/a><\/h2>\s*<p>(.+?)<\/p>\s*<\/li>/im) do
31
+ api = {'path'=>$1, 'title'=>$2, 'description'=>$3}
32
+ next if api['path'] =~ /\.\./
33
+ if apis.key?(api['title'])
34
+ apis[api['title']]['description'] = api['description']
35
+ else
36
+ # Only for Relationship Extraction
37
+ open(doc_urls[:doc_base2] + api['path'], Options, &:read).scan(/<li><a href="(.+?)".*?>API\s+explorer<\/a><\/li>/i) do
38
+ ref = host2 + $1
39
+ open(ref, Options, &:read).scan(/getAbsoluteUrl\("(.+?)"\)/) do
40
+ api['path'] = ref.split('/')[0..-2].join('/') + '/' + $1
41
+ end
42
+ end
43
+ apis[api['title']] = api
44
+ end
45
+ end
46
+
47
+ apis
48
+ end
49
+
50
+ # for Swagger 2.0
51
+ def listings(apis)
52
+ methods = {}
53
+ digest = {}
54
+ apis['paths'].each_pair do |path, operations|
55
+ operations.each_pair do |method, operation|
56
+ body = nil
57
+ (operation['parameters']||[]).each do |parameter|
58
+ next unless parameter['in'] == 'body'
59
+ body = parameter['name']
60
+ break
61
+ end
62
+ nickname = operation['operationId'].sub(/(.)/) {$1.downcase}
63
+ methods[nickname] = {'method'=>method, 'path'=>path, 'operation'=>operation, 'body'=>body}
64
+ digest[nickname] = {'method'=>method, 'path'=>path, 'summary'=>operation['summary']}
65
+ end
66
+ end
67
+ {'apis'=>apis, 'methods'=>methods, 'digest'=>digest}
68
+ end
69
+ end
70
+
71
+ api_docs = {
72
+ :gateway => 'https://gateway.watsonplatform.net',
73
+ :doc_base1 => 'https://watson-api-explorer.mybluemix.net/',
74
+ :doc_base2 => 'https://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/',
75
+ :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE
76
+ }
77
+ JSON.parse(ENV['WATSON_API_DOCS'] || '{}').each_pair do |key, value|
78
+ api_docs[key.to_sym] = value
79
+ end
80
+ doc_urls = {
81
+ :doc_base1 => api_docs.delete(:doc_base1),
82
+ :doc_base2 => api_docs.delete(:doc_base2)
83
+ }
84
+
85
+ Gateway = api_docs.delete(:gateway)
86
+ Options = api_docs
87
+ Services = JSON.parse(ENV['VCAP_SERVICES'] || '{}')
88
+
89
+ retrieve_doc(doc_urls).each_value do |list|
90
+ module_eval %Q{
91
+ class #{list['title'].gsub(/\s+(.)/) {$1.upcase}} < self
92
+ Service = superclass::Services['#{list['title'].sub(/\s+/,'_').downcase}']
93
+ RawDoc = "#{list['path']}"
94
+
95
+ class << self
96
+ alias :_const_missing :const_missing
97
+
98
+ def const_missing(constant)
99
+ if constant == :API
100
+ const_set(:API, listings(JSON.parse(open(RawDoc, superclass::Options, &:read))))
101
+ else
102
+ _const_missing(constant)
103
+ end
104
+ end
105
+ end
106
+ pp [self, 'See ' + RawDoc, API['digest']] if '#{__FILE__}' == '#{$PROGRAM_NAME}'
107
+ end
108
+ }
109
+ end
110
+
111
+ # All subclass constructors use following hash parameter -
112
+ #
113
+ # @param [Hash] options See following..
114
+ # @option options [String] :url API URL (default: the url described in listings or VCAP_SERVICES)
115
+ # @option options [String] :user USER ID (default: the username described in VCAP_SERVICES)
116
+ # @option options [String] :password USER Password (default: the password described in VCAP_SERVICES)
117
+ # @option options [Object] other_options Other options are passed to RestClient::Resource.new[http://www.rubydoc.info/gems/rest-client/RestClient/Resource] as it is.
118
+ #
119
+ # @note VCAP_SERVICES[http://www.ibm.com/smarterplanet/us/en/ibmwatson/developercloud/doc/getting_started/gs-bluemix.shtml#vcapViewing] is IBM Bluemix™ environment variable.
120
+ #
121
+ def initialize(options={})
122
+ self.class::API['methods'].each_pair do |method, definition|
123
+ self.class.module_eval %Q{define_method("#{method}",
124
+ Proc.new {|options={}| rest_access_#{definition['body'] ? 'with' : 'without'}_body("#{method}", options)}
125
+ )} unless respond_to?(method)
126
+ end
127
+ credential = self.class::Service ? self.class::Service.first['credentials'] : {}
128
+ if options[:url]
129
+ @url = options.delete(:url)
130
+ elsif credential['url']
131
+ @url = credential['url']
132
+ else
133
+ @url = Gateway + self.class::API['apis']['basePath']
134
+ end
135
+ @options = {:user=>credential['username'], :password=>credential['password']}.merge(options)
136
+ @service = RestClient::Resource.new(@url, @options)
137
+ end
138
+
139
+ private
140
+
141
+ def rest_access_without_body(method, options={})
142
+ path, access = swagger_info(method, options)
143
+ @service[path].send(access, options)
144
+ end
145
+
146
+ def rest_access_with_body(method, options={})
147
+ path, access = swagger_info(method, options)
148
+ body = options.delete(self.class::API['methods'][method.to_s]['body'])
149
+ @service[path].send(access, body, options)
150
+ end
151
+
152
+ def swagger_info(method, options)
153
+ spec = self.class::API['methods'][method.to_s]
154
+ lacked = []
155
+ spec['operation']['parameters'].each do |parameter|
156
+ lacked << parameter['name'] if parameter['required'] && !options[parameter['name']]
157
+ end
158
+ raise ArgumentError, "Parameter(s) '#{lacked.join(', ')}' required, see #{self.class::RawDoc}." unless lacked.empty?
159
+ [spec['path'].gsub(/\{(.+?)\}/) {options.delete($1)}, spec['method']]
160
+ end
161
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: watson-api-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Takashi SUGA
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-14 00:00:00.000000000 Z
11
+ date: 2016-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client