shotgun_api_ruby 0.0.8 → 0.1.1

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.
@@ -3,12 +3,17 @@
3
3
  module ShotgunApiRuby
4
4
  class Entities
5
5
  class Params < Hash
6
+ class TooComplexFiltersError < StandardError
7
+ end
8
+
6
9
  def add_sort(sort)
7
10
  return unless sort
8
11
 
9
12
  self[:sort] =
10
13
  if sort.is_a?(Hash)
11
- sort.map{ |field, direction| "#{direction.to_s.start_with?('desc') ? '-' : ''}#{field}" }.join(',')
14
+ sort.map do |field, direction|
15
+ "#{direction.to_s.start_with?('desc') ? '-' : ''}#{field}"
16
+ end.join(',')
12
17
  else
13
18
  [sort].flatten.join(',')
14
19
  end
@@ -26,11 +31,7 @@ module ShotgunApiRuby
26
31
 
27
32
  def add_fields(fields)
28
33
  self[:fields] =
29
- if fields
30
- [fields].flatten.join(',')
31
- else
32
- "*"
33
- end
34
+ fields && !fields.empty? ? [fields].flatten.join(',') : '*'
34
35
  end
35
36
 
36
37
  def add_options(return_only, include_archived_projects)
@@ -42,16 +43,95 @@ module ShotgunApiRuby
42
43
  }
43
44
  end
44
45
 
45
- def add_filter(filters)
46
+ def add_filter(filters, logical_operator = 'and')
46
47
  return unless filters
47
48
 
48
- # filter
49
- self['filter'] = translate_simple_filter_to_sg(filters)
49
+ self[:filter] =
50
+ if (self.class.filters_are_simple?(filters))
51
+ translate_simple_filters_to_sg(filters)
52
+ elsif filters.is_a? Hash
53
+ {
54
+ conditions:
55
+ filters[:conditions] || filters['conditions'] ||
56
+ translate_complex_filters_to_sg(filters),
57
+ logical_operator:
58
+ filters[:logical_operator] || filters['logical_operator'] ||
59
+ logical_operator,
60
+ }
61
+ else
62
+ { conditions: filters, logical_operator: logical_operator }
63
+ end
64
+ end
65
+
66
+ def add_grouping(grouping)
67
+ return unless grouping
68
+
69
+ if grouping.is_a? Array
70
+ self[:grouping] = grouping
71
+ return
72
+ end
73
+
74
+ self[:grouping] =
75
+ grouping
76
+ .each
77
+ .with_object([]) do |(key, options), result|
78
+ if options.is_a? Hash
79
+ result << {
80
+ field: key.to_s,
81
+ type:
82
+ options[:type]&.to_s || options['type']&.to_s || 'exact',
83
+ direction:
84
+ options[:direction]&.to_s || options['direction']&.to_s ||
85
+ 'asc',
86
+ }
87
+ else
88
+ result << {
89
+ field: key.to_s,
90
+ type: 'exact',
91
+ direction: options.to_s,
92
+ }
93
+ end
94
+ end
95
+ end
96
+
97
+ def add_summary_fields(summary_fields)
98
+ return unless summary_fields
99
+
100
+ if summary_fields.is_a? Array
101
+ self[:summary_fields] = summary_fields
102
+ return
103
+ end
104
+
105
+ if summary_fields.is_a? Hash
106
+ self[:summary_fields] =
107
+ summary_fields.map { |k, v| { field: k.to_s, type: v.to_s } }
108
+ end
109
+ end
110
+
111
+ def self.filters_are_simple?(filters)
112
+ return false if filters.is_a? Array
113
+
114
+ if filters.is_a?(Hash) &&
115
+ (filters[:conditions] || filters['conditions'])
116
+ return false
117
+ end
118
+
119
+ filters.values.all? do |filter_val|
120
+ (
121
+ filter_val.is_a?(Integer) || filter_val.is_a?(String) ||
122
+ filter_val.is_a?(Symbol)
123
+ ) ||
124
+ (
125
+ filter_val.is_a?(Array) && filter_val.all? do |val|
126
+ val.is_a?(String) || val.is_a?(Symbol) || val.is_a?(Integer)
127
+ end
128
+ )
129
+ end
50
130
  end
