forked from dftbplus/dftbplus
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
244 additions
and
171 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#!/usr/bin/env python3 | ||
import os | ||
import re | ||
import fnmatch | ||
import argparse | ||
|
||
|
||
DESCRIPTION = "Replaces the year in files with existing copyright header." | ||
|
||
YEAR = "2024" | ||
|
||
PATTERN = re.compile( | ||
r"""Copyright\s+\(C\)\s+(\d{4}\s*-\s*)*(?P<year>\d{4})\s+DFTB\+\s+developers\s+group""" | ||
) | ||
|
||
FOLDERS = ["app/", "cmake/", "src/", "sys/", "test/", "tools/", "utils/"] | ||
|
||
FILES = ["LICENSE"] | ||
|
||
CHANGE_MANUALLY = ["src/dftbp/common/release.F90", "doc/dptools/api/conf.py"] | ||
|
||
IGNORED_FOLDERS = ["__pycache__"] | ||
|
||
IGNORED_FILES = [ | ||
"*~", | ||
"*.pyc", | ||
"*/make.deps", | ||
"*/make.extdeps", | ||
"*.mgf", | ||
"*.egg", | ||
"*.skf", | ||
] | ||
|
||
|
||
def main(): | ||
"""Main function""" | ||
args = parse_arguments() | ||
rootdir = os.path.abspath(args.rootdir) | ||
process_files(rootdir) | ||
print_files_manually(rootdir) | ||
|
||
|
||
def parse_arguments(): | ||
"""Parses the arguments""" | ||
parser = argparse.ArgumentParser(description=DESCRIPTION) | ||
msg = "Root directory of the project (default: current directory)" | ||
parser.add_argument("--rootdir", default=os.getcwd(), help=msg) | ||
args = parser.parse_args() | ||
return args | ||
|
||
|
||
def process_files(rootdir): | ||
"""Replaces the year in header""" | ||
file_list = find_files(rootdir) | ||
number_files = len(file_list) | ||
indent = len(str(number_files)) + 1 | ||
for num, file in enumerate(file_list): | ||
changed_date = False | ||
with open(file, "r", encoding="utf-8") as fp: | ||
newcontent = "" | ||
for line in fp.readlines(): | ||
hit = PATTERN.search(line) | ||
if hit: | ||
changed_date = True | ||
start, stop = hit.span("year") | ||
newcontent += line[:start] + YEAR + line[stop:] | ||
else: | ||
newcontent += line | ||
with open(file, "w", encoding="utf-8") as fp: | ||
fp.write(newcontent) | ||
if changed_date: | ||
print(f"{num + 1:>{indent}} of {number_files}: ", file, " CHANGED") | ||
else: | ||
print(f"{num + 1:>{indent}} of {number_files}: ", file, " UNCHANGED") | ||
|
||
|
||
def find_files(rootdir): | ||
"""Walks through 'FOLDERS' and 'FILES' in rootdir and adds them to | ||
'file_list'""" | ||
file_list = [] | ||
for file in FILES: | ||
file_list.append(os.path.join(rootdir, file)) | ||
for folder in FOLDERS: | ||
for root, dirs, files in os.walk(os.path.join(rootdir, folder)): | ||
dirs[:] = [d for d in dirs if d not in IGNORED_FOLDERS] | ||
for file in files: | ||
for ignored in IGNORED_FILES: | ||
if fnmatch.fnmatch(file, ignored): | ||
break | ||
else: | ||
file_list.append(os.path.join(root, file)) | ||
return file_list | ||
|
||
|
||
def print_files_manually(rootdir): | ||
"""Prints the files that needs to be changed manually""" | ||
print("Please change the year in the following files manually:") | ||
for file in CHANGE_MANUALLY: | ||
print(os.path.join(rootdir, file)) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
#!/usr/bin/env python3 | ||
import sys | ||
import os | ||
import re | ||
import fnmatch | ||
import argparse | ||
|
||
if sys.hexversion < 0x03050000: | ||
sys.stderr.write("Error: this script requires Python 3.5 or newer") | ||
sys.exit(1) | ||
|
||
|
||
DESCRIPTION = "Creates the copyright header in all relevant source files." | ||
|
||
COPYRIGHT = """DFTB+: general package for performing fast atomistic simulations | ||
Copyright (C) 2006 - 2024 DFTB+ developers group | ||
See the LICENSE file for terms of usage and distribution.""" | ||
|
||
|
||
FOLDERS = ["app/", "cmake/", "src/", "sys/", "test/", "tools/", "utils/"] | ||
|
||
FILE_TYPES = [ | ||
("*.[fF]90", "fortran"), | ||
("*.[hc]", "c"), | ||
("*.fpp", "fortran"), | ||
("*.inc", "fortran"), | ||
("*.fypp", "fypp"), | ||
("make.*", "makefile"), | ||
("makefile", "makefile"), | ||
("*.sh", "shell"), | ||
("*.py", "python"), | ||
] | ||
|
||
|
||
def main(): | ||
"""Main function""" | ||
args = parse_arguments() | ||
process_files(os.path.abspath(args.rootdir)) | ||
|
||
|
||
def parse_arguments(): | ||
"""Parses the arguments""" | ||
parser = argparse.ArgumentParser(description=DESCRIPTION) | ||
msg = "Root directory of the project (default: current directory)" | ||
parser.add_argument("--rootdir", default=os.getcwd(), help=msg) | ||
args = parser.parse_args() | ||
return args | ||
|
||
|
||
def find_files(rootdir): | ||
"""Walks through 'FOLDERS' and 'FILE_TYPES' in rootdir and adds them to | ||
'file_list'""" | ||
file_list = [] | ||
for folder in FOLDERS: | ||
for root, _, files in os.walk(os.path.join(rootdir, folder)): | ||
for file in files: | ||
for fpattern, ftype in FILE_TYPES: | ||
if fnmatch.fnmatch(file, fpattern): | ||
file_list.append((os.path.join(root, file), ftype)) | ||
return file_list | ||
|
||
|
||
def process_files(rootdir): | ||
"""Iterates over files and inserts headers accordingly""" | ||
file_list = find_files(rootdir) | ||
for file, ftype in file_list: | ||
headerpattern, newheader = HEADER_BY_TYPE[ftype] | ||
set_header(file, headerpattern, newheader) | ||
|
||
|
||
def set_header(fname, headerpattern, header): | ||
"""Adds headers to files that do not contain headers""" | ||
with open(fname, "r", encoding="utf-8") as fp: | ||
txt = fp.readlines() | ||
first_line = txt[0] | ||
hit = headerpattern.search("".join(txt)) | ||
if not hit: | ||
if SHEBANG.match(first_line) is None: | ||
newtxt = header + "\n\n" + first_line + "".join(txt[1:]) | ||
else: | ||
newtxt = first_line + header + "\n\n" + "".join(txt[1:]) | ||
with open(fname, "w", encoding="utf-8") as fp: | ||
fp.write(newtxt) | ||
print("Header added in: ", fname) | ||
|
||
|
||
def pretty_header(txt, commentbegin, commentend, marker, linelength): | ||
"""Creates 'pretty header'""" | ||
commentlen = len(commentbegin) + len(commentend) | ||
headerseparator = commentbegin + marker * (linelength - commentlen) + commentend | ||
headerlines = [headerseparator] | ||
for line in txt.split("\n"): | ||
line = line.strip() | ||
padding = linelength - commentlen - 2 - len(line) | ||
headerlines.append(commentbegin + " " + line + " " * padding + commentend) | ||
headerlines.append(headerseparator) | ||
return "\n".join(headerlines) | ||
|
||
|
||
RAWTEXT_HEADER_PATTERN = re.compile( | ||
r"[ \t]*\|---+\|[ \t]*\n(?:[ \t]*\|.*\n)*?[ \t]*\|---+\|[ \t]*$", re.MULTILINE | ||
) | ||
RAWTEXT_HEADER = pretty_header(COPYRIGHT, "!", "!", "-", 80) | ||
|
||
FORTRAN_HEADER_PATTERN = re.compile( | ||
r"[ \t]*!---+![ \t]*\n(?:[ \t]*!.*\n)*?[ \t]*!---+![ \t]*$", re.MULTILINE | ||
) | ||
FORTRAN_HEADER = pretty_header(COPYRIGHT, "!", "!", "-", 100) | ||
|
||
SCRIPT_HEADER_PATTERN = re.compile( | ||
r"[ \t]*#---+#[ \t]*\n(?:[ \t]*#.*\n)*?[ \t]*#---+#[ \t]*$", re.MULTILINE | ||
) | ||
SCRIPT_HEADER = pretty_header(COPYRIGHT, "#", "#", "-", 80) | ||
|
||
FYPP_HEADER_PATTERN = re.compile( | ||
r"[ \t]*#!---+![ \t]*\n(?:[ \t]*#!.*\n)*?[ \t]*#!---+![ \t]*$", re.MULTILINE | ||
) | ||
FYPP_HEADER = pretty_header(COPYRIGHT, "#!", "!", "-", 100) | ||
|
||
C_HEADER_PATTERN = re.compile( | ||
r"[ \t]*/\*---+\*/[ \t]*\n(?:[ \t]*/\*.*\n)*?[ \t]*/\*---+\*/[ \t]*$", re.MULTILINE | ||
) | ||
C_HEADER = pretty_header(COPYRIGHT, "/*", "*/", "-", 100) | ||
|
||
SHEBANG = re.compile(r"^#!(.*)") | ||
|
||
|
||
HEADER_BY_TYPE = { | ||
"fortran": (FORTRAN_HEADER_PATTERN, FORTRAN_HEADER), | ||
"makefile": (SCRIPT_HEADER_PATTERN, SCRIPT_HEADER), | ||
"python": (SCRIPT_HEADER_PATTERN, SCRIPT_HEADER), | ||
"rawtext": (RAWTEXT_HEADER_PATTERN, RAWTEXT_HEADER), | ||
"shell": (SCRIPT_HEADER_PATTERN, SCRIPT_HEADER), | ||
"fypp": (FYPP_HEADER_PATTERN, FYPP_HEADER), | ||
"c": (C_HEADER_PATTERN, C_HEADER), | ||
} | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
Oops, something went wrong.