summaryrefslogtreecommitdiff
path: root/gr-utils/python/blocktool/core/comments.py
diff options
context:
space:
mode:
authorArpit Gupta <guptarpit1997@gmail.com>2019-12-19 22:48:00 +0530
committerMarcus Müller <mmueller@gnuradio.org>2019-12-19 18:18:00 +0100
commit116f0401f54e4c8483952118c013b8c668eb3682 (patch)
treec4362ba8274ff68d78f8179603d3173481134775 /gr-utils/python/blocktool/core/comments.py
parentf3dcc45afea4fafa84b0c0e861031105a67bbaf2 (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.py270
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')