51
131
 
52
132
  private
53
133
 
54
- def translate_simple_filter_to_sg(filters)
134
+ def translate_simple_filters_to_sg(filters)
55
135
  filters.map do |field, value|
56
136
  [
57
137
  field.to_s,
@@ -59,6 +139,44 @@ module ShotgunApiRuby
59
139
  ]
60
140
  end.to_h
61
141
  end
142
+
143
+ def translate_complex_filters_to_sg(filters)
144
+ # We don't know how to translate anything but hashes
145
+ return filters if !filters.is_a?(Hash)
146
+
147
+ filters
148
+ .each
149
+ .with_object([]) do |item, result|
150
+ field, value = item
151
+ case value
152
+ when String, Symbol, Integer, Float
153
+ result << [field.to_s, 'is', value]
154
+ when Hash
155
+ value.each do |subfield, subvalue|
156
+ sanitized_subfield =
157
+ if !subfield.to_s.include?('.')
158
+ "#{field.capitalize}.#{subfield}"
159
+ else
160
+ subfield
161
+ end
162
+ case subvalue
163
+ when String, Symbol, Integer, Float
164
+ result << ["#{field}.#{sanitized_subfield}", 'is', subvalue]
165
+ when Array
166
+ result << ["#{field}.#{sanitized_subfield}", 'in', subvalue]
167
+ else
168
+ raise TooComplexFiltersError,
169
+ 'This case is too complex to auto-translate. Please use shotgun query syntax.'
170
+ end
171
+ end
172
+ when Array
173
+ result << [field.to_s, 'in', value]
174
+ else
175
+ raise TooComplexFiltersError,
176
+ 'This case is too complex to auto-translate. Please use shotgun query syntax.'
177
+ end
178
+ end
179
+ end
62
180
  end
63
181
  end
64
182
  end
@@ -19,9 +19,7 @@ module ShotgunApiRuby
19
19
 
20
20
  resp_body = JSON.parse(resp.body)
21
21
 
22
- OpenStruct.new(
23
- resp_body["data"].transform_values{ |v| v["value"] }
24
- )
22
+ OpenStruct.new(resp_body['data'].transform_values { |v| v['value'] })
25
23
  end
26
24
 
27
25
  def fields
@@ -33,15 +31,18 @@ module ShotgunApiRuby
33
31
  end
34
32
 
35
33
  OpenStruct.new(
36
- resp_body["data"].transform_values do |value|
34
+ resp_body['data'].transform_values do |value|
37
35
  OpenStruct.new(
38
- value.transform_values do |attribute|
39
- attribute["value"]
40
- end.merge(
41
- properties: OpenStruct.new(value["properties"].transform_values{ |prop| prop["value"] })
42
- )
36
+ value.transform_values { |attribute| attribute['value'] }.merge(
37
+ properties:
38
+ OpenStruct.new(
39
+ value['properties'].transform_values do |prop|
40
+ prop['value']
41
+ end,
42
+ ),
43
+ ),
43
44
  )
44
- end
45
+ end,
45
46
  )
46
47
  end
47
48
  end
