# # Copyright 2018 Free Software Foundation, Inc. # # This file is part of GNU Radio # # SPDX-License-Identifier: GPL-3.0-or-later # # """ Module to add new blocks """ from __future__ import print_function from __future__ import absolute_import from __future__ import unicode_literals import os import re import getpass import click from ..core import ModToolAdd from ..tools import SequenceCompleter, ask_yes_no from .base import common_params, block_name, run, cli_input, ModToolException @click.command('add') @click.option('-t', '--block-type', type=click.Choice(ModToolAdd.block_types), help=f"One of {', '.join(ModToolAdd.block_types)}.") @click.option('--license-file', help="File containing the license header for every source code file.") @click.option('--copyright', help="Name of the copyright holder (you or your company) MUST be a quoted string.") @click.option('--argument-list', default="", help="The argument list for the constructor and make functions.") @click.option('--add-python-qa', is_flag=True, default=None, help="If given, Python QA code is automatically added if possible.") @click.option('--add-cpp-qa', is_flag=True, default=None, help="If given, C++ QA code is automatically added if possible.") @click.option('--skip-cmakefiles', is_flag=True, help="If given, only source files are written, but CMakeLists.txt files are left unchanged.") @click.option('-l', '--lang', type=click.Choice(ModToolAdd.language_candidates), help="Programming Language") @common_params @block_name def cli(**kwargs): """Adds a block to the out-of-tree module.""" kwargs['cli'] = True self = ModToolAdd(**kwargs) click.secho("GNU Radio module name identified: " + self.info['modname'], fg='green') get_blocktype(self) get_lang(self) info_lang = {'cpp': 'C++', 'python': 'Python'}[self.info['lang']] click.secho(f"Language: {info_lang}", fg='green') 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.') get_blockname(self) click.secho("Block/code identifier: " + self.info['blockname'], fg='green') self.info['fullblockname'] = self.info['modname'] + '_' + self.info['blockname'] if not self.license_file: get_copyrightholder(self) self.info['license'] = self.setup_choose_license() get_arglist(self) get_py_qa(self) get_cpp_qa(self) if self.info['version'] == 'autofoo' and not self.skip_cmakefiles: click.secho("Warning: Autotools modules are not supported. "+ "Files will be created, but Makefiles will not be edited.", fg='yellow') self.skip_cmakefiles = True run(self) def get_blocktype(self): """ Get the blocktype of the block to be added """ if self.info['blocktype'] is None: click.secho(str(self.block_types), fg='yellow') with SequenceCompleter(self.block_types): while self.info['blocktype'] not in self.block_types: self.info['blocktype'] = cli_input("Enter block type: ") if self.info['blocktype'] not in self.block_types: click.secho('Must be one of ' + str(self.block_types), fg='yellow') def get_lang(self): """ Get the Programming Language of the block to be added """ if self.info['lang'] is None: with SequenceCompleter(self.language_candidates): while self.info['lang'] not in self.language_candidates: self.info['lang'] = cli_input("Language (python/cpp): ") if self.info['lang'] == 'c++': self.info['lang'] = 'cpp' def get_blockname(self): """ Get the blockname""" if not self.info['blockname'] or self.info['blockname'].isspace(): while not self.info['blockname'] or self.info['blockname'].isspace(): self.info['blockname'] = cli_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.') for block in os.scandir('./grc/'): if block.is_file(): s = block.name present_block = self.info['modname'] + "_" + self.info['blockname'] + ".block.yml" if s == present_block: raise ModToolException('Block Already Present.') def get_copyrightholder(self): """ Get the copyrightholder of the block to be added """ if not self.info['copyrightholder'] or self.info['copyrightholder'].isspace(): 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'] = cli_input("Please specify the copyright holder: ") if not self.info['copyrightholder'] or self.info['copyrightholder'].isspace(): self.info['copyrightholder'] = f'gr-{self.info["modname"]} author' elif self.info['is_component']: click.secho("For GNU Radio components the FSF is added as copyright holder", fg='cyan') def get_arglist(self): """ Get the argument list of the block to be added """ if self.info['arglist'] is not None: self.info['arglist'] = click.prompt(click.style( 'Enter valid argument list, including default arguments: \n', fg='cyan'), prompt_suffix='', default='', show_default=False) def get_py_qa(self): """ Get a boolean value for addition of py_qa """ if self.add_py_qa is None: if not (self.info['blocktype'] in ('noblock') or self.skip_subdirs['python']): self.add_py_qa = ask_yes_no(click.style('Add Python QA code?', fg='cyan'), True) else: self.add_py_qa = False def get_cpp_qa(self): """ Get a boolean value for addition of cpp_qa """ if self.add_cc_qa is None: if self.info['lang'] == 'cpp': self.add_cc_qa = ask_yes_no(click.style('Add C++ QA code?', fg='cyan'), not self.add_py_qa) else: self.add_cc_qa = False