1# 2# Copyright 2018 Free Software Foundation, Inc. 3# 4# This file is part of GNU Radio 5# 6# GNU Radio is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 3, or (at your option) 9# any later version. 10# 11# GNU Radio is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with GNU Radio; see the file COPYING. If not, write to 18# the Free Software Foundation, Inc., 51 Franklin Street, 19# Boston, MA 02110-1301, USA. 20# 21""" Module to convert XML bindings to YAML bindings """ 22 23from __future__ import print_function 24from __future__ import absolute_import 25from __future__ import unicode_literals 26 27import os 28import re 29import glob 30import logging 31 32from .base import ModTool, ModToolException 33from ..tools import get_modname 34 35logger = logging.getLogger(__name__) 36 37 38def get_xml_candidates(): 39 """ Returns a list of XML candidates for update """ 40 xml_candidates = [] 41 xml_files = [x for x in glob.glob1("grc", "*.xml")] 42 mod_name = get_modname() 43 for candidate in xml_files: 44 candidate = os.path.splitext(candidate)[0] 45 candidate = candidate.split(mod_name + "_", 1)[-1] 46 xml_candidates.append(candidate) 47 return xml_candidates 48 49 50class ModToolUpdate(ModTool): 51 """ Update the grc bindings for a block """ 52 name = 'update' 53 description = 'Update the grc bindings for a block' 54 55 def __init__(self, blockname=None, complete=False, **kwargs): 56 ModTool.__init__(self, blockname, **kwargs) 57 self.info['complete'] = complete 58 59 60 def validate(self): 61 """ Validates the arguments """ 62 ModTool._validate(self) 63 if self.info['complete']: 64 return 65 if not self.info['blockname'] or self.info['blockname'].isspace(): 66 raise ModToolException('Block name not specified!') 67 block_candidates = get_xml_candidates() 68 if self.info['blockname'] not in block_candidates: 69 choices = [x for x in block_candidates if self.info['blockname'] in x] 70 if len(choices) > 0: 71 print("Suggested alternatives: "+str(choices)) 72 raise ModToolException("The XML bindings does not exists!") 73 74 def run(self): 75 from gnuradio.grc.converter import Converter 76 if not self.cli: 77 self.validate() 78 logger.warning("Warning: This is an experimental feature. Please verify the bindings.") 79 module_name = self.info['modname'] 80 path = './grc/' 81 conv = Converter(path, path) 82 if self.info['complete']: 83 blocks = get_xml_candidates() 84 else: 85 blocks = [self.info['blockname']] 86 for blockname in blocks: 87 xml_file = "{}_{}.xml".format(module_name, blockname) 88 yml_file = "{}_{}.block.yml".format(module_name, blockname) 89 conv.load_block_xml(path+xml_file) 90 logger.info("Converted {} to {}".format(xml_file, yml_file)) 91 os.remove(path+xml_file) 92 nsubs = self._run_cmakelists(xml_file, yml_file) 93 if nsubs > 1: 94 logger.warning("Changed more than expected for the block '%s' in the CMakeLists.txt. " 95 "Please verify the CMakeLists manually.", blockname) 96 elif nsubs == 0: 97 logger.warning("No entry found for the block '%s' in the CMakeLists.txt. " 98 'Please verify the CMakeLists manually.', blockname) 99 else: 100 logger.info('Updated the CMakeLists.txt') 101 102 def _run_cmakelists(self, to_remove, to_add): 103 """ Changes in the CMakeLists """ 104 filename = './grc/CMakeLists.txt' 105 with open(filename) as f: 106 cfile = f.read() 107 (cfile, nsubs) = re.subn(to_remove, to_add, cfile) 108 with open(filename, 'w') as f: 109 f.write(cfile) 110 self.scm.mark_file_updated(filename) 111 return nsubs 112