1
1
# frozen_string_literal: true
2
2
3
3
require 'json'
4
+ require_relative 'example_code_python'
4
5
5
6
class ExampleCode < BaseMustacheRenderer
6
7
self . template_file = "#{ __dir__ } /templates/example_code.mustache"
@@ -9,217 +10,21 @@ def initialize(action, args)
9
10
super ( action , args )
10
11
end
11
12
12
- # Resolves the correct OpenSearch client method call
13
- def client_method_call
14
- segments = @action . full_name . to_s . split ( '.' )
15
- return "client" if segments . empty?
16
-
17
- if segments . size == 1
18
- "client.#{ segments . first } "
19
- else
20
- "client.#{ se gments . first } .#{ segments [ 1 ] } "
21
- end
22
- end
23
-
24
13
def rest_lines
25
- @args . raw [ ' rest' ] &. split ( " \n " ) &. map ( & :strip ) || [ ]
14
+ @args . rest . raw_lines
26
15
end
27
16
28
17
def rest_code
29
- rest_lines . join ( "\n " )
30
- end
31
-
32
- # Uses the declared HTTP method in the OpenAPI spec
33
- def http_method
34
- @action . http_verbs . first &.upcase || "GET"
35
- end
36
-
37
- # Converts OpenAPI-style path (/index/{id}) into Ruby-style interpolation (/index/#{id})
38
- def path_only
39
- url = @action . urls . first
40
- return '' unless url
41
- url . gsub ( /\{ (\w +)\} / , '#{\1}' )
42
- end
43
- def javascript_code
44
- "JavaScript example code not yet implemented"
45
- end
46
- # Assembles a query string from the declared query parameters
47
- def query_string
48
- return '' if @action . query_parameters . empty?
49
- @action . query_parameters . map { |param | "#{ param . name } =example" } . join ( '&' )
50
- end
51
-
52
- # Combines path and query string for display
53
- def path_with_query
54
- qs = query_string
55
- qs . empty? ? path_only : "#{ path_only } ?#{ qs } "
56
- end
57
-
58
- # Hash version of query params
59
- def query_params
60
- @action . query_parameters . to_h { |param | [ param . name , "example" ] }
61
- end
62
-
63
- # Parses the body from the REST example (only for preserving raw formatting)
64
- def body
65
- body_lines = rest_lines [ 1 ..]
66
- return nil if body_lines . empty?
67
- begin
68
- JSON . parse ( body_lines . join ( "\n " ) )
69
- rescue
70
- nil
71
- end
72
- end
73
-
74
- def action_expects_body? ( verb )
75
- verb = verb . downcase
76
- @action . operations . any? do |op |
77
- op . http_verb . to_s . downcase == verb &&
78
- op . spec &.requestBody &&
79
- op . spec . requestBody . respond_to? ( :content )
80
- end
81
- end
82
-
83
- def matching_spec_path
84
- return @matching_spec_path if defined? ( @matching_spec_path )
85
-
86
- # Extract raw request path from rest line
87
- raw_line = rest_lines . first . to_s
88
- _ , request_path = raw_line . split
89
- request_segments = request_path . split ( '?' ) . first . split ( '/' ) . reject ( &:empty? )
90
-
91
- # Choose the best matching spec URL
92
- best = nil
93
- best_score = -1
94
-
95
- @action . urls . each do |spec_path |
96
- spec_segments = spec_path . split ( '/' ) . reject ( &:empty? )
97
- next unless spec_segments . size == request_segments . size
98
-
99
- score = 0
100
- spec_segments . each_with_index do |seg , i |
101
- if seg . start_with? ( '{' )
102
- score += 1 # parameter match
103
- elsif seg == request_segments [ i ]
104
- score += 2 # exact match
105
- else
106
- score = -1
107
- break
108
- end
109
- end
110
-
111
- if score > best_score
112
- best = spec_path
113
- best_score = score
114
- end
18
+ base = rest_lines . join ( "\n " )
19
+ body = @args . rest . body
20
+ if body
21
+ body . is_a? ( String ) ? base + "\n " + body : base + "\n " + JSON . pretty_generate ( body )
22
+ else
23
+ base
115
24
end
116
-
117
- @matching_spec_path = best
118
25
end
119
26
120
- # Final Python code using action metadata
121
27
def python_code
122
- return "# Invalid action" unless @action &.full_name
123
-
124
- client_setup = <<~PYTHON
125
- from opensearchpy import OpenSearch
126
-
127
- host = 'localhost'
128
- port = 9200
129
- auth = ('admin', 'admin') # For testing only. Don't store credentials in code.
130
- ca_certs_path = '/full/path/to/root-ca.pem' # Provide a CA bundle if you use intermediate CAs with your root CA.
131
-
132
- # Create the client with SSL/TLS enabled, but hostname verification disabled.
133
- client = OpenSearch(
134
- hosts = [{'host': host, 'port': port}],
135
- http_compress = True, # enables gzip compression for request bodies
136
- http_auth = auth,
137
- use_ssl = True,
138
- verify_certs = True,
139
- ssl_assert_hostname = False,
140
- ssl_show_warn = False,
141
- ca_certs = ca_certs_path
142
- )
143
-
144
- PYTHON
145
-
146
- if @args . raw [ 'body' ] == '{"hello"}'
147
- puts "# This is a debug example"
148
- end
149
-
150
- namespace , method = @action . full_name . split ( '.' )
151
- client_call = "client"
152
- client_call += ".#{ namespace } " if namespace
153
- client_call += ".#{ method } "
154
-
155
- args = [ ]
156
-
157
- # Extract actual path and query from the first line of the REST input
158
- raw_line = rest_lines . first . to_s
159
- http_verb , full_path = raw_line . split
160
- path_part , query_string = full_path . to_s . split ( '?' , 2 )
161
-
162
- # Extract used path values from the path part
163
- path_values = path_part . split ( '/' ) . reject ( &:empty? )
164
-
165
- # Match spec path (e.g. /_cat/aliases/{name}) to determine which param this value belongs to
166
- spec_path = matching_spec_path . to_s
167
- spec_parts = spec_path . split ( '/' ) . reject ( &:empty? )
168
-
169
- param_mapping = { }
170
- spec_parts . each_with_index do |part , i |
171
- if part =~ /\{ (.+?)\} / && path_values [ i ]
172
- param_mapping [ $1] = path_values [ i ]
173
- end
174
- end
175
-
176
- # Add path parameters if they were present in the example
177
- @action . path_parameters . each do |param |
178
- if param_mapping . key? ( param . name )
179
- args << "#{ param . name } = \" #{ param_mapping [ param . name ] } \" "
180
- end
181
- end
182
-
183
- # Add query parameters from query string
184
- if query_string
185
- query_pairs = query_string . split ( '&' ) . map { |s | s . split ( '=' , 2 ) }
186
- query_hash = query_pairs . map do |k , v |
187
- "#{ k } : #{ v ? "\" #{ v } \" " : "True" } "
188
- end . join ( ', ' )
189
- args << "params = { #{ query_hash } }" unless query_hash . empty?
190
- end
191
-
192
- # Add body if spec allows it AND it's present in REST
193
- if action_expects_body? ( http_verb )
194
- if @args . raw [ 'body' ]
195
- begin
196
- parsed = JSON . parse ( @args . raw [ 'body' ] )
197
- pretty = JSON . pretty_generate ( parsed ) . gsub ( /^/ , ' ' )
198
- args << "body = #{ pretty } "
199
- rescue JSON ::ParserError
200
- args << "body = #{ JSON . dump ( @args . raw [ 'body' ] ) } "
201
- end
202
- else
203
- args << 'body = { "Insert body here" }'
204
- end
205
- end
206
-
207
- # Final result
208
- call_code = if args . empty?
209
- "response = #{ client_call } ()"
210
- else
211
- final_args = args . map { |line | " #{ line } " } . join ( ",\n " )
212
- <<~PYTHON
213
- response = #{ client_call } (
214
- #{ final_args }
215
- )
216
- PYTHON
217
- end
218
- # Prepend client if requested
219
- if @args . raw [ 'include_client_setup' ]
220
- client_setup + call_code
221
- else
222
- call_code
223
- end
28
+ ExampleCodePython . new ( @action , @args ) . render
224
29
end
225
- end
30
+ end
0 commit comments