summaryrefslogtreecommitdiff
path: root/gr-utils/python/modtool/core/rename.py
diff options
context:
space:
mode:
authorSwapnil Negi <swapnil.negi09@gmail.com>2019-01-04 18:29:50 +0100
committerAndrej Rode <mail@andrejro.de>2019-01-04 18:58:02 +0100
commit055287896c8c97eb0cdda825559e217d8db54a14 (patch)
tree613262f5ed45ba4eaadf1bd76009aa16ad22806f /gr-utils/python/modtool/core/rename.py
parent2fcf3b8afe51092003b7f916edb9e5d6372d4842 (diff)
modtool: gr-modtool overhaul GSoC 2018
This commit contains all the changes done during the 2018 GSoC "gr-modtool overhaul". Changes include: - Rewrite of gr-modtool based on Python Click - Split of gr-modtool in cli and core - Adherence to new GNU Radio 3.8 API for OOTs - Pylint improvements - Py3k and Py2k compatibility This feature is merged in a squash-merge due to big refactoring on the head and base branch and the impossibility to unclutter both.
Diffstat (limited to 'gr-utils/python/modtool/core/rename.py')
-rw-r--r--gr-utils/python/modtool/core/rename.py201
1 files changed, 201 insertions, 0 deletions
diff --git a/gr-utils/python/modtool/core/rename.py b/gr-utils/python/modtool/core/rename.py
new file mode 100644
index 0000000000..8eec0ee8ec
--- /dev/null
+++ b/gr-utils/python/modtool/core/rename.py
@@ -0,0 +1,201 @@
+#
+# Copyright 2014, 2018 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio 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 3, or (at your option)
+# any later version.
+#
+# GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+""" Module to rename blocks """
+
+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import unicode_literals
+
+import os
+import re
+import logging
+
+from .base import get_block_candidates, ModTool, ModToolException
+
+logger = logging.getLogger(__name__)
+
+def get_block_candidates():
+ cpp_filters = ["*.cc", "*.cpp"]
+ cpp_blocks = []
+ for ftr in cpp_filters:
+ cpp_blocks += filter(lambda x: not (x.startswith('qa_') or
+ x.startswith('test_')),
+ glob.glob1("lib", ftr))
+ python_blocks = filter(lambda x: not (x.startswith('qa_') or
+ x.startswith('build') or
+ x.startswith('__init__')),
+ glob.glob1("python", "*.py"))
+ block_candidates = [x.split('_impl')[0] for x in cpp_blocks] + [x.split('.')[0] for x in python_blocks]
+ return block_candidates
+
+
+class ModToolRename(ModTool):
+ """ Rename a block in the out-of-tree module. """
+ name = 'rename'
+ description = 'Rename a block inside a module.'
+
+ def __init__(self, blockname=None, new_name=None, **kwargs):
+ ModTool.__init__(self, blockname, **kwargs)
+ self.info['oldname'] = blockname
+ self.info['newname'] = new_name
+
+ def validate(self):
+ """ Validates the arguments """
+ ModTool._validate(self)
+ if not self.info['oldname']:
+ raise ModToolException('Old block name (blockname) not specified.')
+ if not re.match('[a-zA-Z0-9_]+', self.info['oldname']):
+ raise ModToolException('Invalid block name.')
+ block_candidates = get_block_candidates()
+ if self.info['oldname'] not in block_candidates:
+ choices = [x for x in block_candidates if self.info['oldname'] in x]
+ if len(choices)>0:
+ print("Suggested alternatives: "+str(choices))
+ raise ModToolException("Blockname for renaming does not exists!")
+ if not self.info['newname']:
+ raise ModToolException('New blockname (new_name) not specified.')
+ if not re.match('[a-zA-Z0-9_]+', self.info['newname']):
+ raise ModToolException('Invalid new block name.')
+
+ def assign(self):
+ self.info['fullnewname'] = self.info['modname'] + '_' + self.info['newname']
+
+ def run(self):
+ """ Go, go, go. """
+ # This portion will be covered by the CLI
+ if not self.cli:
+ self.validate()
+ self.assign()
+ module = self.info['modname']
+ oldname = self.info['oldname']
+ newname = self.info['newname']
+ logger.info("In module '{}' rename block '{}' to '{}'".format(module, oldname, newname))
+ self._run_swig_rename(self._file['swig'], oldname, newname)
+ self._run_grc_rename(self.info['modname'], oldname, newname)
+ self._run_python_qa(self.info['modname'], oldname, newname)
+ self._run_python(self.info['modname'], oldname, newname)
+ self._run_lib(self.info['modname'], oldname, newname)
+ self._run_include(self.info['modname'], oldname, newname)
+ return
+
+ def _run_swig_rename(self, swigfilename, old, new):
+ """ Rename SWIG includes and block_magic """
+ nsubs = self._run_file_replace(swigfilename, old, new)
+ if nsubs < 1:
+ logger.info("Couldn't find '{}' in file '{}'.".format(old, swigfilename))
+ if nsubs == 2:
+ logger.info("Changing 'noblock' type file")
+ if nsubs > 3:
+ logger.warning("Hm, changed more then expected while editing {}.".format(swigfilename))
+ return False
+
+ def _run_lib(self, module, old, new):
+ ccfile = './lib/' + old + '_impl.cc'
+ if not os.path.isfile(ccfile): # in case it is a 'noblock'
+ ccfile = './lib/' + old + '.cc'
+ hfile = './lib/' + old + '_impl.h'
+ self._run_file_replace(ccfile, old, new)
+ self._run_file_replace(hfile, old, new)
+ self._run_file_replace(hfile, old.upper(), new.upper()) # take care of include guards
+ self._run_cmakelists('./lib/', old, new)
+ self._run_file_rename('./lib/', old, new)
+ self._run_cpp_qa(module, old, new)
+
+ def _run_cpp_qa(self, module, old, new):
+ path = './lib/'
+ filename = 'qa_' + module + '.cc'
+ nsubs = self._run_file_replace(path + filename, old, new)
+ if nsubs > 0:
+ logger.info("C++ QA code detected, renaming...")
+ filename = 'qa_' + old + '.cc'
+ self._run_file_replace(path + filename, old, new)
+ filename = 'qa_' + old + '.h'
+ self._run_file_replace(path + filename, old, new)
+ self._run_file_replace(path + filename, old.upper(), new.upper())
+ self._run_file_rename(path, 'qa_' + old, 'qa_' + new)
+ else:
+ logger.info("No C++ QA code detected, skipping...")
+
+ def _run_include(self, module, old, new):
+ path = './include/' + module + '/'
+ filename = path + old + '.h'
+ self._run_file_replace(filename, old, new)
+ self._run_file_replace(filename, old.upper(), new.upper()) # take care of include guards
+ self._run_cmakelists(path, old, new)
+ self._run_file_rename(path, old, new)
+
+ def _run_python(self, module, old, new):
+ path = './python/'
+ filename = '__init__.py'
+ nsubs = self._run_file_replace(path + filename, old, new)
+ if nsubs > 0:
+ logger.info("Python block detected, renaming...")
+ filename = old + '.py'
+ self._run_file_replace(path + filename, old, new)
+ self._run_cmakelists(path, old, new)
+ self._run_file_rename(path, old, new)
+ else:
+ logger.info("Not a Python block, nothing to do here...")
+
+ def _run_python_qa(self, module, old, new):
+ new = 'qa_' + new
+ old = 'qa_' + old
+ filename = './python/' + old + '.py'
+ self._run_file_replace(filename, old, new)
+ self._run_cmakelists('./python/', old, new)
+ self._run_file_rename('./python/', old, new)
+
+ def _run_grc_rename(self, module, old, new):
+ grcfile = './grc/' + module + '_' + old + '.yml'
+ self._run_file_replace(grcfile, old, new)
+ self._run_cmakelists('./grc/', old, new)
+ self._run_file_rename('./grc/', module + '_' + old, module + '_' + new)
+
+ def _run_cmakelists(self, path, first, second):
+ filename = path + 'CMakeLists.txt'
+ nsubs = self._run_file_replace(filename, first, second)
+ if nsubs < 1:
+ logger.info("'{}' wasn't in '{}'.".format(first, filename))
+
+ def _run_file_rename(self, path, old, new):
+ files = os.listdir(path)
+ for file in files:
+ if file.find(old) > -1 and file.find(old) < 3:
+ nl = file.replace(old, new)
+ src = path + file
+ dst = path + nl
+ logger.info("Renaming file '{}' to '{}'.".format(src, dst))
+ os.rename(src, dst)
+
+ def _run_file_replace(self, filename, old, new):
+ if not os.path.isfile(filename):
+ return False
+ else:
+ logger.info("In '{}' renaming occurences of '{}' to '{}'".format(filename, old, new))
+
+ with open(filename) as f:
+ cfile = f.read()
+ (cfile, nsubs) = re.subn(old, new, cfile)
+
+ with open(filename, 'w') as f:
+ f.write(cfile)
+ self.scm.mark_file_updated(filename)
+ return nsubs