def run(self): cmd_result = 0 versions = self.args.api_versions or self.config.spec_versions for version in versions: fs_path = write_full_spec(self.config, self.args.spec_dir, version, self.args.full_spec_file) if not self.validate_spec(fs_path): cmd_result = 1 return cmd_result
def test_write_full_spec_section_not_found(tmpdir): specdir = tmpdir.mkdir("spec") v1dir = specdir.mkdir("v1") header = str(v1dir.join("header.yaml")) nope = str(v1dir.join("nope.yaml")) with open(header, "w") as f: f.write("{}") with pytest.raises(SpecSectionNotFoundError) as e: write_full_spec( str(specdir), "v1", ["header.yaml", "nope.yaml"], str(v1dir.join("full.yaml")), ) assert (str( e.value ) == f"Spec section 'nope.yaml' not found for api version 'v1' ({nope})")
def run(self): fs_paths = {} versions = self.args.api_versions or self.config.spec_versions languages = self.args.languages or self.config.languages pull_repo = self.args.clone_repo # first, generate full spec for all major versions of the API for version in versions: fs_paths[version] = write_full_spec(self.config, self.args.spec_dir, version, self.args.full_spec_file) missing_templates = self.get_missing_templates(languages) if missing_templates and not self.args.builtin_templates: log.error( "Missing templates for %s; please run `apigentools templates` first", ", ".join(missing_templates)) return 1 # cache codegen version if self.get_codegen_version() is None: log.error("Failed to get codegen version, exiting") return 1 # now, for each language generate a client library for every major version that is explicitly # listed in its settings (meaning that we can have languages that don't support all major # API versions) for language in languages: language_config = self.config.get_language_config(language) # Clone the language target repo into the output directory if pull_repo: self.pull_repository(language_config) for version in language_config.spec_versions: log.info("Generation in %s, spec version %s", language, version) language_oapi_config_path = os.path.join( self.args.config_dir, LANGUAGE_OAPI_CONFIGS, "{lang}_{v}.json".format(lang=language, v=version)) with open(language_oapi_config_path) as lcp: language_oapi_config = json.load(lcp) version_output_dir = self.get_generated_lang_version_dir( language, version) generate_cmd = [ self.config.codegen_exec, "generate", "--http-user-agent", "{c}/{v}/{l}".format( c=self.config.user_agent_client_name, v=self.get_version_from_lang_oapi_config( language_oapi_config), l=language), "-g", language, "-c", language_oapi_config_path, "-i", fs_paths[version], "-o", version_output_dir, "--additional-properties", "apigentoolsStamp='{stamp}'".format( stamp=self.get_stamp()), ] if not self.args.builtin_templates: generate_cmd.extend( ["-t", os.path.join(self.args.template_dir, language)]) os.makedirs(version_output_dir, exist_ok=True) self.run_language_commands(language, "pre", version_output_dir) run_command(generate_cmd, additional_env=language_config.command_env) self.run_language_commands(language, "post", version_output_dir) self.render_downstream_templates( language, self.args.downstream_templates_dir, ) # Write the apigentools.info file once per language # after each nested folder has been created self.write_dot_apigentools_info(language) return 0
def run(self): info = collections.defaultdict(dict) fs_files = set() # first, generate full spec for all major versions of the API for language, version, fs_file in self.yield_lang_version_specfile(): info[language][version] = fs_file if fs_file in fs_files: log.info(f"Reuse {fs_file} for {language} and {version}") continue fs_files.add(fs_file) # Generate full spec file is needed write_full_spec( constants.SPEC_REPO_SPEC_DIR, version, self.config.get_language_config(language).spec_sections_for( version), fs_file, ) log.info(f"Generated {fs_file} for {language}/{version}") pull_repo = self.args.get("clone_repo") # now, for each language generate a client library for every major version that is explicitly # listed in its settings (meaning that we can have languages that don't support all major # API versions) for language, versions in info.items(): language_config = self.config.get_language_config(language) general_chevron_vars = language_config.chevron_vars_for() general_chevron_vars["stamp"] = self.get_stamp() # Clone the language target repo into the output directory if pull_repo: self.pull_repository(language_config, branch=self.args.get("branch")) if self.args.get("delete_generated_files"): self.remove_generated_files(language_config) for version, input_spec in versions.items(): if self.args.get("skip_templates"): log.info("Skipping templates processing for {}/{}".format( language, version)) else: tpl_cmd_args = copy.deepcopy(self.args) tpl_cmd_args["languages"] = [language] tpl_cmd_args["api_versions"] = [version] template_cmd = TemplatesCommand(self.config, tpl_cmd_args) retval = template_cmd.run() if retval != 0: return retval log.info("Generation in %s/%s", language, version) version_output_dir = language_config.generated_lang_version_dir_for( version) os.makedirs(version_output_dir, exist_ok=True) self.run_language_commands( language, version, version_output_dir, language_config.chevron_vars_for(version, input_spec), ) self.write_dot_apigentools_info(language_config, version) self.render_downstream_templates( language_config, language_config.chevron_vars_for()) return 0
def test_write_full_spec(tmpdir): s1 = { "components": { "schemas": { "MySchema": { "type": "object", }, }, }, "paths": { "/api/v1/foo": { "get": { "operationId": "getFoo", "summary": "get", }, }, }, } s2 = { "components": { "schemas": { "MyOtherSchema": { "type": "string", }, }, }, "paths": { "/api/v1/foo": { # add a new operation to the same path "post": { "operationId": "postFoo", "summary": "post", }, }, }, } header = { "servers": [{ "url": "http://base.url" }], } expected = { "components": { "callbacks": {}, "examples": {}, "headers": {}, "links": {}, "parameters": {}, "requestBodies": {}, "responses": {}, "schemas": { "MySchema": { "type": "object", }, "MyOtherSchema": { "type": "string", }, }, "securitySchemes": {}, }, "paths": { "/api/v1/foo": { "get": { "operationId": "getFoo", "summary": "get", }, "post": { "operationId": "postFoo", "summary": "post", }, }, }, "security": [], "servers": [{ "url": "http://base.url" }], "tags": [], } specdir = tmpdir.mkdir("spec") versiondir = specdir.mkdir("v1") p1 = os.path.join(str(versiondir), "s1.yaml") p2 = os.path.join(str(versiondir), "s2.yaml") header_file = os.path.join(str(versiondir), "header.yaml") with open(p1, "w") as f: yaml.dump(s1, f) with open(p2, "w") as f: yaml.dump(s2, f) with open(header_file, "w") as f: yaml.dump(header, f) written = write_full_spec( str(specdir), "v1", ["header.yaml", "s1.yaml", "s2.yaml"], os.path.join(str(versiondir), "full.yaml"), ) with open(written, "r") as f: assert yaml.load(f) == expected