gapic-generator 0.1.5 → 0.3.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.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -0
  3. data/lib/gapic/formatting_utils.rb +63 -12
  4. data/lib/gapic/generator/version.rb +1 -1
  5. data/lib/gapic/generators/base_generator.rb +0 -8
  6. data/lib/gapic/generators/default_generator.rb +13 -14
  7. data/lib/gapic/helpers/filepath_helper.rb +45 -0
  8. data/lib/gapic/helpers/namespace_helper.rb +51 -0
  9. data/lib/gapic/presenters.rb +44 -0
  10. data/{templates/default/helpers → lib/gapic}/presenters/enum_presenter.rb +19 -14
  11. data/{templates/default/helpers → lib/gapic}/presenters/enum_value_presenter.rb +19 -12
  12. data/lib/gapic/presenters/field_presenter.rb +154 -0
  13. data/lib/gapic/presenters/file_presenter.rb +59 -0
  14. data/lib/gapic/presenters/gem_presenter.rb +176 -0
  15. data/lib/gapic/presenters/message_presenter.rb +73 -0
  16. data/lib/gapic/presenters/method_presenter.rb +307 -0
  17. data/lib/gapic/presenters/package_presenter.rb +80 -0
  18. data/lib/gapic/presenters/resource_presenter.rb +99 -0
  19. data/lib/gapic/presenters/sample_presenter.rb +84 -0
  20. data/lib/gapic/presenters/service_presenter.rb +306 -0
  21. data/lib/gapic/resource_lookup.rb +23 -38
  22. data/lib/gapic/schema/api.rb +70 -0
  23. data/lib/gapic/schema/loader.rb +9 -2
  24. data/lib/gapic/schema/wrappers.rb +134 -24
  25. data/templates/default/gem/entrypoint.erb +8 -0
  26. data/templates/default/gem/gemspec.erb +2 -2
  27. data/templates/default/gem/readme.erb +17 -3
  28. data/templates/default/gem/rubocop.erb +13 -41
  29. data/templates/default/helpers/filepath_helper.rb +2 -21
  30. data/templates/default/helpers/namespace_helper.rb +2 -27
  31. data/templates/default/layouts/_ruby.erb +1 -3
  32. data/templates/default/lib/_package.erb +17 -0
  33. data/templates/default/lib/_service.erb +32 -0
  34. data/templates/default/package.erb +5 -5
  35. data/templates/default/service.erb +5 -7
  36. data/templates/default/service/_helpers.erb +3 -0
  37. data/templates/default/service/client/_client.erb +7 -17
  38. data/templates/default/service/client/_operations.erb +0 -4
  39. data/templates/default/service/client/_paths.erb +1 -0
  40. data/templates/default/service/client/method/def/_options_defaults.erb +1 -1
  41. data/templates/default/service/client/method/def/_response_normal.erb +1 -1
  42. data/templates/default/service/client/method/docs/_request_normal.erb +10 -5
  43. data/templates/default/service/client/method/docs/_request_streaming.erb +1 -1
  44. metadata +20 -15
  45. data/templates/default/helpers/presenter_helper.rb +0 -24
  46. data/templates/default/helpers/presenters/field_presenter.rb +0 -146
  47. data/templates/default/helpers/presenters/file_presenter.rb +0 -53
  48. data/templates/default/helpers/presenters/gem_presenter.rb +0 -140
  49. data/templates/default/helpers/presenters/message_presenter.rb +0 -66
  50. data/templates/default/helpers/presenters/method_presenter.rb +0 -293
  51. data/templates/default/helpers/presenters/package_presenter.rb +0 -65
  52. data/templates/default/helpers/presenters/resource_presenter.rb +0 -92
  53. data/templates/default/helpers/presenters/sample_presenter.rb +0 -74
  54. data/templates/default/helpers/presenters/service_presenter.rb +0 -276
  55. data/templates/default/service/client/_helpers.erb +0 -9
@@ -51,6 +51,15 @@ module Gapic
51
51
  loader.load_file fd, request.file_to_generate.include?(fd.name)
