Skip to content

Commit

Permalink
Add command-line tool lower_case_cmake.py (TriBITSPub#274)
Browse files Browse the repository at this point in the history
This will be used to refactor all TriBITS code and documentation to lower case
command names.
  • Loading branch information
bartlettroscoe committed Jun 16, 2021
1 parent 7a11ddb commit 277c40b
Show file tree
Hide file tree
Showing 3 changed files with 307 additions and 0 deletions.
9 changes: 9 additions & 0 deletions test/python_utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ TRIBITS_ADD_ADVANCED_TEST( mockprogram_UnitTests
XHOST travis-ci-server-linux
)

TRIBITS_ADD_ADVANCED_TEST( lower_case_cmake_UnitTests
OVERALL_WORKING_DIRECTORY TEST_NAME
OVERALL_NUM_MPI_PROCS 1
TEST_0 CMND ${PYTHON_EXECUTABLE}
ARGS ${CMAKE_CURRENT_SOURCE_DIR}/lower_case_cmake_UnitTests.py -v
PASS_REGULAR_EXPRESSION "OK"
XHOST travis-ci-server-linux
)

TRIBITS_ADD_ADVANCED_TEST( gitdist_UnitTests
OVERALL_WORKING_DIRECTORY TEST_NAME
OVERALL_NUM_MPI_PROCS 1
Expand Down
179 changes: 179 additions & 0 deletions test/python_utils/lower_case_cmake_UnitTests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#################################
# Unit testing code for gitdist #
#################################

import sys
import imp
import shutil

from unittest_helpers import *

pythonDir = os.path.abspath(GeneralScriptSupport.getScriptBaseDir())
utilsDir = pythonDir+"/utils"
tribitsDir = os.path.abspath(pythonDir+"/..")

sys.path = [pythonUtilsDir] + sys.path

import lower_case_cmake as LCC


class test_makeCmndsLowerCaseInCMakeStr(unittest.TestCase):

def test_upper_1(self):
cmakeCodeStrIn = "\n"+\
"SET(SOME_VAR some_value)\n"+\
"\n"
cmakeCodeStrOut_expected = "\n"+\
"set(SOME_VAR some_value)\n"+\
"\n"
cmakeCodeStrOut = LCC.makeCmndsLowerCaseInCMakeStr(cmakeCodeStrIn)
self.assertEqual(cmakeCodeStrOut, cmakeCodeStrOut_expected)

def test_mixed_1(self):
cmakeCodeStrIn = "\n"+\
" SET (SOME_VAR some_value)\n"+\
"\n"+\
" # Some comment\n"+\
" Some_Longer_Func(SOME_VAR some_value)\n"+\
"\n"+\
" other_functioNS\n"+\
" (\n"+\
" SOME_VAR some_value)\n"+\
"\n"
cmakeCodeStrOut_expected = "\n"+\
" set (SOME_VAR some_value)\n"+\
"\n"+\
" # Some comment\n"+\
" some_longer_func(SOME_VAR some_value)\n"+\
"\n"+\
" other_functions\n"+\
" (\n"+\
" SOME_VAR some_value)\n"+\
"\n"
cmakeCodeStrOut = LCC.makeCmndsLowerCaseInCMakeStr(cmakeCodeStrIn)
self.assertEqual(cmakeCodeStrOut, cmakeCodeStrOut_expected)

def test_macro_def_1(self):
cmakeCodeStrIn = "\n"+\
"# Some macro we are defining\n"+\
"#\n"+\
"# Usage::\n"+\
"#\n"+\
"# SOME_MACRO(<some_args>)\n"+\
"#\n"+\
"Macro(Some_Macro1 ARG1 ARG2)\n"+\
" #SOME_CALL()\n"+\
"EndMacro()\n"+\
"\n"+\
"MACRO (Some_Macro2)\n"+\
"ENDMACRO()\n"+\
"\n"+\
"macrO\n"+\
" (SOME_MACRO3)\n"+\
"ENDMACRO()\n"+\
"\n"+\
"MACRO\n"+\
" (\n"+\
" SOME_MACRO4)\n"+\
"ENDMACRO()\n"+\
"\n"
cmakeCodeStrOut_expected = "\n"+\
"# Some macro we are defining\n"+\
"#\n"+\
"# Usage::\n"+\
"#\n"+\
"# some_macro(<some_args>)\n"+\
"#\n"+\
"macro(some_macro1 ARG1 ARG2)\n"+\
" #some_call()\n"+\
"endmacro()\n"+\
"\n"+\
"macro (some_macro2)\n"+\
"endmacro()\n"+\
"\n"+\
"macro\n"+\
" (some_macro3)\n"+\
"endmacro()\n"+\
"\n"+\
"macro\n"+\
" (\n"+\
" some_macro4)\n"+\
"endmacro()\n"+\
"\n"
cmakeCodeStrOut = LCC.makeCmndsLowerCaseInCMakeStr(cmakeCodeStrIn)
self.assertEqual(cmakeCodeStrOut, cmakeCodeStrOut_expected)

def test_function_def_1(self):
cmakeCodeStrIn = "\n"+\
"# Some function we are defining\n"+\
"#\n"+\
"# Usage::\n"+\
"#\n"+\
"# SOME_FUNCTION(<some_args>)\n"+\
"#\n"+\
"Function(Some_Function1 ARG1 ARG2)\n"+\
" #SOME_CALL()\n"+\
"EndFunction()\n"+\
"\n"+\
"FUNCTION (Some_Function2)\n"+\
"ENDFUNCTION()\n"+\
"\n"+\
"function\n"+\
" (SOME_FUNCTION3)\n"+\
"ENDFUNCTION()\n"+\
"\n"+\
"FUNCTION\n"+\
" (\n"+\
" SOME_FUNCTION4)\n"+\
"ENDFUNCTION()\n"+\
"\n"
cmakeCodeStrOut_expected = "\n"+\
"# Some function we are defining\n"+\
"#\n"+\
"# Usage::\n"+\
"#\n"+\
"# some_function(<some_args>)\n"+\
"#\n"+\
"function(some_function1 ARG1 ARG2)\n"+\
" #some_call()\n"+\
"endfunction()\n"+\
"\n"+\
"function (some_function2)\n"+\
"endfunction()\n"+\
"\n"+\
"function\n"+\
" (some_function3)\n"+\
"endfunction()\n"+\
"\n"+\
"function\n"+\
" (\n"+\
" some_function4)\n"+\
"endfunction()\n"+\
"\n"
cmakeCodeStrOut = LCC.makeCmndsLowerCaseInCMakeStr(cmakeCodeStrIn)
self.assertEqual(cmakeCodeStrOut, cmakeCodeStrOut_expected)

def test_no_match_logical_operators(self):
cmakeCodeStrIn = "\n"+\
"FUNCTION(SOME_FUNCTION)\n"+\
" IF ( (VAR1) AND (VAR2) )\n"+\
" IF ( (VAR1) OR (VAR2) )\n"+\
" IF ( (VAR1) AND NOT (VAR2) )\n"+\
"ENDFUNCTION()\n"+\
"\n"
cmakeCodeStrOut_expected = "\n"+\
"function(some_function)\n"+\
" if ( (VAR1) AND (VAR2) )\n"+\
" if ( (VAR1) OR (VAR2) )\n"+\
" if ( (VAR1) AND NOT (VAR2) )\n"+\
"endfunction()\n"+\
"\n"
cmakeCodeStrOut = LCC.makeCmndsLowerCaseInCMakeStr(cmakeCodeStrIn)
self.assertEqual(cmakeCodeStrOut, cmakeCodeStrOut_expected)


if __name__ == '__main__':
unittest.main()
119 changes: 119 additions & 0 deletions tribits/python_utils/lower_case_cmake.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import re


# Define regexes for matches

commandCallRegex = \
re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*[\s]*\(', re.DOTALL)
macroDefRegex = \
re.compile(r'[mM][aA][cC][rR][oO][\s]*\([\s]*[a-zA-Z_][a-zA-Z0-9_]*', re.DOTALL)
functionDefRegex = \
re.compile(r'[fF][uU][nN][cC][tT][iI][oO][nN][\s]*\([\s]*[a-zA-Z_][a-zA-Z0-9_]*',
re.DOTALL)
andLogicalRegex = re.compile(r'AND[\s]*\(', re.DOTALL)
orLogicalRegex = re.compile(r'OR[\s]*\(', re.DOTALL)
notLogicalRegex = re.compile(r'NOT[\s]*\(', re.DOTALL)


# Lower case CMake command calls and macro and function names.
#
def makeCmndsLowerCaseInCMakeStr(cmakeCodeStrIn):
cmakeCodeStrOut = cmakeCodeStrIn
cmakeCodeStrOut = makeRegexMatchesLowerCaseInCMakeStr(cmakeCodeStrOut,
commandCallRegex)
cmakeCodeStrOut = makeRegexMatchesLowerCaseInCMakeStr(cmakeCodeStrOut,
macroDefRegex)
cmakeCodeStrOut = makeRegexMatchesLowerCaseInCMakeStr(cmakeCodeStrOut,
functionDefRegex)
return cmakeCodeStrOut


# Make regex pattern matches lower cases.
#
def makeRegexMatchesLowerCaseInCMakeStr(cmakeCodeStrIn, regex):
cmakeCodeStrOut = ""
cmakeCodeStrInLen = len(cmakeCodeStrIn)
cmakeCodeStrStartSearchIdx = 0
while cmakeCodeStrStartSearchIdx < cmakeCodeStrInLen:
m = regex.search(cmakeCodeStrIn[cmakeCodeStrStartSearchIdx:])
if m:
# Get the substr for the match
cmakeCodeStrMatchStartIdx = cmakeCodeStrStartSearchIdx + m.start()
cmakeCodeStrMatchEndIdx = cmakeCodeStrStartSearchIdx + m.end()
commandCallMatchStr = \
cmakeCodeStrIn[cmakeCodeStrMatchStartIdx:cmakeCodeStrMatchEndIdx]
assert m.group() == commandCallMatchStr
# Lower case the matching command call and update the output string
# since last match
cmakeCodeStrOut += \
cmakeCodeStrIn[cmakeCodeStrStartSearchIdx:cmakeCodeStrMatchStartIdx]
cmakeCodeStrOut += conditionalLowerCaseCMakeGroup(commandCallMatchStr)
# Update indexes for next search
cmakeCodeStrStartSearchIdx += m.end()
else:
# No more matches so copy the rest of the string
cmakeCodeStrOut += \
cmakeCodeStrIn[cmakeCodeStrStartSearchIdx:]
break

return cmakeCodeStrOut


def conditionalLowerCaseCMakeGroup(cmakeMatchGroup):
if andLogicalRegex.match(cmakeMatchGroup) \
or orLogicalRegex.match(cmakeMatchGroup) \
or notLogicalRegex.match(cmakeMatchGroup) \
:
return cmakeMatchGroup
return cmakeMatchGroup.lower()


#
# Helper functions for main()
#


usageHelp = r"""
Convert the cmake command calls to lower case and macro and function names
in defintions to lower case in a given file.
"""


def getCmndLineOptions():
from argparse import ArgumentParser, RawDescriptionHelpFormatter
clp = ArgumentParser(description=usageHelp,
formatter_class=RawDescriptionHelpFormatter)
clp.add_argument("file",
help="The file to lower-case the CMake commands within." )
options = clp.parse_args(sys.argv[1:])
return options


def validateCmndLineOptions(inOptions):
if not os.path.exists(inOptions.file):
print("Error, the file '"+inOptions.file+"' does not exist!")
sys.exit(1)


def lowerCaseCMakeCodeInFile(inOptions):
with open(inOptions.file, 'r') as fileHandle:
cmakeStrOrig = fileHandle.read()
cmakeStrLowerCased = makeCmndsLowerCaseInCMakeStr(cmakeStrOrig)
with open(inOptions.file, 'w') as fileHandle:
fileHandle.write(cmakeStrLowerCased)

#
# main()
#


if __name__ == '__main__':
inOptions = getCmndLineOptions()
validateCmndLineOptions(inOptions)
lowerCaseCMakeCodeInFile(inOptions)

0 comments on commit 277c40b

Please sign in to comment.