1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

Additional reports (#18779)

* Additional reports
* Fix default status to be a list
This commit is contained in:
Toshio Kuratomi 2016-12-06 13:17:49 -08:00 committed by Matt Clay
parent b5a63a556d
commit ab43a26915

View file

@ -4,6 +4,7 @@ import ast
import csv import csv
import os import os
import sys import sys
from collections import defaultdict
from distutils.version import StrictVersion from distutils.version import StrictVersion
from pprint import pformat, pprint from pprint import pformat, pprint
@ -17,6 +18,10 @@ from ansible.plugins import module_loader
NONMODULE_PY_FILES = frozenset(('async_wrapper.py',)) NONMODULE_PY_FILES = frozenset(('async_wrapper.py',))
NONMODULE_MODULE_NAMES = frozenset(os.path.splitext(p)[0] for p in NONMODULE_PY_FILES) NONMODULE_MODULE_NAMES = frozenset(os.path.splitext(p)[0] for p in NONMODULE_PY_FILES)
# Default metadata
DEFAULT_METADATA = {'version': '1.0', 'status': ['preview'], 'supported_by':'community'}
class ParseError(Exception): class ParseError(Exception):
"""Thrown when parsing a file fails""" """Thrown when parsing a file fails"""
pass pass
@ -311,6 +316,7 @@ def parse_assigned_metadata_initial(csvfile):
else: else:
print('Module %s has no supported_by field. Using community' % record[0]) print('Module %s has no supported_by field. Using community' % record[0])
supported_by = 'community' supported_by = 'community'
supported_by = DEFAULT_METADATA['supported_by']
status = [] status = []
if record[6]: if record[6]:
@ -318,9 +324,9 @@ def parse_assigned_metadata_initial(csvfile):
if record[7]: if record[7]:
status.append('deprecated') status.append('deprecated')
if not status: if not status:
status.append('preview') status.extend(DEFAULT_METADATA['status'])
yield (module, {'version': '1.0', 'supported_by': supported_by, 'status': status}) yield (module, {'version': DEFAULT_METADATA['version'], 'supported_by': supported_by, 'status': status})
def parse_assigned_metadata(csvfile): def parse_assigned_metadata(csvfile):
@ -397,25 +403,41 @@ def write_metadata(filename, new_metadata, version=None, overwrite=False):
f.write(module_data) f.write(module_data)
def return_metadata(plugins):
metadata = {}
for name, filename in plugins:
# There may be several files for a module (if it is written in another
# language, for instance) but only one of them (the .py file) should
# contain the metadata.
if name not in metadata or metadata[name] is not None:
with open(filename, 'rb') as f:
module_data = f.read()
metadata[name] = extract_metadata(module_data)[0]
return metadata
def metadata_summary(plugins, version=None): def metadata_summary(plugins, version=None):
"""Compile information about the metadata status for a list of modules """Compile information about the metadata status for a list of modules
:arg plugins: List of plugins to look for. Each entry in the list is :arg plugins: List of plugins to look for. Each entry in the list is
a tuple of (module name, full path to module) a tuple of (module name, full path to module)
:kwarg version: If given, make sure the modules have this version of :kwarg version: If given, make sure the modules have this version of
metadata or highe. metadata or higher.
:returns: A tuple consisting of a list of modules with no metadata at the :returns: A tuple consisting of a list of modules with no metadata at the
required version and a list of files that have metadata at the required version and a list of files that have metadata at the
required version. required version.
""" """
no_metadata = {} no_metadata = {}
has_metadata = {} has_metadata = {}
for name, filename in plugins: supported_by = defaultdict(set)
if name not in no_metadata and name not in has_metadata: status = defaultdict(set)
with open(filename, 'rb') as f:
module_data = f.read()
metadata = extract_metadata(module_data)[0] plugins = list(plugins)
all_mods_metadata = return_metadata(plugins)
for name, filename in plugins:
# Does the module have metadata?
if name not in no_metadata and name not in has_metadata:
metadata = all_mods_metadata[name]
if metadata is None: if metadata is None:
no_metadata[name] = filename no_metadata[name] = filename
elif version is not None and ('version' not in metadata or StrictVersion(metadata['version']) < StrictVersion(version)): elif version is not None and ('version' not in metadata or StrictVersion(metadata['version']) < StrictVersion(version)):
@ -423,7 +445,17 @@ def metadata_summary(plugins, version=None):
else: else:
has_metadata[name] = filename has_metadata[name] = filename
return list(no_metadata.values()), list(has_metadata.values()) # What categories does the plugin belong in?
if all_mods_metadata[name] is None:
# No metadata for this module. Use the default metadata
supported_by[DEFAULT_METADATA['supported_by']].add(filename)
status[DEFAULT_METADATA['status'][0]].add(filename)
else:
supported_by[all_mods_metadata[name]['supported_by']].add(filename)
for one_status in all_mods_metadata[name]['status']:
status[one_status].add(filename)
return list(no_metadata.values()), list(has_metadata.values()), supported_by, status
# #
# Subcommands # Subcommands
@ -466,15 +498,12 @@ def add_default(version=None, overwrite=False):
plugins = ((os.path.splitext((os.path.basename(p)))[0], p) for p in plugins) plugins = ((os.path.splitext((os.path.basename(p)))[0], p) for p in plugins)
plugins = (p for p in plugins if p[0] not in NONMODULE_MODULE_NAMES) plugins = (p for p in plugins if p[0] not in NONMODULE_MODULE_NAMES)
# Default metadata
new_metadata = {'version': '1.0', 'status': 'preview', 'supported_by':'community'}
# Iterate through each plugin # Iterate through each plugin
processed = set() processed = set()
diagnostic_messages = [] diagnostic_messages = []
for name, filename in (info for info in plugins if info[0] not in processed): for name, filename in (info for info in plugins if info[0] not in processed):
try: try:
write_metadata(filename, new_metadata, version, overwrite) write_metadata(filename, DEFAULT_METADATA, version, overwrite)
except ParseError as e: except ParseError as e:
diagnostic_messages.append(e.args[0]) diagnostic_messages.append(e.args[0])
continue continue
@ -496,17 +525,43 @@ def report(version=None):
""" """
# List of all plugins # List of all plugins
plugins = module_loader.all(path_only=True) plugins = module_loader.all(path_only=True)
plugins = list(plugins)
plugins = ((os.path.splitext((os.path.basename(p)))[0], p) for p in plugins) plugins = ((os.path.splitext((os.path.basename(p)))[0], p) for p in plugins)
plugins = (p for p in plugins if p[0] != NONMODULE_MODULE_NAMES) plugins = (p for p in plugins if p[0] != NONMODULE_MODULE_NAMES)
plugins = list(plugins)
no_metadata, has_metadata = metadata_summary(plugins, version=version) no_metadata, has_metadata, support, status = metadata_summary(plugins, version=version)
print('== Has metadata ==') print('== Has metadata ==')
pprint(sorted(has_metadata)) pprint(sorted(has_metadata))
print('')
print('== Has no metadata ==') print('== Has no metadata ==')
pprint(sorted(no_metadata)) pprint(sorted(no_metadata))
print('') print('')
print('No Metadata: {0} Has Metadata: {1}'.format(len(no_metadata), len(has_metadata)))
print('== Supported by core ==')
pprint(sorted(support['core']))
print('== Supported by committers ==')
pprint(sorted(support['committer']))
print('== Supported by community ==')
pprint(sorted(support['community']))
print('')
print('== Status: stableinterface ==')
pprint(sorted(status['stableinterface']))
print('== Status: preview ==')
pprint(sorted(status['preview']))
print('== Status: deprecated ==')
pprint(sorted(status['deprecated']))
print('== Status: removed ==')
pprint(sorted(status['removed']))
print('')
print('== Summary ==')
print('No Metadata: {0} Has Metadata: {1}'.format(len(no_metadata), len(has_metadata)))
print('Supported by core: {0} Supported by community: {1} Supported by committer: {2}'.format(len(support['core']), len(support['community']), len(support['committer'])))
print('Status StableInterface: {0} Status Preview: {1} Status Deprecated: {2} Status Removed: {3}'.format(len(status['stableinterface']), len(status['preview']), len(status['deprecated']), len(status['removed'])))
return 0 return 0