52
52
  end
53
53
  @files.each { |f| f.parent = self }
54
+ @resource_types = analyze_resources
55
+ end
56
+
57
+ def containing_api
58
+ self
59
+ end
60
+
61
+ def containing_file
62
+ nil
54
63
  end
55
64
 
56
65
  def lookup address
@@ -200,6 +209,22 @@ module Gapic
200
209
  end
201
210
  end
202
211
 
212
+ # Whether the generate_path_helpers_output parameter was given in the configuration
213
+ def generate_path_helpers_output_defined?
214
+ configuration.key? :generate_path_helpers_output
215
+ end
216
+
217
+ # Sets the generate_path_helpers_output parameter in the configuration
218
+ def generate_path_helpers_output= value
219
+ configuration[:generate_path_helpers_output] = value
220
+ end
221
+
222
+ # Whether to generate path helpers for output as well as input messages
223
+ def generate_path_helpers_output?
224
+ # if not set in configuration, false by default
225
+ configuration[:generate_path_helpers_output] ||= false
226
+ end
227
+
203
228
  # Raw parsed json of the combined grpc service config files if provided
204
229
  # or an empty hash if no config was provided
205
230
  def grpc_service_config_raw
@@ -219,8 +244,53 @@ module Gapic
219
244
  end
220
245
  end
221
246
 
247
+ # Get a resource given its type string
248
+ def lookup_resource_type resource_type
249
+ @resource_types[resource_type]
250
+ end
251
+
222
252
  private
223
253
 
254
+ # Does a pre-analysis of all resources defined in the job. This has
255
+ # two effects:
256
+ # * Side effect: each resource has its parent_resources field set.
257
+ # * A mapping from resource type to resource wrapper is returned.
258
+ def analyze_resources
259
+ # In order to set parent_resources, we first populate a mapping from
260
+ # parsed pattern to resource mapping (in the patterns variable). This
261
+ # is done in one pass along with populating the resource type mapping.
262
+ # Then, we go through all resources again, get its expected parent
263
+ # patterns, and anything that shows up in the patterns mapping is taken
264
+ # to be a parent.
265
+ types = {}
266
+ patterns = {}
267
+ @files.each do |file|
268
+ file.resources.each { |resource| populate_resource_lookups resource, types, patterns }
269
+ file.messages.each { |message| populate_message_resource_lookups message, types, patterns }
270
+ end
271
+ types.each do |_type, resource|
272
+ parents = resource.parsed_parent_patterns
273
+ .map { |pat| patterns[pat] }
274
+ .compact.uniq
275
+ resource.parent_resources.replace parents
276
+ end
277
+ types
278
+ end
279
+
280
+ def populate_resource_lookups resource, types, patterns
281
+ types[resource.type] = resource
282
+ resource.parsed_patterns.each do |pat|
283
+ patterns[pat] = resource
284
+ end
285
+ end
286
+
287
+ def populate_message_resource_lookups message, types, patterns
288
+ populate_resource_lookups message.resource, types, patterns if message.resource
289
+ message.nested_messages.each do |nested|
290
+ populate_message_resource_lookups nested, types, patterns
291
+ end
292
+ end
293
+
224
294
  def parse_parameter str
225
295
  str.scan(/\\.|,|=|[^\\,=]+/)
226
296
  .each_with_object([[String.new]]) do |tok, arr|
@@ -64,9 +64,13 @@ module Gapic
64
64
  load_service registry, s, address, docs, [6, i]
65
65
  end
66
66
 
67
+ # Load top-level resources
68
+ resource_descriptors = file_descriptor.options[:".google.api.resource_definition"] if file_descriptor.options
69
+ resources = Array(resource_descriptors).map { |descriptor| Resource.new descriptor }
70
+
67
71
  # Construct and return the file.
68
72
  File.new file_descriptor, address, docs[path], messages, enums,
69
- services, file_to_generate, registry
73
+ services, resources, file_to_generate, registry
70
74
  end
71
75
 
72
76
  # Updates the fields of a message and it's nested messages.
