From 055287896c8c97eb0cdda825559e217d8db54a14 Mon Sep 17 00:00:00 2001
From: Swapnil Negi <swapnil.negi09@gmail.com>
Date: Fri, 4 Jan 2019 18:29:50 +0100
Subject: 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.
---
 gr-utils/python/modtool/modtool_add.py | 367 ---------------------------------
 1 file changed, 367 deletions(-)
 delete mode 100644 gr-utils/python/modtool/modtool_add.py

(limited to 'gr-utils/python/modtool/modtool_add.py')

diff --git a/gr-utils/python/modtool/modtool_add.py b/gr-utils/python/modtool/modtool_add.py
deleted file mode 100644
index 9f128d2fde..0000000000
--- a/gr-utils/python/modtool/modtool_add.py
+++ /dev/null
@@ -1,367 +0,0 @@
-#
-# Copyright 2013, 2017-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 add new blocks """
-
-from __future__ import print_function
-from __future__ import absolute_import
-from __future__ import unicode_literals
-
-from builtins import input
-
-import os
-import re
-import getpass
-
-from .util_functions import append_re_line_sequence, ask_yes_no, SequenceCompleter
-from .cmakefile_editor import CMakeFileEditor
-from .modtool_base import ModTool, ModToolException
-from .templates import Templates
-from .code_generator import render_template
-
-class ModToolAdd(ModTool):
-    """ Add block to the out-of-tree module. """
-    name = 'add'
-    description = 'Add new block into module.'
-    _block_types = ('sink', 'source', 'sync', 'decimator', 'interpolator',
-                    'general', 'tagged_stream', 'hier', 'noblock')
-
-    def __init__(self):
-        ModTool.__init__(self)
-        self._add_cc_qa = False
-        self._add_py_qa = False
-        self._skip_cmakefiles = False
-        self._license_file = None
-
-    @staticmethod
-    def setup_parser(parser):
-        parser.add_argument("-t", "--block-type", choices=ModToolAdd._block_types,
-                help="One of %s." % ', '.join(ModToolAdd._block_types))
-        parser.add_argument("--license-file",
-                help="File containing the license header for every source code file.")
-        parser.add_argument("--copyright",
-                help="Name of the copyright holder (you or your company) MUST be a quoted string.")
-        parser.add_argument("--argument-list",
-                help="The argument list for the constructor and make functions.")
-        parser.add_argument("--add-python-qa", action="store_true", default=None,
-                help="If given, Python QA code is automatically added if possible.")
-        parser.add_argument("--add-cpp-qa", action="store_true", default=None,
-                help="If given, C++ QA code is automatically added if possible.")
-        parser.add_argument("--skip-cmakefiles", action="store_true",
-                help="If given, only source files are written, but CMakeLists.txt files are left unchanged.")
-        parser.add_argument("-l", "--lang", choices=('cpp', 'c++', 'python'),
-                help="Programing language")
-        ModTool.setup_parser_block(parser)
-        return parser
-
-    def setup(self, options):
-        ModTool.setup(self, options)
-
-        if self._info['blockname'] is None:
-            if len(options) >= 2:
-                self._info['blockname'] = options[1]
-            else:
-                self._info['blockname'] = input("Enter name of block/code (without module name prefix): ")
-        if os.path.isfile("./lib/"+self._info['blockname']+"_impl.cc") or os.path.isfile("./python/"+self._info['blockname']+".py"):
-            raise ModToolException('The given blockname already exists!')
-        if not re.match('[a-zA-Z0-9_]+', self._info['blockname']):
-            raise ModToolException('Invalid block name.')
-        print("Block/code identifier: " + self._info['blockname'])
-        self._info['fullblockname'] = self._info['modname'] + '_' + self._info['blockname']
-
-        self._info['blocktype'] = options.block_type
-        if self._info['blocktype'] is None:
-            # Print list out of blocktypes to user for reference
-            print(str(self._block_types))
-            with SequenceCompleter(sorted(self._block_types)):
-                while self._info['blocktype'] not in self._block_types:
-                    self._info['blocktype'] = input("Enter block type: ")
-                    if self._info['blocktype'] not in self._block_types:
-                        print('Must be one of ' + str(self._block_types))
-
-        # Allow user to specify language interactively if not set
-        self._info['lang'] = options.lang
-        if self._info['lang'] is None:
-            language_candidates = ('c++', 'cpp', 'python')
-            with SequenceCompleter(language_candidates):
-                while self._info['lang'] not in language_candidates:
-                    self._info['lang'] = input("Language (python/cpp): ")
-        if self._info['lang'] == 'c++':
-            self._info['lang'] = 'cpp'
-
-        print("Language: %s" % {'cpp': 'C++', 'python': 'Python'}[self._info['lang']])
-
-        if ((self._skip_subdirs['lib'] and self._info['lang'] == 'cpp')
-                or (self._skip_subdirs['python'] and self._info['lang'] == 'python')):
-            raise ModToolException('Missing or skipping relevant subdir.')
-
-        if self._info['blockname'] is None:
-            self._info['blockname'] = input("Enter name of block/code (without module name prefix): ")
-        if not re.match('[a-zA-Z0-9_]+', self._info['blockname']):
-            raise ModToolException('Invalid block name.')
-        print("Block/code identifier: " + self._info['blockname'])
-        self._info['fullblockname'] = self._info['modname'] + '_' + self._info['blockname']
-        if not options.license_file:
-            self._info['copyrightholder'] = options.copyright
-            if self._info['copyrightholder'] is None:
-                user = getpass.getuser()
-                git_user = self.scm.get_gituser()
-                if git_user:
-                    copyright_candidates = (user, git_user, 'GNU Radio')
-                else:
-                    copyright_candidates = (user, 'GNU Radio')
-                with SequenceCompleter(copyright_candidates):
-                    self._info['copyrightholder'] = input("Please specify the copyright holder: ")
-                    if not self._info['copyrightholder'] or self._info['copyrightholder'].isspace():
-                        self._info['copyrightholder'] = "gr-"+self._info['modname']+" author"
-            elif self._info['is_component']:
-                print("For GNU Radio components the FSF is added as copyright holder")
-        self._license_file = options.license_file
-        self._info['license'] = self.setup_choose_license()
-        if options.argument_list is not None:
-            self._info['arglist'] = options.argument_list
-        else:
-            self._info['arglist'] = input('Enter valid argument list, including default arguments: ')
-
-        if not (self._info['blocktype'] in ('noblock') or self._skip_subdirs['python']):
-            self._add_py_qa = options.add_python_qa
-            if self._add_py_qa is None:
-                self._add_py_qa = ask_yes_no('Add Python QA code?', True)
-        if self._info['lang'] == 'cpp':
-            self._add_cc_qa = options.add_cpp_qa
-            if self._add_cc_qa is None:
-                self._add_cc_qa = ask_yes_no('Add C++ QA code?', not self._add_py_qa)
-        self._skip_cmakefiles = options.skip_cmakefiles
-        if self._info['version'] == 'autofoo' and not self._skip_cmakefiles:
-            print("Warning: Autotools modules are not supported. ",
-                  "Files will be created, but Makefiles will not be edited.")
-            self._skip_cmakefiles = True
-
-    def setup_choose_license(self):
-        """ Select a license by the following rules, in this order:
-        1) The contents of the file given by --license-file
-        2) The contents of the file LICENSE or LICENCE in the modules
-           top directory
-        3) The default license. """
-        if self._license_file is not None \
-            and os.path.isfile(self._license_file):
-            return open(self._license_file).read()
-        elif os.path.isfile('LICENSE'):
-            return open('LICENSE').read()
-        elif os.path.isfile('LICENCE'):
-            return open('LICENCE').read()
-        elif self._info['is_component']:
-            return Templates['grlicense']
-        else:
-            return Templates['defaultlicense'].format(**self._info)
-
-    def _write_tpl(self, tpl, path, fname):
-        """ Shorthand for writing a substituted template to a file"""
-        path_to_file = os.path.join(path, fname)
-        print("Adding file '%s'..." % path_to_file)
-        open(path_to_file, 'w').write(render_template(tpl, **self._info))
-        self.scm.add_files((path_to_file,))
-
-    def run(self, options):
-        """ Go, go, go. """
-        self.setup(options)
-        has_swig = (
-            self._info['lang'] == 'cpp'
-            and not self._skip_subdirs['swig']
-        )
-        has_grc = False
-        if self._info['lang'] == 'cpp':
-            self._run_lib()
-            has_grc = has_swig
-        else: # Python
-            self._run_python()
-            if self._info['blocktype'] != 'noblock':
-                has_grc = True
-        if has_swig:
-            self._run_swig()
-        if self._add_py_qa:
-            self._run_python_qa()
-        if has_grc and not self._skip_subdirs['grc']:
-            self._run_grc()
-
-    def _run_lib(self):
-        """ Do everything that needs doing in the subdir 'lib' and 'include'.
-        - add .cc and .h files
-        - include them into CMakeLists.txt
-        - check if C++ QA code is req'd
-        - if yes, create qa_*.{cc,h} and add them to CMakeLists.txt
-        """
-        def _add_qa():
-            " Add C++ QA files for 3.7 API "
-            fname_qa_h = 'qa_%s.h' % self._info['blockname']
-            fname_qa_cc = 'qa_%s.cc' % self._info['blockname']
-            self._write_tpl('qa_cpp', 'lib', fname_qa_cc)
-            self._write_tpl('qa_h', 'lib', fname_qa_h)
-            if not self._skip_cmakefiles:
-                try:
-                    append_re_line_sequence(self._file['cmlib'],
-                                            r'\$\{CMAKE_CURRENT_SOURCE_DIR\}/qa_%s.cc.*\n' % self._info['modname'],
-                                            '    ${CMAKE_CURRENT_SOURCE_DIR}/qa_%s.cc' % self._info['blockname'])
-                    append_re_line_sequence(self._file['qalib'],
-                                            '#include.*\n',
-                                            '#include "%s"' % fname_qa_h)
-                    append_re_line_sequence(self._file['qalib'],
-                                            '(addTest.*suite.*\n|new CppUnit.*TestSuite.*\n)',
-                                            '  s->addTest(gr::%s::qa_%s::suite());' % (self._info['modname'],
-                                                                                       self._info['blockname'])
-                                           )
-                    self.scm.mark_files_updated((self._file['qalib'],))
-                except IOError:
-                    print("Can't add C++ QA files.")
-        def _add_qa_boostutf():
-            " Add C++ QA files for 3.8 API "
-            fname_qa_cc = 'qa_%s.cc' % self._info['blockname']
-            self._write_tpl('qa_cpp_boostutf', 'lib', fname_qa_cc)
-            if not self._skip_cmakefiles:
-                try:
-                    ed = CMakeFileEditor(self._file['cmlib'])
-                    cmake_list_var = \
-                        'test_{}_source'.format(self._info['modname'])
-                    if not ed.append_value(
-                            'list',
-                            fname_qa_cc,
-                            to_ignore_start='APPEND ' + cmake_list_var):
-                        print("Couldn't add C++ QA files.")
-                    ed.write()
-                    self.scm.mark_files_updated((self._file['cmlib'],))
-                except IOError:
-                    print("Can't add C++ QA files.")
-        fname_cc = None
-        fname_h = None
-        if self._info['version'] in ('37', '38'):
-            fname_h = self._info['blockname'] + '.h'
-            fname_cc = self._info['blockname'] + '.cc'
-            if self._info['blocktype'] in ('source', 'sink', 'sync', 'decimator',
-                                           'interpolator', 'general', 'hier', 'tagged_stream'):
-                fname_cc = self._info['blockname'] + '_impl.cc'
-                self._write_tpl('block_impl_h', 'lib', self._info['blockname'] + '_impl.h')
-            self._write_tpl('block_impl_cpp', 'lib', fname_cc)
-            self._write_tpl('block_def_h', self._info['includedir'], fname_h)
-        else: # Pre-3.7 or autotools
-            fname_h = self._info['fullblockname'] + '.h'
-            fname_cc = self._info['fullblockname'] + '.cc'
-            self._write_tpl('block_h36', self._info['includedir'], fname_h)
-            self._write_tpl('block_cpp36', 'lib', fname_cc)
-        if self._add_cc_qa:
-            if self._info['version'] == '37':
-                _add_qa()
-            if self._info['version'] == '38':
-                _add_qa_boostutf()
-            elif self._info['version'] == '36':
-                print("Warning: C++ QA files not supported for 3.6-style OOTs.")
-            elif self._info['version'] == 'autofoo':
-                print("Warning: C++ QA files not supported for autotools.")
-        if not self._skip_cmakefiles:
-            ed = CMakeFileEditor(self._file['cmlib'])
-            cmake_list_var = '[a-z]*_?' + self._info['modname'] + '_sources'
-            if not ed.append_value('list', fname_cc, to_ignore_start='APPEND ' + cmake_list_var):
-                ed.append_value('add_library', fname_cc)
-            ed.write()
-            ed = CMakeFileEditor(self._file['cminclude'])
-            ed.append_value('install', fname_h, to_ignore_end='DESTINATION[^()]+')
-            ed.write()
-            self.scm.mark_files_updated((self._file['cminclude'], self._file['cmlib']))
-
-    def _run_swig(self):
-        """ Do everything that needs doing in the subdir 'swig'.
-        - Edit main *.i file
-        """
-        if self._get_mainswigfile() is None:
-            print('Warning: No main swig file found.')
-            return
-        print("Editing %s..." % self._file['swig'])
-        mod_block_sep = '/'
-        if self._info['version'] == '36':
-            mod_block_sep = '_'
-        swig_block_magic_str = render_template('swig_block_magic', **self._info)
-        open(self._file['swig'], 'a').write(swig_block_magic_str)
-        include_str = '#include "%s%s%s.h"' % (
-            {True: 'gnuradio/' + self._info['modname'],
-             False: self._info['modname']}[self._info['is_component']],
-            mod_block_sep,
-            self._info['blockname'])
-        if re.search('#include', open(self._file['swig'], 'r').read()):
-            append_re_line_sequence(self._file['swig'], '^#include.*\n', include_str)
-        else: # I.e., if the swig file is empty
-            oldfile = open(self._file['swig'], 'r').read()
-            regexp = re.compile(r'^%\{\n', re.MULTILINE)
-            oldfile = regexp.sub('%%{\n%s\n' % include_str, oldfile, count=1)
-            open(self._file['swig'], 'w').write(oldfile)
-        self.scm.mark_files_updated((self._file['swig'],))
-
-    def _run_python_qa(self):
-        """ Do everything that needs doing in the subdir 'python' to add
-        QA code.
-        - add .py files
-        - include in CMakeLists.txt
-        """
-        fname_py_qa = 'qa_' + self._info['blockname'] + '.py'
-        self._write_tpl('qa_python', self._info['pydir'], fname_py_qa)
-        os.chmod(os.path.join(self._info['pydir'], fname_py_qa), 0o755)
-        self.scm.mark_files_updated((os.path.join(self._info['pydir'], fname_py_qa),))
-        if self._skip_cmakefiles or CMakeFileEditor(self._file['cmpython']).check_for_glob('qa_*.py'):
-            return
-        print("Editing %s/CMakeLists.txt..." % self._info['pydir'])
-        open(self._file['cmpython'], 'a').write(
-            'GR_ADD_TEST(qa_%s ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/%s)\n' % \
-                (self._info['blockname'], fname_py_qa))
-        self.scm.mark_files_updated((self._file['cmpython'],))
-
-    def _run_python(self):
-        """ Do everything that needs doing in the subdir 'python' to add
-        a Python block.
-        - add .py file
-        - include in CMakeLists.txt
-        - include in __init__.py
-        """
-        fname_py = self._info['blockname'] + '.py'
-        self._write_tpl('block_python', self._info['pydir'], fname_py)
-        append_re_line_sequence(self._file['pyinit'],
-                                '(^from.*import.*\n|# import any pure.*\n)',
-                                'from %s import %s' % (self._info['blockname'],
-                                                       self._info['blockname']))
-        self.scm.mark_files_updated((self._file['pyinit'],))
-        if self._skip_cmakefiles:
-            return
-        ed = CMakeFileEditor(self._file['cmpython'])
-        ed.append_value('GR_PYTHON_INSTALL', fname_py, to_ignore_end='DESTINATION[^()]+')
-        ed.write()
-        self.scm.mark_files_updated((self._file['cmpython'],))
-
-    def _run_grc(self):
-        """ Do everything that needs doing in the subdir 'grc' to add
-        a GRC bindings XML file.
-        - add .xml file
-        - include in CMakeLists.txt
-        """
-        fname_grc = self._info['fullblockname'] + '.xml'
-        self._write_tpl('grc_xml', 'grc', fname_grc)
-        ed = CMakeFileEditor(self._file['cmgrc'], '\n    ')
-        if self._skip_cmakefiles or ed.check_for_glob('*.xml'):
-            return
-        print("Editing grc/CMakeLists.txt...")
-        ed.append_value('install', fname_grc, to_ignore_end='DESTINATION[^()]+')
-        ed.write()
-        self.scm.mark_files_updated((self._file['cmgrc'],))
-- 
cgit v1.2.3