@@ -0,0 +1,64 @@
1
+ module ShotgunApiRuby
2
+ class Entities
3
+ class Summarize
4
+ Summary = Struct.new(:summaries, :groups)
5
+
6
+ def initialize(connection, type, base_url_prefix)
7
+ @connection = connection.dup
8
+ @type = type
9
+ @connection.url_prefix = "#{base_url_prefix}/entity/#{type}/_summarize"
10
+ end
11
+ attr_reader :type, :connection
12
+
13
+ def count(filter: nil, logical_operator: 'and')
14
+ result =
15
+ summarize(
16
+ filter: filter,
17
+ logical_operator: logical_operator,
18
+ summary_fields: [{ type: :record_count, field: 'id' }],
19
+ )
20
+ result.summaries&.[]('id') || 0
21
+ end
22
+
23
+ def summarize(
24
+ filter: nil,
25
+ grouping: nil,
26
+ summary_fields: nil,
27
+ logical_operator: 'and',
28
+ include_archived_projects: nil
29
+ )
30
+ params = Params.new
31
+
32
+ params.add_filter(filter, logical_operator)
33
+
34
+ params[:filters] = params[:filter] if params[:filter]
35
+ params.delete(:filter)
36
+
37
+ params.add_grouping(grouping)
38
+ params.add_summary_fields(summary_fields)
39
+ params.add_options(nil, include_archived_projects)
40
+
41
+ resp =
42
+ @connection.post('', params) do |req|
43
+ req.headers['Content-Type'] =
44
+ if params[:filters].is_a? Array
45
+ 'application/vnd+shotgun.api3_array+json'
46
+ else
47
+ 'application/vnd+shotgun.api3_hash+json'
48
+ end
49
+ req.body = params.to_h.to_json
50
+ end
51
+ resp_body = JSON.parse(resp.body)
52
+
53
+ if resp.status >= 300
54
+ raise "Error while getting summarize for #{type}: #{resp_body['errors']}"
55
+ end
56
+
57
+ Summary.new(
58
+ resp_body['data']['summaries'],
59
+ resp_body['data']&.[]('groups'),
60
+ )
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,13 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShotgunApiRuby
4
+ # Represent each entity returned by Shotgun
4
5
  Entity =
5
6
  Struct.new(:type, :attributes, :relationships, :id, :links) do
6
7
  def method_missing(name, *args, &block)
7
8
  if attributes.respond_to?(name)
8
- define_singleton_method(name) do
9
- attributes.public_send(name)
10
- end
9
+ define_singleton_method(name) { attributes.public_send(name) }
11
10
  public_send(name)
12
11
  else
13
12
  super
@@ -17,7 +17,7 @@ module ShotgunApiRuby
17
17
  raise "Error while getting server preferences: #{resp_body['errors']}"
18
18
  end
19
19
 
20
- data = resp_body["data"]
20
+ data = resp_body['data']
21
21
  OpenStruct.new(data)
22
22
  end
23
23
  end
@@ -16,7 +16,7 @@ module ShotgunApiRuby
16
16
  raise "Error while getting server infos: #{resp_body['errors']}"
17
17
  end
18
18
 
19
- data = resp_body["data"]
19
+ data = resp_body['data']
20
20
  OpenStruct.new(data)
21
21
  end
22
22
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ShotgunApiRuby
4
- VERSION = "0.0.8"
4
+ VERSION = '0.1.1'
5
5
  end
data/package.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "shotgun_api_ruby",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "repository": "git@github.com:shotgunsoftware/shotgun_api_ruby.git",
6
+ "author": "Denis <Zaratan> Pasin <zaratan@hey.com>",
7
+ "license": "MIT",
8
+ "devDependencies": {
9
+ "@prettier/plugin-ruby": "^1.3.0",
10
+ "prettier": "^2.2.1"
11
+ }
12
+ }
@@ -26,8 +26,6 @@ Gem::Specification.new do |spec|
26
26
  Dir.chdir(File.expand_path(__dir__)) do
27
27
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
28
28
  end
29
- spec.bindir = "exe"
30
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
29
  spec.require_paths = ["lib"]
32
30
 
33
31
  spec.add_dependency "activesupport"
@@ -37,11 +35,20 @@ Gem::Specification.new do |spec|
37
35
  spec.add_development_dependency "bundler"
38
36
  spec.add_development_dependency "bundler-audit"
39
37
  spec.add_development_dependency "dotenv"