@@ -158,9 +162,12 @@ module Gapic
158
162
  load_field registry, e, address, docs, path + [6, i]
159
163
  end
160
164
 
165
+ resource_descriptor = descriptor.options[:".google.api.resource"] if descriptor.options
166
+ resource = resource_descriptor ? Resource.new(resource_descriptor) : nil
167
+
161
168
  # Construct, cache, and return.
162
169
  msg = Message.new(descriptor, address, docs[path], fields, extensions,
163
- nested_messages, nested_enums)
170
+ resource, nested_messages, nested_enums)
164
171
  @prior_messages << msg
165
172
  add_to_registry registry, address, msg
166
173
  end
@@ -95,14 +95,33 @@ module Gapic
95
95
  @docs = docs
96
96
  end
97
97
 
98
+ # Returns the "root" of this schema.
99
+ # @return [Gapic::Schema::Api]
100
+ def containing_api
101
+ parent&.containing_api
102
+ end
103
+
104
+ # Returns the file containing this proto entity
105
+ # @return [Gapic::Schema::File]
106
+ def containing_file
107
+ parent&.containing_file
108
+ end
109
+
110
+ ##
98
111
  # Gets the cleaned up leading comments documentation
99
- def docs_leading_comments
112
+ #
113
+ # @param disable_xrefs [Boolean] (default is `false`) Disable linking to
114
+ # cross-references, and render them simply as text. This can be used if
115
+ # it is known that the targets are not present in the current library.
116
+ # @return [String]
117
+ #
118
+ def docs_leading_comments disable_xrefs: false
100
119
  return nil if @docs.nil?
101
120
  return nil if @docs.leading_comments.empty?
102
121
 
103
122
  lines = @docs.leading_comments.each_line.to_a
104
123
  lines.map! { |line| line.start_with?(" ") ? line[1..-1] : line }
105
- lines = FormattingUtils.escape_braces lines
124
+ lines = FormattingUtils.format_doc_lines containing_api, lines, disable_xrefs: disable_xrefs
106
125
  lines.join
107
126
  end
108
127
 
@@ -338,16 +357,19 @@ module Gapic
338
357
  # Wrapper for a protobuf file.
339
358
  #
340
359
  # @!attribute [r] messages
341
- # @ return [Enumerable<Message>] The top level messages contained in
360
+ # @return [Enumerable<Message>] The top level messages contained in
342
361
  # this file.
343
362
  # @!attribute [r] enums
344
- # @ return [Enumerable<Enum>] The top level enums contained in this
363
+ # @return [Enumerable<Enum>] The top level enums contained in this
345
364
  # file.
346
365
  # @!attribute [r] services
347
- # @ return [Enumerable<Service>] The services contained in this file.
366
+ # @return [Enumerable<Service>] The services contained in this file.
367
+ # @!attribute [r] resources
368
+ # @return [Enumerable<Resource>] The top level resources contained in
369
+ # this file.
348
370
  class File < Proto
349
371
  extend Forwardable
350
- attr_reader :messages, :enums, :services, :registry
372
+ attr_reader :messages, :enums, :services, :resources, :registry
351
373
 
352
374
  # Initializes a message object.
353
375
  # @param descriptor [Google::Protobuf::DescriptorProto] the protobuf
@@ -360,20 +382,27 @@ module Gapic
360
382
  # file.
361
383
  # @param enums [Enumerable<Enum>] The top level enums of this file.
362
384
  # @param services [Enumerable<Service>] The services of this file.
385
+ # @param resources [Enumerable<Resource>] The resources from this file.
363
386
  # @param generate [Boolean] Whether this file should be generated.
364
387
  def initialize descriptor, address, docs, messages, enums, services,
365
- generate, registry
388
+ resources, generate, registry
366
389
  super descriptor, address, docs
367
390
  @messages = messages || []
368
391
  @enums = enums || []
369
392
  @services = services || []
393
+ @resources = resources || []
370
394
  @generate = generate
371
395
  @registry = registry
372
396
 
373
397
  # Apply parent
374
398
  @messages.each { |m| m.parent = self }
375
- @enums.each { |m| m.parent = self }
399
+ @enums.each { |m| m.parent = self }
376
400
  @services.each { |m| m.parent = self }
401
+ @resources.each { |m| m.parent = self }
402
+ end
403
+
404
+ def containing_file
405
+ self
377
406
  end
378
407
 
379
408
  def lookup address
@@ -390,13 +419,6 @@ module Gapic
390
419
  options[:ruby_package] if options
391
420
  end
392
421
 
393
- # @return [Array<Google::Api::ResourceDescriptor>] A representation of the resource.
394
- # This is generally intended to be attached to the "name" field.
395
- # See `google/api/resource.proto`.
396
- def resources
397
- options[:".google.api.resource_definition"] if options
398
- end
399
-
400
422
  # @!method name
401
423
  # @return [String] file name, relative to root of source tree.
402
424
  # @!method package
@@ -488,6 +510,8 @@ module Gapic
488
510
  # @ return [Enumerable<Field>] The fields of a message.
489
511
  # @!attribute [r] extensions
490
512
  # @ return [Enumerable<Field>] The extensions of a message.
513
+ # @!attribute [r] resource
514
+ # @ return [Resource,nil] A representation of the resource.
491
515
  # @!attribute [r] nested_messages
492
516
  # @ return [Enumerable<Message>] The nested message declarations of a
493
517
  # message.
@@ -495,7 +519,7 @@ module Gapic
495
519
  # @ return [Enumerable<Enum>] The nested enum declarations of a message.
496
520
  class Message < Proto
497
521
  extend Forwardable
498
- attr_reader :fields, :extensions, :nested_messages, :nested_enums
522
+ attr_reader :fields, :extensions, :resource, :nested_messages, :nested_enums
499
523
 
500
524
  # Initializes a message object.
501
525
  # @param descriptor [Google::Protobuf::DescriptorProto] the protobuf
@@ -506,15 +530,17 @@ module Gapic
506
530
  # of the proto. See #docs for more info.
507
531
  # @param fields [Enumerable<Field>] The fields of this message.
508
532
  # @param extensions [Enumerable<Field>] The extensions of this message.
533
+ # @param resource [Resource,nil] The resource of this message, or nil if none.
509
534
  # @param nested_messages [Enumerable<Message>] The nested message
510
535
  # declarations of this message.
511
536
  # @param nested_enums [Enumerable<Enum>] The nested enum declarations
512
537
  # of this message.
513
- def initialize descriptor, address, docs, fields, extensions,
538
+ def initialize descriptor, address, docs, fields, extensions, resource,
514
539
  nested_messages, nested_enums
515
540
  super descriptor, address, docs
516
541
  @fields = fields || []
517
542
  @extensions = extensions || []
543
+ @resource = resource
518
544
  @nested_messages = nested_messages || []
519
545
  @nested_enums = nested_enums || []
520
546
 
@@ -522,13 +548,7 @@ module Gapic
522
548
  @extensions.each { |x| x.parent = self }
523
549
  @nested_messages.each { |m| m.parent = self }
524
550
  @nested_enums.each { |e| e.parent = self }
525
- end
526
-
527
- # @return [Google::Api::ResourceDescriptor] A representation of the resource.
528
- # This is generally intended to be attached to the "name" field.
529
- # See `google/api/resource.proto`.
530
- def resource
531
- options[:".google.api.resource"] if options
551
+ @resource.parent = self if @resource
532
552
  end
533
553
 
534
554
  # @return [Boolean] whether this type is a map entry
@@ -713,5 +733,95 @@ module Gapic
713
733
  :options
714
734
  )
715
735
  end
