-
Notifications
You must be signed in to change notification settings - Fork 603
Multi-Language Support for Spec-Insert -> Python #10187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
d428c57
46b0106
b545d6a
5f75fb5
2ac865f
32c1278
d83404b
f26c32d
9f43033
9df6657
dd4ebbe
1c99540
da48f26
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# frozen_string_literal: true | ||
|
||
require 'json' | ||
require_relative 'example_code_python' | ||
|
||
class ExampleCode < BaseMustacheRenderer | ||
self.template_file = "#{__dir__}/templates/example_code.mustache" | ||
|
||
def initialize(action, args) | ||
super(action, args) | ||
end | ||
|
||
def rest_lines | ||
@args.rest.raw_lines | ||
end | ||
|
||
def rest_code | ||
base = rest_lines.join("\n") | ||
body = @args.rest.body | ||
if body | ||
body.is_a?(String) ? base + "\n" + body : base + "\n" + JSON.pretty_generate(body) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the condition here necessary? Can you put |
||
else | ||
base | ||
end | ||
end | ||
|
||
def python_code | ||
ExampleCodePython.new(@action, @args).render | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
require 'json' | ||
|
||
class ExampleCodePython < BaseMustacheRenderer | ||
self.template_file = "#{__dir__}/templates/example_code.python.mustache" | ||
|
||
def initialize(action, args) | ||
super(action, args) | ||
end | ||
|
||
def call_code | ||
return "# Invalid action" unless @action&.full_name | ||
client_setup = <<~PYTHON | ||
from opensearchpy import OpenSearch | ||
|
||
host = 'localhost' | ||
port = 9200 | ||
auth = ('admin', 'admin') # For testing only. Don't store credentials in code. | ||
ca_certs_path = '/full/path/to/root-ca.pem' # Provide a CA bundle if you use intermediate CAs with your root CA. | ||
|
||
# Create the client with SSL/TLS enabled, but hostname verification disabled. | ||
client = OpenSearch( | ||
hosts = [{'host': host, 'port': port}], | ||
http_compress = True, # enables gzip compression for request bodies | ||
http_auth = auth, | ||
use_ssl = True, | ||
verify_certs = True, | ||
ssl_assert_hostname = False, | ||
ssl_show_warn = False, | ||
ca_certs = ca_certs_path | ||
) | ||
|
||
PYTHON | ||
|
||
parts = @action.full_name.split('.') | ||
client_call = "client" | ||
|
||
if parts.length == 2 | ||
namespace, method = parts | ||
client_call += ".#{namespace}.#{method}" | ||
else | ||
namespace = parts[0] | ||
client_call += ".#{namespace}" | ||
end | ||
|
||
args = [] | ||
|
||
rest = @args.rest | ||
http_verb = rest.verb | ||
full_path = [rest.path, rest.query&.map { |k,v| "#{k}=#{v}" }.join('&')].compact.join('?') | ||
path_part, query_string = full_path.to_s.split('?', 2) | ||
path_values = path_part.split('/').reject(&:empty?) | ||
|
||
spec_path = match_spec_path(full_path) | ||
spec_parts = spec_path.split('/').reject(&:empty?) | ||
|
||
param_mapping = {} | ||
spec_parts.each_with_index do |part, i| | ||
if part =~ /\{(.+?)\}/ && path_values[i] | ||
param_mapping[$1] = path_values[i] | ||
end | ||
end | ||
|
||
@action.path_parameters.each do |param| | ||
if param_mapping.key?(param.name) | ||
args << "#{param.name} = \"#{param_mapping[param.name]}\"" | ||
end | ||
end | ||
|
||
if query_string | ||
query_pairs = query_string.split('&').map { |s| s.split('=', 2) } | ||
query_hash = query_pairs.map do |k, v| | ||
"\"#{k}\": #{v ? "\"#{v}\"" : "\"false\""}" | ||
end.join(', ') | ||
args << "params = { #{query_hash} }" unless query_hash.empty? | ||
end | ||
|
||
body = rest.body | ||
if expects_body?(http_verb) | ||
if body | ||
begin | ||
parsed = JSON.parse(@args.raw['body']) | ||
pretty = JSON.pretty_generate(parsed).gsub(/^/, ' ') | ||
args << "body = #{pretty}" | ||
rescue JSON::ParserError | ||
args << "body = #{JSON.dump(@args.raw['body'])}" | ||
end | ||
else | ||
args << 'body = { "Insert body here" }' | ||
end | ||
end | ||
|
||
python_setup = if args.empty? | ||
"response = #{client_call}()" | ||
else | ||
final_args = args.map { |line| " #{line}" }.join(",\n") | ||
<<~PYTHON | ||
|
||
response = #{client_call}( | ||
#{final_args} | ||
) | ||
PYTHON | ||
end | ||
if @args.raw['include_client_setup'] | ||
client_setup + python_setup | ||
else | ||
python_setup | ||
end | ||
end | ||
|
||
private | ||
|
||
def expects_body?(verb) | ||
verb = verb.downcase | ||
@action.operations.any? do |op| | ||
op.http_verb.to_s.downcase == verb && | ||
op.spec&.requestBody && | ||
op.spec.requestBody.respond_to?(:content) | ||
end | ||
end | ||
|
||
def match_spec_path(full_path) | ||
request_path = full_path.split('?').first | ||
request_segments = request_path.split('/').reject(&:empty?) | ||
|
||
best = '' | ||
best_score = -1 | ||
|
||
@action.urls.each do |spec_path| | ||
spec_segments = spec_path.split('/').reject(&:empty?) | ||
next unless spec_segments.size == request_segments.size | ||
|
||
score = 0 | ||
spec_segments.each_with_index do |seg, i| | ||
if seg.start_with?('{') | ||
score += 1 | ||
elsif seg == request_segments[i] | ||
score += 2 | ||
else | ||
score = -1 | ||
break | ||
end | ||
end | ||
|
||
if score > best_score | ||
best = spec_path | ||
best_score = score | ||
end | ||
end | ||
|
||
best | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{% capture step1_rest %} | ||
{{{rest_code}}} | ||
{% endcapture %} | ||
|
||
{% capture step1_python %} | ||
{{{python_code}}} | ||
{% endcapture %} | ||
|
||
{% include code-block.html | ||
rest=step1_rest | ||
python=step1_python %} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{{! example_code.python.mustache }} | ||
|
||
{{{call_code}}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The template logic in example_code_python.rb should be put into the mustache template file to help better visualize what the end result would look like. Else we get a 2-line template like this which is not useful. Not a blocker. You should resolve this in a follow up. |
Uh oh!
There was an error while loading. Please reload this page.