38
+ spec.add_development_dependency 'faker', '> 1.8'
39
+ spec.add_development_dependency 'guard-rspec', '> 4.7'
40
40
  spec.add_development_dependency "overcommit"
41
+ spec.add_development_dependency "prettier"
41
42
  spec.add_development_dependency "pry"
42
43
  spec.add_development_dependency "rake"
43
44
  spec.add_development_dependency "rspec", "~> 3.0"
45
+ spec.add_development_dependency 'rspec_in_context', '> 1'
44
46
  spec.add_development_dependency "rubocop"
47
+ spec.add_development_dependency 'rubocop-faker'
45
48
  spec.add_development_dependency "rubocop-performance"
49
+ spec.add_development_dependency 'simplecov', '> 0.16'
46
50
  spec.add_development_dependency "solargraph"
51
+ spec.add_development_dependency 'timecop'
52
+ spec.add_development_dependency 'vcr'
53
+ spec.add_development_dependency 'yard'
47
54
  end
data/yarn.lock ADDED
@@ -0,0 +1,15 @@
1
+ # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2
+ # yarn lockfile v1
3
+
4
+
5
+ "@prettier/plugin-ruby@^1.3.0":
6
+ version "1.5.5"
7
+ resolved "https://registry.yarnpkg.com/@prettier/plugin-ruby/-/plugin-ruby-1.5.5.tgz#9e206fc856a182a292fcfab9043f53c7a3d0af97"
8
+ integrity sha512-b387GdXU+LrnY+oaKWRUI5EnsUvrQ0G1jUSVPkvUTGzp/w+BB9/n4SICVPY3V9/wYsvWpAZq4LkE4FdBufXUtA==
9
+ dependencies:
10
+ prettier ">=1.10"
11
+
12
+ prettier@>=1.10, prettier@^2.2.1:
13
+ version "2.3.1"
14
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.1.tgz#76903c3f8c4449bc9ac597acefa24dc5ad4cbea6"
15
+ integrity sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA==
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shotgun_api_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis <Zaratan> Pasin
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-16 00:00:00.000000000 Z
11
+ date: 2021-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -94,6 +94,34 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: faker
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.8'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.8'
111
+ - !ruby/object:Gem::Dependency
112
+ name: guard-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">"
116
+ - !ruby/object:Gem::Version
117
+ version: '4.7'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">"
123
+ - !ruby/object:Gem::Version
124
+ version: '4.7'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: overcommit
99
127
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +136,20 @@ dependencies:
108
136
  - - ">="
109
137
  - !ruby/object:Gem::Version
110
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: prettier
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
111
153
  - !ruby/object:Gem::Dependency
112
154
  name: pry
113
155
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +192,20 @@ dependencies:
150
192
  - - "~>"
151
193
  - !ruby/object:Gem::Version
152
194
  version: '3.0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: rspec_in_context
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">"
200
+ - !ruby/object:Gem::Version
201
+ version: '1'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">"
207
+ - !ruby/object:Gem::Version
208
+ version: '1'
153
209
  - !ruby/object:Gem::Dependency
154
210
  name: rubocop
155
211
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +220,20 @@ dependencies:
164
220
  - - ">="
165
221
  - !ruby/object:Gem::Version
166
222
  version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: rubocop-faker
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
167
237
  - !ruby/object:Gem::Dependency
168
238
  name: rubocop-performance
169
239
  requirement: !ruby/object:Gem::Requirement
@@ -178,6 +248,20 @@ dependencies:
178
248
  - - ">="
179
249
  - !ruby/object:Gem::Version
180
250
  version: '0'
251
+ - !ruby/object:Gem::Dependency
252
+ name: simplecov
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ">"
256
+ - !ruby/object:Gem::Version
257
+ version: '0.16'
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - ">"
263
+ - !ruby/object:Gem::Version
264
+ version: '0.16'
181
265
  - !ruby/object:Gem::Dependency
182
266
  name: solargraph
183
267
  requirement: !ruby/object:Gem::Requirement
