diff options
author | Arpit Gupta <guptarpit1997@gmail.com> | 2019-12-19 22:48:00 +0530 |
---|---|---|
committer | Marcus Müller <mmueller@gnuradio.org> | 2019-12-19 18:18:00 +0100 |
commit | 116f0401f54e4c8483952118c013b8c668eb3682 (patch) | |
tree | c4362ba8274ff68d78f8179603d3173481134775 /gr-utils/python/blocktool/core/comments.py | |
parent | f3dcc45afea4fafa84b0c0e861031105a67bbaf2 (diff) |
Block header parsing tool: GSoC 2019 (#2750)
* Add base.py file in cli module to import override Click functions
* Create cli and core base module for AST generation of header blocks
* Create basic CLI for blocktool with minimal support
* Add Sequence Completer to CLI and successful generation of AST
* CLI structure complete with parseheader command
* Basic core structure complete
* Add test script gr_blocktool to run the tool
* Add JSON schema and validation for parsed json output file
* Change properties and methods key to list in JSON schema
* Create an independent api from blocktool
* Bug fix for abslute path of the header files
* Create basic parser core api
* Parse the block header documentation
* Expose the core api, minor bug fixes
* Create the code pylint compatible
* Modify cli to accept file_path as an argument, parse default values of make function arguments
* Fix: Namespace parsing of block header file
* Parse the io_signature from the implementation file of the block header
* Create json file generator
* Add key-value io_signature and docstring in json schema, change sample generated json output
* Fix: squash an I/O parsing bug
* Change directory structure for blocktool tests
* Add Blocktool unittest
* Removed empty strings, make the code pylint compatible
* Use str.format() to get output
* Implement YAML generator
* Add a new CLI argument to parse a complete header directory
* Add Logger to log errors without raising exceptions
* Create output schema file in blocktool core
* Change directory structure of blocktool and cli commands
* write unittests for Blocktool Excceptions
* Add sample yaml files
* Simplify blocktool cli structure
* Refactor blocktool exception handling
* Split long blocktool unit-tests
* Parse message ports from the implementation file
* Add tests for parsed message port id, update sample json files
* Add blocktool subdirectory, files in CMakeLists.txt
* Remove test files to run Blocktool
* Fix: locates implementation file by traversing the module
* Integrate blocktool with modtool as an external plugin
* Create proper formatting of io_signature for yaml files
* Extend modtool makeyaml command to extend support for blocktool
* Remove external plugin for modtool support, add blocktool independent script
* Minor formatiing, change function name due to conflict with modtool function
* Add support to read and add blocktool special comments in header file
* Fix: Key Errors, Modify Documentation Reader
* Raise warning in case of conflict in the parsed information and blocktool comments
* Remove all the blocktool boilerplate cli code and provide minimal support
* Remove gr_blocktool script and use blocktool as a python module
* Major refactoring of the modtool cli structure to support the blocktool API
* Check for PyGCCXML dependency during build
* Add README.md for gr-blocktool and remove modtool cli warnings
Diffstat (limited to 'gr-utils/python/blocktool/core/comments.py')
-rw-r--r-- | gr-utils/python/blocktool/core/comments.py | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/gr-utils/python/blocktool/core/comments.py b/gr-utils/python/blocktool/core/comments.py new file mode 100644 index 0000000000..9938eca122 --- /dev/null +++ b/gr-utils/python/blocktool/core/comments.py @@ -0,0 +1,270 @@ +# +# Copyright 2019 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 read and add special blocktool comments in the public header """ + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + +import warnings + +from ..core import Constants + + +def strip_symbols(line): + """ + helper function to strip symbols + from blocktool comment syntax + """ + return line.split(':')[-1].lstrip().rstrip() + + +def exist_comments(self): + """ + function to check if blocktool special comments + already exist in the public header + """ + _comments = True + _index = None + lines = [] + with open(self.target_file, 'r') as header: + lines = header.readlines() + for line in lines: + if Constants.BLOCKTOOL in line: + _index = lines.index(line) + return bool(_index) + + +def validate_message_port(self, message_ports, suppress_input, suppress_output): + """ + function to solve conflicts if any in the + *message_port* comments and the implementation information + """ + if message_ports['input'] != self.parsed_data['message_port']['input']: + if not suppress_input: + warnings.warn( + 'Conflict in values input message port Id. Add ! at the start of the key-value line to mandatory use the comment value.') + self.parsed_data['message_port']['input'] = message_ports['input'] + if message_ports['output'] != self.parsed_data['message_port']['output']: + if not suppress_output: + warnings.warn( + 'Conflict in values output message port Id. Add ! at the start of the key-value line to mandatory use the comment value.') + self.parsed_data['message_port']['output'] = message_ports['output'] + + +def read_comments(self): + """ + function to read special blocktool comments + in the public header + """ + temp_parsed_data = {} + if self.parsed_data['io_signature'] or self.parsed_data['message_port']: + temp_parsed_data['io_signature'] = self.parsed_data['io_signature'] + temp_parsed_data['message_port'] = self.parsed_data['message_port'] + self.parsed_data['io_signature'] = { + "input": { + "signature": None + }, + "output": { + "signature": None + } + } + self.parsed_data['message_port'] = { + "input": [], + "output": [] + } + _suppress_input = False + _suppress_output = False + parsed_io = self.parsed_data['io_signature'] + message_port = self.parsed_data['message_port'] + special_comments = [] + _index = None + lines = [] + with open(self.target_file, 'r') as header: + lines = header.readlines() + for line in lines: + if Constants.BLOCKTOOL in line: + _index = lines.index(line) + + if _index is not None: + _index = _index+1 + for num in range(_index, len(lines)): + if Constants.END_BLOCKTOOL in lines[num]: + break + special_comments.append(lines[num]) + for comment in special_comments: + if Constants.INPUT_SIG in comment: + parsed_io['input']['signature'] = strip_symbols(comment) + if Constants.INPUT_MAX in comment: + parsed_io['input']['max_streams'] = strip_symbols(comment) + if Constants.INPUT_MIN in comment: + parsed_io['input']['min_streams'] = strip_symbols(comment) + if parsed_io['input']['signature'] is Constants.MAKE and not None: + if Constants.INPUT_MAKE_SIZE in comment: + parsed_io['input']['sizeof_stream_item'] = strip_symbols( + comment) + elif parsed_io['input']['signature'] is Constants.MAKE2 and not None: + if Constants.INPUT_MAKE_SIZE1 in comment: + parsed_io['input']['sizeof_stream_item1'] = strip_symbols( + comment) + if Constants.INPUT_MAKE_SIZE2 in comment: + parsed_io['input']['sizeof_stream_item2'] = strip_symbols( + comment) + elif parsed_io['input']['signature'] is Constants.MAKE3 and not None: + if Constants.INPUT_MAKE_SIZE1 in comment: + parsed_io['input']['sizeof_stream_item1'] = strip_symbols( + comment) + if Constants.INPUT_MAKE_SIZE2 in comment: + parsed_io['input']['sizeof_stream_item2'] = strip_symbols( + comment) + if Constants.INPUT_MAKE_SIZE3 in comment: + parsed_io['input']['sizeof_stream_item3'] = strip_symbols( + comment) + elif parsed_io['input']['signature'] is Constants.MAKEV and not None: + if Constants.INPUT_MAKEV_SIZE in comment: + parsed_io['input']['sizeof_stream_items'] = strip_symbols( + comment) + + if Constants.OUTPUT_SIG in comment: + parsed_io['output']['signature'] = strip_symbols(comment) + if Constants.OUTPUT_MAX in comment: + parsed_io['output']['max_streams'] = strip_symbols(comment) + if Constants.OUTPUT_MIN in comment: + parsed_io['output']['min_streams'] = strip_symbols(comment) + if parsed_io['output']['signature'] is Constants.MAKE and not None: + if Constants.OUTPUT_MAKE_SIZE in comment: + parsed_io['output']['sizeof_stream_item'] = strip_symbols( + comment) + elif parsed_io['output']['signature'] is Constants.MAKE2: + if Constants.OUTPUT_MAKE_SIZE1 in comment: + parsed_io['output']['sizeof_stream_item1'] = strip_symbols( + comment) + if Constants.OUTPUT_MAKE_SIZE2 in comment: + parsed_io['output']['sizeof_stream_item2'] = strip_symbols( + comment) + elif parsed_io['output']['signature'] is Constants.MAKE3 and not None: + if Constants.OUTPUT_MAKE_SIZE1 in comment: + parsed_io['output']['sizeof_stream_item1'] = strip_symbols( + comment) + if Constants.OUTPUT_MAKE_SIZE2 in comment: + parsed_io['output']['sizeof_stream_item2'] = strip_symbols( + comment) + if Constants.OUTPUT_MAKE_SIZE3 in comment: + parsed_io['output']['sizeof_stream_item3'] = strip_symbols( + comment) + elif parsed_io['output']['signature'] is Constants.MAKEV and not None: + if Constants.OUTPUT_MAKEV_SIZE in comment: + parsed_io['output']['sizeof_stream_items'] = strip_symbols( + comment) + + if Constants.INPUT_PORT in comment: + if Constants.EXCLAMATION in comment: + _suppress_input = True + if strip_symbols(comment): + message_port['input'] = strip_symbols(comment).split(', ') + if Constants.OUTPUT_PORT in comment: + if Constants.EXCLAMATION in comment: + _suppress_output = True + if strip_symbols(comment): + message_port['output'] = strip_symbols(comment).split(', ') + validate_message_port( + self, temp_parsed_data['message_port'], _suppress_input, _suppress_output) + self.parsed_data['io_signature'] = temp_parsed_data['io_signature'] + + +def add_comments(self): + """ + function to add special blocktool comments + in the public header + """ + _index = None + lines = [] + parsed_io = self.parsed_data['io_signature'] + message_port = self.parsed_data['message_port'] + with open(self.target_file, 'r') as header: + lines = header.readlines() + for line in lines: + if Constants.BLOCKTOOL in line: + _index = lines.index(line) + if _index is None: + with open(self.target_file, 'a') as header: + header.write('\n') + header.write('/* '+Constants.BLOCKTOOL + '\n') + header.write('input_signature: ' + + parsed_io['input']['signature'] + '\n') + header.write('input_min_streams: ' + + parsed_io['input']['min_streams'] + '\n') + header.write('input_max_streams: ' + + parsed_io['input']['max_streams'] + '\n') + if parsed_io['input']['signature'] is Constants.MAKE: + header.write('input_sizeof_stream_item: ' + + parsed_io['input']['sizeof_stream_item'] + '\n') + elif parsed_io['input']['signature'] is Constants.MAKE2: + header.write('input_sizeof_stream_item1: ' + + parsed_io['input']['sizeof_stream_item1'] + '\n') + header.write('input_sizeof_stream_item2: ' + + parsed_io['input']['sizeof_stream_item2'] + '\n') + elif parsed_io['input']['signature'] is Constants.MAKE3: + header.write('input_sizeof_stream_item1: ' + + parsed_io['input']['sizeof_stream_item1'] + '\n') + header.write('input_sizeof_stream_item2: ' + + parsed_io['input']['sizeof_stream_item2'] + '\n') + header.write('input_sizeof_stream_item3: ' + + parsed_io['input']['sizeof_stream_item3'] + '\n') + elif parsed_io['input']['signature'] is Constants.MAKEV: + header.write('input_sizeof_stream_item: ' + + parsed_io['input']['sizeof_stream_items'] + '\n') + header.write('output_signature: ' + + parsed_io['output']['signature'] + '\n') + header.write('output_min_streams: ' + + parsed_io['output']['min_streams'] + '\n') + header.write('output_max_streams: ' + + parsed_io['output']['max_streams'] + '\n') + if parsed_io['output']['signature'] is Constants.MAKE: + header.write('output_sizeof_stream_item: ' + + parsed_io['output']['sizeof_stream_item'] + '\n') + elif parsed_io['output']['signature'] is Constants.MAKE2: + header.write('output_sizeof_stream_item1: ' + + parsed_io['output']['sizeof_stream_item1'] + '\n') + header.write('output_sizeof_stream_item2: ' + + parsed_io['output']['sizeof_stream_item2'] + '\n') + elif parsed_io['output']['signature'] is Constants.MAKE3: + header.write('output_sizeof_stream_item1: ' + + parsed_io['output']['sizeof_stream_item1'] + '\n') + header.write('output_sizeof_stream_item2: ' + + parsed_io['output']['sizeof_stream_item2'] + '\n') + header.write('output_sizeof_stream_item3: ' + + parsed_io['output']['sizeof_stream_item3'] + '\n') + elif parsed_io['output']['signature'] is Constants.MAKEV: + header.write('output_sizeof_stream_item: ' + + parsed_io['output']['sizeof_stream_items'] + '\n') + + if message_port['input']: + header.write('message_input: ' + + ', '.join(message_port['input']) + '\n') + else: + header.write('message_input: ' + '\n') + if message_port['output']: + header.write('message_output: ' + + ', '.join(message_port['output']) + '\n') + else: + header.write('message_output: ' + '\n') + header.write(Constants.END_BLOCKTOOL + '*/' + '\n') |