summaryrefslogtreecommitdiff
path: root/gr-utils/python/modtool/tools
diff options
context:
space:
mode:
Diffstat (limited to 'gr-utils/python/modtool/tools')
-rw-r--r--gr-utils/python/modtool/tools/CMakeLists.txt19
-rw-r--r--gr-utils/python/modtool/tools/__init__.py19
-rw-r--r--gr-utils/python/modtool/tools/cmakefile_editor.py140
-rw-r--r--gr-utils/python/modtool/tools/code_generator.py52
-rw-r--r--gr-utils/python/modtool/tools/grc_yaml_generator.py129
-rw-r--r--gr-utils/python/modtool/tools/parser_cc_block.py223
-rw-r--r--gr-utils/python/modtool/tools/scm.py223
-rw-r--r--gr-utils/python/modtool/tools/util_functions.py167
8 files changed, 0 insertions, 972 deletions
diff --git a/gr-utils/python/modtool/tools/CMakeLists.txt b/gr-utils/python/modtool/tools/CMakeLists.txt
deleted file mode 100644
index 8248bb3e7d..0000000000
--- a/gr-utils/python/modtool/tools/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2018 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-
-include(GrPython)
-
-GR_PYTHON_INSTALL(FILES
- __init__.py
- cmakefile_editor.py
- code_generator.py
- grc_yaml_generator.py
- parser_cc_block.py
- scm.py
- util_functions.py
- DESTINATION ${GR_PYTHON_DIR}/gnuradio/modtool/tools
-)
diff --git a/gr-utils/python/modtool/tools/__init__.py b/gr-utils/python/modtool/tools/__init__.py
deleted file mode 100644
index 55a55fd166..0000000000
--- a/gr-utils/python/modtool/tools/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# Copyright 2018 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-#
-
-from __future__ import print_function
-from __future__ import absolute_import
-from __future__ import unicode_literals
-
-from .cmakefile_editor import CMakeFileEditor
-from .code_generator import render_template
-from .grc_yaml_generator import GRCYAMLGenerator
-from .parser_cc_block import ParserCCBlock
-from .scm import SCMRepoFactory
-from .util_functions import * \ No newline at end of file
diff --git a/gr-utils/python/modtool/tools/cmakefile_editor.py b/gr-utils/python/modtool/tools/cmakefile_editor.py
deleted file mode 100644
index 29f9c3eb09..0000000000
--- a/gr-utils/python/modtool/tools/cmakefile_editor.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#
-# Copyright 2013, 2018 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-#
-""" Edit CMakeLists.txt files """
-
-from __future__ import print_function
-from __future__ import absolute_import
-from __future__ import unicode_literals
-
-import re
-import logging
-
-logger = logging.getLogger(__name__)
-
-
-class CMakeFileEditor(object):
- """A tool for editing CMakeLists.txt files. """
- def __init__(self, filename, separator='\n ', indent=' '):
- self.filename = filename
- with open(filename, 'r') as f:
- self.cfile = f.read()
- self.separator = separator
- self.indent = indent
-
- def append_value(self, entry, value, to_ignore_start='', to_ignore_end=''):
- """ Add a value to an entry. """
- regexp = re.compile(r'({}\({}[^()]*?)\s*?(\s?{})\)'.format(entry, to_ignore_start, to_ignore_end),
- re.MULTILINE)
- substi = r'\1' + self.separator + value + r'\2)'
- (self.cfile, nsubs) = regexp.subn(substi, self.cfile, count=1)
- return nsubs
-
- def remove_value(self, entry, value, to_ignore_start='', to_ignore_end=''):
- """
- Remove a value from an entry.
- Example: You want to remove file.cc from this list() entry:
- list(SOURCES
- file.cc
- other_file.cc
- )
-
- Then run:
- >>> C.remove_value('list', 'file.cc', 'SOURCES')
-
- Returns the number of occurrences of entry in the current file
- that were removed.
- """
- # In the case of the example above, these are cases we need to catch:
- # - list(file.cc ...
- # entry is right after the value parentheses, no whitespace. Can only happen
- # when to_ignore_start is empty.
- # - list(... file.cc)
- # Other entries come first, then entry is preceded by whitespace.
- # - list(SOURCES ... file.cc) # whitespace!
- # When to_ignore_start is not empty, entry must always be preceded by whitespace.
- if len(to_ignore_start) == 0:
- regexp = r'^\s*({entry}\((?:[^()]*?\s+|)){value}\s*([^()]*{to_ignore_end}\s*\)){to_ignore_start}'
- else:
- regexp = r'^\s*({entry}\(\s*{to_ignore_start}[^()]*?\s+){value}\s*([^()]*{to_ignore_end}\s*\))'
- regexp = regexp.format(
- entry=entry,
- to_ignore_start=to_ignore_start,
- value=value,
- to_ignore_end=to_ignore_end,
- )
- regexp = re.compile(regexp, re.MULTILINE)
- (self.cfile, nsubs) = re.subn(regexp, r'\1\2', self.cfile, count=1)
- return nsubs
-
- def delete_entry(self, entry, value_pattern=''):
- """Remove an entry from the current buffer."""
- regexp = r'{}\s*\([^()]*{}[^()]*\)[^\n]*\n'.format(entry, value_pattern)
- regexp = re.compile(regexp, re.MULTILINE)
- (self.cfile, nsubs) = re.subn(regexp, '', self.cfile, count=1)
- return nsubs
-
- def write(self):
- """ Write the changes back to the file. """
- with open(self.filename, 'w') as f:
- f.write(self.cfile)
-
- def remove_double_newlines(self):
- """Simply clear double newlines from the file buffer."""
- self.cfile = re.compile('\n\n\n+', re.MULTILINE).sub('\n\n', self.cfile)
-
- def find_filenames_match(self, regex):
- """ Find the filenames that match a certain regex
- on lines that aren't comments """
- filenames = []
- reg = re.compile(regex)
- fname_re = re.compile(r'[a-zA-Z]\w+\.\w{1,5}$')
- for line in self.cfile.splitlines():
- if len(line.strip()) == 0 or line.strip()[0] == '#':
- continue
- for word in re.split('[ /)(\t\n\r\f\v]', line):
- if fname_re.match(word) and reg.search(word):
- filenames.append(word)
- return filenames
-
- def disable_file(self, fname):
- """ Comment out a file.
- Example:
- add_library(
- file1.cc
- )
-
- Here, file1.cc becomes #file1.cc with disable_file('file1.cc').
- """
- starts_line = False
- for line in self.cfile.splitlines():
- if len(line.strip()) == 0 or line.strip()[0] == '#':
- continue
- if re.search(r'\b'+fname+r'\b', line):
- if re.match(fname, line.lstrip()):
- starts_line = True
- break
- comment_out_re = r'#\1' + '\n' + self.indent
- if not starts_line:
- comment_out_re = r'\n' + self.indent + comment_out_re
- (self.cfile, nsubs) = re.subn(r'(\b'+fname+r'\b)\s*', comment_out_re, self.cfile)
- if nsubs == 0:
- logger.warning("Warning: A replacement failed when commenting out {}. Check the CMakeFile.txt manually.".format(fname))
- elif nsubs > 1:
- logger.warning("Warning: Replaced {} {} times (instead of once). Check the CMakeFile.txt manually.".format(fname, nsubs))
-
- def comment_out_lines(self, pattern, comment_str='#'):
- """ Comments out all lines that match with pattern """
- for line in self.cfile.splitlines():
- if re.search(pattern, line):
- self.cfile = self.cfile.replace(line, comment_str+line)
-
- def check_for_glob(self, globstr):
- """ Returns true if a glob as in globstr is found in the cmake file """
- glob_re = r'GLOB\s[a-z_]+\s"{}"'.format(globstr.replace('*', r'\*'))
- return re.search(glob_re, self.cfile, flags=re.MULTILINE|re.IGNORECASE) is not None
diff --git a/gr-utils/python/modtool/tools/code_generator.py b/gr-utils/python/modtool/tools/code_generator.py
deleted file mode 100644
index fb0d7da686..0000000000
--- a/gr-utils/python/modtool/tools/code_generator.py
+++ /dev/null
@@ -1,52 +0,0 @@
-#
-# Copyright 2013-2014 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-#
-""" A code generator (needed by ModToolAdd) """
-
-from __future__ import print_function
-from __future__ import absolute_import
-from __future__ import unicode_literals
-
-from mako.template import Template
-from ..templates import Templates
-from .util_functions import str_to_fancyc_comment
-from .util_functions import str_to_python_comment
-from .util_functions import strip_default_values
-from .util_functions import strip_arg_types
-from .util_functions import strip_arg_types_grc
-
-GRTYPELIST = {
- 'sync': 'sync_block',
- 'sink': 'sync_block',
- 'source': 'sync_block',
- 'decimator': 'sync_decimator',
- 'interpolator': 'sync_interpolator',
- 'general': 'block',
- 'tagged_stream': 'tagged_stream_block',
- 'hier': 'hier_block2',
- 'noblock': ''
-}
-
-def render_template(tpl_id, **kwargs):
- """ Return the parsed and rendered template given by tpl_id """
- # Choose template
- tpl = Template(Templates[tpl_id])
- # Set up all variables
- kwargs['str_to_fancyc_comment'] = str_to_fancyc_comment
- kwargs['str_to_python_comment'] = str_to_python_comment
- kwargs['strip_default_values'] = strip_default_values
- kwargs['strip_arg_types'] = strip_arg_types
- kwargs['strip_arg_types_grc'] = strip_arg_types_grc
- kwargs['grblocktype'] = GRTYPELIST[kwargs['blocktype']]
- if kwargs['is_component']:
- kwargs['include_dir_prefix'] = "gnuradio/" + kwargs['modname']
- else:
- kwargs['include_dir_prefix'] = kwargs['modname']
- # Render and return
- return tpl.render(**kwargs)
-
diff --git a/gr-utils/python/modtool/tools/grc_yaml_generator.py b/gr-utils/python/modtool/tools/grc_yaml_generator.py
deleted file mode 100644
index 07c00639cf..0000000000
--- a/gr-utils/python/modtool/tools/grc_yaml_generator.py
+++ /dev/null
@@ -1,129 +0,0 @@
-#
-# Copyright 2018 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-#
-""" A tool for generating YAML bindings """
-
-from __future__ import print_function
-from __future__ import absolute_import
-from __future__ import unicode_literals
-
-from collections import OrderedDict
-
-import yaml
-try:
- from yaml import CLoader as Loader, CDumper as Dumper
-except:
- from yaml import Loader, Dumper
-
-from .util_functions import is_number
-
-
-## setup dumper for dumping OrderedDict ##
-_mapping_tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG
-
-def dict_representer(dumper, data):
- """ Representer to represent special OrderedDict """
- return dumper.represent_dict(data.items())
-
-
-def dict_constructor(loader, node):
- """ Construct an OrderedDict for dumping """
- return OrderedDict(loader.construct_pairs(node))
-
-Dumper.add_representer(OrderedDict, dict_representer)
-Loader.add_constructor(_mapping_tag, dict_constructor)
-
-
-class GRCYAMLGenerator(object):
- """ Create and write the YAML bindings for a GRC block. """
- def __init__(self, modname=None, blockname=None, doc=None, params=None, iosig=None):
- """docstring for __init__"""
- params_list = ['${'+s['key']+'}' for s in params if s['in_constructor']]
- # Can't make a dict 'cause order matters
- self._header = (('id', '{}_{}'.format(modname, blockname)),
- ('label', blockname.replace('_', ' ')),
- ('category', '[{}]'.format(modname.capitalize()))
- )
- self._templates = (('imports', 'import {}'.format(modname)),
- ('make', '{}.{}({})'.format(modname, blockname, ', '.join(params_list)))
- )
- self.params = params
- self.iosig = iosig
- self.doc = doc
- self.data = None
-
- def make_yaml(self):
- """ Create the actual tag tree """
- data = OrderedDict()
- for tag, value in self._header:
- data[tag] = value
-
- templates = OrderedDict()
- for tag, value in self._templates:
- templates[tag] = value
-
- data['templates'] = templates
-
- parameters = []
- for param in self.params:
- parameter = OrderedDict()
- parameter['id'] = param['key']
- parameter['label'] = param['key'].capitalize()
- if param['default']:
- parameter['default'] = param['default']
- parameter['dtype'] = param['type']
- parameters.append(parameter)
-
- if parameters:
- data['parameters'] = parameters
-
- inputs = []
- outputs = []
- iosig = self.iosig
- for inout in sorted(iosig.keys()):
- if iosig[inout]['max_ports'] == '0':
- continue
- for i in range(len(iosig[inout]['type'])):
- s_type = {'in': 'input', 'out': 'output'}[inout]
- s_obj = OrderedDict()
- s_obj['label'] = inout
- s_obj['domain'] = 'stream'
- s_obj['dtype'] = iosig[inout]['type'][i]
- if iosig[inout]['vlen'][i] != '1':
- vlen = iosig[inout]['vlen'][i]
- if is_number(vlen):
- s_obj['vlen'] = vlen
- else:
- s_obj['vlen'] = '${ '+vlen+' }'
- if i == len(iosig[inout]['type'])-1:
- if not is_number(iosig[inout]['max_ports']):
- s_obj['multiplicity'] = iosig[inout]['max_ports']
- elif len(iosig[inout]['type']) < int(iosig[inout]['max_ports']):
- s_obj['multiplicity'] = str(int(iosig[inout]['max_ports']) -
- len(iosig[inout]['type'])+1)
- if s_type == 'input':
- inputs.append(s_obj)
- elif s_type == 'output':
- outputs.append(s_obj)
-
- if inputs:
- data['inputs'] = inputs
-
- if outputs:
- data['outputs'] = outputs
-
- if self.doc is not None:
- data['documentation'] = self.doc
- self.data = data
- data['file_format'] = 1
-
- def save(self, filename):
- """ Write the YAML file """
- self.make_yaml()
- with open(filename, 'w') as f:
- yaml.dump(self.data, f, Dumper=Dumper, default_flow_style=False)
diff --git a/gr-utils/python/modtool/tools/parser_cc_block.py b/gr-utils/python/modtool/tools/parser_cc_block.py
deleted file mode 100644
index 81c10f0cdc..0000000000
--- a/gr-utils/python/modtool/tools/parser_cc_block.py
+++ /dev/null
@@ -1,223 +0,0 @@
-#
-# Copyright 2013, 2018 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-#
-''' A parser for blocks written in C++ '''
-
-from __future__ import print_function
-from __future__ import absolute_import
-from __future__ import unicode_literals
-
-import re
-import sys
-import logging
-
-logger = logging.getLogger(__name__)
-
-def dummy_translator(the_type, default_v=None):
- """ Doesn't really translate. """
- return the_type
-
-class ParserCCBlock(object):
- """ Class to read blocks written in C++ """
- def __init__(self, filename_cc, filename_h, blockname, version, type_trans=dummy_translator):
- with open(filename_cc) as f:
- self.code_cc = f.read()
- with open(filename_h) as f:
- self.code_h = f.read()
- self.blockname = blockname
- self.type_trans = type_trans
- self.version = version
-
- def read_io_signature(self):
- """ Scans a .cc file for an IO signature. """
- def _figure_out_iotype_and_vlen(iosigcall, typestr):
- """ From a type identifier, returns the data type.
- E.g., for sizeof(int), it will return 'int'.
- Returns a list! """
- if 'gr::io_signature::makev' in iosigcall:
- logger.error('tbi')
- raise ValueError
- return {'type': [_typestr_to_iotype(x) for x in typestr.split(',')],
- 'vlen': [_typestr_to_vlen(x) for x in typestr.split(',')]
- }
- def _typestr_to_iotype(typestr):
- """ Convert a type string (e.g. sizeof(int) * vlen) to the type (e.g. 'int'). """
- type_match = re.search(r'sizeof\s*\(([^)]*)\)', typestr)
- if type_match is None:
- return self.type_trans('char')
- return self.type_trans(type_match.group(1))
- def _typestr_to_vlen(typestr):
- """ From a type identifier, returns the vector length of the block's
- input/out. E.g., for 'sizeof(int) * 10', it returns 10. For
- 'sizeof(int)', it returns '1'. For 'sizeof(int) * vlen', it returns
- the string vlen. """
- # Catch fringe case where no sizeof() is given
- if typestr.find('sizeof') == -1:
- return typestr
- if typestr.find('*') == -1:
- return '1'
- vlen_parts = typestr.split('*')
- for fac in vlen_parts:
- if fac.find('sizeof') != -1:
- vlen_parts.remove(fac)
- if len(vlen_parts) == 1:
- return vlen_parts[0].strip()
- elif len(vlen_parts) > 1:
- return '*'.join(vlen_parts).strip()
- iosig = {}
- iosig_regex = r'(?P<incall>gr::io_signature::make[23v]?)\s*\(\s*(?P<inmin>[^,]+),\s*(?P<inmax>[^,]+),' + \
- r'\s*(?P<intype>(\([^\)]*\)|[^)])+)\),\s*' + \
- r'(?P<outcall>gr::io_signature::make[23v]?)\s*\(\s*(?P<outmin>[^,]+),\s*(?P<outmax>[^,]+),' + \
- r'\s*(?P<outtype>(\([^\)]*\)|[^)])+)\)'
- iosig_match = re.compile(iosig_regex, re.MULTILINE).search(self.code_cc)
- try:
- iosig['in'] = _figure_out_iotype_and_vlen(iosig_match.group('incall'),
- iosig_match.group('intype'))
- iosig['in']['min_ports'] = iosig_match.group('inmin')
- iosig['in']['max_ports'] = iosig_match.group('inmax')
- except Exception:
- logger.error("Error: Can't parse input signature.")
- try:
- iosig['out'] = _figure_out_iotype_and_vlen(iosig_match.group('outcall'),
- iosig_match.group('outtype'))
- iosig['out']['min_ports'] = iosig_match.group('outmin')
- iosig['out']['max_ports'] = iosig_match.group('outmax')
- except Exception:
- logger.error("Error: Can't parse output signature.")
- return iosig
-
-
- def read_params(self):
- """ Read the parameters required to initialize the block """
- def _scan_param_list(start_idx):
- """ Go through a parameter list and return a tuple each:
- (type, name, default_value). Python's re just doesn't cut
- it for C++ code :( """
- i = start_idx
- c = self.code_h
- if c[i] != '(':
- raise ValueError
- i += 1
-
- param_list = []
- read_state = 'type'
- in_string = False
- parens_count = 0 # Counts ()
- brackets_count = 0 # Counts <>
- end_of_list = False
- this_type = ''
- this_name = ''
- this_defv = ''
- WHITESPACE = ' \t\n\r\f\v'
- while not end_of_list:
- # Keep track of (), stop when reaching final closing parens
- if not in_string:
- if c[i] == ')':
- if parens_count == 0:
- if read_state == 'type' and len(this_type):
- raise ValueError(
- 'Found closing parentheses before finishing '
- 'last argument (this is how far I got: {})'.format \
- (str(param_list))
- )
- if len(this_type):
- param_list.append((this_type, this_name, this_defv))
- end_of_list = True
- break
- else:
- parens_count -= 1
- elif c[i] == '(':
- parens_count += 1
- # Parameter type (int, const std::string, std::vector<gr_complex>, unsigned long ...)
- if read_state == 'type':
- if c[i] == '<':
- brackets_count += 1
- if c[i] == '>':
- brackets_count -= 1
- if c[i] == '&':
- i += 1
- continue
- if c[i] in WHITESPACE and brackets_count == 0:
- while c[i] in WHITESPACE:
- i += 1
- continue
- if this_type == 'const' or this_type == '': # Ignore this
- this_type = ''
- elif this_type == 'unsigned': # Continue
- this_type += ' '
- continue
- else:
- read_state = 'name'
- continue
- this_type += c[i]
- i += 1
- continue
- # Parameter name
- if read_state == 'name':
- if c[i] == '&' or c[i] in WHITESPACE:
- i += 1
- elif c[i] == '=':
- if parens_count != 0:
- raise ValueError(
- 'While parsing argument {} ({}): name finished but no closing parentheses.'.format \
- (len(param_list)+1, this_type + ' ' + this_name)
- )
- read_state = 'defv'
- i += 1
- elif c[i] == ',':
- if parens_count:
- raise ValueError(
- 'While parsing argument {} ({}): name finished but no closing parentheses.'.format \
- (len(param_list)+1, this_type + ' ' + this_name)
- )
- read_state = 'defv'
- else:
- this_name += c[i]
- i += 1
- continue
- # Default value
- if read_state == 'defv':
- if in_string:
- if c[i] == '"' and c[i-1] != '\\':
- in_string = False
- else:
- this_defv += c[i]
- elif c[i] == ',':
- if parens_count:
- raise ValueError(
- 'While parsing argument {} ({}): default value finished but no closing parentheses.'.format \
- (len(param_list)+1, this_type + ' ' + this_name)
- )
- read_state = 'type'
- param_list.append((this_type, this_name, this_defv))
- this_type = ''
- this_name = ''
- this_defv = ''
- else:
- this_defv += c[i]
- i += 1
- continue
- return param_list
- # Go, go, go!
- if self.version in ('37', '38'):
- make_regex = r'static\s+sptr\s+make\s*'
- else:
- make_regex = r'(?<=_API)\s+\w+_sptr\s+\w+_make_\w+\s*'
- make_match = re.compile(make_regex, re.MULTILINE).search(self.code_h)
- try:
- params_list = _scan_param_list(make_match.end(0))
- except ValueError as ve:
- logger.error("Can't parse the argument list: ", ve.args[0])
- sys.exit(0)
- params = []
- for plist in params_list:
- params.append({'type': self.type_trans(plist[0], plist[2]),
- 'key': plist[1],
- 'default': plist[2],
- 'in_constructor': True})
- return params
diff --git a/gr-utils/python/modtool/tools/scm.py b/gr-utils/python/modtool/tools/scm.py
deleted file mode 100644
index 707ed6754c..0000000000
--- a/gr-utils/python/modtool/tools/scm.py
+++ /dev/null
@@ -1,223 +0,0 @@
-#
-# Copyright 2013 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-#
-""" Class to handle source code management repositories. """
-
-from __future__ import print_function
-from __future__ import absolute_import
-from __future__ import unicode_literals
-
-import logging
-import subprocess
-
-logger = logging.getLogger(__name__)
-
-try:
- import git
- HAS_GITPYTHON = True
-except ImportError:
- HAS_GITPYTHON = False
-# GitPython is a bit too unstable currently
-HAS_GITPYTHON = False
-
-class InvalidSCMError(Exception):
- """ Exception for when trying to access a repo of wrong type. """
- def __init__(self):
- Exception.__init__(self)
-
-### Base class ###############################################################
-class SCMRepository(object):
- """ Base class to handle interactions with source code management systems. """
- handles_scm_type = '*'
- def __init__(self, path_to_repo, is_empty=False):
- self.path_to_repo = path_to_repo
- self.is_empty = is_empty
-
- def init_repo(self, path_to_repo=None, add_files=True):
- """ Initialize the directory as a repository. Assumes the self.path_to_repo
- (or path_to_repo, if specified) does *not* contain a valid repository.
- If add_files is True, all files in this directory are added to version control.
- Returns true if actually created a repo.
- """
- if path_to_repo is not None:
- self.path_to_repo = path_to_repo
- return False
-
- def add_files(self, paths_to_files):
- """ Add a tuple or list of files to the current repository. """
- pass
-
- def add_file(self, path_to_file):
- """ Add a file to the current repository. """
- self.add_files([path_to_file])
-
- def remove_files(self, paths_to_files):
- """ Remove a tuple or list of files from the current repository. """
- pass
-
- def remove_file(self, path_to_file):
- """ Remove a file from the current repository. """
- self.remove_files([path_to_file])
-
- def mark_files_updated(self, paths_to_files):
- """ Mark a list of tuple of files as changed. """
- pass
-
- def mark_file_updated(self, path_to_file):
- """ Mark a file as changed. """
- self.mark_files_updated([path_to_file])
-
- def is_active(self):
- """ Returns true if this repository manager is operating on an active, source-controlled directory. """
- return self.is_empty
-
- def get_gituser(self):
- """ Gets the git user """
- try:
- return (subprocess.check_output('git config --global user.name', shell=True).strip()).decode('utf-8')
- except (OSError, subprocess.CalledProcessError):
- return None
-
-
-### Git #####################################################################
-class GitManagerGitPython(object):
- """ Manage git through GitPython (preferred way). """
- def __init__(self, path_to_repo, init=False):
- if init:
- self.repo = git.Repo.init(path_to_repo, mkdir=False)
- else:
- try:
- self.repo = git.Repo(path_to_repo)
- except git.InvalidGitRepositoryError:
- self.repo = None
- raise InvalidSCMError
- self.index = self.repo.index
-
- def add_files(self, paths_to_files):
- """ Adds a tuple of files to the index of the current repository. """
- if self.repo is not None:
- self.index.add(paths_to_files)
-
- def remove_files(self, paths_to_files):
- """ Removes a tuple of files from the index of the current repository. """
- if self.repo is not None:
- self.index.remove(paths_to_files)
-
-
-class GitManagerShell(object):
- """ Call the git executable through a shell. """
- def __init__(self, path_to_repo, init=False, git_executable=None):
- self.path_to_repo = path_to_repo
- if git_executable is None:
- try:
- self.git_executable = subprocess.check_output('which git', shell=True).strip()
- except (OSError, subprocess.CalledProcessError):
- raise InvalidSCMError
- try:
- if init:
- subprocess.check_output([self.git_executable, 'init'])
- else:
- subprocess.check_output([self.git_executable, 'status'])
- except OSError:
- raise InvalidSCMError
- except subprocess.CalledProcessError:
- raise InvalidSCMError
-
- def add_files(self, paths_to_files):
- """ Adds a tuple of files to the index of the current repository. Does not commit. """
- subprocess.check_output([self.git_executable, 'add'] + list(paths_to_files))
-
- def remove_files(self, paths_to_files):
- """ Removes a tuple of files from the index of the current repository. Does not commit. """
- subprocess.check_output([self.git_executable, 'rm', '--cached'] + list(paths_to_files))
-
-
-class GitRepository(SCMRepository):
- """ Specific to operating on git repositories. """
- handles_scm_type = 'git'
- def __init__(self, path_to_repo, is_empty=False):
- SCMRepository.__init__(self, path_to_repo, is_empty)
- if not is_empty:
- try:
- if HAS_GITPYTHON:
- self.repo_manager = GitManagerGitPython(path_to_repo)
- else:
- self.repo_manager = GitManagerShell(path_to_repo)
- except InvalidSCMError:
- self.repo_manager = None
- else:
- self.repo_manager = None
-
- def init_repo(self, path_to_repo=None, add_files=True):
- """ Makes the directory in self.path_to_repo a git repo.
- If add_file is True, all files in this dir are added to the index. """
- SCMRepository.init_repo(self, path_to_repo, add_files)
- if HAS_GITPYTHON:
- self.repo_manager = GitManagerGitPython(self.path_to_repo, init=True)
- else:
- self.repo_manager = GitManagerShell(self.path_to_repo, init=True)
- if add_files:
- self.add_files(('*',))
- return True
-
- def add_files(self, paths_to_files):
- """ Add a file to the current repository. Does not commit. """
- self.repo_manager.add_files(paths_to_files)
-
- def remove_files(self, paths_to_files):
- """ Remove a file from the current repository. Does not commit. """
- self.repo_manager.remove_files(paths_to_files)
-
- def mark_files_updated(self, paths_to_files):
- """ Mark a file as changed. Since this is git, same as adding new files. """
- self.add_files(paths_to_files)
-
- def is_active(self):
- return self.repo_manager is not None
-
-
-##############################################################################
-### Factory ##################################################################
-class SCMRepoFactory(object):
- """ Factory object to create the correct SCM class from the given options and dir. """
- def __init__(self, options, path_to_repo):
- self.path_to_repo = path_to_repo
- self.options = options
-
- def make_active_scm_manager(self):
- """ Returns a valid, usable object of type SCMRepository. """
- if self.options.scm_mode == 'no':
- return SCMRepository(self.path_to_repo)
- for glbl in list(globals().values()):
- try:
- if issubclass(glbl, SCMRepository):
- the_scm = glbl(self.path_to_repo)
- if the_scm.is_active():
- logger.info('Found SCM of type:', the_scm.handles_scm_type)
- return the_scm
- except (TypeError, AttributeError, InvalidSCMError):
- pass
- if self.options == 'yes':
- return None
- return SCMRepository(self.path_to_repo)
-
- def make_empty_scm_manager(self, scm_type='git'):
- """ Returns a valid, usable object of type SCMRepository for an uninitialized dir. """
- if self.options.scm_mode == 'no':
- return SCMRepository(self.path_to_repo)
- for glbl in list(globals().values()):
- try:
- if issubclass(glbl, SCMRepository):
- if glbl.handles_scm_type == scm_type:
- return glbl(self.path_to_repo, is_empty=True)
- except (TypeError, AttributeError, InvalidSCMError):
- pass
- if self.options == 'yes':
- return None
- return SCMRepository(self.path_to_repo)
-
diff --git a/gr-utils/python/modtool/tools/util_functions.py b/gr-utils/python/modtool/tools/util_functions.py
deleted file mode 100644
index d7f2b11317..0000000000
--- a/gr-utils/python/modtool/tools/util_functions.py
+++ /dev/null
@@ -1,167 +0,0 @@
-#
-# Copyright 2013, 2018, 2019 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-#
-""" Utility functions for gr_modtool """
-
-from __future__ import print_function
-from __future__ import absolute_import
-from __future__ import unicode_literals
-
-import re
-import sys
-import readline
-
-# None of these must depend on other modtool stuff!
-
-def append_re_line_sequence(filename, linepattern, newline):
- """ Detects the re 'linepattern' in the file. After its last occurrence,
- paste 'newline'. If the pattern does not exist, append the new line
- to the file. Then, write. """
- with open(filename, 'r') as f:
- oldfile = f.read()
- lines = re.findall(linepattern, oldfile, flags=re.MULTILINE)
- if len(lines) == 0:
- with open(filename, 'a') as f:
- f.write(newline)
- return
- last_line = lines[-1]
- newfile = oldfile.replace(last_line, last_line + newline + '\n')
- with open(filename, 'w') as f:
- f.write(newfile)
-
-def remove_pattern_from_file(filename, pattern):
- """ Remove all occurrences of a given pattern from a file. """
- with open(filename, 'r') as f:
- oldfile = f.read()
- pattern = re.compile(pattern, re.MULTILINE)
- with open(filename, 'w') as f:
- f.write(pattern.sub('', oldfile))
-
-def str_to_fancyc_comment(text):
- """ Return a string as a C formatted comment. """
- l_lines = text.splitlines()
- if len(l_lines[0]) == 0:
- outstr = "/*\n"
- else:
- outstr = "/* " + l_lines[0] + "\n"
- for line in l_lines[1:]:
- if len(line) == 0:
- outstr += " *\n"
- else:
- outstr += " * " + line + "\n"
- outstr += " */\n"
- return outstr
-
-def str_to_python_comment(text):
- """ Return a string as a Python formatted comment. """
- l_lines = text.splitlines()
- if len(l_lines[0]) == 0:
- outstr = "#\n"
- else:
- outstr = "# " + l_lines[0] + "\n"
- for line in l_lines[1:]:
- if len(line) == 0:
- outstr += "#\n"
- else:
- outstr += "# " + line + "\n"
- outstr += "#\n"
- return outstr
-
-def strip_default_values(string):
- """ Strip default values from a C++ argument list. """
- return re.sub(' *=[^,)]*', '', string)
-
-def strip_arg_types(string):
- """"
- Strip the argument types from a list of arguments.
- Example: "int arg1, double arg2" -> "arg1, arg2"
- Note that some types have qualifiers, which also are part of
- the type, e.g. "const std::string &name" -> "name", or
- "const char *str" -> "str".
- """
- string = strip_default_values(string)
- return ", ".join(
- [part.strip().split(' ')[-1] for part in string.split(',')]
- ).replace('*','').replace('&','')
-
-def strip_arg_types_grc(string):
- """" Strip the argument types from a list of arguments for GRC make tag.
- Example: "int arg1, double arg2" -> "$arg1, $arg2" """
- if len(string) == 0:
- return ""
- else:
- string = strip_default_values(string)
- return ", ".join(['${' + part.strip().split(' ')[-1] + '}' for part in string.split(',')])
-
-def get_modname():
- """ Grep the current module's name from gnuradio.project or CMakeLists.txt """
- modname_trans = {'howto-write-a-block': 'howto'}
- try:
- with open('gnuradio.project', 'r') as f:
- prfile = f.read()
- regexp = r'projectname\s*=\s*([a-zA-Z0-9-_]+)$'
- return re.search(regexp, prfile, flags=re.MULTILINE).group(1).strip()
- except IOError:
- pass
- # OK, there's no gnuradio.project. So, we need to guess.
- with open('CMakeLists.txt', 'r') as f:
- cmfile = f.read()
- regexp = r'(project\s*\(\s*|GR_REGISTER_COMPONENT\(")gr-(?P<modname>[a-zA-Z0-9-_]+)(\s*(CXX)?|" ENABLE)'
- try:
- modname = re.search(regexp, cmfile, flags=re.MULTILINE).group('modname').strip()
- if modname in list(modname_trans.keys()):
- modname = modname_trans[modname]
- return modname
- except AttributeError:
- return None
-
-def is_number(s):
- """ Return True if the string s contains a number. """
- try:
- float(s)
- return True
- except ValueError:
- return False
-
-def ask_yes_no(question, default):
- """ Asks a binary question. Returns True for yes, False for no.
- default is given as a boolean. """
- question += {True: ' [Y/n] ', False: ' [y/N] '}[default]
- if input(question).lower() != {True: 'n', False: 'y'}[default]:
- return default
- else:
- return not default
-
-class SequenceCompleter(object):
- """ A simple completer function wrapper to be used with readline, e.g.
- option_iterable = ("search", "seek", "destroy")
- readline.set_completer(SequenceCompleter(option_iterable).completefunc)
-
- Typical usage is with the `with` statement. Restores the previous completer
- at exit, thus nestable.
- """
-
- def __init__(self, sequence=None):
- self._seq = sequence or []
- self._tmp_matches = []
-
- def completefunc(self, text, state):
- if not text and state < len(self._seq):
- return self._seq[state]
- if not state:
- self._tmp_matches = [candidate for candidate in self._seq if candidate.startswith(text)]
- if state < len(self._tmp_matches):
- return self._tmp_matches[state]
-
- def __enter__(self):
- self._old_completer = readline.get_completer()
- readline.set_completer(self.completefunc)
- readline.parse_and_bind("tab: complete")
-
- def __exit__(self, exception_type, exception_value, traceback):
- readline.set_completer(self._old_completer)