archivesspace-client 0.5.1 → 0.7.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.
- checksums.yaml +4 -4
- data/README.md +41 -21
- data/archivesspace-client.gemspec +2 -2
- data/examples/upload_ead.rb +53 -0
- data/lib/archivesspace/client/client.rb +21 -11
- data/lib/archivesspace/client/request.rb +1 -0
- data/lib/archivesspace/client/version.rb +1 -1
- data/spec/archivesspace/client_spec.rb +51 -0
- metadata +9 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b567aa6c6f40826a102d43a028600f562d8842f791d8f26269668eaf23757c95
|
|
4
|
+
data.tar.gz: 318036e1c02449bf25265431d44baa2d765970f782cc836daa9db25bd2ca3f89
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 10bae2e2c595663d40ec0629444639acd5c3750ea866a3dc0623152a5598818b33d2d511346d702759cbab9948941fc7fe9b4f0208cabd0c17cbee66d3b52ea3
|
|
7
|
+
data.tar.gz: 000440d2cfeed3c329c08b37040a3b1be15189f41d69afc0ff54e9426915c70165122d320687ad32eae1fc7277fa1321bc22b8cc26e480b8cb166bc03b213868
|
data/README.md
CHANGED
|
@@ -4,22 +4,22 @@ Interact with ArchivesSpace via the API.
|
|
|
4
4
|
|
|
5
5
|
<!-- TOC start (generated with https://github.com/derlin/bitdowntoc) -->
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Usage](#usage)
|
|
9
|
+
- [Configuring a client](#configuring-a-client)
|
|
10
|
+
- [Default configuration](#default-configuration)
|
|
11
|
+
- [Custom configuration, on the fly](#custom-configuration-on-the-fly)
|
|
12
|
+
- [Custom configuration, stored for use with CLI or console](#custom-configuration-stored-for-use-with-cli-or-console)
|
|
13
|
+
- [Making basic requests](#making-basic-requests)
|
|
14
|
+
- [Setting a repository context](#setting-a-repository-context)
|
|
15
|
+
- [Templates](#templates)
|
|
16
|
+
- [CLI](#cli)
|
|
17
|
+
- [Console usage](#console-usage)
|
|
18
|
+
- [Development](#development)
|
|
19
|
+
- [Publishing](#publishing)
|
|
20
|
+
- [Changelog](#changelog)
|
|
21
|
+
- [Contributing](#contributing)
|
|
22
|
+
- [License](#license)
|
|
23
23
|
|
|
24
24
|
<!-- TOC end -->
|
|
25
25
|
|
|
@@ -145,7 +145,8 @@ end
|
|
|
145
145
|
```
|
|
146
146
|
|
|
147
147
|
Scopes restore the previous context on exit (even if the block raises) and can
|
|
148
|
-
be nested
|
|
148
|
+
be nested. Call `repository` with no id to nest a global-scope block inside a
|
|
149
|
+
repository scope:
|
|
149
150
|
|
|
150
151
|
```ruby
|
|
151
152
|
client.repository(2) do
|
|
@@ -153,6 +154,11 @@ client.repository(2) do
|
|
|
153
154
|
client.resources # scoped to repo 3
|
|
154
155
|
end
|
|
155
156
|
client.resources # back to repo 2
|
|
157
|
+
|
|
158
|
+
client.repository do
|
|
159
|
+
client.get('repositories') # global scope
|
|
160
|
+
end
|
|
161
|
+
client.resources # back to repo 2 again
|
|
156
162
|
end
|
|
157
163
|
|
|
158
164
|
# now back in the global scope
|
|
@@ -260,19 +266,33 @@ main/master branch a new release will be built and published.
|
|
|
260
266
|
|
|
261
267
|
## Changelog
|
|
262
268
|
|
|
269
|
+
### 0.7.0
|
|
270
|
+
|
|
271
|
+
- Add support for multipart POST requests, including file uploads to the
|
|
272
|
+
`jobs_with_files` endpoint.
|
|
273
|
+
|
|
274
|
+
### 0.6.0
|
|
275
|
+
|
|
276
|
+
- Support global scope within a nested context. This makes it much
|
|
277
|
+
more ergonomic to request uris within a repository context.
|
|
278
|
+
|
|
279
|
+
### 0.5.1
|
|
280
|
+
|
|
281
|
+
- Fix: prevent caller options passed to request from being mutated.
|
|
282
|
+
|
|
263
283
|
### 0.5.0
|
|
264
284
|
|
|
265
285
|
Breaking changes:
|
|
266
286
|
|
|
267
|
-
|
|
287
|
+
- Removed the `base_repo` configuration option. Use `client.repository(id)` to
|
|
268
288
|
scope requests to a repository instead, either persistently or with a
|
|
269
289
|
block that auto-restores the previous scope.
|
|
270
|
-
|
|
290
|
+
- `client.repository(id)` with a block now saves and restores the previous
|
|
271
291
|
context (including when nested or when the block raises), instead of always
|
|
272
292
|
resetting to the global scope.
|
|
273
|
-
|
|
293
|
+
- Login failure now raises `ArchivesSpace::AuthenticationError` (was
|
|
274
294
|
`ConnectionError`). `ConnectionError` has been removed.
|
|
275
|
-
|
|
295
|
+
- `Client.new` raises `ArchivesSpace::ConfigurationError` (was `RuntimeError`)
|
|
276
296
|
when given a non-`Configuration` argument.
|
|
277
297
|
|
|
278
298
|
## Contributing
|
|
@@ -29,8 +29,8 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
spec.add_development_dependency "vcr", "~> 6.3"
|
|
30
30
|
spec.add_development_dependency "webmock", "~> 3.24"
|
|
31
31
|
|
|
32
|
-
spec.add_dependency "dry-cli", "
|
|
33
|
-
spec.add_dependency "httparty", "~> 0.
|
|
32
|
+
spec.add_dependency "dry-cli", "< 2.0"
|
|
33
|
+
spec.add_dependency "httparty", "~> 0.16"
|
|
34
34
|
spec.add_dependency "json", "~> 2.0"
|
|
35
35
|
spec.add_dependency "jbuilder", "~> 2.12"
|
|
36
36
|
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
4
|
+
require "archivesspace/client"
|
|
5
|
+
|
|
6
|
+
# usage: ruby examples/upload_ead.rb path/to/ead.xml
|
|
7
|
+
path = ARGV.fetch(0) { abort "usage: ruby #{$PROGRAM_NAME} path/to/ead.xml" }
|
|
8
|
+
|
|
9
|
+
# official sandbox, config boilerplate
|
|
10
|
+
config = ArchivesSpace::Configuration.new(
|
|
11
|
+
{
|
|
12
|
+
base_uri: "https://test.archivesspace.org/staff/api",
|
|
13
|
+
username: "admin",
|
|
14
|
+
password: "admin",
|
|
15
|
+
page_size: 50,
|
|
16
|
+
throttle: 0,
|
|
17
|
+
verify_ssl: false
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
client = ArchivesSpace::Client.new(config).login
|
|
22
|
+
|
|
23
|
+
job = {
|
|
24
|
+
jsonmodel_type: "job",
|
|
25
|
+
job: {
|
|
26
|
+
jsonmodel_type: "import_job",
|
|
27
|
+
import_type: "ead_xml",
|
|
28
|
+
filenames: [File.basename(path)]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
client.repository 2 do
|
|
33
|
+
response = File.open(path) do |file|
|
|
34
|
+
client.post_multipart("jobs_with_files", {job: job.to_json, files: [file]})
|
|
35
|
+
end
|
|
36
|
+
abort "upload failed (#{response.status_code}): #{response.body}" unless
|
|
37
|
+
response.status_code == 200
|
|
38
|
+
|
|
39
|
+
job_id = response.parsed["id"]
|
|
40
|
+
puts "created import job #{job_id}"
|
|
41
|
+
|
|
42
|
+
# poll until the import finishes, but not for more than ~60s
|
|
43
|
+
status = nil
|
|
44
|
+
30.times do
|
|
45
|
+
status = client.get("jobs/#{job_id}").parsed["status"]
|
|
46
|
+
puts "status: #{status}"
|
|
47
|
+
break if %w[completed failed canceled].include?(status)
|
|
48
|
+
|
|
49
|
+
sleep 2
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
puts client.get("jobs/#{job_id}/log").body
|
|
53
|
+
end
|
|
@@ -33,6 +33,12 @@ module ArchivesSpace
|
|
|
33
33
|
request "POST", path, {body: payload.to_json, query: params}
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
# Allow passing a file object (multipart = true)
|
|
37
|
+
def post_multipart(path, payload, params = {})
|
|
38
|
+
body = payload.transform_values { |v| v.is_a?(Hash) ? v.to_json : v }
|
|
39
|
+
request "POST", path, {body: body, query: params, multipart: true}
|
|
40
|
+
end
|
|
41
|
+
|
|
36
42
|
def put(path, payload, params = {})
|
|
37
43
|
request "PUT", path, {body: payload.to_json, query: params}
|
|
38
44
|
end
|
|
@@ -42,18 +48,22 @@ module ArchivesSpace
|
|
|
42
48
|
end
|
|
43
49
|
|
|
44
50
|
# Scoping requests
|
|
45
|
-
def repository(id)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
def repository(id = nil)
|
|
52
|
+
if id.nil?
|
|
53
|
+
return use_global_repository unless block_given?
|
|
54
|
+
|
|
55
|
+
new_context = nil
|
|
56
|
+
else
|
|
57
|
+
begin
|
|
58
|
+
Integer(id)
|
|
59
|
+
rescue ArgumentError, TypeError
|
|
60
|
+
raise RepositoryIdError, "Invalid Repository id: #{id}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
new_context = "repositories/#{id}"
|
|
64
|
+
return @context = new_context unless block_given?
|
|
52
65
|
end
|
|
53
66
|
|
|
54
|
-
new_context = "repositories/#{id}"
|
|
55
|
-
return @context = new_context unless block_given?
|
|
56
|
-
|
|
57
67
|
previous = @context
|
|
58
68
|
@context = new_context
|
|
59
69
|
begin
|
|
@@ -72,7 +82,7 @@ module ArchivesSpace
|
|
|
72
82
|
def request(method, path, options = {})
|
|
73
83
|
sleep config.throttle
|
|
74
84
|
options = options.dup
|
|
75
|
-
options[:headers] = {TOKEN => token
|
|
85
|
+
options[:headers] = options.fetch(:headers, {}).merge(TOKEN => token) if token
|
|
76
86
|
Request.new(context, config, method, path, options).execute
|
|
77
87
|
end
|
|
78
88
|
end
|
|
@@ -17,6 +17,7 @@ module ArchivesSpace
|
|
|
17
17
|
@options = options.dup
|
|
18
18
|
|
|
19
19
|
@options[:headers] = DEFAULT_HEADERS.merge(@options.fetch(:headers, {}))
|
|
20
|
+
@options[:headers].delete("Content-Type") if @options[:multipart]
|
|
20
21
|
@options[:headers]["User-Agent"] = "#{Client::NAME}/#{Client::VERSION}"
|
|
21
22
|
|
|
22
23
|
@options[:verify] = config.verify_ssl
|
|
@@ -141,6 +141,39 @@ describe ArchivesSpace::Client do
|
|
|
141
141
|
expect(client.context).to eq "repositories/2"
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
+
it "scopes to the global repository within a block and restores afterwards" do
|
|
145
|
+
client.repository 2
|
|
146
|
+
client.repository(nil) do
|
|
147
|
+
expect(client.context).to be_nil
|
|
148
|
+
end
|
|
149
|
+
expect(client.context).to eq "repositories/2"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "scopes to the global repository when called with no id and a block" do
|
|
153
|
+
client.repository 2
|
|
154
|
+
client.repository do
|
|
155
|
+
expect(client.context).to be_nil
|
|
156
|
+
end
|
|
157
|
+
expect(client.context).to eq "repositories/2"
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "nests a no-arg global block inside a repository block and restores both contexts" do
|
|
161
|
+
client.repository(2) do
|
|
162
|
+
expect(client.context).to eq "repositories/2"
|
|
163
|
+
client.repository do
|
|
164
|
+
expect(client.context).to be_nil
|
|
165
|
+
end
|
|
166
|
+
expect(client.context).to eq "repositories/2"
|
|
167
|
+
end
|
|
168
|
+
expect(client.context).to be_nil
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "restores the previous repository context even if a nil-scoped block raises" do
|
|
172
|
+
client.repository 2
|
|
173
|
+
expect { client.repository(nil) { raise "boom" } }.to raise_error("boom")
|
|
174
|
+
expect(client.context).to eq "repositories/2"
|
|
175
|
+
end
|
|
176
|
+
|
|
144
177
|
it "restores the context even if the block raises" do
|
|
145
178
|
expect { client.repository(2) { raise "boom" } }.to raise_error("boom")
|
|
146
179
|
expect(client.context).to be_nil
|
|
@@ -176,6 +209,24 @@ describe ArchivesSpace::Client do
|
|
|
176
209
|
client.get("resources", opts)
|
|
177
210
|
expect(opts).to eq(caller_opts)
|
|
178
211
|
end
|
|
212
|
+
|
|
213
|
+
it "posts a file (as multipart form data) with session token" do
|
|
214
|
+
client.token = "abc123"
|
|
215
|
+
stub = stub_request(:post, "#{DEFAULT_BASE_URI}/repositories/2/jobs_with_files")
|
|
216
|
+
.with { |req|
|
|
217
|
+
req.headers["Content-Type"].start_with?("multipart/form-data; boundary=") &&
|
|
218
|
+
req.headers["X-Archivesspace-Session"] == "abc123" &&
|
|
219
|
+
req.body.include?('name="files[]"; filename="client_spec.rb"') &&
|
|
220
|
+
req.body.include?('name="job"')
|
|
221
|
+
}
|
|
222
|
+
.to_return(status: 200, body: "{}", headers: {"Content-Type" => "application/json"})
|
|
223
|
+
File.open(__FILE__) do |file|
|
|
224
|
+
client.repository(2) do
|
|
225
|
+
client.post_multipart("jobs_with_files", {job: {jsonmodel_type: "job"}, files: [file]})
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
expect(stub).to have_been_requested
|
|
229
|
+
end
|
|
179
230
|
end
|
|
180
231
|
|
|
181
232
|
describe "URL construction" do
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: archivesspace-client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mark Cooper
|
|
@@ -145,30 +145,30 @@ dependencies:
|
|
|
145
145
|
name: dry-cli
|
|
146
146
|
requirement: !ruby/object:Gem::Requirement
|
|
147
147
|
requirements:
|
|
148
|
-
- - "
|
|
148
|
+
- - "<"
|
|
149
149
|
- !ruby/object:Gem::Version
|
|
150
|
-
version: '0
|
|
150
|
+
version: '2.0'
|
|
151
151
|
type: :runtime
|
|
152
152
|
prerelease: false
|
|
153
153
|
version_requirements: !ruby/object:Gem::Requirement
|
|
154
154
|
requirements:
|
|
155
|
-
- - "
|
|
155
|
+
- - "<"
|
|
156
156
|
- !ruby/object:Gem::Version
|
|
157
|
-
version: '0
|
|
157
|
+
version: '2.0'
|
|
158
158
|
- !ruby/object:Gem::Dependency
|
|
159
159
|
name: httparty
|
|
160
160
|
requirement: !ruby/object:Gem::Requirement
|
|
161
161
|
requirements:
|
|
162
162
|
- - "~>"
|
|
163
163
|
- !ruby/object:Gem::Version
|
|
164
|
-
version: '0.
|
|
164
|
+
version: '0.16'
|
|
165
165
|
type: :runtime
|
|
166
166
|
prerelease: false
|
|
167
167
|
version_requirements: !ruby/object:Gem::Requirement
|
|
168
168
|
requirements:
|
|
169
169
|
- - "~>"
|
|
170
170
|
- !ruby/object:Gem::Version
|
|
171
|
-
version: '0.
|
|
171
|
+
version: '0.16'
|
|
172
172
|
- !ruby/object:Gem::Dependency
|
|
173
173
|
name: json
|
|
174
174
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -223,6 +223,7 @@ files:
|
|
|
223
223
|
- examples/templates.rb
|
|
224
224
|
- examples/test_connection.rb
|
|
225
225
|
- examples/update_feed.rb
|
|
226
|
+
- examples/upload_ead.rb
|
|
226
227
|
- examples/user_groups.rb
|
|
227
228
|
- exe/asclient
|
|
228
229
|
- features/exec.feature
|
|
@@ -269,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
269
270
|
- !ruby/object:Gem::Version
|
|
270
271
|
version: '0'
|
|
271
272
|
requirements: []
|
|
272
|
-
rubygems_version: 4.0.
|
|
273
|
+
rubygems_version: 4.0.22
|
|
273
274
|
specification_version: 4
|
|
274
275
|
summary: Interact with ArchivesSpace via the API.
|
|
275
276
|
test_files: []
|