def _validate_docs(self): doc_info = self._get_docs() deprecated = False if not bool(doc_info['DOCUMENTATION']['value']): self.reporter.error(path=self.object_path, code=301, msg='No DOCUMENTATION provided') else: doc, errors, traces = parse_yaml( doc_info['DOCUMENTATION']['value'], doc_info['DOCUMENTATION']['lineno'], self.name, 'DOCUMENTATION') for error in errors: self.reporter.error(path=self.object_path, code=302, **error) for trace in traces: self.reporter.trace(path=self.object_path, tracebk=trace) if not errors and not traces: with CaptureStd(): try: get_docstring(self.path, verbose=True) except AssertionError: fragment = doc['extends_documentation_fragment'] self.reporter.error( path=self.object_path, code=303, msg='DOCUMENTATION fragment missing: %s' % fragment) except Exception: self.reporter.trace(path=self.object_path, tracebk=traceback.format_exc()) self.reporter.error( path=self.object_path, code=304, msg='Unknown DOCUMENTATION error, see TRACE') if 'options' in doc and doc['options'] is None and doc.get( 'extends_documentation_fragment'): self.reporter.error( path=self.object_path, code=304, msg= ('DOCUMENTATION.options must be a dictionary/hash when used ' 'with DOCUMENTATION.extends_documentation_fragment')) if self.object_name.startswith('_') and not os.path.islink( self.object_path): deprecated = True if 'deprecated' not in doc or not doc.get('deprecated'): self.reporter.error( path=self.object_path, code=318, msg= 'Module deprecated, but DOCUMENTATION.deprecated is missing' ) if os.path.islink(self.object_path): # This module has an alias, which we can tell as it's a symlink # Rather than checking for `module: $filename` we need to check against the true filename self._validate_docs_schema( doc, doc_schema( os.readlink(self.object_path).split('.')[0]), 'DOCUMENTATION', 305) else: # This is the normal case self._validate_docs_schema( doc, doc_schema(self.object_name.split('.')[0]), 'DOCUMENTATION', 305) self._check_version_added(doc) self._check_for_new_args(doc) if not bool(doc_info['EXAMPLES']['value']): self.reporter.error(path=self.object_path, code=310, msg='No EXAMPLES provided') else: _, errors, traces = parse_yaml(doc_info['EXAMPLES']['value'], doc_info['EXAMPLES']['lineno'], self.name, 'EXAMPLES', load_all=True) for error in errors: self.reporter.error(path=self.object_path, code=311, **error) for trace in traces: self.reporter.trace(path=self.object_path, tracebk=trace) if not bool(doc_info['RETURN']['value']): if self._is_new_module(): self.reporter.error(path=self.object_path, code=312, msg='No RETURN provided') else: self.reporter.warning(path=self.object_path, code=312, msg='No RETURN provided') else: data, errors, traces = parse_yaml(doc_info['RETURN']['value'], doc_info['RETURN']['lineno'], self.name, 'RETURN') if data: for ret_key in data: self._validate_docs_schema(data[ret_key], return_schema(data[ret_key]), 'RETURN.%s' % ret_key, 319) for error in errors: self.reporter.error(path=self.object_path, code=313, **error) for trace in traces: self.reporter.trace(path=self.object_path, tracebk=trace) if not bool(doc_info['ANSIBLE_METADATA']['value']): self.reporter.error(path=self.object_path, code=314, msg='No ANSIBLE_METADATA provided') else: metadata = None if isinstance(doc_info['ANSIBLE_METADATA']['value'], ast.Dict): metadata = ast.literal_eval( doc_info['ANSIBLE_METADATA']['value']) else: metadata, errors, traces = parse_yaml( doc_info['ANSIBLE_METADATA']['value'].s, doc_info['ANSIBLE_METADATA']['lineno'], self.name, 'ANSIBLE_METADATA') for error in errors: self.reporter.error(path=self.object_path, code=315, **error) for trace in traces: self.reporter.trace(path=self.object_path, tracebk=trace) if metadata: self._validate_docs_schema(metadata, metadata_1_1_schema(deprecated), 'ANSIBLE_METADATA', 316) return doc_info
def _validate_docs(self): doc_info = self._get_docs() deprecated = False if not bool(doc_info['DOCUMENTATION']['value']): self.reporter.error( path=self.object_path, code=301, msg='No DOCUMENTATION provided' ) else: doc, errors, traces = parse_yaml( doc_info['DOCUMENTATION']['value'], doc_info['DOCUMENTATION']['lineno'], self.name, 'DOCUMENTATION' ) for error in errors: self.reporter.error( path=self.object_path, code=302, **error ) for trace in traces: self.reporter.trace( path=self.object_path, tracebk=trace ) if not errors and not traces: with CaptureStd(): try: get_docstring(self.path, verbose=True) except AssertionError: fragment = doc['extends_documentation_fragment'] self.reporter.error( path=self.object_path, code=303, msg='DOCUMENTATION fragment missing: %s' % fragment ) except Exception: self.reporter.trace( path=self.object_path, tracebk=traceback.format_exc() ) self.reporter.error( path=self.object_path, code=304, msg='Unknown DOCUMENTATION error, see TRACE' ) if 'options' in doc and doc['options'] is None and doc.get('extends_documentation_fragment'): self.reporter.error( path=self.object_path, code=304, msg=('DOCUMENTATION.options must be a dictionary/hash when used ' 'with DOCUMENTATION.extends_documentation_fragment') ) if self.object_name.startswith('_') and not os.path.islink(self.object_path): deprecated = True if 'deprecated' not in doc or not doc.get('deprecated'): self.reporter.error( path=self.object_path, code=318, msg='Module deprecated, but DOCUMENTATION.deprecated is missing' ) if os.path.islink(self.object_path): # This module has an alias, which we can tell as it's a symlink # Rather than checking for `module: $filename` we need to check against the true filename self._validate_docs_schema(doc, doc_schema(os.readlink(self.object_path).split('.')[0]), 'DOCUMENTATION', 305) else: # This is the normal case self._validate_docs_schema(doc, doc_schema(self.object_name.split('.')[0]), 'DOCUMENTATION', 305) self._check_version_added(doc) self._check_for_new_args(doc) if not bool(doc_info['EXAMPLES']['value']): self.reporter.error( path=self.object_path, code=310, msg='No EXAMPLES provided' ) else: _, errors, traces = parse_yaml(doc_info['EXAMPLES']['value'], doc_info['EXAMPLES']['lineno'], self.name, 'EXAMPLES', load_all=True) for error in errors: self.reporter.error( path=self.object_path, code=311, **error ) for trace in traces: self.reporter.trace( path=self.object_path, tracebk=trace ) if not bool(doc_info['RETURN']['value']): if self._is_new_module(): self.reporter.error( path=self.object_path, code=312, msg='No RETURN provided' ) else: self.reporter.warning( path=self.object_path, code=312, msg='No RETURN provided' ) else: data, errors, traces = parse_yaml(doc_info['RETURN']['value'], doc_info['RETURN']['lineno'], self.name, 'RETURN') if data: for ret_key in data: self._validate_docs_schema(data[ret_key], return_schema(data[ret_key]), 'RETURN.%s' % ret_key, 319) for error in errors: self.reporter.error( path=self.object_path, code=313, **error ) for trace in traces: self.reporter.trace( path=self.object_path, tracebk=trace ) if not bool(doc_info['ANSIBLE_METADATA']['value']): self.reporter.error( path=self.object_path, code=314, msg='No ANSIBLE_METADATA provided' ) else: metadata = None if isinstance(doc_info['ANSIBLE_METADATA']['value'], ast.Dict): metadata = ast.literal_eval( doc_info['ANSIBLE_METADATA']['value'] ) else: metadata, errors, traces = parse_yaml( doc_info['ANSIBLE_METADATA']['value'].s, doc_info['ANSIBLE_METADATA']['lineno'], self.name, 'ANSIBLE_METADATA' ) for error in errors: self.reporter.error( path=self.object_path, code=315, **error ) for trace in traces: self.reporter.trace( path=self.object_path, tracebk=trace ) if metadata: self._validate_docs_schema(metadata, metadata_1_1_schema(deprecated), 'ANSIBLE_METADATA', 316) return doc_info