736
+
737
+ # Wrapper for a protobuf Resource.
738
+ #
739
+ # Unlike most wrappers, this does not subclass the {Proto} wrapper because
740
+ # it does not use the fields exposed by that wrapper (`address`, `docs`,
741
+ # etc.) This is here principally to augment the resource definition with
742
+ # information about resource parent-child relationships.
743
+ #
744
+ # Resource parentage is defined implicitly by path patterns. The algorithm
745
+ # is as follows:
746
+ # * If the final segment of a pattern is an ID segment (i.e. `*` or some
747
+ # `{name}`) then remove it and the previous segment (which we assume to
748
+ # be the corresponding collection identifier, as described in AIP-122.)
749
+ # The resulting pattern is what we expect a parent to have.
750
+ # * If the final segment is static, then assume the pattern represents a
751
+ # singleton resource (AIP-156) and remove only that one segment. The
752
+ # resulting pattern is what we expect a parent to have.
753
+ #
754
+ # The {Resource#parsed_parent_patterns} method returns the set of patterns
755
+ # we expect of parents. It is then possible to search for resources with
756
+ # those patterns to determine what the parents are.
757
+ #
758
+ # @!attribute [rw] parent
759
+ # @return [Gapic::Schema::File,Gapic::Schema::Message] The parent object.
760
+ # @!attribute [r] descriptor
761
+ # @return [Array<Gapic::Schema::ResourceDescriptor>] The resource
762
+ # descriptor.
763
+ # @!attribute [r] parsed_patterns
764
+ # @return [Array<Array<String>>] The normalized, segmented forms of the
765
+ # patterns. Normalized means all ID segments are replaced by asterisks
766
+ # to remove non-structural differences due to different names being
767
+ # used. Segmented means simply split on slashes.
768
+ # For example, if a pattern is `"projects/{project}""`, the
769
+ # corresponding parsed pattern would be `["projects", "*"]`.
770
+ # @!attribute [r] parent_resources
771
+ # @return [Array<Gapic::Schema::Resource>] Parent resources
772
+ class Resource
773
+ extend Forwardable
774
+ attr_reader :descriptor, :parsed_patterns, :parent_resources
775
+ attr_accessor :parent
776
+
777
+ # Initializes a resource object.
778
+ # @param descriptor [Google::Protobuf::ResourceDescriptor] the protobuf
779
+ # representation of this resource.
780
+ def initialize descriptor
781
+ @parent = nil
782
+ @descriptor = descriptor
783
+ @parsed_patterns = descriptor.pattern.map do |pattern|
784
+ pattern.split("/").map do |segment|
785
+ segment =~ %r{\{[^/\}]+(=[^\}]+)?\}} ? "*" : segment
786
+ end.freeze
787
+ end.freeze
788
+ @parent_resources = []
789
+ end
790
+
791
+ # Returns the "root" of this schema.
792
+ # @return [Gapic::Schema::Api]
793
+ def containing_api
794
+ parent&.containing_api
795
+ end
796
+
797
+ # Returns the file containing this proto entity
798
+ # @return [Gapic::Schema::File]
799
+ def containing_file
800
+ parent&.containing_file
801
+ end
802
+
803
+ # Returns parsed patterns for the expected parents.
804
+ # @return [Array<Array<String>>]
805
+ def parsed_parent_patterns
806
+ @parsed_patterns.map do |pat|
807
+ parent = pat.last =~ /^\*\*?$/ ? pat[0...-2] : pat[0...-1]
808
+ parent.empty? ? nil : parent
809
+ end.compact.uniq
810
+ end
811
+
812
+ # @!method type
813
+ # @return [String] the resource type string.
814
+ # @!method pattern
815
+ # @return [Array<String>] the set of patterns.
816
+ # @!method name_field
817
+ # @return [String] the field on the resource that designates the
818
+ # resource name field. If omitted, this is assumed to be "name".
819
+ def_delegators(
820
+ :descriptor,
821
+ :type,
822
+ :pattern,
823
+ :name_field
824
+ )
825
+ end
716
826
  end
717
827
  end
@@ -0,0 +1,8 @@
1
+ <%- assert_locals gem -%>
2
+ <%= render partial: "shared/header" -%>
3
+
4
+ # This gem does not autoload during Bundler.require. To load this gem,
5
+ # issue explicit require statements for the packages desired, e.g.:
6
+ <%- gem.packages.each do |package| -%>
7
+ # require "<%= package.package_require %>"
8
+ <%- end -%>
@@ -23,9 +23,9 @@ Gem::Specification.new do |gem|
23
23
 
