Skip to content

scripts: check in library generation script #643

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 42 additions & 13 deletions scripts/build_twilio_library.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import argparse
import glob
import json
import os
import re
import shlex
import shutil
import subprocess
from pathlib import Path
from typing import List, Tuple


from clean_unused_imports import remove_unused_imports, remove_duplicate_imports
from process_orgs_api import preprocess_orgs_spec

Expand Down Expand Up @@ -40,6 +44,10 @@ def build(openapi_spec_path: str, output_path: str, language: str) -> None:


def generate(spec_folder: str, spec_files: List[str], output_path: str, language: str) -> None:
"""
spec_folder: typically "examples/spec/json"
config_path: typically "tmp"
"""
sub_dir = subdirectories.get(language, 'rest')
parent_dir = Path(__file__).parent.parent
output_path = os.path.join(output_path, sub_dir)
Expand All @@ -56,7 +64,9 @@ def generate(spec_folder: str, spec_files: List[str], output_path: str, language
generate_domain_for_language(input_path_versionless, config_path, spec_dir, output_path, language, parent_dir)
if language in generateForLanguages.get(spec_file):
generate_domain_for_language(spec_file, config_path, spec_folder, output_path, language, parent_dir)
else: generate_domain_for_language(spec_file, config_path, spec_folder, output_path, language, parent_dir)
else:
generate_domain_for_language(spec_file, config_path, spec_folder, output_path, language, parent_dir)

if spec_files[0] in generateForLanguages:
if language in generateForLanguages.get(spec_files[0]) or language in dynamic_languages:
print(f'Generating {output_path} from {spec_folder}')
Expand All @@ -74,6 +84,7 @@ def generate(spec_folder: str, spec_files: List[str], output_path: str, language


def generate_domain_for_language(spec_file: str, config_path: str, spec_folder: str, output_path: str, language: str, parent_dir: str) -> None:
print("generate domain for language: {}, config: {}, spec folder: {}, file: {}".format(language, config_path, spec_folder, spec_file))
full_path = os.path.join(spec_folder, spec_file)
full_config_path = os.path.join(config_path, spec_file)
config = {
Expand All @@ -86,20 +97,38 @@ def generate_domain_for_language(spec_file: str, config_path: str, spec_folder:
}
# print(config)
with open(full_config_path, 'w') as f:
f.write(json.dumps(config))

f.write(json.dumps(config) + "\n")

def run_openapi_generator(parent_dir: Path, language: str) -> None:
properties = '-DapiTests=false'
if language in {'node', 'python'}:
properties += ' -DskipFormModel=false'

command = f'cd {parent_dir} && java {properties} ' \
f'-cp target/twilio-openapi-generator.jar ' \
f'org.openapitools.codegen.OpenAPIGenerator batch {CONFIG_FOLDER}/{language}/*'

if os.system(command + '> /dev/null') != 0: # Suppress stdout
raise RuntimeError()
properties = "-DapiTests=false"
if language in {"node", "python"}:
properties += " -DskipFormModel=false"

paths = glob.glob(os.path.join(CONFIG_FOLDER, language, "*"))

command = [
"java",
*properties.split(), # Splits e.g. "-DapiTests=false -DskipFormModel=false" into separate arguments
"-cp",
"target/twilio-openapi-generator.jar",
"org.openapitools.codegen.OpenAPIGenerator",
"batch",
*paths,
]

printable_cmd = " ".join(shlex.quote(arg) for arg in command)
print(f"Running command: {printable_cmd}")

try:
subprocess.run(
command,
cwd=parent_dir, # Change working directory to parent_dir
check=True, # Raise CalledProcessError on non-zero exit
stdout=subprocess.DEVNULL, # Suppress standard output
)
except subprocess.CalledProcessError as exc:
# Wrap the original exception for more informative error handling
raise RuntimeError("OpenAPI generation failed.") from exc


def get_domain_info(oai_spec_location: str, domain: str, is_file: bool = False) -> Tuple[str, str, str]:
Expand Down
Empty file.
101 changes: 101 additions & 0 deletions scripts/generate_libraries/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/env python3

# an example way to run this script would be:
#
# cd /path/to/twilio-oai-generator
# python -m scripts.generate_libraries.main --language go --input=../twilio-oai/spec/json --base=..
#
# and have twilio-oai and twilio-go as sibling directories to twilio-oai-generator

import argparse
import glob
import os
from .. import build_twilio_library as build_library


def parse_args():
parser = argparse.ArgumentParser(
description="Generate files for Twilio library in different languages."
)
parser.add_argument(
"--language",
choices=["csharp", "java", "node", "php", "go", "python", "ruby", "terraform"],
required=True,
help="Specify the target language for code generation."
)
parser.add_argument(
"--base",
default=".",
help="Base directory for code generation. Defaults to current directory."
)
parser.add_argument(
"--input",
default=None,
help="Path to the OpenAPI spec JSON files. If not specified, defaults to 'spec/json' inside the base directory."
)
return parser.parse_args()


def get_output_dir(base, language):
"""
Constructs the output directory for each language based on the given base path.
Update these paths as needed for your environment or repository layout.
"""
if language == "csharp":
return os.path.join(base, "twilio-csharp/src/Twilio")
elif language == "java":
return os.path.join(base, "twilio-java/src/main/java/com/twilio")
elif language == "node":
return os.path.join(base, "twilio-node/src")
elif language == "php":
return os.path.join(base, "twilio-php/src/Twilio")
elif language == "go":
return os.path.join(base, "twilio-go")
elif language == "python":
return os.path.join(base, "twilio-python/twilio")
elif language == "ruby":
return os.path.join(base, "twilio-ruby/lib/twilio-ruby")
elif language == "terraform":
return os.path.join(base, "terraform-provider-twilio")
else:
return None


def generate_files(input_dir, output_dir, language):
# If needed, you can iterate over the input spec files here using glob:
# for filepath in glob.glob(os.path.join(input_dir, "*.json")):
# print(filepath)
build_library.build(input_dir, output_dir, language)


def main():
args = parse_args()

# Determine input directory
input_dir = args.input if args.input else os.path.join(args.base, "spec/json")

# Determine output directory for the chosen language
output_dir = get_output_dir(args.base, args.language)

if not output_dir:
print("Unsupported language or path couldn't be resolved.")
return

# Ensure the output directory exists
os.makedirs(output_dir, exist_ok=True)

# Run a make install (if needed for your environment)
os.system("make install")

# Generate files
generate_files(input_dir, output_dir, args.language)

# Optional language-specific post-processing
if args.language == "go":
os.chdir(output_dir)
os.system("go fmt ./...")
os.system("goimports -w .")


if __name__ == "__main__":
main()
Loading