globus_client 0.5.0 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23d56c1a01cd643aafec353ff36adf2ad15b4792ebbd3091745415d5fcce68eb
4
- data.tar.gz: 0d6acdff1f5a627b6a9030bf1e5154c4efef845bab052c27d4d84206ee04c822
3
+ metadata.gz: d1fb97800b48bd1cd82b00c43cc82ea71e24212a4d1385bb84ffb432aaa61715
4
+ data.tar.gz: e29d9c2ee049c83d0e3c63fbcee2abedbdb1706f3fc29ad907870acad06e88e9
5
5
  SHA512:
6
- metadata.gz: 6c6ea6b0df9c20fddb7157cd5c7a0dc3270308ce11805f1fbaebb35f704647e7bc4d097ab5a89edc68c1c87274d3adaa52abd6928d9c5d89a214eb99cf7193ac
7
- data.tar.gz: e25b26ab750b5b176279e26de6887bafc9fc25cce8b406d2aabec931978858580d26f816e9c2c6e92e3b7cca81afaf1cee6aa84490f88c152a65c2d35ee8c3ec
6
+ metadata.gz: 1b2fd795460970e2eb1449d1053a6baafa14a584d892ec2fa00c778e0921a5f23e7d6824cf98641a1c9d0a54c8d5644a563bcde93e935a42f21f4e0f0bd5e743
7
+ data.tar.gz: deb0f58b722e3c12208bbede68147d6d0311e0a3bbc85740dcfa764fdf46b2a57836e6e6391306aade37f93c182b7e3865ae37700485bdb17b5746b2a36a3b21
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- globus_client (0.5.0)
4
+ globus_client (0.7.0)
5
5
  activesupport (>= 4.2, < 8)
6
6
  faraday
7
7
  zeitwerk
@@ -30,13 +30,13 @@ GEM
30
30
  hashdiff (1.0.1)
31
31
  i18n (1.12.0)
32
32
  concurrent-ruby (~> 1.0)
33
- json (2.6.2)
34
- language_server-protocol (3.17.0.1)
33
+ json (2.6.3)
34
+ language_server-protocol (3.17.0.2)
35
35
  minitest (5.16.3)
36
36
  parallel (1.22.1)
37
37
  parser (3.1.3.0)
38
38
  ast (~> 2.4.1)
39
- public_suffix (5.0.0)
39
+ public_suffix (5.0.1)
40
40
  rainbow (3.1.1)
41
41
  rake (13.0.6)
42
42
  regexp_parser (2.6.1)
@@ -50,7 +50,7 @@ GEM
50
50
  rspec-expectations (3.12.0)
51
51
  diff-lcs (>= 1.2.0, < 2.0)
52
52
  rspec-support (~> 3.12.0)
53
- rspec-mocks (3.12.0)
53
+ rspec-mocks (3.12.1)
54
54
  diff-lcs (>= 1.2.0, < 2.0)
55
55
  rspec-support (~> 3.12.0)
56
56
  rspec-support (3.12.0)
@@ -79,8 +79,8 @@ GEM
79
79
  simplecov_json_formatter (~> 0.1)
80
80
  simplecov-html (0.12.3)
81
81
  simplecov_json_formatter (0.1.4)
82
- standard (1.19.0)
83
- language_server-protocol (= 3.17.0.1)
82
+ standard (1.19.1)
83
+ language_server-protocol (~> 3.17.0.2)
84
84
  rubocop (= 1.39.0)
85
85
  rubocop-performance (= 1.15.1)
86
86
  tzinfo (2.0.5)
data/README.md CHANGED
@@ -55,6 +55,16 @@ GlobusClient.configure(
55
55
  def create_user_directory
56
56
  GlobusClient.mkdir(user_id: 'mjgiarlo@stanford.edu', path: 'mjgiarlo/work1234/version1')
57
57
  end
58
+
59
+ def lookup_dir_contents
60
+ GlobusClient.list_files(user_id: "mjgiarlo@stanford.edu", path: "mjgiarlo/work1234/version1") do |files|
61
+ files_count = files.count
62
+ total_size = files.sum(&:size)
63
+ files_list = files.map(&:name)
64
+
65
+ return [files_count, total_size, files_list]
66
+ end
67
+ end
58
68
  # ...
59
69
  ```
60
70
 
@@ -74,8 +84,8 @@ $ export GLOBUS_CLIENT_ID=$(vault kv get -field=content puppet/application/sdr/g
74
84
  $ export GLOBUS_CLIENT_SECRET=$(vault kv get -field=content puppet/application/sdr/globus/{prod|qa|stage}/client_secret)
75
85
  $ export GLOBUS_ENDPOINT=$(vault kv get -field=content puppet/application/sdr/globus/{prod|qa|stage}/endpoint_uuid)
76
86
  $ export GLOBUS_UPLOADS_DIRECTORY=from_shared_configs
77
- # NOTE: The three args below are a user ID, a work ID, and a work version
78
- $ ./api_test.rb mjgiarlo 987 1
87
+ # NOTE: The two args below are a user ID (email) and a path such as a consumer might construct
88
+ $ ./api_test.rb mjgiarlo@stanford.edu mjgiarlo/work987/version1
79
89
 
80
90
  Initial directory permissions: rw
81
91
  Number of files in directory: 2
data/api_test.rb CHANGED
@@ -1,37 +1,56 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
+ require "benchmark"
4
5
  require "bundler/setup"
5
6
  require "globus_client"
6
7
 
7
- GlobusClient.configure(
8
- client_id: ENV["GLOBUS_CLIENT_ID"],
9
- client_secret: ENV["GLOBUS_CLIENT_SECRET"],
10
- uploads_directory: ENV["GLOBUS_UPLOADS_DIRECTORY"],
11
- transfer_endpoint_id: ENV["GLOBUS_ENDPOINT"]
12
- )
13
-
14
- user_id, path = *ARGV
15
-
16
- # Test public API methods here.
17
- GlobusClient.mkdir(user_id:, path:)
18
-
19
- user_exists = GlobusClient.user_exists?(user_id)
20
-
21
- # Not part of the public API but this allows us to test access changes
22
- before_permissions = GlobusClient::Endpoint.new(GlobusClient.config, user_id:, path:).send(:access_rule)["permissions"]
23
-
24
- files_count = GlobusClient.file_count(user_id:, path:)
25
-
26
- total_size = GlobusClient.total_size(user_id:, path:)
27
-
28
- GlobusClient.disallow_writes(user_id:, path:)
29
-
30
- # Not part of the public API but this allows us to test access changes
31
- after_permissions = GlobusClient::Endpoint.new(GlobusClient.config, user_id:, path:).send(:access_rule)["permissions"]
32
-
33
- puts "User #{user_id} exists: #{user_exists}"
34
- puts "Initial directory permissions: #{before_permissions}"
35
- puts "Number of files in directory: #{files_count}"
36
- puts "Total size of files in directory: #{total_size}"
37
- puts "Final directory permissions: #{after_permissions}"
8
+ Benchmark.bm(20) do |benchmark|
9
+ user_id, path = *ARGV
10
+
11
+ benchmark.report("Configure:") do
12
+ GlobusClient.configure(
13
+ client_id: ENV["GLOBUS_CLIENT_ID"],
14
+ client_secret: ENV["GLOBUS_CLIENT_SECRET"],
15
+ uploads_directory: ENV["GLOBUS_UPLOADS_DIRECTORY"],
16
+ transfer_endpoint_id: ENV["GLOBUS_ENDPOINT"]
17
+ )
18
+ end
19
+
20
+ benchmark.report("mkdir:") do
21
+ GlobusClient.mkdir(user_id:, path:)
22
+ end
23
+
24
+ benchmark.report("user_exists?:") do
25
+ @user_exists = GlobusClient.user_exists?(user_id)
26
+ end
27
+
28
+ benchmark.report("before_perms:") do
29
+ # Not part of the public API but this allows us to test access changes
30
+ @before_permissions = GlobusClient::Endpoint.new(GlobusClient.config, user_id:, path:).send(:access_rule)["permissions"]
31
+ end
32
+
33
+ benchmark.report("list_files:") do
34
+ GlobusClient.list_files(user_id:, path:) do |files|
35
+ @files_count = files.count
36
+ @total_size = files.sum(&:size)
37
+ @files_list = files.map(&:name)
38
+ end
39
+ end
40
+
41
+ benchmark.report("disallow_writes:") do
42
+ GlobusClient.disallow_writes(user_id:, path:)
43
+ end
44
+
45
+ benchmark.report("after_perms:") do
46
+ # Not part of the public API but this allows us to test access changes
47
+ @after_permissions = GlobusClient::Endpoint.new(GlobusClient.config, user_id:, path:).send(:access_rule)["permissions"]
48
+ end
49
+
50
+ puts "User #{user_id} exists: #{@user_exists}"
51
+ puts "Initial directory permissions: #{@before_permissions}"
52
+ puts "Number of files in directory: #{@files_count}"
53
+ puts "Total size of files in directory: #{@total_size}"
54
+ puts "List of files in directory: #{@files_list}"
55
+ puts "Final directory permissions: #{@after_permissions}"
56
+ end
@@ -5,6 +5,8 @@ class GlobusClient
5
5
  class Endpoint
6
6
  PATH_SEPARATOR = "/"
7
7
 
8
+ FileInfo = Struct.new(:name, :size)
9
+
8
10
  # @param config [#token, #uploads_directory, #transfer_endpoint_id, #transfer_url, #auth_url] configuration for the gem
9
11
  # @param path [String] the path to operate on
10
12
  # @param user_id [String] a Globus user ID (e.g., a @stanford.edu email address)
@@ -14,12 +16,10 @@ class GlobusClient
14
16
  @path = path
15
17
  end
16
18
 
17
- def file_count
18
- objects["total"]
19
- end
20
-
21
- def total_size
22
- files.sum { |file| file["size"] }
19
+ def list_files
20
+ ls_path(full_path, []).tap do |files|
21
+ yield files if block_given?
22
+ end
23
23
  end
24
24
 
25
25
  # Create a directory https://docs.globus.org/api/transfer/file_operations/#make_directory
@@ -62,7 +62,7 @@ class GlobusClient
62
62
 
63
63
  def connection
64
64
  # Transfer API connection
65
- Faraday.new(
65
+ @connection ||= Faraday.new(
66
66
  url: config.transfer_url,
67
67
  headers: {Authorization: "Bearer #{config.token}"}
68
68
  )
@@ -77,7 +77,7 @@ class GlobusClient
77
77
  # And this method returns:
78
78
  # ["/uploads/mjgiarlo/", "/uploads/mjgiarlo/work123/", "/uploads/mjgiarlo/work123/version1/"]
79
79
  def paths
80
- path_segments.map.with_index do |_segment, index|
80
+ @paths ||= path_segments.map.with_index do |_segment, index|
81
81
  File
82
82
  .join(config.uploads_directory, path_segments.slice(..index))
83
83
  .concat(PATH_SEPARATOR)
@@ -93,16 +93,23 @@ class GlobusClient
93
93
  path.split(PATH_SEPARATOR)
94
94
  end
95
95
 
96
- def objects
97
- # List files at an endpoint https://docs.globus.org/api/transfer/file_operations/#list_directory_contents
98
- response = connection.get("#{transfer_path}/ls?path=#{full_path}")
99
- return JSON.parse(response.body) if response.success?
100
-
101
- UnexpectedResponse.call(response)
102
- end
103
-
104
- def files
105
- objects["DATA"].select { |object| object["DATA_TYPE"] == "file" }
96
+ # @param filepath [String] an absolute path to look up contents e.g. /uploads/example/work123/version1
97
+ # @param files [Array<FileInfo>] an array of FileInfo structs, each of which has a name and a size
98
+ def ls_path(filepath, files)
99
+ # List files recursively at an endpoint https://docs.globus.org/api/transfer/file_operations/#list_directory_contents
100
+ response = connection.get("#{transfer_path}/ls?path=#{filepath}")
101
+ if response.success?
102
+ data = JSON.parse(response.body)["DATA"]
103
+ data
104
+ .select { |object| object["type"] == "file" }
105
+ .each { |file| files << FileInfo.new("#{filepath}#{file["name"]}", file["size"]) }
106
+ data
107
+ .select { |object| object["type"] == "dir" }
108
+ .each { |dir| ls_path("#{filepath}#{dir["name"]}/", files) }
109
+ else
110
+ UnexpectedResponse.call(response)
111
+ end
112
+ files
106
113
  end
107
114
 
108
115
  def access_request(permissions:)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class GlobusClient
4
- VERSION = "0.5.0"
4
+ VERSION = "0.7.0"
5
5
  end
data/lib/globus_client.rb CHANGED
@@ -32,7 +32,7 @@ class GlobusClient
32
32
  self
33
33
  end
34
34
 
35
- delegate :config, :disallow_writes, :file_count, :mkdir, :total_size, :user_exists?, to: :instance
35
+ delegate :config, :disallow_writes, :file_count, :list_files, :mkdir, :total_size, :user_exists?, :get_filenames, to: :instance
36
36
 
37
37
  def default_transfer_url
38
38
  "https://transfer.api.globusonline.org"
@@ -56,14 +56,27 @@ class GlobusClient
56
56
  endpoint.disallow_writes
57
57
  end
58
58
 
59
+ # NOTE: Can't use the `...` (argument forwarding) operator here because we
60
+ # want to route the keyword args to `Endpoint#new` and the block arg to
61
+ # `Endpoint#list_files`
62
+ def list_files(**keywords, &block)
63
+ endpoint = Endpoint.new(config, **keywords)
64
+ endpoint.list_files(&block)
65
+ end
66
+
59
67
  def file_count(...)
60
68
  endpoint = Endpoint.new(config, ...)
61
- endpoint.file_count
69
+ endpoint.list_files { |files| return files.count }
62
70
  end
63
71
 
64
72
  def total_size(...)
65
73
  endpoint = Endpoint.new(config, ...)
66
- endpoint.total_size
74
+ endpoint.list_files { |files| return files.sum(&:size) }
75
+ end
76
+
77
+ def get_filenames(...)
78
+ endpoint = Endpoint.new(config, ...)
79
+ endpoint.list_files { |files| return files.map(&:name) }
67
80
  end
68
81
 
69
82
  def user_exists?(...)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: globus_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Collier
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-12-09 00:00:00.000000000 Z
13
+ date: 2022-12-16 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport