def parse_raw(self) -> None: if isinstance(self.source, list) or (isinstance(self.source, Path) and self.source.is_dir()): self.current_source_path = Path() self.model_resolver.after_load_files = { s.path.as_posix() for s in self.iter_source } for source in self.iter_source: path_parts = list(source.path.parts) if self.current_source_path is not None: self.current_source_path = source.path with self.model_resolver.current_root_context(path_parts): self.raw_obj = load_yaml(source.text) if self.class_name: obj_name = self.class_name else: # backward compatible obj_name = self.raw_obj.get('title', 'Model') if not self.model_resolver.validate_name(obj_name): raise InvalidClassNameError(obj_name) self._parse_file(self.raw_obj, obj_name, path_parts) # resolve unparsed json pointer for source in self.iter_source: path_parts = list(source.path.parts) reserved_refs = self.reserved_refs.get( tuple(path_parts)) # type: ignore if not reserved_refs: continue if self.current_source_path is not None: self.current_source_path = source.path with self.model_resolver.current_root_context(path_parts): for reserved_ref in sorted(reserved_refs): if self.model_resolver.add_ref(reserved_ref).loaded: continue file_path, model_path = reserved_ref.split('#', 1) valid_path_parts = [p for p in model_path.split('/') if p] if (len(valid_path_parts) == 1 and self.model_resolver.add_ref( f'{file_path}#').loaded): # pragma: no cover continue # for root model self.raw_obj = load_yaml(source.text) self.parse_json_pointer(self.raw_obj, reserved_ref, path_parts)
def _resolve_unparsed_json_pointer(self) -> None: model_count: int = len(self.results) for source in self.iter_source: path_parts = list(source.path.parts) reserved_refs = self.reserved_refs.get( tuple(path_parts)) # type: ignore if not reserved_refs: continue if self.current_source_path is not None: self.current_source_path = source.path with self.model_resolver.current_base_path_context( source.path.parent ), self.model_resolver.current_root_context(path_parts): for reserved_ref in sorted(reserved_refs): if self.model_resolver.add_ref(reserved_ref, resolved=True).loaded: continue # for root model self.raw_obj = load_yaml(source.text) self.parse_json_pointer(self.raw_obj, reserved_ref, path_parts) if model_count != len(self.results): # New model have been generated. It try to resolve json pointer again. self._resolve_unparsed_json_pointer()
def parse_raw(self) -> None: if isinstance(self.source, list) or (isinstance(self.source, Path) and self.source.is_dir()): self.current_source_path = Path() self.model_resolver.after_load_files = { self.base_path.joinpath(s.path).resolve().as_posix() for s in self.iter_source } for source in self.iter_source: if isinstance(self.source, ParseResult): path_parts = self.get_url_path_parts(self.source) else: path_parts = list(source.path.parts) if self.current_source_path is not None: self.current_source_path = source.path with self.model_resolver.current_base_path_context( source.path.parent ), self.model_resolver.current_root_context(path_parts): self.raw_obj = load_yaml(source.text) if self.custom_class_name_generator: obj_name = self.raw_obj.get('title', 'Model') else: if self.class_name: obj_name = self.class_name else: # backward compatible obj_name = self.raw_obj.get('title', 'Model') if not self.model_resolver.validate_name(obj_name): obj_name = title_to_class_name(obj_name) if not self.model_resolver.validate_name(obj_name): raise InvalidClassNameError(obj_name) self._parse_file(self.raw_obj, obj_name, path_parts) self._resolve_unparsed_json_pointer()
def parse_raw(self) -> None: for source in self.iter_source: if self.validation: from prance import BaseParser base_parser = BaseParser(spec_string=source.text, backend='openapi-spec-validator') specification: Dict[str, Any] = base_parser.specification else: specification = load_yaml(source.text) self.raw_obj = specification schemas: Dict[Any, Any] = specification.get('components', {}).get('schemas', {}) if isinstance(self.source, ParseResult): path_parts: List[str] = self.get_url_path_parts(self.source) else: path_parts = list(source.path.parts) with self.model_resolver.current_root_context(path_parts): for obj_name, raw_obj in schemas.items( ): # type: str, Dict[Any, Any] self.parse_raw_obj( obj_name, raw_obj, [*path_parts, '#/components', 'schemas', obj_name], )
def _get_ref_body_from_remote(self, ref: str) -> Dict[Any, Any]: cached_ref_body: Optional[Dict[str, Any]] = self.remote_object_cache.get(ref) if cached_ref_body: return cached_ref_body # Remote Reference – $ref: 'document.json' Uses the whole document located on the same server and in # the same location. TODO treat edge case if self.current_source_path and len(self.current_source_path.parts) > 1: full_path = self.base_path / self.current_source_path.parent / ref else: full_path = self.base_path / ref # yaml loader can parse json data. with full_path.open() as f: ref_body = load_yaml(f) self.remote_object_cache[ref] = ref_body return ref_body
def _get_ref_body_from_url(self, ref: str) -> Dict[Any, Any]: cached_ref_body: Optional[Dict[str, Any]] = self.remote_object_cache.get(ref) if cached_ref_body: return cached_ref_body # URL Reference – $ref: 'http://path/to/your/resource' Uses the whole document located on the different server. try: import httpx except ImportError: # pragma: no cover raise Exception( f'Please run $pip install datamodel-code-generator[http] to resolve URL Reference ref={ref}' ) raw_body: str = httpx.get(ref).text # yaml loader can parse json data. ref_body = load_yaml(raw_body) self.remote_object_cache[ref] = ref_body return ref_body
def parse_raw(self) -> None: if isinstance(self.source, list) or ( isinstance(self.source, Path) and self.source.is_dir() ): self.current_source_path = Path() self.model_resolver.after_load_files = { s.path.as_posix() for s in self.iter_source } for source in self.iter_source: if self.current_source_path is not None: self.current_source_path = source.path path_parts = list(source.path.parts) with self.model_resolver.current_root_context(path_parts): self.raw_obj = load_yaml(source.text) if self.class_name: obj_name = self.class_name else: # backward compatible obj_name = self.raw_obj.get('title', 'Model') if not self.model_resolver.validate_name(obj_name): raise InvalidClassNameError(obj_name) self._parse_file(self.raw_obj, obj_name, path_parts, path_parts)
def _get_ref_body_from_url(self, ref: str) -> Dict[Any, Any]: # URL Reference – $ref: 'http://path/to/your/resource' Uses the whole document located on the different server. return self.remote_object_cache.get_or_put( ref, default_factory=lambda key: load_yaml(self._get_text_from_url(key) ))
def parse(self) -> ParsedObject: openapi = load_yaml(self.input_text) return self.parse_paths(openapi)
def parse_raw(self) -> None: for source in self.iter_source: if self.validation: from prance import BaseParser BaseParser( spec_string=source.text, backend='openapi-spec-validator', encoding=self.encoding, ) specification: Dict[str, Any] = load_yaml(source.text) self.raw_obj = specification schemas: Dict[Any, Any] = specification.get('components', {}).get( 'schemas', {} ) security: Optional[List[Dict[str, List[str]]]] = specification.get( 'security' ) if isinstance(self.source, ParseResult): path_parts: List[str] = self.get_url_path_parts(self.source) else: path_parts = list(source.path.parts) with self.model_resolver.current_root_context(path_parts): if OpenAPIScope.Schemas in self.open_api_scopes: for ( obj_name, raw_obj, ) in schemas.items(): # type: str, Dict[Any, Any] self.parse_raw_obj( obj_name, raw_obj, [*path_parts, '#/components', 'schemas', obj_name], ) if OpenAPIScope.Paths in self.open_api_scopes: paths: Dict[str, Dict[str, Any]] = specification.get('paths', {}) parameters: List[Dict[str, Any]] = [ self._get_ref_body(p['$ref']) if '$ref' in p else p # type: ignore for p in paths.get('parameters', []) if isinstance(p, dict) ] paths_path = [*path_parts, '#/paths'] for path_name, methods in paths.items(): paths_parameters = parameters[:] if 'parameters' in methods: paths_parameters.extend(methods['parameters']) relative_path_name = path_name[1:] if relative_path_name: path = [*paths_path, relative_path_name] else: # pragma: no cover path = get_special_path('root', paths_path) for operation_name, raw_operation in methods.items(): if operation_name not in OPERATION_NAMES: continue if paths_parameters: if 'parameters' in raw_operation: # pragma: no cover raw_operation['parameters'].extend(paths_parameters) else: raw_operation['parameters'] = paths_parameters if security is not None and 'security' not in raw_operation: raw_operation['security'] = security self.parse_operation( raw_operation, [*path, operation_name], )