mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-24 08:00:02 -06:00
ticket 1707 - add documentation validation to makeapi tool
Iterate over all API commands and perform the following validation: * Every command must have documentation and it must be marked for international translation * Every module hosting a command must have documentation and it must be marked for international translation * Every module topic must be marked for international translation For every error found emit a diagnostic. Emit a summary of total errors found. Return error flag if errors found, zero otherwise.
This commit is contained in:
parent
6dfd7c8242
commit
f4ad749126
120
makeapi
120
makeapi
@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# Authors:
|
# Authors:
|
||||||
# Rob Crittenden <rcritten@redhat.com>
|
# Rob Crittenden <rcritten@redhat.com>
|
||||||
|
# John Dennis <jdennis@redhat.com>
|
||||||
#
|
#
|
||||||
# Copyright (C) 2011 Red Hat
|
# Copyright (C) 2011 Red Hat
|
||||||
# see file 'COPYING' for use and warranty information
|
# see file 'COPYING' for use and warranty information
|
||||||
@ -24,14 +25,16 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import inspect
|
||||||
from ipalib import *
|
from ipalib import *
|
||||||
from ipalib.text import Gettext
|
from ipalib.text import Gettext, NGettext
|
||||||
|
|
||||||
API_FILE='API.txt'
|
API_FILE='API.txt'
|
||||||
|
|
||||||
API_FILE_DIFFERENCE = 1
|
API_FILE_DIFFERENCE = 1
|
||||||
API_NEW_COMMAND = 2
|
API_NEW_COMMAND = 2
|
||||||
API_NO_FILE = 4
|
API_NO_FILE = 4
|
||||||
|
API_DOC_ERROR = 8
|
||||||
|
|
||||||
def parse_options():
|
def parse_options():
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
@ -40,6 +43,9 @@ def parse_options():
|
|||||||
parser.add_option("--validate", dest="validate", action="store_true",
|
parser.add_option("--validate", dest="validate", action="store_true",
|
||||||
default=False, help="Validate the API vs the stored API")
|
default=False, help="Validate the API vs the stored API")
|
||||||
|
|
||||||
|
parser.add_option("--no-validate-doc", dest="validate_doc", action="store_false",
|
||||||
|
default=True, help="Do not validate documentation")
|
||||||
|
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
return options, args
|
return options, args
|
||||||
|
|
||||||
@ -53,6 +59,104 @@ def strip_doc(line):
|
|||||||
|
|
||||||
return newline
|
return newline
|
||||||
|
|
||||||
|
def validate_doc():
|
||||||
|
"""
|
||||||
|
Iterate over all API commands and perform the following validation:
|
||||||
|
|
||||||
|
* Every command must have documentation
|
||||||
|
and it must be marked for international translation
|
||||||
|
|
||||||
|
* Every module hosting a command must have documentation
|
||||||
|
and it must be marked for international translation
|
||||||
|
|
||||||
|
* Every module topic must be marked for international translation
|
||||||
|
|
||||||
|
For every error found emit a diagnostic.
|
||||||
|
Emit a summary of total errors found.
|
||||||
|
|
||||||
|
Return error flag if errors found, zero otherwise.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def is_i18n(obj):
|
||||||
|
'Helper utility to determine if object has been internationalized'
|
||||||
|
return isinstance(obj, (Gettext, NGettext))
|
||||||
|
|
||||||
|
# The return value
|
||||||
|
rval = 0
|
||||||
|
|
||||||
|
# Used to track if we've processed a module already
|
||||||
|
modules = {}
|
||||||
|
|
||||||
|
# Initialize error counters
|
||||||
|
n_missing_cmd_doc = 0
|
||||||
|
n_missing_cmd_i18n = 0
|
||||||
|
n_missing_mod_doc = 0
|
||||||
|
n_missing_mod_i18n = 0
|
||||||
|
|
||||||
|
# Iterate over every command
|
||||||
|
for cmd in api.Command():
|
||||||
|
cmd_class = cmd.__class__
|
||||||
|
|
||||||
|
# Skip commands marked as NO_CLI
|
||||||
|
if getattr(cmd, 'NO_CLI', False):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Have we processed this module yet?
|
||||||
|
if not modules.setdefault(cmd.module, 0):
|
||||||
|
# First time seeing this module, validate the module contents
|
||||||
|
mod = sys.modules[cmd.module]
|
||||||
|
|
||||||
|
# See if there is a module topic, if so validate it
|
||||||
|
topic = getattr(mod, 'topic', None)
|
||||||
|
if topic is not None:
|
||||||
|
if not is_i18n(topic[1]):
|
||||||
|
src_file = inspect.getsourcefile(cmd_class)
|
||||||
|
n_missing_mod_i18n += 1
|
||||||
|
print "%s: topic in module \"%s\" is not internationalized" % \
|
||||||
|
(src_file, cmd.module)
|
||||||
|
|
||||||
|
# Does the module have documentation?
|
||||||
|
if mod.__doc__ is None:
|
||||||
|
src_file = inspect.getsourcefile(mod)
|
||||||
|
n_missing_mod_doc += 1
|
||||||
|
print "%s: module \"%s\" has no doc" % \
|
||||||
|
(src_file, cmd.module)
|
||||||
|
# Yes the module has doc, but is it internationalized?
|
||||||
|
elif not is_i18n(mod.__doc__):
|
||||||
|
src_file = inspect.getsourcefile(cmd_class)
|
||||||
|
n_missing_mod_i18n += 1
|
||||||
|
print "%s: module \"%s\" doc is not internationalized" % \
|
||||||
|
(src_file, cmd.module)
|
||||||
|
|
||||||
|
# Increment the count of how many commands in this module
|
||||||
|
modules[cmd.module] = modules[cmd.module] + 1
|
||||||
|
|
||||||
|
# Does the command have documentation?
|
||||||
|
if cmd.__doc__ is None:
|
||||||
|
src_file = inspect.getsourcefile(cmd_class)
|
||||||
|
line_num = inspect.getsourcelines(cmd_class)[1]
|
||||||
|
n_missing_cmd_doc += 1
|
||||||
|
print "%s:%d command \"%s\" has no doc" % (src_file, line_num, cmd.name)
|
||||||
|
# Yes the command has doc, but is it internationalized?
|
||||||
|
elif not is_i18n(cmd.__doc__):
|
||||||
|
src_file = inspect.getsourcefile(cmd_class)
|
||||||
|
line_num = inspect.getsourcelines(cmd_class)[1]
|
||||||
|
n_missing_cmd_i18n += 1
|
||||||
|
print "%s:%d command \"%s\" doc is not internationalized" % (src_file, line_num, cmd.name)
|
||||||
|
|
||||||
|
# If any errors, emit summary information and adjust return value
|
||||||
|
if n_missing_cmd_doc > 0 or n_missing_cmd_i18n > 0:
|
||||||
|
rval = API_DOC_ERROR
|
||||||
|
print "%d commands without doc, %d commands whose doc is not i18n" % \
|
||||||
|
(n_missing_cmd_doc, n_missing_cmd_i18n)
|
||||||
|
|
||||||
|
if n_missing_mod_doc > 0 or n_missing_mod_i18n > 0:
|
||||||
|
rval = API_DOC_ERROR
|
||||||
|
print "%d modules without doc, %d modules whose doc is not i18n" % \
|
||||||
|
(n_missing_mod_doc, n_missing_mod_i18n)
|
||||||
|
|
||||||
|
return rval
|
||||||
|
|
||||||
def make_api():
|
def make_api():
|
||||||
"""
|
"""
|
||||||
Write a new API file from the current tree.
|
Write a new API file from the current tree.
|
||||||
@ -242,6 +346,7 @@ def validate_api():
|
|||||||
return rval
|
return rval
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
rval = 0
|
||||||
options, args = parse_options()
|
options, args = parse_options()
|
||||||
|
|
||||||
cfg = dict(
|
cfg = dict(
|
||||||
@ -257,15 +362,18 @@ def main():
|
|||||||
api.bootstrap(**cfg)
|
api.bootstrap(**cfg)
|
||||||
api.finalize()
|
api.finalize()
|
||||||
|
|
||||||
|
if options.validate_doc:
|
||||||
|
rval |= validate_doc()
|
||||||
|
|
||||||
if options.validate:
|
if options.validate:
|
||||||
if not os.path.exists(API_FILE):
|
if not os.path.exists(API_FILE):
|
||||||
print 'No %s to validate' % API_FILE
|
print 'No %s to validate' % API_FILE
|
||||||
rval = API_NO_FILE
|
rval |= API_NO_FILE
|
||||||
else:
|
else:
|
||||||
rval = validate_api()
|
rval |= validate_api()
|
||||||
else:
|
else:
|
||||||
print "Writing API to API.txt"
|
print "Writing API to API.txt"
|
||||||
rval = make_api()
|
rval |= make_api()
|
||||||
|
|
||||||
if rval & API_FILE_DIFFERENCE:
|
if rval & API_FILE_DIFFERENCE:
|
||||||
print ''
|
print ''
|
||||||
@ -275,6 +383,10 @@ def main():
|
|||||||
print ''
|
print ''
|
||||||
print 'There are one or more new commands defined.\nUpdate API.txt and increment the minor version in VERSION.'
|
print 'There are one or more new commands defined.\nUpdate API.txt and increment the minor version in VERSION.'
|
||||||
|
|
||||||
|
if rval & API_DOC_ERROR:
|
||||||
|
print ''
|
||||||
|
print 'There are one or more documentation problems.\nYou must fix these before preceeding'
|
||||||
|
|
||||||
return rval
|
return rval
|
||||||
|
|
||||||
sys.exit(main())
|
sys.exit(main())
|
||||||
|
Loading…
Reference in New Issue
Block a user