Commit 5d3c30df authored by Michael Hanselmann's avatar Michael Hanselmann

Add tool to check Python file headers

Ensures licence and copyright headers are correct.
Signed-off-by: default avatarMichael Hanselmann <hansmi@google.com>
Reviewed-by: default avatarRené Nussbaumer <rn@google.com>
parent 769582be
......@@ -21,6 +21,7 @@ ACLOCAL_AMFLAGS = -I autotools
BUILD_BASH_COMPLETION = $(top_srcdir)/autotools/build-bash-completion
RUN_IN_TEMPDIR = $(top_srcdir)/autotools/run-in-tempdir
CHECK_PYTHON_CODE = $(top_srcdir)/autotools/check-python-code
CHECK_HEADER = $(top_srcdir)/autotools/check-header
CHECK_MAN = $(top_srcdir)/autotools/check-man
CHECK_VERSION = $(top_srcdir)/autotools/check-version
CHECK_NEWS = $(top_srcdir)/autotools/check-news
......@@ -560,6 +561,7 @@ EXTRA_DIST = \
pylintrc \
autotools/build-bash-completion \
autotools/build-rpc \
autotools/check-header \
autotools/check-python-code \
autotools/check-imports \
autotools/check-man \
......@@ -804,6 +806,7 @@ srclink_files = \
check_python_code = \
$(BUILD_BASH_COMPLETION) \
$(CHECK_IMPORTS) \
$(CHECK_HEADER) \
$(DOCPP) \
$(all_python_code)
......@@ -815,6 +818,7 @@ lint_python_code = \
$(pkglib_python_scripts) \
$(BUILD_BASH_COMPLETION) \
$(CHECK_IMPORTS) \
$(CHECK_HEADER) \
$(DOCPP) \
$(PYTHON_BOOTSTRAP)
......@@ -829,6 +833,7 @@ pep8_python_code = \
$(dist_tools_PYTHON) \
$(pkglib_python_scripts) \
$(BUILD_BASH_COMPLETION) \
$(CHECK_HEADER) \
$(DOCPP) \
$(PYTHON_BOOTSTRAP) \
qa
......@@ -1124,6 +1129,7 @@ check-dirs: $(BUILT_SOURCES)
.PHONY: check-local
check-local: check-dirs $(BUILT_SOURCES)
$(CHECK_PYTHON_CODE) $(check_python_code)
PYTHONPATH=. $(CHECK_HEADER) $(check_python_code)
$(CHECK_VERSION) $(VERSION) $(top_srcdir)/NEWS
$(CHECK_NEWS) < $(top_srcdir)/NEWS
PYTHONPATH=. $(RUN_IN_TEMPDIR) $(CURDIR)/$(CHECK_IMPORTS) . $(standalone_python_modules)
......
#!/usr/bin/python
#
# Copyright (C) 2011 Google Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.
"""Script to verify file header.
"""
# pylint: disable-msg=C0103
# [C0103] Invalid name
import sys
import re
import itertools
from ganeti import constants
from ganeti import utils
from ganeti import compat
#: Assume header is always in the first 8kB of a file
_READ_SIZE = 8 * 1024
_GPLv2 = [
"This program is free software; you can redistribute it and/or modify",
"it under the terms of the GNU General Public License as published by",
"the Free Software Foundation; either version 2 of the License, or",
"(at your option) any later version.",
"",
"This program is distributed in the hope that it will be useful, but",
"WITHOUT ANY WARRANTY; without even the implied warranty of",
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU",
"General Public License for more details.",
"",
"You should have received a copy of the GNU General Public License",
"along with this program; if not, write to the Free Software",
"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA",
"02110-1301, USA.",
]
_SHEBANG = re.compile(r"^#(?:|!(?:/usr/bin/python(?:| -u)|/bin/(?:|ba)sh))$")
_COPYRIGHT_YEAR = r"20[01][0-9]"
_COPYRIGHT = re.compile(r"# Copyright \(C\) (%s(?:, %s)*) Google Inc\.$" %
(_COPYRIGHT_YEAR, _COPYRIGHT_YEAR))
_COPYRIGHT_DESC = "Copyright (C) <year>[, <year> ...] Google Inc."
_AUTOGEN = "# This file is automatically generated, do not edit!"
class HeaderError(Exception):
pass
def _Fail(lineno, msg):
raise HeaderError("Line %s: %s" % (lineno, msg))
def _CheckHeader(getline_fn):
(lineno, line) = getline_fn()
if line == _AUTOGEN:
return
if not _SHEBANG.match(line):
_Fail(lineno, ("Must contain nothing but a hash character (#) or a"
" shebang line (e.g. #!/bin/bash)"))
(lineno, line) = getline_fn()
if line == _AUTOGEN:
return
if line != "#":
_Fail(lineno, "Must contain nothing but hash character (#)")
(lineno, line) = getline_fn()
if line:
_Fail(lineno, "Must be empty")
(lineno, line) = getline_fn()
if not _COPYRIGHT.match(line):
_Fail(lineno, "Must contain copyright information (%s)" % _COPYRIGHT_DESC)
(lineno, line) = getline_fn()
if line != "#":
_Fail(lineno, "Must contain nothing but hash character (#)")
for licence_line in _GPLv2:
(lineno, line) = getline_fn()
if line != ("# %s" % licence_line).rstrip():
_Fail(lineno, "Does not match expected licence line (%s)" % licence_line)
(lineno, line) = getline_fn()
if line:
_Fail(lineno, "Must be empty")
def Main():
"""Main program.
"""
fail = False
for filename in sys.argv[1:]:
content = utils.ReadFile(filename, size=_READ_SIZE)
lines = zip(itertools.count(1), content.splitlines())
try:
_CheckHeader(compat.partial(lines.pop, 0))
except HeaderError, err:
report = str(err)
print "%s: %s" % (filename, report)
fail = True
if fail:
sys.exit(constants.EXIT_FAILURE)
else:
sys.exit(constants.EXIT_SUCCESS)
if __name__ == "__main__":
Main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment