ontologies_api_client 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 794a6f29a2d4ae7a8c6e2ceb514aefe33928dcfd
4
- data.tar.gz: d9c59cc81fe986cae567ee87934c7a8aa74aa220
3
+ metadata.gz: d5e458b6172df81b92332d4a2d2080f55811b5a7
4
+ data.tar.gz: 05c6ee12401b47642ab0bdde94fad20420eb6f6f
5
5
  SHA512:
6
- metadata.gz: c31b2a88f7f282a6258d74978714c70cf8b435a0dd15598cc6eb14f9029c636471c70a9bfcb1d12beb1483fecc47dc33289f870659bd66fd5fefa23fcf00afd6
7
- data.tar.gz: 44530d5a2c0d912eb9b76499f731e8ea5df23b6ce6790f4d75114f7b56676f1cd9a07579e34931254c6234da0b176c2861d6b1a3b1a0e98c01e3121ac172f0ae
6
+ metadata.gz: 762fe87955f4d282a6b174d82b03ac38f36cb7d809f8d219e2936327825a557c78e587f0dcf0b8e26e5e9e055fcbb3d276f19a9d6241091e321b593dc0ab038f
7
+ data.tar.gz: 675c80522af277ac1b7025b4e280f13ca6a9d409ef9685236d160ebe6c570254ec1a817d10276632489ddbafe6130040a1cce39be11c4c897d9878bea5089c8b
data/README.md CHANGED
@@ -8,12 +8,15 @@
8
8
 
9
9
  Configuration is provided by calling the <code>config</code> method
10
10
 
11
- LinkedData::Client.config do |config|
12
- config.rest_url = "http://stagedata.bioontology.org"
13
- config.apikey = "your_apikey"
14
- config.links_attr = "links"
15
- config.cache = false
16
- end
11
+ ```ruby
12
+ require 'ontologies_api_client'
13
+ LinkedData::Client.config do |config|
14
+ config.rest_url = "http://stagedata.bioontology.org"
15
+ config.apikey = "your_apikey"
16
+ config.links_attr = "links"
17
+ config.cache = false
18
+ end
19
+ ```
17
20
 
18
21
  ## Usage
19
22
 
@@ -28,36 +31,82 @@ There are multiple ways to retrieve individual or groups of resources.
28
31
 
29
32
  To retrieve a single record by id:
30
33
 
31
- Category.find("http://data.bioontology.org/categories/all_organisms")
34
+ ```ruby
35
+ Category.find("http://data.bioontology.org/categories/all_organisms")
36
+ ```
32
37
 
33
38
  ***Where***
34
39
 
35
40
  To retrieve all records that match a particular an in-code filter. The code is a block that should return a
36
41
  boolean that indicates whether or not the item should be included in the results.
37
42
 
38
- categories = Category.where do |ont|
39
- ont.name.include?("health")
40
- end
43
+ ```ruby
44
+ categories = Category.where do |ont|
45
+ ont.name.include?("health")
46
+ end
47
+ ```
41
48
 
42
49
  ***Find By***
43
50
 
44
51
  You can use shortcut methods to find by particular attribute/value pairs
45
52
  (attributes are named in the method and multiple can be provided by connecting them with 'and').
46
53
 