@@ -192,6 +276,48 @@ dependencies:
192
276
  - - ">="
193
277
  - !ruby/object:Gem::Version
194
278
  version: '0'
279
+ - !ruby/object:Gem::Dependency
280
+ name: timecop
281
+ requirement: !ruby/object:Gem::Requirement
282
+ requirements:
283
+ - - ">="
284
+ - !ruby/object:Gem::Version
285
+ version: '0'
286
+ type: :development
287
+ prerelease: false
288
+ version_requirements: !ruby/object:Gem::Requirement
289
+ requirements:
290
+ - - ">="
291
+ - !ruby/object:Gem::Version
292
+ version: '0'
293
+ - !ruby/object:Gem::Dependency
294
+ name: vcr
295
+ requirement: !ruby/object:Gem::Requirement
296
+ requirements:
297
+ - - ">="
298
+ - !ruby/object:Gem::Version
299
+ version: '0'
300
+ type: :development
301
+ prerelease: false
302
+ version_requirements: !ruby/object:Gem::Requirement
303
+ requirements:
304
+ - - ">="
305
+ - !ruby/object:Gem::Version
306
+ version: '0'
307
+ - !ruby/object:Gem::Dependency
308
+ name: yard
309
+ requirement: !ruby/object:Gem::Requirement
310
+ requirements:
311
+ - - ">="
312
+ - !ruby/object:Gem::Version
313
+ version: '0'
314
+ type: :development
315
+ prerelease: false
316
+ version_requirements: !ruby/object:Gem::Requirement
317
+ requirements:
318
+ - - ">="
319
+ - !ruby/object:Gem::Version
320
+ version: '0'
195
321
  description: Gem to facilitate the interaction with Shotgun's REST API.
196
322
  email:
197
323
  - denis.pasin@autodesk.com
@@ -204,6 +330,7 @@ files:
204
330
  - ".github/workflows/verify_version_change.yml"
205
331
  - ".gitignore"
206
332
  - ".overcommit.yml"
333
+ - ".prettierrc.js"
207
334
  - ".rspec"
208
335
  - ".rubocop-http---relaxed-ruby-style-rubocop-yml"
209
336
  - ".rubocop.yml"
@@ -212,11 +339,13 @@ files:
212
339
  - ".travis.yml"
213
340
  - CHANGELOG.md
214
341
  - Gemfile
215
- - Gemfile.lock
342
+ - Guardfile
216
343
  - LICENSE.txt
217
344
  - README.md
218
345
  - Rakefile
219
346
  - bin/console
347
+ - bin/prettirun
348
+ - bin/ruborun
220
349
  - bin/setup
221
350
  - lib/shotgun_api_ruby.rb
222
351
  - lib/shotgun_api_ruby/auth.rb
@@ -224,11 +353,14 @@ files:
224
353
  - lib/shotgun_api_ruby/entities.rb
225
354
  - lib/shotgun_api_ruby/entities/params.rb
226
355
  - lib/shotgun_api_ruby/entities/schema.rb
356
+ - lib/shotgun_api_ruby/entities/summarize.rb
227
357
  - lib/shotgun_api_ruby/entity.rb
228
358
  - lib/shotgun_api_ruby/preferences.rb
229
359
  - lib/shotgun_api_ruby/server_info.rb
230
360
  - lib/shotgun_api_ruby/version.rb
361
+ - package.json
231
362
  - shotgun_api_ruby.gemspec
363
+ - yarn.lock
232
364
  homepage: https://github.com/shotgunsoftware/shotgun_api_ruby
233
365
  licenses:
234
366
  - MIT
@@ -251,7 +383,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
251
383
  - !ruby/object:Gem::Version
252
384
  version: '0'
253
385
  requirements: []
254
- rubygems_version: 3.1.4
386
+ rubygems_version: 3.2.15
255
387
  signing_key:
256
388
  specification_version: 4
257
389
  summary: Gem to interact easily with Shotgun REST api.