24
24
  gem.required_ruby_version = ">= 2.4"
25
25
 
26
- gem.add_dependency "gapic-common", "~> 0.1.0"
26
+ gem.add_dependency "gapic-common", "~> 0.2"
27
27
  <%- if gem.iam_dependency? -%>
28
- gem.add_dependency "grpc-google-iam-v1", "~> 0.6.9"
28
+ gem.add_dependency "grpc-google-iam-v1", ">= 0.6.10", "< 2.0"
29
29
  <%- end -%>
30
30
 
31
31
  gem.add_development_dependency "google-style", "~> 1.24.0"
@@ -1,9 +1,9 @@
1
- # <%= gem.title %>
2
-
3
- <%= gem.description %>
1
+ # Ruby Client for the <%= gem.title %> API
4
2
 
5
3
  <%= gem.summary %>
6
4
 
5
+ <%= gem.description %>
6
+
7
7
  <%= gem.homepage %>
8
8
 
9
9
  ## Installation
@@ -12,6 +12,20 @@
12
12
  $ gem install <%= gem.name %>
13
13
  ```
14
14
 
15
+ ## Quick Start
16
+
17
+ ```ruby
18
+ require "<%= gem.entrypoint_require %>"
19
+ <%- service = gem.packages.first&.services.first -%>
20
+ <%- method = service&.methods.first -%>
21
+ <%- if service && method -%>
22
+
23
+ client = <%= service.create_client_call %>
24
+ request = my_create_request
25
+ response = client.<%= method.name %> request
26
+ <%- end -%>
27
+ ```
28
+
15
29
  ## Supported Ruby Versions
16
30
 
17
31
  This library is supported on Ruby 2.4+.
@@ -9,51 +9,23 @@ AllCops:
9
9
  - "test/**/*"
10
10
 
11
11
  Metrics/AbcSize:
12
- Exclude:
13
- <%- gem.packages.each do |package| -%>
14
- <%- package.services.each do |service| -%>
15
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
16
- <%- end -%>
17
- <%- end -%>
12
+ Enabled: false
18
13
  Metrics/ClassLength:
19
- Exclude:
20
- <%- gem.packages.each do |package| -%>
21
- <%- package.services.each do |service| -%>
22
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
23
- <%- end -%>
24
- <%- end -%>
14
+ Enabled: false
25
15
  Metrics/CyclomaticComplexity:
26
- Exclude:
27
- <%- gem.packages.each do |package| -%>
28
- <%- package.services.each do |service| -%>
29
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
30
- <%- end -%>
31
- <%- end -%>
16
+ Enabled: false
32
17
  Metrics/LineLength:
33
- Exclude:
34
- <%- gem.packages.each do |package| -%>
35
- <%- package.services.each do |service| -%>
36
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
37
- <%- end -%>
38
- <%- end -%>
18
+ Enabled: false
39
19
  Metrics/MethodLength:
40
- Exclude:
41
- <%- gem.packages.each do |package| -%>
42
- <%- package.services.each do |service| -%>
43
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
44
- <%- end -%>
45
- <%- end -%>
20
+ Enabled: false
46
21
  Metrics/PerceivedComplexity:
22
+ Enabled: false
23
+ Naming/FileName:
47
24
  Exclude:
48
- <%- gem.packages.each do |package| -%>
49
- <%- package.services.each do |service| -%>
50
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
51
- <%- end -%>
52
- <%- end -%>
25
+ - "lib/<%= gem.name %>.rb"
53
26
  Style/CaseEquality:
54
- Exclude:
55
- <%- gem.packages.each do |package| -%>
56
- <%- package.services.each do |service| -%>
57
- - "lib/<%= service.client_file_path.sub "client.rb", "*.rb" %>"
58
- <%- end -%>
59
- <%- end -%>
27
+ Enabled: false
28
+ Style/IfUnlessModifier:
29
+ Enabled: false
30
+ Style/ModuleFunction:
31
+ Enabled: false