11# frozen_string_literal: true 
22
33require  'json' 
4+ require_relative  'example_code_python' 
45
56class  ExampleCode  < BaseMustacheRenderer 
67  self . template_file  =  "#{ __dir__ }  
@@ -9,217 +10,21 @@ def initialize(action, args)
910    super ( action ,  args ) 
1011  end 
1112
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- 
2413  def  rest_lines 
25-     @args . raw [ ' rest' ] &. split ( " \n " ) &. map ( & :strip )  ||  [ ] 
14+     @args . rest . raw_lines 
2615  end 
2716
2817  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 }   } . 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 
11524    end 
116- 
117-     @matching_spec_path  =  best 
11825  end 
11926
120-   # Final Python code using action metadata 
12127  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 
22429  end 
225- end 
30+ end 
0 commit comments