47
- categories = Category.find_by_parentCategory("http://data.bioontology.org/categories/anatomy")
54
+ ```ruby
55
+ categories = Category.find_by_parentCategory("http://data.bioontology.org/categories/anatomy")
56
+ ```
57
+
58
+ ## Create / Update / Delete
59
+
60
+ Creates are done via HTTP POST, update via HTTP PATCH, and deletes using HTTP DELETE.
61
+
62
+ ### Create
63
+
64
+ ```ruby
65
+ ontology_values = {
66
+ acronym: "MY_ONT",
67
+ name: "My Ontology",
68
+ administeredBy: [http://data.bioontology.org/users/my_user]
69
+ }
70
+ ontology = LinkedData::Client::Models::Ontology.new(values: ontology_values)
71
+ response = ontology.save
72
+ puts ontology_saved.errors
73
+ ```
74
+
75
+ ### Update
76
+
77
+ ```ruby
78
+ new_values = {
79
+ administeredBy: [http://data.bioontology.org/users/my_other_user]
80
+ }
81
+ ontology = LinkedData::Client::Models::Ontology.find_by_acronym("MY_ONT")
82
+ ontology.update_from_params(params[:ontology])
83
+ response = ontology.update
84
+ puts response.errors
85
+ ```
86
+
87
+ ### Delete
88
+
89
+ ```ruby
90
+ ontology = LinkedData::Client::Models::Ontology.find_by_acronym("MY_ONT")
91
+ response = ontology.delete
92
+ ```
48
93
 
49
94
  ## Hypermedia Navigation
50
95
 
51
96
  All resources have a collection of hypermedia links, available by calling the 'links' method.
52
97
  These links can be navigated by calling the 'explore' method and chaining the link:
53
98
 
54
- ontology = Category.find("http://data.bioontology.org/categories/all_organisms")
55
- classes = ontology.explore.classes
99
+ ```ruby
100
+ ontology = Category.find("http://data.bioontology.org/categories/all_organisms")
101
+ classes = ontology.explore.classes
102
+ ```
56
103
 
57
104
  Links may contain a [URI template](http://tools.ietf.org/html/rfc6570). In this case, the template can be
58
105
  populated by passing in ordered values for the template tokens:
59
106
 
60
- cls = ontology.explore.single_class("http://my.class.id/class1")
107
+ ```ruby
108
+ cls = ontology.explore.single_class("http://my.class.id/class1")
109
+ ```
61
110
 
62
111
  ## Defining Resources
63
112
 
@@ -67,10 +116,12 @@ providing attribute names that we want to retreive for each media type.
67
116
 
68
117
  For example:
69
118
 
70
- class Category < LinkedData::Client::Base
71
- include LinkedData::Client::Collection
72
- @media_type = "http://data.bioontology.org/metadata/Category"
73
- end
119
+ ```ruby
120
+ class Category < LinkedData::Client::Base
121
+ include LinkedData::Client::Collection
122
+ @media_type = "http://data.bioontology.org/metadata/Category"
123
+ end
124
+ ```
74
125
 
75
126
  ### Collections
76
127
 
@@ -89,14 +140,14 @@ For questions please email [support@bioontology.org](support@bioontology.org.)
89
140
 
90
141
  ## License
91
142
 
92
- Copyright (c) 2013, The Board of Trustees of Leland Stanford Junior University All rights reserved.
143
+ Copyright (c) 2014, The Board of Trustees of Leland Stanford Junior University All rights reserved.
93
144
 
94
145
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
95
146
 
96
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
147
+ Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
97
148
 
98
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
149
+ Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
99
150
 
100
151
  THIS SOFTWARE IS PROVIDED BY THE BOARD OF TRUSTEES OF LELAND STANFORD JUNIOR UNIVERSITY ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL The Board of Trustees of Leland Stanford Junior University OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
101
152
 
102
- The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of The Board of Trustees of Leland Stanford Junior University.
153
+ The views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of The Board of Trustees of Leland Stanford Junior University.
@@ -56,6 +56,13 @@ module LinkedData
56
56
  entry_point(@media_type, params)
57
57
  end
58
58
 
59
+ ##
60
+ # Get all resources from the base collection for a resource as a hash with resource ids as the keys
61
+ def all_to_hash(*args)
62
+ all = all(*args)
63
+ Hash[all.map {|e| [e.id, e]}]
64
+ end
65
+
59
66
  ##
60
67
  # Find certain resources from the collection by passing a block that filters results
61
68
  def where(params = {}, &block)
@@ -55,15 +55,17 @@ module LinkedData
55
55
  raw = options[:raw] || false # return the unparsed body of the request
56
56
  params = params.delete_if {|k,v| v == nil || v.to_s.empty?}
57
57
  params[:ncbo_cache_buster] = Time.now.to_f if raw # raw requests don't get cached to ensure body is available
58
+ invalidate_cache = params.delete(:invalidate_cache) || false
58
59
 
59
60
  begin
60
61
  puts "Getting: #{path} with #{params}" if $DEBUG
61
62
  begin
62
63
  response = conn.get do |req|
63
64
  req.url path
64
- req.params = params
65
+ req.params = params.dup
65
66
  req.options[:timeout] = 60
66
67
  req.headers.merge(headers)
68
+ req.headers[:invalidate_cache] = invalidate_cache
67
69
  end
68
70
  rescue Exception => e
69
71
  params = Faraday::Utils.build_query(params)
@@ -1,4 +1,4 @@
1
- require 'cgi'
1
+ require 'uri'
2
2
  require_relative 'http'
3
3
 
4
4
  module LinkedData
@@ -61,7 +61,7 @@ module LinkedData
61
61
  values = values.dup
62
62
  values = [values] unless values.is_a?(Array)
63
63
  return url.gsub(/(\{.*?\})/) do
64
- CGI.escape(values.shift)
64
+ URI.escape(values.shift, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
65
65
  end
66
66
  end
67
67
 
@@ -4,13 +4,15 @@ require 'lz4-ruby'
4
4
  require_relative '../http'
5
5
 
6
6
  module Faraday
7
- ##
8
- # This middleware causes Faraday to return
9
-
10
7
  class ObjectCacheResponse < Faraday::Response
11
8
  attr_accessor :parsed_body
12
9
  end
13
10
 
11
+ ##
12
+ # This middleware causes Faraday to return an actual object instead of a response
13
+ # This is done so that the object is cached instead of the unparsed json body.
14
+ # Otherwise, we have to re-parse the json on every cache hit, which is extrememly costly
15
+ # when compared to unmarshaling an object.
14
16
  class ObjectCache < Faraday::Middleware
15
17
  def initialize(app, *arguments)
16
18
  super(app)
@@ -26,11 +28,21 @@ module Faraday
26
28
  end
27
29
 
28
30
  def call(env)
31
+ invalidate_cache = env[:request_headers].delete(:invalidate_cache)
32
+
29
33
  # Add if newer than last modified statement to headers
30
34
  request_key = cache_key_for(create_request(env))
31
35
  last_modified_key = "LM::#{request_key}"
32
36
  last_retrieved_key = "LR::#{request_key}"
33
37
 
38
+ # If we invalidate the cache, then it forces a clean request
39
+ if invalidate_cache
40
+ cache_delete(request_key)
41
+ cache_delete(last_modified_key)
42
+ cache_delete(last_retrieved_key)
43
+ env[:request_headers]["Cache-Control"] = "no-cache"
44
+ end
45
+
34
46
  # If we made the last request within the expiry
35
47
  if cache_exist?(last_retrieved_key) && cache_exist?(request_key)
36
48
  puts "DEBUG not expired #{env[:url].to_s}" if $CACHE_DEBUG
@@ -171,6 +183,9 @@ module Faraday
171
183
  obj
172
184
  end
173
185
 
186
+ def cache_delete(key)
187
+ @store.delete(key)
188
+ end
174
189
 
175
190
  # Internal: Generates a String key for a given request object.
176
191
  # The request object is folded into a sorted Array (since we can't count
@@ -1,11 +1,10 @@
1
- require "cgi"
1
+ require "uri"
2
2
  require_relative "../base"
3
3
 
4
4
  module LinkedData
5
5
  module Client
6
6
  module Models
7
7
  class Class < LinkedData::Client::Base
8
- require 'cgi'
9
8
  HTTP = LinkedData::Client::HTTP
10
9
  @media_type = "http://www.w3.org/2002/07/owl#Class"
11
10
  @include_attrs = "prefLabel,definition,synonym,obsolete,childrenCount"
@@ -41,12 +40,12 @@ module LinkedData
41
40
  def purl
42
41
  return "" if self.links.nil?
43
42
  ont = self.explore.ontology
44
- "#{LinkedData::Client.settings.purl_prefix}/#{ont.acronym}/#{CGI.escape(self.id)}"
43
+ "#{LinkedData::Client.settings.purl_prefix}/#{ont.acronym}?conceptid=#{URI.escape(self.id, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))}"
45
44
  end
46
45
 
47
46
  def self.find(id, ontology, params = {})
48
47
  ontology = HTTP.get(ontology, params)
49
- ontology.explore.class(CGI.escape(id))
48
+ ontology.explore.class(URI.escape(id, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")))
50
49
  end
51
50
 
52
51
  def self.search(*args)
@@ -1,4 +1,4 @@
1
- require "cgi"
1
+ require "uri"
2
2
  require_relative "../base"
3
3
 
4
4
  module LinkedData
@@ -11,11 +11,11 @@ module LinkedData
11
11
  @media_type = "http://data.bioontology.org/metadata/Mapping"
12
12
 
13
13
  def self.find(id, params = {})
14
- HTTP.get(mappings_url_prefix + CGI.escape(id), params)
14
+ HTTP.get(mappings_url_prefix + URI.escape(id, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")), params)
15
15
  end
16
16
 
17
17
  def delete
18
- HTTP.delete(mappings_url_prefix + CGI.escape(self.id))
18
+ HTTP.delete(mappings_url_prefix + URI.escape(self.id, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")))
19
19
  end
20
20
 
21
21
  private
@@ -24,7 +24,7 @@ module LinkedData
24
24
  end
25
25
 
26
26
  def viewing_restricted?
27
- private? && licensed?
27
+ private? || licensed?
28
28
  end
29
29
 
30
30
  def view?
@@ -39,28 +39,37 @@ module LinkedData
39
39
  end
40
40
  end
41
41
 
42
+ def access?(user)
43
+ return true if !viewing_restricted?
44
+ return false if user.nil?
45
+ return true if user.admin?
46
+ return self.full_acl.any? {|u| u == user.id}
47
+ end
48
+
42
49
  def admin?(user)
43
50
  return false if user.nil?
44
51
  return true if user.admin?
45
52
  return administeredBy.any? {|u| u == user.id}
46
53
  end
47
54
 
55
+ def invalidate_cache
56
+ self.class.all(invalidate_cache: true)
57
+ self.class.all(invalidate_cache: true, include_views: true)
58
+ HTTP.get(self.id, invalidate_cache: true) if self.id
59
+ end
60
+
61
+ # ACL with administrators
62
+ def full_acl
63
+ ((self.acl || []) + self.administeredBy).uniq
64
+ end
65
+
48
66
  # For use with select lists, always includes the admin by default
49
67
  def acl_select
50
68
  select_opts = []
51
- return select_opts if self.acl.nil? or self.acl.empty?
52
-
53
- if self.acl.nil? || self.acl.empty?
54
- self.administeredBy.each do |userId|
55
- select_opts << [User.get(userId).username, userId]
56
- end
57
- else
58
- self.acl.each do |userId|
59
- select_opts << [User.get(userId).username, userId]
60
- end
69
+ self.full_acl.each do |userId|
70
+ select_opts << [User.get(userId).username, userId]
61
71
  end
62
-
63
- (select_opts + self.administeredBy).uniq
72
+ select_opts
64
73
  end
65
74
 
66
75
  ##
@@ -6,14 +6,17 @@ module LinkedData
6
6
  HTTP = LinkedData::Client::HTTP
7
7
 
8
8
  def save
9
- # Create via post
10
- HTTP.post(self.class.collection_path, self.to_hash)
9
+ resp = HTTP.post(self.class.collection_path, self.to_hash)
10
+ invalidate_cache()
11
+ resp
11
12
  end
12
13
 
13
14
  def update(options = {})
14
15
  values = options[:values] || changed_values()
15
16
  return if values.empty?
16
- HTTP.patch(self.id, values)
17
+ resp = HTTP.patch(self.id, values)
18
+ invalidate_cache()
19
+ resp
17
20
  end
18
21
 
19
22
  def update_from_params(params)
@@ -46,7 +49,9 @@ module LinkedData
46
49
  end
47
50
 
48
51
  def delete
49
- HTTP.delete(self.id)
52
+ resp = HTTP.delete(self.id)
53
+ invalidate_cache()
54
+ resp
50
55
  end
51
56
 
52
57
  private
@@ -75,6 +80,11 @@ module LinkedData
75
80
  return current_value.eql?(new_value) rescue current_value == new_value
76
81
  end
77
82
 
83
+ def invalidate_cache
84
+ self.class.all(invalidate_cache: true)
85
+ HTTP.get(self.id, invalidate_cache: true) if self.id
86
+ end
87
+
78
88
  end
79
89
  end
80
90
  end
@@ -10,13 +10,13 @@ Gem::Specification.new do |gem|
10
10
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
11
11
  gem.name = "ontologies_api_client"
12
12
  gem.require_paths = ["lib"]
13
- gem.version = "0.0.5"
13
+ gem.version = "0.0.6"
14
14
 
15
- gem.add_dependency('multi_json')
16
- gem.add_dependency('oj', '<= 2.0.14')
17
- gem.add_dependency('faraday')
18
- gem.add_dependency('excon')
19
- gem.add_dependency('lz4-ruby')
15
+ gem.add_dependency('multi_json', '~> 1.8')
16
+ gem.add_dependency('oj', '~> 2.0')
17
+ gem.add_dependency('faraday', '~> 0.8')
18
+ gem.add_dependency('excon', '~> 0.29')
19
+ gem.add_dependency('lz4-ruby', '~> 0.1')
20
20
  gem.add_dependency('activesupport', '<= 3.0')
21
21
 
22
22
  # gem.executables = %w()
metadata CHANGED
@@ -1,97 +1,97 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ontologies_api_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul R Alexander
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-14 00:00:00.000000000 Z
11
+ date: 2014-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '1.8'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '1.8'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: oj
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - <=
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.0.14
33
+ version: '2.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - <=
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.0.14
40
+ version: '2.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: faraday
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '0.8'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '0.8'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: excon
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '0.29'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '0.29'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: lz4-ruby
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '0.1'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '0.1'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: activesupport
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - <=
87
+ - - "<="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '3.0'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - <=
94
+ - - "<="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '3.0'
97
97
  description: Models and serializers for ontologies and related artifacts backed by
@@ -102,7 +102,7 @@ executables: []
102
102
  extensions: []
103
103
  extra_rdoc_files: []
104
104
  files:
105
- - .gitignore
105
+ - ".gitignore"
106
106
  - Gemfile
107
107
  - Gemfile.lock
108
108
  - LICENSE.txt
@@ -146,17 +146,17 @@ require_paths:
146
146
  - lib
147
147
  required_ruby_version: !ruby/object:Gem::Requirement
148
148
  requirements:
149
- - - '>='
149
+ - - ">="
150
150
  - !ruby/object:Gem::Version
151
151
  version: '0'
152
152
  required_rubygems_version: !ruby/object:Gem::Requirement
153
153
  requirements:
154
- - - '>='
154
+ - - ">="
155
155
  - !ruby/object:Gem::Version
156
156
  version: '0'
157
157
  requirements: []
158
158
  rubyforge_project:
159
- rubygems_version: 2.0.14
159
+ rubygems_version: 2.2.2
160
160
  signing_key:
161
161
  specification_version: 4
162
162
  summary: This library can be used for interacting with a 4store instance that stores