diff options
654 files changed, 12444 insertions, 11380 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index a733a8014f..5fe0d44ebb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -209,7 +209,7 @@ if(MSVC) endif(MSVC) if(WIN32) - add_definitions(-D_USE_MATH_DEFINES) + add_definitions(-D_USE_MATH_DEFINES) endif(WIN32) # Record Compiler Info for record @@ -342,7 +342,9 @@ include(GrBoost) ######################################################################## # Enable python component ######################################################################## +include(GrPython) find_package(PythonLibs ${GR_PYTHON_MIN_VERSION}) +GR_PYTHON_CHECK_MODULE("six - python 2 and 3 compatibility library" six "True" SIX_FOUND) find_package(SWIG) if(SWIG_FOUND) @@ -358,6 +360,7 @@ GR_REGISTER_COMPONENT("python-support" ENABLE_PYTHON PYTHONLIBS_FOUND SWIG_FOUND SWIG_VERSION_CHECK + SIX_FOUND ) find_package(CppUnit ${GR_CPPUNIT_MIN_VERSION}) diff --git a/cmake/Modules/GrMiscUtils.cmake b/cmake/Modules/GrMiscUtils.cmake index b158a08d07..a3086bebb6 100644 --- a/cmake/Modules/GrMiscUtils.cmake +++ b/cmake/Modules/GrMiscUtils.cmake @@ -339,7 +339,7 @@ if __name__ == '__main__': add_custom_command( OUTPUT ${expanded_files_h} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}.h.t ${ARGN} ) @@ -384,7 +384,7 @@ if __name__ == '__main__': add_custom_command( OUTPUT ${expanded_files_cc} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.cc.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}.cc.t ${ARGN} ) @@ -393,7 +393,7 @@ if __name__ == '__main__': add_custom_command( OUTPUT ${expanded_files_h} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}.h.t ${ARGN} ) @@ -446,7 +446,7 @@ if __name__ == '__main__': add_custom_command( OUTPUT ${expanded_files_cc_impl} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.cc.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}_impl.cc.t ${ARGN} ) @@ -455,7 +455,7 @@ if __name__ == '__main__': add_custom_command( OUTPUT ${expanded_files_h_impl} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.h.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}_impl.h.t ${ARGN} ) diff --git a/cmake/Modules/GrPython.cmake b/cmake/Modules/GrPython.cmake index 0bfa92db8d..fdbd21d840 100644 --- a/cmake/Modules/GrPython.cmake +++ b/cmake/Modules/GrPython.cmake @@ -1,4 +1,4 @@ -# Copyright 2010-2011 Free Software Foundation, Inc. +# Copyright 2010-2016 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -27,26 +27,21 @@ set(__INCLUDED_GR_PYTHON_CMAKE TRUE) # This allows the user to specify a specific interpreter, # or finds the interpreter via the built-in cmake module. ######################################################################## -#this allows the user to override PYTHON_EXECUTABLE -if(PYTHON_EXECUTABLE) - set(PYTHONINTERP_FOUND TRUE) +if (PYTHON_EXECUTABLE) + message(STATUS "User set python executable ${PYTHON_EXECUTABLE}") + find_package(PythonInterp ${GR_PYTHON_MIN_VERSION} REQUIRED) +else (PYTHON_EXECUTABLE) + message(STATUS "PYTHON_EXECUTABLE not set - using default python3") + message(STATUS "Use -DPYTHON_EXECUTABLE=/path/to/python2 to build for python2.") + find_package(PythonInterp ${GR_PYTHON3_MIN_VERSION} REQUIRED) +endif (PYTHON_EXECUTABLE) -#otherwise if not set, try to automatically find it -else(PYTHON_EXECUTABLE) +if (${PYTHON_VERSION_MAJOR} VERSION_EQUAL 3) + set(PYTHON3 TRUE) +endif () - #use the built-in find script - find_package(PythonInterp 2) - - #and if that fails use the find program routine - if(NOT PYTHONINTERP_FOUND) - find_program(PYTHON_EXECUTABLE NAMES python python2 python2.7 python2.6 python2.5) - if(PYTHON_EXECUTABLE) - set(PYTHONINTERP_FOUND TRUE) - endif(PYTHON_EXECUTABLE) - endif(NOT PYTHONINTERP_FOUND) - -endif(PYTHON_EXECUTABLE) +find_package(PythonLibs ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} EXACT) if (CMAKE_CROSSCOMPILING) set(QA_PYTHON_EXECUTABLE "/usr/bin/python") @@ -58,18 +53,6 @@ endif(CMAKE_CROSSCOMPILING) set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter") set(QA_PYTHON_EXECUTABLE ${QA_PYTHON_EXECUTABLE} CACHE FILEPATH "python interpreter for QA tests") -#make sure we can use -B with python (introduced in 2.6) -if(PYTHON_EXECUTABLE) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -B -c "" - OUTPUT_QUIET ERROR_QUIET - RESULT_VARIABLE PYTHON_HAS_DASH_B_RESULT - ) - if(PYTHON_HAS_DASH_B_RESULT EQUAL 0) - set(PYTHON_DASH_B "-B") - endif() -endif(PYTHON_EXECUTABLE) - ######################################################################## # Check for the existence of a python module: # - desc a string description of the check @@ -77,27 +60,31 @@ endif(PYTHON_EXECUTABLE) # - cmd an additional command to run # - have the result variable to set ######################################################################## -macro(GR_PYTHON_CHECK_MODULE desc mod cmd have) - message(STATUS "") - message(STATUS "Python checking for ${desc}") +macro(GR_PYTHON_CHECK_MODULE_RAW desc python_code have) execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c " + COMMAND ${PYTHON_EXECUTABLE} -c "${python_code}" + RESULT_VARIABLE return_code + ) + if(return_code EQUAL 0) + message(STATUS "Python checking for ${desc} - found") + set(${have} TRUE) + else() + message(STATUS "Python checking for ${desc} - not found") + set(${have} FALSE) + endif() +endmacro(GR_PYTHON_CHECK_MODULE_RAW) + +macro(GR_PYTHON_CHECK_MODULE desc mod cmd have) + GR_PYTHON_CHECK_MODULE_RAW( + "${desc}" " ######################################### try: import ${mod} assert ${cmd} -except ImportError, AssertionError: exit(-1) +except (ImportError, AssertionError): exit(-1) except: pass #########################################" - RESULT_VARIABLE ${have} - ) - if(${have} EQUAL 0) - message(STATUS "Python checking for ${desc} - found") - set(${have} TRUE) - else(${have} EQUAL 0) - message(STATUS "Python checking for ${desc} - not found") - set(${have} FALSE) - endif(${have} EQUAL 0) + "${have}") endmacro(GR_PYTHON_CHECK_MODULE) ######################################################################## @@ -105,8 +92,12 @@ endmacro(GR_PYTHON_CHECK_MODULE) ######################################################################## if(NOT DEFINED GR_PYTHON_DIR) execute_process(COMMAND ${PYTHON_EXECUTABLE} -c " -from distutils import sysconfig -print sysconfig.get_python_lib(plat_specific=True, prefix='') +import os +import sys +if os.name == 'posix': + print(os.path.join('lib', 'python' + sys.version[:3], 'dist-packages')) +if os.name == 'nt': + print(os.path.join('Lib', 'site-packages')) " OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE ) endif() @@ -119,7 +110,7 @@ file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR) function(GR_UNIQUE_TARGET desc) file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib -unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5] +unique = hashlib.md5(b'${reldir}${ARGN}').hexdigest()[:5] print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))" OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE) add_custom_target(${_target} ALL DEPENDS ${ARGN}) @@ -130,7 +121,7 @@ endfunction(GR_UNIQUE_TARGET) ######################################################################## function(GR_PYTHON_INSTALL) include(CMakeParseArgumentsCopy) - CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION" "FILES;PROGRAMS" ${ARGN}) + CMAKE_PARSE_ARGUMENTS(GR_PYTHON_INSTALL "" "DESTINATION" "FILES;PROGRAMS;DIRECTORY" ${ARGN}) #################################################################### if(GR_PYTHON_INSTALL_FILES) @@ -185,6 +176,80 @@ function(GR_PYTHON_INSTALL) ) #################################################################### + elseif(GR_PYTHON_INSTALL_DIRECTORY) + #################################################################### + install(${ARGN}) #installs regular python files + + # collect all python files in given directories + # ############################################# + unset(pysrcfiles) + foreach(pydir ${GR_PYTHON_INSTALL_DIRECTORY}) + file(GLOB_RECURSE pysrcfiles_tmp "${pydir}/*.py") + list(APPEND pysrcfiles ${pysrcfiles_tmp}) + endforeach(pydir) + + # build target lists + # ################## + unset(pycfiles) # pyc targets + unset(pyofiles) # pyo targets + unset(pygen_paths) # all paths of py[oc] targets + foreach(pyfile ${pysrcfiles}) + # determine if this file is in the source or binary directory + file(RELATIVE_PATH source_rel_path ${CMAKE_CURRENT_SOURCE_DIR} ${pyfile}) + string(LENGTH "${source_rel_path}" source_rel_path_len) + file(RELATIVE_PATH binary_rel_path ${CMAKE_CURRENT_BINARY_DIR} ${pyfile}) + string(LENGTH "${binary_rel_path}" binary_rel_path_len) + + # and set the generated path appropriately + if(${source_rel_path_len} GREATER ${binary_rel_path_len}) + set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${binary_rel_path}) + else() + set(pygenfile ${CMAKE_CURRENT_BINARY_DIR}/${source_rel_path}) + endif() + list(APPEND pycfiles "${pygenfile}c") + list(APPEND pyofiles "${pygenfile}o") + + get_filename_component(pygen_path "${pygenfile}" DIRECTORY) + list(APPEND pygen_paths "${pygen_path}") + file(MAKE_DIRECTORY "${pygen_path}") + endforeach(pyfile) + list(REMOVE_DUPLICATES pygen_paths) + list(SORT pygen_paths) + + # generate the py[oc] files + # ######################### + add_custom_command( + DEPENDS ${pysrcfiles} OUTPUT ${pycfiles} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pycfiles} + ) + add_custom_command( + DEPENDS ${pysrcfiles} OUTPUT ${pyofiles} + COMMAND ${PYTHON_EXECUTABLE} -O ${CMAKE_BINARY_DIR}/python_compile_helper.py ${pysrcfiles} ${pyofiles} + ) + set(python_install_gen_targets ${pycfiles} ${pyofiles}) + + # per-directory install rules + # ########################### + foreach(pygen_path ${pygen_paths}) + # find all targets in that directory (no "list(FILTER ...)") + unset(pygen_path_targets) + foreach(pyget_target ${python_install_gen_targets}) + get_filename_component(pyget_target_path "${pyget_target}" PATH) + if(pygen_path STREQUAL pyget_target_path) + list(APPEND pygen_path_targets "${pyget_target}") + endif() + endforeach(pyget_target) + + # install relative to current binary dir + file(RELATIVE_PATH pygen_path_rel "${CMAKE_CURRENT_BINARY_DIR}" "${pygen_path}") + list(SORT pygen_path_targets) + install( + FILES ${pygen_path_targets} + DESTINATION "${GR_PYTHON_INSTALL_DESTINATION}/${pygen_path_rel}" + ) + endforeach(pygen_path) + + #################################################################### elseif(GR_PYTHON_INSTALL_PROGRAMS) #################################################################### file(TO_NATIVE_PATH ${PYTHON_EXECUTABLE} pyexe_native) @@ -233,7 +298,7 @@ endfunction(GR_PYTHON_INSTALL) file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py " import sys, py_compile files = sys.argv[1:] -srcs, gens = files[:len(files)/2], files[len(files)/2:] +srcs, gens = files[:len(files)//2], files[len(files)//2:] for src, gen in zip(srcs, gens): py_compile.compile(file=src, cfile=gen, doraise=True) ") diff --git a/cmake/Modules/GrSwig.cmake b/cmake/Modules/GrSwig.cmake index de8be5cc19..8e45c546cd 100644 --- a/cmake/Modules/GrSwig.cmake +++ b/cmake/Modules/GrSwig.cmake @@ -76,7 +76,7 @@ function(GR_SWIG_MAKE_DOCS output_file) add_custom_command( OUTPUT ${output_file} DEPENDS ${input_files} ${stamp-file} ${OUTPUT_DIRECTORY}/xml/index.xml - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py ${OUTPUT_DIRECTORY}/xml ${output_file} @@ -146,7 +146,6 @@ macro(GR_SWIG_MAKE name) endif() #append additional include directories - find_package(PythonLibs 2) list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_PATH}) #deprecated name (now dirs) list(APPEND GR_SWIG_INCLUDE_DIRS ${PYTHON_INCLUDE_DIRS}) @@ -178,8 +177,12 @@ macro(GR_SWIG_MAKE name) include_directories(${GR_SWIG_INCLUDE_DIRS}) list(APPEND SWIG_MODULE_${name}_EXTRA_DEPS ${tag_file}) + if (PYTHON3) + set(py3 "-py3") + endif (PYTHON3) + #setup the swig flags with flags and include directories - set(CMAKE_SWIG_FLAGS -fvirtual -modern -keyword -w511 -w314 -module ${name} ${GR_SWIG_FLAGS}) + set(CMAKE_SWIG_FLAGS -fvirtual -modern -keyword -w511 -w314 -relativeimport ${py3} -module ${name} ${GR_SWIG_FLAGS}) #set the C++ property on the swig .i file so it builds set_source_files_properties(${ifiles} PROPERTIES CPLUSPLUS ON) @@ -238,7 +241,7 @@ endmacro(GR_SWIG_INSTALL) ######################################################################## file(WRITE ${CMAKE_BINARY_DIR}/get_swig_deps.py " -import os, sys, re +import os, sys, re, io i_include_matcher = re.compile('%(include|import)\\s*[<|\"](.*)[>|\"]') h_include_matcher = re.compile('#(include)\\s*[<|\"](.*)[>|\"]') @@ -247,7 +250,7 @@ include_dirs = sys.argv[2].split(';') def get_swig_incs(file_path): if file_path.endswith('.i'): matcher = i_include_matcher else: matcher = h_include_matcher - file_contents = open(file_path, 'r').read() + file_contents = io.open(file_path, 'r', encoding='utf-8').read() return matcher.findall(file_contents, re.MULTILINE) def get_swig_deps(file_path, level): diff --git a/cmake/Modules/UseSWIG.cmake b/cmake/Modules/UseSWIG.cmake index e55543532f..a37cc41ae4 100644 --- a/cmake/Modules/UseSWIG.cmake +++ b/cmake/Modules/UseSWIG.cmake @@ -176,7 +176,7 @@ macro(SWIG_ADD_SOURCE_TO_MODULE name outfiles infile) file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib -unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5] +unique = hashlib.md5(b'${reldir}${ARGN}').hexdigest()[:5] print(re.sub('\\W', '_', '${name} ${reldir} ' + unique))" OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE ) diff --git a/docs/doxygen/doxyxml/__init__.py b/docs/doxygen/doxyxml/__init__.py index 5cd0b3c6c5..b7a8884519 100644 --- a/docs/doxygen/doxyxml/__init__.py +++ b/docs/doxygen/doxyxml/__init__.py @@ -63,8 +63,9 @@ This line is uninformative and is only to test line breaks in the comments. u'Outputs the vital aadvark statistics.' """ +from __future__ import unicode_literals -from doxyindex import DoxyIndex, DoxyFunction, DoxyParam, DoxyClass, DoxyFile, DoxyNamespace, DoxyGroup, DoxyFriend, DoxyOther +from .doxyindex import DoxyIndex, DoxyFunction, DoxyParam, DoxyClass, DoxyFile, DoxyNamespace, DoxyGroup, DoxyFriend, DoxyOther def _test(): import os diff --git a/docs/doxygen/doxyxml/base.py b/docs/doxygen/doxyxml/base.py index e8f026ab90..f6f2b8e195 100644 --- a/docs/doxygen/doxyxml/base.py +++ b/docs/doxygen/doxyxml/base.py @@ -25,23 +25,26 @@ Classes based upon this are used to make more user-friendly interfaces to the doxygen xml docs than the generated classes provide. """ +from __future__ import print_function +from __future__ import unicode_literals + import os import pdb from xml.parsers.expat import ExpatError -from generated import compound +from .generated import compound class Base(object): - class Duplicate(StandardError): + class Duplicate(Exception): pass - class NoSuchMember(StandardError): + class NoSuchMember(Exception): pass - class ParsingError(StandardError): + class ParsingError(Exception): pass def __init__(self, parse_data, top=None): @@ -94,7 +97,7 @@ class Base(object): for cls in self.mem_classes: if cls.can_parse(mem): return cls - raise StandardError(("Did not find a class for object '%s'." \ + raise Exception(("Did not find a class for object '%s'." \ % (mem.get_name()))) def convert_mem(self, mem): @@ -102,11 +105,11 @@ class Base(object): cls = self.get_cls(mem) converted = cls.from_parse_data(mem, self.top) if converted is None: - raise StandardError('No class matched this object.') + raise Exception('No class matched this object.') self.add_ref(converted) return converted - except StandardError, e: - print e + except Exception as e: + print(e) @classmethod def includes(cls, inst): diff --git a/docs/doxygen/doxyxml/doxyindex.py b/docs/doxygen/doxyxml/doxyindex.py index e039737714..083550bdf8 100644 --- a/docs/doxygen/doxyxml/doxyindex.py +++ b/docs/doxygen/doxyxml/doxyindex.py @@ -22,12 +22,13 @@ Classes providing more user-friendly interfaces to the doxygen xml docs than the generated classes provide. """ +from __future__ import unicode_literals import os -from generated import index -from base import Base -from text import description +from .generated import index +from .base import Base +from .text import description class DoxyIndex(Base): """ diff --git a/docs/doxygen/doxyxml/generated/__init__.py b/docs/doxygen/doxyxml/generated/__init__.py index 39823979f6..23095c1f34 100644 --- a/docs/doxygen/doxyxml/generated/__init__.py +++ b/docs/doxygen/doxyxml/generated/__init__.py @@ -5,3 +5,4 @@ These do the real work of parsing the doxygen xml files but the resultant classes are not very friendly to navigate so the rest of the doxyxml module processes them further. """ +from __future__ import unicode_literals diff --git a/docs/doxygen/doxyxml/generated/compound.py b/docs/doxygen/doxyxml/generated/compound.py index 1522ac23f1..cd3cd1f96b 100644 --- a/docs/doxygen/doxyxml/generated/compound.py +++ b/docs/doxygen/doxyxml/generated/compound.py @@ -3,15 +3,16 @@ """ Generated Mon Feb 9 19:08:05 2009 by generateDS.py. """ +from __future__ import unicode_literals + -from string import lower as str_lower from xml.dom import minidom from xml.dom import Node import sys -import compoundsuper as supermod -from compoundsuper import MixedContainer +from . import compoundsuper as supermod +from .compoundsuper import MixedContainer class DoxygenTypeSub(supermod.DoxygenType): @@ -499,5 +500,3 @@ def parse(inFilename): rootObj = supermod.DoxygenType.factory() rootObj.build(rootNode) return rootObj - - diff --git a/docs/doxygen/doxyxml/generated/compoundsuper.py b/docs/doxygen/doxyxml/generated/compoundsuper.py index 6255dda163..f18ec6cda9 100644 --- a/docs/doxygen/doxyxml/generated/compoundsuper.py +++ b/docs/doxygen/doxyxml/generated/compoundsuper.py @@ -4,12 +4,16 @@ # Generated Thu Jun 11 18:44:25 2009 by generateDS.py. # +from __future__ import print_function +from __future__ import unicode_literals + import sys -import getopt -from string import lower as str_lower + from xml.dom import minidom from xml.dom import Node +import six + # # User methods # @@ -19,9 +23,9 @@ from xml.dom import Node try: from generatedssuper import GeneratedsSuper -except ImportError, exp: +except ImportError as exp: - class GeneratedsSuper: + class GeneratedsSuper(object): def format_string(self, input_data, input_name=''): return input_data def format_integer(self, input_data, input_name=''): @@ -64,7 +68,7 @@ def showIndent(outfile, level): outfile.write(' ') def quote_xml(inStr): - s1 = (isinstance(inStr, basestring) and inStr or + s1 = (isinstance(inStr, six.string_types) and inStr or '%s' % inStr) s1 = s1.replace('&', '&') s1 = s1.replace('<', '<') @@ -72,7 +76,7 @@ def quote_xml(inStr): return s1 def quote_attrib(inStr): - s1 = (isinstance(inStr, basestring) and inStr or + s1 = (isinstance(inStr, six.string_types) and inStr or '%s' % inStr) s1 = s1.replace('&', '&') s1 = s1.replace('<', '<') @@ -102,7 +106,7 @@ def quote_python(inStr): return '"""%s"""' % s1 -class MixedContainer: +class MixedContainer(object): # Constants for category: CategoryNone = 0 CategoryText = 1 @@ -4221,7 +4225,7 @@ class codelineType(GeneratedsSuper): if attrs.get('lineno'): try: self.lineno = int(attrs.get('lineno').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (lineno): %s' % exp) if attrs.get('refkind'): self.refkind = attrs.get('refkind').value @@ -4504,12 +4508,12 @@ class referenceType(GeneratedsSuper): if attrs.get('endline'): try: self.endline = int(attrs.get('endline').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (endline): %s' % exp) if attrs.get('startline'): try: self.startline = int(attrs.get('startline').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (startline): %s' % exp) if attrs.get('refid'): self.refid = attrs.get('refid').value @@ -4627,17 +4631,17 @@ class locationType(GeneratedsSuper): if attrs.get('bodystart'): try: self.bodystart = int(attrs.get('bodystart').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (bodystart): %s' % exp) if attrs.get('line'): try: self.line = int(attrs.get('line').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (line): %s' % exp) if attrs.get('bodyend'): try: self.bodyend = int(attrs.get('bodyend').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (bodyend): %s' % exp) if attrs.get('bodyfile'): self.bodyfile = attrs.get('bodyfile').value @@ -6778,12 +6782,12 @@ class docTableType(GeneratedsSuper): if attrs.get('rows'): try: self.rows = int(attrs.get('rows').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (rows): %s' % exp) if attrs.get('cols'): try: self.cols = int(attrs.get('cols').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (cols): %s' % exp) def buildChildren(self, child_, nodeName_): if child_.nodeType == Node.ELEMENT_NODE and \ @@ -7108,7 +7112,7 @@ class docHeadingType(GeneratedsSuper): if attrs.get('level'): try: self.level = int(attrs.get('level').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (level): %s' % exp) def buildChildren(self, child_, nodeName_): if child_.nodeType == Node.TEXT_NODE: @@ -8283,7 +8287,7 @@ Options: """ def usage(): - print USAGE_TEXT + print(USAGE_TEXT) sys.exit(1) @@ -8339,4 +8343,3 @@ if __name__ == '__main__': main() #import pdb #pdb.run('main()') - diff --git a/docs/doxygen/doxyxml/generated/index.py b/docs/doxygen/doxyxml/generated/index.py index 7a70e14a1a..eb9a9048b2 100644 --- a/docs/doxygen/doxyxml/generated/index.py +++ b/docs/doxygen/doxyxml/generated/index.py @@ -3,14 +3,15 @@ """ Generated Mon Feb 9 19:08:05 2009 by generateDS.py. """ +from __future__ import unicode_literals from xml.dom import minidom import os import sys -import compound +from . import compound -import indexsuper as supermod +from . import indexsuper as supermod class DoxygenTypeSub(supermod.DoxygenType): def __init__(self, version=None, compound=None): diff --git a/docs/doxygen/doxyxml/generated/indexsuper.py b/docs/doxygen/doxyxml/generated/indexsuper.py index a991530198..11312db635 100644 --- a/docs/doxygen/doxyxml/generated/indexsuper.py +++ b/docs/doxygen/doxyxml/generated/indexsuper.py @@ -4,12 +4,16 @@ # Generated Thu Jun 11 18:43:54 2009 by generateDS.py. # +from __future__ import print_function +from __future__ import unicode_literals + import sys -import getopt -from string import lower as str_lower + from xml.dom import minidom from xml.dom import Node +import six + # # User methods # @@ -19,9 +23,9 @@ from xml.dom import Node try: from generatedssuper import GeneratedsSuper -except ImportError, exp: +except ImportError as exp: - class GeneratedsSuper: + class GeneratedsSuper(object): def format_string(self, input_data, input_name=''): return input_data def format_integer(self, input_data, input_name=''): @@ -64,7 +68,7 @@ def showIndent(outfile, level): outfile.write(' ') def quote_xml(inStr): - s1 = (isinstance(inStr, basestring) and inStr or + s1 = (isinstance(inStr, six.string_types) and inStr or '%s' % inStr) s1 = s1.replace('&', '&') s1 = s1.replace('<', '<') @@ -72,7 +76,7 @@ def quote_xml(inStr): return s1 def quote_attrib(inStr): - s1 = (isinstance(inStr, basestring) and inStr or + s1 = (isinstance(inStr, six.string_types) and inStr or '%s' % inStr) s1 = s1.replace('&', '&') s1 = s1.replace('<', '<') @@ -102,7 +106,7 @@ def quote_python(inStr): return '"""%s"""' % s1 -class MixedContainer: +class MixedContainer(object): # Constants for category: CategoryNone = 0 CategoryText = 1 @@ -462,7 +466,7 @@ Options: """ def usage(): - print USAGE_TEXT + print(USAGE_TEXT) sys.exit(1) @@ -520,4 +524,3 @@ if __name__ == '__main__': main() #import pdb #pdb.run('main()') - diff --git a/docs/doxygen/doxyxml/text.py b/docs/doxygen/doxyxml/text.py index 629edd180d..f0322f6237 100644 --- a/docs/doxygen/doxyxml/text.py +++ b/docs/doxygen/doxyxml/text.py @@ -21,6 +21,7 @@ """ Utilities for extracting text from generated classes. """ +from __future__ import unicode_literals def is_string(txt): if isinstance(txt, str): @@ -49,7 +50,7 @@ def description_bit(obj): elif is_string(obj): return obj else: - raise StandardError('Expecting a string or something with content, content_ or value attribute') + raise Exception('Expecting a string or something with content, content_ or value attribute') # If this bit is a paragraph then add one some line breaks. if hasattr(obj, 'name') and obj.name == 'para': result += "\n\n" diff --git a/docs/doxygen/other/doxypy.py b/docs/doxygen/other/doxypy.py index a9af32ab53..e474a9694f 100755..100644 --- a/docs/doxygen/other/doxypy.py +++ b/docs/doxygen/other/doxypy.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +from __future__ import print_function +from __future__ import unicode_literals + __applicationName__ = "doxypy" __blurb__ = """ doxypy is an input filter for Doxygen. It preprocesses python @@ -11,8 +14,8 @@ __doc__ = __blurb__ + \ """ In order to make Doxygen preprocess files through doxypy, simply add the following lines to your Doxyfile: - FILTER_SOURCE_FILES = YES - INPUT_FILTER = "python /path/to/doxypy.py" + FILTER_SOURCE_FILES = YES + INPUT_FILTER = "python /path/to/doxypy.py" """ __version__ = "0.4.2" @@ -20,8 +23,8 @@ __date__ = "5th December 2008" __website__ = "http://code.foosel.org/doxypy" __author__ = ( - "Philippe 'demod' Neumann (doxypy at demod dot org)", - "Gina 'foosel' Haeussge (gina at foosel dot net)" + "Philippe 'demod' Neumann (doxypy at demod dot org)", + "Gina 'foosel' Haeussge (gina at foosel dot net)" ) __licenseName__ = "GPL v2" @@ -45,364 +48,364 @@ import re from argparse import ArgumentParser class FSM(object): - """Implements a finite state machine. - - Transitions are given as 4-tuples, consisting of an origin state, a target - state, a condition for the transition (given as a reference to a function - which gets called with a given piece of input) and a pointer to a function - to be called upon the execution of the given transition. - """ - - """ - @var transitions holds the transitions - @var current_state holds the current state - @var current_input holds the current input - @var current_transition hold the currently active transition - """ - - def __init__(self, start_state=None, transitions=[]): - self.transitions = transitions - self.current_state = start_state - self.current_input = None - self.current_transition = None - - def setStartState(self, state): - self.current_state = state - - def addTransition(self, from_state, to_state, condition, callback): - self.transitions.append([from_state, to_state, condition, callback]) - - def makeTransition(self, input): - """ Makes a transition based on the given input. - - @param input input to parse by the FSM - """ - for transition in self.transitions: - [from_state, to_state, condition, callback] = transition - if from_state == self.current_state: - match = condition(input) - if match: - self.current_state = to_state - self.current_input = input - self.current_transition = transition - if args.debug: - print >>sys.stderr, "# FSM: executing (%s -> %s) for line '%s'" % (from_state, to_state, input) - callback(match) - return + """Implements a finite state machine. + + Transitions are given as 4-tuples, consisting of an origin state, a target + state, a condition for the transition (given as a reference to a function + which gets called with a given piece of input) and a pointer to a function + to be called upon the execution of the given transition. + """ + + """ + @var transitions holds the transitions + @var current_state holds the current state + @var current_input holds the current input + @var current_transition hold the currently active transition + """ + + def __init__(self, start_state=None, transitions=[]): + self.transitions = transitions + self.current_state = start_state + self.current_input = None + self.current_transition = None + + def setStartState(self, state): + self.current_state = state + + def addTransition(self, from_state, to_state, condition, callback): + self.transitions.append([from_state, to_state, condition, callback]) + + def makeTransition(self, input): + """ Makes a transition based on the given input. + + @param input input to parse by the FSM + """ + for transition in self.transitions: + [from_state, to_state, condition, callback] = transition + if from_state == self.current_state: + match = condition(input) + if match: + self.current_state = to_state + self.current_input = input + self.current_transition = transition + if args.debug: + print("# FSM: executing (%s -> %s) for line '%s'" % (from_state, to_state, input), file=sys.stderr) + callback(match) + return class Doxypy(object): - def __init__(self): - string_prefixes = "[uU]?[rR]?" - - self.start_single_comment_re = re.compile("^\s*%s(''')" % string_prefixes) - self.end_single_comment_re = re.compile("(''')\s*$") - - self.start_double_comment_re = re.compile("^\s*%s(\"\"\")" % string_prefixes) - self.end_double_comment_re = re.compile("(\"\"\")\s*$") - - self.single_comment_re = re.compile("^\s*%s(''').*(''')\s*$" % string_prefixes) - self.double_comment_re = re.compile("^\s*%s(\"\"\").*(\"\"\")\s*$" % string_prefixes) - - self.defclass_re = re.compile("^(\s*)(def .+:|class .+:)") - self.empty_re = re.compile("^\s*$") - self.hashline_re = re.compile("^\s*#.*$") - self.importline_re = re.compile("^\s*(import |from .+ import)") - - self.multiline_defclass_start_re = re.compile("^(\s*)(def|class)(\s.*)?$") - self.multiline_defclass_end_re = re.compile(":\s*$") - - ## Transition list format - # ["FROM", "TO", condition, action] - transitions = [ - ### FILEHEAD - - # single line comments - ["FILEHEAD", "FILEHEAD", self.single_comment_re.search, self.appendCommentLine], - ["FILEHEAD", "FILEHEAD", self.double_comment_re.search, self.appendCommentLine], - - # multiline comments - ["FILEHEAD", "FILEHEAD_COMMENT_SINGLE", self.start_single_comment_re.search, self.appendCommentLine], - ["FILEHEAD_COMMENT_SINGLE", "FILEHEAD", self.end_single_comment_re.search, self.appendCommentLine], - ["FILEHEAD_COMMENT_SINGLE", "FILEHEAD_COMMENT_SINGLE", self.catchall, self.appendCommentLine], - ["FILEHEAD", "FILEHEAD_COMMENT_DOUBLE", self.start_double_comment_re.search, self.appendCommentLine], - ["FILEHEAD_COMMENT_DOUBLE", "FILEHEAD", self.end_double_comment_re.search, self.appendCommentLine], - ["FILEHEAD_COMMENT_DOUBLE", "FILEHEAD_COMMENT_DOUBLE", self.catchall, self.appendCommentLine], - - # other lines - ["FILEHEAD", "FILEHEAD", self.empty_re.search, self.appendFileheadLine], - ["FILEHEAD", "FILEHEAD", self.hashline_re.search, self.appendFileheadLine], - ["FILEHEAD", "FILEHEAD", self.importline_re.search, self.appendFileheadLine], - ["FILEHEAD", "DEFCLASS", self.defclass_re.search, self.resetCommentSearch], - ["FILEHEAD", "DEFCLASS_MULTI", self.multiline_defclass_start_re.search, self.resetCommentSearch], - ["FILEHEAD", "DEFCLASS_BODY", self.catchall, self.appendFileheadLine], - - ### DEFCLASS - - # single line comments - ["DEFCLASS", "DEFCLASS_BODY", self.single_comment_re.search, self.appendCommentLine], - ["DEFCLASS", "DEFCLASS_BODY", self.double_comment_re.search, self.appendCommentLine], - - # multiline comments - ["DEFCLASS", "COMMENT_SINGLE", self.start_single_comment_re.search, self.appendCommentLine], - ["COMMENT_SINGLE", "DEFCLASS_BODY", self.end_single_comment_re.search, self.appendCommentLine], - ["COMMENT_SINGLE", "COMMENT_SINGLE", self.catchall, self.appendCommentLine], - ["DEFCLASS", "COMMENT_DOUBLE", self.start_double_comment_re.search, self.appendCommentLine], - ["COMMENT_DOUBLE", "DEFCLASS_BODY", self.end_double_comment_re.search, self.appendCommentLine], - ["COMMENT_DOUBLE", "COMMENT_DOUBLE", self.catchall, self.appendCommentLine], - - # other lines - ["DEFCLASS", "DEFCLASS", self.empty_re.search, self.appendDefclassLine], - ["DEFCLASS", "DEFCLASS", self.defclass_re.search, self.resetCommentSearch], - ["DEFCLASS", "DEFCLASS_MULTI", self.multiline_defclass_start_re.search, self.resetCommentSearch], - ["DEFCLASS", "DEFCLASS_BODY", self.catchall, self.stopCommentSearch], - - ### DEFCLASS_BODY - - ["DEFCLASS_BODY", "DEFCLASS", self.defclass_re.search, self.startCommentSearch], - ["DEFCLASS_BODY", "DEFCLASS_MULTI", self.multiline_defclass_start_re.search, self.startCommentSearch], - ["DEFCLASS_BODY", "DEFCLASS_BODY", self.catchall, self.appendNormalLine], - - ### DEFCLASS_MULTI - ["DEFCLASS_MULTI", "DEFCLASS", self.multiline_defclass_end_re.search, self.appendDefclassLine], - ["DEFCLASS_MULTI", "DEFCLASS_MULTI", self.catchall, self.appendDefclassLine], - ] - - self.fsm = FSM("FILEHEAD", transitions) - self.outstream = sys.stdout - - self.output = [] - self.comment = [] - self.filehead = [] - self.defclass = [] - self.indent = "" - - def __closeComment(self): - """Appends any open comment block and triggering block to the output.""" - - if args.autobrief: - if len(self.comment) == 1 \ - or (len(self.comment) > 2 and self.comment[1].strip() == ''): - self.comment[0] = self.__docstringSummaryToBrief(self.comment[0]) - - if self.comment: - block = self.makeCommentBlock() - self.output.extend(block) - - if self.defclass: - self.output.extend(self.defclass) - - def __docstringSummaryToBrief(self, line): - """Adds \\brief to the docstrings summary line. - - A \\brief is prepended, provided no other doxygen command is at the - start of the line. - """ - stripped = line.strip() - if stripped and not stripped[0] in ('@', '\\'): - return "\\brief " + line - else: - return line - - def __flushBuffer(self): - """Flushes the current outputbuffer to the outstream.""" - if self.output: - try: - if args.debug: - print >>sys.stderr, "# OUTPUT: ", self.output - print >>self.outstream, "\n".join(self.output) - self.outstream.flush() - except IOError: - # Fix for FS#33. Catches "broken pipe" when doxygen closes - # stdout prematurely upon usage of INPUT_FILTER, INLINE_SOURCES - # and FILTER_SOURCE_FILES. - pass - self.output = [] - - def catchall(self, input): - """The catchall-condition, always returns true.""" - return True - - def resetCommentSearch(self, match): - """Restarts a new comment search for a different triggering line. - - Closes the current commentblock and starts a new comment search. - """ - if args.debug: - print >>sys.stderr, "# CALLBACK: resetCommentSearch" - self.__closeComment() - self.startCommentSearch(match) - - def startCommentSearch(self, match): - """Starts a new comment search. - - Saves the triggering line, resets the current comment and saves - the current indentation. - """ - if args.debug: - print >>sys.stderr, "# CALLBACK: startCommentSearch" - self.defclass = [self.fsm.current_input] - self.comment = [] - self.indent = match.group(1) - - def stopCommentSearch(self, match): - """Stops a comment search. - - Closes the current commentblock, resets the triggering line and - appends the current line to the output. - """ - if args.debug: - print >>sys.stderr, "# CALLBACK: stopCommentSearch" - self.__closeComment() - - self.defclass = [] - self.output.append(self.fsm.current_input) - - def appendFileheadLine(self, match): - """Appends a line in the FILEHEAD state. - - Closes the open comment block, resets it and appends the current line. - """ - if args.debug: - print >>sys.stderr, "# CALLBACK: appendFileheadLine" - self.__closeComment() - self.comment = [] - self.output.append(self.fsm.current_input) - - def appendCommentLine(self, match): - """Appends a comment line. - - The comment delimiter is removed from multiline start and ends as - well as singleline comments. - """ - if args.debug: - print >>sys.stderr, "# CALLBACK: appendCommentLine" - (from_state, to_state, condition, callback) = self.fsm.current_transition - - # single line comment - if (from_state == "DEFCLASS" and to_state == "DEFCLASS_BODY") \ - or (from_state == "FILEHEAD" and to_state == "FILEHEAD"): - # remove comment delimiter from begin and end of the line - activeCommentDelim = match.group(1) - line = self.fsm.current_input - self.comment.append(line[line.find(activeCommentDelim)+len(activeCommentDelim):line.rfind(activeCommentDelim)]) - - if (to_state == "DEFCLASS_BODY"): - self.__closeComment() - self.defclass = [] - # multiline start - elif from_state == "DEFCLASS" or from_state == "FILEHEAD": - # remove comment delimiter from begin of the line - activeCommentDelim = match.group(1) - line = self.fsm.current_input - self.comment.append(line[line.find(activeCommentDelim)+len(activeCommentDelim):]) - # multiline end - elif to_state == "DEFCLASS_BODY" or to_state == "FILEHEAD": - # remove comment delimiter from end of the line - activeCommentDelim = match.group(1) - line = self.fsm.current_input - self.comment.append(line[0:line.rfind(activeCommentDelim)]) - if (to_state == "DEFCLASS_BODY"): - self.__closeComment() - self.defclass = [] - # in multiline comment - else: - # just append the comment line - self.comment.append(self.fsm.current_input) - - def appendNormalLine(self, match): - """Appends a line to the output.""" - if args.debug: - print >>sys.stderr, "# CALLBACK: appendNormalLine" - self.output.append(self.fsm.current_input) - - def appendDefclassLine(self, match): - """Appends a line to the triggering block.""" - if args.debug: - print >>sys.stderr, "# CALLBACK: appendDefclassLine" - self.defclass.append(self.fsm.current_input) - - def makeCommentBlock(self): - """Indents the current comment block with respect to the current - indentation level. - - @returns a list of indented comment lines - """ - doxyStart = "##" - commentLines = self.comment - - commentLines = map(lambda x: "%s# %s" % (self.indent, x), commentLines) - l = [self.indent + doxyStart] - l.extend(commentLines) - - return l - - def parse(self, input): - """Parses a python file given as input string and returns the doxygen- - compatible representation. - - @param input the python code to parse - @returns the modified python code - """ - lines = input.split("\n") - - for line in lines: - self.fsm.makeTransition(line) - - if self.fsm.current_state == "DEFCLASS": - self.__closeComment() - - return "\n".join(self.output) - - def parseFile(self, filename): - """Parses a python file given as input string and returns the doxygen- - compatible representation. - - @param input the python code to parse - @returns the modified python code - """ - f = open(filename, 'r') - - for line in f: - self.parseLine(line.rstrip('\r\n')) - if self.fsm.current_state == "DEFCLASS": - self.__closeComment() - self.__flushBuffer() - f.close() - - def parseLine(self, line): - """Parse one line of python and flush the resulting output to the - outstream. - - @param line the python code line to parse - """ - self.fsm.makeTransition(line) - self.__flushBuffer() + def __init__(self): + string_prefixes = "[uU]?[rR]?" + + self.start_single_comment_re = re.compile("^\s*%s(''')" % string_prefixes) + self.end_single_comment_re = re.compile("(''')\s*$") + + self.start_double_comment_re = re.compile("^\s*%s(\"\"\")" % string_prefixes) + self.end_double_comment_re = re.compile("(\"\"\")\s*$") + + self.single_comment_re = re.compile("^\s*%s(''').*(''')\s*$" % string_prefixes) + self.double_comment_re = re.compile("^\s*%s(\"\"\").*(\"\"\")\s*$" % string_prefixes) + + self.defclass_re = re.compile("^(\s*)(def .+:|class .+:)") + self.empty_re = re.compile("^\s*$") + self.hashline_re = re.compile("^\s*#.*$") + self.importline_re = re.compile("^\s*(import |from .+ import)") + + self.multiline_defclass_start_re = re.compile("^(\s*)(def|class)(\s.*)?$") + self.multiline_defclass_end_re = re.compile(":\s*$") + + ## Transition list format + # ["FROM", "TO", condition, action] + transitions = [ + ### FILEHEAD + + # single line comments + ["FILEHEAD", "FILEHEAD", self.single_comment_re.search, self.appendCommentLine], + ["FILEHEAD", "FILEHEAD", self.double_comment_re.search, self.appendCommentLine], + + # multiline comments + ["FILEHEAD", "FILEHEAD_COMMENT_SINGLE", self.start_single_comment_re.search, self.appendCommentLine], + ["FILEHEAD_COMMENT_SINGLE", "FILEHEAD", self.end_single_comment_re.search, self.appendCommentLine], + ["FILEHEAD_COMMENT_SINGLE", "FILEHEAD_COMMENT_SINGLE", self.catchall, self.appendCommentLine], + ["FILEHEAD", "FILEHEAD_COMMENT_DOUBLE", self.start_double_comment_re.search, self.appendCommentLine], + ["FILEHEAD_COMMENT_DOUBLE", "FILEHEAD", self.end_double_comment_re.search, self.appendCommentLine], + ["FILEHEAD_COMMENT_DOUBLE", "FILEHEAD_COMMENT_DOUBLE", self.catchall, self.appendCommentLine], + + # other lines + ["FILEHEAD", "FILEHEAD", self.empty_re.search, self.appendFileheadLine], + ["FILEHEAD", "FILEHEAD", self.hashline_re.search, self.appendFileheadLine], + ["FILEHEAD", "FILEHEAD", self.importline_re.search, self.appendFileheadLine], + ["FILEHEAD", "DEFCLASS", self.defclass_re.search, self.resetCommentSearch], + ["FILEHEAD", "DEFCLASS_MULTI", self.multiline_defclass_start_re.search, self.resetCommentSearch], + ["FILEHEAD", "DEFCLASS_BODY", self.catchall, self.appendFileheadLine], + + ### DEFCLASS + + # single line comments + ["DEFCLASS", "DEFCLASS_BODY", self.single_comment_re.search, self.appendCommentLine], + ["DEFCLASS", "DEFCLASS_BODY", self.double_comment_re.search, self.appendCommentLine], + + # multiline comments + ["DEFCLASS", "COMMENT_SINGLE", self.start_single_comment_re.search, self.appendCommentLine], + ["COMMENT_SINGLE", "DEFCLASS_BODY", self.end_single_comment_re.search, self.appendCommentLine], + ["COMMENT_SINGLE", "COMMENT_SINGLE", self.catchall, self.appendCommentLine], + ["DEFCLASS", "COMMENT_DOUBLE", self.start_double_comment_re.search, self.appendCommentLine], + ["COMMENT_DOUBLE", "DEFCLASS_BODY", self.end_double_comment_re.search, self.appendCommentLine], + ["COMMENT_DOUBLE", "COMMENT_DOUBLE", self.catchall, self.appendCommentLine], + + # other lines + ["DEFCLASS", "DEFCLASS", self.empty_re.search, self.appendDefclassLine], + ["DEFCLASS", "DEFCLASS", self.defclass_re.search, self.resetCommentSearch], + ["DEFCLASS", "DEFCLASS_MULTI", self.multiline_defclass_start_re.search, self.resetCommentSearch], + ["DEFCLASS", "DEFCLASS_BODY", self.catchall, self.stopCommentSearch], + + ### DEFCLASS_BODY + + ["DEFCLASS_BODY", "DEFCLASS", self.defclass_re.search, self.startCommentSearch], + ["DEFCLASS_BODY", "DEFCLASS_MULTI", self.multiline_defclass_start_re.search, self.startCommentSearch], + ["DEFCLASS_BODY", "DEFCLASS_BODY", self.catchall, self.appendNormalLine], + + ### DEFCLASS_MULTI + ["DEFCLASS_MULTI", "DEFCLASS", self.multiline_defclass_end_re.search, self.appendDefclassLine], + ["DEFCLASS_MULTI", "DEFCLASS_MULTI", self.catchall, self.appendDefclassLine], + ] + + self.fsm = FSM("FILEHEAD", transitions) + self.outstream = sys.stdout + + self.output = [] + self.comment = [] + self.filehead = [] + self.defclass = [] + self.indent = "" + + def __closeComment(self): + """Appends any open comment block and triggering block to the output.""" + + if args.autobrief: + if len(self.comment) == 1 \ + or (len(self.comment) > 2 and self.comment[1].strip() == ''): + self.comment[0] = self.__docstringSummaryToBrief(self.comment[0]) + + if self.comment: + block = self.makeCommentBlock() + self.output.extend(block) + + if self.defclass: + self.output.extend(self.defclass) + + def __docstringSummaryToBrief(self, line): + """Adds \\brief to the docstrings summary line. + + A \\brief is prepended, provided no other doxygen command is at the + start of the line. + """ + stripped = line.strip() + if stripped and not stripped[0] in ('@', '\\'): + return "\\brief " + line + else: + return line + + def __flushBuffer(self): + """Flushes the current outputbuffer to the outstream.""" + if self.output: + try: + if args.debug: + print("# OUTPUT: ", self.output, file=sys.stderr) + print("\n".join(self.output), file=self.outstream) + self.outstream.flush() + except IOError: + # Fix for FS#33. Catches "broken pipe" when doxygen closes + # stdout prematurely upon usage of INPUT_FILTER, INLINE_SOURCES + # and FILTER_SOURCE_FILES. + pass + self.output = [] + + def catchall(self, input): + """The catchall-condition, always returns true.""" + return True + + def resetCommentSearch(self, match): + """Restarts a new comment search for a different triggering line. + + Closes the current commentblock and starts a new comment search. + """ + if args.debug: + print("# CALLBACK: resetCommentSearch", file=sys.stderr) + self.__closeComment() + self.startCommentSearch(match) + + def startCommentSearch(self, match): + """Starts a new comment search. + + Saves the triggering line, resets the current comment and saves + the current indentation. + """ + if args.debug: + print("# CALLBACK: startCommentSearch", file=sys.stderr) + self.defclass = [self.fsm.current_input] + self.comment = [] + self.indent = match.group(1) + + def stopCommentSearch(self, match): + """Stops a comment search. + + Closes the current commentblock, resets the triggering line and + appends the current line to the output. + """ + if args.debug: + print("# CALLBACK: stopCommentSearch", file=sys.stderr) + self.__closeComment() + + self.defclass = [] + self.output.append(self.fsm.current_input) + + def appendFileheadLine(self, match): + """Appends a line in the FILEHEAD state. + + Closes the open comment block, resets it and appends the current line. + """ + if args.debug: + print("# CALLBACK: appendFileheadLine", file=sys.stderr) + self.__closeComment() + self.comment = [] + self.output.append(self.fsm.current_input) + + def appendCommentLine(self, match): + """Appends a comment line. + + The comment delimiter is removed from multiline start and ends as + well as singleline comments. + """ + if args.debug: + print("# CALLBACK: appendCommentLine", file=sys.stderr) + (from_state, to_state, condition, callback) = self.fsm.current_transition + + # single line comment + if (from_state == "DEFCLASS" and to_state == "DEFCLASS_BODY") \ + or (from_state == "FILEHEAD" and to_state == "FILEHEAD"): + # remove comment delimiter from begin and end of the line + activeCommentDelim = match.group(1) + line = self.fsm.current_input + self.comment.append(line[line.find(activeCommentDelim)+len(activeCommentDelim):line.rfind(activeCommentDelim)]) + + if (to_state == "DEFCLASS_BODY"): + self.__closeComment() + self.defclass = [] + # multiline start + elif from_state == "DEFCLASS" or from_state == "FILEHEAD": + # remove comment delimiter from begin of the line + activeCommentDelim = match.group(1) + line = self.fsm.current_input + self.comment.append(line[line.find(activeCommentDelim)+len(activeCommentDelim):]) + # multiline end + elif to_state == "DEFCLASS_BODY" or to_state == "FILEHEAD": + # remove comment delimiter from end of the line + activeCommentDelim = match.group(1) + line = self.fsm.current_input + self.comment.append(line[0:line.rfind(activeCommentDelim)]) + if (to_state == "DEFCLASS_BODY"): + self.__closeComment() + self.defclass = [] + # in multiline comment + else: + # just append the comment line + self.comment.append(self.fsm.current_input) + + def appendNormalLine(self, match): + """Appends a line to the output.""" + if args.debug: + print("# CALLBACK: appendNormalLine", file=sys.stderr) + self.output.append(self.fsm.current_input) + + def appendDefclassLine(self, match): + """Appends a line to the triggering block.""" + if args.debug: + print("# CALLBACK: appendDefclassLine", file=sys.stderr) + self.defclass.append(self.fsm.current_input) + + def makeCommentBlock(self): + """Indents the current comment block with respect to the current + indentation level. + + @returns a list of indented comment lines + """ + doxyStart = "##" + commentLines = self.comment + + commentLines = ["%s# %s" % (self.indent, x) for x in commentLines] + l = [self.indent + doxyStart] + l.extend(commentLines) + + return l + + def parse(self, input): + """Parses a python file given as input string and returns the doxygen- + compatible representation. + + @param input the python code to parse + @returns the modified python code + """ + lines = input.split("\n") + + for line in lines: + self.fsm.makeTransition(line) + + if self.fsm.current_state == "DEFCLASS": + self.__closeComment() + + return "\n".join(self.output) + + def parseFile(self, filename): + """Parses a python file given as input string and returns the doxygen- + compatible representation. + + @param input the python code to parse + @returns the modified python code + """ + f = open(filename, 'r') + + for line in f: + self.parseLine(line.rstrip('\r\n')) + if self.fsm.current_state == "DEFCLASS": + self.__closeComment() + self.__flushBuffer() + f.close() + + def parseLine(self, line): + """Parse one line of python and flush the resulting output to the + outstream. + + @param line the python code line to parse + """ + self.fsm.makeTransition(line) + self.__flushBuffer() def argParse(): - """Parses commandline args.""" - parser = ArgumentParser(prog=__applicationName__) - - parser.add_argument("--version", action="version", - version="%(prog)s " + __version__ - ) - parser.add_argument("--autobrief", action="store_true", - help="use the docstring summary line as \\brief description" - ) - parser.add_argument("--debug", action="store_true", - help="enable debug output on stderr" - ) - parser.add_argument("filename", metavar="FILENAME") - - return parser.parse_args() + """Parses commandline args.""" + parser = ArgumentParser(prog=__applicationName__) + + parser.add_argument("--version", action="version", + version="%(prog)s " + __version__ + ) + parser.add_argument("--autobrief", action="store_true", + help="use the docstring summary line as \\brief description" + ) + parser.add_argument("--debug", action="store_true", + help="enable debug output on stderr" + ) + parser.add_argument("filename", metavar="FILENAME") + + return parser.parse_args() def main(): - """Starts the parser on the file given by the filename as the first - argument on the commandline. - """ - global args - args = argParse() - fsm = Doxypy() - fsm.parseFile(args.filename) + """Starts the parser on the file given by the filename as the first + argument on the commandline. + """ + global args + args = argParse() + fsm = Doxypy() + fsm.parseFile(args.filename) if __name__ == "__main__": - main() + main() diff --git a/docs/doxygen/swig_doc.py b/docs/doxygen/swig_doc.py index c9e89aec1b..307920d776 100644 --- a/docs/doxygen/swig_doc.py +++ b/docs/doxygen/swig_doc.py @@ -26,6 +26,7 @@ The file instructs SWIG to transfer the doxygen comments into the python docstrings. """ +from __future__ import unicode_literals import sys, time @@ -84,8 +85,8 @@ def utoascii(text): if text is None: return '' out = text.encode('ascii', 'replace') - out = out.replace('"', '\\"') - return out + out = out.replace(b'"', b'\\"').decode('ascii') + return str(out) def combine_descriptions(obj): @@ -301,7 +302,7 @@ def make_swig_interface_file(di, swigdocfilename, custom_output=None): output = "\n\n".join(output) - swig_doc = file(swigdocfilename, 'w') + swig_doc = open(swigdocfilename, 'w') swig_doc.write(output) swig_doc.close() @@ -309,7 +310,7 @@ if __name__ == "__main__": # Parse command line options and set up doxyxml. err_msg = "Execute using: python swig_doc.py xml_path outputfilename" if len(sys.argv) != 3: - raise StandardError(err_msg) + raise Exception(err_msg) xml_path = sys.argv[1] swigdocfilename = sys.argv[2] di = DoxyIndex(xml_path) diff --git a/docs/exploring-gnuradio/dial_tone.py b/docs/exploring-gnuradio/dial_tone.py index ba43c43bfc..42cbf3c9d0 100755..100644 --- a/docs/exploring-gnuradio/dial_tone.py +++ b/docs/exploring-gnuradio/dial_tone.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import analog @@ -40,5 +41,5 @@ def build_graph(): if __name__ == '__main__': tb = build_graph() tb.start() - raw_input('Press Enter to quit: ') + eval(input('Press Enter to quit: ')) tb.stop() diff --git a/docs/exploring-gnuradio/fm_demod.py b/docs/exploring-gnuradio/fm_demod.py index 8e8b6425f9..71d7f64c82 100755..100644 --- a/docs/exploring-gnuradio/fm_demod.py +++ b/docs/exploring-gnuradio/fm_demod.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from gnuradio import filter @@ -46,7 +48,7 @@ class build_graph(gr.top_block): # Set the demodulator using the same deviation as the receiver. max_dev = 75e3 - fm_demod_gain = input_rate/(2*math.pi*max_dev/8.0) + fm_demod_gain = input_rate / (2*math.pi*max_dev/8.0) fm_demod = analog.quadrature_demod_cf(fm_demod_gain) # Create a filter for the resampler and filter the audio @@ -80,7 +82,7 @@ class build_graph(gr.top_block): def main(args): tb = build_graph() tb.start() # fork thread and return - raw_input('Press Enter to quit: ') + eval(input('Press Enter to quit: ')) tb.stop() if __name__ == '__main__': diff --git a/docs/sphinx/gnuradio_sphinx.py b/docs/sphinx/gnuradio_sphinx.py index 22b96c32e7..cdfd46ceca 100644 --- a/docs/sphinx/gnuradio_sphinx.py +++ b/docs/sphinx/gnuradio_sphinx.py @@ -1,6 +1,7 @@ """ Customizations of sphinx for gnuradio use. """ +from __future__ import unicode_literals from sphinx.ext.autodoc import py_ext_sig_re from sphinx.ext.autodoc import ClassDocumenter, FunctionDocumenter, members_option diff --git a/docs/sphinx/hieroglyph/__init__.py b/docs/sphinx/hieroglyph/__init__.py index 25dea27fba..d6b00fc049 100644 --- a/docs/sphinx/hieroglyph/__init__.py +++ b/docs/sphinx/hieroglyph/__init__.py @@ -1,6 +1,7 @@ +from __future__ import unicode_literals # We only need to expose the setup function to Sphinx from .hieroglyph import setup from .version import __version__ -__author__ = 'Robert Smallshire'
\ No newline at end of file +__author__ = 'Robert Smallshire' diff --git a/docs/sphinx/hieroglyph/errors.py b/docs/sphinx/hieroglyph/errors.py index 9c1d2213b2..9f7cde9570 100644 --- a/docs/sphinx/hieroglyph/errors.py +++ b/docs/sphinx/hieroglyph/errors.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals from sphinx.errors import ExtensionError @@ -7,4 +8,4 @@ class HieroglyphError(ExtensionError): ''' An exception type specific to the Hieroglyph Sphinx extension. ''' - pass
\ No newline at end of file + pass diff --git a/docs/sphinx/hieroglyph/hieroglyph.py b/docs/sphinx/hieroglyph/hieroglyph.py index 0056d9ab8a..bb58a6e04b 100644 --- a/docs/sphinx/hieroglyph/hieroglyph.py +++ b/docs/sphinx/hieroglyph/hieroglyph.py @@ -1,9 +1,11 @@ from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals import re -from errors import HieroglyphError -from nodes import (Node, Raises, Except, Note, Warning, Returns, Arg, +from .errors import HieroglyphError +from .nodes import (Node, Raises, Except, Note, Warning, Returns, Arg, ensure_terminal_blank) __author__ = 'Robert Smallshire' diff --git a/docs/sphinx/hieroglyph/nodes.py b/docs/sphinx/hieroglyph/nodes.py index f0c08b5621..1c091ab6a0 100644 --- a/docs/sphinx/hieroglyph/nodes.py +++ b/docs/sphinx/hieroglyph/nodes.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals __author__ = 'Robert Smallshire' class Node(object): diff --git a/docs/sphinx/hieroglyph/test/__init__.py b/docs/sphinx/hieroglyph/test/__init__.py index c9b674ead2..c568b0851f 100644 --- a/docs/sphinx/hieroglyph/test/__init__.py +++ b/docs/sphinx/hieroglyph/test/__init__.py @@ -1 +1,2 @@ +from __future__ import unicode_literals __author__ = 'rjs' diff --git a/docs/sphinx/hieroglyph/test/test_comments.py b/docs/sphinx/hieroglyph/test/test_comments.py index d1a1453ee1..1cc569605c 100644 --- a/docs/sphinx/hieroglyph/test/test_comments.py +++ b/docs/sphinx/hieroglyph/test/test_comments.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals import unittest from hieroglyph.hieroglyph import parse_hieroglyph_text diff --git a/docs/sphinx/hieroglyph/test/test_hierglyph.py b/docs/sphinx/hieroglyph/test/test_hierglyph.py index 4f86db5784..7815960905 100644 --- a/docs/sphinx/hieroglyph/test/test_hierglyph.py +++ b/docs/sphinx/hieroglyph/test/test_hierglyph.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals import unittest from hieroglyph.hieroglyph import first_paragraph_indent, gather_lines, unindent diff --git a/docs/sphinx/hieroglyph/test/test_nodes.py b/docs/sphinx/hieroglyph/test/test_nodes.py index 12cd25a03e..4b6003c91a 100644 --- a/docs/sphinx/hieroglyph/test/test_nodes.py +++ b/docs/sphinx/hieroglyph/test/test_nodes.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals import unittest from hieroglyph.nodes import Node, Arg, Raises, Except, Returns, Warning, Note diff --git a/docs/sphinx/hieroglyph/version.py b/docs/sphinx/hieroglyph/version.py index b35385b6b8..f823af4363 100644 --- a/docs/sphinx/hieroglyph/version.py +++ b/docs/sphinx/hieroglyph/version.py @@ -1,3 +1,4 @@ '''Specification of the hieroglyph version''' +from __future__ import unicode_literals __version__ = '0.6' diff --git a/gnuradio-runtime/apps/evaluation_random_numbers.py b/gnuradio-runtime/apps/evaluation_random_numbers.py index 069493c73e..30b61be858 100644 --- a/gnuradio-runtime/apps/evaluation_random_numbers.py +++ b/gnuradio-runtime/apps/evaluation_random_numbers.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr import numpy as np from scipy.stats import norm, laplace, rayleigh @@ -40,7 +43,7 @@ laplace_num_bins = 31 rndm = gr.random() # instance of gnuradio random class (gr::random) -print 'All histograms contain',num_tests,'realisations.' +print('All histograms contain',num_tests,'realisations.') #*** GENERATE DATA ***# @@ -73,7 +76,7 @@ rayleigh_expected = np.zeros(rayleigh_num_bins-1) laplace_expected = np.zeros(laplace_num_bins-1) for k in range(len(uniform_hist[0])): - uniform_expected[k] = num_tests/float(uniform_num_bins-1) + uniform_expected[k] = num_tests / float(uniform_num_bins-1) for k in range(len(gauss_hist[0])): gauss_expected[k] = float(norm.cdf(gauss_hist[1][k+1])-norm.cdf(gauss_hist[1][k]))*num_tests @@ -86,10 +89,10 @@ for k in range(len(laplace_hist[0])): #*** PLOT HISTOGRAMS AND EXPECTATIONS TAKEN FROM SCIPY ***# -uniform_bins_center = uniform_bins[0:-1]+(uniform_bins[1]-uniform_bins[0])/2.0 -gauss_bins_center = gauss_bins[0:-1]+(gauss_bins[1]-gauss_bins[0])/2.0 -rayleigh_bins_center = rayleigh_bins[0:-1]+(rayleigh_bins[1]-rayleigh_bins[0])/2.0 -laplace_bins_center = laplace_bins[0:-1]+(laplace_bins[1]-laplace_bins[0])/2.0 +uniform_bins_center = uniform_bins[0:-1]+(uniform_bins[1]-uniform_bins[0]) / 2.0 +gauss_bins_center = gauss_bins[0:-1]+(gauss_bins[1]-gauss_bins[0]) / 2.0 +rayleigh_bins_center = rayleigh_bins[0:-1]+(rayleigh_bins[1]-rayleigh_bins[0]) / 2.0 +laplace_bins_center = laplace_bins[0:-1]+(laplace_bins[1]-laplace_bins[0]) / 2.0 plt.figure(1) @@ -99,7 +102,7 @@ plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Uniform: Distribution') plt.legend(['histogram gr::random','calculation scipy'],loc=1) plt.subplot(2,1,2) -plt.plot(uniform_bins_center,uniform_hist[0]/uniform_expected,'rs--') +plt.plot(uniform_bins_center,uniform_hist[0] / uniform_expected,'rs--') plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Uniform: Relative deviation to scipy') plt.figure(2) @@ -110,7 +113,7 @@ plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Gauss: Distribution') plt.legend(['histogram gr::random','calculation scipy'],loc=1) plt.subplot(2,1,2) -plt.plot(gauss_bins_center,gauss_hist[0]/gauss_expected,'rs--') +plt.plot(gauss_bins_center,gauss_hist[0] / gauss_expected,'rs--') plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Gauss: Relative deviation to scipy') plt.figure(3) @@ -122,7 +125,7 @@ plt.legend(['histogram gr::random','calculation scipy'],loc=1) plt.subplot(2,1,2) -plt.plot(rayleigh_bins_center,rayleigh_hist[0]/rayleigh_expected,'rs--') +plt.plot(rayleigh_bins_center,rayleigh_hist[0] / rayleigh_expected,'rs--') plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Rayleigh: Relative deviation to scipy') plt.figure(4) @@ -133,7 +136,7 @@ plt.xlabel('Bins'), plt.ylabel('Count'), plt.title('Laplace: Distribution') plt.legend(['histogram gr::random','calculation scipy'],loc=1) plt.subplot(2,1,2) -plt.plot(laplace_bins_center,laplace_hist[0]/laplace_expected,'rs--') +plt.plot(laplace_bins_center,laplace_hist[0] / laplace_expected,'rs--') plt.xlabel('Bins'), plt.ylabel('Relative deviation'), plt.title('Laplace: Relative deviation to scipy') plt.show() diff --git a/gnuradio-runtime/examples/mp-sched/affinity_set.py b/gnuradio-runtime/examples/mp-sched/affinity_set.py index e6637b44bf..b717e1e506 100755..100644 --- a/gnuradio-runtime/examples/mp-sched/affinity_set.py +++ b/gnuradio-runtime/examples/mp-sched/affinity_set.py @@ -4,6 +4,8 @@ # Title: Affinity Set Test ################################################## +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import eng_notation from gnuradio import gr from gnuradio import blocks @@ -57,7 +59,7 @@ if __name__ == '__main__': tb.start() while(1): - ret = raw_input('Enter a new Core # or Press Enter to quit: ') + ret = eval(input('Enter a new Core # or Press Enter to quit: ')) if(len(ret) == 0): tb.stop() sys.exit(0) @@ -67,6 +69,6 @@ if __name__ == '__main__': try: n = int(ret) except ValueError: - print "Invalid number" + print("Invalid number") else: tb.filter_filt_0.set_processor_affinity([n,]) diff --git a/gnuradio-runtime/examples/mp-sched/plot_flops.py b/gnuradio-runtime/examples/mp-sched/plot_flops.py index 9bd2ff12bb..e71770aee3 100755..100644 --- a/gnuradio-runtime/examples/mp-sched/plot_flops.py +++ b/gnuradio-runtime/examples/mp-sched/plot_flops.py @@ -23,6 +23,7 @@ Reads output from run_synthetic.py and runs gnuplot showing GFLOPS as f(npipes, nstages) """ +from __future__ import unicode_literals import re import sys diff --git a/gnuradio-runtime/examples/mp-sched/run_synthetic.py b/gnuradio-runtime/examples/mp-sched/run_synthetic.py index 802fb9fd34..684f95bd87 100755..100644 --- a/gnuradio-runtime/examples/mp-sched/run_synthetic.py +++ b/gnuradio-runtime/examples/mp-sched/run_synthetic.py @@ -22,6 +22,8 @@ """ Run synthetic.py for npipes in [1,16], nstages in [1,16] """ +from __future__ import division +from __future__ import unicode_literals import re import sys @@ -49,7 +51,7 @@ def write_shell_script(f, data_filename, description, ncores, gflops, max_pipes_ # We'd like each run of synthetic to take ~10 seconds desired_time_per_run = 10 est_gflops_avail = min(nstages * npipes, ncores) * gflops - nsamples = (est_gflops_avail * desired_time_per_run)/(512.0 * nstages * npipes) + nsamples = (est_gflops_avail * desired_time_per_run) / (512.0 * nstages * npipes) nsamples = int(nsamples * 1e9) cmd = "./synthetic.py -m -s %d -p %d -N %d\n" % (nstages, npipes, nsamples) diff --git a/gnuradio-runtime/examples/mp-sched/synthetic.py b/gnuradio-runtime/examples/mp-sched/synthetic.py index 16e39734ae..0f0b7b37cc 100755..100644 --- a/gnuradio-runtime/examples/mp-sched/synthetic.py +++ b/gnuradio-runtime/examples/mp-sched/synthetic.py @@ -19,6 +19,9 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, eng_notation from gnuradio import blocks, filter from gnuradio.eng_arg import eng_float, intx @@ -35,7 +38,7 @@ class pipeline(gr.hier_block2): gr.hier_block2.__init__(self, "pipeline", gr.io_signature(1, 1, gr.sizeof_float), gr.io_signature(0, 0, 0)) - taps = ntaps*[1.0/ntaps] + taps = ntaps*[1.0 / ntaps] upstream = self for i in range(nstages): op = filter.fir_filter_fff(1, taps) @@ -85,23 +88,23 @@ def time_it(tb): start = os.times() tb.run() stop = os.times() - delta = map((lambda a, b: a-b), stop, start) + delta = list(map((lambda a, b: a-b), stop, start)) user, sys, childrens_user, childrens_sys, real = delta total_user = user + childrens_user total_sys = sys + childrens_sys if tb.machine_readable: - print "%3d %3d %.3e %7.3f %7.3f %7.3f %7.3f %.6e %.3e" % ( - tb.npipes, tb.nstages, tb.nsamples, real, total_user, total_sys, (total_user+total_sys)/real, tb.flop, tb.flop/real) + print("%3d %3d %.3e %7.3f %7.3f %7.3f %7.3f %.6e %.3e" % ( + tb.npipes, tb.nstages, tb.nsamples, real, total_user, total_sys, (total_user+total_sys) / real, tb.flop, tb.flop / real)) else: - print "npipes %7d" % (tb.npipes,) - print "nstages %7d" % (tb.nstages,) - print "nsamples %s" % (eng_notation.num_to_str(tb.nsamples),) - print "real %7.3f" % (real,) - print "user %7.3f" % (total_user,) - print "sys %7.3f" % (total_sys,) - print "(user+sys)/real %7.3f" % ((total_user + total_sys)/real,) - print "pseudo_flop %s" % (eng_notation.num_to_str(tb.flop),) - print "pseudo_flop/real %s" % (eng_notation.num_to_str(tb.flop/real),) + print("npipes %7d" % (tb.npipes,)) + print("nstages %7d" % (tb.nstages,)) + print("nsamples %s" % (eng_notation.num_to_str(tb.nsamples),)) + print("real %7.3f" % (real,)) + print("user %7.3f" % (total_user,)) + print("sys %7.3f" % (total_sys,)) + print("(user+sys)/real %7.3f" % ((total_user + total_sys) / real,)) + print("pseudo_flop %s" % (eng_notation.num_to_str(tb.flop),)) + print("pseudo_flop/real %s" % (eng_notation.num_to_str(tb.flop / real),)) if __name__ == "__main__": @@ -109,7 +112,7 @@ if __name__ == "__main__": tb = top() time_it(tb) except KeyboardInterrupt: - raise SystemExit, 128 + raise SystemExit(128) diff --git a/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py b/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py index bb3296d428..93f26c6637 100755..100644 --- a/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py +++ b/gnuradio-runtime/examples/mp-sched/wfm_rcv_pll_to_wav.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, gru, eng_notation, filter from gnuradio import audio from gnuradio import analog @@ -94,7 +96,7 @@ class wfm_rx_block (gr.top_block): if args.volume is None: g = self.volume_range() - args.volume = float(g[0]+g[1])/2 + args.volume = float(g[0]+g[1]) / 2 # set initial values @@ -109,8 +111,8 @@ class wfm_rx_block (gr.top_block): def set_vol (self, vol): g = self.volume_range() self.vol = max(g[0], min(g[1], vol)) - self.volume_control_l.set_k(10**(self.vol/10)) - self.volume_control_r.set_k(10**(self.vol/10)) + self.volume_control_l.set_k(10**(self.vol / 10)) + self.volume_control_r.set_k(10**(self.vol / 10)) def volume_range(self): return (-20.0, 0.0, 0.5) diff --git a/gnuradio-runtime/examples/network/audio_sink.py b/gnuradio-runtime/examples/network/audio_sink.py index 9b91db5d1e..9ebe8a4c80 100755..100644 --- a/gnuradio-runtime/examples/network/audio_sink.py +++ b/gnuradio-runtime/examples/network/audio_sink.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from argparse import ArgumentParser diff --git a/gnuradio-runtime/examples/network/audio_source.py b/gnuradio-runtime/examples/network/audio_source.py index 6a464a8f28..cc4a34c63f 100755..100644 --- a/gnuradio-runtime/examples/network/audio_source.py +++ b/gnuradio-runtime/examples/network/audio_source.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from argparse import ArgumentParser diff --git a/gnuradio-runtime/examples/network/dial_tone_sink.py b/gnuradio-runtime/examples/network/dial_tone_sink.py index 4b1db98649..e6acbb08d4 100755..100644 --- a/gnuradio-runtime/examples/network/dial_tone_sink.py +++ b/gnuradio-runtime/examples/network/dial_tone_sink.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr, audio from gnuradio import blocks from argparse import ArgumentParser diff --git a/gnuradio-runtime/examples/network/dial_tone_source.py b/gnuradio-runtime/examples/network/dial_tone_source.py index ee2bc9529b..aa3ab9954f 100755..100644 --- a/gnuradio-runtime/examples/network/dial_tone_source.py +++ b/gnuradio-runtime/examples/network/dial_tone_source.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from argparse import ArgumentParser import sys diff --git a/gnuradio-runtime/examples/network/vector_sink.py b/gnuradio-runtime/examples/network/vector_sink.py index 362f631380..a8850d8a01 100755..100644 --- a/gnuradio-runtime/examples/network/vector_sink.py +++ b/gnuradio-runtime/examples/network/vector_sink.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from gnuradio.eng_arg import eng_float, intx diff --git a/gnuradio-runtime/examples/network/vector_source.py b/gnuradio-runtime/examples/network/vector_source.py index be40134bc0..cf8d0000c2 100755..100644 --- a/gnuradio-runtime/examples/network/vector_source.py +++ b/gnuradio-runtime/examples/network/vector_source.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from argparse import ArgumentParser diff --git a/gnuradio-runtime/examples/volk_benchmark/volk_math.py b/gnuradio-runtime/examples/volk_benchmark/volk_math.py index 753257c237..6fc6cfa78d 100755..100644 --- a/gnuradio-runtime/examples/volk_benchmark/volk_math.py +++ b/gnuradio-runtime/examples/volk_benchmark/volk_math.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks import argparse @@ -87,7 +89,7 @@ def run_tests(func, N, iters): res = format_results(func.__name__, t) return res except AttributeError: - print "\tCould not run test. Skipping." + print("\tCould not run test. Skipping.") return None def main(): @@ -119,7 +121,7 @@ def main(): default=20, help='Number of iterations [default: %(default)s]') parser.add_argument('--tests', type=int, nargs='*', - choices=xrange(len(avail_tests)), + choices=list(range(len(avail_tests))), help='A list of tests to run; can be a single test or a \ space-separated list.') parser.add_argument('--list', action='store_true', @@ -129,8 +131,8 @@ def main(): args = parser.parse_args() if(args.list): - print "Available Tests to Run:" - print "\n".join(["\t{0}: {1}".format(i,f.__name__) for i,f in enumerate(avail_tests)]) + print("Available Tests to Run:") + print("\n".join(["\t{0}: {1}".format(i,f.__name__) for i,f in enumerate(avail_tests)])) sys.exit(0) N = int(args.nitems) @@ -141,7 +143,7 @@ def main(): new_table(conn, label) if args.all: - tests = xrange(len(avail_tests)) + tests = list(range(len(avail_tests))) else: tests = args.tests diff --git a/gnuradio-runtime/examples/volk_benchmark/volk_plot.py b/gnuradio-runtime/examples/volk_benchmark/volk_plot.py index 48f9922054..2e02773e05 100755..100644 --- a/gnuradio-runtime/examples/volk_benchmark/volk_plot.py +++ b/gnuradio-runtime/examples/volk_benchmark/volk_plot.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +from __future__ import division +from __future__ import unicode_literals import sys, math import argparse from volk_test_funcs import * @@ -100,7 +102,7 @@ def main(): # Plot the results - x0 = xrange(len(name_reg)) + x0 = list(range(len(name_reg))) i = 0 for t in (table_data): ydata = [] @@ -119,7 +121,7 @@ def main(): if(args.percent != t): # makes x values for this data set placement # width of bars depends on number of comparisons - wdth = 0.80/(M-1) + wdth = 0.80 / (M-1) x1 = [x + i*wdth for x in x0] i += 1 @@ -130,7 +132,7 @@ def main(): else: # makes x values for this data set placement # width of bars depends on number of comparisons - wdth = 0.80/M + wdth = 0.80 / M x1 = [x + i*wdth for x in x0] i += 1 diff --git a/gnuradio-runtime/examples/volk_benchmark/volk_test_funcs.py b/gnuradio-runtime/examples/volk_benchmark/volk_test_funcs.py index 0f2c84100a..eb39ca7ae1 100644 --- a/gnuradio-runtime/examples/volk_benchmark/volk_test_funcs.py +++ b/gnuradio-runtime/examples/volk_benchmark/volk_test_funcs.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks import math, sys, os, time @@ -122,18 +124,18 @@ class helper(gr.top_block): self.snks = [] self.head = blocks.head(isizeof, N) - for n in xrange(nsrcs): + for n in range(nsrcs): self.srcs.append(blocks.null_source(isizeof)) - for n in xrange(nsnks): + for n in range(nsnks): self.snks.append(blocks.null_sink(osizeof)) self.connect(self.srcs[0], self.head, (self.op,0)) - for n in xrange(1, nsrcs): + for n in range(1, nsrcs): self.connect(self.srcs[n], (self.op,n)) - for n in xrange(nsnks): + for n in range(nsnks): self.connect((self.op,n), self.snks[n]) def timeit(tb, iterations): @@ -143,10 +145,10 @@ def timeit(tb, iterations): ''' r = gr.enable_realtime_scheduling() if r != gr.RT_OK: - print "Warning: failed to enable realtime scheduling" + print("Warning: failed to enable realtime scheduling") times = [] - for i in xrange(iterations): + for i in range(iterations): start_time = time.time() tb.run() end_time = time.time() diff --git a/gnuradio-runtime/examples/volk_benchmark/volk_types.py b/gnuradio-runtime/examples/volk_benchmark/volk_types.py index 546e9629c0..697ec213c1 100755..100644 --- a/gnuradio-runtime/examples/volk_benchmark/volk_types.py +++ b/gnuradio-runtime/examples/volk_benchmark/volk_types.py @@ -1,5 +1,7 @@ #!/usr/bin/env python +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks import argparse @@ -105,7 +107,7 @@ def run_tests(func, N, iters): res = format_results(func.__name__, t) return res except AttributeError: - print "\tCould not run test. Skipping." + print("\tCould not run test. Skipping.") return None def main(): @@ -143,7 +145,7 @@ def main(): default=20, help='Number of iterations [default: %(default)s]') parser.add_argument('--tests', type=int, nargs='*', - choices=xrange(len(avail_tests)), + choices=list(range(len(avail_tests))), help='A list of tests to run; can be a single test or a \ space-separated list.') parser.add_argument('--list', action='store_true', @@ -153,8 +155,8 @@ def main(): args = parser.parse_args() if(args.list): - print "Available Tests to Run:" - print "\n".join(["\t{0}: {1}".format(i,f.__name__) for i,f in enumerate(avail_tests)]) + print("Available Tests to Run:") + print("\n".join(["\t{0}: {1}".format(i,f.__name__) for i,f in enumerate(avail_tests)])) sys.exit(0) N = int(args.nitems) @@ -165,7 +167,7 @@ def main(): new_table(conn, label) if args.all: - tests = xrange(len(avail_tests)) + tests = list(range(len(avail_tests))) else: tests = args.tests diff --git a/gnuradio-runtime/include/gnuradio/sptr_magic.h b/gnuradio-runtime/include/gnuradio/sptr_magic.h index 6deb3062ae..d5e587186a 100644 --- a/gnuradio-runtime/include/gnuradio/sptr_magic.h +++ b/gnuradio-runtime/include/gnuradio/sptr_magic.h @@ -40,7 +40,7 @@ namespace gnuradio { static void create_and_stash_initial_sptr(gr::hier_block2 *p); static void cancel_initial_sptr(gr::hier_block2 *p); }; - }; + } /* * \brief New! Improved! Standard method to get/create the diff --git a/gnuradio-runtime/lib/CMakeLists.txt b/gnuradio-runtime/lib/CMakeLists.txt index 5e414164f8..4fd5a610f6 100644 --- a/gnuradio-runtime/lib/CMakeLists.txt +++ b/gnuradio-runtime/lib/CMakeLists.txt @@ -24,7 +24,7 @@ GR_CHECK_HDR_N_DEF(sys/resource.h HAVE_SYS_RESOURCE_H) # Handle the generated constants ######################################################################## execute_process(COMMAND ${PYTHON_EXECUTABLE} -c - "import time;print time.strftime('%a, %d %b %Y %H:%M:%S', time.gmtime())" + "import time;print(time.strftime('%a, %d %b %Y %H:%M:%S', time.gmtime()))" OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE ) message(STATUS "Loading build date ${BUILD_DATE} into constants...") @@ -48,8 +48,8 @@ list(APPEND gnuradio_runtime_sources ${CMAKE_CURRENT_BINARY_DIR}/constants.cc) ######################################################################## include_directories(${GNURADIO_RUNTIME_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/../include/ - ${VOLK_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR}/../include/ + ${VOLK_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ) diff --git a/gnuradio-runtime/lib/math/gen_sine_table.py b/gnuradio-runtime/lib/math/gen_sine_table.py index d7d11eff11..75e3a0c58f 100755..100644 --- a/gnuradio-runtime/lib/math/gen_sine_table.py +++ b/gnuradio-runtime/lib/math/gen_sine_table.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals import math import sys @@ -38,8 +40,8 @@ def gen_approx_table (f, nentries, min_x, max_x): for i in range (nentries): a = (i * incx) + min_x b = ((i + 1) * incx) + min_x - m = (f(b)-f(a))/(b-a) - c = (3*a+b)*(f(a)-f(b))/(4*(b-a)) + (f((a+b)/2) + f(a))/2 + m = (f(b)-f(a)) / (b-a) + c = (3*a+b)*(f(a)-f(b))/(4*(b-a)) + (f(old_div((a+b) / 2) + f(a)),2) abs_error = c+m*a-f(a) r.append ((m, c, abs_error)) return r diff --git a/gnuradio-runtime/lib/pmt/CMakeLists.txt b/gnuradio-runtime/lib/pmt/CMakeLists.txt index e5c8f2f47e..85b2a4d6e0 100644 --- a/gnuradio-runtime/lib/pmt/CMakeLists.txt +++ b/gnuradio-runtime/lib/pmt/CMakeLists.txt @@ -66,7 +66,7 @@ add_custom_command( ${CMAKE_CURRENT_SOURCE_DIR}/unv_template.h.t ${CMAKE_CURRENT_SOURCE_DIR}/unv_template.cc.t ${CMAKE_CURRENT_SOURCE_DIR}/unv_qa_template.cc.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} -c + COMMAND ${PYTHON_EXECUTABLE} -B -c "import os, sys; srcdir='${CMAKE_CURRENT_SOURCE_DIR}'; sys.path.append(srcdir); os.environ['srcdir']=srcdir; from generate_unv import main; main()" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} VERBATIM diff --git a/gnuradio-runtime/lib/pmt/gen-serial-tags.py b/gnuradio-runtime/lib/pmt/gen-serial-tags.py index 18e927beb5..2ff2240a47 100644 --- a/gnuradio-runtime/lib/pmt/gen-serial-tags.py +++ b/gnuradio-runtime/lib/pmt/gen-serial-tags.py @@ -32,11 +32,14 @@ enum pst_tags { #endif /* INCLUDED_PMT_SERIAL_TAGS_H */ """ +from __future__ import print_function +from __future__ import unicode_literals + import sys, os, re if __name__ == '__main__': if len(sys.argv) != 3: - print "Usage %s <input_scm_file> <output_hdr_file>"%__file__ + print("Usage %s <input_scm_file> <output_hdr_file>"%__file__) exit() input_scm_file, output_hdr_file = sys.argv[1:] enums = list() diff --git a/gnuradio-runtime/lib/pmt/generate_unv.py b/gnuradio-runtime/lib/pmt/generate_unv.py index 6218099fc1..45c57a3fb8 100755..100644 --- a/gnuradio-runtime/lib/pmt/generate_unv.py +++ b/gnuradio-runtime/lib/pmt/generate_unv.py @@ -23,6 +23,7 @@ """ Generate code for uniform numeric vectors """ +from __future__ import unicode_literals import re, os, os.path @@ -93,7 +94,7 @@ using namespace pmt; # set srcdir to the directory that contains Makefile.am try: srcdir = os.environ['srcdir'] -except KeyError, e: +except KeyError as e: srcdir = "." srcdir = srcdir + '/' diff --git a/gnuradio-runtime/lib/sptr_magic.cc b/gnuradio-runtime/lib/sptr_magic.cc index e5e83722fc..bffef04756 100644 --- a/gnuradio-runtime/lib/sptr_magic.cc +++ b/gnuradio-runtime/lib/sptr_magic.cc @@ -102,4 +102,4 @@ namespace gnuradio { s_map.erase(pos); return sptr; } -}; +} diff --git a/gnuradio-runtime/python/build_utils.py b/gnuradio-runtime/python/build_utils.py index cf58a97637..82a2265cc2 100644 --- a/gnuradio-runtime/python/build_utils.py +++ b/gnuradio-runtime/python/build_utils.py @@ -21,6 +21,7 @@ """Misc utilities used at build time """ +from __future__ import unicode_literals import re, os, os.path from build_utils_codes import * @@ -29,7 +30,7 @@ from build_utils_codes import * # set srcdir to the directory that contains Makefile.am try: srcdir = os.environ['srcdir'] -except KeyError, e: +except KeyError as e: srcdir = "." srcdir = srcdir + '/' @@ -39,7 +40,7 @@ try: do_makefile = False else: do_makefile = True -except KeyError, e: +except KeyError as e: do_makefile = False # set do_sources to either true or false dependeing on the environment @@ -48,7 +49,7 @@ try: do_sources = False else: do_sources = True -except KeyError, e: +except KeyError as e: do_sources = True name_dict = {} @@ -127,7 +128,7 @@ def extract_extension (template_name): # we return everything between the penultimate . and .t mo = re.search (r'\.([a-z]+)\.t$', template_name) if not mo: - raise ValueError, "Incorrectly formed template_name '%s'" % (template_name,) + raise ValueError("Incorrectly formed template_name '%s'" % (template_name,)) return mo.group (1) def open_src (name, mode): diff --git a/gnuradio-runtime/python/build_utils_codes.py b/gnuradio-runtime/python/build_utils_codes.py index 9ea96baae4..22a6bdb99b 100644 --- a/gnuradio-runtime/python/build_utils_codes.py +++ b/gnuradio-runtime/python/build_utils_codes.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2004 Free Software Foundation, Inc. # diff --git a/gnuradio-runtime/python/gnuradio/__init__.py b/gnuradio-runtime/python/gnuradio/__init__.py index 062450cb5f..c1735c3d8b 100644 --- a/gnuradio-runtime/python/gnuradio/__init__.py +++ b/gnuradio-runtime/python/gnuradio/__init__.py @@ -7,6 +7,7 @@ While not primarily a simulation tool, GNU Radio does support development of sig GNU Radio is licensed under the GNU General Public License (GPL) version 3. All of the code is copyright of the Free Software Foundation. """ +from __future__ import unicode_literals # This file makes gnuradio a package # The docstring will be associated with the top level of the package. diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py b/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py index 87d2cf5658..beec500023 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/GNURadioControlPortClient.py @@ -27,6 +27,8 @@ Remote Procedure Call (RPC) transports, the Apache Thrift middle-ware RPC is currently the only supported transport. """ +from __future__ import print_function +from __future__ import unicode_literals import exceptions @@ -38,7 +40,7 @@ Two constructors are provided for creating a connection to ControlPort. """ -class GNURadioControlPortClient(): +class GNURadioControlPortClient(object): """ Constructor for creating a ControlPort connection to a specified host / port @@ -113,7 +115,7 @@ class GNURadioControlPortClient(): self.client = None from gnuradio.ctrlport.RPCConnection import RPCMethods - if RPCMethods.has_key(rpcmethod): + if rpcmethod in RPCMethods: from gnuradio.ctrlport.RPCConnectionThrift import RPCConnectionThrift if rpcmethod == 'thrift': #print("making RPCConnectionThrift") @@ -128,5 +130,5 @@ class GNURadioControlPortClient(): if not blockingcallback is None: blockingcallback() else: - print("Unsupported RPC method: ", rpcmethod) + print(("Unsupported RPC method: ", rpcmethod)) raise exceptions.ValueError() diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py b/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py index c5bfd0a8cb..56604d4fac 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/GrDataPlotter.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + from gnuradio import gr from gnuradio import blocks from gnuradio import filter @@ -31,7 +34,7 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4 and gr-qtgui." + print("Error: Program requires PyQt4 and gr-qtgui.") sys.exit(1) class GrDataPlotParent(gr.top_block, QtGui.QWidget): @@ -62,7 +65,7 @@ class GrDataPlotParent(gr.top_block, QtGui.QWidget): self.layout.removeWidget(self.py_window) self.disconnect(self.thr, (self.snk, 0)) self.disconnect(self.src[0], self.thr) - for n in xrange(1, self._ncons): + for n in range(1, self._ncons): self.disconnect(self.src[n], (self.snk,n)) self._ncons = nconnections @@ -75,7 +78,7 @@ class GrDataPlotParent(gr.top_block, QtGui.QWidget): self._last_data = [] self.src = [] - for n in xrange(self._ncons): + for n in range(self._ncons): self.set_line_label(n, self.knobnames[n]) self._last_data.append(int(self._npts)*[0,]) @@ -142,7 +145,7 @@ class GrDataPlotParent(gr.top_block, QtGui.QWidget): if(self._npts != npts): # Adjust buffers to accomodate new settings - for n in xrange(self._ncons): + for n in range(self._ncons): if(npts < self._npts): if(self._data_len[n] < npts): self._last_data[n] = self._last_data[n][0:npts] @@ -156,7 +159,7 @@ class GrDataPlotParent(gr.top_block, QtGui.QWidget): if(self._stripchart): # Update the plot data depending on type - for n in xrange(self._ncons): + for n in range(self._ncons): if(type(data[n]) == list): data[n] = self.data_to_complex(data[n]) if(len(data[n]) > self._npts): @@ -179,7 +182,7 @@ class GrDataPlotParent(gr.top_block, QtGui.QWidget): self._last_data[n].append(data[n]) self.src[n].set_data(self._last_data[n]) else: - for n in xrange(self._ncons): + for n in range(self._ncons): if(type(data[n]) != list): data[n] = [data[n],] data[n] = self.data_to_complex(data[n]) @@ -407,11 +410,11 @@ class GrTimeRasterB(GrDataPlotParent): self.snk.set_line_label(n, self.knobnames[n]) -class GrDataPlotterValueTable: +class GrDataPlotterValueTable(object): def __init__(self, uid, parent, x, y, xsize, ysize, headers=['Statistic Key ( Source Block :: Stat Name ) ', 'Curent Value', 'Units', 'Description']): - # must encapsulate, cuz Qt's bases are not classes + # must encapsulate, cuz Qt's bases are not classes self.uid = uid self.treeWidget = QtGui.QTreeWidget(parent) self.treeWidget.setColumnCount(len(headers)) @@ -434,7 +437,7 @@ class GrDataPlotterValueTable: # itemKey is the text in the first column of a QTreeWidgetItem itemKey = str(item.text(0)) - if itemKey in knobs.keys(): + if itemKey in list(knobs.keys()): # This key was found in the tree, update its values. foundKeys.append(itemKey) @@ -465,7 +468,7 @@ class GrDataPlotterValueTable: deleteKeys.append(itemKey) # Add items to tree that are not currently in the tree. - for k in knobs.keys(): + for k in list(knobs.keys()): if k not in foundKeys: v = knobs[k].value if(type(v) == ControlPort.complex): diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py index 1b129534c9..b85c827f72 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnection.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2015 Free Software Foundation, Inc. # diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py index 522c74117b..466fc9fc04 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/RPCConnectionThrift.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from thrift import Thrift from thrift.transport import TSocket from thrift.transport import TTransport @@ -30,7 +31,7 @@ from gnuradio import gr import pmt import sys -class ThriftRadioClient: +class ThriftRadioClient(object): def __init__(self, host, port): self.tsocket = TSocket.TSocket(host, port) self.transport = TTransport.TBufferedTransport(self.tsocket) @@ -55,7 +56,7 @@ Args: """ class RPCConnectionThrift(RPCConnection.RPCConnection): - class Knob(): + class Knob(object): def __init__(self, key, value=None, ktype=0): (self.key, self.value, self.ktype) = (key, value, ktype) @@ -144,7 +145,7 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): def properties(self, *args): knobprops = self.thriftclient.radio.properties(*args) - for key, knobprop in knobprops.iteritems(): + for key, knobprop in list(knobprops.items()): #print("key:", key, "value:", knobprop, "type:", knobprop.type) knobprops[key].min = self.unpackKnob(key, knobprop.min) knobprops[key].max = self.unpackKnob(key, knobprop.max) @@ -153,28 +154,28 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): def getKnobs(self, *args): result = {} - for key, knob in self.thriftclient.radio.getKnobs(*args).iteritems(): + for key, knob in list(self.thriftclient.radio.getKnobs(*args).items()): #print("key:", key, "value:", knob, "type:", knob.type) result[key] = self.unpackKnob(key, knob) # If complex, convert to Python complex # FIXME: better list iterator way to handle this? if(knob.type == self.BaseTypes.C32VECTOR): - for i in xrange(len(result[key].value)): + for i in range(len(result[key].value)): result[key].value[i] = complex(result[key].value[i].re, result[key].value[i].im) return result def getKnobsRaw(self, *args): result = {} - for key, knob in self.thriftclient.radio.getKnobs(*args).iteritems(): + for key, knob in list(self.thriftclient.radio.getKnobs(*args).items()): #print("key:", key, "value:", knob, "type:", knob.type) result[key] = knob return result def getRe(self,*args): result = {} - for key, knob in self.thriftclient.radio.getRe(*args).iteritems(): + for key, knob in list(self.thriftclient.radio.getRe(*args).items()): result[key] = self.unpackKnob(key, knob) return result @@ -182,7 +183,7 @@ class RPCConnectionThrift(RPCConnection.RPCConnection): if(type(*args) == dict): a = dict(*args) result = {} - for key, knob in a.iteritems(): + for key, knob in list(a.items()): result[key] = self.packKnob(knob) self.thriftclient.radio.setKnobs(result) elif(type(*args) == list or type(*args) == tuple): diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/__init__.py b/gnuradio-runtime/python/gnuradio/ctrlport/__init__.py index 8f33d65bbc..363d42a68e 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/__init__.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/__init__.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import +from __future__ import unicode_literals # # Copyright 2012 Free Software Foundation, Inc. # @@ -22,7 +24,7 @@ # import swig generated symbols into the ctrlport namespace #from ctrlport_swig import * -from monitor import * +from .monitor import * # import any pure python here #import GNURadio diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx index 15a2153a0f..302275feb1 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx +++ b/gnuradio-runtime/python/gnuradio/ctrlport/gr-perf-monitorx @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + import sys, time, re, pprint import random,math,operator try: @@ -36,14 +38,14 @@ try: try: from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar except ImportError: - print sys.argv[0], "could not load QTAgg backend." + print(sys.argv[0], "could not load QTAgg backend.") sys.exit(1) from matplotlib.figure import Figure except ImportError: - print sys.argv[0], "requires networkx and matplotlib.", \ - "Please check that they are installed and try again." + print(sys.argv[0], "requires networkx and matplotlib.", + "Please check that they are installed and try again.") sys.exit(1) from PyQt4 import QtCore,Qt @@ -282,7 +284,7 @@ class ConInfoDialog(QtGui.QDialog): class DataTable(QtGui.QWidget): def update(self): - print "update" + print("update") def closeEvent(self, event): self.timer = None @@ -498,7 +500,7 @@ class MForm(QtGui.QWidget): self.clockSel.setCurrentIndex(self.clockSelIdx) self.prevent_clock_change = False except: - print "WARNING: Failed to get current clock setting!" + print("WARNING: Failed to get current clock setting!") nodes_stream = self.G_stream.nodes() nodes_msg = self.G_msg.nodes() @@ -571,7 +573,7 @@ class MForm(QtGui.QWidget): self.parent.statusBar().showMessage("Current GNU Radio Control Port Query Latency: %f ms"%\ (latency*1000)) - except Exception, e: + except Exception as e: sys.stderr.write("gr-perf-monitorx: radio.getKnobs threw exception ({0}).\n".format(e)) if(type(self.parent) is MAINWindow): # Find window of connection @@ -625,7 +627,7 @@ class MForm(QtGui.QWidget): return; idx = self.clockSel.currentIndex(); clk = self.clocks.values()[idx] -# print "UPDATE CLOCK!!! %d -> %d"%(idx,clk); +# print("UPDATE CLOCK!!! %d -> %d"%(idx,clk);) k = self.radioclient.getKnobs([self.clockKey]); k[self.clockKey].value = clk; km = {}; diff --git a/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py b/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py index f651be2449..49b66e9830 100644 --- a/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py +++ b/gnuradio-runtime/python/gnuradio/ctrlport/monitor.py @@ -20,12 +20,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + import sys, subprocess, re, signal, time, atexit, os from gnuradio import gr -class monitor: +class monitor(object): def __init__(self,tool="gr-ctrlport-monitor"): - print "ControlPort Monitor running." + print("ControlPort Monitor running.") self.started = False self.tool = tool atexit.register(self.shutdown) @@ -38,35 +41,35 @@ class monitor: gr.prefs().singleton().set_bool("PerfCounters","on",True); gr.prefs().singleton().set_bool("PerfCounters","export",True); except: - print "no support for gr.prefs setting" + print("no support for gr.prefs setting") def __del__(self): if(self.started): self.stop() def start(self): - print "monitor::endpoints() = %s" % (gr.rpcmanager_get().endpoints()) + print("monitor::endpoints() = %s" % (gr.rpcmanager_get().endpoints())) try: cmd = map(lambda a: [self.tool, re.search("-h (\S+|\d+\.\d+\.\d+\.\d+)",a).group(1), re.search("-p (\d+)",a).group(1)], gr.rpcmanager_get().endpoints())[0] - print "running: %s"%(str(cmd)) + print("running: %s"%(str(cmd))) self.proc = subprocess.Popen(cmd); self.started = True except: self.proc = None - print "failed to to start ControlPort Monitor on specified port" + print("failed to to start ControlPort Monitor on specified port") def stop(self): if(self.proc): if(self.proc.returncode == None): - print "\tcalling stop on shutdown" + print("\tcalling stop on shutdown") self.proc.terminate() else: - print "\tno proc to shut down, exiting" + print("\tno proc to shut down, exiting") def shutdown(self): - print "ctrlport.monitor received shutdown signal" + print("ctrlport.monitor received shutdown signal") if(self.started): self.stop() diff --git a/gnuradio-runtime/python/gnuradio/eng_arg.py b/gnuradio-runtime/python/gnuradio/eng_arg.py index 05cd8a1f2a..5983352443 100644 --- a/gnuradio-runtime/python/gnuradio/eng_arg.py +++ b/gnuradio-runtime/python/gnuradio/eng_arg.py @@ -22,6 +22,7 @@ ''' Add support for engineering notation to argparse.ArgumentParser ''' +from __future__ import unicode_literals import argparse from gnuradio import eng_notation diff --git a/gnuradio-runtime/python/gnuradio/eng_notation.py b/gnuradio-runtime/python/gnuradio/eng_notation.py index d23f9005f0..5a3a216ee4 100644 --- a/gnuradio-runtime/python/gnuradio/eng_notation.py +++ b/gnuradio-runtime/python/gnuradio/eng_notation.py @@ -21,6 +21,7 @@ """ Display numbers as strings using engineering notation. """ +from __future__ import unicode_literals scale_factor = {} scale_factor['E'] = 1e18 @@ -66,7 +67,7 @@ def str_to_num (value): try: scale = 1.0 suffix = value[-1] - if scale_factor.has_key (suffix): + if suffix in scale_factor: return float (value[0:-1]) * scale_factor[suffix] return float (value) except: diff --git a/gnuradio-runtime/python/gnuradio/eng_option.py b/gnuradio-runtime/python/gnuradio/eng_option.py index ae000fe442..565780be28 100644 --- a/gnuradio-runtime/python/gnuradio/eng_option.py +++ b/gnuradio-runtime/python/gnuradio/eng_option.py @@ -20,10 +20,12 @@ # '''Add support for engineering notation to optparse.OptionParser''' +from __future__ import absolute_import +from __future__ import unicode_literals from copy import copy from optparse import Option, OptionValueError -import eng_notation +from . import eng_notation def check_eng_float (option, opt, value): try: diff --git a/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt b/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt index fc966b8ece..7c82b1df35 100644 --- a/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt +++ b/gnuradio-runtime/python/gnuradio/gr/CMakeLists.txt @@ -22,6 +22,7 @@ include(GrPython) GR_PYTHON_INSTALL(FILES __init__.py + exceptions.py tag_utils.py packet_utils.py gateway.py @@ -48,6 +49,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gnuradio-runtime/python/gnuradio/gr/__init__.py b/gnuradio-runtime/python/gnuradio/gr/__init__.py index 9717390e3e..72f54e9f42 100644 --- a/gnuradio-runtime/python/gnuradio/gr/__init__.py +++ b/gnuradio-runtime/python/gnuradio/gr/__init__.py @@ -24,6 +24,8 @@ """ Core contents. """ +from __future__ import absolute_import +from __future__ import unicode_literals # This is the main GNU Radio python module. # We pull the swig output and the other modules into the gnuradio.gr namespace @@ -31,20 +33,20 @@ Core contents. # If gnuradio is installed then the swig output will be in this directory. # Otherwise it will reside in ../../../swig. -import os +import os, sys try: - from runtime_swig import * + from .runtime_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "..", "swig")) - from runtime_swig import * + from .runtime_swig import * -from exceptions import * -from top_block import * -from hier_block2 import * -from tag_utils import * -from gateway import basic_block, sync_block, decim_block, interp_block +from .exceptions import * +from .top_block import * +from .hier_block2 import * +from .tag_utils import * +from .gateway import basic_block, sync_block, decim_block, interp_block # Force the preference database to be initialized prefs = prefs.singleton diff --git a/gnuradio-runtime/python/gnuradio/gr/exceptions.py b/gnuradio-runtime/python/gnuradio/gr/exceptions.py index dba04750bc..1b7fd025b7 100644 --- a/gnuradio-runtime/python/gnuradio/gr/exceptions.py +++ b/gnuradio-runtime/python/gnuradio/gr/exceptions.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2004 Free Software Foundation, Inc. # diff --git a/gnuradio-runtime/python/gnuradio/gr/gateway.py b/gnuradio-runtime/python/gnuradio/gr/gateway.py index 2e46bca430..2bc1b21591 100644 --- a/gnuradio-runtime/python/gnuradio/gr/gateway.py +++ b/gnuradio-runtime/python/gnuradio/gr/gateway.py @@ -19,18 +19,23 @@ # Boston, MA 02110-1301, USA. # -import runtime_swig as gr -from runtime_swig import io_signature, io_signaturev -from runtime_swig import block_gw_message_type -from runtime_swig import block_gateway +from __future__ import print_function +from __future__ import unicode_literals + + import numpy +from . import runtime_swig as gr +from .runtime_swig import io_signature, io_signaturev +from .runtime_swig import block_gw_message_type +from .runtime_swig import block_gateway + ######################################################################## # Magic to turn pointers into numpy arrays # http://docs.scipy.org/doc/numpy/reference/arrays.interface.html ######################################################################## def pointer_to_ndarray(addr, dtype, nitems): - class array_like: + class array_like(object): __array_interface__ = { 'data' : (int(addr), False), 'typestr' : dtype.base.str, @@ -87,13 +92,13 @@ class gateway_block(object): #ensure that the sigs are iterable dtypes def sig_to_dtype_sig(sig): if sig is None: sig = () - return map(numpy.dtype, sig) + return list(map(numpy.dtype, sig)) self.__in_sig = sig_to_dtype_sig(in_sig) self.__out_sig = sig_to_dtype_sig(out_sig) #cache the ranges to iterate when dispatching work - self.__in_indexes = range(len(self.__in_sig)) - self.__out_indexes = range(len(self.__out_sig)) + self.__in_indexes = list(range(len(self.__in_sig))) + self.__out_indexes = list(range(len(self.__out_sig))) #convert the signatures into gr.io_signatures def sig_to_gr_io_sigv(sig): diff --git a/gnuradio-runtime/python/gnuradio/gr/gr_threading.py b/gnuradio-runtime/python/gnuradio/gr/gr_threading.py index 5d6f0fdaf9..cb0519f6f6 100644 --- a/gnuradio-runtime/python/gnuradio/gr/gr_threading.py +++ b/gnuradio-runtime/python/gnuradio/gr/gr_threading.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import +from __future__ import unicode_literals # # Copyright 2005 Free Software Foundation, Inc. # @@ -25,10 +27,10 @@ from sys import version_info as _version_info if _version_info[0:2] == (2, 3): #print "Importing gr_threading_23" - from gr_threading_23 import * + from .gr_threading_23 import * elif _version_info[0:2] == (2, 4): #print "Importing gr_threading_24" - from gr_threading_24 import * + from .gr_threading_24 import * else: # assume the patch was applied... #print "Importing system provided threading" diff --git a/gnuradio-runtime/python/gnuradio/gr/gr_threading_23.py b/gnuradio-runtime/python/gnuradio/gr/gr_threading_23.py index dee8034c1c..ff33224d58 100644 --- a/gnuradio-runtime/python/gnuradio/gr/gr_threading_23.py +++ b/gnuradio-runtime/python/gnuradio/gr/gr_threading_23.py @@ -4,15 +4,18 @@ # It's been patched to fix a problem with join, where a KeyboardInterrupt # caused a lock to be left in the acquired state. +from __future__ import print_function +from __future__ import unicode_literals + import sys as _sys try: - import thread + import _thread except ImportError: del _sys.modules[__name__] raise -from StringIO import StringIO as _StringIO +from io import StringIO as _StringIO from time import time as _time, sleep as _sleep from traceback import print_exc as _print_exc @@ -21,11 +24,11 @@ __all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', 'Timer', 'setprofile', 'settrace'] -_start_new_thread = thread.start_new_thread -_allocate_lock = thread.allocate_lock -_get_ident = thread.get_ident -ThreadError = thread.error -del thread +_start_new_thread = _thread.start_new_thread +_allocate_lock = _thread.allocate_lock +_get_ident = _thread.get_ident +ThreadError = _thread.error +del _thread # Debug support (adapted from ihooks.py). @@ -127,8 +130,9 @@ class _RLock(_Verbose): # Internal methods used by condition variables - def _acquire_restore(self, (count, owner)): + def _acquire_restore(self, lock): self.__block.acquire() + count, owner = lock self.__count = count self.__owner = owner if __debug__: @@ -313,7 +317,7 @@ class _BoundedSemaphore(_Semaphore): def release(self): if self._Semaphore__value >= self._initial_value: - raise ValueError, "Semaphore released too many times" + raise ValueError("Semaphore released too many times") return _Semaphore.release(self) @@ -627,7 +631,7 @@ def activeCount(): def enumerate(): _active_limbo_lock.acquire() - active = _active.values() + _limbo.values() + active = list(_active.values()) + list(_limbo.values()) _active_limbo_lock.release() return active @@ -698,7 +702,7 @@ def _test(): def run(self): while self.count > 0: item = self.queue.get() - print item + print(item) self.count = self.count - 1 NP = 3 diff --git a/gnuradio-runtime/python/gnuradio/gr/gr_threading_24.py b/gnuradio-runtime/python/gnuradio/gr/gr_threading_24.py index 8539bfc047..efb20dca59 100644 --- a/gnuradio-runtime/python/gnuradio/gr/gr_threading_24.py +++ b/gnuradio-runtime/python/gnuradio/gr/gr_threading_24.py @@ -4,10 +4,13 @@ # It's been patched to fix a problem with join, where a KeyboardInterrupt # caused a lock to be left in the acquired state. +from __future__ import print_function +from __future__ import unicode_literals + import sys as _sys try: - import thread + import _thread except ImportError: del _sys.modules[__name__] raise @@ -21,11 +24,11 @@ __all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event', 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', 'Timer', 'setprofile', 'settrace', 'local'] -_start_new_thread = thread.start_new_thread -_allocate_lock = thread.allocate_lock -_get_ident = thread.get_ident -ThreadError = thread.error -del thread +_start_new_thread = _thread.start_new_thread +_allocate_lock = _thread.allocate_lock +_get_ident = _thread.get_ident +ThreadError = _thread.error +del _thread # Debug support (adapted from ihooks.py). @@ -127,8 +130,9 @@ class _RLock(_Verbose): # Internal methods used by condition variables - def _acquire_restore(self, (count, owner)): + def _acquire_restore(self, lock): self.__block.acquire() + count, owner = lock self.__count = count self.__owner = owner if __debug__: @@ -311,7 +315,7 @@ class _BoundedSemaphore(_Semaphore): def release(self): if self._Semaphore__value >= self._initial_value: - raise ValueError, "Semaphore released too many times" + raise ValueError("Semaphore released too many times") return _Semaphore.release(self) @@ -688,7 +692,7 @@ def activeCount(): def enumerate(): _active_limbo_lock.acquire() - active = _active.values() + _limbo.values() + active = list(_active.values()) + list(_limbo.values()) _active_limbo_lock.release() return active @@ -700,7 +704,7 @@ _MainThread() # module, or from the python fallback try: - from thread import _local as local + from _thread import _local as local except ImportError: from _threading_local import local @@ -767,7 +771,7 @@ def _test(): def run(self): while self.count > 0: item = self.queue.get() - print item + print(item) self.count = self.count - 1 NP = 3 diff --git a/gnuradio-runtime/python/gnuradio/gr/hier_block2.py b/gnuradio-runtime/python/gnuradio/gr/hier_block2.py index 3f4c6aa9c7..8d0533c71c 100644 --- a/gnuradio-runtime/python/gnuradio/gr/hier_block2.py +++ b/gnuradio-runtime/python/gnuradio/gr/hier_block2.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2006,2007,2014 Free Software Foundation, Inc. # @@ -21,7 +22,7 @@ import functools -from runtime_swig import hier_block2_swig, dot_graph +from .runtime_swig import hier_block2_swig, dot_graph import pmt diff --git a/gnuradio-runtime/python/gnuradio/gr/packet_utils.py b/gnuradio-runtime/python/gnuradio/gr/packet_utils.py index 720cfd962f..770a5c0b36 100644 --- a/gnuradio-runtime/python/gnuradio/gr/packet_utils.py +++ b/gnuradio-runtime/python/gnuradio/gr/packet_utils.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr import pmt @@ -28,9 +31,9 @@ def make_lengthtags(lengths, offsets, tagname='length', vlen=1): assert(len(offsets) == len(lengths)) for offset, length in zip(offsets, lengths): tag = gr.tag_t() - tag.offset = offset/vlen + tag.offset = offset // vlen tag.key = pmt.string_to_symbol(tagname) - tag.value = pmt.from_long(length/vlen) + tag.value = pmt.from_long(length // vlen) tags.append(tag) return tags @@ -73,7 +76,7 @@ def count_bursts(data, tags, tsb_tag_key, vlen=1): if pos in lengths: if in_packet: print("Got tag at pos {0} current packet_pos is {1}".format(pos, packet_pos)) - raise StandardError("Received packet tag while in packet.") + raise Exception("Received packet tag while in packet.") packet_pos = -1 packet_length = lengths[pos] in_packet = True @@ -128,9 +131,9 @@ def packets_to_vectors(packets, tsb_tag_key, vlen=1): for packet in packets: data.extend(packet) tag = gr.tag_t() - tag.offset = offset/vlen + tag.offset = offset // vlen tag.key = pmt.string_to_symbol(tsb_tag_key) - tag.value = pmt.from_long(len(packet)/vlen) + tag.value = pmt.from_long(len(packet) // vlen) tags.append(tag) offset = offset + len(packet) return data, tags diff --git a/gnuradio-runtime/python/gnuradio/gr/pubsub.py b/gnuradio-runtime/python/gnuradio/gr/pubsub.py index 90568418fc..25108b8f70 100644 --- a/gnuradio-runtime/python/gnuradio/gr/pubsub.py +++ b/gnuradio-runtime/python/gnuradio/gr/pubsub.py @@ -26,43 +26,46 @@ Abstract GNU Radio publisher/subscriber interface This is a proof of concept implementation, will likely change significantly. """ +from __future__ import print_function +from __future__ import unicode_literals + class pubsub(dict): def __init__(self): - self._publishers = { } - self._subscribers = { } - self._proxies = { } + self._publishers = { } + self._subscribers = { } + self._proxies = { } def __missing__(self, key, value=None): - dict.__setitem__(self, key, value) - self._publishers[key] = None - self._subscribers[key] = [] - self._proxies[key] = None + dict.__setitem__(self, key, value) + self._publishers[key] = None + self._subscribers[key] = [] + self._proxies[key] = None def __setitem__(self, key, val): - if not self.has_key(key): - self.__missing__(key, val) - elif self._proxies[key] is not None: - (p, newkey) = self._proxies[key] - p[newkey] = val - else: - dict.__setitem__(self, key, val) - for sub in self._subscribers[key]: - # Note this means subscribers will get called in the thread - # context of the 'set' caller. - sub(val) + if key not in self: + self.__missing__(key, val) + elif self._proxies[key] is not None: + (p, newkey) = self._proxies[key] + p[newkey] = val + else: + dict.__setitem__(self, key, val) + for sub in self._subscribers[key]: + # Note this means subscribers will get called in the thread + # context of the 'set' caller. + sub(val) def __getitem__(self, key): - if not self.has_key(key): self.__missing__(key) - if self._proxies[key] is not None: - (p, newkey) = self._proxies[key] - return p[newkey] - elif self._publishers[key] is not None: - return self._publishers[key]() - else: - return dict.__getitem__(self, key) + if key not in self: self.__missing__(key) + if self._proxies[key] is not None: + (p, newkey) = self._proxies[key] + return p[newkey] + elif self._publishers[key] is not None: + return self._publishers[key]() + else: + return dict.__getitem__(self, key) def publish(self, key, publisher): - if not self.has_key(key): self.__missing__(key) + if key not in self: self.__missing__(key) if self._proxies[key] is not None: (p, newkey) = self._proxies[key] p.publish(newkey, publisher) @@ -70,7 +73,7 @@ class pubsub(dict): self._publishers[key] = publisher def subscribe(self, key, subscriber): - if not self.has_key(key): self.__missing__(key) + if key not in self: self.__missing__(key) if self._proxies[key] is not None: (p, newkey) = self._proxies[key] p.subscribe(newkey, subscriber) @@ -92,9 +95,9 @@ class pubsub(dict): self._subscribers[key].remove(subscriber) def proxy(self, key, p, newkey=None): - if not self.has_key(key): self.__missing__(key) - if newkey is None: newkey = key - self._proxies[key] = (p, newkey) + if key not in self: self.__missing__(key) + if newkey is None: newkey = key + self._proxies[key] = (p, newkey) def unproxy(self, key): self._proxies[key] = None @@ -105,49 +108,49 @@ if __name__ == "__main__": o = pubsub() # Non-existent key gets auto-created with None value - print "Auto-created key 'foo' value:", o['foo'] + print("Auto-created key 'foo' value:", o['foo']) # Add some subscribers # First is a bare function def print_len(x): - print "len=%i" % (len(x), ) + print("len=%i" % (len(x), )) o.subscribe('foo', print_len) # The second is a class member function class subber(object): - def __init__(self, param): - self._param = param - def printer(self, x): - print self._param, `x` + def __init__(self, param): + self._param = param + def printer(self, x): + print(self._param, repr(x)) s = subber('param') o.subscribe('foo', s.printer) # The third is a lambda function - o.subscribe('foo', lambda x: sys.stdout.write('val='+`x`+'\n')) + o.subscribe('foo', lambda x: sys.stdout.write('val='+repr(x)+'\n')) # Update key 'foo', will notify subscribers - print "Updating 'foo' with three subscribers:" + print("Updating 'foo' with three subscribers:") o['foo'] = 'bar'; # Remove first subscriber o.unsubscribe('foo', print_len) # Update now will only trigger second and third subscriber - print "Updating 'foo' after removing a subscriber:" + print("Updating 'foo' after removing a subscriber:") o['foo'] = 'bar2'; # Publish a key as a function, in this case, a lambda function o.publish('baz', lambda : 42) - print "Published value of 'baz':", o['baz'] + print("Published value of 'baz':", o['baz']) # Unpublish the key o.unpublish('baz') # This will return None, as there is no publisher - print "Value of 'baz' with no publisher:", o['baz'] + print("Value of 'baz' with no publisher:", o['baz']) # Set 'baz' key, it gets cached o['baz'] = 'bazzz' # Now will return cached value, since no provider - print "Cached value of 'baz' after being set:", o['baz'] + print("Cached value of 'baz' after being set:", o['baz']) diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_feval.py b/gnuradio-runtime/python/gnuradio/gr/qa_feval.py index 9018e12f36..078e2bf789 100755..100644 --- a/gnuradio-runtime/python/gnuradio/gr/qa_feval.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_feval.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest class my_add2_dd(gr.feval_dd): diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_flowgraph.py b/gnuradio-runtime/python/gnuradio/gr/qa_flowgraph.py index fa4fd4910e..f5802c51bc 100755..100644 --- a/gnuradio-runtime/python/gnuradio/gr/qa_flowgraph.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_flowgraph.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import time import pmt from gnuradio import gr, gr_unittest, blocks diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py b/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py index 005331c2ec..c8f3d1a5f9 100644 --- a/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_hier_block2.py @@ -19,9 +19,12 @@ # Boston, MA 02110-1301, USA. # -import pmt, time +import time + from gnuradio import gr_unittest, blocks, gr, analog from gnuradio.gr.hier_block2 import _multiple_endpoints, _optional_endpoints +import pmt + class test_hblk(gr.hier_block2): def __init__(self, io_sig=1*[gr.sizeof_gr_complex], ndebug=2): @@ -126,7 +129,7 @@ class test_hier_block2(gr_unittest.TestCase): time.sleep(1) tb.stop() tb.wait() - + def test_012(self): s, st, h, k = analog.sig_source_c(44100, analog.GR_COS_WAVE, 440, 1.0, 0.0), blocks.message_strobe(pmt.PMT_NIL, 100), blocks.head(gr.sizeof_gr_complex, 1000), test_hblk([gr.sizeof_gr_complex], 16) tb = gr.top_block() @@ -139,4 +142,3 @@ class test_hier_block2(gr_unittest.TestCase): if __name__ == '__main__': gr_unittest.run(test_hier_block2, "test_hier_block2.xml") - diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_kludged_imports.py b/gnuradio-runtime/python/gnuradio/gr/qa_kludged_imports.py index f80188c9fc..e2e9047c9b 100755..100644 --- a/gnuradio-runtime/python/gnuradio/gr/qa_kludged_imports.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_kludged_imports.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest class test_kludged_imports (gr_unittest.TestCase): diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_random.py b/gnuradio-runtime/python/gnuradio/gr/qa_random.py index d3e5410454..6fbf5e478a 100644 --- a/gnuradio-runtime/python/gnuradio/gr/qa_random.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_random.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest import numpy as np diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py index 55b62a12ac..3d7b99d12c 100755..100644 --- a/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py +++ b/gnuradio-runtime/python/gnuradio/gr/qa_tag_utils.py @@ -20,12 +20,12 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + + from gnuradio import gr, gr_unittest +import pmt -try: - import pmt_swig as pmt -except ImportError: - import pmt class test_tag_utils (gr_unittest.TestCase): @@ -111,6 +111,6 @@ class test_tag_utils (gr_unittest.TestCase): if __name__ == '__main__': - print 'hi' + print('hi') gr_unittest.run(test_tag_utils, "test_tag_utils.xml") diff --git a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py index 0d4805a8b8..d054865c22 100644 --- a/gnuradio-runtime/python/gnuradio/gr/tag_utils.py +++ b/gnuradio-runtime/python/gnuradio/gr/tag_utils.py @@ -1,6 +1,7 @@ +from __future__ import unicode_literals import pmt -import runtime_swig as gr +from . import runtime_swig as gr class PythonTag(object): " Python container for tags " @@ -51,29 +52,29 @@ def python_to_tag(tag_struct): good = False tag = gr.tag_t() if(type(tag_struct) == dict): - if(tag_struct.has_key('offset')): - if(isinstance(tag_struct['offset'], (int,long))): + if('offset' in tag_struct): + if(isinstance(tag_struct['offset'], int)): tag.offset = tag_struct['offset'] good = True - if(tag_struct.has_key('key')): + if('key' in tag_struct): if(isinstance(tag_struct['key'], pmt.swig_int_ptr)): tag.key = tag_struct['key'] good = True - if(tag_struct.has_key('value')): + if('value' in tag_struct): if(isinstance(tag_struct['value'], pmt.swig_int_ptr)): tag.value = tag_struct['value'] good = True - if(tag_struct.has_key('srcid')): + if('srcid' in tag_struct): if(isinstance(tag_struct['srcid'], pmt.swig_int_ptr)): tag.srcid = tag_struct['srcid'] good = True elif(type(tag_struct) == list or type(tag_struct) == tuple): if(len(tag_struct) == 4): - if(isinstance(tag_struct[0], (int,long))): + if(isinstance(tag_struct[0], int)): tag.offset = tag_struct[0] good = True @@ -90,7 +91,7 @@ def python_to_tag(tag_struct): good = True elif(len(tag_struct) == 3): - if(isinstance(tag_struct[0], (int,long))): + if(isinstance(tag_struct[0], int)): tag.offset = tag_struct[0] good = True diff --git a/gnuradio-runtime/python/gnuradio/gr/top_block.py b/gnuradio-runtime/python/gnuradio/gr/top_block.py index 2efcbd9aae..e7608bf5e9 100644 --- a/gnuradio-runtime/python/gnuradio/gr/top_block.py +++ b/gnuradio-runtime/python/gnuradio/gr/top_block.py @@ -19,15 +19,18 @@ # Boston, MA 02110-1301, USA. # -from runtime_swig import top_block_swig, \ - top_block_wait_unlocked, top_block_run_unlocked, \ - top_block_start_unlocked, top_block_stop_unlocked, \ - top_block_unlock_unlocked, dot_graph_tb +from __future__ import absolute_import +from __future__ import unicode_literals + +from .runtime_swig import (top_block_swig, + top_block_wait_unlocked, top_block_run_unlocked, + top_block_start_unlocked, top_block_stop_unlocked, + top_block_unlock_unlocked, dot_graph_tb) #import gnuradio.gr.gr_threading as _threading -import gr_threading as _threading +from . import gr_threading as _threading -from hier_block2 import hier_block2 +from .hier_block2 import hier_block2 class _top_block_waiter(_threading.Thread): """ diff --git a/gnuradio-runtime/python/gnuradio/gr_unittest.py b/gnuradio-runtime/python/gnuradio/gr_unittest.py index c729566e88..e9d35d6869 100755..100644 --- a/gnuradio-runtime/python/gnuradio/gr_unittest.py +++ b/gnuradio-runtime/python/gnuradio/gr_unittest.py @@ -22,10 +22,16 @@ """ GNU radio specific extension of unittest. """ +from __future__ import absolute_import +from __future__ import unicode_literals +from __future__ import division + +import os +import stat import unittest -import gr_xmlrunner -import sys, os, stat +from . import gr_xmlrunner + class TestCase(unittest.TestCase): """A subclass of unittest.TestCase that adds additional assertions @@ -43,11 +49,12 @@ class TestCase(unittest.TestCase): as significant digits (measured from the most signficant digit). """ if round(second.real-first.real, places) != 0: - raise self.failureException, \ - (msg or '%s != %s within %s places' % (`first`, `second`, `places` )) + raise self.failureException( + msg or '%r != %r within %r places' % (first, second, places)) if round(second.imag-first.imag, places) != 0: - raise self.failureException, \ - (msg or '%s != %s within %s places' % (`first`, `second`, `places` )) + raise self.failureException( + msg or '%r != %r within %r places' % (first, second, places) + ) def assertComplexAlmostEqual2 (self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None): """ @@ -57,48 +64,52 @@ class TestCase(unittest.TestCase): return if abs(ref) > abs_eps: - if abs(ref-x)/abs(ref) > rel_eps: - raise self.failureException, \ - (msg or '%s != %s rel_error = %s rel_limit = %s' % ( - `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` )) + if abs(ref-x) / abs(ref) > rel_eps: + raise self.failureException( + msg or '%r != %r rel_error = %r rel_limit = %r' % ( + ref, x, abs(ref-x) / abs(ref), rel_eps + ) + ) else: - raise self.failureException, \ - (msg or '%s != %s rel_error = %s rel_limit = %s' % ( - `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` )) + raise self.failureException( + msg or '%r != %r rel_error = %r rel_limit = %r' % ( + ref, x, abs(ref-x) / abs(ref), rel_eps + ) + ) def assertComplexTuplesAlmostEqual (self, a, b, places=7, msg=None): self.assertEqual (len(a), len(b)) - for i in xrange (len(a)): + for i in range (len(a)): self.assertComplexAlmostEqual (a[i], b[i], places, msg) def assertComplexTuplesAlmostEqual2 (self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None): self.assertEqual (len(ref), len(x)) - for i in xrange (len(ref)): + for i in range (len(ref)): try: self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) - except self.failureException, e: + except self.failureException as e: #sys.stderr.write("index = %d " % (i,)) - #sys.stderr.write("%s\n" % (e,)) + #sys.stderr.write("%r\n" % (e,)) raise def assertFloatTuplesAlmostEqual (self, a, b, places=7, msg=None): self.assertEqual (len(a), len(b)) - for i in xrange (len(a)): + for i in range (len(a)): self.assertAlmostEqual (a[i], b[i], places, msg) def assertFloatTuplesAlmostEqual2 (self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None): self.assertEqual (len(ref), len(x)) - for i in xrange (len(ref)): + for i in range (len(ref)): try: self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) - except self.failureException, e: + except self.failureException as e: #sys.stderr.write("index = %d " % (i,)) - #sys.stderr.write("%s\n" % (e,)) + #sys.stderr.write("%r\n" % (e,)) raise @@ -124,7 +135,7 @@ def run(PUT, filename=None): path = basepath + "/python" if not os.path.exists(basepath): - os.makedirs(basepath, 0750) + os.makedirs(basepath, mode=0o750) xmlrunner = None # only proceed if .unittests is writable @@ -132,13 +143,13 @@ def run(PUT, filename=None): if(st & stat.S_IWUSR > 0): # Test if path exists; if not, build it if not os.path.exists(path): - os.makedirs(path, 0750) + os.makedirs(path, mode=0o750) # Just for safety: make sure we can write here, too st = os.stat(path)[stat.ST_MODE] if(st & stat.S_IWUSR > 0): # Create an XML runner to filename - fout = file(path+"/"+filename, "w") + fout = open(path+"/"+filename, "w") xmlrunner = gr_xmlrunner.XMLTestRunner(fout) txtrunner = TextTestRunner(verbosity=1) @@ -148,7 +159,7 @@ def run(PUT, filename=None): suite = TestLoader().loadTestsFromTestCase(PUT) # use the xmlrunner if we can write the the directory - if(xmlrunner is not None): + if xmlrunner is not None: xmlrunner.run(suite) main() diff --git a/gnuradio-runtime/python/gnuradio/gr_xmlrunner.py b/gnuradio-runtime/python/gnuradio/gr_xmlrunner.py index 31298197ff..fccb1b76f0 100644 --- a/gnuradio-runtime/python/gnuradio/gr_xmlrunner.py +++ b/gnuradio-runtime/python/gnuradio/gr_xmlrunner.py @@ -1,25 +1,56 @@ """ XML Test Runner for PyUnit """ - # Written by Sebastian Rittau <srittau@jroger.in-berlin.de> and placed in # the Public Domain. With contributions by Paolo Borelli and others. # Added to GNU Radio Oct. 3, 2010 -__version__ = "0.1" +from __future__ import unicode_literals import os.path import re import sys import time -import traceback import unittest +import linecache from xml.sax.saxutils import escape +from io import StringIO + + +__version__ = "0.1" -try: - from StringIO import StringIO -except ImportError: - from io import StringIO + +# inline trackeback.print_tb so that py2 uses unicode literals (py2/3 compat) +def print_tb(tb, limit=None, out=None): + """Print up to 'limit' stack trace entries from the traceback 'tb'. + + If 'limit' is omitted or None, all entries are printed. If 'file' + is omitted or None, the output goes to sys.stderr; otherwise + 'file' should be an open file or file-like object with a write() + method. + """ + def _print(out, s='', terminator='\n'): + out.write(s+terminator) + + if out is None: + out = sys.stderr + if limit is None: + if hasattr(sys, 'tracebacklimit'): + limit = sys.tracebacklimit + n = 0 + while tb is not None and (limit is None or n < limit): + f = tb.tb_frame + lineno = tb.tb_lineno + co = f.f_code + filename = co.co_filename + name = co.co_name + _print(out, ' Out "%s", line %d, in %s' % (filename, lineno, name)) + linecache.checkcache(filename) + line = linecache.getline(filename, lineno, f.f_globals) + if line: + _print(out, ' ' + line.strip()) + tb = tb.tb_next + n = n+1 class _TestInfo(object): @@ -60,12 +91,12 @@ class _TestInfo(object): supplied stream. """ - stream.write(' <testcase classname="%(class)s" name="%(method)s" time="%(time).4f">' % \ - { - "class": self._class, - "method": self._method, - "time": self._time, - }) + stream.write(' <testcase classname="%(class)s" name="%(method)s" time="%(time).4f">' % + { + 'class': self._class, + 'method': self._method, + 'time': self._time, + }) if self._failure is not None: self._print_error(stream, 'failure', self._failure) if self._error is not None: @@ -76,10 +107,10 @@ class _TestInfo(object): """Print information from a failure or error to the supplied stream.""" text = escape(str(error[1])) stream.write('\n') - stream.write(' <%s type="%s">%s\n' \ - % (tagname, _clsname(error[0]), text)) + stream.write(' <%s type="%s">%s\n' + % (tagname, _clsname(error[0]), text)) tb_stream = StringIO() - traceback.print_tb(error[2], None, tb_stream) + print_tb(error[2], None, tb_stream) stream.write(escape(tb_stream.getvalue())) stream.write(' </%s>\n' % tagname) stream.write(' ') @@ -137,14 +168,17 @@ class _XMLTestResult(unittest.TestResult): output and standard error streams must be passed in.a """ - stream.write('<testsuite errors="%(e)d" failures="%(f)d" ' % \ - { "e": len(self.errors), "f": len(self.failures) }) - stream.write('name="%(n)s" tests="%(t)d" time="%(time).3f">\n' % \ - { - "n": self._test_name, - "t": self.testsRun, - "time": time_taken, - }) + stream.write('<testsuite errors="%(e)d" failures="%(f)d" ' % + { + "e": len(self.errors), + "f": len(self.failures) + }) + stream.write('name="%(n)s" tests="%(t)d" time="%(time).3f">\n' % + { + "n": self._test_name, + "t": self.testsRun, + "time": time_taken + }) for info in self._tests: info.print_report(stream) stream.write(' <system-out><![CDATA[%s]]></system-out>\n' % out) @@ -173,9 +207,9 @@ class XMLTestRunner(object): """Run the given test case or test suite.""" class_ = test.__class__ classname = class_.__module__ + "." + class_.__name__ - if self._stream == None: + if self._stream is None: filename = "TEST-%s.xml" % classname - stream = file(os.path.join(self._path, filename), "w") + stream = open(os.path.join(self._path, filename), "w") stream.write('<?xml version="1.0" encoding="utf-8"?>\n') else: stream = self._stream diff --git a/gnuradio-runtime/python/gnuradio/gru/__init__.py b/gnuradio-runtime/python/gnuradio/gru/__init__.py index 4e41d03a74..0948edb17f 100644 --- a/gnuradio-runtime/python/gnuradio/gru/__init__.py +++ b/gnuradio-runtime/python/gnuradio/gru/__init__.py @@ -1,13 +1,15 @@ +from __future__ import absolute_import +from __future__ import unicode_literals # make this a package # Import gru stuff -from daemon import * -from freqz import * -from gnuplot_freqz import * -from hexint import * -from listmisc import * -from mathmisc import * -from msgq_runner import * -from os_read_exactly import * -from seq_with_cursor import * -from socket_stuff import * +from .daemon import * +from .freqz import * +from .gnuplot_freqz import * +from .hexint import * +from .listmisc import * +from .mathmisc import * +from .msgq_runner import * +from .os_read_exactly import * +from .seq_with_cursor import * +from .socket_stuff import * diff --git a/gnuradio-runtime/python/gnuradio/gru/daemon.py b/gnuradio-runtime/python/gnuradio/gru/daemon.py index e04702152d..14138f9730 100644 --- a/gnuradio-runtime/python/gnuradio/gru/daemon.py +++ b/gnuradio-runtime/python/gnuradio/gru/daemon.py @@ -18,6 +18,10 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. # + +from __future__ import print_function +from __future__ import unicode_literals + import os, sys, signal # Turn application into a background daemon process. @@ -55,38 +59,38 @@ import os, sys, signal def daemonize(pidfile=None, logfile=None): # fork() into background try: - pid = os.fork() - except OSError, e: - raise Exception, "%s [%d]" % (e.strerror, e.errno) + pid = os.fork() + except OSError as e: + raise Exception("%s [%d]" % (e.strerror, e.errno)) if pid == 0: # First child of first fork() - # Become session leader of new session - os.setsid() + # Become session leader of new session + os.setsid() - # fork() into background again - try: - pid = os.fork() - except OSError, e: - raise Exception, "%s [%d]" % (e.strerror, e.errno) + # fork() into background again + try: + pid = os.fork() + except OSError as e: + raise Exception("%s [%d]" % (e.strerror, e.errno)) - if pid != 0: - os._exit(0) # Second child of second fork() + if pid != 0: + os._exit(0) # Second child of second fork() - else: # Second child of first fork() - os._exit(0) + else: # Second child of first fork() + os._exit(0) - os.umask(0111) + os.umask(0o111) # Write pid pid = os.getpid() if pidfile is not None: - open(pidfile, 'w').write('%d\n'%pid) + open(pidfile, 'w').write('%d\n'%pid) # Redirect streams if logfile is not None: - lf = open(logfile, 'a+') - sys.stdout = lf - sys.stderr = lf + lf = open(logfile, 'a+') + sys.stdout = lf + sys.stderr = lf # Prevent pinning any filesystem mounts os.chdir('/') @@ -97,6 +101,6 @@ def daemonize(pidfile=None, logfile=None): if __name__ == "__main__": import time daemonize() - print "Hello, world, from daemon process." + print("Hello, world, from daemon process.") time.sleep(20) - print "Goodbye, world, from daemon process." + print("Goodbye, world, from daemon process.") diff --git a/gnuradio-runtime/python/gnuradio/gru/freqz.py b/gnuradio-runtime/python/gnuradio/gru/freqz.py index 6d8b94db8b..7ce25e2de1 100644 --- a/gnuradio-runtime/python/gnuradio/gru/freqz.py +++ b/gnuradio-runtime/python/gnuradio/gru/freqz.py @@ -52,6 +52,8 @@ # DAMAGE. # +from __future__ import division +from __future__ import unicode_literals __all__ = ['freqz'] import numpy @@ -106,7 +108,7 @@ def polyval(p,x): y = x * y + p[i] return y -class poly1d: +class poly1d(object): """A one-dimensional polynomial class. p = poly1d([1,2,3]) constructs the polynomial x**2 + 2 x + 3 @@ -125,14 +127,14 @@ class poly1d: """ def __init__(self, c_or_r, r=0): if isinstance(c_or_r,poly1d): - for key in c_or_r.__dict__.keys(): + for key in list(c_or_r.__dict__.keys()): self.__dict__[key] = c_or_r.__dict__[key] return if r: c_or_r = poly(c_or_r) c_or_r = atleast_1d(c_or_r) if len(c_or_r.shape) > 1: - raise ValueError, "Polynomial must be 1d only." + raise ValueError("Polynomial must be 1d only.") c_or_r = trim_zeros(c_or_r, trim='f') if len(c_or_r) == 0: c_or_r = numpy.array([0]) @@ -227,7 +229,7 @@ class poly1d: def __pow__(self, val): if not isscalar(val) or int(val) != val or val < 0: - raise ValueError, "Power to non-negative integers only." + raise ValueError("Power to non-negative integers only.") res = [1] for k in range(val): res = polymul(self.coeffs, res) @@ -243,20 +245,20 @@ class poly1d: def __div__(self, other): if isscalar(other): - return poly1d(self.coeffs/other) + return poly1d(self.coeffs / other) else: other = poly1d(other) - return map(poly1d,polydiv(self.coeffs, other.coeffs)) + return list(map(poly1d,polydiv(self.coeffs, other.coeffs))) def __rdiv__(self, other): if isscalar(other): - return poly1d(other/self.coeffs) + return poly1d(other / self.coeffs) else: other = poly1d(other) - return map(poly1d,polydiv(other.coeffs, self.coeffs)) + return list(map(poly1d,polydiv(other.coeffs, self.coeffs))) def __setattr__(self, key, val): - raise ValueError, "Attributes cannot be changed this way." + raise ValueError("Attributes cannot be changed this way.") def __getattr__(self, key): if key in ['r','roots']: @@ -279,7 +281,7 @@ class poly1d: def __setitem__(self, key, val): ind = self.order - key if key < 0: - raise ValueError, "Does not support negative powers." + raise ValueError("Does not support negative powers.") if key > self.order: zr = numpy.zeros(key-self.order,self.coeffs.typecode()) self.__dict__['coeffs'] = numpy.concatenate((zr,self.coeffs)) @@ -323,22 +325,22 @@ def freqz(b, a, worN=None, whole=0, plot=None): h -- The frequency response. w -- The frequencies at which h was computed. """ - b, a = map(atleast_1d, (b,a)) + b, a = list(map(atleast_1d, (b,a))) if whole: lastpoint = 2*pi else: lastpoint = pi if worN is None: N = 512 - w = Num.arange(0,lastpoint,lastpoint/N) - elif isinstance(worN, types.IntType): + w = Num.arange(0,lastpoint,lastpoint / N) + elif isinstance(worN, int): N = worN - w = Num.arange(0,lastpoint,lastpoint/N) + w = Num.arange(0,lastpoint,lastpoint / N) else: w = worN w = atleast_1d(w) zm1 = exp(-1j*w) - h = polyval(b[::-1], zm1) / polyval(a[::-1], zm1) + h = polyval(b[::-1] / zm1, polyval(a[::-1], zm1)) # if not plot is None: # plot(w, h) return h, w diff --git a/gnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py b/gnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py index dd483e4277..5a1ea91cad 100755..100644 --- a/gnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py +++ b/gnuradio-runtime/python/gnuradio/gru/gnuplot_freqz.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals __all__ = ['gnuplot_freqz'] import tempfile @@ -46,10 +48,10 @@ def gnuplot_freqz (hw, Fs=None, logfreq=False): h, w = hw ampl = 20 * numpy.log10 (numpy.absolute (h) + 1e-9) - phase = map (lambda x: math.atan2 (x.imag, x.real), h) + phase = [math.atan2 (x.imag, x.real) for x in h] if Fs: - w *= (Fs/(2*math.pi)) + w *= (Fs / (2*math.pi)) for freq, a, ph in zip (w, ampl, phase): data_file.write ("%g\t%g\t%g\n" % (freq, a, ph)) @@ -99,4 +101,4 @@ def test_plot (): if __name__ == '__main__': handle = test_plot () - raw_input ('Press Enter to continue: ') + eval(input ('Press Enter to continue: ')) diff --git a/gnuradio-runtime/python/gnuradio/gru/hexint.py b/gnuradio-runtime/python/gnuradio/gru/hexint.py index 0fb5ecde04..096b876701 100644 --- a/gnuradio-runtime/python/gnuradio/gru/hexint.py +++ b/gnuradio-runtime/python/gnuradio/gru/hexint.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2005 Free Software Foundation, Inc. # diff --git a/gnuradio-runtime/python/gnuradio/gru/listmisc.py b/gnuradio-runtime/python/gnuradio/gru/listmisc.py index 9e70eb863c..a981147337 100644 --- a/gnuradio-runtime/python/gnuradio/gru/listmisc.py +++ b/gnuradio-runtime/python/gnuradio/gru/listmisc.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2005 Free Software Foundation, Inc. # diff --git a/gnuradio-runtime/python/gnuradio/gru/mathmisc.py b/gnuradio-runtime/python/gnuradio/gru/mathmisc.py index 7e6f23a346..790d7c993c 100644 --- a/gnuradio-runtime/python/gnuradio/gru/mathmisc.py +++ b/gnuradio-runtime/python/gnuradio/gru/mathmisc.py @@ -1,3 +1,5 @@ +from __future__ import division +from __future__ import unicode_literals # # Copyright 2005 Free Software Foundation, Inc. # @@ -30,4 +32,4 @@ def lcm(a,b): return a * b / gcd(a, b) def log2(x): - return math.log(x)/math.log(2) + return math.log(x) / math.log(2) diff --git a/gnuradio-runtime/python/gnuradio/gru/msgq_runner.py b/gnuradio-runtime/python/gnuradio/gru/msgq_runner.py index 767a74a717..2d58480f5f 100644 --- a/gnuradio-runtime/python/gnuradio/gru/msgq_runner.py +++ b/gnuradio-runtime/python/gnuradio/gru/msgq_runner.py @@ -40,6 +40,7 @@ To manually stop the runner, call stop() on the object. To determine if the runner has exited, call exited() on the object. """ +from __future__ import unicode_literals from gnuradio import gr import gnuradio.gr.gr_threading as _threading @@ -66,7 +67,7 @@ class msgq_runner(_threading.Thread): else: try: self._callback(msg) - except Exception, e: + except Exception as e: if self._exit_on_error: self._exit_error = e self.stop() diff --git a/gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py b/gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py index 40b053770e..c079fc4e11 100644 --- a/gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py +++ b/gnuradio-runtime/python/gnuradio/gru/os_read_exactly.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2005 Free Software Foundation, Inc. # diff --git a/gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py b/gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py index def3299b69..0aefbf83bb 100644 --- a/gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py +++ b/gnuradio-runtime/python/gnuradio/gru/seq_with_cursor.py @@ -21,8 +21,12 @@ # misc utilities +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + import types -import exceptions + class seq_with_cursor (object): __slots__ = [ 'items', 'index' ] @@ -40,7 +44,7 @@ class seq_with_cursor (object): elif initial_index >= 0 and initial_index < len (self.items): self.index = initial_index else: - raise exceptions.ValueError + raise ValueError def set_index_by_value(self, v): """ @@ -51,9 +55,9 @@ class seq_with_cursor (object): cv = self.current() more = True while cv < v and more: - cv, more = self.next() # side effect! + cv, more = next(self) # side effect! - def next (self): + def __next__ (self): new_index = self.index + 1 if new_index < len (self.items): self.index = new_index @@ -74,4 +78,3 @@ class seq_with_cursor (object): def get_seq (self): return self.items[:] # copy of items - diff --git a/gnuradio-runtime/python/gnuradio/gru/socket_stuff.py b/gnuradio-runtime/python/gnuradio/gru/socket_stuff.py index b7c5ac2fe1..ce08ce1e10 100644 --- a/gnuradio-runtime/python/gnuradio/gru/socket_stuff.py +++ b/gnuradio-runtime/python/gnuradio/gru/socket_stuff.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2005 Free Software Foundation, Inc. # @@ -37,7 +38,7 @@ def tcp_connect_or_die(sock_addr): s = socket.socket (socket.AF_INET, socket.SOCK_STREAM) try: s.connect(sock_addr) - except socket.error, err: + except socket.error as err: sys.stderr.write('Failed to connect to %s: %s\n' % (sock_addr, os.strerror (err.args[0]),)) sys.exit(1) @@ -55,7 +56,7 @@ def udp_connect_or_die(sock_addr): s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(sock_addr) - except socket.error, err: + except socket.error as err: sys.stderr.write('Failed to connect to %s: %s\n' % (sock_addr, os.strerror (err.args[0]),)) sys.exit(1) diff --git a/gnuradio-runtime/python/pmt/CMakeLists.txt b/gnuradio-runtime/python/pmt/CMakeLists.txt index 1ddfc2a46f..7afac956cb 100644 --- a/gnuradio-runtime/python/pmt/CMakeLists.txt +++ b/gnuradio-runtime/python/pmt/CMakeLists.txt @@ -41,6 +41,6 @@ foreach(py_qa_test_file ${py_qa_test_files}) ${CMAKE_BINARY_DIR}/gnuradio-runtime/swig ) set(GR_TEST_TARGET_DEPS gnuradio-runtime) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gnuradio-runtime/python/pmt/__init__.py b/gnuradio-runtime/python/pmt/__init__.py index 399fae8701..89eb555823 100644 --- a/gnuradio-runtime/python/pmt/__init__.py +++ b/gnuradio-runtime/python/pmt/__init__.py @@ -39,14 +39,17 @@ bool, symbol (string), integer, real, complex, null, pair, list, vector, dict, uniform_vector, any (boost::any cast) ''' +from __future__ import absolute_import +from __future__ import unicode_literals + import os try: - from pmt_swig import * + from .pmt_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from pmt_swig import * + from .pmt_swig import * # due to changes in the PMT_NIL singleton for static builds, we force # this into Python here. @@ -55,5 +58,5 @@ PMT_T = get_PMT_T() PMT_F = get_PMT_F() PMT_EOF = get_PMT_EOF() -from pmt_to_python import pmt_to_python as to_python -from pmt_to_python import python_to_pmt as to_pmt +from .pmt_to_python import pmt_to_python as to_python +from .pmt_to_python import python_to_pmt as to_pmt diff --git a/gnuradio-runtime/python/pmt/pmt_to_python.py b/gnuradio-runtime/python/pmt/pmt_to_python.py index f9000ec279..918e2f9872 100644 --- a/gnuradio-runtime/python/pmt/pmt_to_python.py +++ b/gnuradio-runtime/python/pmt/pmt_to_python.py @@ -17,8 +17,9 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. -try: import pmt_swig as pmt -except: import pmt +from __future__ import unicode_literals + +from . import pmt_swig as pmt import numpy # SWIG isn't taking in the #define PMT_NIL; @@ -34,7 +35,7 @@ def pmt_to_tuple(p): return tuple(elems) def pmt_from_tuple(p): - args = map(python_to_pmt, p) + args = list(map(python_to_pmt, p)) return pmt.make_tuple(*args) def pmt_to_vector(p): @@ -62,7 +63,7 @@ def pmt_to_dict(p): def pmt_from_dict(p): d = pmt.make_dict() - for k, v in p.iteritems(): + for k, v in list(p.items()): #dict is immutable -> therefore pmt_dict_add returns the new dict d = pmt.dict_add(d, python_to_pmt(k), python_to_pmt(v)) return d @@ -88,27 +89,27 @@ uvector_mappings = dict([ (numpy_mappings[key][3], (numpy_mappings[key][2], key) def numpy_to_uvector(numpy_array): try: mapping = numpy_mappings[numpy_array.dtype] - pc = map(mapping[1], numpy.ravel(numpy_array)) + pc = list(map(mapping[1], numpy.ravel(numpy_array))) return mapping[0](numpy_array.size, pc) except KeyError: raise ValueError("unsupported numpy array dtype for converstion to pmt %s"%(numpy_array.dtype)) def uvector_to_numpy(uvector): - match = None - for test_func in uvector_mappings.keys(): - if test_func(uvector): - match = uvector_mappings[test_func] - return numpy.array(match[0](uvector), dtype = match[1]) - else: - raise ValueError("unsupported uvector data type for conversion to numpy array %s"%(uvector)) + match = None + for test_func in list(uvector_mappings.keys()): + if test_func(uvector): + match = uvector_mappings[test_func] + return numpy.array(match[0](uvector), dtype = match[1]) + else: + raise ValueError("unsupported uvector data type for conversion to numpy array %s"%(uvector)) type_mappings = ( #python type, check pmt type, to python, from python (None, pmt.is_null, lambda x: None, lambda x: PMT_NIL), (bool, pmt.is_bool, pmt.to_bool, pmt.from_bool), (str, pmt.is_symbol, pmt.symbol_to_string, pmt.string_to_symbol), - (unicode, lambda x: False, None, lambda x: pmt.string_to_symbol(x.encode('utf-8'))), + (str, lambda x: False, None, lambda x: pmt.string_to_symbol(x.encode('utf-8'))), (int, pmt.is_integer, pmt.to_long, pmt.from_long), - (long, pmt.is_uint64, lambda x: long(pmt.to_uint64(x)), pmt.from_uint64), + (int, pmt.is_uint64, lambda x: int(pmt.to_uint64(x)), pmt.from_uint64), (float, pmt.is_real, pmt.to_double, pmt.from_double), (complex, pmt.is_complex, pmt.to_complex, pmt.from_complex), (tuple, pmt.is_tuple, pmt_to_tuple, pmt_from_tuple), diff --git a/gnuradio-runtime/python/pmt/qa_pmt.py b/gnuradio-runtime/python/pmt/qa_pmt.py index 32cff62f44..0d87676a30 100755..100644 --- a/gnuradio-runtime/python/pmt/qa_pmt.py +++ b/gnuradio-runtime/python/pmt/qa_pmt.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + import unittest import pmt @@ -30,7 +32,7 @@ class test_pmt(unittest.TestCase): b = pmt.from_double(123765) d1 = pmt.make_dict() d2 = pmt.dict_add(d1, a, b) - print d2 + print(d2) def test02(self): const = 123765 diff --git a/gnuradio-runtime/python/pmt/qa_pmt_to_python.py b/gnuradio-runtime/python/pmt/qa_pmt_to_python.py index e63ade1843..18a8e2bcf5 100755..100644 --- a/gnuradio-runtime/python/pmt/qa_pmt_to_python.py +++ b/gnuradio-runtime/python/pmt/qa_pmt_to_python.py @@ -20,16 +20,19 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import + + import unittest import pmt -import pmt_to_python as pmt2py +from pmt import pmt_to_python as pmt2py class test_pmt_to_python(unittest.TestCase): def test_pmt_from_double(self): b = pmt.from_double(123765) self.assertEqual(pmt.to_python(b), 123765) - t = pmt.to_pmt(range(5)) + t = pmt.to_pmt(list(range(5))) def test_numpy_to_uvector_and_reverse(self): import numpy as np diff --git a/gnuradio-runtime/swig/basic_block.i b/gnuradio-runtime/swig/basic_block.i index cf75479bb8..363e121bc6 100644 --- a/gnuradio-runtime/swig/basic_block.i +++ b/gnuradio-runtime/swig/basic_block.i @@ -31,6 +31,10 @@ namespace std { %template(x_vector_basic_block_sptr) vector<gr::basic_block_sptr>; }; +%begin %{ +#define SWIG_PYTHON_2_UNICODE +%} + namespace gr { class gr::basic_block @@ -60,6 +64,8 @@ namespace gr { } #ifdef SWIGPYTHON +%import py3compat.i + %pythoncode %{ basic_block_sptr.__repr__ = lambda self: "<basic_block %s (%d)>" % (self.name(), self.unique_id ()) %} diff --git a/gnuradio-runtime/swig/gnuradio.i b/gnuradio-runtime/swig/gnuradio.i index 7056d28ff5..6e8a3093f2 100644 --- a/gnuradio-runtime/swig/gnuradio.i +++ b/gnuradio-runtime/swig/gnuradio.i @@ -77,3 +77,14 @@ %} %include <gnuradio/high_res_timer.h> + +//////////////////////////////////////////////////////////////////////// +// Python 2/3 compatibilty + +%begin %{ +#define SWIG_PYTHON_2_UNICODE +%} + +#ifdef SWIGPYTHON +%import py3compat.i +#endif diff --git a/gnuradio-runtime/swig/pmt_swig.i b/gnuradio-runtime/swig/pmt_swig.i index 2063a5c972..c627b7d3e6 100644 --- a/gnuradio-runtime/swig/pmt_swig.i +++ b/gnuradio-runtime/swig/pmt_swig.i @@ -25,6 +25,10 @@ %include "std_string.i" %include "stdint.i" +%begin %{ +#define SWIG_PYTHON_2_UNICODE +%} + %{ #include <boost/intrusive_ptr.hpp> #include <boost/shared_ptr.hpp> @@ -58,6 +62,8 @@ %template(pmt_vector_cfloat) std::vector< std::complex<float> >; %template(pmt_vector_cdouble) std::vector< std::complex<double> >; +%import py3compat.i + //////////////////////////////////////////////////////////////////////// // Language independent exception handler //////////////////////////////////////////////////////////////////////// diff --git a/gnuradio-runtime/swig/py3compat.i b/gnuradio-runtime/swig/py3compat.i new file mode 100644 index 0000000000..6e726c294f --- /dev/null +++ b/gnuradio-runtime/swig/py3compat.i @@ -0,0 +1,7 @@ +%begin %{ +#define SWIG_PYTHON_2_UNICODE +%} + +%pythonbegin %{ +from __future__ import absolute_import +%} diff --git a/gr-analog/examples/fmtest.py b/gr-analog/examples/fmtest.py index 7ed08cafbe..04218a4472 100755..100644 --- a/gr-analog/examples/fmtest.py +++ b/gr-analog/examples/fmtest.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from gnuradio import filter @@ -31,13 +34,13 @@ try: import scipy from scipy import fftpack except ImportError: - print "Error: Program requires scipy (see: www.scipy.org)." + print("Error: Program requires scipy (see: www.scipy.org).") sys.exit(1) try: import pylab except ImportError: - print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + print("Error: Program requires matplotlib (see: matplotlib.sourceforge.net).") sys.exit(1) @@ -80,7 +83,7 @@ class fmtest(gr.top_block): # Create a signal source and frequency modulate it self.sum = blocks.add_cc() - for n in xrange(self._N): + for n in range(self._N): sig = analog.sig_source_f(self._audio_rate, analog.GR_SIN_WAVE, freq[n], 0.5) fm = fmtx(f_lo[n], self._audio_rate, self._if_rate) self.connect(sig, fm) @@ -95,17 +98,17 @@ class fmtest(gr.top_block): # Design the channlizer self._M = 10 - bw = chspacing/2.0 - t_bw = chspacing/10.0 + bw = chspacing / 2.0 + t_bw = chspacing / 10.0 self._chan_rate = self._if_rate / self._M self._taps = filter.firdes.low_pass_2(1, self._if_rate, bw, t_bw, attenuation_dB=100, window=filter.firdes.WIN_BLACKMAN_hARRIS) - tpc = math.ceil(float(len(self._taps)) / float(self._M)) + tpc = math.ceil(float(len(self._taps)) / float(self._M)) - print "Number of taps: ", len(self._taps) - print "Number of channels: ", self._M - print "Taps per channel: ", tpc + print("Number of taps: ", len(self._taps)) + print("Number of channels: ", self._M) + print("Taps per channel: ", tpc) self.pfb = filter.pfb.channelizer_ccf(self._M, self._taps) @@ -115,7 +118,7 @@ class fmtest(gr.top_block): self.fmdet = list() self.squelch = list() self.snks = list() - for i in xrange(self._M): + for i in range(self._M): self.fmdet.append(analog.nbfm_rx(self._audio_rate, self._chan_rate)) self.squelch.append(analog.standard_squelch(self._audio_rate*10)) self.snks.append(blocks.vector_sink_f()) @@ -152,11 +155,11 @@ def main(): d = fm.snk_tx.data()[Ns:Ns+Ne] sp1_f = fig1.add_subplot(2, 1, 1) - X,freq = sp1_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + X,freq = sp1_f.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs, window = lambda d: d*winfunc(fftlen), visible=False) X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) - f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + f_in = scipy.arange(-fs / 2.0, fs / 2.0, fs / float(X_in.size)) p1_f = sp1_f.plot(f_in, X_in, "b") sp1_f.set_xlim([min(f_in), max(f_in)+1]) sp1_f.set_ylim([-120.0, 20.0]) @@ -165,7 +168,7 @@ def main(): sp1_f.set_xlabel("Frequency (Hz)") sp1_f.set_ylabel("Power (dBW)") - Ts = 1.0/fs + Ts = 1.0 / fs Tmax = len(d)*Ts t_in = scipy.arange(0, Tmax, Ts) @@ -184,20 +187,20 @@ def main(): # Plot each of the channels outputs. Frequencies on Figure 2 and # time signals on Figure 3 fs_o = fm._audio_rate - for i in xrange(len(fm.snks)): + for i in range(len(fm.snks)): # remove issues with the transients at the beginning # also remove some corruption at the end of the stream # this is a bug, probably due to the corner cases d = fm.snks[i].data()[Ns:Ne] sp2_f = fig2.add_subplot(Nrows, Ncols, 1+i) - X,freq = sp2_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + X,freq = sp2_f.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs_o, window = lambda d: d*winfunc(fftlen), visible=False) #X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) X_o = 10.0*scipy.log10(abs(X)) #f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size)) - f_o = scipy.arange(0, fs_o/2.0, fs_o/2.0/float(X_o.size)) + f_o = scipy.arange(0, fs_o / 2.0, fs_o/2.0/float(X_o.size)) p2_f = sp2_f.plot(f_o, X_o, "b") sp2_f.set_xlim([min(f_o), max(f_o)+0.1]) sp2_f.set_ylim([-120.0, 20.0]) @@ -208,7 +211,7 @@ def main(): sp2_f.set_ylabel("Power (dBW)") - Ts = 1.0/fs_o + Ts = 1.0 / fs_o Tmax = len(d)*Ts t_o = scipy.arange(0, Tmax, Ts) diff --git a/gr-analog/examples/tags/uhd_burst_detector.py b/gr-analog/examples/tags/uhd_burst_detector.py index 5aa80b2549..d3d221a45c 100755..100644 --- a/gr-analog/examples/tags/uhd_burst_detector.py +++ b/gr-analog/examples/tags/uhd_burst_detector.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import eng_notation from gnuradio import gr from gnuradio import filter, analog, blocks diff --git a/gr-analog/python/analog/CMakeLists.txt b/gr-analog/python/analog/CMakeLists.txt index 1fed9d1890..ba3dfb5fc3 100644 --- a/gr-analog/python/analog/CMakeLists.txt +++ b/gr-analog/python/analog/CMakeLists.txt @@ -53,7 +53,7 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-analog/python/analog/__init__.py b/gr-analog/python/analog/__init__.py index 3c4a0ff624..79c19e1e3e 100644 --- a/gr-analog/python/analog/__init__.py +++ b/gr-analog/python/analog/__init__.py @@ -21,24 +21,26 @@ ''' Blocks and utilities for analog modulation and demodulation. ''' +from __future__ import absolute_import +from __future__ import unicode_literals # The presence of this file turns this directory into a Python package import os try: - from analog_swig import * + from .analog_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from analog_swig import * + from .analog_swig import * -from am_demod import * -from fm_demod import * -from fm_emph import * -from nbfm_rx import * -from nbfm_tx import * -from standard_squelch import * -from wfm_rcv import * -from wfm_rcv_fmdet import * -from wfm_rcv_pll import * -from wfm_tx import * +from .am_demod import * +from .fm_demod import * +from .fm_emph import * +from .nbfm_rx import * +from .nbfm_tx import * +from .standard_squelch import * +from .wfm_rcv import * +from .wfm_rcv_fmdet import * +from .wfm_rcv_pll import * +from .wfm_tx import * diff --git a/gr-analog/python/analog/am_demod.py b/gr-analog/python/analog/am_demod.py index 3459e825f4..eeb8964f34 100644 --- a/gr-analog/python/analog/am_demod.py +++ b/gr-analog/python/analog/am_demod.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2006,2007,2012 Free Software Foundation, Inc. # @@ -39,22 +40,22 @@ class am_demod_cf(gr.hier_block2): audio_stop: audio low pass filter stop frequency (float) """ def __init__(self, channel_rate, audio_decim, audio_pass, audio_stop): - gr.hier_block2.__init__(self, "am_demod_cf", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_float)) # Input signature + gr.hier_block2.__init__(self, "am_demod_cf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Input signature - MAG = blocks.complex_to_mag() - DCR = blocks.add_const_ff(-1.0) + MAG = blocks.complex_to_mag() + DCR = blocks.add_const_ff(-1.0) - audio_taps = filter.optfir.low_pass(0.5, # Filter gain + audio_taps = filter.optfir.low_pass(0.5, # Filter gain channel_rate, # Sample rate audio_pass, # Audio passband audio_stop, # Audio stopband - 0.1, # Passband ripple - 60) # Stopband attenuation - LPF = filter.fir_filter_fff(audio_decim, audio_taps) + 0.1, # Passband ripple + 60) # Stopband attenuation + LPF = filter.fir_filter_fff(audio_decim, audio_taps) - self.connect(self, MAG, DCR, LPF, self) + self.connect(self, MAG, DCR, LPF, self) class demod_10k0a3e_cf(am_demod_cf): """ @@ -68,6 +69,6 @@ class demod_10k0a3e_cf(am_demod_cf): audio_decim: input to output decimation rate (integer) """ def __init__(self, channel_rate, audio_decim): - am_demod_cf.__init__(self, channel_rate, audio_decim, - 5000, # Audio passband - 5500) # Audio stopband + am_demod_cf.__init__(self, channel_rate, audio_decim, + 5000, # Audio passband + 5500) # Audio stopband diff --git a/gr-analog/python/analog/fm_demod.py b/gr-analog/python/analog/fm_demod.py index 4e3c01d194..1344db831c 100644 --- a/gr-analog/python/analog/fm_demod.py +++ b/gr-analog/python/analog/fm_demod.py @@ -19,14 +19,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + from gnuradio import gr, filter -from fm_emph import fm_deemph +from .fm_emph import fm_deemph from math import pi -try: - from gnuradio import analog -except ImportError: - import analog_swig as analog +from . import analog_swig as analog class fm_demod_cf(gr.hier_block2): @@ -54,7 +55,7 @@ class fm_demod_cf(gr.hier_block2): gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(1, 1, gr.sizeof_float)) # Output signature - k = channel_rate/(2*pi*deviation) + k = channel_rate / (2*pi*deviation) QUAD = analog.quadrature_demod_cf(k) audio_taps = filter.optfir.low_pass( diff --git a/gr-analog/python/analog/fm_emph.py b/gr-analog/python/analog/fm_emph.py index bfa4742ace..a4a83bd217 100644 --- a/gr-analog/python/analog/fm_emph.py +++ b/gr-analog/python/analog/fm_emph.py @@ -19,6 +19,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + from gnuradio import gr, filter import math import cmath @@ -132,8 +136,8 @@ class fm_deemph(gr.hier_block2): # Since H(s = 0) = 1.0, then H(z = 1) = 1.0 and has 0 dB gain at DC if 0: - print "btaps =", btaps - print "ataps =", ataps + print("btaps =", btaps) + print("ataps =", ataps) global plot1 plot1 = gru.gnuplot_freqz(gru.freqz(btaps, ataps), fs, True) @@ -149,11 +153,11 @@ class fm_deemph(gr.hier_block2): # o------+ +-----+--------o # | R1 | | # +----/\/\/\/--+ \ -# / + # / # \ R2 # / # \ -# | + # | # o--------------------------+--------o # # (This fine ASCII rendition is based on Figure 5-15 @@ -263,44 +267,43 @@ class fm_preemph(gr.hier_block2): gr.io_signature(1, 1, gr.sizeof_float), # Input signature gr.io_signature(1, 1, gr.sizeof_float)) # Output signature - # Set fh to something sensible, if needed. - # N.B. fh == fs/2.0 or fh == 0.0 results in a pole on the unit circle - # at z = -1.0 or z = 1.0 respectively. That makes the filter unstable - # and useless. - if fh <= 0.0 or fh >= fs/2.0: - fh = 0.925 * fs/2.0 + # Set fh to something sensible, if needed. + # N.B. fh == fs/2.0 or fh == 0.0 results in a pole on the unit circle + # at z = -1.0 or z = 1.0 respectively. That makes the filter unstable + # and useless. + if fh <= 0.0 or fh >= fs / 2.0: + fh = 0.925 * fs/2.0 - # Digital corner frequencies - w_cl = 1.0 / tau - w_ch = 2.0 * math.pi * fh + # Digital corner frequencies + w_cl = 1.0 / tau + w_ch = 2.0 * math.pi * fh - # Prewarped analog corner frequencies - w_cla = 2.0 * fs * math.tan(w_cl / (2.0 * fs)) - w_cha = 2.0 * fs * math.tan(w_ch / (2.0 * fs)) + # Prewarped analog corner frequencies + w_cla = 2.0 * fs * math.tan(w_cl / (2.0 * fs)) + w_cha = 2.0 * fs * math.tan(w_ch / (2.0 * fs)) - # Resulting digital pole, zero, and gain term from the bilinear - # transformation of H(s) = (s + w_cla) / (s + w_cha) to - # H(z) = b0 (1 - z1 z^-1)/(1 - p1 z^-1) - kl = -w_cla / (2.0 * fs) - kh = -w_cha / (2.0 * fs) - z1 = (1.0 + kl) / (1.0 - kl) - p1 = (1.0 + kh) / (1.0 - kh) - b0 = (1.0 - kl) / (1.0 - kh) + # Resulting digital pole, zero, and gain term from the bilinear + # transformation of H(s) = (s + w_cla) / (s + w_cha) to + # H(z) = b0 (1 - z1 z^-1)/(1 - p1 z^-1) + kl = -w_cla / (2.0 * fs) + kh = -w_cha / (2.0 * fs) + z1 = (1.0 + kl) / (1.0 - kl) + p1 = (1.0 + kh) / (1.0 - kh) + b0 = (1.0 - kl) / (1.0 - kh) - # Since H(s = infinity) = 1.0, then H(z = -1) = 1.0 and - # this filter has 0 dB gain at fs/2.0. - # That isn't what users are going to expect, so adjust with a - # gain, g, so that H(z = 1) = 1.0 for 0 dB gain at DC. - w_0dB = 2.0 * math.pi * 0.0 - g = abs(1.0 - p1 * cmath.rect(1.0, -w_0dB)) \ - / (b0 * abs(1.0 - z1 * cmath.rect(1.0, -w_0dB))) + # Since H(s = infinity) = 1.0, then H(z = -1) = 1.0 and + # this filter has 0 dB gain at fs/2.0. + # That isn't what users are going to expect, so adjust with a + # gain, g, so that H(z = 1) = 1.0 for 0 dB gain at DC. + w_0dB = 2.0 * math.pi * 0.0 + g = abs(1.0 - p1 * cmath.rect(1.0 / -w_0dB), (b0 * abs(1.0 - z1 * cmath.rect(1.0, -w_0dB)))) - btaps = [ g * b0 * 1.0, g * b0 * -z1 ] - ataps = [ 1.0, -p1 ] + btaps = [ g * b0 * 1.0, g * b0 * -z1 ] + ataps = [ 1.0, -p1 ] if 0: - print "btaps =", btaps - print "ataps =", ataps + print("btaps =", btaps) + print("ataps =", ataps) global plot2 plot2 = gru.gnuplot_freqz(gru.freqz(btaps, ataps), fs, True) diff --git a/gr-analog/python/analog/nbfm_rx.py b/gr-analog/python/analog/nbfm_rx.py index 38fbf803c8..3e8dcd5287 100644 --- a/gr-analog/python/analog/nbfm_rx.py +++ b/gr-analog/python/analog/nbfm_rx.py @@ -19,15 +19,19 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + import math + from gnuradio import gr from gnuradio import filter -from fm_emph import fm_deemph -try: - from gnuradio import analog -except ImportError: - import analog_swig as analog +from . import analog_swig as analog +from .fm_emph import fm_deemph + class nbfm_rx(gr.hier_block2): def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3): @@ -52,22 +56,22 @@ class nbfm_rx(gr.hier_block2): audio_filter """ - gr.hier_block2.__init__(self, "nbfm_rx", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + gr.hier_block2.__init__(self, "nbfm_rx", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature # FIXME audio_rate and quad_rate ought to be exact rationals self._audio_rate = audio_rate = int(audio_rate) self._quad_rate = quad_rate = int(quad_rate) if quad_rate % audio_rate != 0: - raise ValueError, "quad_rate is not an integer multiple of audio_rate" + raise ValueError("quad_rate is not an integer multiple of audio_rate") - squelch_threshold = 20 # dB + squelch_threshold = 20 # dB #self.squelch = analog.simple_squelch_cc(squelch_threshold, 0.001) # FM Demodulator input: complex; output: float - k = quad_rate/(2*math.pi*max_dev) + k = quad_rate / (2*math.pi*max_dev) self.quad_demod = analog.quadrature_demod_cf(k) # FM Deemphasis IIR filter @@ -81,7 +85,7 @@ class nbfm_rx(gr.hier_block2): 0.5e3, # Transition band filter.firdes.WIN_HAMMING) # filter type - print "len(audio_taps) =", len(audio_taps) + print("len(audio_taps) =", len(audio_taps)) # Decimating audio filter # input: float; output: float; taps: float @@ -90,5 +94,5 @@ class nbfm_rx(gr.hier_block2): self.connect(self, self.quad_demod, self.deemph, self.audio_filter, self) def set_max_deviation(self, max_dev): - k = self._quad_rate/(2*math.pi*max_dev) + k = self._quad_rate / (2*math.pi*max_dev) self.quad_demod.set_gain(k) diff --git a/gr-analog/python/analog/nbfm_tx.py b/gr-analog/python/analog/nbfm_tx.py index aa6c1eccc7..a7620451eb 100644 --- a/gr-analog/python/analog/nbfm_tx.py +++ b/gr-analog/python/analog/nbfm_tx.py @@ -19,14 +19,18 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + import math + from gnuradio import gr, filter -from fm_emph import fm_preemph +from .fm_emph import fm_preemph + +from . import analog_swig as analog -try: - from gnuradio import analog -except ImportError: - import analog_swig as analog class nbfm_tx(gr.hier_block2): def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3, fh=-1.0): @@ -46,16 +50,16 @@ class nbfm_tx(gr.hier_block2): quad_rate must be an integer multiple of audio_rate. """ - gr.hier_block2.__init__(self, "nbfm_tx", - gr.io_signature(1, 1, gr.sizeof_float), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + gr.hier_block2.__init__(self, "nbfm_tx", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature # FIXME audio_rate and quad_rate ought to be exact rationals self._audio_rate = audio_rate = int(audio_rate) self._quad_rate = quad_rate = int(quad_rate) if quad_rate % audio_rate != 0: - raise ValueError, "quad_rate is not an integer multiple of audio_rate" + raise ValueError("quad_rate is not an integer multiple of audio_rate") do_interp = audio_rate != quad_rate @@ -66,10 +70,10 @@ class nbfm_tx(gr.hier_block2): quad_rate, # Fs 4500, # passband cutoff 7000, # stopband cutoff - 0.1, # passband ripple dB + 0.1, # passband ripple dB 40) # stopband atten dB - #print "len(interp_taps) =", len(interp_taps) + #print("len(interp_taps) =", len(interp_taps)) self.interpolator = filter.interp_fir_filter_fff (interp_factor, interp_taps) self.preemph = fm_preemph(quad_rate, tau=tau, fh=fh) @@ -90,10 +94,10 @@ class nbfm_tx(gr.hier_block2): class ctcss_gen_f(gr.hier_block2): def __init__(self, sample_rate, tone_freq): - gr.hier_block2.__init__(self, "ctcss_gen_f", - gr.io_signature(0, 0, 0), # Input signature - gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + gr.hier_block2.__init__(self, "ctcss_gen_f", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature self.plgen = analog.sig_source_f(sample_rate, analog.GR_SIN_WAVE, tone_freq, 0.1, 0.0) - self.connect(self.plgen, self) + self.connect(self.plgen, self) diff --git a/gr-analog/python/analog/qa_agc.py b/gr-analog/python/analog/qa_agc.py index 70c9ba578c..bac661f8b2 100755..100644 --- a/gr-analog/python/analog/qa_agc.py +++ b/gr-analog/python/analog/qa_agc.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, analog, blocks class test_agc(gr_unittest.TestCase): @@ -33,10 +34,10 @@ class test_agc(gr_unittest.TestCase): def test_001_sets(self): agc = analog.agc_cc(1e-3, 1, 1) - agc.set_rate(1) - agc.set_reference(1.1) - agc.set_gain(1.1) - agc.set_max_gain(100) + agc.set_rate(1) + agc.set_reference(1.1) + agc.set_gain(1.1) + agc.set_max_gain(100) self.assertAlmostEqual(agc.rate(), 1) self.assertAlmostEqual(agc.reference(), 1.1) @@ -118,10 +119,10 @@ class test_agc(gr_unittest.TestCase): def test_002_sets(self): agc = analog.agc_ff(1e-3, 1, 1) - agc.set_rate(1) - agc.set_reference(1.1) - agc.set_gain(1.1) - agc.set_max_gain(100) + agc.set_rate(1) + agc.set_reference(1.1) + agc.set_gain(1.1) + agc.set_max_gain(100) self.assertAlmostEqual(agc.rate(), 1) self.assertAlmostEqual(agc.reference(), 1.1) @@ -203,11 +204,11 @@ class test_agc(gr_unittest.TestCase): def test_003_sets(self): agc = analog.agc2_cc(1e-3, 1e-1, 1, 1) - agc.set_attack_rate(1) - agc.set_decay_rate(2) - agc.set_reference(1.1) - agc.set_gain(1.1) - agc.set_max_gain(100) + agc.set_attack_rate(1) + agc.set_decay_rate(2) + agc.set_reference(1.1) + agc.set_gain(1.1) + agc.set_max_gain(100) self.assertAlmostEqual(agc.attack_rate(), 1) self.assertAlmostEqual(agc.decay_rate(), 2) @@ -290,11 +291,11 @@ class test_agc(gr_unittest.TestCase): def test_004_sets(self): agc = analog.agc2_ff(1e-3, 1e-1, 1, 1) - agc.set_attack_rate(1) - agc.set_decay_rate(2) - agc.set_reference(1.1) - agc.set_gain(1.1) - agc.set_max_gain(100) + agc.set_attack_rate(1) + agc.set_decay_rate(2) + agc.set_reference(1.1) + agc.set_gain(1.1) + agc.set_max_gain(100) self.assertAlmostEqual(agc.attack_rate(), 1) self.assertAlmostEqual(agc.decay_rate(), 2) @@ -450,10 +451,10 @@ class test_agc(gr_unittest.TestCase): def test_006_sets(self): agc = analog.agc3_cc(1e-3, 1e-1, 1) - agc.set_attack_rate(1) - agc.set_decay_rate(2) - agc.set_reference(1.1) - agc.set_gain(1.1) + agc.set_attack_rate(1) + agc.set_decay_rate(2) + agc.set_reference(1.1) + agc.set_gain(1.1) self.assertAlmostEqual(agc.attack_rate(), 1) self.assertAlmostEqual(agc.decay_rate(), 2) @@ -481,7 +482,7 @@ class test_agc(gr_unittest.TestCase): tb.run() dst_data = dst1.data() M = 100 - result = map(lambda x: abs(x), dst_data[N-M:]) + result = [abs(x) for x in dst_data[N-M:]] self.assertFloatTuplesAlmostEqual(result, M*[ref,], 4) def test_100(self): diff --git a/gr-analog/python/analog/qa_cpfsk.py b/gr-analog/python/analog/qa_cpfsk.py index be2e0a9b7e..ef8ea0cb3f 100755..100644 --- a/gr-analog/python/analog/qa_cpfsk.py +++ b/gr-analog/python/analog/qa_cpfsk.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import math from gnuradio import gr, gr_unittest, analog, blocks @@ -50,7 +51,7 @@ class test_cpfsk_bc(gr_unittest.TestCase): def test_cpfsk_bc_002(self): src_data = 10*[0, 1] - expected_result = map(lambda x: complex(2*x-1,0), src_data) + expected_result = [complex(2*x-1,0) for x in src_data] src = blocks.vector_source_b(src_data) op = analog.cpfsk_bc(2, 1, 2) diff --git a/gr-analog/python/analog/qa_ctcss_squelch.py b/gr-analog/python/analog/qa_ctcss_squelch.py index 3be1e9de3b..f3db194f5d 100755..100644 --- a/gr-analog/python/analog/qa_ctcss_squelch.py +++ b/gr-analog/python/analog/qa_ctcss_squelch.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, analog, blocks class test_ctcss_squelch(gr_unittest.TestCase): @@ -63,7 +65,7 @@ class test_ctcss_squelch(gr_unittest.TestCase): ramp = 1 gate = True - src_data = map(lambda x: float(x)/10.0, range(1, 40)) + src_data = [float(x) / 10.0 for x in range(1, 40)] expected_result = src_data expected_result[0] = 0 @@ -88,7 +90,7 @@ class test_ctcss_squelch(gr_unittest.TestCase): ramp = 1 gate = False - src_data = map(lambda x: float(x)/10.0, range(1, 40)) + src_data = [float(x) / 10.0 for x in range(1, 40)] src = blocks.vector_source_f(src_data) op = analog.ctcss_squelch_ff(rate, freq, level, length, ramp, gate) diff --git a/gr-analog/python/analog/qa_dpll.py b/gr-analog/python/analog/qa_dpll.py index 3ae8a3684b..2d215e3d9d 100755..100644 --- a/gr-analog/python/analog/qa_dpll.py +++ b/gr-analog/python/analog/qa_dpll.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, analog, blocks class test_dpll_bb(gr_unittest.TestCase): @@ -42,7 +44,7 @@ class test_dpll_bb(gr_unittest.TestCase): self.assertAlmostEqual(g, 0.2) f = op.freq() - self.assertEqual(1/period, f) + self.assertEqual(1 / period, f) d0 = 1.0 - 0.5*f; d1 = op.decision_threshold() diff --git a/gr-analog/python/analog/qa_fastnoise.py b/gr-analog/python/analog/qa_fastnoise.py index 91e1cb87b7..e90fcfd96e 100644 --- a/gr-analog/python/analog/qa_fastnoise.py +++ b/gr-analog/python/analog/qa_fastnoise.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, analog class test_fastnoise_source(gr_unittest.TestCase): diff --git a/gr-analog/python/analog/qa_fmdet.py b/gr-analog/python/analog/qa_fmdet.py index a9c88c3b95..77ad213411 100755..100644 --- a/gr-analog/python/analog/qa_fmdet.py +++ b/gr-analog/python/analog/qa_fmdet.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, analog, blocks class test_fmdet_cf(gr_unittest.TestCase): diff --git a/gr-analog/python/analog/qa_frequency_modulator.py b/gr-analog/python/analog/qa_frequency_modulator.py index 0f5c45b11a..29282b0ea6 100755..100644 --- a/gr-analog/python/analog/qa_frequency_modulator.py +++ b/gr-analog/python/analog/qa_frequency_modulator.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import math from gnuradio import gr, gr_unittest, analog, blocks @@ -38,9 +40,9 @@ class test_frequency_modulator(gr_unittest.TestCase): def test_fm_001(self): pi = math.pi - sensitivity = pi/4 - src_data = (1.0/4, 1.0/2, 1.0/4, -1.0/4, -1.0/2, -1/4.0) - running_sum = (pi/16, 3*pi/16, pi/4, 3*pi/16, pi/16, 0) + sensitivity = pi / 4 + src_data = (1.0 / 4, 1.0 / 2, 1.0 / 4, -1.0 / 4, -1.0 / 2, -1 / 4.0) + running_sum = (pi / 16, 3*pi/16, pi / 4, 3*pi/16, pi / 16, 0) expected_result = tuple([sincos(x) for x in running_sum]) src = blocks.vector_source_f(src_data) op = analog.frequency_modulator_fc(sensitivity) diff --git a/gr-analog/python/analog/qa_noise.py b/gr-analog/python/analog/qa_noise.py index 5576773f23..cf2e9e607f 100755..100644 --- a/gr-analog/python/analog/qa_noise.py +++ b/gr-analog/python/analog/qa_noise.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, analog class test_noise_source(gr_unittest.TestCase): diff --git a/gr-analog/python/analog/qa_phase_modulator.py b/gr-analog/python/analog/qa_phase_modulator.py index c6223e5cd4..7f7d57fa75 100755..100644 --- a/gr-analog/python/analog/qa_phase_modulator.py +++ b/gr-analog/python/analog/qa_phase_modulator.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import math from gnuradio import gr, gr_unittest, analog, blocks @@ -38,8 +40,8 @@ class test_phase_modulator(gr_unittest.TestCase): def test_fm_001(self): pi = math.pi - sensitivity = pi/4 - src_data = (1.0/4, 1.0/2, 1.0/4, -1.0/4, -1.0/2, -1/4.0) + sensitivity = pi / 4 + src_data = (1.0 / 4, 1.0 / 2, 1.0 / 4, -1.0 / 4, -1.0 / 2, -1 / 4.0) expected_result = tuple([sincos(sensitivity*x) for x in src_data]) src = blocks.vector_source_f(src_data) diff --git a/gr-analog/python/analog/qa_pll_carriertracking.py b/gr-analog/python/analog/qa_pll_carriertracking.py index 10ad414644..56bb14d2cb 100755..100644 --- a/gr-analog/python/analog/qa_pll_carriertracking.py +++ b/gr-analog/python/analog/qa_pll_carriertracking.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import math from gnuradio import gr, gr_unittest, analog, blocks @@ -137,7 +139,7 @@ class test_pll_carriertracking(gr_unittest.TestCase): sampling_freq = 10e3 freq = sampling_freq / 100 - loop_bw = math.pi/100.0 + loop_bw = math.pi / 100.0 maxf = 1 minf = -1 diff --git a/gr-analog/python/analog/qa_pll_freqdet.py b/gr-analog/python/analog/qa_pll_freqdet.py index c7a8aa8363..2006dd7360 100755..100644 --- a/gr-analog/python/analog/qa_pll_freqdet.py +++ b/gr-analog/python/analog/qa_pll_freqdet.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import math from gnuradio import gr, gr_unittest, analog, blocks @@ -137,7 +139,7 @@ class test_pll_freqdet(gr_unittest.TestCase): sampling_freq = 10e3 freq = sampling_freq / 100 - loop_bw = math.pi/100.0 + loop_bw = math.pi / 100.0 maxf = 1 minf = -1 @@ -153,7 +155,7 @@ class test_pll_freqdet(gr_unittest.TestCase): dst_data = dst.data() # convert it from normalized frequency to absolute frequency (Hz) - dst_data = [i*(sampling_freq/(2*math.pi)) for i in dst_data] + dst_data = [i*(sampling_freq / (2*math.pi)) for i in dst_data] self.assertFloatTuplesAlmostEqual(expected_result, dst_data, 3) diff --git a/gr-analog/python/analog/qa_pll_refout.py b/gr-analog/python/analog/qa_pll_refout.py index 835b6a4522..ac1139cc03 100755..100644 --- a/gr-analog/python/analog/qa_pll_refout.py +++ b/gr-analog/python/analog/qa_pll_refout.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import math from gnuradio import gr, gr_unittest, analog, blocks @@ -137,7 +139,7 @@ class test_pll_refout(gr_unittest.TestCase): sampling_freq = 10e3 freq = sampling_freq / 100 - loop_bw = math.pi/100.0 + loop_bw = math.pi / 100.0 maxf = 1 minf = -1 diff --git a/gr-analog/python/analog/qa_probe_avg_mag_sqrd.py b/gr-analog/python/analog/qa_probe_avg_mag_sqrd.py index a52c0806e3..68652eb364 100755..100644 --- a/gr-analog/python/analog/qa_probe_avg_mag_sqrd.py +++ b/gr-analog/python/analog/qa_probe_avg_mag_sqrd.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import math from gnuradio import gr, gr_unittest, analog, blocks diff --git a/gr-analog/python/analog/qa_pwr_squelch.py b/gr-analog/python/analog/qa_pwr_squelch.py index 561ca79a7c..9f84a61402 100755..100644 --- a/gr-analog/python/analog/qa_pwr_squelch.py +++ b/gr-analog/python/analog/qa_pwr_squelch.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, analog, blocks class test_pwr_squelch(gr_unittest.TestCase): @@ -61,7 +63,7 @@ class test_pwr_squelch(gr_unittest.TestCase): alpha = 0.0001 thr = -25 - src_data = map(lambda x: float(x)/10.0, range(1, 40)) + src_data = [float(x) / 10.0 for x in range(1, 40)] src = blocks.vector_source_c(src_data) op = analog.pwr_squelch_cc(thr, alpha) dst = blocks.vector_sink_c() @@ -107,7 +109,7 @@ class test_pwr_squelch(gr_unittest.TestCase): alpha = 0.0001 thr = -25 - src_data = map(lambda x: float(x)/10.0, range(1, 40)) + src_data = [float(x) / 10.0 for x in range(1, 40)] src = blocks.vector_source_f(src_data) op = analog.pwr_squelch_ff(thr, alpha) dst = blocks.vector_sink_f() diff --git a/gr-analog/python/analog/qa_quadrature_demod.py b/gr-analog/python/analog/qa_quadrature_demod.py index 08f3f4600e..e3a513b9ab 100755..100644 --- a/gr-analog/python/analog/qa_quadrature_demod.py +++ b/gr-analog/python/analog/qa_quadrature_demod.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import cmath from gnuradio import gr, gr_unittest, analog, blocks @@ -37,13 +39,13 @@ class test_quadrature_demod(gr_unittest.TestCase): fs = 8000.0 src_data = [] - for i in xrange(200): - ti = i/fs + for i in range(200): + ti = i / fs src_data.append(cmath.exp(2j*cmath.pi*f*ti)) # f/fs is a quarter turn per sample. # Set the gain based on this to get 1 out. - gain = 1.0/(cmath.pi/4) + gain = 1.0 / (cmath.pi / 4) expected_result = [0,] + 199*[1.0] diff --git a/gr-analog/python/analog/qa_rail_ff.py b/gr-analog/python/analog/qa_rail_ff.py index e3990dfd3a..93cde00a97 100755..100644 --- a/gr-analog/python/analog/qa_rail_ff.py +++ b/gr-analog/python/analog/qa_rail_ff.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, analog, blocks def clip(x, lo, hi): @@ -60,7 +61,7 @@ class test_rail(gr_unittest.TestCase): lo = -0.75 hi = 0.90 src_data = [-2, -1, -0.5, -0.25, 0, 0.25, 0.5, 1, 2] - expected_result = map(lambda x: clip(x, lo, hi), src_data) + expected_result = [clip(x, lo, hi) for x in src_data] src = blocks.vector_source_f(src_data) op = analog.rail_ff(lo, hi) diff --git a/gr-analog/python/analog/qa_random_uniform_source.py b/gr-analog/python/analog/qa_random_uniform_source.py index 474c5716c7..d02ea7ea87 100755..100644 --- a/gr-analog/python/analog/qa_random_uniform_source.py +++ b/gr-analog/python/analog/qa_random_uniform_source.py @@ -21,6 +21,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest from gnuradio import blocks, analog import numpy as np diff --git a/gr-analog/python/analog/qa_sig_source.py b/gr-analog/python/analog/qa_sig_source.py index 8d050fa72b..a38db29280 100755..100644 --- a/gr-analog/python/analog/qa_sig_source.py +++ b/gr-analog/python/analog/qa_sig_source.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import math import pmt from gnuradio import gr, gr_unittest, analog, blocks diff --git a/gr-analog/python/analog/qa_simple_squelch.py b/gr-analog/python/analog/qa_simple_squelch.py index b09a3b2a87..a0b09e7198 100755..100644 --- a/gr-analog/python/analog/qa_simple_squelch.py +++ b/gr-analog/python/analog/qa_simple_squelch.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, analog, blocks class test_simple_squelch(gr_unittest.TestCase): @@ -48,7 +50,7 @@ class test_simple_squelch(gr_unittest.TestCase): alpha = 0.0001 thr = -25 - src_data = map(lambda x: float(x)/10.0, range(1, 40)) + src_data = [float(x) / 10.0 for x in range(1, 40)] src = blocks.vector_source_c(src_data) op = analog.simple_squelch_cc(thr, alpha) dst = blocks.vector_sink_c() diff --git a/gr-analog/python/analog/standard_squelch.py b/gr-analog/python/analog/standard_squelch.py index 3ed9ebceaa..9609f2449e 100644 --- a/gr-analog/python/analog/standard_squelch.py +++ b/gr-analog/python/analog/standard_squelch.py @@ -1,3 +1,5 @@ +from __future__ import division +from __future__ import unicode_literals # # Copyright 2005,2007,2012 Free Software Foundation, Inc. # @@ -26,29 +28,29 @@ from gnuradio import filter class standard_squelch(gr.hier_block2): def __init__(self, audio_rate): - gr.hier_block2.__init__(self, "standard_squelch", - gr.io_signature(1, 1, gr.sizeof_float), # Input signature - gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + gr.hier_block2.__init__(self, "standard_squelch", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature self.input_node = blocks.add_const_ff(0) # FIXME kludge self.low_iir = filter.iir_filter_ffd((0.0193,0,-0.0193),(1,1.9524,-0.9615)) self.low_square = blocks.multiply_ff() - self.low_smooth = filter.single_pole_iir_filter_ff(1/(0.01*audio_rate)) # 100ms time constant + self.low_smooth = filter.single_pole_iir_filter_ff(1 / (0.01*audio_rate)) # 100ms time constant self.hi_iir = filter.iir_filter_ffd((0.0193,0,-0.0193),(1,1.3597,-0.9615)) self.hi_square = blocks.multiply_ff() - self.hi_smooth = filter.single_pole_iir_filter_ff(1/(0.01*audio_rate)) + self.hi_smooth = filter.single_pole_iir_filter_ff(1 / (0.01*audio_rate)) self.sub = blocks.sub_ff(); self.add = blocks.add_ff(); self.gate = blocks.threshold_ff(0.3,0.43,0) - self.squelch_lpf = filter.single_pole_iir_filter_ff(1/(0.01*audio_rate)) + self.squelch_lpf = filter.single_pole_iir_filter_ff(1 / (0.01*audio_rate)) self.div = blocks.divide_ff() self.squelch_mult = blocks.multiply_ff() - self.connect(self, self.input_node) + self.connect(self, self.input_node) self.connect(self.input_node, (self.squelch_mult, 0)) self.connect(self.input_node,self.low_iir) @@ -66,7 +68,7 @@ class standard_squelch(gr.hier_block2): self.connect(self.sub, (self.div, 0)) self.connect(self.add, (self.div, 1)) self.connect(self.div, self.gate, self.squelch_lpf, (self.squelch_mult,1)) - self.connect(self.squelch_mult, self) + self.connect(self.squelch_mult, self) def set_threshold(self, threshold): self.gate.set_hi(threshold) @@ -75,4 +77,4 @@ class standard_squelch(gr.hier_block2): return self.gate.hi() def squelch_range(self): - return (0.0, 1.0, 1.0/100) + return (0.0, 1.0, 1.0 / 100) diff --git a/gr-analog/python/analog/wfm_rcv.py b/gr-analog/python/analog/wfm_rcv.py index d35d219275..c1f6dea339 100644 --- a/gr-analog/python/analog/wfm_rcv.py +++ b/gr-analog/python/analog/wfm_rcv.py @@ -19,14 +19,17 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, filter -from fm_emph import fm_deemph +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + import math -try: - from gnuradio import analog -except ImportError: - import analog_swig as analog +from gnuradio import gr, filter + +from . import analog_swig as analog +from .fm_emph import fm_deemph + class wfm_rcv(gr.hier_block2): def __init__ (self, quad_rate, audio_decimation): @@ -40,14 +43,14 @@ class wfm_rcv(gr.hier_block2): quad_rate: input sample rate of complex baseband input. (float) audio_decimation: how much to decimate quad_rate to get to audio. (integer) """ - gr.hier_block2.__init__(self, "wfm_rcv", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + gr.hier_block2.__init__(self, "wfm_rcv", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature volume = 20. max_dev = 75e3 - fm_demod_gain = quad_rate/(2*math.pi*max_dev) + fm_demod_gain = quad_rate / (2*math.pi*max_dev) audio_rate = quad_rate / audio_decimation @@ -64,7 +67,7 @@ class wfm_rcv(gr.hier_block2): width_of_transition_band = audio_rate / 32 audio_coeffs = filter.firdes.low_pass(1.0, # gain quad_rate, # sampling rate - audio_rate/2 - width_of_transition_band, + audio_rate / 2 - width_of_transition_band, width_of_transition_band, filter.firdes.WIN_HAMMING) # input: float; output: float diff --git a/gr-analog/python/analog/wfm_rcv_fmdet.py b/gr-analog/python/analog/wfm_rcv_fmdet.py index b7cd1458fb..fe91465a3b 100644 --- a/gr-analog/python/analog/wfm_rcv_fmdet.py +++ b/gr-analog/python/analog/wfm_rcv_fmdet.py @@ -19,16 +19,19 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + +import math + from gnuradio import gr from gnuradio import blocks from gnuradio import filter -from fm_emph import fm_deemph -import math -try: - from gnuradio import analog -except ImportError: - import analog_swig as analog +from . import analog_swig as analog +from .fm_emph import fm_deemph + class wfm_rcv_fmdet(gr.hier_block2): def __init__ (self, demod_rate, audio_decimation): @@ -43,11 +46,11 @@ class wfm_rcv_fmdet(gr.hier_block2): demod_rate: input sample rate of complex baseband input. (float) audio_decimation: how much to decimate demod_rate to get to audio. (integer) """ - gr.hier_block2.__init__(self, "wfm_rcv_fmdet", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(2, 2, gr.sizeof_float)) # Output signature - lowfreq = -125e3/demod_rate - highfreq = 125e3/demod_rate + gr.hier_block2.__init__(self, "wfm_rcv_fmdet", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(2, 2, gr.sizeof_float)) # Output signature + lowfreq = -125e3 / demod_rate + highfreq = 125e3 / demod_rate audio_rate = demod_rate / audio_decimation # We assign to self so that outsiders can grab the demodulator @@ -98,8 +101,8 @@ class wfm_rcv_fmdet(gr.hier_block2): stereo_dsbsc_filter_coeffs = \ filter.firdes.complex_band_pass(20.0, demod_rate, - 38000-15000/2, - 38000+15000/2, + 38000-15000 / 2, + 38000+15000 / 2, width_of_transition_band, filter.firdes.WIN_HAMMING) #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) @@ -127,12 +130,12 @@ class wfm_rcv_fmdet(gr.hier_block2): #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs # construct overlap add filter system from coefficients for stereo carrier - self.rds_signal_filter = \ + self.rds_signal_filter = \ filter.fir_filter_fcc(audio_decimation, stereo_rds_filter_coeffs) - self.rds_carrier_generator = blocks.multiply_cc(); - self.rds_signal_generator = blocks.multiply_cc(); - self_rds_signal_processor = blocks.null_sink(gr.sizeof_gr_complex); + self.rds_carrier_generator = blocks.multiply_cc(); + self.rds_signal_generator = blocks.multiply_cc(); + self_rds_signal_processor = blocks.null_sink(gr.sizeof_gr_complex); loop_bw = 2*math.pi/100.0 max_freq = -2.0*math.pi*18990/audio_rate; @@ -191,21 +194,21 @@ class wfm_rcv_fmdet(gr.hier_block2): #send it to negative side of a subtracter self.connect(self.LmR_real,(self.Make_Right,1)) - # Make rds carrier by taking the squared pilot tone and - # multiplying by pilot tone - self.connect(self.stereo_basebander,(self.rds_carrier_generator,0)) + # Make rds carrier by taking the squared pilot tone and + # multiplying by pilot tone + self.connect(self.stereo_basebander,(self.rds_carrier_generator,0)) self.connect(self.stereo_carrier_pll_recovery,(self.rds_carrier_generator,1)) - # take signal, filter off rds, send into mixer 0 channel - self.connect(self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0)) + # take signal, filter off rds, send into mixer 0 channel + self.connect(self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0)) # take rds_carrier_generator output and send into mixer 1 # channel - self.connect(self.rds_carrier_generator,(self.rds_signal_generator,1)) + self.connect(self.rds_carrier_generator,(self.rds_signal_generator,1)) - # send basebanded rds signal and send into "processor" - # which for now is a null sink - self.connect(self.rds_signal_generator,self_rds_signal_processor) + # send basebanded rds signal and send into "processor" + # which for now is a null sink + self.connect(self.rds_signal_generator,self_rds_signal_processor) if 1: diff --git a/gr-analog/python/analog/wfm_rcv_pll.py b/gr-analog/python/analog/wfm_rcv_pll.py index 282e2b14be..b6ca7fe7c2 100644 --- a/gr-analog/python/analog/wfm_rcv_pll.py +++ b/gr-analog/python/analog/wfm_rcv_pll.py @@ -19,16 +19,19 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + +import math + from gnuradio import gr from gnuradio import blocks from gnuradio import filter -from fm_emph import fm_deemph -import math -try: - from gnuradio import analog -except ImportError: - import analog_swig as analog +from . import analog_swig as analog +from .fm_emph import fm_deemph + class wfm_rcv_pll(gr.hier_block2): def __init__(self, demod_rate, audio_decimation): @@ -42,9 +45,9 @@ class wfm_rcv_pll(gr.hier_block2): demod_rate: input sample rate of complex baseband input. (float) audio_decimation: how much to decimate demod_rate to get to audio. (integer) """ - gr.hier_block2.__init__(self, "wfm_rcv_pll", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(2, 2, gr.sizeof_float)) # Output signature + gr.hier_block2.__init__(self, "wfm_rcv_pll", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(2, 2, gr.sizeof_float)) # Output signature bandwidth = 250e3 audio_rate = demod_rate / audio_decimation @@ -92,8 +95,8 @@ class wfm_rcv_pll(gr.hier_block2): stereo_dsbsc_filter_coeffs = \ filter.firdes.complex_band_pass(20.0, demod_rate, - 38000-15000/2, - 38000+15000/2, + 38000-15000 / 2, + 38000+15000 / 2, width_of_transition_band, filter.firdes.WIN_HAMMING) #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) @@ -120,12 +123,12 @@ class wfm_rcv_pll(gr.hier_block2): #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs # construct overlap add filter system from coefficients for stereo carrier - self.rds_signal_filter = \ + self.rds_signal_filter = \ filter.fir_filter_fcc(audio_decimation, stereo_rds_filter_coeffs) - self.rds_carrier_generator = blocks.multiply_cc(); - self.rds_signal_generator = blocks.multiply_cc(); - self_rds_signal_processor = blocks.null_sink(gr.sizeof_gr_complex); + self.rds_carrier_generator = blocks.multiply_cc(); + self.rds_signal_generator = blocks.multiply_cc(); + self_rds_signal_processor = blocks.null_sink(gr.sizeof_gr_complex); loop_bw = 2*math.pi/100.0 max_freq = -2.0*math.pi*18990/audio_rate; @@ -169,15 +172,15 @@ class wfm_rcv_pll(gr.hier_block2): #take the same real part of the DSBSC baseband signal and send it to negative side of a subtracter self.connect(self.LmR_real,(self.Make_Right,1)) - # Make rds carrier by taking the squared pilot tone and multiplying by pilot tone - self.connect(self.stereo_basebander,(self.rds_carrier_generator,0)) + # Make rds carrier by taking the squared pilot tone and multiplying by pilot tone + self.connect(self.stereo_basebander,(self.rds_carrier_generator,0)) self.connect(self.stereo_carrier_pll_recovery,(self.rds_carrier_generator,1)) - # take signal, filter off rds, send into mixer 0 channel - self.connect(self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0)) + # take signal, filter off rds, send into mixer 0 channel + self.connect(self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0)) # take rds_carrier_generator output and send into mixer 1 channel - self.connect(self.rds_carrier_generator,(self.rds_signal_generator,1)) - # send basebanded rds signal and send into "processor" which for now is a null sink - self.connect(self.rds_signal_generator,self_rds_signal_processor) + self.connect(self.rds_carrier_generator,(self.rds_signal_generator,1)) + # send basebanded rds signal and send into "processor" which for now is a null sink + self.connect(self.rds_signal_generator,self_rds_signal_processor) if 1: diff --git a/gr-analog/python/analog/wfm_tx.py b/gr-analog/python/analog/wfm_tx.py index a1b589350d..9f49ca3ca2 100644 --- a/gr-analog/python/analog/wfm_tx.py +++ b/gr-analog/python/analog/wfm_tx.py @@ -19,15 +19,19 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + import math + from gnuradio import gr from gnuradio import filter -from fm_emph import fm_preemph -try: - from gnuradio import analog -except ImportError: - import analog_swig as analog +from . import analog_swig as analog +from .fm_emph import fm_preemph + class wfm_tx(gr.hier_block2): def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=75e3, fh=-1.0): @@ -46,16 +50,16 @@ class wfm_tx(gr.hier_block2): quad_rate must be an integer multiple of audio_rate. """ - gr.hier_block2.__init__(self, "wfm_tx", - gr.io_signature(1, 1, gr.sizeof_float), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + gr.hier_block2.__init__(self, "wfm_tx", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature # FIXME audio_rate and quad_rate ought to be exact rationals audio_rate = int(audio_rate) quad_rate = int(quad_rate) if quad_rate % audio_rate != 0: - raise ValueError, "quad_rate is not an integer multiple of audio_rate" + raise ValueError("quad_rate is not an integer multiple of audio_rate") do_interp = audio_rate != quad_rate @@ -66,10 +70,10 @@ class wfm_tx(gr.hier_block2): quad_rate, # Fs 16000, # passband cutoff 18000, # stopband cutoff - 0.1, # passband ripple dB + 0.1, # passband ripple dB 40) # stopband atten dB - print "len(interp_taps) =", len(interp_taps) + print("len(interp_taps) =", len(interp_taps)) self.interpolator = filter.interp_fir_filter_fff (interp_factor, interp_taps) self.preemph = fm_preemph(quad_rate, tau=tau, fh=fh) diff --git a/gr-audio/examples/python/audio_copy.py b/gr-audio/examples/python/audio_copy.py index b68e949497..5909be6508 100755..100644 --- a/gr-audio/examples/python/audio_copy.py +++ b/gr-audio/examples/python/audio_copy.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio.eng_arg import eng_float diff --git a/gr-audio/examples/python/audio_play.py b/gr-audio/examples/python/audio_play.py index 367d7bd201..7d551cc18a 100755..100644 --- a/gr-audio/examples/python/audio_play.py +++ b/gr-audio/examples/python/audio_play.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks diff --git a/gr-audio/examples/python/audio_to_file.py b/gr-audio/examples/python/audio_to_file.py index b385abf925..e35bb70382 100755..100644 --- a/gr-audio/examples/python/audio_to_file.py +++ b/gr-audio/examples/python/audio_to_file.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks diff --git a/gr-audio/examples/python/dial_tone.py b/gr-audio/examples/python/dial_tone.py index ebef8c01cb..98a75e6bb5 100755..100644 --- a/gr-audio/examples/python/dial_tone.py +++ b/gr-audio/examples/python/dial_tone.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio.eng_arg import eng_float diff --git a/gr-audio/examples/python/dial_tone_daemon.py b/gr-audio/examples/python/dial_tone_daemon.py index 9919e367a6..932ae07d4f 100755..100644 --- a/gr-audio/examples/python/dial_tone_daemon.py +++ b/gr-audio/examples/python/dial_tone_daemon.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr, gru from gnuradio import audio from gnuradio.eng_arg import eng_float @@ -54,5 +56,5 @@ class my_top_block(gr.top_block): if __name__ == '__main__': pid = gru.daemonize() - print "To stop this program, enter 'kill %d'" % pid + print("To stop this program, enter 'kill %d'" % pid) my_top_block().run() diff --git a/gr-audio/examples/python/dial_tone_wav.py b/gr-audio/examples/python/dial_tone_wav.py index 351ca94e78..b9cf6bc510 100755..100644 --- a/gr-audio/examples/python/dial_tone_wav.py +++ b/gr-audio/examples/python/dial_tone_wav.py @@ -22,6 +22,7 @@ # GNU Radio example program to record a dial tone to a WAV file +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from gnuradio.eng_arg import eng_float diff --git a/gr-audio/examples/python/mono_tone.py b/gr-audio/examples/python/mono_tone.py index 653fd575fc..be86a4f6f4 100755..100644 --- a/gr-audio/examples/python/mono_tone.py +++ b/gr-audio/examples/python/mono_tone.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio.eng_arg import eng_float diff --git a/gr-audio/examples/python/multi_tone.py b/gr-audio/examples/python/multi_tone.py index 00c052794a..a2e8702a7a 100755..100644 --- a/gr-audio/examples/python/multi_tone.py +++ b/gr-audio/examples/python/multi_tone.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio.eng_arg import eng_float, intx @@ -59,11 +61,11 @@ class my_top_block(gr.top_block): # See "Genesis of a Music". He was into some very wild tunings... base = 392 ratios = { 1 : 1.0, - 3 : 3.0/2, - 5 : 5.0/4, - 7 : 7.0/4, - 9 : 9.0/8, - 11 : 11.0/8 } + 3 : 3.0 / 2, + 5 : 5.0 / 4, + 7 : 7.0 / 4, + 9 : 9.0 / 8, + 11 : 11.0 / 8 } # progression = (1, 5, 3, 7) # progression = (1, 9, 3, 7) diff --git a/gr-audio/examples/python/noise.py b/gr-audio/examples/python/noise.py index 31fdb16fe5..ee4e7f213c 100755..100644 --- a/gr-audio/examples/python/noise.py +++ b/gr-audio/examples/python/noise.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import digital diff --git a/gr-audio/examples/python/spectrum_inversion.py b/gr-audio/examples/python/spectrum_inversion.py index 163668e450..f5d5a05b90 100755..100644 --- a/gr-audio/examples/python/spectrum_inversion.py +++ b/gr-audio/examples/python/spectrum_inversion.py @@ -26,6 +26,7 @@ # to a SSB signal on the wrong sideband. # +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks diff --git a/gr-audio/examples/python/test_resampler.py b/gr-audio/examples/python/test_resampler.py index 4d8a9233e7..daca7fc717 100755..100644 --- a/gr-audio/examples/python/test_resampler.py +++ b/gr-audio/examples/python/test_resampler.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, gru from gnuradio import audio from gnuradio import filter @@ -54,11 +57,11 @@ class my_top_block(gr.top_block): input_rate = int(args.input_rate) output_rate = int(args.output_rate) - interp = gru.lcm(input_rate, output_rate) / input_rate - decim = gru.lcm(input_rate, output_rate) / output_rate + interp = gru.lcm(input_rate / output_rate, input_rate) + decim = gru.lcm(input_rate / output_rate, output_rate) - print "interp =", interp - print "decim =", decim + print("interp =", interp) + print("decim =", decim) ampl = 0.1 src0 = analog.sig_source_f(input_rate, analog.GR_SIN_WAVE, 650, ampl) diff --git a/gr-audio/python/audio/CMakeLists.txt b/gr-audio/python/audio/CMakeLists.txt index 2edbf21cf4..2f1fee57f5 100644 --- a/gr-audio/python/audio/CMakeLists.txt +++ b/gr-audio/python/audio/CMakeLists.txt @@ -41,6 +41,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-audio/python/audio/__init__.py b/gr-audio/python/audio/__init__.py index 8674c26030..03f5d6a93b 100644 --- a/gr-audio/python/audio/__init__.py +++ b/gr-audio/python/audio/__init__.py @@ -26,6 +26,7 @@ ports on a computer. The underlying hardware driver is system and OS dependent and this module should automatically discover the correct one to use. ''' +from __future__ import unicode_literals import os try: diff --git a/gr-blocks/examples/ctrlport/simple_copy_controller.py b/gr-blocks/examples/ctrlport/simple_copy_controller.py index 7bd05006f5..0f907eef67 100755..100644 --- a/gr-blocks/examples/ctrlport/simple_copy_controller.py +++ b/gr-blocks/examples/ctrlport/simple_copy_controller.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +from __future__ import unicode_literals import sys import pmt from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient diff --git a/gr-blocks/examples/ctrlport/usrp_sink_controller.py b/gr-blocks/examples/ctrlport/usrp_sink_controller.py index ec687d80e1..a5dc200705 100755..100644 --- a/gr-blocks/examples/ctrlport/usrp_sink_controller.py +++ b/gr-blocks/examples/ctrlport/usrp_sink_controller.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +from __future__ import unicode_literals import sys import pmt from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient diff --git a/gr-blocks/examples/ctrlport/usrp_source_controller.py b/gr-blocks/examples/ctrlport/usrp_source_controller.py index 78c5ae66aa..ec27c84a1b 100755..100644 --- a/gr-blocks/examples/ctrlport/usrp_source_controller.py +++ b/gr-blocks/examples/ctrlport/usrp_source_controller.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +from __future__ import unicode_literals import sys import pmt from gnuradio.ctrlport.GNURadioControlPortClient import GNURadioControlPortClient diff --git a/gr-blocks/examples/tags/test_file_tags.py b/gr-blocks/examples/tags/test_file_tags.py index cc11cf594e..0837bcc2ae 100755..100644 --- a/gr-blocks/examples/tags/test_file_tags.py +++ b/gr-blocks/examples/tags/test_file_tags.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + from gnuradio import gr from gnuradio import blocks import sys @@ -27,7 +30,7 @@ import sys try: import scipy except ImportError: - print "Error: Program requires scipy (see: www.scipy.org)." + print("Error: Program requires scipy (see: www.scipy.org).") sys.exit(1) def main(): @@ -52,5 +55,3 @@ def main(): if __name__ == "__main__": main() - - diff --git a/gr-blocks/python/blocks/CMakeLists.txt b/gr-blocks/python/blocks/CMakeLists.txt index afb860a075..aa6de297b2 100644 --- a/gr-blocks/python/blocks/CMakeLists.txt +++ b/gr-blocks/python/blocks/CMakeLists.txt @@ -53,7 +53,7 @@ if(ENABLE_TESTING) foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-blocks/python/blocks/__init__.py b/gr-blocks/python/blocks/__init__.py index fc4cc7ab66..148479a21e 100644 --- a/gr-blocks/python/blocks/__init__.py +++ b/gr-blocks/python/blocks/__init__.py @@ -22,16 +22,20 @@ ''' Processing blocks common to many flowgraphs. ''' + +from __future__ import absolute_import +from __future__ import unicode_literals + import os try: - from blocks_swig import * + from .blocks_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from blocks_swig import * + from .blocks_swig import * -from stream_to_vector_decimator import * +from .stream_to_vector_decimator import * #alias old add_vXX and multiply_vXX add_vcc = add_cc diff --git a/gr-blocks/python/blocks/parse_file_metadata.py b/gr-blocks/python/blocks/parse_file_metadata.py index 7d8d41d166..39092d8abd 100644 --- a/gr-blocks/python/blocks/parse_file_metadata.py +++ b/gr-blocks/python/blocks/parse_file_metadata.py @@ -20,6 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + import sys from gnuradio import gr, blocks import pmt @@ -65,7 +69,7 @@ def parse_header(p, VERBOSE=False): r = pmt.dict_ref(p, pmt.string_to_symbol("version"), dump) version = pmt.to_long(r) if(VERBOSE): - print "Version Number: {0}".format(version) + print("Version Number: {0}".format(version)) else: sys.stderr.write("Could not find key 'version': invalid or corrupt data file.\n") sys.exit(1) @@ -76,7 +80,7 @@ def parse_header(p, VERBOSE=False): samp_rate = pmt.to_double(r) info["rx_rate"] = samp_rate if(VERBOSE): - print "Sample Rate: {0:.2f} sps".format(samp_rate) + print("Sample Rate: {0:.2f} sps".format(samp_rate)) else: sys.stderr.write("Could not find key 'sr': invalid or corrupt data file.\n") sys.exit(1) @@ -91,7 +95,7 @@ def parse_header(p, VERBOSE=False): t = secs + fracs info["rx_time"] = t if(VERBOSE): - print "Seconds: {0:.6f}".format(t) + print("Seconds: {0:.6f}".format(t)) else: sys.stderr.write("Could not find key 'time': invalid or corrupt data file.\n") sys.exit(1) @@ -102,7 +106,7 @@ def parse_header(p, VERBOSE=False): dsize = pmt.to_long(r) info["size"] = dsize if(VERBOSE): - print "Item size: {0}".format(dsize) + print("Item size: {0}".format(dsize)) else: sys.stderr.write("Could not find key 'size': invalid or corrupt data file.\n") sys.exit(1) @@ -114,7 +118,7 @@ def parse_header(p, VERBOSE=False): stype = ftype_to_string[dtype] info["type"] = stype if(VERBOSE): - print "Data Type: {0} ({1})".format(stype, dtype) + print("Data Type: {0} ({1})".format(stype, dtype)) else: sys.stderr.write("Could not find key 'type': invalid or corrupt data file.\n") sys.exit(1) @@ -125,7 +129,7 @@ def parse_header(p, VERBOSE=False): cplx = pmt.to_bool(r) info["cplx"] = cplx if(VERBOSE): - print "Complex? {0}".format(cplx) + print("Complex? {0}".format(cplx)) else: sys.stderr.write("Could not find key 'cplx': invalid or corrupt data file.\n") sys.exit(1) @@ -138,9 +142,9 @@ def parse_header(p, VERBOSE=False): info["extra_len"] = seg_start - HEADER_LENGTH info["has_extra"] = info["extra_len"] > 0 if(VERBOSE): - print "Header Length: {0} bytes".format(info["hdr_len"]) - print "Extra Length: {0}".format((info["extra_len"])) - print "Extra Header? {0}".format(info["has_extra"]) + print("Header Length: {0} bytes".format(info["hdr_len"])) + print("Extra Length: {0}".format((info["extra_len"]))) + print("Extra Header? {0}".format(info["has_extra"])) else: sys.stderr.write("Could not find key 'strt': invalid or corrupt data file.\n") sys.exit(1) @@ -150,13 +154,13 @@ def parse_header(p, VERBOSE=False): r = pmt.dict_ref(p, pmt.string_to_symbol("bytes"), dump) nbytes = pmt.to_uint64(r) - nitems = nbytes/dsize + nitems = nbytes / dsize info["nitems"] = nitems info["nbytes"] = nbytes if(VERBOSE): - print "Size of Data: {0} bytes".format(nbytes) - print " {0} items".format(nitems) + print("Size of Data: {0} bytes".format(nbytes)) + print(" {0} items".format(nitems)) else: sys.stderr.write("Could not find key 'size': invalid or corrupt data file.\n") sys.exit(1) @@ -171,12 +175,12 @@ def parse_extra_dict(p, info, VERBOSE=False): items = pmt.dict_items(p) nitems = pmt.length(items) - for i in xrange(nitems): + for i in range(nitems): item = pmt.nth(i, items) key = pmt.symbol_to_string(pmt.car(item)) val = pmt.cdr(item) info[key] = val if(VERBOSE): - print "{0}: {1}".format(key, val) + print("{0}: {1}".format(key, val)) return info diff --git a/gr-blocks/python/blocks/qa_add_mult_div_sub.py b/gr-blocks/python/blocks/qa_add_mult_div_sub.py index 8699b3a085..f90609f9e0 100755..100644 --- a/gr-blocks/python/blocks/qa_add_mult_div_sub.py +++ b/gr-blocks/python/blocks/qa_add_mult_div_sub.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_add_mult_div_sub(gr_unittest.TestCase): @@ -31,7 +32,7 @@ class test_add_mult_div_sub(gr_unittest.TestCase): self.tb = None def help_ii(self, src_data, exp_data, op): - for s in zip(range(len(src_data)), src_data): + for s in zip(list(range(len(src_data))), src_data): src = blocks.vector_source_i(s[1]) self.tb.connect(src, (op, s[0])) dst = blocks.vector_sink_i() @@ -41,7 +42,7 @@ class test_add_mult_div_sub(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_ss(self, src_data, exp_data, op): - for s in zip(range(len(src_data)), src_data): + for s in zip(list(range(len(src_data))), src_data): src = blocks.vector_source_s(s[1]) self.tb.connect(src, (op, s[0])) dst = blocks.vector_sink_s() @@ -51,7 +52,7 @@ class test_add_mult_div_sub(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_ff(self, src_data, exp_data, op): - for s in zip(range(len(src_data)), src_data): + for s in zip(list(range(len(src_data))), src_data): src = blocks.vector_source_f(s[1]) self.tb.connect(src, (op, s[0])) dst = blocks.vector_sink_f() @@ -61,7 +62,7 @@ class test_add_mult_div_sub(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_cc(self, src_data, exp_data, op): - for s in zip(range(len(src_data)), src_data): + for s in zip(list(range(len(src_data))), src_data): src = blocks.vector_source_c(s[1]) self.tb.connect(src, (op, s[0])) dst = blocks.vector_sink_c() diff --git a/gr-blocks/python/blocks/qa_add_mult_v.py b/gr-blocks/python/blocks/qa_add_mult_v.py index 721ee4eca6..eaa33755b7 100755..100644 --- a/gr-blocks/python/blocks/qa_add_mult_v.py +++ b/gr-blocks/python/blocks/qa_add_mult_v.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_add_mult_v(gr_unittest.TestCase): @@ -31,12 +32,13 @@ class test_add_mult_v(gr_unittest.TestCase): self.tb = None def help_ss(self, size, src_data, exp_data, op): - for s in zip(range (len (src_data)), src_data): + for s in zip(list(range(len (src_data))), src_data): src = blocks.vector_source_s(s[1]) - srcv = blocks.stream_to_vector(gr.sizeof_short, size) - self.tb.connect(src, srcv) + srcv = blocks.stream_to_vector(gr.sizeof_short, size) + self.tb.connect(src, srcv) self.tb.connect(srcv, (op, s[0])) - rhs = blocks.vector_to_stream(gr.sizeof_short, size) + + rhs = blocks.vector_to_stream(gr.sizeof_short, size) dst = blocks.vector_sink_s() self.tb.connect(op, rhs, dst) self.tb.run() @@ -44,12 +46,13 @@ class test_add_mult_v(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_ii(self, size, src_data, exp_data, op): - for s in zip(range (len (src_data)), src_data): + for s in zip(list(range(len (src_data))), src_data): src = blocks.vector_source_i(s[1]) - srcv = blocks.stream_to_vector(gr.sizeof_int, size) - self.tb.connect(src, srcv) + srcv = blocks.stream_to_vector(gr.sizeof_int, size) + self.tb.connect(src, srcv) self.tb.connect(srcv, (op, s[0])) - rhs = blocks.vector_to_stream(gr.sizeof_int, size) + + rhs = blocks.vector_to_stream(gr.sizeof_int, size) dst = blocks.vector_sink_i() self.tb.connect(op, rhs, dst) self.tb.run() @@ -57,12 +60,13 @@ class test_add_mult_v(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_ff(self, size, src_data, exp_data, op): - for s in zip(range (len (src_data)), src_data): + for s in zip(list(range(len (src_data))), src_data): src = blocks.vector_source_f(s[1]) - srcv = blocks.stream_to_vector(gr.sizeof_float, size) - self.tb.connect(src, srcv) + srcv = blocks.stream_to_vector(gr.sizeof_float, size) + self.tb.connect(src, srcv) self.tb.connect(srcv, (op, s[0])) - rhs = blocks.vector_to_stream(gr.sizeof_float, size) + + rhs = blocks.vector_to_stream(gr.sizeof_float, size) dst = blocks.vector_sink_f() self.tb.connect(op, rhs, dst) self.tb.run() @@ -70,12 +74,13 @@ class test_add_mult_v(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_cc(self, size, src_data, exp_data, op): - for s in zip(range (len (src_data)), src_data): + for s in zip(list(range(len (src_data))), src_data): src = blocks.vector_source_c(s[1]) - srcv = blocks.stream_to_vector(gr.sizeof_gr_complex, size) - self.tb.connect(src, srcv) + srcv = blocks.stream_to_vector(gr.sizeof_gr_complex, size) + self.tb.connect(src, srcv) self.tb.connect(srcv, (op, s[0])) - rhs = blocks.vector_to_stream(gr.sizeof_gr_complex, size) + + rhs = blocks.vector_to_stream(gr.sizeof_gr_complex, size) dst = blocks.vector_sink_c() self.tb.connect(op, rhs, dst) self.tb.run() @@ -83,9 +88,9 @@ class test_add_mult_v(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_const_ss(self, src_data, exp_data, op): - src = blocks.vector_source_s(src_data) - srcv = blocks.stream_to_vector(gr.sizeof_short, len(src_data)) - rhs = blocks.vector_to_stream(gr.sizeof_short, len(src_data)) + src = blocks.vector_source_s(src_data) + srcv = blocks.stream_to_vector(gr.sizeof_short, len(src_data)) + rhs = blocks.vector_to_stream(gr.sizeof_short, len(src_data)) dst = blocks.vector_sink_s() self.tb.connect(src, srcv, op, rhs, dst) self.tb.run() @@ -93,9 +98,9 @@ class test_add_mult_v(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_const_ii(self, src_data, exp_data, op): - src = blocks.vector_source_i(src_data) - srcv = blocks.stream_to_vector(gr.sizeof_int, len(src_data)) - rhs = blocks.vector_to_stream(gr.sizeof_int, len(src_data)) + src = blocks.vector_source_i(src_data) + srcv = blocks.stream_to_vector(gr.sizeof_int, len(src_data)) + rhs = blocks.vector_to_stream(gr.sizeof_int, len(src_data)) dst = blocks.vector_sink_i() self.tb.connect(src, srcv, op, rhs, dst) self.tb.run() @@ -103,9 +108,9 @@ class test_add_mult_v(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_const_ff(self, src_data, exp_data, op): - src = blocks.vector_source_f(src_data) - srcv = blocks.stream_to_vector(gr.sizeof_float, len(src_data)) - rhs = blocks.vector_to_stream(gr.sizeof_float, len(src_data)) + src = blocks.vector_source_f(src_data) + srcv = blocks.stream_to_vector(gr.sizeof_float, len(src_data)) + rhs = blocks.vector_to_stream(gr.sizeof_float, len(src_data)) dst = blocks.vector_sink_f() self.tb.connect(src, srcv, op, rhs, dst) self.tb.run() @@ -113,9 +118,9 @@ class test_add_mult_v(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_const_cc(self, src_data, exp_data, op): - src = blocks.vector_source_c(src_data) - srcv = blocks.stream_to_vector(gr.sizeof_gr_complex, len(src_data)) - rhs = blocks.vector_to_stream(gr.sizeof_gr_complex, len(src_data)) + src = blocks.vector_source_c(src_data) + srcv = blocks.stream_to_vector(gr.sizeof_gr_complex, len(src_data)) + rhs = blocks.vector_to_stream(gr.sizeof_gr_complex, len(src_data)) dst = blocks.vector_sink_c() self.tb.connect(src, srcv, op, rhs, dst) self.tb.run() @@ -125,234 +130,234 @@ class test_add_mult_v(gr_unittest.TestCase): # add_vXX def test_add_vss_one(self): - src1_data = (1,) - src2_data = (2,) - src3_data = (3,) - expected_result = (6,) - op = blocks.add_ss(1) - self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = blocks.add_ss(1) + self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op) def test_add_vss_five(self): - src1_data = (1, 2, 3, 4, 5) - src2_data = (6, 7, 8, 9, 10) - src3_data = (11, 12, 13, 14, 15) - expected_result = (18, 21, 24, 27, 30) - op = blocks.add_ss(5) - self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (18, 21, 24, 27, 30) + op = blocks.add_ss(5) + self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op) def test_add_vii_one(self): - src1_data = (1,) - src2_data = (2,) - src3_data = (3,) - expected_result = (6,) - op = blocks.add_ii(1) - self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = blocks.add_ii(1) + self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op) def test_add_vii_five(self): - src1_data = (1, 2, 3, 4, 5) - src2_data = (6, 7, 8, 9, 10) - src3_data = (11, 12, 13, 14, 15) - expected_result = (18, 21, 24, 27, 30) - op = blocks.add_ii(5) - self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (18, 21, 24, 27, 30) + op = blocks.add_ii(5) + self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op) def test_add_vff_one(self): - src1_data = (1.0,) - src2_data = (2.0,) - src3_data = (3.0,) - expected_result = (6.0,) - op = blocks.add_ff(1) - self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1.0,) + src2_data = (2.0,) + src3_data = (3.0,) + expected_result = (6.0,) + op = blocks.add_ff(1) + self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op) def test_add_vff_five(self): - src1_data = (1.0, 2.0, 3.0, 4.0, 5.0) - src2_data = (6.0, 7.0, 8.0, 9.0, 10.0) - src3_data = (11.0, 12.0, 13.0, 14.0, 15.0) - expected_result = (18.0, 21.0, 24.0, 27.0, 30.0) - op = blocks.add_ff(5) - self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1.0, 2.0, 3.0, 4.0, 5.0) + src2_data = (6.0, 7.0, 8.0, 9.0, 10.0) + src3_data = (11.0, 12.0, 13.0, 14.0, 15.0) + expected_result = (18.0, 21.0, 24.0, 27.0, 30.0) + op = blocks.add_ff(5) + self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op) def test_add_vcc_one(self): - src1_data = (1.0+2.0j,) - src2_data = (3.0+4.0j,) - src3_data = (5.0+6.0j,) - expected_result = (9.0+12j,) - op = blocks.add_cc(1) - self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1.0+2.0j,) + src2_data = (3.0+4.0j,) + src3_data = (5.0+6.0j,) + expected_result = (9.0+12j,) + op = blocks.add_cc(1) + self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op) def test_add_vcc_five(self): - src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) - src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) - src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) - expected_result = (33.0+36.0j, 39.0+42.0j, 45.0+48.0j, 51.0+54.0j, 57.0+60.0j) - op = blocks.add_cc(5) - self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) + src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) + expected_result = (33.0+36.0j, 39.0+42.0j, 45.0+48.0j, 51.0+54.0j, 57.0+60.0j) + op = blocks.add_cc(5) + self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op) # add_const_vXX def test_add_const_vss_one(self): - src_data = (1,) - op = blocks.add_const_vss((2,)) - exp_data = (3,) - self.help_const_ss(src_data, exp_data, op) + src_data = (1,) + op = blocks.add_const_vss((2,)) + exp_data = (3,) + self.help_const_ss(src_data, exp_data, op) def test_add_const_vss_five(self): - src_data = (1, 2, 3, 4, 5) - op = blocks.add_const_vss((6, 7, 8, 9, 10)) - exp_data = (7, 9, 11, 13, 15) - self.help_const_ss(src_data, exp_data, op) + src_data = (1, 2, 3, 4, 5) + op = blocks.add_const_vss((6, 7, 8, 9, 10)) + exp_data = (7, 9, 11, 13, 15) + self.help_const_ss(src_data, exp_data, op) def test_add_const_vii_one(self): - src_data = (1,) - op = blocks.add_const_vii((2,)) - exp_data = (3,) - self.help_const_ii(src_data, exp_data, op) + src_data = (1,) + op = blocks.add_const_vii((2,)) + exp_data = (3,) + self.help_const_ii(src_data, exp_data, op) def test_add_const_vii_five(self): - src_data = (1, 2, 3, 4, 5) - op = blocks.add_const_vii((6, 7, 8, 9, 10)) - exp_data = (7, 9, 11, 13, 15) - self.help_const_ii(src_data, exp_data, op) + src_data = (1, 2, 3, 4, 5) + op = blocks.add_const_vii((6, 7, 8, 9, 10)) + exp_data = (7, 9, 11, 13, 15) + self.help_const_ii(src_data, exp_data, op) def test_add_const_vff_one(self): - src_data = (1.0,) - op = blocks.add_const_vff((2.0,)) - exp_data = (3.0,) - self.help_const_ff(src_data, exp_data, op) + src_data = (1.0,) + op = blocks.add_const_vff((2.0,)) + exp_data = (3.0,) + self.help_const_ff(src_data, exp_data, op) def test_add_const_vff_five(self): - src_data = (1.0, 2.0, 3.0, 4.0, 5.0) - op = blocks.add_const_vff((6.0, 7.0, 8.0, 9.0, 10.0)) - exp_data = (7.0, 9.0, 11.0, 13.0, 15.0) - self.help_const_ff(src_data, exp_data, op) + src_data = (1.0, 2.0, 3.0, 4.0, 5.0) + op = blocks.add_const_vff((6.0, 7.0, 8.0, 9.0, 10.0)) + exp_data = (7.0, 9.0, 11.0, 13.0, 15.0) + self.help_const_ff(src_data, exp_data, op) def test_add_const_vcc_one(self): - src_data = (1.0+2.0j,) - op = blocks.add_const_vcc((2.0+3.0j,)) - exp_data = (3.0+5.0j,) - self.help_const_cc(src_data, exp_data, op) + src_data = (1.0+2.0j,) + op = blocks.add_const_vcc((2.0+3.0j,)) + exp_data = (3.0+5.0j,) + self.help_const_cc(src_data, exp_data, op) def test_add_const_vcc_five(self): - src_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) - op = blocks.add_const_vcc((11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)) - exp_data = (12.0+14.0j, 16.0+18.0j, 20.0+22.0j, 24.0+26.0j, 28.0+30.0j) - self.help_const_cc(src_data, exp_data, op) + src_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + op = blocks.add_const_vcc((11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)) + exp_data = (12.0+14.0j, 16.0+18.0j, 20.0+22.0j, 24.0+26.0j, 28.0+30.0j) + self.help_const_cc(src_data, exp_data, op) # multiply_vXX def test_multiply_vss_one(self): - src1_data = (1,) - src2_data = (2,) - src3_data = (3,) - expected_result = (6,) - op = blocks.multiply_ss(1) - self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = blocks.multiply_ss(1) + self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op) def test_multiply_vss_five(self): - src1_data = (1, 2, 3, 4, 5) - src2_data = (6, 7, 8, 9, 10) - src3_data = (11, 12, 13, 14, 15) - expected_result = (66, 168, 312, 504, 750) - op = blocks.multiply_ss(5) - self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (66, 168, 312, 504, 750) + op = blocks.multiply_ss(5) + self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op) def test_multiply_vii_one(self): - src1_data = (1,) - src2_data = (2,) - src3_data = (3,) - expected_result = (6,) - op = blocks.multiply_ii(1) - self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = blocks.multiply_ii(1) + self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op) def test_multiply_vii_five(self): - src1_data = (1, 2, 3, 4, 5) - src2_data = (6, 7, 8, 9, 10) - src3_data = (11, 12, 13, 14, 15) - expected_result = (66, 168, 312, 504, 750) - op = blocks.multiply_ii(5) - self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (66, 168, 312, 504, 750) + op = blocks.multiply_ii(5) + self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op) def test_multiply_vff_one(self): - src1_data = (1.0,) - src2_data = (2.0,) - src3_data = (3.0,) - expected_result = (6.0,) - op = blocks.multiply_ff(1) - self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1.0,) + src2_data = (2.0,) + src3_data = (3.0,) + expected_result = (6.0,) + op = blocks.multiply_ff(1) + self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op) def test_multiply_vff_five(self): - src1_data = (1.0, 2.0, 3.0, 4.0, 5.0) - src2_data = (6.0, 7.0, 8.0, 9.0, 10.0) - src3_data = (11.0, 12.0, 13.0, 14.0, 15.0) - expected_result = (66.0, 168.0, 312.0, 504.0, 750.0) - op = blocks.multiply_ff(5) - self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1.0, 2.0, 3.0, 4.0, 5.0) + src2_data = (6.0, 7.0, 8.0, 9.0, 10.0) + src3_data = (11.0, 12.0, 13.0, 14.0, 15.0) + expected_result = (66.0, 168.0, 312.0, 504.0, 750.0) + op = blocks.multiply_ff(5) + self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op) def test_multiply_vcc_one(self): - src1_data = (1.0+2.0j,) - src2_data = (3.0+4.0j,) - src3_data = (5.0+6.0j,) - expected_result = (-85+20j,) - op = blocks.multiply_cc(1) - self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1.0+2.0j,) + src2_data = (3.0+4.0j,) + src3_data = (5.0+6.0j,) + expected_result = (-85+20j,) + op = blocks.multiply_cc(1) + self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op) def test_multiply_vcc_five(self): - src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) - src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) - src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) - expected_result = (-1021.0+428.0j, -2647.0+1754.0j, -4945.0+3704.0j, -8011.0+6374.0j, -11941.0+9860.0j) - op = blocks.multiply_cc(5) - self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op) + src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) + src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) + expected_result = (-1021.0+428.0j, -2647.0+1754.0j, -4945.0+3704.0j, -8011.0+6374.0j, -11941.0+9860.0j) + op = blocks.multiply_cc(5) + self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op) # multiply_const_vXX def test_multiply_const_vss_one(self): - src_data = (2,) - op = blocks.multiply_const_vss((3,)) - exp_data = (6,) - self.help_const_ss(src_data, exp_data, op) + src_data = (2,) + op = blocks.multiply_const_vss((3,)) + exp_data = (6,) + self.help_const_ss(src_data, exp_data, op) def test_multiply_const_vss_five(self): - src_data = (1, 2, 3, 4, 5) - op = blocks.multiply_const_vss((6, 7, 8, 9, 10)) - exp_data = (6, 14, 24, 36, 50) - self.help_const_ss(src_data, exp_data, op) + src_data = (1, 2, 3, 4, 5) + op = blocks.multiply_const_vss((6, 7, 8, 9, 10)) + exp_data = (6, 14, 24, 36, 50) + self.help_const_ss(src_data, exp_data, op) def test_multiply_const_vii_one(self): - src_data = (2,) - op = blocks.multiply_const_vii((3,)) - exp_data = (6,) - self.help_const_ii(src_data, exp_data, op) + src_data = (2,) + op = blocks.multiply_const_vii((3,)) + exp_data = (6,) + self.help_const_ii(src_data, exp_data, op) def test_multiply_const_vii_five(self): - src_data = (1, 2, 3, 4, 5) - op = blocks.multiply_const_vii((6, 7, 8, 9, 10)) - exp_data = (6, 14, 24, 36, 50) - self.help_const_ii(src_data, exp_data, op) + src_data = (1, 2, 3, 4, 5) + op = blocks.multiply_const_vii((6, 7, 8, 9, 10)) + exp_data = (6, 14, 24, 36, 50) + self.help_const_ii(src_data, exp_data, op) def test_multiply_const_vff_one(self): - src_data = (2.0,) - op = blocks.multiply_const_vff((3.0,)) - exp_data = (6.0,) - self.help_const_ff(src_data, exp_data, op) + src_data = (2.0,) + op = blocks.multiply_const_vff((3.0,)) + exp_data = (6.0,) + self.help_const_ff(src_data, exp_data, op) def test_multiply_const_vff_five(self): - src_data = (1.0, 2.0, 3.0, 4.0, 5.0) - op = blocks.multiply_const_vff((6.0, 7.0, 8.0, 9.0, 10.0)) - exp_data = (6.0, 14.0, 24.0, 36.0, 50.0) - self.help_const_ff(src_data, exp_data, op) + src_data = (1.0, 2.0, 3.0, 4.0, 5.0) + op = blocks.multiply_const_vff((6.0, 7.0, 8.0, 9.0, 10.0)) + exp_data = (6.0, 14.0, 24.0, 36.0, 50.0) + self.help_const_ff(src_data, exp_data, op) def test_multiply_const_vcc_one(self): - src_data = (1.0+2.0j,) - op = blocks.multiply_const_vcc((2.0+3.0j,)) - exp_data = (-4.0+7.0j,) - self.help_const_cc(src_data, exp_data, op) + src_data = (1.0+2.0j,) + op = blocks.multiply_const_vcc((2.0+3.0j,)) + exp_data = (-4.0+7.0j,) + self.help_const_cc(src_data, exp_data, op) def test_multiply_const_vcc_five(self): - src_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) - op = blocks.multiply_const_vcc((11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)) - exp_data = (-13.0+34.0j, -17.0+94.0j, -21.0+170.0j, -25.0+262.0j, -29.0+370.0j) - self.help_const_cc(src_data, exp_data, op) + src_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + op = blocks.multiply_const_vcc((11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)) + exp_data = (-13.0+34.0j, -17.0+94.0j, -21.0+170.0j, -25.0+262.0j, -29.0+370.0j) + self.help_const_cc(src_data, exp_data, op) if __name__ == '__main__': diff --git a/gr-blocks/python/blocks/qa_affinity.py b/gr-blocks/python/blocks/qa_affinity.py index 98b5c44862..d80e50bc40 100644 --- a/gr-blocks/python/blocks/qa_affinity.py +++ b/gr-blocks/python/blocks/qa_affinity.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_affinity(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_argmax.py b/gr-blocks/python/blocks/qa_argmax.py index fead481c0f..9dea186fea 100644 --- a/gr-blocks/python/blocks/qa_argmax.py +++ b/gr-blocks/python/blocks/qa_argmax.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import math diff --git a/gr-blocks/python/blocks/qa_bin_statistics.py b/gr-blocks/python/blocks/qa_bin_statistics.py index 52b8585721..e6bdfaca5b 100755..100644 --- a/gr-blocks/python/blocks/qa_bin_statistics.py +++ b/gr-blocks/python/blocks/qa_bin_statistics.py @@ -20,17 +20,21 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, blocks - -import random -import struct - """ Note: There has been an issue with this block in the past, see Issue #199. This test is being enabled only on the 'next' branch for version v3.7 for now. TWR """ +from __future__ import print_function + +import struct + +import six + +from gnuradio import gr, gr_unittest, blocks + + class counter(gr.feval_dd): def __init__(self, step_size=1): gr.feval_dd.__init__(self) @@ -57,8 +61,8 @@ class counter3(gr.feval_dd): t = self.count self.count = self.count + self.step_size self.f(self.count) - except Exception, e: - print "Exception: ", e + except Exception as e: + print("Exception: ", e) return t def foobar3(new_t): @@ -79,8 +83,8 @@ class counter4(gr.feval_dd): t = self.count self.count = self.count + self.step_size self.obj_instance.foobar4(self.count) - except Exception, e: - print "Exception: ", e + except Exception as e: + print("Exception: ", e) return t @@ -89,7 +93,8 @@ class parse_msg(object): self.center_freq = msg.arg1() self.vlen = int(msg.arg2()) assert(msg.length() == self.vlen * gr.sizeof_float) - self.data = struct.unpack('%df' % (self.vlen,), msg.to_string()) + self.data = struct.unpack(b'%df' % self.vlen, six.b(msg.to_string())) + class test_bin_statistics(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_block_behavior.py b/gr-blocks/python/blocks/qa_block_behavior.py index a21e423b21..482e88a316 100644 --- a/gr-blocks/python/blocks/qa_block_behavior.py +++ b/gr-blocks/python/blocks/qa_block_behavior.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_block_behavior(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_block_gateway.py b/gr-blocks/python/blocks/qa_block_gateway.py index 1e848cff04..d4794179bd 100644 --- a/gr-blocks/python/blocks/qa_block_gateway.py +++ b/gr-blocks/python/blocks/qa_block_gateway.py @@ -1,3 +1,5 @@ +from __future__ import division + # # Copyright 2011-2013 Free Software Foundation, Inc. # @@ -113,7 +115,7 @@ class tag_source(gr.sync_block): #put code here to fill the output items... #make a new tag on the middle element every time work is called - count = self.nitems_written(0) + num_output_items/2 + count = self.nitems_written(0) + num_output_items // 2 key = pmt.string_to_symbol("example_key") value = pmt.string_to_symbol("example_value") self.add_item_tag(0, count, key, value) @@ -187,8 +189,8 @@ class vector_to_stream(gr.interp_block): def work(self, input_items, output_items): n = 0 - for i in xrange(len(input_items[0])): - for j in xrange(self.block_size): + for i in range(len(input_items[0])): + for j in range(self.block_size): output_items[0][n] = input_items[0][i][j] n += 1 diff --git a/gr-blocks/python/blocks/qa_boolean_operators.py b/gr-blocks/python/blocks/qa_boolean_operators.py index cbcd5688a1..e364aaaa04 100755..100644 --- a/gr-blocks/python/blocks/qa_boolean_operators.py +++ b/gr-blocks/python/blocks/qa_boolean_operators.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_boolean_operators (gr_unittest.TestCase): @@ -31,7 +32,7 @@ class test_boolean_operators (gr_unittest.TestCase): self.tb = None def help_ss (self, src_data, exp_data, op): - for s in zip (range (len (src_data)), src_data): + for s in zip (list(range(len (src_data))), src_data): src = blocks.vector_source_s (s[1]) self.tb.connect (src, (op, s[0])) dst = blocks.vector_sink_s () @@ -41,7 +42,7 @@ class test_boolean_operators (gr_unittest.TestCase): self.assertEqual (exp_data, result_data) def help_bb (self, src_data, exp_data, op): - for s in zip (range (len (src_data)), src_data): + for s in zip (list(range(len (src_data))), src_data): src = blocks.vector_source_b (s[1]) self.tb.connect (src, (op, s[0])) dst = blocks.vector_sink_b () @@ -51,7 +52,7 @@ class test_boolean_operators (gr_unittest.TestCase): self.assertEqual (exp_data, result_data) def help_ii (self, src_data, exp_data, op): - for s in zip (range (len (src_data)), src_data): + for s in zip (list(range(len (src_data))), src_data): src = blocks.vector_source_i (s[1]) self.tb.connect (src, (op, s[0])) dst = blocks.vector_sink_i () diff --git a/gr-blocks/python/blocks/qa_burst_tagger.py b/gr-blocks/python/blocks/qa_burst_tagger.py index b1a4f942f1..a2b7b402ec 100644 --- a/gr-blocks/python/blocks/qa_burst_tagger.py +++ b/gr-blocks/python/blocks/qa_burst_tagger.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import pmt diff --git a/gr-blocks/python/blocks/qa_conjugate.py b/gr-blocks/python/blocks/qa_conjugate.py index 36172e30a0..d672c453c5 100644 --- a/gr-blocks/python/blocks/qa_conjugate.py +++ b/gr-blocks/python/blocks/qa_conjugate.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_conjugate (gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_copy.py b/gr-blocks/python/blocks/qa_copy.py index 20914b51e3..c832c0ef04 100755..100644 --- a/gr-blocks/python/blocks/qa_copy.py +++ b/gr-blocks/python/blocks/qa_copy.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_copy(gr_unittest.TestCase): @@ -46,7 +47,7 @@ class test_copy(gr_unittest.TestCase): expected_result = () src = blocks.vector_source_b(src_data) op = blocks.copy(gr.sizeof_char) - op.set_enabled(False) + op.set_enabled(False) dst = blocks.vector_sink_b() self.tb.connect(src, op, dst) self.tb.run() diff --git a/gr-blocks/python/blocks/qa_cpp_py_binding.py b/gr-blocks/python/blocks/qa_cpp_py_binding.py index 23a5c9b826..f15bfddb29 100644 --- a/gr-blocks/python/blocks/qa_cpp_py_binding.py +++ b/gr-blocks/python/blocks/qa_cpp_py_binding.py @@ -24,6 +24,7 @@ # This program tests mixed python and c++ ctrlport exports in a single app # + import sys, time, random, numpy, re from gnuradio import gr, gr_unittest, blocks @@ -37,7 +38,7 @@ def get1(): def get2(): return "failure" -class inc_class: +class inc_class(object): def __init__(self): self.val = 1 def pp(self): @@ -131,7 +132,7 @@ class test_cpp_py_binding(gr_unittest.TestCase): self.assertComplexTuplesAlmostEqual(val, rval, 5) def test_002(self): - data = range(1,9) + data = list(range(1,9)) self.src = blocks.vector_source_c(data) self.p1 = blocks.ctrlport_probe_c("aaa","C++ exported variable") @@ -163,7 +164,7 @@ class test_cpp_py_binding(gr_unittest.TestCase): # Get all exported knobs ret = radio.getKnobs([probe_name + "::bbb"]) - for name in ret.keys(): + for name in list(ret.keys()): result = ret[name].value self.assertEqual(result, expected_result) diff --git a/gr-blocks/python/blocks/qa_cpp_py_binding_set.py b/gr-blocks/python/blocks/qa_cpp_py_binding_set.py index 5b81de08f9..641f588faf 100644 --- a/gr-blocks/python/blocks/qa_cpp_py_binding_set.py +++ b/gr-blocks/python/blocks/qa_cpp_py_binding_set.py @@ -24,6 +24,7 @@ # This program tests mixed python and c++ GRCP sets in a single app # + import sys, time, random, numpy, re from gnuradio import gr, gr_unittest, blocks @@ -31,7 +32,7 @@ from gnuradio.ctrlport import GNURadio from gnuradio import ctrlport import os -class inc_class: +class inc_class(object): def __init__(self,val): self.val = val; @@ -108,7 +109,7 @@ class test_cpp_py_binding_set(gr_unittest.TestCase): def test_002(self): - data = range(1, 10) + data = list(range(1, 10)) self.src = blocks.vector_source_c(data, True) self.p = blocks.nop(gr.sizeof_gr_complex) diff --git a/gr-blocks/python/blocks/qa_ctrlport_probes.py b/gr-blocks/python/blocks/qa_ctrlport_probes.py index c678846df0..d373bb9fff 100644 --- a/gr-blocks/python/blocks/qa_ctrlport_probes.py +++ b/gr-blocks/python/blocks/qa_ctrlport_probes.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import sys, time, random, numpy from gnuradio import gr, gr_unittest, blocks import os, struct, re @@ -36,7 +37,7 @@ class test_ctrlport_probes(gr_unittest.TestCase): self.tb = None def test_001(self): - data = range(1,9) + data = list(range(1,9)) self.src = blocks.vector_source_c(data, True) self.probe = blocks.ctrlport_probe2_c("samples","Complex", @@ -68,7 +69,7 @@ class test_ctrlport_probes(gr_unittest.TestCase): # Get all exported knobs ret = radio.getKnobs([probe_name + "::samples"]) - for name in ret.keys(): + for name in list(ret.keys()): # Get data in probe, which might be offset; find the # beginning and unwrap. result = ret[name].value @@ -81,7 +82,7 @@ class test_ctrlport_probes(gr_unittest.TestCase): def test_002(self): - data = range(1,9) + data = list(range(1,9)) self.src = blocks.vector_source_f(data, True) self.probe = blocks.ctrlport_probe2_f("samples","Floats", @@ -109,7 +110,7 @@ class test_ctrlport_probes(gr_unittest.TestCase): # Get all exported knobs ret = radio.getKnobs([probe_name + "::samples"]) - for name in ret.keys(): + for name in list(ret.keys()): # Get data in probe, which might be offset; find the # beginning and unwrap. result = ret[name].value @@ -121,7 +122,7 @@ class test_ctrlport_probes(gr_unittest.TestCase): self.tb.wait() def test_003(self): - data = range(1,9) + data = list(range(1,9)) self.src = blocks.vector_source_i(data, True) self.probe = blocks.ctrlport_probe2_i("samples","Integers", @@ -149,7 +150,7 @@ class test_ctrlport_probes(gr_unittest.TestCase): # Get all exported knobs ret = radio.getKnobs([probe_name + "::samples"]) - for name in ret.keys(): + for name in list(ret.keys()): # Get data in probe, which might be offset; find the # beginning and unwrap. result = ret[name].value @@ -162,7 +163,7 @@ class test_ctrlport_probes(gr_unittest.TestCase): def test_004(self): - data = range(1,9) + data = list(range(1,9)) self.src = blocks.vector_source_s(data, True) self.probe = blocks.ctrlport_probe2_s("samples","Shorts", @@ -190,7 +191,7 @@ class test_ctrlport_probes(gr_unittest.TestCase): # Get all exported knobs ret = radio.getKnobs([probe_name + "::samples"]) - for name in ret.keys(): + for name in list(ret.keys()): # Get data in probe, which might be offset; find the # beginning and unwrap. result = ret[name].value @@ -202,7 +203,7 @@ class test_ctrlport_probes(gr_unittest.TestCase): self.tb.wait() def test_005(self): - data = range(1,9) + data = list(range(1,9)) self.src = blocks.vector_source_b(data, True) self.probe = blocks.ctrlport_probe2_b("samples","Bytes", @@ -230,7 +231,7 @@ class test_ctrlport_probes(gr_unittest.TestCase): # Get all exported knobs ret = radio.getKnobs([probe_name + "::samples"]) - for name in ret.keys(): + for name in list(ret.keys()): # Get data in probe, which might be offset; find the # beginning and unwrap. result = ret[name].value diff --git a/gr-blocks/python/blocks/qa_delay.py b/gr-blocks/python/blocks/qa_delay.py index 09200862bd..2fd3691424 100755..100644 --- a/gr-blocks/python/blocks/qa_delay.py +++ b/gr-blocks/python/blocks/qa_delay.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import pmt diff --git a/gr-blocks/python/blocks/qa_endian_swap.py b/gr-blocks/python/blocks/qa_endian_swap.py index dd6ee349b2..3e1e059608 100644 --- a/gr-blocks/python/blocks/qa_endian_swap.py +++ b/gr-blocks/python/blocks/qa_endian_swap.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import ctypes diff --git a/gr-blocks/python/blocks/qa_file_metadata.py b/gr-blocks/python/blocks/qa_file_metadata.py index 886207f108..16c1a8916f 100644 --- a/gr-blocks/python/blocks/qa_file_metadata.py +++ b/gr-blocks/python/blocks/qa_file_metadata.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import +from __future__ import division + import os, math from gnuradio import gr, gr_unittest, blocks @@ -28,9 +31,9 @@ import pmt import parse_file_metadata def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: amp*math.cos(2.*math.pi*freq*x) + \ - 1j*amp*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [amp*math.cos(2.*math.pi*freq*x) + \ + 1j*amp*math.sin(2.*math.pi*freq*x) for x in t] return y class test_file_metadata(gr_unittest.TestCase): @@ -44,7 +47,7 @@ class test_file_metadata(gr_unittest.TestCase): def test_001(self): N = 1000 - outfile = "test_out.dat" + outfile = "test_out.dat" detached = False samp_rate = 200000 @@ -62,8 +65,8 @@ class test_file_metadata(gr_unittest.TestCase): 1000000, extras_str, detached) fsnk.set_unbuffered(True) - self.tb.connect(src, fsnk) - self.tb.run() + self.tb.connect(src, fsnk) + self.tb.run() fsnk.close() handle = open(outfile, "rb") @@ -119,12 +122,12 @@ class test_file_metadata(gr_unittest.TestCase): # Test that the data portion was extracted and received correctly. self.assertComplexTuplesAlmostEqual(vsnk.data(), ssnk.data(), 5) - os.remove(outfile) + os.remove(outfile) def test_002(self): N = 1000 - outfile = "test_out.dat" - outfile_hdr = "test_out.dat.hdr" + outfile = "test_out.dat" + outfile_hdr = "test_out.dat.hdr" detached = True samp_rate = 200000 @@ -142,8 +145,8 @@ class test_file_metadata(gr_unittest.TestCase): 1000000, extras_str, detached) fsnk.set_unbuffered(True) - self.tb.connect(src, fsnk) - self.tb.run() + self.tb.connect(src, fsnk) + self.tb.run() fsnk.close() # Open detached header for reading @@ -201,8 +204,8 @@ class test_file_metadata(gr_unittest.TestCase): # Test that the data portion was extracted and received correctly. self.assertComplexTuplesAlmostEqual(vsnk.data(), ssnk.data(), 5) - os.remove(outfile) - os.remove(outfile_hdr) + os.remove(outfile) + os.remove(outfile_hdr) if __name__ == '__main__': gr_unittest.run(test_file_metadata, "test_file_metadata.xml") diff --git a/gr-blocks/python/blocks/qa_file_source_sink.py b/gr-blocks/python/blocks/qa_file_source_sink.py index da1a07b347..30c7708a3c 100644 --- a/gr-blocks/python/blocks/qa_file_source_sink.py +++ b/gr-blocks/python/blocks/qa_file_source_sink.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import os import tempfile @@ -34,8 +35,8 @@ class test_file_source_sink(gr_unittest.TestCase): self.tb = None def test_001(self): - src_data = range(1000) - expected_result = range(1000) + src_data = list(range(1000)) + expected_result = list(range(1000)) snk2 = blocks.vector_sink_f() @@ -57,8 +58,8 @@ class test_file_source_sink(gr_unittest.TestCase): self.assertFloatTuplesAlmostEqual(expected_result, result_data) def test_descriptor_001(self): - src_data = range(1000) - expected_result = range(1000) + src_data = list(range(1000)) + expected_result = list(range(1000)) snk2 = blocks.vector_sink_f() @@ -88,7 +89,7 @@ class test_file_source_sink(gr_unittest.TestCase): self.assertFloatTuplesAlmostEqual(expected_result, result_data) def test_file_source_can_seek_after_open(self): - src_data = range(1000) + src_data = list(range(1000)) with tempfile.NamedTemporaryFile() as temp: src = blocks.vector_source_f(src_data) diff --git a/gr-blocks/python/blocks/qa_head.py b/gr-blocks/python/blocks/qa_head.py index 9b5bca221b..b6167f9379 100755..100644 --- a/gr-blocks/python/blocks/qa_head.py +++ b/gr-blocks/python/blocks/qa_head.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_head(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_hier_block2.py b/gr-blocks/python/blocks/qa_hier_block2.py index 3e780806bc..20c6a7c180 100755..100644 --- a/gr-blocks/python/blocks/qa_hier_block2.py +++ b/gr-blocks/python/blocks/qa_hier_block2.py @@ -1,10 +1,13 @@ #!/usr/bin/env python -from gnuradio import gr, gr_unittest, blocks -import numpy import threading import time +import numpy + +from gnuradio import gr, gr_unittest, blocks + + class add_ff(gr.sync_block): def __init__(self): gr.sync_block.__init__( @@ -29,88 +32,88 @@ class multiply_const_ff(gr.sync_block): self.k = k def work(self, input_items, output_items): - output_items[0][:] = map(lambda x: self.k*x, input_items[0]) + output_items[0][:] = [self.k*x for x in input_items[0]] return len(output_items[0]) class test_hier_block2(gr_unittest.TestCase): def setUp(self): - pass + pass def tearDown(self): - pass + pass def test_001_make(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - self.assertEqual("test_block", hblock.name()) - self.assertEqual(1, hblock.input_signature().max_streams()) - self.assertEqual(1, hblock.output_signature().min_streams()) - self.assertEqual(1, hblock.output_signature().max_streams()) - self.assertEqual(gr.sizeof_int, hblock.output_signature().sizeof_stream_item(0)) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + self.assertEqual("test_block", hblock.name()) + self.assertEqual(1, hblock.input_signature().max_streams()) + self.assertEqual(1, hblock.output_signature().min_streams()) + self.assertEqual(1, hblock.output_signature().max_streams()) + self.assertEqual(gr.sizeof_int, hblock.output_signature().sizeof_stream_item(0)) def test_002_connect_input(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - hblock.connect(hblock, nop1) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) def test_004_connect_output(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - hblock.connect(nop1, hblock) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) def test_005_connect_output_in_use(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - nop2 = blocks.nop(gr.sizeof_int) - hblock.connect(nop1, hblock) - self.assertRaises(ValueError, - lambda: hblock.connect(nop2, hblock)) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + nop2 = blocks.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) + self.assertRaises(ValueError, + lambda: hblock.connect(nop2, hblock)) def test_006_connect_invalid_src_port_neg(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - self.assertRaises(ValueError, - lambda: hblock.connect((hblock, -1), nop1)) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + self.assertRaises(ValueError, + lambda: hblock.connect((hblock, -1), nop1)) def test_005_connect_invalid_src_port_exceeds(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - self.assertRaises(ValueError, - lambda: hblock.connect((hblock, 1), nop1)) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + self.assertRaises(ValueError, + lambda: hblock.connect((hblock, 1), nop1)) def test_007_connect_invalid_dst_port_neg(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - nop2 = blocks.nop(gr.sizeof_int) - self.assertRaises(ValueError, - lambda: hblock.connect(nop1, (nop2, -1))) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + nop2 = blocks.nop(gr.sizeof_int) + self.assertRaises(ValueError, + lambda: hblock.connect(nop1, (nop2, -1))) def test_008_connect_invalid_dst_port_exceeds(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.null_sink(gr.sizeof_int) - nop2 = blocks.null_sink(gr.sizeof_int) - self.assertRaises(ValueError, - lambda: hblock.connect(nop1, (nop2, 1))) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.null_sink(gr.sizeof_int) + nop2 = blocks.null_sink(gr.sizeof_int) + self.assertRaises(ValueError, + lambda: hblock.connect(nop1, (nop2, 1))) def test_009_check_topology(self): - hblock = gr.top_block("test_block") - hblock.check_topology(0, 0) + hblock = gr.top_block("test_block") + hblock.check_topology(0, 0) def test_010_run(self): expected = (1.0, 2.0, 3.0, 4.0) @@ -123,89 +126,89 @@ class test_hier_block2(gr_unittest.TestCase): hblock.run() actual1 = sink1.data() actual2 = sink2.data() - self.assertEquals(expected, actual1) - self.assertEquals(expected, actual2) + self.assertEqual(expected, actual1) + self.assertEqual(expected, actual2) def test_012_disconnect_input(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - hblock.connect(hblock, nop1) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) hblock.disconnect(hblock, nop1) def test_013_disconnect_input_not_connected(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) nop2 = blocks.nop(gr.sizeof_int) - hblock.connect(hblock, nop1) + hblock.connect(hblock, nop1) self.assertRaises(ValueError, lambda: hblock.disconnect(hblock, nop2)) def test_014_disconnect_input_neg(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - hblock.connect(hblock, nop1) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) self.assertRaises(ValueError, lambda: hblock.disconnect((hblock, -1), nop1)) def test_015_disconnect_input_exceeds(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - hblock.connect(hblock, nop1) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) self.assertRaises(ValueError, lambda: hblock.disconnect((hblock, 1), nop1)) def test_016_disconnect_output(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - hblock.connect(nop1, hblock) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) hblock.disconnect(nop1, hblock) def test_017_disconnect_output_not_connected(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) nop2 = blocks.nop(gr.sizeof_int) - hblock.connect(nop1, hblock) + hblock.connect(nop1, hblock) self.assertRaises(ValueError, lambda: hblock.disconnect(nop2, hblock)) def test_018_disconnect_output_neg(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - hblock.connect(hblock, nop1) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) self.assertRaises(ValueError, lambda: hblock.disconnect(nop1, (hblock, -1))) def test_019_disconnect_output_exceeds(self): - hblock = gr.hier_block2("test_block", - gr.io_signature(1,1,gr.sizeof_int), - gr.io_signature(1,1,gr.sizeof_int)) - nop1 = blocks.nop(gr.sizeof_int) - hblock.connect(nop1, hblock) + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = blocks.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) self.assertRaises(ValueError, lambda: hblock.disconnect(nop1, (hblock, 1))) def test_020_run(self): - hblock = gr.top_block("test_block") - data = (1.0, 2.0, 3.0, 4.0) - src = blocks.vector_source_f(data, False) - dst = blocks.vector_sink_f() - hblock.connect(src, dst) - hblock.run() - self.assertEquals(data, dst.data()) + hblock = gr.top_block("test_block") + data = (1.0, 2.0, 3.0, 4.0) + src = blocks.vector_source_f(data, False) + dst = blocks.vector_sink_f() + hblock.connect(src, dst) + hblock.run() + self.assertEqual(data, dst.data()) def test_021_connect_single(self): hblock = gr.top_block("test_block") @@ -258,7 +261,7 @@ class test_hier_block2(gr_unittest.TestCase): hb.connect(src, dst) tb.connect(hb) tb.run() - self.assertEquals(expected_data, dst.data()) + self.assertEqual(expected_data, dst.data()) def test_027a_internally_unconnected_input(self): tb = gr.top_block() @@ -333,7 +336,7 @@ class test_hier_block2(gr_unittest.TestCase): tb.disconnect(src) # Singleton disconnect tb.connect(src, dst) tb.run() - self.assertEquals(dst.data(), (1,)) + self.assertEqual(dst.data(), (1,)) def test_030_nested_input(self): tb = gr.top_block() @@ -349,7 +352,7 @@ class test_hier_block2(gr_unittest.TestCase): hb1.connect(hb1, hb2) hb2.connect(hb2, blocks.copy(gr.sizeof_char), dst) tb.run() - self.assertEquals(dst.data(), (1,)) + self.assertEqual(dst.data(), (1,)) def test_031_multiple_internal_inputs(self): tb = gr.top_block() @@ -368,7 +371,7 @@ class test_hier_block2(gr_unittest.TestCase): dst = blocks.vector_sink_f() tb.connect(src, hb, dst) tb.run() - self.assertEquals(dst.data(), (3.0,)) + self.assertEqual(dst.data(), (3.0,)) def test_032_nested_multiple_internal_inputs(self): tb = gr.top_block() @@ -392,7 +395,7 @@ class test_hier_block2(gr_unittest.TestCase): dst = blocks.vector_sink_f() tb.connect(src, hb, dst) tb.run() - self.assertEquals(dst.data(), (3.0,)) + self.assertEqual(dst.data(), (3.0,)) def test_033a_set_affinity(self): @@ -404,7 +407,7 @@ class test_hier_block2(gr_unittest.TestCase): hblock.set_processor_affinity([0,]) hblock.run() actual = snk.data() - self.assertEquals(expected, actual) + self.assertEqual(expected, actual) def test_033b_unset_affinity(self): expected = (1.0, 2.0, 3.0, 4.0) @@ -416,7 +419,7 @@ class test_hier_block2(gr_unittest.TestCase): hblock.unset_processor_affinity() hblock.run() actual = snk.data() - self.assertEquals(expected, actual) + self.assertEqual(expected, actual) def test_033c_get_affinity(self): expected = (1.0, 2.0, 3.0, 4.0) @@ -426,7 +429,7 @@ class test_hier_block2(gr_unittest.TestCase): hblock.connect(src, snk) hblock.set_processor_affinity([0,]) procs = hblock.processor_affinity() - self.assertEquals((0,), procs) + self.assertEqual((0,), procs) def test_34a_lock_unlock(self): hblock = gr.top_block("test_block") diff --git a/gr-blocks/python/blocks/qa_hier_block2_message_connections.py b/gr-blocks/python/blocks/qa_hier_block2_message_connections.py index 4283f537e8..e66a0dbdc8 100644 --- a/gr-blocks/python/blocks/qa_hier_block2_message_connections.py +++ b/gr-blocks/python/blocks/qa_hier_block2_message_connections.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import weakref from gnuradio import blocks, gr, gr_unittest diff --git a/gr-blocks/python/blocks/qa_integrate.py b/gr-blocks/python/blocks/qa_integrate.py index be4285ce95..4ecfbb5171 100755..100644 --- a/gr-blocks/python/blocks/qa_integrate.py +++ b/gr-blocks/python/blocks/qa_integrate.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_integrate (gr_unittest.TestCase): @@ -31,66 +32,66 @@ class test_integrate (gr_unittest.TestCase): self.tb = None def test_000_ss(self): - src_data = (1, 2, 3, 4, 5, 6) - dst_data = (6, 15) - src = blocks.vector_source_s(src_data) - itg = blocks.integrate_ss(3) - dst = blocks.vector_sink_s() - self.tb.connect(src, itg, dst) - self.tb.run() - self.assertEqual(dst_data, dst.data()) + src_data = (1, 2, 3, 4, 5, 6) + dst_data = (6, 15) + src = blocks.vector_source_s(src_data) + itg = blocks.integrate_ss(3) + dst = blocks.vector_sink_s() + self.tb.connect(src, itg, dst) + self.tb.run() + self.assertEqual(dst_data, dst.data()) def test_001_ii(self): - src_data = (1, 2, 3, 4, 5, 6) - dst_data = (6, 15) - src = blocks.vector_source_i(src_data) - itg = blocks.integrate_ii(3) - dst = blocks.vector_sink_i() - self.tb.connect(src, itg, dst) - self.tb.run() - self.assertEqual(dst_data, dst.data()) + src_data = (1, 2, 3, 4, 5, 6) + dst_data = (6, 15) + src = blocks.vector_source_i(src_data) + itg = blocks.integrate_ii(3) + dst = blocks.vector_sink_i() + self.tb.connect(src, itg, dst) + self.tb.run() + self.assertEqual(dst_data, dst.data()) def test_002_ff(self): - src_data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] - dst_data = [6.0, 15.0] - src = blocks.vector_source_f(src_data) - itg = blocks.integrate_ff(3) - dst = blocks.vector_sink_f() - self.tb.connect(src, itg, dst) - self.tb.run() - self.assertFloatTuplesAlmostEqual(dst_data, dst.data(), 6) + src_data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] + dst_data = [6.0, 15.0] + src = blocks.vector_source_f(src_data) + itg = blocks.integrate_ff(3) + dst = blocks.vector_sink_f() + self.tb.connect(src, itg, dst) + self.tb.run() + self.assertFloatTuplesAlmostEqual(dst_data, dst.data(), 6) def test_003_cc(self): - src_data = [1.0+1.0j, 2.0+2.0j, 3.0+3.0j, 4.0+4.0j, 5.0+5.0j, 6.0+6.0j] - dst_data = [6.0+6.0j, 15.0+15.0j] - src = blocks.vector_source_c(src_data) - itg = blocks.integrate_cc(3) - dst = blocks.vector_sink_c() - self.tb.connect(src, itg, dst) - self.tb.run() - self.assertComplexTuplesAlmostEqual(dst_data, dst.data(), 6) + src_data = [1.0+1.0j, 2.0+2.0j, 3.0+3.0j, 4.0+4.0j, 5.0+5.0j, 6.0+6.0j] + dst_data = [6.0+6.0j, 15.0+15.0j] + src = blocks.vector_source_c(src_data) + itg = blocks.integrate_cc(3) + dst = blocks.vector_sink_c() + self.tb.connect(src, itg, dst) + self.tb.run() + self.assertComplexTuplesAlmostEqual(dst_data, dst.data(), 6) def test_004_ss_vec(self): - src_data = (1, 2, 3, 4, 5, 6) - dst_data = (9, 12) - vlen = 2 - src = blocks.vector_source_s(src_data, False, vlen) - itg = blocks.integrate_ss(3, vlen) - dst = blocks.vector_sink_s(vlen) - self.tb.connect(src, itg, dst) - self.tb.run() - self.assertEqual(dst_data, dst.data()) + src_data = (1, 2, 3, 4, 5, 6) + dst_data = (9, 12) + vlen = 2 + src = blocks.vector_source_s(src_data, False, vlen) + itg = blocks.integrate_ss(3, vlen) + dst = blocks.vector_sink_s(vlen) + self.tb.connect(src, itg, dst) + self.tb.run() + self.assertEqual(dst_data, dst.data()) def test_003_cc_vec(self): - src_data = [1.0+1.0j, 2.0+2.0j, 3.0+3.0j, 4.0+4.0j, 5.0+5.0j, 6.0+6.0j] - dst_data = [9.0+9.0j, 12.0+12.0j] - vlen = 2 - src = blocks.vector_source_c(src_data, False, vlen) - itg = blocks.integrate_cc(3, vlen) - dst = blocks.vector_sink_c(vlen) - self.tb.connect(src, itg, dst) - self.tb.run() - self.assertComplexTuplesAlmostEqual(dst_data, dst.data(), 6) + src_data = [1.0+1.0j, 2.0+2.0j, 3.0+3.0j, 4.0+4.0j, 5.0+5.0j, 6.0+6.0j] + dst_data = [9.0+9.0j, 12.0+12.0j] + vlen = 2 + src = blocks.vector_source_c(src_data, False, vlen) + itg = blocks.integrate_cc(3, vlen) + dst = blocks.vector_sink_c(vlen) + self.tb.connect(src, itg, dst) + self.tb.run() + self.assertComplexTuplesAlmostEqual(dst_data, dst.data(), 6) if __name__ == '__main__': gr_unittest.run(test_integrate, "test_integrate.xml") diff --git a/gr-blocks/python/blocks/qa_interleave.py b/gr-blocks/python/blocks/qa_interleave.py index 526e4a4e6f..9d334a465f 100755..100644 --- a/gr-blocks/python/blocks/qa_interleave.py +++ b/gr-blocks/python/blocks/qa_interleave.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, blocks class test_interleave (gr_unittest.TestCase): @@ -32,10 +34,10 @@ class test_interleave (gr_unittest.TestCase): def test_int_001 (self): lenx = 64 - src0 = blocks.vector_source_f (range (0, lenx, 4)) - src1 = blocks.vector_source_f (range (1, lenx, 4)) - src2 = blocks.vector_source_f (range (2, lenx, 4)) - src3 = blocks.vector_source_f (range (3, lenx, 4)) + src0 = blocks.vector_source_f (list(range(0, lenx, 4))) + src1 = blocks.vector_source_f (list(range(1, lenx, 4))) + src2 = blocks.vector_source_f (list(range(2, lenx, 4))) + src3 = blocks.vector_source_f (list(range(3, lenx, 4))) op = blocks.interleave (gr.sizeof_float) dst = blocks.vector_sink_f () @@ -54,13 +56,13 @@ class test_interleave (gr_unittest.TestCase): lenx = 64 plusup_big = lambda a: a + (blksize * 4) plusup_little = lambda a: a + blksize - a_vec = range(0,blksize) - for i in range(0,(lenx/(4 * blksize)) - 1): - a_vec += map(plusup_big, a_vec[len(a_vec) - blksize:]) + a_vec = list(range(0,blksize)) + for i in range(0,(lenx // (4 * blksize)) - 1): + a_vec += list(map(plusup_big, a_vec[len(a_vec) - blksize:])) - b_vec = map(plusup_little, a_vec) - c_vec = map(plusup_little, b_vec) - d_vec = map(plusup_little, c_vec) + b_vec = list(map(plusup_little, a_vec)) + c_vec = list(map(plusup_little, b_vec)) + d_vec = list(map(plusup_little, c_vec)) src0 = blocks.vector_source_f (a_vec) src1 = blocks.vector_source_f (b_vec) @@ -82,7 +84,7 @@ class test_interleave (gr_unittest.TestCase): def test_deint_001 (self): lenx = 64 - src = blocks.vector_source_f (range (lenx)) + src = blocks.vector_source_f (list(range(lenx))) op = blocks.deinterleave (gr.sizeof_float) dst0 = blocks.vector_sink_f () dst1 = blocks.vector_sink_f () @@ -109,7 +111,7 @@ class test_interleave (gr_unittest.TestCase): def test_deint_002 (self): blksize = 4 lenx = 64 - src = blocks.vector_source_f (range (lenx)) + src = blocks.vector_source_f (list(range(lenx))) op = blocks.deinterleave (gr.sizeof_float, blksize) dst0 = blocks.vector_sink_f () dst1 = blocks.vector_sink_f () @@ -125,13 +127,13 @@ class test_interleave (gr_unittest.TestCase): plusup_big = lambda a: a + (blksize * 4) plusup_little = lambda a: a + blksize - a_vec = range(0,blksize) - for i in range(0,(lenx/(4 * blksize)) - 1): - a_vec += map(plusup_big, a_vec[len(a_vec) - blksize:]) + a_vec = list(range(0,blksize)) + for i in range(0,(lenx // (4 * blksize)) - 1): + a_vec += list(map(plusup_big, a_vec[len(a_vec) - blksize:])) - b_vec = map(plusup_little, a_vec) - c_vec = map(plusup_little, b_vec) - d_vec = map(plusup_little, c_vec) + b_vec = list(map(plusup_little, a_vec)) + c_vec = list(map(plusup_little, b_vec)) + d_vec = list(map(plusup_little, c_vec)) expected_result0 = tuple (a_vec) expected_result1 = tuple (b_vec) diff --git a/gr-blocks/python/blocks/qa_keep_m_in_n.py b/gr-blocks/python/blocks/qa_keep_m_in_n.py index 4db48335b2..30a15d9ded 100755..100644 --- a/gr-blocks/python/blocks/qa_keep_m_in_n.py +++ b/gr-blocks/python/blocks/qa_keep_m_in_n.py @@ -19,6 +19,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # + from gnuradio import gr, gr_unittest, blocks import sys @@ -27,15 +28,15 @@ import random class test_keep_m_in_n(gr_unittest.TestCase): def setUp(self): - pass + pass def tearDown(self): - pass + pass def test_001(self): self.maxDiff = None; tb = gr.top_block() - src = blocks.vector_source_b( range(0,100) ) + src = blocks.vector_source_b( list(range(0,100)) ) # itemsize, M, N, offset km2 = blocks.keep_m_in_n( 1, 1, 2, 0 ); @@ -49,11 +50,10 @@ class test_keep_m_in_n(gr_unittest.TestCase): tb.connect(src,km7,snk7); tb.run(); - self.assertEqual(range(0,100,2), list(snk2.data())); - self.assertEqual(range(1,100,3), list(snk3.data())); - self.assertEqual(range(2,100,7), list(snk7.data())); + self.assertEqual(list(range(0,100,2)), list(snk2.data())); + self.assertEqual(list(range(1,100,3)), list(snk3.data())); + self.assertEqual(list(range(2,100,7)), list(snk7.data())); if __name__ == '__main__': gr_unittest.run(test_keep_m_in_n, "test_keep_m_in_n.xml") - diff --git a/gr-blocks/python/blocks/qa_keep_one_in_n.py b/gr-blocks/python/blocks/qa_keep_one_in_n.py index d8251fe611..fd7c122c62 100755..100644 --- a/gr-blocks/python/blocks/qa_keep_one_in_n.py +++ b/gr-blocks/python/blocks/qa_keep_one_in_n.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_keep_one_in_n(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_logger.py b/gr-blocks/python/blocks/qa_logger.py index d2b6b3ee5e..bdcd24cf0e 100644 --- a/gr-blocks/python/blocks/qa_logger.py +++ b/gr-blocks/python/blocks/qa_logger.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_logger (gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_max.py b/gr-blocks/python/blocks/qa_max.py index 709dbee72e..45c2261ded 100755..100644 --- a/gr-blocks/python/blocks/qa_max.py +++ b/gr-blocks/python/blocks/qa_max.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, blocks import math @@ -47,18 +49,18 @@ class test_max(gr_unittest.TestCase): self.assertEqual(expected_result, result_data) def stest_002(self): - src_data=(-100,-99,-98,-97,-96,-1) - expected_result = (float(max(src_data)),) + src_data=(-100,-99,-98,-97,-96,-1) + expected_result = (float(max(src_data)),) - src = blocks.vector_source_f(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_float, len(src_data)) - op = blocks.max_ff(len(src_data)) - dst = blocks.vector_sink_f() + src = blocks.vector_source_f(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_float, len(src_data)) + op = blocks.max_ff(len(src_data)) + dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, op, dst) - self.tb.run() - result_data = dst.data() - self.assertEqual(expected_result, result_data) + self.tb.connect(src, s2v, op, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) def stest_003(self): src_data0 = (0, 2, -3, 0, 12, 0) @@ -85,7 +87,7 @@ class test_max(gr_unittest.TestCase): expected_data = [] tmp = [float(max(x,y)) for x,y in zip(src_data0, src_data1)] - for i in xrange(len(tmp)/dim): + for i in range(len(tmp) / dim): expected_data.append(float(max(tmp[i*dim:(i+1)*dim]))) src0 = blocks.vector_source_f(src_data0) @@ -118,18 +120,18 @@ class test_max(gr_unittest.TestCase): self.assertEqual(expected_result, result_data) def stest_s002(self): - src_data=(-100,-99,-98,-97,-96,-1) - expected_result = (max(src_data),) + src_data=(-100,-99,-98,-97,-96,-1) + expected_result = (max(src_data),) - src = blocks.vector_source_s(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_short, len(src_data)) - op = blocks.max_ss(len(src_data)) - dst = blocks.vector_sink_s() + src = blocks.vector_source_s(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_short, len(src_data)) + op = blocks.max_ss(len(src_data)) + dst = blocks.vector_sink_s() - self.tb.connect(src, s2v, op, dst) - self.tb.run() - result_data = dst.data() - self.assertEqual(expected_result, result_data) + self.tb.connect(src, s2v, op, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) def stest_s003(self): @@ -157,7 +159,7 @@ class test_max(gr_unittest.TestCase): expected_data = [] tmp = [max(x,y) for x,y in zip(src_data0, src_data1)] - for i in xrange(len(tmp)/dim): + for i in range(len(tmp) / dim): expected_data.append(max(tmp[i*dim:(i+1)*dim])) src0 = blocks.vector_source_s(src_data0) diff --git a/gr-blocks/python/blocks/qa_message.py b/gr-blocks/python/blocks/qa_message.py index 1d0380d44c..639001f09a 100755..100644 --- a/gr-blocks/python/blocks/qa_message.py +++ b/gr-blocks/python/blocks/qa_message.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import time from gnuradio import gr, gr_unittest, blocks @@ -95,7 +96,7 @@ class test_message(gr_unittest.TestCase): input_data = (0,1,2,3,4,5,6,7,8,9) src = blocks.vector_source_b(input_data) dst = blocks.vector_sink_b() - tb = gr.top_block() + tb = gr.top_block() tb.connect(src, dst) tb.run() self.assertEquals(input_data, dst.data()) @@ -105,7 +106,7 @@ class test_message(gr_unittest.TestCase): src = blocks.message_strobe(msg, 500) snk = blocks.message_debug() - tb = gr.top_block() + tb = gr.top_block() tb.msg_connect(src, "strobe", snk, "store") tb.start() time.sleep(1) diff --git a/gr-blocks/python/blocks/qa_min.py b/gr-blocks/python/blocks/qa_min.py index 642782a1a1..374c15e319 100644 --- a/gr-blocks/python/blocks/qa_min.py +++ b/gr-blocks/python/blocks/qa_min.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, blocks import math @@ -47,18 +49,18 @@ class test_min(gr_unittest.TestCase): self.assertEqual(expected_result, result_data) def stest_002(self): - src_data=(-100,-99,-98,-97,-96,-1) - expected_result = (float(min(src_data)),) + src_data=(-100,-99,-98,-97,-96,-1) + expected_result = (float(min(src_data)),) - src = blocks.vector_source_f(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_float, len(src_data)) - op = blocks.min_ff(len(src_data)) - dst = blocks.vector_sink_f() + src = blocks.vector_source_f(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_float, len(src_data)) + op = blocks.min_ff(len(src_data)) + dst = blocks.vector_sink_f() - self.tb.connect(src, s2v, op, dst) - self.tb.run() - result_data = dst.data() - self.assertEqual(expected_result, result_data) + self.tb.connect(src, s2v, op, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) def stest_003(self): src_data0 = (0, 2, -3, 0, 12, 0) @@ -85,7 +87,7 @@ class test_min(gr_unittest.TestCase): expected_data = [] tmp = [float(min(x,y)) for x,y in zip(src_data0, src_data1)] - for i in xrange(len(tmp)/dim): + for i in range(len(tmp) / dim): expected_data.append(float(min(tmp[i*dim:(i+1)*dim]))) src0 = blocks.vector_source_f(src_data0) @@ -118,18 +120,18 @@ class test_min(gr_unittest.TestCase): self.assertEqual(expected_result, result_data) def stest_s002(self): - src_data=(-100,-99,-98,-97,-96,-1) - expected_result = (min(src_data),) + src_data=(-100,-99,-98,-97,-96,-1) + expected_result = (min(src_data),) - src = blocks.vector_source_s(src_data) - s2v = blocks.stream_to_vector(gr.sizeof_short, len(src_data)) - op = blocks.min_ss(len(src_data)) - dst = blocks.vector_sink_s() + src = blocks.vector_source_s(src_data) + s2v = blocks.stream_to_vector(gr.sizeof_short, len(src_data)) + op = blocks.min_ss(len(src_data)) + dst = blocks.vector_sink_s() - self.tb.connect(src, s2v, op, dst) - self.tb.run() - result_data = dst.data() - self.assertEqual(expected_result, result_data) + self.tb.connect(src, s2v, op, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) def stest_s003(self): @@ -157,7 +159,7 @@ class test_min(gr_unittest.TestCase): expected_data = [] tmp = [min(x,y) for x,y in zip(src_data0, src_data1)] - for i in xrange(len(tmp)/dim): + for i in range(len(tmp) / dim): expected_data.append(min(tmp[i*dim:(i+1)*dim])) src0 = blocks.vector_source_s(src_data0) diff --git a/gr-blocks/python/blocks/qa_moving_average.py b/gr-blocks/python/blocks/qa_moving_average.py index 2c58805925..513861f007 100644 --- a/gr-blocks/python/blocks/qa_moving_average.py +++ b/gr-blocks/python/blocks/qa_moving_average.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import math, random diff --git a/gr-blocks/python/blocks/qa_multiply_conjugate.py b/gr-blocks/python/blocks/qa_multiply_conjugate.py index c2391f1410..dadea69ba2 100644 --- a/gr-blocks/python/blocks/qa_multiply_conjugate.py +++ b/gr-blocks/python/blocks/qa_multiply_conjugate.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_multiply_conjugate (gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_multiply_matrix_xx.py b/gr-blocks/python/blocks/qa_multiply_matrix_xx.py index feee53d510..eb10535565 100755..100644 --- a/gr-blocks/python/blocks/qa_multiply_matrix_xx.py +++ b/gr-blocks/python/blocks/qa_multiply_matrix_xx.py @@ -21,6 +21,7 @@ # Boston, MA 02110-1301, USA. # + import time import numpy import os @@ -73,7 +74,7 @@ class test_multiply_matrix_xx (gr_unittest.TestCase): self.multiplier.set_A(A2) A = A2 A_matrix = numpy.matrix(A) - for i in xrange(N): + for i in range(N): if tags is None: these_tags = () else: @@ -83,17 +84,17 @@ class test_multiply_matrix_xx (gr_unittest.TestCase): (self.multiplier, i) ) sinks = [] - for i in xrange(M): + for i in range(M): sinks.append(BLOCK_LOOKUP[datatype]['sink']()) self.tb.connect((self.multiplier, i), sinks[i]) # Run and check self.tb.run() - for i in xrange(X_in.shape[1]): + for i in range(X_in.shape[1]): Y_out_exp[:,i] = A_matrix * X_in[:,i] Y_out = [list(x.data()) for x in sinks] if tags is not None: self.the_tags = [] - for i in xrange(M): + for i in range(M): self.the_tags.append(sinks[i].tags()) self.assertEqual(list(Y_out), Y_out_exp.tolist()) diff --git a/gr-blocks/python/blocks/qa_mute.py b/gr-blocks/python/blocks/qa_mute.py index 97ee5bd821..d061954ef8 100755..100644 --- a/gr-blocks/python/blocks/qa_mute.py +++ b/gr-blocks/python/blocks/qa_mute.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_mute(gr_unittest.TestCase): @@ -31,7 +32,7 @@ class test_mute(gr_unittest.TestCase): self.tb = None def help_ii(self, src_data, exp_data, op): - for s in zip(range(len(src_data)), src_data): + for s in zip(list(range(len(src_data))), src_data): src = blocks.vector_source_i(s[1]) self.tb.connect(src, (op, s[0])) dst = blocks.vector_sink_i() @@ -41,7 +42,7 @@ class test_mute(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_ff(self, src_data, exp_data, op): - for s in zip(range(len(src_data)), src_data): + for s in zip(list(range(len(src_data))), src_data): src = blocks.vector_source_f(s[1]) self.tb.connect(src, (op, s[0])) dst = blocks.vector_sink_f() @@ -51,7 +52,7 @@ class test_mute(gr_unittest.TestCase): self.assertEqual(exp_data, result_data) def help_cc(self, src_data, exp_data, op): - for s in zip(range(len(src_data)), src_data): + for s in zip(list(range(len(src_data))), src_data): src = blocks.vector_source_c(s[1]) self.tb.connect(src, (op, s[0])) dst = blocks.vector_sink_c() diff --git a/gr-blocks/python/blocks/qa_nlog10.py b/gr-blocks/python/blocks/qa_nlog10.py index c925479f59..94269c34f0 100755..100644 --- a/gr-blocks/python/blocks/qa_nlog10.py +++ b/gr-blocks/python/blocks/qa_nlog10.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_nlog10(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_null_sink_source.py b/gr-blocks/python/blocks/qa_null_sink_source.py index 03d6ab14c1..8ddd8db6fc 100644 --- a/gr-blocks/python/blocks/qa_null_sink_source.py +++ b/gr-blocks/python/blocks/qa_null_sink_source.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import math diff --git a/gr-blocks/python/blocks/qa_pack_k_bits.py b/gr-blocks/python/blocks/qa_pack_k_bits.py index ab0b638a09..28285845b3 100755..100644 --- a/gr-blocks/python/blocks/qa_pack_k_bits.py +++ b/gr-blocks/python/blocks/qa_pack_k_bits.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import random from gnuradio import gr, gr_unittest, blocks @@ -54,7 +55,7 @@ class test_pack(gr_unittest.TestCase): self.assertEqual(expected_results, dst.data()) def test_003(self): - src_data = expected_results = map(lambda x: random.randint(0,3), range(10)); + src_data = expected_results = [random.randint(0,3) for x in range(10)]; src = blocks.vector_source_b( src_data ); pack = blocks.pack_k_bits_bb(2); unpack = blocks.unpack_k_bits_bb(2); diff --git a/gr-blocks/python/blocks/qa_packed_to_unpacked.py b/gr-blocks/python/blocks/qa_packed_to_unpacked.py index 02dc872490..13e93a7136 100755..100644 --- a/gr-blocks/python/blocks/qa_packed_to_unpacked.py +++ b/gr-blocks/python/blocks/qa_packed_to_unpacked.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import random @@ -139,7 +140,7 @@ class test_packing(gr_unittest.TestCase): def test_009(self): random.seed(0) src_data = [] - for i in xrange(202): + for i in range(202): src_data.append((random.randint(0,255))) src_data = tuple(src_data) expected_results = src_data @@ -158,7 +159,7 @@ class test_packing(gr_unittest.TestCase): def test_010(self): random.seed(0) src_data = [] - for i in xrange(56): + for i in range(56): src_data.append((random.randint(0,255))) src_data = tuple(src_data) expected_results = src_data @@ -176,7 +177,7 @@ class test_packing(gr_unittest.TestCase): def test_011(self): random.seed(0) src_data = [] - for i in xrange(56): + for i in range(56): src_data.append((random.randint(0,255))) src_data = tuple(src_data) expected_results = src_data @@ -196,7 +197,7 @@ class test_packing(gr_unittest.TestCase): def test_100a(self): random.seed(0) src_data = [] - for i in xrange(100): + for i in range(100): src_data.append((random.randint(-2**15,2**15-1))) src_data = tuple(src_data) expected_results = src_data @@ -214,7 +215,7 @@ class test_packing(gr_unittest.TestCase): def test_100b(self): random.seed(0) src_data = [] - for i in xrange(100): + for i in range(100): src_data.append((random.randint(-2**15,2**15-1))) src_data = tuple(src_data) expected_results = src_data @@ -232,7 +233,7 @@ class test_packing(gr_unittest.TestCase): def test_101a(self): random.seed(0) src_data = [] - for i in xrange(100): + for i in range(100): src_data.append((random.randint(-2**15,2**15-1))) src_data = tuple(src_data) expected_results = src_data @@ -250,7 +251,7 @@ class test_packing(gr_unittest.TestCase): def test_101b(self): random.seed(0) src_data = [] - for i in xrange(100): + for i in range(100): src_data.append((random.randint(-2**15,2**15-1))) src_data = tuple(src_data) expected_results = src_data @@ -270,7 +271,7 @@ class test_packing(gr_unittest.TestCase): def test_200a(self): random.seed(0) src_data = [] - for i in xrange(100): + for i in range(100): src_data.append((random.randint(-2**31,2**31-1))) src_data = tuple(src_data) expected_results = src_data @@ -288,7 +289,7 @@ class test_packing(gr_unittest.TestCase): def test_200b(self): random.seed(0) src_data = [] - for i in xrange(100): + for i in range(100): src_data.append((random.randint(-2**31,2**31-1))) src_data = tuple(src_data) expected_results = src_data @@ -306,7 +307,7 @@ class test_packing(gr_unittest.TestCase): def test_201a(self): random.seed(0) src_data = [] - for i in xrange(100): + for i in range(100): src_data.append((random.randint(-2**31,2**31-1))) src_data = tuple(src_data) expected_results = src_data @@ -324,7 +325,7 @@ class test_packing(gr_unittest.TestCase): def test_201b(self): random.seed(0) src_data = [] - for i in xrange(100): + for i in range(100): src_data.append((random.randint(-2**31,2**31-1))) src_data = tuple(src_data) expected_results = src_data diff --git a/gr-blocks/python/blocks/qa_patterned_interleaver.py b/gr-blocks/python/blocks/qa_patterned_interleaver.py index 2d3168db40..300565210e 100755..100644 --- a/gr-blocks/python/blocks/qa_patterned_interleaver.py +++ b/gr-blocks/python/blocks/qa_patterned_interleaver.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import math diff --git a/gr-blocks/python/blocks/qa_pdu.py b/gr-blocks/python/blocks/qa_pdu.py index 79d39df48b..3ee5e576ea 100755..100644 --- a/gr-blocks/python/blocks/qa_pdu.py +++ b/gr-blocks/python/blocks/qa_pdu.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import time from gnuradio import gr, gr_unittest, blocks @@ -79,7 +80,7 @@ class test_pdu(gr_unittest.TestCase): # Convert the PMT vector into a Python list msg_data = [] - for i in xrange(16): + for i in range(16): msg_data.append(pmt.u8vector_ref(msg_vec, i)) actual_data = 16*[0xFF,] @@ -108,7 +109,7 @@ class test_pdu(gr_unittest.TestCase): def test_002_tags_plus_data(self): packet_len = 16 - src_data = range(packet_len) + src_data = list(range(packet_len)) tag1 = gr.tag_t() tag1.offset = 0 tag1.key = pmt.string_to_symbol('spam') diff --git a/gr-blocks/python/blocks/qa_peak_detector.py b/gr-blocks/python/blocks/qa_peak_detector.py index c855e92530..cb253a5db6 100644 --- a/gr-blocks/python/blocks/qa_peak_detector.py +++ b/gr-blocks/python/blocks/qa_peak_detector.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_peak_detector(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_peak_detector2.py b/gr-blocks/python/blocks/qa_peak_detector2.py index d6fd4fe95f..a7de40200e 100644 --- a/gr-blocks/python/blocks/qa_peak_detector2.py +++ b/gr-blocks/python/blocks/qa_peak_detector2.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_peak_detector2(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_pipe_fittings.py b/gr-blocks/python/blocks/qa_pipe_fittings.py index bc29cc750e..b569157582 100755..100644 --- a/gr-blocks/python/blocks/qa_pipe_fittings.py +++ b/gr-blocks/python/blocks/qa_pipe_fittings.py @@ -20,13 +20,14 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks def calc_expected_result(src_data, n): assert (len(src_data) % n) == 0 result = [list() for x in range(n)] #print "len(result) =", len(result) - for i in xrange(len(src_data)): + for i in range(len(src_data)): (result[i % n]).append(src_data[i]) return [tuple(x) for x in result] @@ -45,7 +46,7 @@ class test_pipe_fittings(gr_unittest.TestCase): """ n = 8 src_len = n * 8 - src_data = range(src_len) + src_data = list(range(src_len)) expected_results = calc_expected_result(src_data, n) #print "expected results: ", expected_results diff --git a/gr-blocks/python/blocks/qa_plateau_detector_fb.py b/gr-blocks/python/blocks/qa_plateau_detector_fb.py index 003c4ea74d..6a41a249e9 100755..100644 --- a/gr-blocks/python/blocks/qa_plateau_detector_fb.py +++ b/gr-blocks/python/blocks/qa_plateau_detector_fb.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class qa_plateau_detector_fb (gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_probe_signal.py b/gr-blocks/python/blocks/qa_probe_signal.py index 8194cafdb0..b7fd6b061c 100644 --- a/gr-blocks/python/blocks/qa_probe_signal.py +++ b/gr-blocks/python/blocks/qa_probe_signal.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_probe_signal(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_python_message_passing.py b/gr-blocks/python/blocks/qa_python_message_passing.py index 7bb5fbe10e..49e2e5e481 100644 --- a/gr-blocks/python/blocks/qa_python_message_passing.py +++ b/gr-blocks/python/blocks/qa_python_message_passing.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import pmt import numpy diff --git a/gr-blocks/python/blocks/qa_regenerate.py b/gr-blocks/python/blocks/qa_regenerate.py index 52b6bdb515..65d76cfe16 100755..100644 --- a/gr-blocks/python/blocks/qa_regenerate.py +++ b/gr-blocks/python/blocks/qa_regenerate.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_regenerate(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_repack_bits_bb.py b/gr-blocks/python/blocks/qa_repack_bits_bb.py index 50e1506196..fa86c0ccac 100755..100644 --- a/gr-blocks/python/blocks/qa_repack_bits_bb.py +++ b/gr-blocks/python/blocks/qa_repack_bits_bb.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import random from gnuradio import gr, gr_unittest, blocks import pmt diff --git a/gr-blocks/python/blocks/qa_repeat.py b/gr-blocks/python/blocks/qa_repeat.py index eaf20d4e27..0054f8ce5e 100755..100644 --- a/gr-blocks/python/blocks/qa_repeat.py +++ b/gr-blocks/python/blocks/qa_repeat.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_repeat (gr_unittest.TestCase): @@ -31,17 +32,17 @@ class test_repeat (gr_unittest.TestCase): self.tb = None def test_001_float(self): - src_data = [n*1.0 for n in range(100)]; - dst_data = [] - for n in range(100): - dst_data += [1.0*n, 1.0*n, 1.0*n] - - src = blocks.vector_source_f(src_data) - rpt = blocks.repeat(gr.sizeof_float, 3) - dst = blocks.vector_sink_f() - self.tb.connect(src, rpt, dst) - self.tb.run() - self.assertFloatTuplesAlmostEqual(dst_data, dst.data(), 6) + src_data = [n*1.0 for n in range(100)]; + dst_data = [] + for n in range(100): + dst_data += [1.0*n, 1.0*n, 1.0*n] + + src = blocks.vector_source_f(src_data) + rpt = blocks.repeat(gr.sizeof_float, 3) + dst = blocks.vector_sink_f() + self.tb.connect(src, rpt, dst) + self.tb.run() + self.assertFloatTuplesAlmostEqual(dst_data, dst.data(), 6) if __name__ == '__main__': gr_unittest.run(test_repeat, "test_repeat.xml") diff --git a/gr-blocks/python/blocks/qa_rms.py b/gr-blocks/python/blocks/qa_rms.py index 0b07c37bdc..53c13b54d1 100644 --- a/gr-blocks/python/blocks/qa_rms.py +++ b/gr-blocks/python/blocks/qa_rms.py @@ -20,19 +20,21 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, blocks import math def sig_source_f(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: amp*math.cos(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [amp*math.cos(2.*math.pi*freq*x) for x in t] return y def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: amp*math.cos(2.*math.pi*freq*x) + \ - 1j*amp*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [amp*math.cos(2.*math.pi*freq*x) + \ + 1j*amp*math.sin(2.*math.pi*freq*x) for x in t] return y class test_rms(gr_unittest.TestCase): @@ -48,7 +50,7 @@ class test_rms(gr_unittest.TestCase): src_data = sig_source_f(1, 0.01, amp, 200) N = 750000 - expected_data = amp/math.sqrt(2.0) + expected_data = amp / math.sqrt(2.0) src = blocks.vector_source_f(src_data, True) head = blocks.head(gr.sizeof_float, N) diff --git a/gr-blocks/python/blocks/qa_sample_and_hold.py b/gr-blocks/python/blocks/qa_sample_and_hold.py index f645148695..306151600a 100644 --- a/gr-blocks/python/blocks/qa_sample_and_hold.py +++ b/gr-blocks/python/blocks/qa_sample_and_hold.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import time from gnuradio import gr, gr_unittest, blocks diff --git a/gr-blocks/python/blocks/qa_skiphead.py b/gr-blocks/python/blocks/qa_skiphead.py index a9b6df40cf..6eed7b465f 100755..100644 --- a/gr-blocks/python/blocks/qa_skiphead.py +++ b/gr-blocks/python/blocks/qa_skiphead.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_skiphead(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_socket_pdu.py b/gr-blocks/python/blocks/qa_socket_pdu.py index db9f53c71e..60da3d6bdd 100755..100644 --- a/gr-blocks/python/blocks/qa_socket_pdu.py +++ b/gr-blocks/python/blocks/qa_socket_pdu.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import random import pmt @@ -67,7 +68,7 @@ class qa_socket_pdu (gr_unittest.TestCase): received = self.dbg.get_message(0) received_data = pmt.cdr(received) msg_data = [] - for i in xrange(4): + for i in range(4): msg_data.append(pmt.u8vector_ref(received_data, i)) self.assertEqual(srcdata, tuple(msg_data)) diff --git a/gr-blocks/python/blocks/qa_stream_mux.py b/gr-blocks/python/blocks/qa_stream_mux.py index 3b470afa4c..b09e6db762 100755..100644 --- a/gr-blocks/python/blocks/qa_stream_mux.py +++ b/gr-blocks/python/blocks/qa_stream_mux.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import pmt import os @@ -49,8 +50,8 @@ class test_stream_mux (gr_unittest.TestCase): return dst.data () def help_stream_ramp_2ff(self, N, stream_sizes): - r1 = range(N) - r2 = range(N) + r1 = list(range(N)) + r2 = list(range(N)) r2.reverse() v0 = blocks.vector_source_f(r1, False) diff --git a/gr-blocks/python/blocks/qa_stream_to_tagged_stream.py b/gr-blocks/python/blocks/qa_stream_to_tagged_stream.py index 0d3f503abd..27904ede01 100755..100644 --- a/gr-blocks/python/blocks/qa_stream_to_tagged_stream.py +++ b/gr-blocks/python/blocks/qa_stream_to_tagged_stream.py @@ -21,6 +21,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest from gnuradio import blocks @@ -34,7 +35,7 @@ class qa_stream_to_tagged_stream (gr_unittest.TestCase): def test_001_t (self): src_data = (1, ) * 50 - packet_len = 10L + packet_len = 10 len_tag_key = 'packet_len' src = blocks.vector_source_f(src_data, False, 1) tagger = blocks.stream_to_tagged_stream(gr.sizeof_float, 1, packet_len, len_tag_key) @@ -44,7 +45,7 @@ class qa_stream_to_tagged_stream (gr_unittest.TestCase): self.assertEqual(sink.data(), src_data) tags = [gr.tag_to_python(x) for x in sink.tags()] tags = sorted([(x.offset, x.key, x.value) for x in tags]) - expected_tags = [(long(pos), 'packet_len', packet_len) for pos in range(0, 50, 10) ] + expected_tags = [(int(pos), 'packet_len', packet_len) for pos in range(0, 50, 10) ] self.assertEqual(tags, expected_tags) diff --git a/gr-blocks/python/blocks/qa_stretch.py b/gr-blocks/python/blocks/qa_stretch.py index e91a375abf..540d89c0c4 100755..100644 --- a/gr-blocks/python/blocks/qa_stretch.py +++ b/gr-blocks/python/blocks/qa_stretch.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, blocks class test_stretch(gr_unittest.TestCase): @@ -34,8 +36,8 @@ class test_stretch(gr_unittest.TestCase): tb = self.tb data = 10*[1,] - data0 = map(lambda x: x/20.0, data) - data1 = map(lambda x: x/10.0, data) + data0 = [x / 20.0 for x in data] + data1 = [x / 10.0 for x in data] expected_result0 = 10*[0.05,] expected_result1 = 10*[0.1,] diff --git a/gr-blocks/python/blocks/qa_tag_debug.py b/gr-blocks/python/blocks/qa_tag_debug.py index 5ccb285a5d..68d131ac0b 100755..100644 --- a/gr-blocks/python/blocks/qa_tag_debug.py +++ b/gr-blocks/python/blocks/qa_tag_debug.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_tag_debug(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_tag_file_sink.py b/gr-blocks/python/blocks/qa_tag_file_sink.py index 250ad1addf..bd4ee54380 100644 --- a/gr-blocks/python/blocks/qa_tag_file_sink.py +++ b/gr-blocks/python/blocks/qa_tag_file_sink.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import os, struct @@ -51,14 +52,14 @@ class test_tag_file_sink(gr_unittest.TestCase): # Open the files and read in the data, then remove the files # to clean up the directory. - outfile0 = file(file0, 'rb') - outfile1 = file(file1, 'rb') - data0 = outfile0.read(8) - data1 = outfile1.read(8) + outfile0 = open(file0, 'rb') + outfile1 = open(file1, 'rb') + data0 = outfile0.read(8) + data1 = outfile1.read(8) outfile0.close() outfile1.close() - os.remove(file0) - os.remove(file1) + os.remove(file0) + os.remove(file1) # Convert the 8 bytes from the files into a tuple of 2 ints. idata0 = struct.unpack('ii', data0) diff --git a/gr-blocks/python/blocks/qa_tag_gate.py b/gr-blocks/python/blocks/qa_tag_gate.py index 7ae676562e..085abf3377 100755..100644 --- a/gr-blocks/python/blocks/qa_tag_gate.py +++ b/gr-blocks/python/blocks/qa_tag_gate.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import pmt @@ -37,7 +38,7 @@ class qa_tag_gate (gr_unittest.TestCase): tag.key = pmt.string_to_symbol('key') tag.value = pmt.from_long(42) tag.offset = 0 - src = blocks.vector_source_f(range(20), False, 1, (tag,)) + src = blocks.vector_source_f(list(range(20)), False, 1, (tag,)) gate = blocks.tag_gate(gr.sizeof_float, False) sink = blocks.vector_sink_f() self.tb.connect(src, gate, sink) diff --git a/gr-blocks/python/blocks/qa_tagged_stream_mux.py b/gr-blocks/python/blocks/qa_tagged_stream_mux.py index 6f1c1c538a..aeedd16c4d 100755..100644 --- a/gr-blocks/python/blocks/qa_tagged_stream_mux.py +++ b/gr-blocks/python/blocks/qa_tagged_stream_mux.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import numpy import pmt from gnuradio import gr, gr_unittest, blocks @@ -84,9 +85,9 @@ class qa_tagged_stream_mux (gr_unittest.TestCase): This will add a 'special' tag to item 0 on stream 1. It should be on item 0 of the output stream. """ packet_len_0 = 5 - data0 = range(packet_len_0) + data0 = list(range(packet_len_0)) packet_len_1 = 3 - data1 = range(packet_len_1) + data1 = list(range(packet_len_1)) mux = blocks.tagged_stream_mux( gr.sizeof_float, self.tsb_key, @@ -99,7 +100,7 @@ class qa_tagged_stream_mux (gr_unittest.TestCase): (mux, 0) ) self.tb.connect( - blocks.vector_source_f(range(packet_len_1), tags=(make_tag('spam', 'eggs', 0),)), + blocks.vector_source_f(list(range(packet_len_1)), tags=(make_tag('spam', 'eggs', 0),)), blocks.stream_to_tagged_stream(gr.sizeof_float, 1, packet_len_1, self.tsb_key), (mux, 1) ) diff --git a/gr-blocks/python/blocks/qa_tags_strobe.py b/gr-blocks/python/blocks/qa_tags_strobe.py index c4e1b5d8bc..e347e30c8e 100644 --- a/gr-blocks/python/blocks/qa_tags_strobe.py +++ b/gr-blocks/python/blocks/qa_tags_strobe.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, blocks import pmt import math @@ -55,7 +57,7 @@ class test_tags_strobe(gr_unittest.TestCase): def test_002(self): N = 10000 nsamps = 123 - ntags = N / nsamps + ntags = N // nsamps src = blocks.tags_strobe(gr.sizeof_float, pmt.intern("TEST"), nsamps) diff --git a/gr-blocks/python/blocks/qa_tcp_server_sink.py b/gr-blocks/python/blocks/qa_tcp_server_sink.py index f7d3a0af92..96c6fcbe32 100644 --- a/gr-blocks/python/blocks/qa_tcp_server_sink.py +++ b/gr-blocks/python/blocks/qa_tcp_server_sink.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import os import socket diff --git a/gr-blocks/python/blocks/qa_threshold.py b/gr-blocks/python/blocks/qa_threshold.py index 49798426f3..5b92ca1a7e 100644 --- a/gr-blocks/python/blocks/qa_threshold.py +++ b/gr-blocks/python/blocks/qa_threshold.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_threshold(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_throttle.py b/gr-blocks/python/blocks/qa_throttle.py index 7d18e87ade..dae489fec8 100755..100644 --- a/gr-blocks/python/blocks/qa_throttle.py +++ b/gr-blocks/python/blocks/qa_throttle.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks class test_throttle(gr_unittest.TestCase): diff --git a/gr-blocks/python/blocks/qa_transcendental.py b/gr-blocks/python/blocks/qa_transcendental.py index 1da56381f4..ba30a62e3d 100644 --- a/gr-blocks/python/blocks/qa_transcendental.py +++ b/gr-blocks/python/blocks/qa_transcendental.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import math diff --git a/gr-blocks/python/blocks/qa_tsb_vector_sink_X.py b/gr-blocks/python/blocks/qa_tsb_vector_sink_X.py index ac3cd38d45..dca47b321e 100755..100644 --- a/gr-blocks/python/blocks/qa_tsb_vector_sink_X.py +++ b/gr-blocks/python/blocks/qa_tsb_vector_sink_X.py @@ -21,6 +21,7 @@ # Boston, MA 02110-1301, USA. # + import pmt from gnuradio import gr, gr_unittest from gnuradio import blocks @@ -36,7 +37,7 @@ class qa_tsb_vector_sink (gr_unittest.TestCase): def test_001_t (self): packet_len = 4 - data = range(2 * packet_len) + data = list(range(2 * packet_len)) tag = gr.tag_t() tag.key = pmt.intern("foo") tag.offset = 5 diff --git a/gr-blocks/python/blocks/qa_type_conversions.py b/gr-blocks/python/blocks/qa_type_conversions.py index cd600de2be..6206542edb 100755..100644 --- a/gr-blocks/python/blocks/qa_type_conversions.py +++ b/gr-blocks/python/blocks/qa_type_conversions.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks from math import sqrt, atan2 diff --git a/gr-blocks/python/blocks/qa_udp_source_sink.py b/gr-blocks/python/blocks/qa_udp_source_sink.py index 905b9e08a0..f0418357fd 100644 --- a/gr-blocks/python/blocks/qa_udp_source_sink.py +++ b/gr-blocks/python/blocks/qa_udp_source_sink.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import os diff --git a/gr-blocks/python/blocks/qa_unpack_k_bits.py b/gr-blocks/python/blocks/qa_unpack_k_bits.py index 765c459dfa..f351e75d30 100755..100644 --- a/gr-blocks/python/blocks/qa_unpack_k_bits.py +++ b/gr-blocks/python/blocks/qa_unpack_k_bits.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import random diff --git a/gr-blocks/python/blocks/qa_vco.py b/gr-blocks/python/blocks/qa_vco.py index fdd1eb1001..a67fe36d62 100644 --- a/gr-blocks/python/blocks/qa_vco.py +++ b/gr-blocks/python/blocks/qa_vco.py @@ -20,18 +20,20 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, blocks import math def sig_source_f(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: amp*math.cos(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [amp*math.cos(2.*math.pi*freq*x) for x in t] return y def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x) + \ - 1j*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) + \ + 1j*math.sin(2.*math.pi*freq*x) for x in t] return y class test_vco(gr_unittest.TestCase): @@ -49,7 +51,7 @@ class test_vco(gr_unittest.TestCase): sig_source_f(1, 0.25, 1, 200) src = blocks.vector_source_f(src_data) - op = blocks.vco_f(1, math.pi/2.0, 1) + op = blocks.vco_f(1, math.pi / 2.0, 1) dst = blocks.vector_sink_f() self.tb.connect(src, op, dst) @@ -66,7 +68,7 @@ class test_vco(gr_unittest.TestCase): sig_source_c(1, 0.25, 1, 200) src = blocks.vector_source_f(src_data) - op = blocks.vco_c(1, math.pi/2.0, 1) + op = blocks.vco_c(1, math.pi / 2.0, 1) dst = blocks.vector_sink_c() self.tb.connect(src, op, dst) diff --git a/gr-blocks/python/blocks/qa_vector_insert.py b/gr-blocks/python/blocks/qa_vector_insert.py index b916e3d528..5913fee68a 100755..100644 --- a/gr-blocks/python/blocks/qa_vector_insert.py +++ b/gr-blocks/python/blocks/qa_vector_insert.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import math diff --git a/gr-blocks/python/blocks/qa_vector_map.py b/gr-blocks/python/blocks/qa_vector_map.py index 1c07de826f..1e7545c2f3 100644 --- a/gr-blocks/python/blocks/qa_vector_map.py +++ b/gr-blocks/python/blocks/qa_vector_map.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import math @@ -34,7 +35,7 @@ class test_vector_map(gr_unittest.TestCase): def test_reversing(self): # Chunk data in blocks of N and reverse the block contents. N = 5 - src_data = range(0, 20) + src_data = list(range(0, 20)) expected_result = [] for i in range(N-1, len(src_data), N): for j in range(0, N): @@ -52,10 +53,10 @@ class test_vector_map(gr_unittest.TestCase): # Split an input vector into N streams. N = 5 M = 20 - src_data = range(0, M) + src_data = list(range(0, M)) expected_results = [] for n in range(0, N): - expected_results.append(range(n, M, N)) + expected_results.append(list(range(n, M, N))) mapping = [[(0, n)] for n in range(0, N)] src = blocks.vector_source_f(src_data, False, N) vmap = blocks.vector_map(gr.sizeof_float, (N, ), mapping) diff --git a/gr-blocks/python/blocks/qa_vector_sink_source.py b/gr-blocks/python/blocks/qa_vector_sink_source.py index 026713f5f4..c9bdfb4b5b 100755..100644 --- a/gr-blocks/python/blocks/qa_vector_sink_source.py +++ b/gr-blocks/python/blocks/qa_vector_sink_source.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import pmt import math diff --git a/gr-blocks/python/blocks/qa_wavfile.py b/gr-blocks/python/blocks/qa_wavfile.py index 5c3a69e1d0..438da000ef 100755..100644 --- a/gr-blocks/python/blocks/qa_wavfile.py +++ b/gr-blocks/python/blocks/qa_wavfile.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks import os @@ -38,35 +39,35 @@ class test_wavefile(gr_unittest.TestCase): self.tb = None def test_001_checkwavread(self): - wf = blocks.wavfile_source(g_in_file) - self.assertEqual(wf.sample_rate(), 8000) + wf = blocks.wavfile_source(g_in_file) + self.assertEqual(wf.sample_rate(), 8000) def test_002_checkwavcopy(self): - infile = g_in_file - outfile = "test_out.wav" + infile = g_in_file + outfile = "test_out.wav" - wf_in = blocks.wavfile_source(infile) - wf_out = blocks.wavfile_sink(outfile, + wf_in = blocks.wavfile_source(infile) + wf_out = blocks.wavfile_sink(outfile, wf_in.channels(), wf_in.sample_rate(), wf_in.bits_per_sample()) - self.tb.connect(wf_in, wf_out) - self.tb.run() - wf_out.close() + self.tb.connect(wf_in, wf_out) + self.tb.run() + wf_out.close() - # we're loosing all extra header chunks - self.assertEqual(getsize(infile) - g_extra_header_len, getsize(outfile)) + # we're loosing all extra header chunks + self.assertEqual(getsize(infile) - g_extra_header_len, getsize(outfile)) - in_f = file(infile, 'rb') - out_f = file(outfile, 'rb') + in_f = open(infile, 'rb') + out_f = open(outfile, 'rb') - in_data = in_f.read() - out_data = out_f.read() + in_data = in_f.read() + out_data = out_f.read() out_f.close() - os.remove(outfile) - # cut extra header chunks input file - self.assertEqual(in_data[:g_extra_header_offset] + \ - in_data[g_extra_header_offset + g_extra_header_len:], out_data) + os.remove(outfile) + # cut extra header chunks input file + self.assertEqual(in_data[:g_extra_header_offset] + \ + in_data[g_extra_header_offset + g_extra_header_len:], out_data) if __name__ == '__main__': gr_unittest.run(test_wavefile, "test_wavefile.xml") diff --git a/gr-blocks/python/blocks/stream_to_vector_decimator.py b/gr-blocks/python/blocks/stream_to_vector_decimator.py index bcbfd96b8b..9896ab8d34 100644 --- a/gr-blocks/python/blocks/stream_to_vector_decimator.py +++ b/gr-blocks/python/blocks/stream_to_vector_decimator.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2008 Free Software Foundation, Inc. # @@ -19,9 +20,11 @@ # Boston, MA 02110-1301, USA. # -import blocks_swig as blocks from gnuradio import gr +from . import blocks_swig as blocks + + class stream_to_vector_decimator(gr.hier_block2): """ Convert the stream to a vector, decimate the vector stream to achieve the vector rate. diff --git a/gr-blocks/swig/blocks_swig.py.in b/gr-blocks/swig/blocks_swig.py.in index 7682f17d83..71ab4dac16 100644 --- a/gr-blocks/swig/blocks_swig.py.in +++ b/gr-blocks/swig/blocks_swig.py.in @@ -19,14 +19,16 @@ # Boston, MA 02110-1301, USA. # -from blocks_swig0 import * -from blocks_swig1 import * -from blocks_swig2 import * -from blocks_swig3 import * -from blocks_swig4 import * -from blocks_swig5 import * -from blocks_swig6 import * -from blocks_swig7 import * -from blocks_swig8 import * -from blocks_swig9 import * -from blocks_swig10 import * +from __future__ import absolute_import + +from .blocks_swig0 import * +from .blocks_swig1 import * +from .blocks_swig2 import * +from .blocks_swig3 import * +from .blocks_swig4 import * +from .blocks_swig5 import * +from .blocks_swig6 import * +from .blocks_swig7 import * +from .blocks_swig8 import * +from .blocks_swig9 import * +from .blocks_swig10 import * diff --git a/gr-channels/python/channels/CMakeLists.txt b/gr-channels/python/channels/CMakeLists.txt index a91033df75..391b868931 100644 --- a/gr-channels/python/channels/CMakeLists.txt +++ b/gr-channels/python/channels/CMakeLists.txt @@ -50,6 +50,6 @@ if(ENABLE_TESTING) file (GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-channels/python/channels/__init__.py b/gr-channels/python/channels/__init__.py index ae4c4ab715..1bae9b44e2 100644 --- a/gr-channels/python/channels/__init__.py +++ b/gr-channels/python/channels/__init__.py @@ -22,23 +22,25 @@ ''' Blocks for channel models and related functions. ''' +from __future__ import absolute_import +from __future__ import unicode_literals import os try: - from channels_swig import * + from .channels_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from channels_swig import * + from .channels_swig import * # Blocks for Hardware Impairments -from amp_bal import * -from conj_fs_iqcorr import * -from distortion_2_gen import * -from distortion_3_gen import * -from iqbal_gen import * -from impairments import * -from phase_bal import * -from phase_noise_gen import * -from quantizer import * +from .amp_bal import * +from .conj_fs_iqcorr import * +from .distortion_2_gen import * +from .distortion_3_gen import * +from .iqbal_gen import * +from .impairments import * +from .phase_bal import * +from .phase_noise_gen import * +from .quantizer import * diff --git a/gr-channels/python/channels/amp_bal.py b/gr-channels/python/channels/amp_bal.py index 30e0f0d8e2..0ec3db8ab5 100644 --- a/gr-channels/python/channels/amp_bal.py +++ b/gr-channels/python/channels/amp_bal.py @@ -7,6 +7,7 @@ # Generated: Thu Aug 1 11:47:46 2013 ################################################## +from __future__ import unicode_literals from gnuradio import blocks from gnuradio import gr from gnuradio.filter import firdes diff --git a/gr-channels/python/channels/conj_fs_iqcorr.py b/gr-channels/python/channels/conj_fs_iqcorr.py index 700eb645c2..f9873f1606 100644 --- a/gr-channels/python/channels/conj_fs_iqcorr.py +++ b/gr-channels/python/channels/conj_fs_iqcorr.py @@ -7,6 +7,7 @@ # Generated: Thu Aug 1 13:00:27 2013 ################################################## +from __future__ import unicode_literals from gnuradio import blocks from gnuradio import filter from gnuradio import gr diff --git a/gr-channels/python/channels/distortion_2_gen.py b/gr-channels/python/channels/distortion_2_gen.py index f8933cf7aa..cf44fd8d29 100644 --- a/gr-channels/python/channels/distortion_2_gen.py +++ b/gr-channels/python/channels/distortion_2_gen.py @@ -6,6 +6,7 @@ # Generated: Thu Aug 1 12:30:23 2013 ################################################## +from __future__ import unicode_literals from gnuradio import blocks from gnuradio import gr from gnuradio.filter import firdes diff --git a/gr-channels/python/channels/distortion_3_gen.py b/gr-channels/python/channels/distortion_3_gen.py index 1607e01bf2..9cb388806e 100644 --- a/gr-channels/python/channels/distortion_3_gen.py +++ b/gr-channels/python/channels/distortion_3_gen.py @@ -6,6 +6,7 @@ # Generated: Thu Aug 1 12:37:59 2013 ################################################## +from __future__ import unicode_literals from gnuradio import blocks from gnuradio import gr from gnuradio.filter import firdes diff --git a/gr-channels/python/channels/impairments.py b/gr-channels/python/channels/impairments.py index 3da838a902..5e2319a5d9 100644 --- a/gr-channels/python/channels/impairments.py +++ b/gr-channels/python/channels/impairments.py @@ -6,6 +6,9 @@ # Generated: Thu Aug 1 12:46:10 2013 ################################################## +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals from gnuradio import analog from gnuradio import blocks from gnuradio import gr @@ -13,10 +16,10 @@ from gnuradio.filter import firdes import math #Import locally -from phase_noise_gen import * -from iqbal_gen import * -from distortion_2_gen import * -from distortion_3_gen import * +from .phase_noise_gen import * +from .iqbal_gen import * +from .distortion_2_gen import * +from .distortion_3_gen import * class impairments(gr.hier_block2): @@ -42,7 +45,7 @@ class impairments(gr.hier_block2): ################################################## # Blocks ################################################## - self.channels_phase_noise_gen_0_0 = phase_noise_gen(math.pow(10.0,phase_noise_mag/20.0), .01) + self.channels_phase_noise_gen_0_0 = phase_noise_gen(math.pow(10.0,phase_noise_mag / 20.0), .01) self.channels_iqbal_gen_0 = iqbal_gen(magbal, phasebal) self.channels_distortion_3_gen_0 = distortion_3_gen(beta) self.channels_distortion_2_gen_0 = distortion_2_gen(gamma) @@ -75,7 +78,7 @@ class impairments(gr.hier_block2): def set_phase_noise_mag(self, phase_noise_mag): self.phase_noise_mag = phase_noise_mag - self.channels_phase_noise_gen_0_0.set_noise_mag(math.pow(10.0,self.phase_noise_mag/20.0)) + self.channels_phase_noise_gen_0_0.set_noise_mag(math.pow(10.0,self.phase_noise_mag / 20.0)) def get_magbal(self): return self.magbal diff --git a/gr-channels/python/channels/iqbal_gen.py b/gr-channels/python/channels/iqbal_gen.py index d42ca22778..bfe439350f 100644 --- a/gr-channels/python/channels/iqbal_gen.py +++ b/gr-channels/python/channels/iqbal_gen.py @@ -6,6 +6,8 @@ # Generated: Thu Aug 1 12:08:07 2013 ################################################## +from __future__ import division +from __future__ import unicode_literals from gnuradio import blocks from gnuradio import gr from gnuradio.filter import firdes @@ -29,7 +31,7 @@ class iqbal_gen(gr.hier_block2): ################################################## # Blocks ################################################## - self.mag = blocks.multiply_const_vff((math.pow(10,magnitude/20.0), )) + self.mag = blocks.multiply_const_vff((math.pow(10,magnitude / 20.0), )) self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff((math.sin(phase*math.pi/180.0), )) self.blocks_float_to_complex_0 = blocks.float_to_complex(1) self.blocks_complex_to_float_0 = blocks.complex_to_float(1) @@ -55,7 +57,7 @@ class iqbal_gen(gr.hier_block2): def set_magnitude(self, magnitude): self.magnitude = magnitude - self.mag.set_k((math.pow(10,self.magnitude/20.0), )) + self.mag.set_k((math.pow(10,self.magnitude / 20.0), )) def get_phase(self): return self.phase diff --git a/gr-channels/python/channels/phase_bal.py b/gr-channels/python/channels/phase_bal.py index b760e6f439..2ebdebcc27 100644 --- a/gr-channels/python/channels/phase_bal.py +++ b/gr-channels/python/channels/phase_bal.py @@ -6,6 +6,7 @@ # Generated: Thu Aug 1 11:49:41 2013 ################################################## +from __future__ import unicode_literals from gnuradio import blocks from gnuradio import filter from gnuradio import gr diff --git a/gr-channels/python/channels/phase_noise_gen.py b/gr-channels/python/channels/phase_noise_gen.py index 95c5676e40..5e05c0a100 100644 --- a/gr-channels/python/channels/phase_noise_gen.py +++ b/gr-channels/python/channels/phase_noise_gen.py @@ -6,6 +6,7 @@ # Generated: Thu Aug 1 11:59:39 2013 ################################################## +from __future__ import unicode_literals from gnuradio import analog from gnuradio import blocks from gnuradio import filter diff --git a/gr-channels/python/channels/qa_channel_model.py b/gr-channels/python/channels/qa_channel_model.py index fed542f44f..53cc80f911 100755..100644 --- a/gr-channels/python/channels/qa_channel_model.py +++ b/gr-channels/python/channels/qa_channel_model.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, analog, blocks, channels import math diff --git a/gr-channels/python/channels/qa_fading_model.py b/gr-channels/python/channels/qa_fading_model.py index 1e99312e82..84ca531d6d 100644 --- a/gr-channels/python/channels/qa_fading_model.py +++ b/gr-channels/python/channels/qa_fading_model.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, analog, blocks, channels import math diff --git a/gr-channels/python/channels/quantizer.py b/gr-channels/python/channels/quantizer.py index a3d918c7c2..897a1eb432 100644 --- a/gr-channels/python/channels/quantizer.py +++ b/gr-channels/python/channels/quantizer.py @@ -5,6 +5,8 @@ # Generated: Thu Aug 1 11:09:51 2013 ################################################## +from __future__ import division +from __future__ import unicode_literals from gnuradio import blocks from gnuradio import gr from gnuradio.filter import firdes @@ -27,7 +29,7 @@ class quantizer(gr.hier_block2): # Blocks ################################################## self.blocks_short_to_float_0 = blocks.short_to_float(1, 1) - self.blocks_multiply_const_vxx_0_0 = blocks.multiply_const_vff((1.0/pow(2.0,bits-1.0), )) + self.blocks_multiply_const_vxx_0_0 = blocks.multiply_const_vff((1.0 / pow(2.0,bits-1.0), )) self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff((pow(2,bits-1.0), )) self.blocks_float_to_short_0 = blocks.float_to_short(1, 1) @@ -48,7 +50,7 @@ class quantizer(gr.hier_block2): def set_bits(self, bits): self.bits = bits - self.blocks_multiply_const_vxx_0_0.set_k((1.0/pow(2.0,self.bits-1.0), )) + self.blocks_multiply_const_vxx_0_0.set_k((1.0 / pow(2.0,self.bits-1.0), )) self.blocks_multiply_const_vxx_0.set_k((pow(2,self.bits-1.0), )) diff --git a/gr-comedi/python/comedi/CMakeLists.txt b/gr-comedi/python/comedi/CMakeLists.txt index e3f7031a23..b3e983e9bd 100644 --- a/gr-comedi/python/comedi/CMakeLists.txt +++ b/gr-comedi/python/comedi/CMakeLists.txt @@ -43,6 +43,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-comedi/python/comedi/__init__.py b/gr-comedi/python/comedi/__init__.py index 701b82af70..f9f1124e5a 100644 --- a/gr-comedi/python/comedi/__init__.py +++ b/gr-comedi/python/comedi/__init__.py @@ -21,13 +21,14 @@ ''' Blocks and utilities for COMEDI devices ''' +from __future__ import unicode_literals # The presence of this file turns this directory into a Python package import os try: - from comedi_swig import * + from .comedi_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from comedi_swig import * + from .comedi_swig import * diff --git a/gr-comedi/python/comedi/qa_comedi.py b/gr-comedi/python/comedi/qa_comedi.py index 08ec92dd13..f4dc7b7778 100755..100644 --- a/gr-comedi/python/comedi/qa_comedi.py +++ b/gr-comedi/python/comedi/qa_comedi.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, comedi class test_comedi(gr_unittest.TestCase): diff --git a/gr-digital/examples/berawgn.py b/gr-digital/examples/berawgn.py index c47d99174a..886c93bdfe 100755..100644 --- a/gr-digital/examples/berawgn.py +++ b/gr-digital/examples/berawgn.py @@ -32,6 +32,10 @@ Of course, expect the maximum value for BER to be one order of magnitude below what you chose for N_BITS. """ +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + import math import numpy @@ -43,13 +47,13 @@ import sys try: from scipy.special import erfc except ImportError: - print "Error: could not import scipy (http://www.scipy.org/)" + print("Error: could not import scipy (http://www.scipy.org/)") sys.exit(1) try: import pylab except ImportError: - print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + print("Error: could not import pylab (http://matplotlib.sourceforge.net/)") sys.exit(1) # Best to choose powers of 10 @@ -58,7 +62,7 @@ RAND_SEED = 42 def berawgn(EbN0): """ Calculates theoretical bit error rate in AWGN (for BPSK and given Eb/N0) """ - return 0.5 * erfc(math.sqrt(10**(float(EbN0)/10))) + return 0.5 * erfc(math.sqrt(10**(float(EbN0) / 10))) class BitErrors(gr.hier_block2): """ Two inputs: true and received bits. We compare them and @@ -81,7 +85,7 @@ class BitErrors(gr.hier_block2): blocks.unpack_k_bits_bb(bits_per_byte), blocks.uchar_to_float(), blocks.integrate_ff(intdump_decim), - blocks.multiply_const_ff(1.0/N_BITS), + blocks.multiply_const_ff(1.0 / N_BITS), self) self.connect((self, 1), (comp, 1)) @@ -91,7 +95,7 @@ class BERAWGNSimu(gr.top_block): gr.top_block.__init__(self) self.const = digital.qpsk_constellation() # Source is N_BITS bits, non-repeated - data = map(int, numpy.random.randint(0, self.const.arity(), N_BITS/self.const.bits_per_symbol())) + data = list(map(int, numpy.random.randint(0, self.const.arity(), N_BITS / self.const.bits_per_symbol()))) src = blocks.vector_source_b(data, False) mod = digital.chunks_to_symbols_bc((self.const.points()), 1) add = blocks.add_vcc() @@ -107,12 +111,12 @@ class BERAWGNSimu(gr.top_block): def EbN0_to_noise_voltage(self, EbN0): """ Converts Eb/N0 to a complex noise voltage (assuming unit symbol power) """ - return 1.0 / math.sqrt(self.const.bits_per_symbol() * 10**(float(EbN0)/10)) + return 1.0 / math.sqrt(self.const.bits_per_symbol( * 10**(float(EbN0) / 10))) def simulate_ber(EbN0): """ All the work's done here: create flow graph, run, read out BER """ - print "Eb/N0 = %d dB" % EbN0 + print("Eb/N0 = %d dB" % EbN0) fg = BERAWGNSimu(EbN0) fg.run() return numpy.sum(fg.sink.data()) @@ -120,9 +124,9 @@ def simulate_ber(EbN0): if __name__ == "__main__": EbN0_min = 0 EbN0_max = 15 - EbN0_range = range(EbN0_min, EbN0_max+1) + EbN0_range = list(range(EbN0_min, EbN0_max+1)) ber_theory = [berawgn(x) for x in EbN0_range] - print "Simulating..." + print("Simulating...") ber_simu = [simulate_ber(x) for x in EbN0_range] f = pylab.figure() @@ -135,4 +139,3 @@ if __name__ == "__main__": s.legend() s.grid() pylab.show() - diff --git a/gr-digital/examples/example_costas.py b/gr-digital/examples/example_costas.py index 77495d944c..56fc419013 100755..100644 --- a/gr-digital/examples/example_costas.py +++ b/gr-digital/examples/example_costas.py @@ -20,6 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + from gnuradio import gr, digital, filter from gnuradio import blocks from gnuradio import channels @@ -31,13 +35,13 @@ import sys try: import scipy except ImportError: - print "Error: could not import scipy (http://www.scipy.org/)" + print("Error: could not import scipy (http://www.scipy.org/)") sys.exit(1) try: import pylab except ImportError: - print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + print("Error: could not import pylab (http://matplotlib.sourceforge.net/)") sys.exit(1) class example_costas(gr.top_block): diff --git a/gr-digital/examples/example_fll.py b/gr-digital/examples/example_fll.py index cda92eaa78..2603f06342 100755..100644 --- a/gr-digital/examples/example_fll.py +++ b/gr-digital/examples/example_fll.py @@ -20,6 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + from gnuradio import gr, digital, filter from gnuradio import blocks from gnuradio import channels @@ -31,13 +35,13 @@ import sys try: import scipy except ImportError: - print "Error: could not import scipy (http://www.scipy.org/)" + print("Error: could not import scipy (http://www.scipy.org/)") sys.exit(1) try: import pylab except ImportError: - print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + print("Error: could not import pylab (http://matplotlib.sourceforge.net/)") sys.exit(1) class example_fll(gr.top_block): diff --git a/gr-digital/examples/example_timing.py b/gr-digital/examples/example_timing.py index 9e8e3e07b4..93ce691cf7 100755..100644 --- a/gr-digital/examples/example_timing.py +++ b/gr-digital/examples/example_timing.py @@ -20,6 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + from gnuradio import gr, digital, filter from gnuradio import blocks from gnuradio import channels @@ -31,13 +35,13 @@ import sys try: import scipy except ImportError: - print "Error: could not import scipy (http://www.scipy.org/)" + print("Error: could not import scipy (http://www.scipy.org/)") sys.exit(1) try: import pylab except ImportError: - print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + print("Error: could not import pylab (http://matplotlib.sourceforge.net/)") sys.exit(1) from scipy import fftpack @@ -69,8 +73,8 @@ class example_timing(gr.top_block): self.taps = self.clk.taps() self.dtaps = self.clk.diff_taps() - self.delay = int(scipy.ceil(((len(rrc_taps)-1)/2 + - (len(self.taps[0])-1)/2)/float(sps))) + 1 + self.delay = int(scipy.ceil((old_div((len(rrc_taps)-1) / 2 + + (len(self.taps[0])-1) / 2),float(sps)))) + 1 self.vsnk_err = blocks.vector_sink_f() diff --git a/gr-digital/examples/gen_whitener.py b/gr-digital/examples/gen_whitener.py index 62345cee5d..4b4ecdb528 100755..100644 --- a/gr-digital/examples/gen_whitener.py +++ b/gr-digital/examples/gen_whitener.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr, gru from gnuradio import blocks from gnuradio.eng_arg import eng_float, intx diff --git a/gr-digital/examples/narrowband/benchmark_add_channel.py b/gr-digital/examples/narrowband/benchmark_add_channel.py index cd85f4e488..846caddd26 100755..100644 --- a/gr-digital/examples/narrowband/benchmark_add_channel.py +++ b/gr-digital/examples/narrowband/benchmark_add_channel.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2010,2011 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. -# +# + +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import channels, gr from gnuradio import blocks @@ -32,14 +36,14 @@ class my_top_block(gr.top_block): def __init__(self, ifile, ofile, options): gr.top_block.__init__(self) - SNR = 10.0**(options.snr/10.0) + SNR = 10.0**(options.snr / 10.0) frequency_offset = options.frequency_offset time_offset = options.time_offset - phase_offset = options.phase_offset*(math.pi/180.0) + phase_offset = options.phase_offset*(math.pi / 180.0) # calculate noise voltage from SNR power_in_signal = abs(options.tx_amplitude)**2 - noise_power = power_in_signal/SNR + noise_power = power_in_signal / SNR noise_voltage = math.sqrt(noise_power) self.src = blocks.file_source(gr.sizeof_gr_complex, ifile) @@ -52,7 +56,7 @@ class my_top_block(gr.top_block): self.snk = blocks.file_sink(gr.sizeof_gr_complex, ofile) self.connect(self.src, self.channel, self.phase, self.snk) - + # ///////////////////////////////////////////////////////////////////////////// # main @@ -86,13 +90,13 @@ def main(): ifile = args[0] ofile = args[1] - + # build the graph tb = my_top_block(ifile, ofile, options) r = gr.enable_realtime_scheduling() if r != gr.RT_OK: - print "Warning: Failed to enable realtime scheduling." + print("Warning: Failed to enable realtime scheduling.") tb.start() # start flow graph tb.wait() # wait for it to finish diff --git a/gr-digital/examples/narrowband/benchmark_rx.py b/gr-digital/examples/narrowband/benchmark_rx.py index 09d923fc6b..8467d376e7 100755..100644 --- a/gr-digital/examples/narrowband/benchmark_rx.py +++ b/gr-digital/examples/narrowband/benchmark_rx.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2010,2011,2013 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. -# +# + +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, gru from gnuradio import blocks @@ -37,7 +41,7 @@ import struct import sys #import os -#print os.getpid() +#print(os.getpid()) #raw_input('Attach and press enter: ') class my_top_block(gr.top_block): @@ -47,10 +51,10 @@ class my_top_block(gr.top_block): if(options.rx_freq is not None): # Work-around to get the modulation's bits_per_symbol args = demodulator.extract_kwargs_from_options(options) - symbol_rate = options.bitrate / demodulator(**args).bits_per_symbol() + symbol_rate = options.bitrate / demodulator(**args.bits_per_symbol()) self.source = uhd_receiver(options.args, symbol_rate, - options.samples_per_symbol, options.rx_freq, + options.samples_per_symbol, options.rx_freq, options.lo_offset, options.rx_gain, options.spec, options.antenna, options.clock_source, options.verbose) @@ -66,7 +70,7 @@ class my_top_block(gr.top_block): # Set up receive path # do this after for any adjustments to the options that may # occur in the sinks (specifically the UHD sink) - self.rxpath = receive_path(demodulator, rx_callback, options) + self.rxpath = receive_path(demodulator, rx_callback, options) self.connect(self.source, self.rxpath) @@ -82,7 +86,7 @@ def main(): n_rcvd = 0 n_right = 0 - + def rx_callback(ok, payload): global n_rcvd, n_right (pktno,) = struct.unpack('!H', payload[0:2]) @@ -90,8 +94,8 @@ def main(): if ok: n_right += 1 - print "ok = %5s pktno = %4d n_rcvd = %4d n_right = %4d" % ( - ok, pktno, n_rcvd, n_right) + print("ok = %5s pktno = %4d n_rcvd = %4d n_right = %4d" % ( + ok, pktno, n_rcvd, n_right)) demods = digital.modulation_utils.type_1_demods() @@ -99,17 +103,17 @@ def main(): parser = OptionParser (option_class=eng_option, conflict_handler="resolve") expert_grp = parser.add_option_group("Expert") - parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), + parser.add_option("-m", "--modulation", type="choice", choices=list(demods.keys()), default='psk', help="Select modulation from: %s [default=%%default]" - % (', '.join(demods.keys()),)) + % (', '.join(list(demods.keys())),)) parser.add_option("","--from-file", default=None, help="input file of samples to demod") receive_path.add_options(parser, expert_grp) uhd_receiver.add_options(parser) - for mod in demods.values(): + for mod in list(demods.values()): mod.add_options(expert_grp) (options, args) = parser.parse_args () @@ -130,7 +134,7 @@ def main(): r = gr.enable_realtime_scheduling() if r != gr.RT_OK: - print "Warning: Failed to enable realtime scheduling." + print("Warning: Failed to enable realtime scheduling.") tb.start() # start flow graph tb.wait() # wait for it to finish diff --git a/gr-digital/examples/narrowband/benchmark_tx.py b/gr-digital/examples/narrowband/benchmark_tx.py index 2cb74d5a77..bf38f0bf12 100755..100644 --- a/gr-digital/examples/narrowband/benchmark_tx.py +++ b/gr-digital/examples/narrowband/benchmark_tx.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2010,2011,2013 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. -# +# + +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks @@ -35,8 +39,8 @@ from uhd_interface import uhd_transmitter import time, struct, sys -#import os -#print os.getpid() +#import os +#print(os.getpid()) #raw_input('Attach and press enter') class my_top_block(gr.top_block): @@ -46,7 +50,7 @@ class my_top_block(gr.top_block): if(options.tx_freq is not None): # Work-around to get the modulation's bits_per_symbol args = modulator.extract_kwargs_from_options(options) - symbol_rate = options.bitrate / modulator(**args).bits_per_symbol() + symbol_rate = options.bitrate / modulator(**args.bits_per_symbol()) self.sink = uhd_transmitter(options.args, symbol_rate, options.samples_per_symbol, options.tx_freq, @@ -54,7 +58,7 @@ class my_top_block(gr.top_block): options.spec, options.antenna, options.clock_source, options.verbose) options.samples_per_symbol = self.sink._sps - + elif(options.to_file is not None): sys.stderr.write(("Saving samples to '%s'.\n\n" % (options.to_file))) self.sink = blocks.file_sink(gr.sizeof_gr_complex, options.to_file) @@ -82,10 +86,10 @@ def main(): parser = OptionParser(option_class=eng_option, conflict_handler="resolve") expert_grp = parser.add_option_group("Expert") - parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(), + parser.add_option("-m", "--modulation", type="choice", choices=list(mods.keys()), default='psk', help="Select modulation from: %s [default=%%default]" - % (', '.join(mods.keys()),)) + % (', '.join(list(mods.keys())),)) parser.add_option("-s", "--size", type="eng_float", default=1500, help="set packet size [default=%default]") @@ -101,7 +105,7 @@ def main(): transmit_path.add_options(parser, expert_grp) uhd_transmitter.add_options(parser) - for mod in mods.values(): + for mod in list(mods.values()): mod.add_options(expert_grp) (options, args) = parser.parse_args () @@ -109,7 +113,7 @@ def main(): if len(args) != 0: parser.print_help() sys.exit(1) - + if options.from_file is not None: source_file = open(options.from_file, 'r') @@ -118,10 +122,10 @@ def main(): r = gr.enable_realtime_scheduling() if r != gr.RT_OK: - print "Warning: failed to enable realtime scheduling" + print("Warning: failed to enable realtime scheduling") tb.start() # start flow graph - + # generate and send packets nbytes = int(1e6 * options.megabytes) n = 0 @@ -130,7 +134,7 @@ def main(): while n < nbytes: if options.from_file is None: - data = (pkt_size - 2) * chr(pktno & 0xff) + data = (pkt_size - 2) * chr(pktno & 0xff) else: data = source_file.read(pkt_size - 2) if data == '': @@ -143,7 +147,7 @@ def main(): if options.discontinuous and pktno % 5 == 4: time.sleep(1) pktno += 1 - + send_pkt(eof=True) tb.wait() # wait for it to finish diff --git a/gr-digital/examples/narrowband/digital_bert_rx.py b/gr-digital/examples/narrowband/digital_bert_rx.py index c04c76762f..aaa8b3e9ea 100755..100644 --- a/gr-digital/examples/narrowband/digital_bert_rx.py +++ b/gr-digital/examples/narrowband/digital_bert_rx.py @@ -20,6 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + from gnuradio import gr, eng_notation from optparse import OptionParser from gnuradio.eng_option import eng_option @@ -44,8 +48,8 @@ class status_thread(_threading.Thread): def run(self): while not self.done: - print "Freq. Offset: {0:5.0f} Hz Timing Offset: {1:10.1f} ppm Estimated SNR: {2:4.1f} dB BER: {3:g}".format( - tb.frequency_offset(), tb.timing_offset()*1e6, tb.snr(), tb.ber()) + print("Freq. Offset: {0:5.0f} Hz Timing Offset: {1:10.1f} ppm Estimated SNR: {2:4.1f} dB BER: {3:g}".format( + tb.frequency_offset(), tb.timing_offset()*1e6, tb.snr(), tb.ber())) try: time.sleep(1.0) except KeyboardInterrupt: @@ -63,10 +67,10 @@ class bert_receiver(gr.hier_block2): gr.hier_block2.__init__(self, "bert_receive", gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature(0, 0, 0)) # Output signature - + self._bitrate = bitrate - self._demod = digital.generic_demod(constellation, differential, + self._demod = digital.generic_demod(constellation, differential, samples_per_symbol, gray_coded, excess_bw, freq_bw, timing_bw, phase_bw, @@ -77,15 +81,15 @@ class bert_receiver(gr.hier_block2): # Add an SNR probe on the demodulated constellation self._snr_probe = digital.probe_mpsk_snr_est_c(digital.SNR_EST_M2M4, 1000, - alpha=10.0/self._symbol_rate) + alpha=10.0 / self._symbol_rate) self.connect(self._demod.time_recov, self._snr_probe) - + # Descramble BERT sequence. A channel error will create 3 incorrect bits self._descrambler = digital.descrambler_bb(0x8A, 0x7F, 7) # CCSDS 7-bit descrambler # Measure BER by the density of 0s in the stream - self._ber = digital.probe_density_b(1.0/self._symbol_rate) - + self._ber = digital.probe_density_b(1.0 / self._symbol_rate) + self.connect(self, self._demod, self._descrambler, self._ber) def frequency_offset(self): @@ -98,22 +102,22 @@ class bert_receiver(gr.hier_block2): return self._snr_probe.snr() def ber(self): - return (1.0-self._ber.density())/3.0 + return (1.0-self._ber.density()) / 3.0 class rx_psk_block(gr.top_block): def __init__(self, demod, options): - gr.top_block.__init__(self, "rx_mpsk") + gr.top_block.__init__(self, "rx_mpsk") self._demodulator_class = demod # Get demod_kwargs demod_kwargs = self._demodulator_class.extract_kwargs_from_options(options) - + # demodulator - self._demodulator = self._demodulator_class(**demod_kwargs) + self._demodulator = self._demodulator_class(**demod_kwargs) if(options.rx_freq is not None): symbol_rate = options.bitrate / self._demodulator.bits_per_symbol() @@ -131,17 +135,17 @@ class rx_psk_block(gr.top_block): # Create the BERT receiver self._receiver = bert_receiver(options.bitrate, - self._demodulator._constellation, + self._demodulator._constellation, options.samples_per_symbol, - options.differential, - options.excess_bw, + options.differential, + options.excess_bw, gray_coded=True, freq_bw=options.freq_bw, timing_bw=options.timing_bw, phase_bw=options.phase_bw, verbose=options.verbose, log=options.log) - + self.connect(self._source, self._receiver) def snr(self): @@ -149,7 +153,7 @@ class rx_psk_block(gr.top_block): def mag(self): return self._receiver.signal_mean() - + def var(self): return self._receiver.noise_variance() @@ -158,19 +162,19 @@ class rx_psk_block(gr.top_block): def frequency_offset(self): return self._receiver.frequency_offset() - + def timing_offset(self): return self._receiver.timing_offset() - + def get_options(demods): parser = OptionParser(option_class=eng_option, conflict_handler="resolve") parser.add_option("","--from-file", default=None, help="input file of samples to demod") - parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), + parser.add_option("-m", "--modulation", type="choice", choices=list(demods.keys()), default='psk', help="Select modulation from: %s [default=%%default]" - % (', '.join(demods.keys()),)) + % (', '.join(list(demods.keys())),)) parser.add_option("-r", "--bitrate", type="eng_float", default=250e3, help="Select modulation bit rate (default=%default)") parser.add_option("-S", "--samples-per-symbol", type="float", default=2, @@ -184,14 +188,14 @@ def get_options(demods): uhd_receiver.add_options(parser) demods = digital.modulation_utils.type_1_demods() - for mod in demods.values(): + for mod in list(demods.values()): mod.add_options(parser) - + (options, args) = parser.parse_args() if len(args) != 0: parser.print_help() sys.exit(1) - + return (options, args) @@ -203,8 +207,8 @@ if __name__ == "__main__": demod = demods[options.modulation] tb = rx_psk_block(demod, options) - print "\n*** SNR estimator is inaccurate below about 7dB" - print "*** BER estimator is inaccurate above about 10%\n" + print("\n*** SNR estimator is inaccurate below about 7dB") + print("*** BER estimator is inaccurate above about 10%\n") updater = status_thread(tb) try: diff --git a/gr-digital/examples/narrowband/digital_bert_tx.py b/gr-digital/examples/narrowband/digital_bert_tx.py index 6859d2e7af..acc81b4492 100755..100644 --- a/gr-digital/examples/narrowband/digital_bert_tx.py +++ b/gr-digital/examples/narrowband/digital_bert_tx.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, eng_notation from gnuradio.eng_option import eng_option from optparse import OptionParser @@ -97,10 +99,10 @@ class tx_psk_block(gr.top_block): def get_options(mods): parser = OptionParser(option_class=eng_option, conflict_handler="resolve") - parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(), + parser.add_option("-m", "--modulation", type="choice", choices=list(mods.keys()), default='psk', help="Select modulation from: %s [default=%%default]" - % (', '.join(mods.keys()),)) + % (', '.join(list(mods.keys())),)) parser.add_option("", "--amplitude", type="eng_float", default=0.2, help="set Tx amplitude (0-1) (default=%default)") parser.add_option("-r", "--bitrate", type="eng_float", default=250e3, @@ -116,7 +118,7 @@ def get_options(mods): uhd_transmitter.add_options(parser) - for mod in mods.values(): + for mod in list(mods.values()): mod.add_options(parser) (options, args) = parser.parse_args() diff --git a/gr-digital/examples/narrowband/receive_path.py b/gr-digital/examples/narrowband/receive_path.py index 8bbfe92770..f4d0dcc1ea 100644 --- a/gr-digital/examples/narrowband/receive_path.py +++ b/gr-digital/examples/narrowband/receive_path.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2005-2007,2011 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. -# +# + +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, gru, filter from gnuradio import eng_notation @@ -34,10 +38,10 @@ import sys class receive_path(gr.hier_block2): def __init__(self, demod_class, rx_callback, options): - gr.hier_block2.__init__(self, "receive_path", - gr.io_signature(1, 1, gr.sizeof_gr_complex), - gr.io_signature(0, 0, 0)) - + gr.hier_block2.__init__(self, "receive_path", + gr.io_signature(1, 1, gr.sizeof_gr_complex), + gr.io_signature(0, 0, 0)) + options = copy.copy(options) # make a copy so we can destructively modify self._verbose = options.verbose @@ -56,10 +60,10 @@ class receive_path(gr.hier_block2): # Make sure the channel BW factor is between 1 and sps/2 # or the filter won't work. - if(self._chbw_factor < 1.0 or self._chbw_factor > self.samples_per_symbol()/2): - sys.stderr.write("Channel bandwidth factor ({0}) must be within the range [1.0, {1}].\n".format(self._chbw_factor, self.samples_per_symbol()/2)) + if(self._chbw_factor < 1.0 or self._chbw_factor > self.samples_per_symbol() / 2): + sys.stderr.write("Channel bandwidth factor ({0}) must be within the range [1.0, {1}].\n".format(self._chbw_factor, self.samples_per_symbol() / 2)) sys.exit(1) - + # Design filter to get actual channel we want sw_decim = 1 chan_coeffs = filter.firdes.low_pass(1.0, # gain @@ -68,7 +72,7 @@ class receive_path(gr.hier_block2): 0.5, # width of trans. band filter.firdes.WIN_HANN) # filter type self.channel_filter = filter.fft_filter_ccc(sw_decim, chan_coeffs) - + # receiver self.packet_receiver = \ digital.demod_pkts(self.demodulator, @@ -85,8 +89,8 @@ class receive_path(gr.hier_block2): if self._verbose: self._print_verbage() - # connect block input to channel filter - self.connect(self, self.channel_filter) + # connect block input to channel filter + self.connect(self, self.channel_filter) # connect the channel input filter to the carrier power detector self.connect(self.channel_filter, self.probe) @@ -145,8 +149,8 @@ class receive_path(gr.hier_block2): """ Prints information about the receive path """ - print "\nReceive Path:" - print "modulation: %s" % (self._demod_class.__name__) - print "bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate)) - print "samples/symbol: %.4f" % (self.samples_per_symbol()) - print "Differential: %s" % (self.differential()) + print("\nReceive Path:") + print("modulation: %s" % (self._demod_class.__name__)) + print("bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate))) + print("samples/symbol: %.4f" % (self.samples_per_symbol())) + print("Differential: %s" % (self.differential())) diff --git a/gr-digital/examples/narrowband/rx_voice.py b/gr-digital/examples/narrowband/rx_voice.py index 8a0e9844be..16e4eb20ad 100755..100644 --- a/gr-digital/examples/narrowband/rx_voice.py +++ b/gr-digital/examples/narrowband/rx_voice.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2005,2006,2009,2011,2013 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. -# +# + +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, audio, uhd from gnuradio import blocks @@ -40,24 +44,24 @@ from receive_path import receive_path from uhd_interface import uhd_receiver #import os -#print os.getpid() +#print(os.getpid()) #raw_input('Attach and press enter') class audio_tx(gr.hier_block2): def __init__(self, audio_output_dev): - gr.hier_block2.__init__(self, "audio_tx", - gr.io_signature(0, 0, 0), # Input signature - gr.io_signature(0, 0, 0)) # Output signature - + gr.hier_block2.__init__(self, "audio_tx", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(0, 0, 0)) # Output signature + self.sample_rate = sample_rate = 8000 self.packet_src = blocks.message_source(33) voice_decoder = vocoder.gsm_fr_decode_ps() s2f = blocks.short_to_float() - sink_scale = blocks.multiply_const_ff(1.0/32767.) + sink_scale = blocks.multiply_const_ff(1.0 / 32767.) audio_sink = audio.sink(sample_rate, audio_output_dev) self.connect(self.packet_src, voice_decoder, s2f, sink_scale, audio_sink) - + def msgq(self): return self.packet_src.msgq() @@ -79,7 +83,7 @@ class my_top_block(gr.top_block): usrp_rate = self.source.get_sample_rate() rrate = audio_rate / usrp_rate self.resampler = filter.pfb.arb_resampler_ccf(rrate) - + self.connect(self.source, self.resampler, self.rxpath) elif(options.from_file is not None): @@ -92,7 +96,7 @@ class my_top_block(gr.top_block): self.source = blocks.null_source(gr.sizeof_gr_complex) self.connect(self.source, self.thr, self.rxpath) - self.connect(self.audio_tx) + self.connect(self.audio_tx) # ///////////////////////////////////////////////////////////////////////////// # main @@ -105,7 +109,7 @@ def main(): n_rcvd = 0 n_right = 0 - + def rx_callback(ok, payload): global n_rcvd, n_right n_rcvd += 1 @@ -113,9 +117,8 @@ def main(): n_right += 1 tb.audio_tx.msgq().insert_tail(gr.message_from_string(payload)) - - print "ok = %r n_rcvd = %4d n_right = %4d" % ( - ok, n_rcvd, n_right) + + print("ok = %r n_rcvd = %4d n_right = %4d" % (ok, n_rcvd, n_right)) demods = digital.modulation_utils.type_1_demods() @@ -123,10 +126,10 @@ def main(): parser = OptionParser (option_class=eng_option, conflict_handler="resolve") expert_grp = parser.add_option_group("Expert") - parser.add_option("-m", "--modulation", type="choice", choices=demods.keys(), + parser.add_option("-m", "--modulation", type="choice", choices=list(demods.keys()), default='gmsk', help="Select modulation from: %s [default=%%default]" - % (', '.join(demods.keys()),)) + % (', '.join(list(demods.keys())),)) parser.add_option("-O", "--audio-output", type="string", default="", help="pcm output device name. E.g., hw:0,0 or /dev/dsp") parser.add_option("","--from-file", default=None, @@ -134,7 +137,7 @@ def main(): receive_path.add_options(parser, expert_grp) uhd_receiver.add_options(parser) - for mod in demods.values(): + for mod in list(demods.values()): mod.add_options(expert_grp) parser.set_defaults(bitrate=50e3) # override default bitrate default @@ -156,7 +159,7 @@ def main(): r = gr.enable_realtime_scheduling() if r != gr.RT_OK: - print "Warning: Failed to enable realtime scheduling." + print("Warning: Failed to enable realtime scheduling.") tb.run() diff --git a/gr-digital/examples/narrowband/transmit_path.py b/gr-digital/examples/narrowband/transmit_path.py index 70b4044e52..c451f64365 100644 --- a/gr-digital/examples/narrowband/transmit_path.py +++ b/gr-digital/examples/narrowband/transmit_path.py @@ -1,23 +1,26 @@ # # Copyright 2005-2007,2011 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. -# +# + +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr from gnuradio import eng_notation @@ -36,10 +39,10 @@ class transmit_path(gr.hier_block2): ''' See below for what options should hold ''' - gr.hier_block2.__init__(self, "transmit_path", - gr.io_signature(0,0,0), - gr.io_signature(1,1,gr.sizeof_gr_complex)) - + gr.hier_block2.__init__(self, "transmit_path", + gr.io_signature(0,0,0), + gr.io_signature(1,1,gr.sizeof_gr_complex)) + options = copy.copy(options) # make a copy so we can destructively modify self._verbose = options.verbose @@ -49,10 +52,10 @@ class transmit_path(gr.hier_block2): # Get mod_kwargs mod_kwargs = self._modulator_class.extract_kwargs_from_options(options) - + # transmitter - self.modulator = self._modulator_class(**mod_kwargs) - + self.modulator = self._modulator_class(**mod_kwargs) + self.packet_transmitter = \ digital.mod_pkts(self.modulator, access_code=None, @@ -72,19 +75,19 @@ class transmit_path(gr.hier_block2): def set_tx_amplitude(self, ampl): """ Sets the transmit amplitude sent to the USRP in volts - + Args: : ampl 0 <= ampl < 1. """ self._tx_amplitude = max(0.0, min(ampl, 1)) self.amp.set_k(self._tx_amplitude) - + def send_pkt(self, payload='', eof=False): """ Calls the transmitter method to send a packet """ return self.packet_transmitter.send_pkt(payload, eof) - + def bitrate(self): return self._bitrate @@ -120,8 +123,8 @@ class transmit_path(gr.hier_block2): """ Prints information about the transmit path """ - print "Tx amplitude %s" % (self._tx_amplitude) - print "modulation: %s" % (self._modulator_class.__name__) - print "bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate)) - print "samples/symbol: %.4f" % (self.samples_per_symbol()) - print "Differential: %s" % (self.differential()) + print("Tx amplitude %s" % (self._tx_amplitude)) + print("modulation: %s" % (self._modulator_class.__name__)) + print("bitrate: %sb/s" % (eng_notation.num_to_str(self._bitrate))) + print("samples/symbol: %.4f" % (self.samples_per_symbol())) + print("Differential: %s" % (self.differential())) diff --git a/gr-digital/examples/narrowband/tunnel.py b/gr-digital/examples/narrowband/tunnel.py index 7b9b69cc8a..da00baa900 100755..100644 --- a/gr-digital/examples/narrowband/tunnel.py +++ b/gr-digital/examples/narrowband/tunnel.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2005,2006,2009,2011 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. -# +# + +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals # //////////////////////////////////////////////////////////////////// @@ -49,7 +53,7 @@ from uhd_interface import uhd_receiver import os, sys import random, time, struct -#print os.getpid() +#print(os.getpid()) #raw_input('Attach and press enter') # //////////////////////////////////////////////////////////////////// @@ -71,7 +75,7 @@ IFF_ONE_QUEUE = 0x2000 # beats me ;) def open_tun_interface(tun_device_filename): from fcntl import ioctl - + mode = IFF_TAP | IFF_NO_PI TUNSETIFF = 0x400454ca @@ -79,7 +83,7 @@ def open_tun_interface(tun_device_filename): ifs = ioctl(tun, TUNSETIFF, struct.pack("16sH", "gr%d", mode)) ifname = ifs[:16].strip("\x00") return (tun, ifname) - + # //////////////////////////////////////////////////////////////////// # the flow graph @@ -94,20 +98,20 @@ class my_top_block(gr.top_block): # Get the modulation's bits_per_symbol args = mod_class.extract_kwargs_from_options(options) - symbol_rate = options.bitrate / mod_class(**args).bits_per_symbol() + symbol_rate = options.bitrate / mod_class(**args.bits_per_symbol()) self.source = uhd_receiver(options.args, symbol_rate, options.samples_per_symbol, options.rx_freq, options.rx_gain, options.spec, options.antenna, options.verbose) - + self.sink = uhd_transmitter(options.args, symbol_rate, options.samples_per_symbol, options.tx_freq, options.tx_gain, options.spec, options.antenna, options.verbose) - + options.samples_per_symbol = self.source._sps self.txpath = transmit_path(mod_class, options) @@ -131,7 +135,7 @@ class my_top_block(gr.top_block): self.sink.set_freq(target_freq) self.source.set_freq(target_freq) - + # //////////////////////////////////////////////////////////////////// # Carrier Sense MAC @@ -166,7 +170,7 @@ class cs_mac(object): payload: contents of the packet (string) """ if self.verbose: - print "Rx: ok = %r len(payload) = %4d" % (ok, len(payload)) + print("Rx: ok = %r len(payload) = %4d" % (ok, len(payload))) if ok: os.write(self.tun_fd, payload) @@ -186,7 +190,7 @@ class cs_mac(object): break if self.verbose: - print "Tx: len(payload) = %4d" % (len(payload),) + print("Tx: len(payload) = %4d" % (len(payload),)) delay = min_delay while self.tb.carrier_sensed(): @@ -209,10 +213,10 @@ def main(): parser = OptionParser (option_class=eng_option, conflict_handler="resolve") expert_grp = parser.add_option_group("Expert") - parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(), + parser.add_option("-m", "--modulation", type="choice", choices=list(mods.keys()), default='gmsk', help="Select modulation from: %s [default=%%default]" - % (', '.join(mods.keys()),)) + % (', '.join(list(mods.keys())),)) parser.add_option("-s", "--size", type="eng_float", default=1500, help="set packet size [default=%default]") @@ -227,10 +231,10 @@ def main(): uhd_receiver.add_options(parser) uhd_transmitter.add_options(parser) - for mod in mods.values(): + for mod in list(mods.values()): mod.add_options(expert_grp) - for demod in demods.values(): + for demod in list(demods.values()): demod.add_options(expert_grp) (options, args) = parser.parse_args () @@ -247,7 +251,7 @@ def main(): realtime = True else: realtime = False - print "Note: failed to enable realtime scheduling" + print("Note: failed to enable realtime scheduling") # instantiate the MAC mac = cs_mac(tun_fd, verbose=True) @@ -261,26 +265,26 @@ def main(): mac.set_top_block(tb) # give the MAC a handle for the PHY if tb.txpath.bitrate() != tb.rxpath.bitrate(): - print "WARNING: Transmit bitrate = %sb/sec, Receive bitrate = %sb/sec" % ( + print("WARNING: Transmit bitrate = %sb/sec, Receive bitrate = %sb/sec" % ( eng_notation.num_to_str(tb.txpath.bitrate()), - eng_notation.num_to_str(tb.rxpath.bitrate())) - - print "modulation: %s" % (options.modulation,) - print "freq: %s" % (eng_notation.num_to_str(options.tx_freq)) - print "bitrate: %sb/sec" % (eng_notation.num_to_str(tb.txpath.bitrate()),) - print "samples/symbol: %3d" % (tb.txpath.samples_per_symbol(),) + eng_notation.num_to_str(tb.rxpath.bitrate()))) + + print("modulation: %s" % (options.modulation,)) + print("freq: %s" % (eng_notation.num_to_str(options.tx_freq))) + print("bitrate: %sb/sec" % (eng_notation.num_to_str(tb.txpath.bitrate()),)) + print("samples/symbol: %3d" % (tb.txpath.samples_per_symbol(),)) tb.rxpath.set_carrier_threshold(options.carrier_threshold) - print "Carrier sense threshold:", options.carrier_threshold, "dB" - - print - print "Allocated virtual ethernet interface: %s" % (tun_ifname,) - print "You must now use ifconfig to set its IP address. E.g.," - print - print " $ sudo ifconfig %s 192.168.200.1" % (tun_ifname,) - print - print "Be sure to use a different address in the same subnet for each machine." - print + print("Carrier sense threshold:", options.carrier_threshold, "dB") + + print() + print("Allocated virtual ethernet interface: %s" % (tun_ifname,)) + print("You must now use ifconfig to set its IP address. E.g.,") + print() + print(" $ sudo ifconfig %s 192.168.200.1" % (tun_ifname,)) + print() + print("Be sure to use a different address in the same subnet for each machine.") + print() tb.start() # Start executing the flow graph (runs in separate threads) @@ -289,7 +293,7 @@ def main(): tb.stop() # but if it does, tell flow graph to stop. tb.wait() # wait for it to finish - + if __name__ == '__main__': try: diff --git a/gr-digital/examples/narrowband/tx_voice.py b/gr-digital/examples/narrowband/tx_voice.py index afdb4406e6..e65df64d25 100755..100644 --- a/gr-digital/examples/narrowband/tx_voice.py +++ b/gr-digital/examples/narrowband/tx_voice.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2005-2007,2009,2011,2013 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. -# +# + +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, audio, uhd from gnuradio import eng_notation @@ -40,15 +44,15 @@ from transmit_path import transmit_path from uhd_interface import uhd_transmitter #import os -#print os.getpid() +#print(os.getpid()) #raw_input('Attach and press enter') class audio_rx(gr.hier_block2): def __init__(self, audio_input_dev): - gr.hier_block2.__init__(self, "audio_rx", - gr.io_signature(0, 0, 0), # Input signature - gr.io_signature(0, 0, 0)) # Output signature + gr.hier_block2.__init__(self, "audio_rx", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(0, 0, 0)) # Output signature self.sample_rate = sample_rate = 8000 src = audio.source(sample_rate, audio_input_dev) src_scale = blocks.multiply_const_ff(32767) @@ -60,7 +64,7 @@ class audio_rx(gr.hier_block2): def get_encoded_voice_packet(self): return self.packets_from_encoder.delete_head() - + class my_top_block(gr.top_block): @@ -78,7 +82,7 @@ class my_top_block(gr.top_block): audio_rate = self.audio_rx.sample_rate usrp_rate = self.sink.get_sample_rate() rrate = usrp_rate / audio_rate - + elif(options.to_file is not None): self.sink = blocks.file_sink(gr.sizeof_gr_complex, options.to_file) rrate = 1 @@ -87,10 +91,10 @@ class my_top_block(gr.top_block): rrate = 1 self.resampler = filter.pfb.arb_resampler_ccf(rrate) - - self.connect(self.audio_rx) - self.connect(self.txpath, self.resampler, self.sink) - + + self.connect(self.audio_rx) + self.connect(self.txpath, self.resampler, self.sink) + # ///////////////////////////////////////////////////////////////////////////// # main @@ -102,17 +106,17 @@ def main(): return tb.txpath.send_pkt(payload, eof) def rx_callback(ok, payload): - print "ok = %r, payload = '%s'" % (ok, payload) + print("ok = %r, payload = '%s'" % (ok, payload)) mods = digital.modulation_utils.type_1_mods() parser = OptionParser(option_class=eng_option, conflict_handler="resolve") expert_grp = parser.add_option_group("Expert") - parser.add_option("-m", "--modulation", type="choice", choices=mods.keys(), + parser.add_option("-m", "--modulation", type="choice", choices=list(mods.keys()), default='gmsk', help="Select modulation from: %s [default=%%default]" - % (', '.join(mods.keys()),)) + % (', '.join(list(mods.keys())),)) parser.add_option("-M", "--megabytes", type="eng_float", default=0, help="set megabytes to transmit [default=inf]") parser.add_option("-I", "--audio-input", type="string", default="", @@ -123,7 +127,7 @@ def main(): transmit_path.add_options(parser, expert_grp) uhd_transmitter.add_options(parser) - for mod in mods.values(): + for mod in list(mods.values()): mod.add_options(expert_grp) parser.set_defaults(bitrate=50e3) # override default bitrate default @@ -144,7 +148,7 @@ def main(): r = gr.enable_realtime_scheduling() if r != gr.RT_OK: - print "Warning: failed to enable realtime scheduling" + print("Warning: failed to enable realtime scheduling") tb.start() # start flow graph @@ -161,7 +165,7 @@ def main(): n += len(s) sys.stderr.write('.') pktno += 1 - + send_pkt(eof=True) tb.wait() # wait for it to finish @@ -170,4 +174,4 @@ if __name__ == '__main__': try: main() except KeyboardInterrupt: - pass + pass diff --git a/gr-digital/examples/narrowband/uhd_interface.py b/gr-digital/examples/narrowband/uhd_interface.py index e7c7fe3af0..1da2bbb1bf 100644 --- a/gr-digital/examples/narrowband/uhd_interface.py +++ b/gr-digital/examples/narrowband/uhd_interface.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2010,2011 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. -# +# + +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, uhd from gnuradio import eng_notation @@ -41,10 +45,10 @@ def add_freq_option(parser): help="set Tx and/or Rx frequency to FREQ [default=%default]", metavar="FREQ") -class uhd_interface: +class uhd_interface(object): def __init__(self, istx, args, sym_rate, sps, freq=None, lo_offset=None, gain=None, spec=None, antenna=None, clock_source=None): - + if(istx): self.u = uhd.usrp_sink(device_addr=args, stream_args=uhd.stream_args('fc32')) else: @@ -61,15 +65,15 @@ class uhd_interface: # Set the antenna if(antenna): self.u.set_antenna(antenna, 0) - + self._args = args self._ant = antenna self._spec = spec self._gain = self.set_gain(gain) - self._lo_offset = lo_offset - self._freq = self.set_freq(freq, lo_offset) + self._lo_offset = lo_offset + self._freq = self.set_freq(freq, lo_offset) self._rate, self._sps = self.set_sample_rate(sym_rate, sps) - self._clock_source = clock_source + self._clock_source = clock_source def set_sample_rate(self, sym_rate, req_sps): start_sps = req_sps @@ -78,37 +82,37 @@ class uhd_interface: self.u.set_samp_rate(asked_samp_rate) actual_samp_rate = self.u.get_samp_rate() - sps = actual_samp_rate/sym_rate + sps = actual_samp_rate / sym_rate if(sps < 2): req_sps +=1 else: actual_sps = sps break - + if(sps != req_sps): - print "\nSymbol Rate: %f" % (sym_rate) - print "Requested sps: %f" % (start_sps) - print "Given sample rate: %f" % (actual_samp_rate) - print "Actual sps for rate: %f" % (actual_sps) + print("\nSymbol Rate: %f" % (sym_rate)) + print("Requested sps: %f" % (start_sps)) + print("Given sample rate: %f" % (actual_samp_rate)) + print("Actual sps for rate: %f" % (actual_sps)) if(actual_samp_rate != asked_samp_rate): - print "\nRequested sample rate: %f" % (asked_samp_rate) - print "Actual sample rate: %f" % (actual_samp_rate) + print("\nRequested sample rate: %f" % (asked_samp_rate)) + print("Actual sample rate: %f" % (actual_samp_rate)) return (actual_samp_rate, actual_sps) def get_sample_rate(self): return self.u.get_samp_rate() - + def set_gain(self, gain=None): if gain is None: # if no gain was specified, use the mid-point in dB g = self.u.get_gain_range() - gain = float(g.start()+g.stop())/2 - print "\nNo gain specified." - print "Setting gain to %f (from [%f, %f])" % \ - (gain, g.start(), g.stop()) - + gain = float(g.start()+g.stop()) / 2 + print("\nNo gain specified.") + print("Setting gain to %f (from [%f, %f])" % + (gain, g.start(), g.stop())) + self.u.set_gain(gain, 0) return gain @@ -116,7 +120,7 @@ class uhd_interface: if(freq is None): sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") sys.exit(1) - + r = self.u.set_center_freq(uhd.tune_request(freq, lo_offset)) if r: return freq @@ -163,22 +167,22 @@ class uhd_transmitter(uhd_interface, gr.hier_block2): parser.add_option("", "--tx-gain", type="eng_float", default=None, help="set transmit gain in dB (default is midpoint)") parser.add_option("-C", "--clock-source", type="string", default=None, - help="select clock source (e.g. 'external') [default=%default]") + help="select clock source (e.g. 'external') [default=%default]") parser.add_option("-v", "--verbose", action="store_true", default=False) def _print_verbage(self): """ Prints information about the UHD transmitter """ - print "\nUHD Transmitter:" - print "Args: %s" % (self._args) - print "Freq: %sHz" % (eng_notation.num_to_str(self._freq)) - print "LO Offset: %sHz" % (eng_notation.num_to_str(self._lo_offset)) - print "Gain: %f dB" % (self._gain) - print "Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate)) - print "Antenna: %s" % (self._ant) - print "Subdev Spec: %s" % (self._spec) - print "Clock Source: %s" % (self._clock_source) + print("\nUHD Transmitter:") + print("Args: %s" % (self._args)) + print("Freq: %sHz" % (eng_notation.num_to_str(self._freq))) + print("LO Offset: %sHz" % (eng_notation.num_to_str(self._lo_offset)) ) + print("Gain: %f dB" % (self._gain)) + print("Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate))) + print("Antenna: %s" % (self._ant)) + print("Subdev Spec: %s" % (self._spec)) + print("Clock Source: %s" % (self._clock_source)) #-------------------------------------------------------------------# # RECEIVER @@ -191,7 +195,7 @@ class uhd_receiver(uhd_interface, gr.hier_block2): gr.hier_block2.__init__(self, "uhd_receiver", gr.io_signature(0,0,0), gr.io_signature(1,1,gr.sizeof_gr_complex)) - + # Set up the UHD interface as a receiver uhd_interface.__init__(self, False, args, sym_rate, sps, freq, lo_offset, gain, spec, antenna, clock_source) @@ -214,11 +218,11 @@ class uhd_receiver(uhd_interface, gr.hier_block2): help="set receive frequency to FREQ [default=%default]", metavar="FREQ") parser.add_option("", "--lo-offset", type="eng_float", default=0, - help="set local oscillator offset in Hz (default is 0)") + help="set local oscillator offset in Hz (default is 0)") parser.add_option("", "--rx-gain", type="eng_float", default=None, help="set receive gain in dB (default is midpoint)") parser.add_option("-C", "--clock-source", type="string", default=None, - help="select clock source (e.g. 'external') [default=%default]") + help="select clock source (e.g. 'external') [default=%default]") if not parser.has_option("--verbose"): parser.add_option("-v", "--verbose", action="store_true", default=False) @@ -226,13 +230,13 @@ class uhd_receiver(uhd_interface, gr.hier_block2): """ Prints information about the UHD transmitter """ - print "\nUHD Receiver:" - print "UHD Args: %s" % (self._args) - print "Freq: %sHz" % (eng_notation.num_to_str(self._freq)) - print "LO Offset: %sHz" % (eng_notation.num_to_str(self._lo_offset)) - print "Gain: %f dB" % (self._gain) - print "Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate)) - print "Antenna: %s" % (self._ant) - print "Spec: %s" % (self._spec) - print "Clock Source: %s" % (self._clock_source) + print("\nUHD Receiver:") + print("UHD Args: %s" % (self._args)) + print("Freq: %sHz" % (eng_notation.num_to_str(self._freq))) + print("LO Offset: %sHz" % (eng_notation.num_to_str(self._lo_offset)) ) + print("Gain: %f dB" % (self._gain)) + print("Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate))) + print("Antenna: %s" % (self._ant)) + print("Spec: %s" % (self._spec)) + print("Clock Source: %s" % (self._clock_source)) diff --git a/gr-digital/examples/ofdm/benchmark_add_channel.py b/gr-digital/examples/ofdm/benchmark_add_channel.py index 0ac46985a7..6fc7056dfb 100755..100644 --- a/gr-digital/examples/ofdm/benchmark_add_channel.py +++ b/gr-digital/examples/ofdm/benchmark_add_channel.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2010,2011 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. -# +# + +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, channels from gnuradio import blocks @@ -32,15 +36,15 @@ class my_top_block(gr.top_block): def __init__(self, ifile, ofile, options): gr.top_block.__init__(self) - SNR = 10.0**(options.snr/10.0) + SNR = 10.0**(options.snr / 10.0) time_offset = options.time_offset - phase_offset = options.phase_offset*(math.pi/180.0) + phase_offset = options.phase_offset*(math.pi / 180.0) # calculate noise voltage from SNR power_in_signal = abs(options.tx_amplitude)**2 - noise_power = power_in_signal/SNR + noise_power = power_in_signal / SNR noise_voltage = math.sqrt(noise_power) - print "Noise voltage: ", noise_voltage + print("Noise voltage: ", noise_voltage) frequency_offset = options.frequency_offset / options.fft_length @@ -54,7 +58,7 @@ class my_top_block(gr.top_block): self.snk = blocks.file_sink(gr.sizeof_gr_complex, ofile) self.connect(self.src, self.channel, self.phase, self.snk) - + # ///////////////////////////////////////////////////////////////////////////// # main @@ -94,13 +98,13 @@ def main(): ifile = args[0] ofile = args[1] - + # build the graph tb = my_top_block(ifile, ofile, options) r = gr.enable_realtime_scheduling() if r != gr.RT_OK: - print "Warning: Failed to enable realtime scheduling." + print("Warning: Failed to enable realtime scheduling.") tb.start() # start flow graph tb.wait() # wait for it to finish diff --git a/gr-digital/examples/ofdm/receive_path.py b/gr-digital/examples/ofdm/receive_path.py index 0cb4479a2e..b9abe8cebc 100644 --- a/gr-digital/examples/ofdm/receive_path.py +++ b/gr-digital/examples/ofdm/receive_path.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2005,2006,2011 Free Software Foundation, Inc. # diff --git a/gr-digital/examples/ofdm/transmit_path.py b/gr-digital/examples/ofdm/transmit_path.py index 98a81f3c1a..17adffab44 100644 --- a/gr-digital/examples/ofdm/transmit_path.py +++ b/gr-digital/examples/ofdm/transmit_path.py @@ -1,23 +1,26 @@ # # Copyright 2005,2006,2011 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. -# +# + +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr from gnuradio import eng_notation @@ -31,15 +34,15 @@ import sys # transmit path # ///////////////////////////////////////////////////////////////////////////// -class transmit_path(gr.hier_block2): +class transmit_path(gr.hier_block2): def __init__(self, options): ''' See below for what options should hold ''' - gr.hier_block2.__init__(self, "transmit_path", - gr.io_signature(0, 0, 0), - gr.io_signature(1, 1, gr.sizeof_gr_complex)) + gr.hier_block2.__init__(self, "transmit_path", + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, gr.sizeof_gr_complex)) options = copy.copy(options) # make a copy so we can destructively modify @@ -63,13 +66,13 @@ class transmit_path(gr.hier_block2): def set_tx_amplitude(self, ampl): """ Sets the transmit amplitude sent to the USRP - + Args: : ampl 0 <= ampl < 1.0. Try 0.10 """ self._tx_amplitude = max(0.0, min(ampl, 1)) self.amp.set_k(self._tx_amplitude) - + def send_pkt(self, payload='', eof=False): """ Calls the transmitter method to send a packet @@ -97,5 +100,5 @@ class transmit_path(gr.hier_block2): """ Prints information about the transmit path """ - print "Tx amplitude %s" % (self._tx_amplitude) - + print("Tx amplitude %s" % (self._tx_amplitude)) + diff --git a/gr-digital/examples/ofdm/uhd_interface.py b/gr-digital/examples/ofdm/uhd_interface.py index ac34d956ae..df5be60f30 100644 --- a/gr-digital/examples/ofdm/uhd_interface.py +++ b/gr-digital/examples/ofdm/uhd_interface.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2010,2011 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. -# +# + +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, uhd from gnuradio import eng_notation @@ -41,17 +45,17 @@ def add_freq_option(parser): help="set Tx and/or Rx frequency to FREQ [default=%default]", metavar="FREQ") -class uhd_interface: +class uhd_interface(object): def __init__(self, istx, args, bandwidth, freq=None, lo_offset=None, gain=None, spec=None, antenna=None, clock_source=None): - + if(istx): self.u = uhd.usrp_sink(device_addr=args, stream_args=uhd.stream_args('fc32')) else: self.u = uhd.usrp_source(device_addr=args, stream_args=uhd.stream_args('fc32')) # Set clock source to external. - if(clock_source): + if(clock_source): self.u.set_clock_source(clock_source, 0) # Set the subdevice spec @@ -61,7 +65,7 @@ class uhd_interface: # Set the antenna if(antenna): self.u.set_antenna(antenna, 0) - + self._args = args self._ant = antenna self._spec = spec @@ -74,21 +78,21 @@ class uhd_interface: def set_sample_rate(self, bandwidth): self.u.set_samp_rate(bandwidth) actual_bw = self.u.get_samp_rate() - + return actual_bw def get_sample_rate(self): return self.u.get_samp_rate() - + def set_gain(self, gain=None): if gain is None: # if no gain was specified, use the mid-point in dB g = self.u.get_gain_range() - gain = float(g.start()+g.stop())/2 - print "\nNo gain specified." - print "Setting gain to %f (from [%f, %f])" % \ - (gain, g.start(), g.stop()) - + gain = float(g.start()+g.stop()) / 2 + print("\nNo gain specified.") + print("Setting gain to %f (from [%f, %f])" % + (gain, g.start(), g.stop())) + self.u.set_gain(gain, 0) return gain @@ -96,7 +100,7 @@ class uhd_interface: if(freq is None): sys.stderr.write("You must specify -f FREQ or --freq FREQ\n") sys.exit(1) - + r = self.u.set_center_freq(uhd.tune_request(freq, lo_offset)) if r: @@ -151,15 +155,15 @@ class uhd_transmitter(uhd_interface, gr.hier_block2): """ Prints information about the UHD transmitter """ - print "\nUHD Transmitter:" - print "UHD Args: %s" % (self._args) - print "Freq: %sHz" % (eng_notation.num_to_str(self._freq)) - print "LO Offset: %sHz" % (eng_notation.num_to_str(self._lo_offset)) - print "Gain: %f dB" % (self._gain) - print "Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate)) - print "Antenna: %s" % (self._ant) - print "Subdev Sec: %s" % (self._spec) - print "Clock Source: %s" % (self._clock_source) + print("\nUHD Transmitter:") + print("UHD Args: %s" % (self._args)) + print("Freq: %sHz" % (eng_notation.num_to_str(self._freq))) + print("LO Offset: %sHz" % (eng_notation.num_to_str(self._lo_offset))) + print("Gain: %f dB" % (self._gain)) + print("Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate))) + print("Antenna: %s" % (self._ant)) + print("Subdev Sec: %s" % (self._spec)) + print("Clock Source: %s" % (self._clock_source)) @@ -174,7 +178,7 @@ class uhd_receiver(uhd_interface, gr.hier_block2): gr.hier_block2.__init__(self, "uhd_receiver", gr.io_signature(0,0,0), gr.io_signature(1,1,gr.sizeof_gr_complex)) - + # Set up the UHD interface as a receiver uhd_interface.__init__(self, False, args, bandwidth, freq, lo_offset, gain, spec, antenna, clock_source) @@ -209,13 +213,13 @@ class uhd_receiver(uhd_interface, gr.hier_block2): """ Prints information about the UHD transmitter """ - print "\nUHD Receiver:" - print "UHD Args: %s" % (self._args) - print "Freq: %sHz" % (eng_notation.num_to_str(self._freq)) - print "LO Offset: %sHz" % (eng_notation.num_to_str(self._lo_offset)) - print "Gain: %f dB" % (self._gain) - print "Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate)) - print "Antenna: %s" % (self._ant) - print "Subdev Sec: %s" % (self._spec) - print "Clock Source: %s" % (self._clock_source) + print("\nUHD Receiver:") + print("UHD Args: %s" % (self._args)) + print("Freq: %sHz" % (eng_notation.num_to_str(self._freq))) + print("LO Offset: %sHz" % (eng_notation.num_to_str(self._lo_offset))) + print("Gain: %f dB" % (self._gain)) + print("Sample Rate: %ssps" % (eng_notation.num_to_str(self._rate))) + print("Antenna: %s" % (self._ant)) + print("Subdev Sec: %s" % (self._spec)) + print("Clock Source: %s" % (self._clock_source)) diff --git a/gr-digital/examples/run_length.py b/gr-digital/examples/run_length.py index 5020655dbb..a122a2b8eb 100755..100644 --- a/gr-digital/examples/run_length.py +++ b/gr-digital/examples/run_length.py @@ -1,24 +1,27 @@ #!/usr/bin/env python # # Copyright 2007 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. -# +# + +from __future__ import print_function +from __future__ import unicode_literals from optparse import OptionParser import sys @@ -30,9 +33,9 @@ def main(): (options, args) = parser.parse_args() if options.file == None: - print "Must specify file to read from using '-f'." + print("Must specify file to read from using '-f'.") sys.exit(1) - print "Using", options.file, "for data." + print("Using", options.file, "for data.") f = open(options.file, 'r') runs = [] @@ -40,7 +43,7 @@ def main(): current = 0 bytes = 0 bits = 0 - + for ch in f.read(): x = ord(ch) bytes = bytes + 1 @@ -66,18 +69,16 @@ def main(): runs[count-1] = runs[count-1] + 1 chk = 0 - print "Bytes read: ", bytes - print "Bits read: ", bits - print + print("Bytes read: ", bytes) + print("Bits read: ", bits) + print() for i in range(len(runs)): chk = chk + runs[i]*(i+1) - print "Runs of length", i+1, ":", runs[i] - print - print "Sum of runs:", chk, "bits" - print - print "Maximum run length is", len(runs), "bits" + print("Runs of length", i+1, ":", runs[i]) + print() + print("Sum of runs:", chk, "bits") + print() + print("Maximum run length is", len(runs), "bits") if __name__ == "__main__": main() - - diff --git a/gr-digital/examples/snr_estimators.py b/gr-digital/examples/snr_estimators.py index 31efe6b83e..b1decd84d8 100755..100644 --- a/gr-digital/examples/snr_estimators.py +++ b/gr-digital/examples/snr_estimators.py @@ -20,19 +20,23 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + import sys try: import scipy from scipy import stats except ImportError: - print "Error: Program requires scipy (www.scipy.org)." + print("Error: Program requires scipy (www.scipy.org).") sys.exit(1) try: import pylab except ImportError: - print "Error: Program requires Matplotlib (matplotlib.sourceforge.net)." + print("Error: Program requires Matplotlib (matplotlib.sourceforge.net).") sys.exit(1) from gnuradio import gr, digital, filter @@ -55,7 +59,7 @@ def online_skewness(data): M2 = 0 M3 = 0 - for n in xrange(len(data)): + for n in range(len(data)): delta = data[n] - mean delta_n = delta / (n+1) term1 = delta * delta_n * n @@ -63,12 +67,12 @@ def online_skewness(data): M3 = M3 + term1 * delta_n * (n - 1) - 3 * delta_n * M2 M2 = M2 + term1 - return scipy.sqrt(len(data))*M3 / scipy.power(M2, 3.0/2.0); + return scipy.sqrt(len(data))*M3 / scipy.power(M2, 3.0 / 2.0); def snr_est_simple(signal): s = scipy.mean(abs(signal)**2) n = 2*scipy.var(abs(signal)) - snr_rat = s/n + snr_rat = s / n return 10.0*scipy.log10(snr_rat), snr_rat def snr_est_skew(signal): @@ -94,11 +98,11 @@ def snr_est_svr(signal): N = len(signal) ssum = 0 msum = 0 - for i in xrange(1, N): + for i in range(1, N): ssum += (abs(signal[i])**2)*(abs(signal[i-1])**2) msum += (abs(signal[i])**4) - savg = (1.0/(float(N)-1.0))*ssum - mavg = (1.0/(float(N)-1.0))*msum + savg = (1.0 / (float(N-1.0)))*ssum + mavg = (1.0 / (float(N-1.0)))*msum beta = savg / (mavg - savg) snr_rat = ((beta - 1) + scipy.sqrt(beta*(beta-1))) @@ -126,9 +130,9 @@ def main(): parser.add_option("", "--snr-step", type="float", default=0.5, help="SNR step amount [default=%default]") parser.add_option("-t", "--type", type="choice", - choices=gr_estimators.keys(), default="simple", + choices=list(gr_estimators.keys()), default="simple", help="Estimator type {0} [default=%default]".format( - gr_estimators.keys())) + list(gr_estimators.keys()))) (options, args) = parser.parse_args () N = options.nsamples @@ -155,14 +159,14 @@ def main(): SNR_step = options.snr_step SNR_dB = scipy.arange(SNR_min, SNR_max+SNR_step, SNR_step) for snr in SNR_dB: - SNR = 10.0**(snr/10.0) + SNR = 10.0**(snr / 10.0) scale = scipy.sqrt(2*SNR) - yy = bits + n_cpx/scale - print "SNR: ", snr + yy = bits + n_cpx / scale + print("SNR: ", snr) Sknown = scipy.mean(yy**2) - Nknown = scipy.var(n_cpx/scale) - snr0 = Sknown/Nknown + Nknown = scipy.var(n_cpx / scale) + snr0 = Sknown / Nknown snr0dB = 10.0*scipy.log10(snr0) snr_known.append(float(snr0dB)) @@ -171,7 +175,7 @@ def main(): gr_src = blocks.vector_source_c(bits.tolist(), False) gr_snr = digital.mpsk_snr_est_cc(gr_est, ntag, 0.001) - gr_chn = channels.channel_model(1.0/scale) + gr_chn = channels.channel_model(1.0 / scale) gr_snk = blocks.null_sink(gr.sizeof_gr_complex) tb = gr.top_block() tb.connect(gr_src, gr_chn, gr_snr, gr_snk) diff --git a/gr-digital/python/digital/CMakeLists.txt b/gr-digital/python/digital/CMakeLists.txt index 8f88948a2e..e9d58491c4 100644 --- a/gr-digital/python/digital/CMakeLists.txt +++ b/gr-digital/python/digital/CMakeLists.txt @@ -78,6 +78,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-digital/python/digital/__init__.py b/gr-digital/python/digital/__init__.py index 79b740644d..90aa413a25 100644 --- a/gr-digital/python/digital/__init__.py +++ b/gr-digital/python/digital/__init__.py @@ -1,59 +1,63 @@ # Copyright 2011-2013 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. -# +# ''' Blocks and utilities for digital modulation and demodulation. ''' +from __future__ import absolute_import +from __future__ import unicode_literals + # The presence of this file turns this directory into a Python package import os try: - from digital_swig import * + from .digital_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from digital_swig import * -from psk import * -from qam import * -from qamlike import * -from bpsk import * -from qpsk import * -from gmsk import * -from gfsk import * -from cpm import * -from pkt import * -from crc import * -from modulation_utils import * -from ofdm import * -from ofdm_receiver import * -from ofdm_sync_fixed import * -from ofdm_sync_ml import * -from ofdm_sync_pnac import * -from ofdm_sync_pn import * -from ofdm_txrx import ofdm_tx, ofdm_rx -from soft_dec_lut_gen import * -from psk_constellations import * -from qam_constellations import * -from constellation_map_generator import * + from .digital_swig import * + +from .psk import * +from .qam import * +from .qamlike import * +from .bpsk import * +from .qpsk import * +from .gmsk import * +from .gfsk import * +from .cpm import * +from .pkt import * +from .crc import * +from .modulation_utils import * +from .ofdm import * +from .ofdm_receiver import * +from .ofdm_sync_fixed import * +from .ofdm_sync_ml import * +from .ofdm_sync_pnac import * +from .ofdm_sync_pn import * +from .ofdm_txrx import ofdm_tx, ofdm_rx +from .soft_dec_lut_gen import * +from .psk_constellations import * +from .qam_constellations import * +from .constellation_map_generator import * -import packet_utils -import ofdm_packet_utils +from . import packet_utils +from . import ofdm_packet_utils diff --git a/gr-digital/python/digital/bpsk.py b/gr-digital/python/digital/bpsk.py index 2ecaac3386..6193622be8 100644 --- a/gr-digital/python/digital/bpsk.py +++ b/gr-digital/python/digital/bpsk.py @@ -23,14 +23,17 @@ BPSK modulation and demodulation. """ +from __future__ import absolute_import +from __future__ import unicode_literals + from math import pi, log from cmath import exp from gnuradio import gr from gnuradio.digital.generic_mod_demod import generic_mod, generic_demod from gnuradio.digital.generic_mod_demod import shared_mod_args, shared_demod_args -import digital_swig -import modulation_utils +from . import digital_swig +from . import modulation_utils # ///////////////////////////////////////////////////////////////////////////// # BPSK constellation diff --git a/gr-digital/python/digital/constellation_map_generator.py b/gr-digital/python/digital/constellation_map_generator.py index 1dedd81280..bd4158194f 100644 --- a/gr-digital/python/digital/constellation_map_generator.py +++ b/gr-digital/python/digital/constellation_map_generator.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals def constellation_map_generator(basis_cpoints, basis_symbols, k, pi): ''' Uses the a basis constellation provided (e.g., from diff --git a/gr-digital/python/digital/cpm.py b/gr-digital/python/digital/cpm.py index 322c3f0bfc..0752f01d66 100644 --- a/gr-digital/python/digital/cpm.py +++ b/gr-digital/python/digital/cpm.py @@ -1,37 +1,44 @@ # -# CPM modulation and demodulation. +# CPM modulation and demodulation. # # # Copyright 2005-2007,2011 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. -# +# + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals # See gnuradio-examples/python/digital for examples + +from math import pi +import numpy + from gnuradio import gr, filter from gnuradio import analog from gnuradio import blocks -from math import pi -import numpy +from . import digital_swig +from . import modulation_utils -import digital_swig -import modulation_utils # default values (used in __init__ and add_options) _def_samples_per_symbol = 2 @@ -53,16 +60,16 @@ _def_log = False class cpm_mod(gr.hier_block2): """ Hierarchical block for Continuous Phase modulation. - + The input is a byte stream (unsigned char) representing packed bits and the output is the complex modulated signal at baseband. - + See Proakis for definition of generic CPM signals: s(t)=exp(j phi(t)) phi(t)= 2 pi h int_0^t f(t') dt' f(t)=sum_k a_k g(t-kT) (normalizing assumption: int_0^infty g(t) dt = 1/2) - + Args: samples_per_symbol: samples per baud >= 2 (integer) bits_per_symbol: bits per symbol (integer) @@ -76,21 +83,21 @@ class cpm_mod(gr.hier_block2): debug: Print modulation data to files? (boolean) """ - def __init__(self, + def __init__(self, samples_per_symbol=_def_samples_per_symbol, bits_per_symbol=_def_bits_per_symbol, h_numerator=_def_h_numerator, h_denominator=_def_h_denominator, cpm_type=_def_cpm_type, - bt=_def_bt, - symbols_per_pulse=_def_symbols_per_pulse, + bt=_def_bt, + symbols_per_pulse=_def_symbols_per_pulse, generic_taps=_def_generic_taps, verbose=_def_verbose, log=_def_log): - gr.hier_block2.__init__(self, "cpm_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + gr.hier_block2.__init__(self, "cpm_mod", + gr.io_signature(1, 1, gr.sizeof_char), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._samples_per_symbol = samples_per_symbol self._bits_per_symbol = bits_per_symbol @@ -99,29 +106,29 @@ class cpm_mod(gr.hier_block2): self._cpm_type = cpm_type self._bt=bt if cpm_type == 0 or cpm_type == 2 or cpm_type == 3: # CPFSK, RC, Generic - self._symbols_per_pulse = symbols_per_pulse + self._symbols_per_pulse = symbols_per_pulse elif cpm_type == 1: # GMSK - self._symbols_per_pulse = 4 + self._symbols_per_pulse = 4 else: - raise TypeError, ("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,)) + raise TypeError("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,)) self._generic_taps=numpy.array(generic_taps) if samples_per_symbol < 2: - raise TypeError, ("samples_per_symbol must be >= 2, is %r" % (samples_per_symbol,)) + raise TypeError("samples_per_symbol must be >= 2, is %r" % (samples_per_symbol,)) self.nsymbols = 2**bits_per_symbol self.sym_alphabet = numpy.arange(-(self.nsymbols-1),self.nsymbols,2).tolist() - self.ntaps = int(self._symbols_per_pulse * samples_per_symbol) - sensitivity = 2 * pi * h_numerator / h_denominator / samples_per_symbol + self.ntaps = int(self._symbols_per_pulse * samples_per_symbol) + sensitivity = 2 * pi * h_numerator / h_denominator / samples_per_symbol # Unpack Bytes into bits_per_symbol groups self.B2s = blocks.packed_to_unpacked_bb(bits_per_symbol,gr.GR_MSB_FIRST) - - - # Turn it into symmetric PAM data. + + + # Turn it into symmetric PAM data. self.pam = digital_swig.chunks_to_symbols_bf(self.sym_alphabet,1) # Generate pulse (sum of taps = samples_per_symbol/2) @@ -129,72 +136,72 @@ class cpm_mod(gr.hier_block2): self.taps= (1.0/self._symbols_per_pulse/2,) * self.ntaps elif cpm_type == 1: # GMSK gaussian_taps = filter.firdes.gaussian( - 1.0/2, # gain + 1.0 / 2, # gain samples_per_symbol, # symbol_rate bt, # bandwidth * symbol time self.ntaps # number of taps ) - sqwave = (1,) * samples_per_symbol # rectangular window - self.taps = numpy.convolve(numpy.array(gaussian_taps),numpy.array(sqwave)) + sqwave = (1,) * samples_per_symbol # rectangular window + self.taps = numpy.convolve(numpy.array(gaussian_taps),numpy.array(sqwave)) elif cpm_type == 2: # Raised Cosine # generalize it for arbitrary roll-off factor - self.taps = (1-numpy.cos(2*pi*numpy.arange(0,self.ntaps)/samples_per_symbol/self._symbols_per_pulse))/(2*self._symbols_per_pulse) + self.taps = (1-numpy.cos(2*pi*numpy.arange(0 / self.ntaps/samples_per_symbol/self._symbols_per_pulse)),(2*self._symbols_per_pulse)) elif cpm_type == 3: # Generic CPM self.taps = generic_taps else: - raise TypeError, ("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,)) + raise TypeError("cpm_type must be an integer in {0,1,2,3}, is %r" % (cpm_type,)) self.filter = filter.pfb.arb_resampler_fff(samples_per_symbol, self.taps) - # FM modulation - self.fmmod = analog.frequency_modulator_fc(sensitivity) - + # FM modulation + self.fmmod = analog.frequency_modulator_fc(sensitivity) + if verbose: self._print_verbage() - + if log: self._setup_logging() - # Connect - self.connect(self, self.B2s, self.pam, self.filter, self.fmmod, self) + # Connect + self.connect(self, self.B2s, self.pam, self.filter, self.fmmod, self) def samples_per_symbol(self): return self._samples_per_symbol - - def bits_per_symbol(self): + + def bits_per_symbol(self): return self._bits_per_symbol - - def h_numerator(self): + + def h_numerator(self): return self._h_numerator - def h_denominator(self): + def h_denominator(self): return self._h_denominator - def cpm_type(self): + def cpm_type(self): return self._cpm_type - def bt(self): + def bt(self): return self._bt - def symbols_per_pulse(self): + def symbols_per_pulse(self): return self._symbols_per_pulse def _print_verbage(self): - print "Samples per symbol = %d" % self._samples_per_symbol - print "Bits per symbol = %d" % self._bits_per_symbol - print "h = " , self._h_numerator , " / " , self._h_denominator - print "Symbol alphabet = " , self.sym_alphabet - print "Symbols per pulse = %d" % self._symbols_per_pulse - print "taps = " , self.taps - - print "CPM type = %d" % self._cpm_type + print("Samples per symbol = %d" % self._samples_per_symbol) + print("Bits per symbol = %d" % self._bits_per_symbol) + print("h = " , self._h_numerator , " / " , self._h_denominator) + print("Symbol alphabet = " , self.sym_alphabet) + print("Symbols per pulse = %d" % self._symbols_per_pulse) + print("taps = " , self.taps) + + print("CPM type = %d" % self._cpm_type) if self._cpm_type == 1: - print "Gaussian filter BT = %.2f" % self._bt + print("Gaussian filter BT = %.2f" % self._bt) def _setup_logging(self): - print "Modulation logging turned on." + print("Modulation logging turned on.") self.connect(self.B2s, blocks.file_sink(gr.sizeof_float, "symbols.dat")) self.connect(self.pam, diff --git a/gr-digital/python/digital/crc.py b/gr-digital/python/digital/crc.py index e228faaa98..31e98d368a 100644 --- a/gr-digital/python/digital/crc.py +++ b/gr-digital/python/digital/crc.py @@ -1,26 +1,27 @@ +from __future__ import unicode_literals # # Copyright 2005,2007,2011 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. -# +# from gnuradio import gru -import digital_swig as digital +from . import digital_swig as digital import struct def gen_and_append_crc32(s): diff --git a/gr-digital/python/digital/generic_mod_demod.py b/gr-digital/python/digital/generic_mod_demod.py index 1b8e1149c9..ad487b27e9 100644 --- a/gr-digital/python/digital/generic_mod_demod.py +++ b/gr-digital/python/digital/generic_mod_demod.py @@ -19,32 +19,22 @@ # Boston, MA 02110-1301, USA. # -# See gnuradio-examples/python/digital for examples - """ Generic modulation and demodulation. """ -from gnuradio import gr -from modulation_utils import extract_kwargs_from_options_for_class -from utils import mod_codes -import digital_swig as digital -import math +# See gnuradio-examples/python/digital for examples -try: - from gnuradio import blocks -except ImportError: - import blocks_swig as blocks +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals -try: - from gnuradio import filter -except ImportError: - import filter_swig as filter +from gnuradio import gr, blocks, filter, analog +from .modulation_utils import extract_kwargs_from_options_for_class +from .utils import mod_codes +from . import digital_swig as digital +import math -try: - from gnuradio import analog -except ImportError: - import analog_swig as analog # default values (used in __init__ and add_options) _def_samples_per_symbol = 2 @@ -113,9 +103,9 @@ class generic_mod(gr.hier_block2): verbose=_def_verbose, log=_def_log): - gr.hier_block2.__init__(self, "generic_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + gr.hier_block2.__init__(self, "generic_mod", + gr.io_signature(1, 1, gr.sizeof_char), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._constellation = constellation self._samples_per_symbol = samples_per_symbol @@ -125,7 +115,7 @@ class generic_mod(gr.hier_block2): self.pre_diff_code = pre_diff_code and self._constellation.apply_pre_diff_code() if self._samples_per_symbol < 2: - raise TypeError, ("sps must be >= 2, is %f" % self._samples_per_symbol) + raise TypeError("sps must be >= 2, is %f" % self._samples_per_symbol) arity = pow(2,self.bits_per_symbol()) @@ -153,7 +143,7 @@ class generic_mod(gr.hier_block2): self.rrc_filter = filter.pfb_arb_resampler_ccf(self._samples_per_symbol, self.rrc_taps) - # Connect + # Connect self._blocks = [self, self.bytes2chunks] if self.pre_diff_code: self._blocks.append(self.symbol_mapper) @@ -191,12 +181,12 @@ class generic_mod(gr.hier_block2): def _print_verbage(self): - print "\nModulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "RRC roll-off factor: %.2f" % self._excess_bw + print("\nModulator:") + print("bits per symbol: %d" % self.bits_per_symbol()) + print("RRC roll-off factor: %.2f" % self._excess_bw) def _setup_logging(self): - print "Modulation logging turned on." + print("Modulation logging turned on.") self.connect(self.bytes2chunks, blocks.file_sink(gr.sizeof_char, "tx_bytes2chunks.8b")) if self.pre_diff_code: @@ -249,9 +239,9 @@ class generic_demod(gr.hier_block2): verbose=_def_verbose, log=_def_log): - gr.hier_block2.__init__(self, "generic_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature + gr.hier_block2.__init__(self, "generic_demod", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_char)) # Output signature self._constellation = constellation self._samples_per_symbol = samples_per_symbol @@ -263,7 +253,7 @@ class generic_demod(gr.hier_block2): self._differential = differential if self._samples_per_symbol < 2: - raise TypeError, ("sps must be >= 2, is %d" % self._samples_per_symbol) + raise TypeError("sps must be >= 2, is %d" % self._samples_per_symbol) # Only apply a predifferential coding if the constellation also supports it. self.pre_diff_code = pre_diff_code and self._constellation.apply_pre_diff_code() @@ -328,15 +318,15 @@ class generic_demod(gr.hier_block2): return self._constellation.bits_per_symbol() def _print_verbage(self): - print "\nDemodulator:" - print "bits per symbol: %d" % self.bits_per_symbol() - print "RRC roll-off factor: %.2f" % self._excess_bw - print "FLL bandwidth: %.2e" % self._freq_bw - print "Timing bandwidth: %.2e" % self._timing_bw - print "Phase bandwidth: %.2e" % self._phase_bw + print("\nDemodulator:") + print("bits per symbol: %d" % self.bits_per_symbol()) + print("RRC roll-off factor: %.2f" % self._excess_bw) + print("FLL bandwidth: %.2e" % self._freq_bw) + print("Timing bandwidth: %.2e" % self._timing_bw) + print("Phase bandwidth: %.2e" % self._phase_bw) def _setup_logging(self): - print "Modulation logging turned on." + print("Modulation logging turned on.") self.connect(self.agc, blocks.file_sink(gr.sizeof_gr_complex, "rx_agc.32fc")) self.connect((self.freq_recov, 0), diff --git a/gr-digital/python/digital/gfsk.py b/gr-digital/python/digital/gfsk.py index 3569ffe6cf..5ce3e85812 100644 --- a/gr-digital/python/digital/gfsk.py +++ b/gr-digital/python/digital/gfsk.py @@ -1,43 +1,42 @@ # -# GFSK modulation and demodulation. +# GFSK modulation and demodulation. # # # Copyright 2005-2007,2012 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. -# +# + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals # See gnuradio-examples/python/digital for examples +import numpy + from gnuradio import gr from gnuradio import analog -from gnuradio import blocks -import modulation_utils -import digital_swig as digital -from math import pi -import numpy -from pprint import pprint -import inspect +from gnuradio import blocks, filter +from . import modulation_utils +from . import digital_swig as digital -try: - from gnuradio import filter -except ImportError: - import filter_swig as filter # default values (used in __init__ and add_options) _def_samples_per_symbol = 2 @@ -69,22 +68,22 @@ class gfsk_mod(gr.hier_block2): verbose=_def_verbose, log=_def_log): """ - Hierarchical block for Gaussian Frequency Shift Key (GFSK) - modulation. + Hierarchical block for Gaussian Frequency Shift Key (GFSK) + modulation. - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. Args: samples_per_symbol: samples per baud >= 2 (integer) bt: Gaussian filter bandwidth * symbol time (float) verbose: Print information about modulator? (bool) debug: Print modualtion data to files? (bool) - """ + """ - gr.hier_block2.__init__(self, "gfsk_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + gr.hier_block2.__init__(self, "gfsk_mod", + gr.io_signature(1, 1, gr.sizeof_char), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature samples_per_symbol = int(samples_per_symbol) self._samples_per_symbol = samples_per_symbol @@ -92,43 +91,43 @@ class gfsk_mod(gr.hier_block2): self._differential = False if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2: - raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,)) + raise TypeError("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,)) - ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once - #sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2 + ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once + #sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2 - # Turn it into NRZ data. - #self.nrz = digital.bytes_to_syms() + # Turn it into NRZ data. + #self.nrz = digital.bytes_to_syms() self.unpack = blocks.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST) self.nrz = digital.chunks_to_symbols_bf([-1, 1]) - # Form Gaussian filter + # Form Gaussian filter # Generate Gaussian response (Needs to be convolved with window below). - self.gaussian_taps = filter.firdes.gaussian( - 1.0, # gain - samples_per_symbol, # symbol_rate - bt, # bandwidth * symbol time - ntaps # number of taps - ) - - self.sqwave = (1,) * samples_per_symbol # rectangular window - self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave)) - self.gaussian_filter = filter.interp_fir_filter_fff(samples_per_symbol, self.taps) - - # FM modulation - self.fmmod = analog.frequency_modulator_fc(sensitivity) - - # small amount of output attenuation to prevent clipping USRP sink - self.amp = blocks.multiply_const_cc(0.999) - + self.gaussian_taps = filter.firdes.gaussian( + 1.0, # gain + samples_per_symbol, # symbol_rate + bt, # bandwidth * symbol time + ntaps # number of taps + ) + + self.sqwave = (1,) * samples_per_symbol # rectangular window + self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave)) + self.gaussian_filter = filter.interp_fir_filter_fff(samples_per_symbol, self.taps) + + # FM modulation + self.fmmod = analog.frequency_modulator_fc(sensitivity) + + # small amount of output attenuation to prevent clipping USRP sink + self.amp = blocks.multiply_const_cc(0.999) + if verbose: self._print_verbage() - + if log: self._setup_logging() - # Connect & Initialize base class - self.connect(self, self.unpack, self.nrz, self.gaussian_filter, self.fmmod, self.amp, self) + # Connect & Initialize base class + self.connect(self, self.unpack, self.nrz, self.gaussian_filter, self.fmmod, self.amp, self) def samples_per_symbol(self): return self._samples_per_symbol @@ -138,12 +137,12 @@ class gfsk_mod(gr.hier_block2): return 1 def _print_verbage(self): - print "bits per symbol = %d" % self.bits_per_symbol() - print "Gaussian filter bt = %.2f" % self._bt + print("bits per symbol = %d" % self.bits_per_symbol()) + print("Gaussian filter bt = %.2f" % self._bt) def _setup_logging(self): - print "Modulation logging turned on." + print("Modulation logging turned on.") self.connect(self.nrz, blocks.file_sink(gr.sizeof_float, "nrz.dat")) self.connect(self.gaussian_filter, @@ -184,11 +183,11 @@ class gfsk_demod(gr.hier_block2): verbose=_def_verbose, log=_def_log): """ - Hierarchical block for Gaussian Minimum Shift Key (GFSK) - demodulation. + Hierarchical block for Gaussian Minimum Shift Key (GFSK) + demodulation. - The input is the complex modulated signal at baseband. - The output is a stream of bits packed 1 bit per byte (the LSB) + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (the LSB) Args: samples_per_symbol: samples per baud (integer) @@ -196,18 +195,18 @@ class gfsk_demod(gr.hier_block2): log: Print modualtion data to files? (bool) Clock recovery parameters. These all have reasonble defaults. - + Args: gain_mu: controls rate of mu adjustment (float) mu: fractional delay [0.0, 1.0] (float) omega_relative_limit: sets max variation in omega (float, typically 0.000200 (200 ppm)) freq_error: bit rate error as a fraction - float: - """ + float: + """ - gr.hier_block2.__init__(self, "gfsk_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature + gr.hier_block2.__init__(self, "gfsk_demod", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_char)) # Output signature self._samples_per_symbol = samples_per_symbol self._gain_mu = gain_mu @@ -215,24 +214,24 @@ class gfsk_demod(gr.hier_block2): self._omega_relative_limit = omega_relative_limit self._freq_error = freq_error self._differential = False - + if samples_per_symbol < 2: - raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol + raise TypeError("samples_per_symbol >= 2, is %f" % samples_per_symbol) self._omega = samples_per_symbol*(1+self._freq_error) if not self._gain_mu: self._gain_mu = 0.175 - - self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped - # Demodulate FM - #sensitivity = (pi / 2) / samples_per_symbol - self.fmdemod = analog.quadrature_demod_cf(1.0 / sensitivity) + self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped - # the clock recovery block tracks the symbol clock and resamples as needed. - # the output of the block is a stream of soft symbols (float) - self.clock_recovery = digital.clock_recovery_mm_ff(self._omega, self._gain_omega, + # Demodulate FM + #sensitivity = (pi / 2) / samples_per_symbol + self.fmdemod = analog.quadrature_demod_cf(1.0 / sensitivity) + + # the clock recovery block tracks the symbol clock and resamples as needed. + # the output of the block is a stream of soft symbols (float) + self.clock_recovery = digital.clock_recovery_mm_ff(self._omega, self._gain_omega, self._mu, self._gain_mu, self._omega_relative_limit) @@ -241,12 +240,12 @@ class gfsk_demod(gr.hier_block2): if verbose: self._print_verbage() - + if log: self._setup_logging() - # Connect & Initialize base class - self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self) + # Connect & Initialize base class + self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self) def samples_per_symbol(self): return self._samples_per_symbol @@ -256,16 +255,16 @@ class gfsk_demod(gr.hier_block2): return 1 def _print_verbage(self): - print "bits per symbol = %d" % self.bits_per_symbol() - print "M&M clock recovery omega = %f" % self._omega - print "M&M clock recovery gain mu = %f" % self._gain_mu - print "M&M clock recovery mu = %f" % self._mu - print "M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit - print "frequency error = %f" % self._freq_error + print("bits per symbol = %d" % self.bits_per_symbol()) + print("M&M clock recovery omega = %f" % self._omega) + print("M&M clock recovery gain mu = %f" % self._gain_mu) + print("M&M clock recovery mu = %f" % self._mu) + print("M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit) + print("frequency error = %f" % self._freq_error) def _setup_logging(self): - print "Demodulation logging turned on." + print("Demodulation logging turned on.") self.connect(self.fmdemod, blocks.file_sink(gr.sizeof_float, "fmdemod.dat")) self.connect(self.clock_recovery, diff --git a/gr-digital/python/digital/gmsk.py b/gr-digital/python/digital/gmsk.py index e7a92a95db..5e25a3d3a1 100644 --- a/gr-digital/python/digital/gmsk.py +++ b/gr-digital/python/digital/gmsk.py @@ -1,26 +1,31 @@ # -# GMSK modulation and demodulation. +# GMSK modulation and demodulation. # # # Copyright 2005-2007,2012 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. -# +# + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals # See gnuradio-examples/python/digital for examples @@ -31,8 +36,8 @@ import inspect import numpy from gnuradio import gr, blocks, analog, filter -import modulation_utils -import digital_swig as digital +from . import modulation_utils +from . import digital_swig as digital # default values (used in __init__ and add_options) _def_samples_per_symbol = 2 @@ -58,10 +63,10 @@ class gmsk_mod(gr.hier_block2): """ Hierarchical block for Gaussian Minimum Shift Key (GMSK) modulation. - + The input is a byte stream (unsigned char with packed bits) and the output is the complex modulated signal at baseband. - + Args: samples_per_symbol: samples per baud >= 2 (integer) bt: Gaussian filter bandwidth * symbol time (float) @@ -75,9 +80,9 @@ class gmsk_mod(gr.hier_block2): verbose=_def_verbose, log=_def_log): - gr.hier_block2.__init__(self, "gmsk_mod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + gr.hier_block2.__init__(self, "gmsk_mod", + gr.io_signature(1, 1, gr.sizeof_char), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature samples_per_symbol = int(samples_per_symbol) self._samples_per_symbol = samples_per_symbol @@ -85,40 +90,40 @@ class gmsk_mod(gr.hier_block2): self._differential = False if not isinstance(samples_per_symbol, int) or samples_per_symbol < 2: - raise TypeError, ("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,)) + raise TypeError("samples_per_symbol must be an integer >= 2, is %r" % (samples_per_symbol,)) - ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once - sensitivity = (pi / 2) / samples_per_symbol # phase change per bit = pi / 2 + ntaps = 4 * samples_per_symbol # up to 3 bits in filter at once + sensitivity = (old_div(pi / 2), samples_per_symbol) # phase change per bit = pi / 2 - # Turn it into NRZ data. - #self.nrz = digital.bytes_to_syms() + # Turn it into NRZ data. + #self.nrz = digital.bytes_to_syms() self.unpack = blocks.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST) self.nrz = digital.chunks_to_symbols_bf([-1, 1], 1) - # Form Gaussian filter + # Form Gaussian filter # Generate Gaussian response (Needs to be convolved with window below). - self.gaussian_taps = filter.firdes.gaussian( - 1, # gain - samples_per_symbol, # symbol_rate - bt, # bandwidth * symbol time - ntaps # number of taps - ) - - self.sqwave = (1,) * samples_per_symbol # rectangular window - self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave)) - self.gaussian_filter = filter.interp_fir_filter_fff(samples_per_symbol, self.taps) - - # FM modulation - self.fmmod = analog.frequency_modulator_fc(sensitivity) - + self.gaussian_taps = filter.firdes.gaussian( + 1, # gain + samples_per_symbol, # symbol_rate + bt, # bandwidth * symbol time + ntaps # number of taps + ) + + self.sqwave = (1,) * samples_per_symbol # rectangular window + self.taps = numpy.convolve(numpy.array(self.gaussian_taps),numpy.array(self.sqwave)) + self.gaussian_filter = filter.interp_fir_filter_fff(samples_per_symbol, self.taps) + + # FM modulation + self.fmmod = analog.frequency_modulator_fc(sensitivity) + if verbose: self._print_verbage() - + if log: self._setup_logging() - # Connect & Initialize base class - self.connect(self, self.unpack, self.nrz, self.gaussian_filter, self.fmmod, self) + # Connect & Initialize base class + self.connect(self, self.unpack, self.nrz, self.gaussian_filter, self.fmmod, self) def samples_per_symbol(self): return self._samples_per_symbol @@ -128,12 +133,12 @@ class gmsk_mod(gr.hier_block2): return 1 def _print_verbage(self): - print "bits per symbol = %d" % self.bits_per_symbol() - print "Gaussian filter bt = %.2f" % self._bt + print("bits per symbol = %d" % self.bits_per_symbol()) + print("Gaussian filter bt = %.2f" % self._bt) def _setup_logging(self): - print "Modulation logging turned on." + print("Modulation logging turned on.") self.connect(self.nrz, blocks.file_sink(gr.sizeof_float, "nrz.dat")) self.connect(self.gaussian_filter, @@ -166,10 +171,10 @@ class gmsk_demod(gr.hier_block2): """ Hierarchical block for Gaussian Minimum Shift Key (GMSK) demodulation. - + The input is the complex modulated signal at baseband. The output is a stream of bits packed 1 bit per byte (the LSB) - + Args: samples_per_symbol: samples per baud (integer) gain_mu: controls rate of mu adjustment (float) @@ -179,7 +184,7 @@ class gmsk_demod(gr.hier_block2): verbose: Print information about modulator? (boolean) log: Print modualtion data to files? (boolean) """ - + def __init__(self, samples_per_symbol=_def_samples_per_symbol, gain_mu=_def_gain_mu, @@ -189,9 +194,9 @@ class gmsk_demod(gr.hier_block2): verbose=_def_verbose, log=_def_log): - gr.hier_block2.__init__(self, "gmsk_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature + gr.hier_block2.__init__(self, "gmsk_demod", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_char)) # Output signature self._samples_per_symbol = samples_per_symbol self._gain_mu = gain_mu @@ -199,24 +204,24 @@ class gmsk_demod(gr.hier_block2): self._omega_relative_limit = omega_relative_limit self._freq_error = freq_error self._differential = False - + if samples_per_symbol < 2: - raise TypeError, "samples_per_symbol >= 2, is %f" % samples_per_symbol + raise TypeError("samples_per_symbol >= 2, is %f" % samples_per_symbol) self._omega = samples_per_symbol*(1+self._freq_error) if not self._gain_mu: self._gain_mu = 0.175 - - self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped - # Demodulate FM - sensitivity = (pi / 2) / samples_per_symbol - self.fmdemod = analog.quadrature_demod_cf(1.0 / sensitivity) + self._gain_omega = .25 * self._gain_mu * self._gain_mu # critically damped - # the clock recovery block tracks the symbol clock and resamples as needed. - # the output of the block is a stream of soft symbols (float) - self.clock_recovery = digital.clock_recovery_mm_ff(self._omega, self._gain_omega, + # Demodulate FM + sensitivity = (old_div(pi / 2), samples_per_symbol) + self.fmdemod = analog.quadrature_demod_cf(1.0 / sensitivity) + + # the clock recovery block tracks the symbol clock and resamples as needed. + # the output of the block is a stream of soft symbols (float) + self.clock_recovery = digital.clock_recovery_mm_ff(self._omega, self._gain_omega, self._mu, self._gain_mu, self._omega_relative_limit) @@ -225,12 +230,12 @@ class gmsk_demod(gr.hier_block2): if verbose: self._print_verbage() - + if log: self._setup_logging() - # Connect & Initialize base class - self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self) + # Connect & Initialize base class + self.connect(self, self.fmdemod, self.clock_recovery, self.slicer, self) def samples_per_symbol(self): return self._samples_per_symbol @@ -240,16 +245,16 @@ class gmsk_demod(gr.hier_block2): return 1 def _print_verbage(self): - print "bits per symbol = %d" % self.bits_per_symbol() - print "M&M clock recovery omega = %f" % self._omega - print "M&M clock recovery gain mu = %f" % self._gain_mu - print "M&M clock recovery mu = %f" % self._mu - print "M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit - print "frequency error = %f" % self._freq_error + print("bits per symbol = %d" % self.bits_per_symbol()) + print("M&M clock recovery omega = %f" % self._omega) + print("M&M clock recovery gain mu = %f" % self._gain_mu) + print("M&M clock recovery mu = %f" % self._mu) + print("M&M clock recovery omega rel. limit = %f" % self._omega_relative_limit) + print("frequency error = %f" % self._freq_error) def _setup_logging(self): - print "Demodulation logging turned on." + print("Demodulation logging turned on.") self.connect(self.fmdemod, blocks.file_sink(gr.sizeof_float, "fmdemod.dat")) self.connect(self.clock_recovery, diff --git a/gr-digital/python/digital/modulation_utils.py b/gr-digital/python/digital/modulation_utils.py index d499094d05..57d7ccdae8 100644 --- a/gr-digital/python/digital/modulation_utils.py +++ b/gr-digital/python/digital/modulation_utils.py @@ -22,6 +22,7 @@ Miscellaneous utilities for managing mods and demods, as well as other items useful in dealing with generalized handling of different modulations and demods. """ +from __future__ import unicode_literals import inspect diff --git a/gr-digital/python/digital/ofdm.py b/gr-digital/python/digital/ofdm.py index 563b70ad00..db15a4d3f1 100644 --- a/gr-digital/python/digital/ofdm.py +++ b/gr-digital/python/digital/ofdm.py @@ -1,33 +1,38 @@ #!/usr/bin/env python # # Copyright 2006-2008,2013 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. -# +# + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals import math from gnuradio import gr, fft from gnuradio import blocks -import digital_swig as digital -import ofdm_packet_utils -from ofdm_receiver import ofdm_receiver +from . import digital_swig as digital +from . import ofdm_packet_utils +from .ofdm_receiver import ofdm_receiver import gnuradio.gr.gr_threading as _threading -import psk, qam +from . import psk, qam # ///////////////////////////////////////////////////////////////////////////// # mod/demod with packets as i/o @@ -37,12 +42,12 @@ class ofdm_mod(gr.hier_block2): """ Modulates an OFDM stream. Based on the options fft_length, occupied_tones, and cp_length, this block creates OFDM symbols using a specified modulation option. - + Send packets by calling send_pkt """ def __init__(self, options, msgq_limit=2, pad_for_usrp=True): """ - Hierarchical block for sending packets + Hierarchical block for sending packets Packets to be sent are enqueued by calling send_pkt. The output is the complex modulated signal at baseband. @@ -53,9 +58,9 @@ class ofdm_mod(gr.hier_block2): pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples """ - gr.hier_block2.__init__(self, "ofdm_mod", - gr.io_signature(0, 0, 0), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + gr.hier_block2.__init__(self, "ofdm_mod", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._pad_for_usrp = pad_for_usrp self._modulation = options.modulation @@ -66,7 +71,7 @@ class ofdm_mod(gr.hier_block2): win = [] #[1 for i in range(self._fft_length)] # Use freq domain to get doubled-up known symbol for correlation in time domain - zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0)) + zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones) / 2.0)) ksfreq = known_symbols_4512_3[0:self._occupied_tones] for i in range(len(ksfreq)): if((zeros_on_left + i) & 1): @@ -74,46 +79,46 @@ class ofdm_mod(gr.hier_block2): # hard-coded known symbols preambles = (ksfreq,) - + padded_preambles = list() for pre in preambles: padded = self._fft_length*[0,] padded[zeros_on_left : zeros_on_left + self._occupied_tones] = pre padded_preambles.append(padded) - + symbol_length = options.fft_length + options.cp_length - + mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256} arity = mods[self._modulation] - + rot = 1 if self._modulation == "qpsk": rot = (0.707+0.707j) - + # FIXME: pass the constellation objects instead of just the points if(self._modulation.find("psk") >= 0): constel = psk.psk_constellation(arity) - rotated_const = map(lambda pt: pt * rot, constel.points()) + rotated_const = [pt * rot for pt in constel.points()] elif(self._modulation.find("qam") >= 0): constel = qam.qam_constellation(arity) - rotated_const = map(lambda pt: pt * rot, constel.points()) - #print rotated_const + rotated_const = [pt * rot for pt in constel.points()] + #print(rotated_const) self._pkt_input = digital.ofdm_mapper_bcv(rotated_const, msgq_limit, options.occupied_tones, options.fft_length) - + self.preambles = digital.ofdm_insert_preamble(self._fft_length, padded_preambles) self.ifft = fft.fft_vcc(self._fft_length, False, win, True) self.cp_adder = digital.ofdm_cyclic_prefixer(self._fft_length, symbol_length) self.scale = blocks.multiply_const_cc(1.0 / math.sqrt(self._fft_length)) - + self.connect((self._pkt_input, 0), (self.preambles, 0)) self.connect((self._pkt_input, 1), (self.preambles, 1)) self.connect(self.preambles, self.ifft, self.cp_adder, self.scale, self) - + if options.verbose: self._print_verbage() @@ -137,12 +142,12 @@ class ofdm_mod(gr.hier_block2): if eof: msg = gr.message(1) # tell self._pkt_input we're not sending any more packets else: - # print "original_payload =", string_to_hex_list(payload) + # print("original_payload =", string_to_hex_list(payload)) pkt = ofdm_packet_utils.make_packet(payload, 1, 1, self._pad_for_usrp, whitening=True) - - #print "pkt =", string_to_hex_list(pkt) + + #print("pkt =", string_to_hex_list(pkt)) msg = gr.message_from_string(pkt) self._pkt_input.msgq().insert_tail(msg) @@ -164,11 +169,11 @@ class ofdm_mod(gr.hier_block2): """ Prints information about the OFDM modulator """ - print "\nOFDM Modulator:" - print "Modulation Type: %s" % (self._modulation) - print "FFT length: %3d" % (self._fft_length) - print "Occupied Tones: %3d" % (self._occupied_tones) - print "CP length: %3d" % (self._cp_length) + print("\nOFDM Modulator:") + print("Modulation Type: %s" % (self._modulation)) + print("FFT length: %3d" % (self._fft_length)) + print("Occupied Tones: %3d" % (self._occupied_tones)) + print("CP length: %3d" % (self._cp_length)) class ofdm_demod(gr.hier_block2): @@ -183,18 +188,18 @@ class ofdm_demod(gr.hier_block2): def __init__(self, options, callback=None): """ - Hierarchical block for demodulating and deframing packets. + Hierarchical block for demodulating and deframing packets. - The input is the complex modulated signal at baseband. + The input is the complex modulated signal at baseband. Demodulated packets are sent to the handler. Args: options: pass modulation options from higher layers (fft length, occupied tones, etc.) callback: function of two args: ok, payload (ok: bool; payload: string) - """ - gr.hier_block2.__init__(self, "ofdm_demod", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + """ + gr.hier_block2.__init__(self, "ofdm_demod", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY @@ -206,7 +211,7 @@ class ofdm_demod(gr.hier_block2): self._snr = options.snr # Use freq domain to get doubled-up known symbol for correlation in time domain - zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones)/2.0)) + zeros_on_left = int(math.ceil((self._fft_length - self._occupied_tones) / 2.0)) ksfreq = known_symbols_4512_3[0:self._occupied_tones] for i in range(len(ksfreq)): if((zeros_on_left + i) & 1): @@ -224,7 +229,7 @@ class ofdm_demod(gr.hier_block2): mods = {"bpsk": 2, "qpsk": 4, "8psk": 8, "qam8": 8, "qam16": 16, "qam64": 64, "qam256": 256} arity = mods[self._modulation] - + rot = 1 if self._modulation == "qpsk": rot = (0.707+0.707j) @@ -232,15 +237,15 @@ class ofdm_demod(gr.hier_block2): # FIXME: pass the constellation objects instead of just the points if(self._modulation.find("psk") >= 0): constel = psk.psk_constellation(arity) - rotated_const = map(lambda pt: pt * rot, constel.points()) + rotated_const = [pt * rot for pt in constel.points()] elif(self._modulation.find("qam") >= 0): constel = qam.qam_constellation(arity) - rotated_const = map(lambda pt: pt * rot, constel.points()) - #print rotated_const + rotated_const = [pt * rot for pt in constel.points()] + #print(rotated_const) phgain = 0.25 frgain = phgain*phgain / 4.0 - self.ofdm_demod = digital.ofdm_frame_sink(rotated_const, range(arity), + self.ofdm_demod = digital.ofdm_frame_sink(rotated_const, list(range(arity)), self._rcvd_pktq, self._occupied_tones, phgain, frgain) @@ -263,7 +268,7 @@ class ofdm_demod(gr.hier_block2): if options.verbose: self._print_verbage() - + self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) @staticmethod @@ -286,11 +291,11 @@ class ofdm_demod(gr.hier_block2): """ Prints information about the OFDM demodulator """ - print "\nOFDM Demodulator:" - print "Modulation Type: %s" % (self._modulation) - print "FFT length: %3d" % (self._fft_length) - print "Occupied Tones: %3d" % (self._occupied_tones) - print "CP length: %3d" % (self._cp_length) + print("\nOFDM Demodulator:") + print("Modulation Type: %s" % (self._modulation)) + print("FFT length: %3d" % (self._fft_length)) + print("Occupied Tones: %3d" % (self._occupied_tones)) + print("CP length: %3d" % (self._cp_length)) diff --git a/gr-digital/python/digital/ofdm_packet_utils.py b/gr-digital/python/digital/ofdm_packet_utils.py index e9ca641c7a..e26308a262 100644 --- a/gr-digital/python/digital/ofdm_packet_utils.py +++ b/gr-digital/python/digital/ofdm_packet_utils.py @@ -19,10 +19,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + import struct import numpy from gnuradio import gru -import crc +from . import crc def conv_packed_binary_string_to_1_0_string(s): """ @@ -35,7 +40,7 @@ def conv_packed_binary_string_to_1_0_string(s): t = (x >> i) & 0x1 r.append(t) - return ''.join(map(lambda x: chr(x + ord('0')), r)) + return ''.join([chr(x + ord('0')) for x in r]) def conv_1_0_string_to_packed_binary_string(s): """ @@ -46,7 +51,7 @@ def conv_1_0_string_to_packed_binary_string(s): to get to a multiple of 8. """ if not is_1_0_string(s): - raise ValueError, "Input must be a string containing only 0's and 1's" + raise ValueError("Input must be a string containing only 0's and 1's") # pad to multiple of 8 padded = False @@ -78,7 +83,7 @@ def is_1_0_string(s): return True def string_to_hex_list(s): - return map(lambda x: hex(ord(x)), s) + return [hex(ord(x)) for x in s] def whiten(s, o): @@ -93,7 +98,7 @@ def dewhiten(s, o): def make_header(payload_len, whitener_offset=0): # Upper nibble is offset, lower 12 bits is len val = ((whitener_offset & 0xf) << 12) | (payload_len & 0x0fff) - #print "offset =", whitener_offset, " len =", payload_len, " val=", val + #print("offset =", whitener_offset, " len =", payload_len, " val=", val) return struct.pack('!HH', val, val) def make_packet(payload, samples_per_symbol, bits_per_symbol, @@ -113,15 +118,15 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol, """ if not whitener_offset >=0 and whitener_offset < 16: - raise ValueError, "whitener_offset must be between 0 and 15, inclusive (%i)" % (whitener_offset,) + raise ValueError("whitener_offset must be between 0 and 15, inclusive (%i)" % (whitener_offset,)) payload_with_crc = crc.gen_and_append_crc32(payload) - #print "outbound crc =", string_to_hex_list(payload_with_crc[-4:]) + #print("outbound crc =", string_to_hex_list(payload_with_crc[-4:])) L = len(payload_with_crc) MAXLEN = len(random_mask_tuple) if L > MAXLEN: - raise ValueError, "len(payload) must be in [0, %d]" % (MAXLEN,) + raise ValueError("len(payload) must be in [0, %d]" % (MAXLEN,)) pkt_hd = make_header(L, whitener_offset) pkt_dt = ''.join((payload_with_crc, '\x55')) @@ -136,7 +141,7 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol, else: pkt = pkt_hd + pkt_dt - #print "make_packet: len(pkt) =", len(pkt) + #print("make_packet: len(pkt) =", len(pkt)) return pkt @@ -157,7 +162,7 @@ def _npadding_bytes(pkt_byte_len, samples_per_symbol, bits_per_symbol): number of bytes of padding to append. """ modulus = 128 - byte_modulus = gru.lcm(modulus/8, samples_per_symbol) * bits_per_symbol / samples_per_symbol + byte_modulus = gru.lcm(modulus / 8, samples_per_symbol) * bits_per_symbol / samples_per_symbol r = pkt_byte_len % byte_modulus if r == 0: return 0 @@ -182,9 +187,9 @@ def unmake_packet(whitened_payload_with_crc, whitener_offset=0, dewhitening=1): ok, payload = crc.check_crc32(payload_with_crc) if 0: - print "payload_with_crc =", string_to_hex_list(payload_with_crc) - print "ok = %r, len(payload) = %d" % (ok, len(payload)) - print "payload =", string_to_hex_list(payload) + print("payload_with_crc =", string_to_hex_list(payload_with_crc)) + print("ok = %r, len(payload) = %d" % (ok, len(payload))) + print("payload =", string_to_hex_list(payload)) return ok, payload diff --git a/gr-digital/python/digital/ofdm_receiver.py b/gr-digital/python/digital/ofdm_receiver.py index 4b7836b43c..d23b338b78 100644 --- a/gr-digital/python/digital/ofdm_receiver.py +++ b/gr-digital/python/digital/ofdm_receiver.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2006-2008 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. -# +# + +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals import math from numpy import fft @@ -28,16 +32,12 @@ from gnuradio import analog from gnuradio import blocks from gnuradio import filter -import digital_swig as digital -from ofdm_sync_pn import ofdm_sync_pn -from ofdm_sync_fixed import ofdm_sync_fixed -from ofdm_sync_pnac import ofdm_sync_pnac -from ofdm_sync_ml import ofdm_sync_ml +from . import digital_swig as digital +from .ofdm_sync_pn import ofdm_sync_pn +from .ofdm_sync_fixed import ofdm_sync_fixed +from .ofdm_sync_pnac import ofdm_sync_pnac +from .ofdm_sync_ml import ofdm_sync_ml -try: - from gnuradio import filter -except ImportError: - import filter_swig as filter class ofdm_receiver(gr.hier_block2): """ @@ -51,9 +51,9 @@ class ofdm_receiver(gr.hier_block2): def __init__(self, fft_length, cp_length, occupied_tones, snr, ks, logging=False): """ - Hierarchical block for receiving OFDM symbols. + Hierarchical block for receiving OFDM symbols. - The input is the complex modulated signal at baseband. + The input is the complex modulated signal at baseband. Synchronized packets are sent back to the demodulator. Args: @@ -63,13 +63,13 @@ class ofdm_receiver(gr.hier_block2): snr: estimated signal to noise ratio used to guide cyclic prefix synchronizer (float) ks: known symbols used as preambles to each packet (list of lists) logging: turn file logging on or off (bool) - """ + """ - gr.hier_block2.__init__(self, "ofdm_receiver", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.hier_block2.__init__(self, "ofdm_receiver", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature2(2, 2, gr.sizeof_gr_complex*occupied_tones, gr.sizeof_char)) # Output signature - - bw = (float(occupied_tones) / float(fft_length)) / 2.0 + + bw = (old_div(float(occupied_tones) / float(fft_length)), 2.0) tb = bw*0.08 chan_coeffs = filter.firdes.low_pass (1.0, # gain 1.0, # sampling rate @@ -77,13 +77,13 @@ class ofdm_receiver(gr.hier_block2): tb, # width of trans. band filter.firdes.WIN_HAMMING) # filter type self.chan_filt = filter.fft_filter_ccc(1, chan_coeffs) - + win = [1 for i in range(fft_length)] - zeros_on_left = int(math.ceil((fft_length - occupied_tones)/2.0)) + zeros_on_left = int(math.ceil((fft_length - occupied_tones) / 2.0)) ks0 = fft_length*[0,] ks0[zeros_on_left : zeros_on_left + occupied_tones] = ks[0] - + ks0 = fft.ifftshift(ks0) ks0time = fft.ifft(ks0) # ADD SCALING FACTOR @@ -91,19 +91,19 @@ class ofdm_receiver(gr.hier_block2): SYNC = "pn" if SYNC == "ml": - nco_sensitivity = -1.0/fft_length # correct for fine frequency + nco_sensitivity = -1.0 / fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_ml(fft_length, cp_length, snr, ks0time, logging) elif SYNC == "pn": - nco_sensitivity = -2.0/fft_length # correct for fine frequency + nco_sensitivity = -2.0 / fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_pn(fft_length, cp_length, logging) elif SYNC == "pnac": - nco_sensitivity = -2.0/fft_length # correct for fine frequency + nco_sensitivity = -2.0 / fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_pnac(fft_length, cp_length, ks0time, @@ -111,10 +111,10 @@ class ofdm_receiver(gr.hier_block2): # for testing only; do not user over the air # remove filter and filter delay for this elif SYNC == "fixed": - self.chan_filt = blocks.multiply_const_cc(1.0) + self.chan_filt = blocks.multiply_const_cc(1.0) nsymbols = 18 # enter the number of symbols per packet freq_offset = 0.0 # if you use a frequency offset, enter it here - nco_sensitivity = -2.0/fft_length # correct for fine frequency + nco_sensitivity = -2.0 / fft_length # correct for fine frequency self.ofdm_sync = ofdm_sync_fixed(fft_length, cp_length, nsymbols, diff --git a/gr-digital/python/digital/ofdm_sync_fixed.py b/gr-digital/python/digital/ofdm_sync_fixed.py index 9cbd59b943..891ba17d07 100644 --- a/gr-digital/python/digital/ofdm_sync_fixed.py +++ b/gr-digital/python/digital/ofdm_sync_fixed.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals import math from gnuradio import gr from gnuradio import blocks diff --git a/gr-digital/python/digital/ofdm_sync_ml.py b/gr-digital/python/digital/ofdm_sync_ml.py index 3afd647098..6a03c21639 100644 --- a/gr-digital/python/digital/ofdm_sync_ml.py +++ b/gr-digital/python/digital/ofdm_sync_ml.py @@ -1,37 +1,31 @@ #!/usr/bin/env python # # Copyright 2007,2008 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. -# +# + +from __future__ import division +from __future__ import unicode_literals -import math -from gnuradio import gr -try: - from gnuradio import filter -except ImportError: - import filter_swig as filter +from gnuradio import gr, blocks, filter -try: - from gnuradio import blocks -except ImportError: - import blocks_swig as blocks class ofdm_sync_ml(gr.hier_block2): def __init__(self, fft_length, cp_length, snr, kstime, logging): @@ -41,13 +35,13 @@ class ofdm_sync_ml(gr.hier_block2): Signal Processing, vol. 45, no. 7, pp. 1800-1805, 1997. ''' - gr.hier_block2.__init__(self, "ofdm_sync_ml", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.hier_block2.__init__(self, "ofdm_sync_ml", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature gr.io_signature2(2, 2, gr.sizeof_float, gr.sizeof_char)) # Output signature self.input = blocks.add_const_cc(0) - SNR = 10.0**(snr/10.0) + SNR = 10.0**(snr / 10.0) rho = SNR / (SNR + 1.0) symbol_length = fft_length + cp_length @@ -66,15 +60,15 @@ class ofdm_sync_ml(gr.hier_block2): self.magsqrd2 = blocks.complex_to_mag_squared() self.adder = blocks.add_ff() - moving_sum_taps = [rho/2 for i in range(cp_length)] + moving_sum_taps = [rho / 2 for i in range(cp_length)] self.moving_sum_filter = filter.fir_filter_fff(1,moving_sum_taps) - + self.connect(self.input,self.magsqrd1) self.connect(self.delay,self.magsqrd2) self.connect(self.magsqrd1,(self.adder,0)) self.connect(self.magsqrd2,(self.adder,1)) self.connect(self.adder,self.moving_sum_filter) - + # Correlation from ML Sync self.conjg = blocks.conjugate_cc(); @@ -82,7 +76,7 @@ class ofdm_sync_ml(gr.hier_block2): movingsum2_taps = [1.0 for i in range(cp_length)] self.movingsum2 = filter.fir_filter_ccf(1,movingsum2_taps) - + # Correlator data handler self.c2mag = blocks.complex_to_mag() self.angle = blocks.complex_to_arg() @@ -104,7 +98,7 @@ class ofdm_sync_ml(gr.hier_block2): # use the sync loop values to set the sampler and the NCO # self.diff = theta # self.angle = epsilon - + self.connect(self.diff, self.pk_detect) # The DPLL corrects for timing differences between CP correlations @@ -115,7 +109,7 @@ class ofdm_sync_ml(gr.hier_block2): self.connect(self.dpll, (self.sample_and_hold,1)) else: self.connect(self.pk_detect, (self.sample_and_hold,1)) - + self.connect(self.angle, (self.sample_and_hold,0)) ################################ @@ -130,7 +124,7 @@ class ofdm_sync_ml(gr.hier_block2): self.div = blocks.divide_ff() # The output signature of the correlation has a few spikes because the rest of the - # system uses the repeated preamble symbol. It needs to work that generically if + # system uses the repeated preamble symbol. It needs to work that generically if # anyone wants to use this against a WiMAX-like signal since it, too, repeats. # The output theta of the correlator above is multiplied with this correlation to # identify the proper peak and remove other products in this cross-correlation @@ -139,17 +133,17 @@ class ofdm_sync_ml(gr.hier_block2): self.f2b = blocks.float_to_char() self.b2f = blocks.char_to_float() self.mul = blocks.multiply_ff() - + # Normalize the power of the corr output by the energy. This is not really needed # and could be removed for performance, but it makes for a cleaner signal. # if this is removed, the threshold value needs adjustment. self.connect(self.input, self.kscorr, self.corrmag, (self.div,0)) self.connect(self.moving_sum_filter, (self.div,1)) - + self.connect(self.div, (self.mul,0)) self.connect(self.pk_detect, self.b2f, (self.mul,1)) self.connect(self.mul, self.slice) - + # Set output signals # Output 0: fine frequency correction value # Output 1: timing signal diff --git a/gr-digital/python/digital/ofdm_sync_pn.py b/gr-digital/python/digital/ofdm_sync_pn.py index 8bf7ed782a..bdc7fd6438 100644 --- a/gr-digital/python/digital/ofdm_sync_pn.py +++ b/gr-digital/python/digital/ofdm_sync_pn.py @@ -1,38 +1,31 @@ #!/usr/bin/env python # # Copyright 2007,2008 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. -# +# + +from __future__ import division +from __future__ import unicode_literals -import math -from numpy import fft -from gnuradio import gr -try: - from gnuradio import filter -except ImportError: - import filter_swig as filter +from gnuradio import gr, blocks, filter -try: - from gnuradio import blocks -except ImportError: - import blocks_swig as blocks class ofdm_sync_pn(gr.hier_block2): def __init__(self, fft_length, cp_length, logging=False): @@ -52,7 +45,7 @@ class ofdm_sync_pn(gr.hier_block2): # PN Sync # Create a delay line - self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length/2) + self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length / 2) # Correlation from ML Sync self.conjg = blocks.conjugate_cc(); @@ -98,10 +91,10 @@ class ofdm_sync_pn(gr.hier_block2): self.connect(self.c2mag, (self.normalize,0)) # Create a moving sum filter for the corr output - matched_filter_taps = [1.0/cp_length for i in range(cp_length)] + matched_filter_taps = [1.0 / cp_length for i in range(cp_length)] self.matched_filter = filter.fir_filter_fff(1,matched_filter_taps) self.connect(self.normalize, self.matched_filter) - + self.connect(self.matched_filter, self.sub1, self.pk_detect) #self.connect(self.matched_filter, self.pk_detect) self.connect(self.pk_detect, (self.sample_and_hold,1)) diff --git a/gr-digital/python/digital/ofdm_sync_pnac.py b/gr-digital/python/digital/ofdm_sync_pnac.py index 55a6c21f4c..4d756f7ff7 100644 --- a/gr-digital/python/digital/ofdm_sync_pnac.py +++ b/gr-digital/python/digital/ofdm_sync_pnac.py @@ -1,38 +1,31 @@ #!/usr/bin/env python # # Copyright 2007 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. -# +# + +from __future__ import division +from __future__ import unicode_literals -import math -from numpy import fft -from gnuradio import gr -try: - from gnuradio import filter -except ImportError: - import filter_swig as filter +from gnuradio import gr, blocks, filter -try: - from gnuradio import blocks -except ImportError: - import blocks_swig as blocks class ofdm_sync_pnac(gr.hier_block2): def __init__(self, fft_length, cp_length, kstime, logging=False): @@ -69,9 +62,9 @@ class ofdm_sync_pnac(gr.hier_block2): kstime = [k.conjugate() for k in kstime[0:fft_length//2]] kstime.reverse() self.crosscorr_filter = filter.fir_filter_ccc(1, kstime) - + # Create a delay line - self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length/2) + self.delay = blocks.delay(gr.sizeof_gr_complex, fft_length / 2) # Correlation from ML Sync self.conjg = blocks.conjugate_cc(); @@ -105,7 +98,7 @@ class ofdm_sync_pnac(gr.hier_block2): self.connect(self.corr, self.c2mag) self.connect(self.corr, self.angle) self.connect(self.angle, (self.sample_and_hold,0)) - + # Get the power of the input signal to compare against the correlation self.connect(self.crosscorr_filter, self.mag, self.power) diff --git a/gr-digital/python/digital/ofdm_txrx.py b/gr-digital/python/digital/ofdm_txrx.py index 6f96fc6287..f90a579385 100644 --- a/gr-digital/python/digital/ofdm_txrx.py +++ b/gr-digital/python/digital/ofdm_txrx.py @@ -25,24 +25,21 @@ For simple configurations, no need to connect all the relevant OFDM blocks to form an OFDM Tx/Rx--simply use these. """ +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + # Reminder: All frequency-domain stuff is in shifted form, i.e. DC carrier # in the middle! + import numpy -from gnuradio import gr -import digital_swig as digital -from utils import tagged_streams -try: - # This will work when feature #505 is added. - from gnuradio import fft - from gnuradio import blocks - from gnuradio import analog -except ImportError: - # Until then this will work. - import fft_swig as fft - import blocks_swig as blocks - import analog_swig as analog +from gnuradio import gr, blocks, fft, analog + +from . import digital_swig as digital + _def_fft_len = 64 _def_cp_len = 16 @@ -50,7 +47,7 @@ _def_frame_length_tag_key = "frame_length" _def_packet_length_tag_key = "packet_length" _def_packet_num_tag_key = "packet_num" # Data and pilot carriers are same as in 802.11a -_def_occupied_carriers = (range(-26, -21) + range(-20, -7) + range(-6, 0) + range(1, 7) + range(8, 21) + range(22, 27),) +_def_occupied_carriers = (list(range(-26, -21)) + list(range(-20, -7)) + list(range(-6, 0)) + list(range(1, 7)) + list(range(8, 21)) + list(range(22, 27)),) _def_pilot_carriers=((-21, -7, 7, 21,),) _pilot_sym_scramble_seq = ( 1,1,1,1, -1,-1,-1,1, -1,-1,-1,-1, 1,1,-1,1, -1,-1,1,1, -1,1,1,-1, 1,1,1,1, 1,1,-1,1, @@ -112,7 +109,7 @@ def _get_constellation(bps): try: return constellation[bps] except KeyError: - print 'Modulation not supported.' + print('Modulation not supported.') exit(1) class ofdm_tx(gr.hier_block2): diff --git a/gr-digital/python/digital/packet_utils.py b/gr-digital/python/digital/packet_utils.py index de7e2988da..04d27125fa 100644 --- a/gr-digital/python/digital/packet_utils.py +++ b/gr-digital/python/digital/packet_utils.py @@ -19,10 +19,18 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division + import struct + import numpy +import six + from gnuradio import gru -import crc +from . import crc + def conv_packed_binary_string_to_1_0_string(s): """ @@ -35,7 +43,7 @@ def conv_packed_binary_string_to_1_0_string(s): t = (x >> i) & 0x1 r.append(t) - return ''.join(map(lambda x: chr(x + ord('0')), r)) + return ''.join([chr(x + ord('0')) for x in r]) def conv_1_0_string_to_packed_binary_string(s): """ @@ -46,7 +54,7 @@ def conv_1_0_string_to_packed_binary_string(s): to get to a multiple of 8. """ if not is_1_0_string(s): - raise ValueError, "Input must be a string containing only 0's and 1's" + raise ValueError("Input must be a string containing only 0's and 1's") # pad to multiple of 8 padded = False @@ -83,7 +91,7 @@ def is_1_0_string(s): return True def string_to_hex_list(s): - return map(lambda x: hex(ord(x)), s) + return [hex(ord(x)) for x in s] def whiten(s, o): @@ -98,8 +106,8 @@ def dewhiten(s, o): def make_header(payload_len, whitener_offset=0): # Upper nibble is offset, lower 12 bits is len val = ((whitener_offset & 0xf) << 12) | (payload_len & 0x0fff) - #print "offset =", whitener_offset, " len =", payload_len, " val=", val - return struct.pack('!HH', val, val) + #print("offset =", whitener_offset, " len =", payload_len, " val=", val) + return struct.pack(b'!HH', val, val) def make_packet(payload, samples_per_symbol, bits_per_symbol, preamble=default_preamble, access_code=default_access_code, @@ -123,13 +131,13 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol, and finally CRC-32. """ if not is_1_0_string(preamble): - raise ValueError, "preamble must be a string containing only 0's and 1's (%r)" % (preamble,) + raise ValueError("preamble must be a string containing only 0's and 1's (%r)" % (preamble,)) if not is_1_0_string(access_code): - raise ValueError, "access_code must be a string containing only 0's and 1's (%r)" % (access_code,) + raise ValueError("access_code must be a string containing only 0's and 1's (%r)" % (access_code,)) if not whitener_offset >=0 and whitener_offset < 16: - raise ValueError, "whitener_offset must be between 0 and 15, inclusive (%i)" % (whitener_offset,) + raise ValueError("whitener_offset must be between 0 and 15, inclusive (%i)" % (whitener_offset,)) (packed_access_code, padded) = conv_1_0_string_to_packed_binary_string(access_code) (packed_preamble, ignore) = conv_1_0_string_to_packed_binary_string(preamble) @@ -138,24 +146,24 @@ def make_packet(payload, samples_per_symbol, bits_per_symbol, payload_with_crc = crc.gen_and_append_crc32(payload) else: payload_with_crc = payload - #print "outbound crc =", string_to_hex_list(payload_with_crc[-4:]) + #print("outbound crc =", string_to_hex_list(payload_with_crc[-4:])) L = len(payload_with_crc) MAXLEN = len(random_mask_tuple) if L > MAXLEN: - raise ValueError, "len(payload) must be in [0, %d]" % (MAXLEN,) + raise ValueError("len(payload) must be in [0, %d]" % (MAXLEN,)) if whitening: - pkt = ''.join((packed_preamble, packed_access_code, make_header(L, whitener_offset), - whiten(payload_with_crc, whitener_offset), '\x55')) + pkt = b''.join((packed_preamble, packed_access_code, make_header(L, whitener_offset), + whiten(payload_with_crc, whitener_offset), b'\x55')) else: - pkt = ''.join((packed_preamble, packed_access_code, make_header(L, whitener_offset), - (payload_with_crc), '\x55')) + pkt = b''.join((packed_preamble, packed_access_code, make_header(L, whitener_offset), + (payload_with_crc), b'\x55')) if pad_for_usrp: - pkt = pkt + (_npadding_bytes(len(pkt), int(samples_per_symbol), bits_per_symbol) * '\x55') + pkt = pkt + (_npadding_bytes(len(pkt), int(samples_per_symbol), bits_per_symbol) * b'\x55') - #print "make_packet: len(pkt) =", len(pkt) + #print("make_packet: len(pkt) =", len(pkt)) return pkt def _npadding_bytes(pkt_byte_len, samples_per_symbol, bits_per_symbol): @@ -175,7 +183,7 @@ def _npadding_bytes(pkt_byte_len, samples_per_symbol, bits_per_symbol): number of bytes of padding to append. """ modulus = 128 - byte_modulus = gru.lcm(modulus/8, samples_per_symbol) * bits_per_symbol / samples_per_symbol + byte_modulus = gru.lcm(modulus // 8, samples_per_symbol) * bits_per_symbol // samples_per_symbol r = pkt_byte_len % byte_modulus if r == 0: return 0 @@ -206,10 +214,10 @@ def unmake_packet(whitened_payload_with_crc, whitener_offset=0, ok = True if 0: - print "payload_with_crc =", string_to_hex_list(payload_with_crc) - print "ok = %r, len(payload) = %d" % (ok, len(payload)) - print "payload =", string_to_hex_list(payload) - print "" + print("payload_with_crc =", string_to_hex_list(payload_with_crc)) + print("ok = %r, len(payload) = %d" % (ok, len(payload))) + print("payload =", string_to_hex_list(payload)) + print("") return ok, payload diff --git a/gr-digital/python/digital/pkt.py b/gr-digital/python/digital/pkt.py index fbdcaa3a66..585a2915c0 100644 --- a/gr-digital/python/digital/pkt.py +++ b/gr-digital/python/digital/pkt.py @@ -1,34 +1,34 @@ # # Copyright 2005, 2006, 2007 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. -# +# + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals from math import pi -from gnuradio import gr +from gnuradio import gr, blocks import gnuradio.gr.gr_threading as _threading -import packet_utils -import digital_swig as digital +from . import packet_utils +from . import digital_swig as digital -try: - from gnuradio import blocks -except ImportError: - import blocks_swig as blocks # ///////////////////////////////////////////////////////////////////////////// # mod/demod with packets as i/o @@ -43,7 +43,7 @@ class mod_pkts(gr.hier_block2): def __init__(self, modulator, preamble=None, access_code=None, msgq_limit=2, pad_for_usrp=True, use_whitener_offset=False, modulate=True): """ - Hierarchical block for sending packets + Hierarchical block for sending packets Packets to be sent are enqueued by calling send_pkt. The output is the complex modulated signal at baseband. @@ -54,29 +54,29 @@ class mod_pkts(gr.hier_block2): msgq_limit: maximum number of messages in message queue (int) pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples use_whitener_offset: If true, start of whitener XOR string is incremented each packet - + See gmsk_mod for remaining parameters """ - gr.hier_block2.__init__(self, "mod_pkts", - gr.io_signature(0, 0, 0), # Input signature - gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + gr.hier_block2.__init__(self, "mod_pkts", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature self._modulator = modulator self._pad_for_usrp = pad_for_usrp self._use_whitener_offset = use_whitener_offset self._whitener_offset = 0 - + if access_code is None: access_code = packet_utils.default_access_code if not packet_utils.is_1_0_string(access_code): - raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + raise ValueError("Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)) self._access_code = access_code - + if preamble is None: preamble = packet_utils.default_preamble if not packet_utils.is_1_0_string(preamble): - raise ValueError, "Invalid preamble %r. Must be string of 1's and 0's" % (preamble,) + raise ValueError("Invalid preamble %r. Must be string of 1's and 0's" % (preamble,)) self._preamble = preamble # accepts messages from the outside world @@ -93,7 +93,7 @@ class mod_pkts(gr.hier_block2): if eof: msg = gr.message(1) # tell self._pkt_input we're not sending any more packets else: - # print "original_payload =", string_to_hex_list(payload) + # print("original_payload =", string_to_hex_list(payload)) pkt = packet_utils.make_packet(payload, self._modulator.samples_per_symbol(), self._modulator.bits_per_symbol(), @@ -101,11 +101,11 @@ class mod_pkts(gr.hier_block2): self._access_code, self._pad_for_usrp, self._whitener_offset) - #print "pkt =", string_to_hex_list(pkt) + #print("pkt =", string_to_hex_list(pkt)) msg = gr.message_from_string(pkt) if self._use_whitener_offset is True: self._whitener_offset = (self._whitener_offset + 1) % 16 - + self._pkt_input.msgq().insert_tail(msg) @@ -120,9 +120,9 @@ class demod_pkts(gr.hier_block2): def __init__(self, demodulator, access_code=None, callback=None, threshold=-1): """ - Hierarchical block for demodulating and deframing packets. + Hierarchical block for demodulating and deframing packets. - The input is the complex modulated signal at baseband. + The input is the complex modulated signal at baseband. Demodulated packets are sent to the handler. Args: @@ -130,17 +130,17 @@ class demod_pkts(gr.hier_block2): access_code: AKA sync vector (string of 1's and 0's) callback: function of two args: ok, payload (ok: bool; payload: string) threshold: detect access_code with up to threshold bits wrong (-1 -> use default) (int) - """ + """ - gr.hier_block2.__init__(self, "demod_pkts", - gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature - gr.io_signature(0, 0, 0)) # Output signature + gr.hier_block2.__init__(self, "demod_pkts", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(0, 0, 0)) # Output signature self._demodulator = demodulator if access_code is None: access_code = packet_utils.default_access_code if not packet_utils.is_1_0_string(access_code): - raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + raise ValueError("Invalid access_code %r. Must be string of 1's and 0's" % (access_code,)) self._access_code = access_code if threshold == -1: @@ -151,7 +151,7 @@ class demod_pkts(gr.hier_block2): self.framer_sink = digital.framer_sink_1(self._rcvd_pktq) self.connect(self, self._demodulator, self.correlator, self.framer_sink) - + self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) diff --git a/gr-digital/python/digital/psk.py b/gr-digital/python/digital/psk.py index 0e0c65ea2b..5518ba55f3 100644 --- a/gr-digital/python/digital/psk.py +++ b/gr-digital/python/digital/psk.py @@ -1,36 +1,40 @@ # # Copyright 2005,2006,2011 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. -# +# """ PSK modulation and demodulation. """ +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + from math import pi, log from cmath import exp -import digital_swig -import modulation_utils -from utils import mod_codes, gray_code -from generic_mod_demod import generic_mod, generic_demod -from generic_mod_demod import shared_mod_args, shared_demod_args +from . import digital_swig +from . import modulation_utils +from .utils import mod_codes, gray_code +from .generic_mod_demod import generic_mod, generic_demod +from .generic_mod_demod import shared_mod_args, shared_demod_args # Default number of points in constellation. _def_constellation_points = 4 @@ -56,7 +60,7 @@ def create_encodings(mod_code, arity, differential): else: raise ValueError('That modulation code is not implemented for this constellation.') return (pre_diff_code, post_diff_code) - + # ///////////////////////////////////////////////////////////////////////////// # PSK constellation # ///////////////////////////////////////////////////////////////////////////// @@ -68,7 +72,7 @@ def psk_constellation(m=_def_constellation_points, mod_code=_def_mod_code, """ k = log(m) / log(2.0) if (k != int(k)): - raise StandardError('Number of constellation points must be a power of two.') + raise Exception('Number of constellation points must be a power of two.') points = [exp(2*pi*(0+1j)*i/m) for i in range(0,m)] pre_diff_code, post_diff_code = create_encodings(mod_code, m, differential) if post_diff_code is not None: @@ -84,7 +88,7 @@ def psk_constellation(m=_def_constellation_points, mod_code=_def_mod_code, class psk_mod(generic_mod): """ Hierarchical block for RRC-filtered PSK modulation. - + The input is a byte stream (unsigned char), treated as a series of packed symbols. Symbols are grouped from MSB to LSB. @@ -118,7 +122,7 @@ class psk_demod(generic_demod): """ Hierarchical block for RRC-filtered PSK modulation. - + The input is a complex modulated signal at baseband. The output is a stream of bytes, each representing a recovered bit. diff --git a/gr-digital/python/digital/psk_constellations.py b/gr-digital/python/digital/psk_constellations.py index d2db4e848b..ce8f45d47b 100755..100644 --- a/gr-digital/python/digital/psk_constellations.py +++ b/gr-digital/python/digital/psk_constellations.py @@ -20,8 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import +from __future__ import unicode_literals import numpy -from constellation_map_generator import * +from .constellation_map_generator import * ''' Note on the naming scheme. Each constellation is named using a prefix diff --git a/gr-digital/python/digital/qa_binary_slicer_fb.py b/gr-digital/python/digital/qa_binary_slicer_fb.py index 93e12dbb8d..0b2879380b 100755..100644 --- a/gr-digital/python/digital/qa_binary_slicer_fb.py +++ b/gr-digital/python/digital/qa_binary_slicer_fb.py @@ -1,24 +1,25 @@ #!/usr/bin/env python # # Copyright 2011-2013 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. -# +# + import random @@ -33,8 +34,8 @@ class test_binary_slicer_fb(gr_unittest.TestCase): self.tb = None def test_binary_slicer_fb(self): - expected_result = ( 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1) - src_data = (-1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1) + expected_result = ( 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1) + src_data = (-1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, 1) src_data = [s + (1 - random.random()) for s in src_data] # add some noise src = blocks.vector_source_f(src_data) op = digital.binary_slicer_fb() @@ -45,11 +46,10 @@ class test_binary_slicer_fb(gr_unittest.TestCase): self.tb.run() # run the graph and wait for it to finish actual_result = dst.data() # fetch the contents of the sink - #print "actual result", actual_result - #print "expected result", expected_result + #print "actual result", actual_result + #print "expected result", expected_result self.assertFloatTuplesAlmostEqual(expected_result, actual_result) if __name__ == '__main__': gr_unittest.run(test_binary_slicer_fb, "test_binary_slicer_fb.xml") - diff --git a/gr-digital/python/digital/qa_burst_shaper.py b/gr-digital/python/digital/qa_burst_shaper.py index 36c6d06479..949a5f573d 100755..100644 --- a/gr-digital/python/digital/qa_burst_shaper.py +++ b/gr-digital/python/digital/qa_burst_shaper.py @@ -21,6 +21,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest from gnuradio import blocks, digital import pmt @@ -121,7 +122,7 @@ class qa_burst_shaper (gr_unittest.TestCase): window = np.concatenate((-2.0*np.ones(5), -4.0*np.ones(5))) tags = (make_length_tag(0, length),) phasing = np.zeros(5) - for i in xrange(5): + for i in range(5): phasing[i] = ((-1.0)**i) expected = np.concatenate((np.zeros(prepad), phasing*window[0:5], np.ones(length), phasing*window[5:10], @@ -154,7 +155,7 @@ class qa_burst_shaper (gr_unittest.TestCase): -4.0*np.ones(5, dtype=complex))) tags = (make_length_tag(0, length),) phasing = np.zeros(5, dtype=complex) - for i in xrange(5): + for i in range(5): phasing[i] = complex((-1.0)**i) expected = np.concatenate((np.zeros(prepad, dtype=complex), phasing*window[0:5], @@ -264,7 +265,7 @@ class qa_burst_shaper (gr_unittest.TestCase): # checks self.assertFloatTuplesAlmostEqual(sink.data(), expected, 6) - for i in xrange(len(etags)): + for i in range(len(etags)): self.assertTrue(compare_tags(sink.tags()[i], etags[i])) def test_tag_gap (self): @@ -303,7 +304,7 @@ class qa_burst_shaper (gr_unittest.TestCase): # checks self.assertFloatTuplesAlmostEqual(sink.data(), expected, 6) - for i in xrange(len(etags)): + for i in range(len(etags)): self.assertTrue(compare_tags(sink.tags()[i], etags[i])) def test_tag_propagation (self): diff --git a/gr-digital/python/digital/qa_chunks_to_symbols.py b/gr-digital/python/digital/qa_chunks_to_symbols.py index 0d80f71d6c..8a4266617f 100755..100644 --- a/gr-digital/python/digital/qa_chunks_to_symbols.py +++ b/gr-digital/python/digital/qa_chunks_to_symbols.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import pmt from gnuradio import gr, gr_unittest, digital, blocks @@ -138,12 +139,12 @@ class test_chunks_to_symbols(gr_unittest.TestCase): def test_sf_callback(self): - constA = [-3, -1, 1, 3] + constA = [-3, -1, 1, 3] constB = [12, -12, 6, -6] src_data = (0, 1, 2, 3, 3, 2, 1, 0) expected_result=(12, -12, 6, -6, -6, 6, -12, 12) - src = blocks.vector_source_s(src_data, False, 1, "") + src = blocks.vector_source_s(src_data, False, 1, "") op = digital.chunks_to_symbols_sf(constA) op.set_symbol_table(constB) dst = blocks.vector_sink_f() @@ -159,7 +160,7 @@ class test_chunks_to_symbols(gr_unittest.TestCase): src_data = (0, 1, 2, 3, 3, 2, 1, 0) expected_result=(12.0+1j, -12.0-1j, 6.0+1j, -6-1j, -6-1j, 6+1j, -12-1j, 12+1j) - src = blocks.vector_source_s(src_data, False, 1, "") + src = blocks.vector_source_s(src_data, False, 1, "") op = digital.chunks_to_symbols_sc(constA) op.set_symbol_table(constB) dst = blocks.vector_sink_c() diff --git a/gr-digital/python/digital/qa_clock_recovery_mm.py b/gr-digital/python/digital/qa_clock_recovery_mm.py index 878ea25c6c..0618ec321c 100755..100644 --- a/gr-digital/python/digital/qa_clock_recovery_mm.py +++ b/gr-digital/python/digital/qa_clock_recovery_mm.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import random import cmath diff --git a/gr-digital/python/digital/qa_cma_equalizer.py b/gr-digital/python/digital/qa_cma_equalizer.py index 6da391f70c..228d951640 100755..100644 --- a/gr-digital/python/digital/qa_cma_equalizer.py +++ b/gr-digital/python/digital/qa_cma_equalizer.py @@ -1,48 +1,49 @@ #!/usr/bin/env python # # Copyright 2006,2007,2010,2011,2013 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. -# +# + from gnuradio import gr, gr_unittest, digital, blocks class test_cma_equalizer_fir(gr_unittest.TestCase): def setUp(self): - self.tb = gr.top_block() + self.tb = gr.top_block() def tearDown(self): - self.tb = None - + self.tb = None + def transform(self, src_data): - SRC = blocks.vector_source_c(src_data, False) - EQU = digital.cma_equalizer_cc(4, 1.0, .001, 1) - DST = blocks.vector_sink_c() - self.tb.connect(SRC, EQU, DST) - self.tb.run() - return DST.data() + SRC = blocks.vector_source_c(src_data, False) + EQU = digital.cma_equalizer_cc(4, 1.0, .001, 1) + DST = blocks.vector_sink_c() + self.tb.connect(SRC, EQU, DST) + self.tb.run() + return DST.data() def test_001_identity(self): - # Constant modulus signal so no adjustments - src_data = (1+0j, 0+1j, -1+0j, 0-1j)*1000 - expected_data = src_data - result = self.transform(src_data) + # Constant modulus signal so no adjustments + src_data = (1+0j, 0+1j, -1+0j, 0-1j)*1000 + expected_data = src_data + result = self.transform(src_data) N = -500 self.assertComplexTuplesAlmostEqual(expected_data[N:], result[N:]) diff --git a/gr-digital/python/digital/qa_constellation.py b/gr-digital/python/digital/qa_constellation.py index 42e49bb059..3436ce6f45 100644 --- a/gr-digital/python/digital/qa_constellation.py +++ b/gr-digital/python/digital/qa_constellation.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import random, math from cmath import exp, pi, log, sqrt @@ -51,7 +53,7 @@ def twod_constell(): def threed_constell(): oned_points = ((1+0j), (0+1j), (-1+0j), (0-1j)) points = [] - r4 = range(0, 4) + r4 = list(range(0, 4)) for ia in r4: for ib in r4: for ic in r4: @@ -143,7 +145,7 @@ def tested_constellations(easy=True, medium=True, difficult=True): diff_poss = (True, False) else: diff_poss = (False,) - poss_args = [[argname, argvalues, 0] for argname, argvalues in poss_args.items()] + poss_args = [[argname, argvalues, 0] for argname, argvalues in list(poss_args.items())] for current_diff in diff_poss: # Add an index into args to keep track of current position in argvalues while True: @@ -211,7 +213,7 @@ class test_constellation(gr_unittest.TestCase): table = digital.soft_dec_table_generator(digital.sd_psk_4_0, prec, Es) c.set_soft_dec_lut(table, prec) - x = sqrt(2.0)/2.0 + x = sqrt(2.0) / 2.0 step = (x.real+x.real) / (2**prec - 1) samples = [ -x-x*1j, -x+x*1j, x+x*1j, x-x*1j, @@ -253,7 +255,7 @@ class test_constellation(gr_unittest.TestCase): table = digital.soft_dec_table(constel, code, prec) c.gen_soft_dec_lut(prec) - x = sqrt(2.0)/2.0 + x = sqrt(2.0) / 2.0 step = (x.real+x.real) / (2**prec - 1) samples = [ -x-x*1j, -x+x*1j, x+x*1j, x-x*1j, @@ -293,7 +295,7 @@ class test_constellation(gr_unittest.TestCase): table = digital.soft_dec_table(constel, code, prec) c.gen_soft_dec_lut(prec) - x = sqrt(2.0)/2.0 + x = sqrt(2.0) / 2.0 step = (x.real+x.real) / (2**prec - 1) samples = [ -x-x*1j, -x+x*1j, x+x*1j, x-x*1j, @@ -322,9 +324,9 @@ class mod_demod(gr.hier_block2): # that they can work with shorts and ints as well as chars. raise ValueError("Constellation cannot contain more than 256 points.") - gr.hier_block2.__init__(self, "mod_demod", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature + gr.hier_block2.__init__(self, "mod_demod", + gr.io_signature(1, 1, gr.sizeof_char), # Input signature + gr.io_signature(1, 1, gr.sizeof_char)) # Output signature arity = constellation.arity() diff --git a/gr-digital/python/digital/qa_constellation_decoder_cb.py b/gr-digital/python/digital/qa_constellation_decoder_cb.py index d3fbce91ba..e7350be553 100755..100644 --- a/gr-digital/python/digital/qa_constellation_decoder_cb.py +++ b/gr-digital/python/digital/qa_constellation_decoder_cb.py @@ -1,24 +1,25 @@ #!/usr/bin/env python # # Copyright 2004,2007,2010-2013 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. -# +# + from gnuradio import gr, gr_unittest, digital, blocks @@ -32,9 +33,9 @@ class test_constellation_decoder(gr_unittest.TestCase): def test_constellation_decoder_cb_bpsk(self): cnst = digital.constellation_bpsk() - src_data = (0.5 + 0.5j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, + src_data = (0.5 + 0.5j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, 0.8 + 1.0j, -0.5 + 0.1j, 0.1 - 1.2j) - expected_result = ( 1, 1, 0, 0, + expected_result = ( 1, 1, 0, 0, 1, 0, 1) src = blocks.vector_source_c(src_data) op = digital.constellation_decoder_cb(cnst.base()) @@ -45,18 +46,18 @@ class test_constellation_decoder(gr_unittest.TestCase): self.tb.run() # run the graph and wait for it to finish actual_result = dst.data() # fetch the contents of the sink - #print "actual result", actual_result - #print "expected result", expected_result + #print "actual result", actual_result + #print "expected result", expected_result self.assertFloatTuplesAlmostEqual(expected_result, actual_result) def _test_constellation_decoder_cb_qpsk(self): cnst = digital.constellation_qpsk() - src_data = (0.5 + 0.5j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, + src_data = (0.5 + 0.5j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, 0.8 + 1.0j, -0.5 + 0.1j, 0.1 - 1.2j) - expected_result = ( 3, 1, 0, 2, + expected_result = ( 3, 1, 0, 2, 3, 2, 1) src = blocks.vector_source_c(src_data) - op = digital_swig.constellation_decoder_cb(cnst.base()) + op = digital.constellation_decoder_cb(cnst.base()) dst = blocks.vector_sink_b() self.tb.connect(src, op) @@ -64,11 +65,10 @@ class test_constellation_decoder(gr_unittest.TestCase): self.tb.run() # run the graph and wait for it to finish actual_result = dst.data() # fetch the contents of the sink - #print "actual result", actual_result - #print "expected result", expected_result + #print "actual result", actual_result + #print "expected result", expected_result self.assertFloatTuplesAlmostEqual(expected_result, actual_result) if __name__ == '__main__': gr_unittest.run(test_constellation_decoder, "test_constellation_decoder.xml") - diff --git a/gr-digital/python/digital/qa_constellation_receiver.py b/gr-digital/python/digital/qa_constellation_receiver.py index 9565c7089e..bcf4b18118 100755..100644 --- a/gr-digital/python/digital/qa_constellation_receiver.py +++ b/gr-digital/python/digital/qa_constellation_receiver.py @@ -1,24 +1,28 @@ #!/usr/bin/env python # # Copyright 2011,2013 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. -# +# + +from __future__ import print_function +from __future__ import absolute_import + import random import math @@ -53,12 +57,13 @@ TIMING_OFFSET = 1.0 FREQ_BW = 2*math.pi/100.0 PHASE_BW = 2*math.pi/100.0 + class channel_model(gr.hier_block2): def __init__(self, noise_voltage, freq, timing): - gr.hier_block2.__init__(self, "channel_model", - gr.io_signature(1, 1, gr.sizeof_gr_complex), + gr.hier_block2.__init__(self, "channel_model", + gr.io_signature(1, 1, gr.sizeof_gr_complex), gr.io_signature(1, 1, gr.sizeof_gr_complex)) - + timing_offset = filter.fractional_resampler_cc(0, timing) noise_adder = blocks.add_cc() @@ -74,16 +79,16 @@ class channel_model(gr.hier_block2): self.connect(mixer_offset, (noise_adder,1)) self.connect(noise, (noise_adder,0)) self.connect(noise_adder, self) - + class test_constellation_receiver(gr_unittest.TestCase): - + # We ignore the first half of the output data since often it takes # a while for the receiver to lock on. ignore_fraction = 0.8 max_data_length = DATA_LENGTH * 6 max_num_samples = 1000 - + def test_basic(self): """ Tests a bunch of different constellations by using generic @@ -172,7 +177,7 @@ class rec_test_tb(gr.top_block): super(rec_test_tb, self).__init__() # Transmission Blocks if src_data is None: - self.src_data = tuple([rndm.randint(0,1) for i in range(0, data_length)]) + self.src_data = tuple([random.randint(0,1) for i in range(0, data_length)]) else: self.src_data = src_data packer = blocks.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) @@ -182,7 +187,7 @@ class rec_test_tb(gr.top_block): if freq_offset: channel = channel_model(NOISE_VOLTAGE, FREQUENCY_OFFSET, TIMING_OFFSET) else: - channel = channel_model(NOISE_VOLTAGE, 0, TIMING_OFFSET) + channel = channel_model(NOISE_VOLTAGE, 0, TIMING_OFFSET) # Receiver Blocks if freq_offset: demod = generic_demod(constellation, differential=differential, diff --git a/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py b/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py index 872aed0157..629d52c0a4 100644 --- a/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py +++ b/gr-digital/python/digital/qa_constellation_soft_decoder_cf.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks from math import sqrt from numpy import random, vectorize @@ -36,7 +37,7 @@ class test_constellation_soft_decoder(gr_unittest.TestCase): cnst_pts, code = const_gen() Es = max([abs(c) for c in cnst_pts]) lut = digital.soft_dec_table_generator(const_sd_gen, prec, Es) - expected_result = list() + expected_result = list() for s in src_data: res = digital.calc_soft_dec_from_table(s, lut, prec, sqrt(2.0)) expected_result += res @@ -52,14 +53,14 @@ class test_constellation_soft_decoder(gr_unittest.TestCase): self.tb.run() actual_result = dst.data() # fetch the contents of the sink - #print "actual result", actual_result - #print "expected result", expected_result + #print "actual result", actual_result + #print "expected result", expected_result self.assertFloatTuplesAlmostEqual(expected_result, actual_result, 5) def helper_no_lut(self, prec, src_data, const_gen, const_sd_gen): cnst_pts, code = const_gen() cnst = digital.constellation_calcdist(cnst_pts, code, 2, 1) - expected_result = list() + expected_result = list() for s in src_data: res = digital.calc_soft_dec(s, cnst.points(), code) expected_result += res @@ -73,8 +74,8 @@ class test_constellation_soft_decoder(gr_unittest.TestCase): self.tb.run() actual_result = dst.data() # fetch the contents of the sink - #print "actual result", actual_result - #print "expected result", expected_result + #print "actual result", actual_result + #print "expected result", expected_result # Double vs. float precision issues between Python and C++, so # use only 4 decimals in comparisons. diff --git a/gr-digital/python/digital/qa_correlate_access_code.py b/gr-digital/python/digital/qa_correlate_access_code.py index 0302e81313..405147b987 100755..100644 --- a/gr-digital/python/digital/qa_correlate_access_code.py +++ b/gr-digital/python/digital/qa_correlate_access_code.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' @@ -35,7 +36,7 @@ def string_to_1_0_list(s): return r def to_1_0_string(L): - return ''.join(map(lambda x: chr(x + ord('0')), L)) + return ''.join([chr(x + ord('0')) for x in L]) class test_correlate_access_code(gr_unittest.TestCase): diff --git a/gr-digital/python/digital/qa_correlate_access_code_XX_ts.py b/gr-digital/python/digital/qa_correlate_access_code_XX_ts.py index 5429ce1e07..7666c3bda8 100755..100644 --- a/gr-digital/python/digital/qa_correlate_access_code_XX_ts.py +++ b/gr-digital/python/digital/qa_correlate_access_code_XX_ts.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks import pmt @@ -35,7 +36,7 @@ def string_to_1_0_list(s): return r def to_1_0_string(L): - return ''.join(map(lambda x: chr(x + ord('0')), L)) + return ''.join([chr(x + ord('0')) for x in L]) class test_correlate_access_code_XX_ts(gr_unittest.TestCase): @@ -51,7 +52,7 @@ class test_correlate_access_code_XX_ts(gr_unittest.TestCase): packet = header + payload pad = (0,) * 64 src_data = (0, 0, 1, 1, 1, 1, 0, 1, 1) + tuple(string_to_1_0_list(packet)) + pad - expected = tuple(map(long, src_data[9+32:-len(pad)])) + expected = tuple(map(int, src_data[9+32:-len(pad)])) src = blocks.vector_source_b(src_data) op = digital.correlate_access_code_bb_ts("1011", 0, "sync") dst = blocks.vector_sink_b() diff --git a/gr-digital/python/digital/qa_correlate_access_code_tag.py b/gr-digital/python/digital/qa_correlate_access_code_tag.py index 378333c286..be5848d9a9 100755..100644 --- a/gr-digital/python/digital/qa_correlate_access_code_tag.py +++ b/gr-digital/python/digital/qa_correlate_access_code_tag.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' @@ -35,7 +36,7 @@ def string_to_1_0_list(s): return r def to_1_0_string(L): - return ''.join(map(lambda x: chr(x + ord('0')), L)) + return ''.join([chr(x + ord('0')) for x in L]) class test_correlate_access_code(gr_unittest.TestCase): diff --git a/gr-digital/python/digital/qa_costas_loop_cc.py b/gr-digital/python/digital/qa_costas_loop_cc.py index e48f45cc22..283a9199df 100755..100644 --- a/gr-digital/python/digital/qa_costas_loop_cc.py +++ b/gr-digital/python/digital/qa_costas_loop_cc.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import random import cmath @@ -57,7 +59,7 @@ class test_costas_loop_cc(gr_unittest.TestCase): order = 2 self.test = digital.costas_loop_cc(natfreq, order) - data = [complex(2*random.randint(0,1)-1, 0) for i in xrange(100)] + data = [complex(2*random.randint(0,1)-1, 0) for i in range(100)] self.src = blocks.vector_source_c(data, False) self.snk = blocks.vector_sink_c() @@ -76,7 +78,7 @@ class test_costas_loop_cc(gr_unittest.TestCase): self.test = digital.costas_loop_cc(natfreq, order) rot = cmath.exp(0.2j) # some small rotation - data = [complex(2*random.randint(0,1)-1, 0) for i in xrange(100)] + data = [complex(2*random.randint(0,1)-1, 0) for i in range(100)] N = 40 # settling time expected_result = data[N:] @@ -102,7 +104,7 @@ class test_costas_loop_cc(gr_unittest.TestCase): rot = cmath.exp(0.2j) # some small rotation data = [complex(2*random.randint(0,1)-1, 2*random.randint(0,1)-1) - for i in xrange(100)] + for i in range(100)] N = 40 # settling time expected_result = data[N:] @@ -126,9 +128,9 @@ class test_costas_loop_cc(gr_unittest.TestCase): order = 8 self.test = digital.costas_loop_cc(natfreq, order) - rot = cmath.exp(-cmath.pi/8.0j) # rotate to match Costas rotation + rot = cmath.exp(-cmath.pi / 8.0j) # rotate to match Costas rotation const = psk.psk_constellation(order) - data = [random.randint(0,7) for i in xrange(100)] + data = [random.randint(0,7) for i in range(100)] data = [2*rot*const.points()[d] for d in data] N = 40 # settling time diff --git a/gr-digital/python/digital/qa_cpm.py b/gr-digital/python/digital/qa_cpm.py index 6468ed507b..47a6fa23b4 100755..100644 --- a/gr-digital/python/digital/qa_cpm.py +++ b/gr-digital/python/digital/qa_cpm.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import numpy from gnuradio import gr, gr_unittest, digital, analog, blocks diff --git a/gr-digital/python/digital/qa_crc32.py b/gr-digital/python/digital/qa_crc32.py index 9252825ad6..6d3d2fa3ce 100755..100644 --- a/gr-digital/python/digital/qa_crc32.py +++ b/gr-digital/python/digital/qa_crc32.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import random import cmath diff --git a/gr-digital/python/digital/qa_crc32_bb.py b/gr-digital/python/digital/qa_crc32_bb.py index 5e45bfb1b0..53ea6f3deb 100755..100644 --- a/gr-digital/python/digital/qa_crc32_bb.py +++ b/gr-digital/python/digital/qa_crc32_bb.py @@ -19,6 +19,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks, digital import pmt @@ -33,7 +34,7 @@ class qa_crc32_bb (gr_unittest.TestCase): def test_001_crc_len (self): """ Make sure the output of a CRC set is 4 bytes longer than the input. """ - data = range(16) + data = list(range(16)) src = blocks.vector_source_b(data) crc = digital.crc32_bb(False, self.tsb_key) sink = blocks.tsb_vector_sink_b(tsb_key=self.tsb_key) @@ -69,7 +70,7 @@ class qa_crc32_bb (gr_unittest.TestCase): def test_003_crc_correct_lentag (self): tag_name = "length" pack_len = 8 - packets = range(pack_len*2) + packets = list(range(pack_len*2)) tag1 = gr.tag_t() tag1.offset = 0 tag1.key = pmt.string_to_symbol(tag_name) @@ -107,7 +108,7 @@ class qa_crc32_bb (gr_unittest.TestCase): tags_found = {'tag1': False, 'tag2': False, 'tag3': False} for tag in sink.tags(): key = pmt.symbol_to_string(tag.key) - if key in correct_offsets.keys(): + if key in list(correct_offsets.keys()): tags_found[key] = True self.assertEqual(correct_offsets[key], tag.offset) self.assertTrue(all(tags_found.values())) @@ -160,7 +161,7 @@ class qa_crc32_bb (gr_unittest.TestCase): def test_006_crc_len (self): """ Make sure the output of a CRC set is 32 (unpacked) bytes longer than the input. """ - data = range(16) + data = list(range(16)) src = blocks.vector_source_b(data) crc = digital.crc32_bb(False, self.tsb_key, False) sink = blocks.tsb_vector_sink_b(tsb_key=self.tsb_key) @@ -196,7 +197,7 @@ class qa_crc32_bb (gr_unittest.TestCase): def test_008_crc_correct_lentag (self): tag_name = "length" pack_len = 8 - packets = range(pack_len*2) + packets = list(range(pack_len*2)) tag1 = gr.tag_t() tag1.offset = 0 tag1.key = pmt.string_to_symbol(tag_name) @@ -234,7 +235,7 @@ class qa_crc32_bb (gr_unittest.TestCase): tags_found = {'tag1': False, 'tag2': False, 'tag3': False} for tag in sink.tags(): key = pmt.symbol_to_string(tag.key) - if key in correct_offsets.keys(): + if key in list(correct_offsets.keys()): tags_found[key] = True self.assertEqual(correct_offsets[key], tag.offset) self.assertTrue(all(tags_found.values())) diff --git a/gr-digital/python/digital/qa_diff_encoder.py b/gr-digital/python/digital/qa_diff_encoder.py index 410b937fbc..58d757d0c2 100755..100644 --- a/gr-digital/python/digital/qa_diff_encoder.py +++ b/gr-digital/python/digital/qa_diff_encoder.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import random from gnuradio import gr, gr_unittest, digital, blocks diff --git a/gr-digital/python/digital/qa_diff_phasor_cc.py b/gr-digital/python/digital/qa_diff_phasor_cc.py index 7cae4870cc..72063cf92c 100755..100644 --- a/gr-digital/python/digital/qa_diff_phasor_cc.py +++ b/gr-digital/python/digital/qa_diff_phasor_cc.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks class test_diff_phasor(gr_unittest.TestCase): diff --git a/gr-digital/python/digital/qa_digital.py b/gr-digital/python/digital/qa_digital.py index 63a167dece..d443b08fde 100755..100644 --- a/gr-digital/python/digital/qa_digital.py +++ b/gr-digital/python/digital/qa_digital.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital class test_digital(gr_unittest.TestCase): diff --git a/gr-digital/python/digital/qa_fll_band_edge.py b/gr-digital/python/digital/qa_fll_band_edge.py index 17c5fa85f8..a4859565ec 100755..100644 --- a/gr-digital/python/digital/qa_fll_band_edge.py +++ b/gr-digital/python/digital/qa_fll_band_edge.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import random import math @@ -48,7 +50,7 @@ class test_fll_band_edge_cc(gr_unittest.TestCase): # Create a set of 1's and -1's, pulse shape and interpolate to sps random.seed(0) - data = [2.0*random.randint(0, 2) - 1.0 for i in xrange(200)] + data = [2.0*random.randint(0, 2) - 1.0 for i in range(200)] self.src = blocks.vector_source_c(data, False) self.rrc = filter.interp_fir_filter_ccf(sps, rrc_taps) diff --git a/gr-digital/python/digital/qa_framer_sink.py b/gr-digital/python/digital/qa_framer_sink.py index 4b260c14ec..555bc121f8 100755..100644 --- a/gr-digital/python/digital/qa_framer_sink.py +++ b/gr-digital/python/digital/qa_framer_sink.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' @@ -34,7 +35,7 @@ def string_to_1_0_list(s): return r def to_1_0_string(L): - return ''.join(map(lambda x: chr(x + ord('0')), L)) + return ''.join([chr(x + ord('0')) for x in L]) class test_framker_sink(gr_unittest.TestCase): diff --git a/gr-digital/python/digital/qa_glfsr_source.py b/gr-digital/python/digital/qa_glfsr_source.py index f39c408198..2c1921e117 100755..100644 --- a/gr-digital/python/digital/qa_glfsr_source.py +++ b/gr-digital/python/digital/qa_glfsr_source.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks class test_glfsr_source(gr_unittest.TestCase): @@ -32,8 +33,8 @@ class test_glfsr_source(gr_unittest.TestCase): def test_000_make_b(self): src = digital.glfsr_source_b(16) - self.assertEquals(src.mask(), 0x8016) - self.assertEquals(src.period(), 2**16-1) + self.assertEqual(src.mask(), 0x8016) + self.assertEqual(src.period(), 2**16-1) def test_001_degree_b(self): self.assertRaises(RuntimeError, @@ -46,11 +47,11 @@ class test_glfsr_source(gr_unittest.TestCase): src = digital.glfsr_source_b(degree, False) b2f = digital.chunks_to_symbols_bf((-1.0,1.0), 1) dst = blocks.vector_sink_f() - del self.tb # Discard existing top block - self.tb = gr.top_block() + del self.tb # Discard existing top block + self.tb = gr.top_block() self.tb.connect(src, b2f, dst) self.tb.run() - self.tb.disconnect_all() + self.tb.disconnect_all() actual_result = dst.data() R = auto_correlate(actual_result) self.assertEqual(R[0], float(len(R))) # Auto-correlation peak at origin @@ -59,8 +60,8 @@ class test_glfsr_source(gr_unittest.TestCase): def test_003_make_f(self): src = digital.glfsr_source_f(16) - self.assertEquals(src.mask(), 0x8016) - self.assertEquals(src.period(), 2**16-1) + self.assertEqual(src.mask(), 0x8016) + self.assertEqual(src.period(), 2**16-1) def test_004_degree_f(self): self.assertRaises(RuntimeError, @@ -71,8 +72,8 @@ class test_glfsr_source(gr_unittest.TestCase): for degree in range(1,11): # Higher degrees take too long to correlate src = digital.glfsr_source_f(degree, False) dst = blocks.vector_sink_f() - del self.tb # Discard existing top block - self.tb = gr.top_block() + del self.tb # Discard existing top block + self.tb = gr.top_block() self.tb.connect(src, dst) self.tb.run() diff --git a/gr-digital/python/digital/qa_hdlc_framer.py b/gr-digital/python/digital/qa_hdlc_framer.py index 6fed264546..4aa8280e83 100755..100644 --- a/gr-digital/python/digital/qa_hdlc_framer.py +++ b/gr-digital/python/digital/qa_hdlc_framer.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks import pmt import numpy @@ -45,7 +46,7 @@ class test_hdlc_framer(gr_unittest.TestCase): self.tb.msg_connect(deframe, "out", debug, "store") self.tb.start() msg = pmt.cons(pmt.PMT_NIL, pmt.init_u8vector(len(src_data),src_data)) - for i in xrange(npkts): + for i in range(npkts): frame.to_basic_block()._post(pmt.intern("in"), msg) sleep(0.2) self.tb.stop() @@ -53,7 +54,7 @@ class test_hdlc_framer(gr_unittest.TestCase): rxmsg = debug.get_message(0) result_len = pmt.blob_length(pmt.cdr(rxmsg)) msg_data = [] - for j in xrange(result_len): + for j in range(result_len): msg_data.append(pmt.u8vector_ref(pmt.cdr(rxmsg), j)) self.assertEqual(src_data, msg_data) diff --git a/gr-digital/python/digital/qa_header_payload_demux.py b/gr-digital/python/digital/qa_header_payload_demux.py index f36d71067c..d77f7c689d 100755..100644 --- a/gr-digital/python/digital/qa_header_payload_demux.py +++ b/gr-digital/python/digital/qa_header_payload_demux.py @@ -20,15 +20,19 @@ # from __future__ import print_function +from __future__ import division + import time import random import numpy + from gnuradio import gr from gnuradio import gr_unittest from gnuradio import digital from gnuradio import blocks import pmt + def make_tag(key, value, offset): tag = gr.tag_t() tag.offset = offset @@ -55,7 +59,7 @@ class HeaderToMessageBlock(gr.sync_block): self.msg_count = 0 def work(self, input_items, output_items): - for i in xrange(len(input_items[0])/self.header_len): + for i in range(len(input_items[0]) // self.header_len): msg = self.messages[self.msg_count] or False #print("Sending message: {0}".format(msg)) self.message_port_pub(pmt.intern('header_data'), pmt.to_pmt(msg)) @@ -227,7 +231,7 @@ class qa_header_payload_demux (gr_unittest.TestCase): header_padding = 1 payload = tuple(range(5, 20)) data_signal = (0,) * n_zeros + header + payload - trigger_signal = [0,] * len(data_signal) + trigger_signal = [0] * len(data_signal) trigger_signal[n_zeros] = 1 # This is dropped: testtag1 = make_tag('tag1', 0, 0) @@ -296,7 +300,7 @@ class qa_header_payload_demux (gr_unittest.TestCase): payload_offset = -1 payload = tuple(range(5, 20)) data_signal = (0,) * n_zeros + header + payload + (0,) * 100 - trigger_signal = [0,] * len(data_signal) + trigger_signal = [0] * len(data_signal) trigger_signal[n_zeros] = 1 # This goes on output 1, item 3 + 1 (for payload offset) testtag4 = make_tag('tag4', 314, n_zeros + len(header) + 3) @@ -379,13 +383,13 @@ class qa_header_payload_demux (gr_unittest.TestCase): data_src = blocks.vector_source_f(data_signal, False, tags=(testtag1, testtag2, testtag3, testtag4)) trigger_src = blocks.vector_source_b(trigger_signal, False) hpd = digital.header_payload_demux( - len(header) / items_per_symbol, # Header length (in symbols) - items_per_symbol, # Items per symbols - gi, # Items per guard time - "frame_len", # Frame length tag key - "detect", # Trigger tag key - True, # Output symbols (not items) - gr.sizeof_float # Bytes per item + len(header) // items_per_symbol, # Header length (in symbols) + items_per_symbol, # Items per symbols + gi, # Items per guard time + "frame_len", # Frame length tag key + "detect", # Trigger tag key + True, # Output symbols (not items) + gr.sizeof_float # Bytes per item ) self.assertEqual(pmt.length(hpd.message_ports_in()), 2) #extra system port defined for you header_sink = blocks.vector_sink_f(items_per_symbol) @@ -548,7 +552,7 @@ class qa_header_payload_demux (gr_unittest.TestCase): indexes = [] burst_sizes = [] total_payload_len = 0 - for burst_count in xrange(n_bursts): + for burst_count in range(n_bursts): gap_size = random.randint(0, max_gap) signal += [0] * gap_size is_failure = random.random() < fail_rate @@ -577,7 +581,7 @@ class qa_header_payload_demux (gr_unittest.TestCase): ### Go, go, go # The divide-by-20 means we'll usually get the same random seed # between the first run and the XML run. - random_seed = int(time.time()/20) + random_seed = int(time.time() / 20) random.seed(random_seed) print("Random seed: {0}".format(random_seed)) n_bursts = 400 @@ -621,4 +625,3 @@ class qa_header_payload_demux (gr_unittest.TestCase): if __name__ == '__main__': gr_unittest.run(qa_header_payload_demux, "qa_header_payload_demux.xml") - diff --git a/gr-digital/python/digital/qa_lfsr.py b/gr-digital/python/digital/qa_lfsr.py index 8b8872ab3b..8cc97a0185 100755..100644 --- a/gr-digital/python/digital/qa_lfsr.py +++ b/gr-digital/python/digital/qa_lfsr.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import math from gnuradio import gr, gr_unittest, digital @@ -37,7 +38,7 @@ class test_lfsr(gr_unittest.TestCase): l = digital.lfsr(1, 1, reglen) result_data = [] - for i in xrange(4*(reglen+1)): + for i in range(4*(reglen+1)): result_data.append(l.next_bit()) expected_result = 4*([1,] + reglen*[0,]) diff --git a/gr-digital/python/digital/qa_lms_equalizer.py b/gr-digital/python/digital/qa_lms_equalizer.py index 7768c1f078..fa79993f84 100755..100644 --- a/gr-digital/python/digital/qa_lms_equalizer.py +++ b/gr-digital/python/digital/qa_lms_equalizer.py @@ -1,51 +1,52 @@ #!/usr/bin/env python # # Copyright 2006,2007,2010,2011,2013 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. -# +# + from gnuradio import gr, gr_unittest, digital, blocks class test_lms_dd_equalizer(gr_unittest.TestCase): def setUp(self): - self.tb = gr.top_block() + self.tb = gr.top_block() def tearDown(self): - self.tb = None - + self.tb = None + def transform(self, src_data, gain, const): - SRC = blocks.vector_source_c(src_data, False) - EQU = digital.lms_dd_equalizer_cc(4, gain, 1, const.base()) - DST = blocks.vector_sink_c() - self.tb.connect(SRC, EQU, DST) - self.tb.run() - return DST.data() + SRC = blocks.vector_source_c(src_data, False) + EQU = digital.lms_dd_equalizer_cc(4, gain, 1, const.base()) + DST = blocks.vector_sink_c() + self.tb.connect(SRC, EQU, DST) + self.tb.run() + return DST.data() def test_001_identity(self): - # Constant modulus signal so no adjustments + # Constant modulus signal so no adjustments const = digital.constellation_qpsk() - src_data = const.points()*1000 + src_data = const.points()*1000 N = 100 # settling time - expected_data = src_data[N:] - result = self.transform(src_data, 0.1, const)[N:] + expected_data = src_data[N:] + result = self.transform(src_data, 0.1, const)[N:] N = -500 self.assertComplexTuplesAlmostEqual(expected_data[N:], result[N:], 5) diff --git a/gr-digital/python/digital/qa_map.py b/gr-digital/python/digital/qa_map.py index 604fa084d9..0b71b2814a 100755..100644 --- a/gr-digital/python/digital/qa_map.py +++ b/gr-digital/python/digital/qa_map.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks class test_map(gr_unittest.TestCase): @@ -32,7 +33,7 @@ class test_map(gr_unittest.TestCase): def helper(self, symbols): src_data = [0, 1, 2, 3, 0, 1, 2, 3] - expected_data = map(lambda x: symbols[x], src_data) + expected_data = [symbols[x] for x in src_data] src = blocks.vector_source_b(src_data) op = digital.map_bb(symbols) dst = blocks.vector_sink_b() diff --git a/gr-digital/python/digital/qa_mpsk_snr_est.py b/gr-digital/python/digital/qa_mpsk_snr_est.py index 97d31c7686..dcc7dcc694 100755..100644 --- a/gr-digital/python/digital/qa_mpsk_snr_est.py +++ b/gr-digital/python/digital/qa_mpsk_snr_est.py @@ -19,6 +19,7 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. # + import random from gnuradio import gr, gr_unittest, digital, blocks @@ -34,15 +35,15 @@ class test_mpsk_snr_est(gr_unittest.TestCase): random.seed(0) # make repeatable N = 10000 - self._noise = [get_n_cplx() for i in xrange(N)] - self._bits = [get_cplx() for i in xrange(N)] + self._noise = [get_n_cplx() for i in range(N)] + self._bits = [get_cplx() for i in range(N)] def tearDown(self): self.tb = None def mpsk_snr_est_setup(self, op): result = [] - for i in xrange(1,6): + for i in range(1,6): src_data = [b+(i*n) for b,n in zip(self._bits, self._noise)] src = blocks.vector_source_c(src_data) @@ -57,7 +58,7 @@ class test_mpsk_snr_est(gr_unittest.TestCase): return result def test_mpsk_snr_est_simple(self): - expected_result = [8.20, 4.99, 3.23, 2.01, 1.03] + expected_result = [8.20, 4.99, 3.23, 2.01, 1.03] N = 10000 alpha = 0.001 @@ -67,7 +68,7 @@ class test_mpsk_snr_est(gr_unittest.TestCase): self.assertFloatTuplesAlmostEqual(expected_result, actual_result, 2) def test_mpsk_snr_est_skew(self): - expected_result = [8.31, 1.83, -1.68, -3.56, -4.68] + expected_result = [8.31, 1.83, -1.68, -3.56, -4.68] N = 10000 alpha = 0.001 @@ -77,7 +78,7 @@ class test_mpsk_snr_est(gr_unittest.TestCase): self.assertFloatTuplesAlmostEqual(expected_result, actual_result, 2) def test_mpsk_snr_est_m2m4(self): - expected_result = [8.01, 3.19, 1.97, 2.15, 2.65] + expected_result = [8.01, 3.19, 1.97, 2.15, 2.65] N = 10000 alpha = 0.001 @@ -87,7 +88,7 @@ class test_mpsk_snr_est(gr_unittest.TestCase): self.assertFloatTuplesAlmostEqual(expected_result, actual_result, 2) def test_mpsk_snr_est_svn(self): - expected_result = [7.91, 3.01, 1.77, 1.97, 2.49] + expected_result = [7.91, 3.01, 1.77, 1.97, 2.49] N = 10000 alpha = 0.001 @@ -97,10 +98,10 @@ class test_mpsk_snr_est(gr_unittest.TestCase): self.assertFloatTuplesAlmostEqual(expected_result, actual_result, 2) def test_probe_mpsk_snr_est_m2m4(self): - expected_result = [8.01, 3.19, 1.97, 2.15, 2.65] + expected_result = [8.01, 3.19, 1.97, 2.15, 2.65] actual_result = [] - for i in xrange(1,6): + for i in range(1,6): src_data = [b+(i*n) for b,n in zip(self._bits, self._noise)] src = blocks.vector_source_c(src_data) diff --git a/gr-digital/python/digital/qa_ofdm_carrier_allocator_cvc.py b/gr-digital/python/digital/qa_ofdm_carrier_allocator_cvc.py index befb15ac4a..4ffe61b8ea 100755..100644 --- a/gr-digital/python/digital/qa_ofdm_carrier_allocator_cvc.py +++ b/gr-digital/python/digital/qa_ofdm_carrier_allocator_cvc.py @@ -1,23 +1,24 @@ #!/usr/bin/env python # Copyright 2012-2014 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. -# +# + from gnuradio import gr, gr_unittest, digital, blocks import pmt @@ -41,7 +42,7 @@ class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase): pilot_symbols = ((1j,),) occupied_carriers = ((0, 1, 2),) pilot_carriers = ((3,),) - sync_word = (range(fft_len),) + sync_word = (list(range(fft_len)),) expected_result = tuple(sync_word[0] + [1j, 0, 0, 1, 2, 3]) # ^ DC carrier src = blocks.vector_source_c(tx_symbols, False, 1) @@ -164,7 +165,7 @@ class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase): - add some random tags - don't shift """ - tx_symbols = range(1, 16); # 15 symbols + tx_symbols = list(range(1, 16)); # 15 symbols pilot_symbols = ((1j, 2j), (3j, 4j)) occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) pilot_carriers = ((2, 13), (3, 12)) @@ -203,7 +204,7 @@ class qa_digital_carrier_allocator_cvc (gr_unittest.TestCase): correct_offsets = {'tag1': 0, 'tag2': 1, 'tag3': 3, 'tag4': 5} for tag in sink.tags(): key = pmt.symbol_to_string(tag.key) - if key in tags_found.keys(): + if key in list(tags_found.keys()): tags_found[key] = True self.assertEqual(correct_offsets[key], tag.offset) self.assertTrue(all(tags_found.values())) diff --git a/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py b/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py index d63b65d018..e39247da0a 100755..100644 --- a/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py +++ b/gr-digital/python/digital/qa_ofdm_chanest_vcvc.py @@ -19,6 +19,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import sys import numpy import random @@ -203,7 +205,7 @@ class qa_ofdm_chanest_vcvc (gr_unittest.TestCase): tx_data = shift_tuple(sync_symbol1, carr_offset) + \ shift_tuple(sync_symbol2, carr_offset) + \ shift_tuple(data_symbol, carr_offset) - channel = range(fft_len) + channel = list(range(fft_len)) src = blocks.vector_source_c(tx_data, False, fft_len) chan = blocks.multiply_const_vcc(channel) chanest = digital.ofdm_chanest_vcvc(sync_symbol1, sync_symbol2, 1) @@ -234,7 +236,7 @@ class qa_ofdm_chanest_vcvc (gr_unittest.TestCase): n_iter = 20 # The more the accurater def run_flow_graph(sync_sym1, sync_sym2, data_sym): top_block = gr.top_block() - carr_offset = random.randint(-max_offset/2, max_offset/2) * 2 + carr_offset = random.randint(-max_offset / 2, max_offset / 2) * 2 tx_data = shift_tuple(sync_sym1, carr_offset) + \ shift_tuple(sync_sym2, carr_offset) + \ shift_tuple(data_sym, carr_offset) @@ -265,14 +267,14 @@ class qa_ofdm_chanest_vcvc (gr_unittest.TestCase): rx_sym_est[i] = (sink.data()[i] / channel_est[i]).real return (carr_offset, list(shift_tuple(rx_sym_est, -carr_offset_hat))) bit_errors = 0 - for k in xrange(n_iter): + for k in range(n_iter): sync_sym = [(random.randint(0, 1) * 2 - 1) * syncsym_mask[i] for i in range(fft_len)] ref_sym = [(random.randint(0, 1) * 2 - 1) * carrier_mask[i] for i in range(fft_len)] data_sym = [(random.randint(0, 1) * 2 - 1) * carrier_mask[i] for i in range(fft_len)] data_sym[26] = 1 (carr_offset, rx_sym) = run_flow_graph(sync_sym, ref_sym, data_sym) rx_sym_est = [0,] * fft_len - for i in xrange(fft_len): + for i in range(fft_len): if carrier_mask[i] == 0: continue rx_sym_est[i] = {True: 1, False: -1}[rx_sym[i] > 0] diff --git a/gr-digital/python/digital/qa_ofdm_cyclic_prefixer.py b/gr-digital/python/digital/qa_ofdm_cyclic_prefixer.py index ecc1c426d6..fc486fa6a2 100755..100644 --- a/gr-digital/python/digital/qa_ofdm_cyclic_prefixer.py +++ b/gr-digital/python/digital/qa_ofdm_cyclic_prefixer.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, digital, blocks import pmt @@ -37,7 +39,7 @@ class test_ofdm_cyclic_prefixer (gr_unittest.TestCase): cp_len = 2 expected_result = (6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7) - src = blocks.vector_source_c(range(fft_len) * 2, False, fft_len) + src = blocks.vector_source_c(list(range(fft_len)) * 2, False, fft_len) cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len) sink = blocks.vector_sink_c() self.tb.connect(src, cp, sink) @@ -49,9 +51,9 @@ class test_ofdm_cyclic_prefixer (gr_unittest.TestCase): fft_len = 8 cp_len = 2 rolloff = 2 - expected_result = (7.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 - 7.0/2+1.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8) - src = blocks.vector_source_c(range(1, fft_len+1) * 2, False, fft_len) + expected_result = (7.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 + 7.0 / 2+1.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8) + src = blocks.vector_source_c(list(range(1, fft_len+1)) * 2, False, fft_len) cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, rolloff) sink = blocks.vector_sink_c() self.tb.connect(src, cp, sink) @@ -63,13 +65,13 @@ class test_ofdm_cyclic_prefixer (gr_unittest.TestCase): fft_len = 8 cp_len = 2 tag_name = "ts_last" - expected_result = (7.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 - 7.0/2+1.0/2, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1.0/2) + expected_result = (7.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, # 1.0/2 + 7.0 / 2+1.0 / 2, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1.0 / 2) tag2 = gr.tag_t() tag2.offset = 1 tag2.key = pmt.string_to_symbol("random_tag") tag2.value = pmt.from_long(42) - src = blocks.vector_source_c(range(1, fft_len+1) * 2, False, fft_len, (tag2,)) + src = blocks.vector_source_c(list(range(1, fft_len+1)) * 2, False, fft_len, (tag2,)) cp = digital.ofdm_cyclic_prefixer(fft_len, fft_len + cp_len, 2, tag_name) sink = blocks.tsb_vector_sink_c(tsb_key=tag_name) self.tb.connect(src, blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, 2, tag_name), cp, sink) diff --git a/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py b/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py index 1b3ffb7738..482147e33a 100755..100644 --- a/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py +++ b/gr-digital/python/digital/qa_ofdm_frame_equalizer_vcvc.py @@ -1,23 +1,25 @@ #!/usr/bin/env python # Copyright 2012,2013 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. -# +# + +from __future__ import division import numpy @@ -220,7 +222,7 @@ class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase): eq = digital.ofdm_frame_equalizer_vcvc(equalizer.base(), 0, self.tsb_key, True) self.tb.connect( src, - blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data)/fft_len, self.tsb_key), + blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data) // fft_len, self.tsb_key), eq, sink ) @@ -278,7 +280,7 @@ class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase): sink = blocks.tsb_vector_sink_c(vlen=fft_len, tsb_key=self.tsb_key) self.tb.connect( src, - blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data)/fft_len, self.tsb_key), + blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data) // fft_len, self.tsb_key), eq, sink ) @@ -360,7 +362,7 @@ class qa_ofdm_frame_equalizer_vcvc (gr_unittest.TestCase): sink = blocks.tsb_vector_sink_c(fft_len, tsb_key=self.tsb_key) self.tb.connect( src, - blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data)/fft_len, self.tsb_key), + blocks.stream_to_tagged_stream(gr.sizeof_gr_complex, fft_len, len(tx_data) // fft_len, self.tsb_key), eq, sink ) diff --git a/gr-digital/python/digital/qa_ofdm_serializer_vcc.py b/gr-digital/python/digital/qa_ofdm_serializer_vcc.py index 8a60b97882..a53aafccb6 100755..100644 --- a/gr-digital/python/digital/qa_ofdm_serializer_vcc.py +++ b/gr-digital/python/digital/qa_ofdm_serializer_vcc.py @@ -1,24 +1,26 @@ #!/usr/bin/env python # # Copyright 2012-2014 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. -# +# + +from __future__ import division import numpy @@ -42,7 +44,7 @@ class qa_ofdm_serializer_vcc (gr_unittest.TestCase): 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0) expected_result = tuple(range(1, 16)) + (0, 0, 0) occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) - n_syms = len(tx_symbols)/fft_len + n_syms = len(tx_symbols) // fft_len src = blocks.vector_source_c(tx_symbols, False, fft_len) serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, self.tsb_key, "", 0, "", False) sink = blocks.tsb_vector_sink_c(tsb_key=self.tsb_key) @@ -60,7 +62,7 @@ class qa_ofdm_serializer_vcc (gr_unittest.TestCase): ) expected_result = tuple(range(18)) occupied_carriers = ((13, 14, 15, 1, 2, 3), (-4, -2, -1, 1, 2, 4),) - n_syms = len(tx_symbols)/fft_len + n_syms = len(tx_symbols) // fft_len src = blocks.vector_source_c(tx_symbols, False, fft_len) serializer = digital.ofdm_serializer_vcc(fft_len, occupied_carriers, self.tsb_key) sink = blocks.tsb_vector_sink_c(tsb_key=self.tsb_key) @@ -71,14 +73,14 @@ class qa_ofdm_serializer_vcc (gr_unittest.TestCase): def test_002_with_offset (self): """ Standard test, carrier offset """ fft_len = 16 - tx_symbols = range(1, 16); + tx_symbols = list(range(1, 16)); tx_symbols = (0, 0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0) carr_offset = 1 # Compare this with tx_symbols from the previous test expected_result = tuple(range(1, 16)) + (0, 0, 0) occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) - n_syms = len(tx_symbols)/fft_len + n_syms = len(tx_symbols) // fft_len offsettag = gr.tag_t() offsettag.offset = 0 offsettag.key = pmt.string_to_symbol("ofdm_sync_carr_offset") @@ -156,7 +158,7 @@ class qa_ofdm_serializer_vcc (gr_unittest.TestCase): pilot_carriers, pilot_symbols, (), self.tsb_key) - tx_ifft = fft.fft_vcc(fft_len, False, (1.0/fft_len,)*fft_len, True) + tx_ifft = fft.fft_vcc(fft_len, False, (1.0 / fft_len,)*fft_len, True) oscillator = analog.sig_source_c(1.0, analog.GR_COS_WAVE, freq_offset, 1.0) mixer = blocks.multiply_cc() rx_fft = fft.fft_vcc(fft_len, True, (), True) @@ -182,13 +184,13 @@ class qa_ofdm_serializer_vcc (gr_unittest.TestCase): def test_005_packet_len_tag (self): """ Standard test """ fft_len = 16 - tx_symbols = range(1, 16); + tx_symbols = list(range(1, 16)); tx_symbols = (0, 1, 1j, 2, 3, 0, 0, 0, 0, 0, 0, 4, 5, 2j, 6, 0, 0, 7, 8, 3j, 9, 0, 0, 0, 0, 0, 0, 10, 4j, 11, 12, 0, 0, 13, 1j, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 2j, 0, 0) expected_result = tuple(range(1, 16)) occupied_carriers = ((1, 3, 4, 11, 12, 14), (1, 2, 4, 11, 13, 14),) - n_syms = len(tx_symbols)/fft_len + n_syms = len(tx_symbols) // fft_len packet_len_tsb_key = "packet_len" tag2 = gr.tag_t() tag2.offset = 0 diff --git a/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py b/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py index ccb6dff439..c09bd2861c 100755..100644 --- a/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py +++ b/gr-digital/python/digital/qa_ofdm_sync_sc_cfb.py @@ -1,24 +1,26 @@ #!/usr/bin/env python # # Copyright 2012,2013 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. -# +# + +from __future__ import division import numpy import random @@ -44,7 +46,7 @@ class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase): fft_len = 32 cp_len = 4 sig_len = (fft_len + cp_len) * 10 - sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len/2)] * 2 + sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len // 2)] * 2 tx_signal = [0,] * n_zeros + \ sync_symbol[-cp_len:] + \ sync_symbol + \ @@ -60,8 +62,8 @@ class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase): self.tb.connect((sync, 0), sink_freq) self.tb.connect((sync, 1), sink_detect) self.tb.run() - sig1_detect = sink_detect.data()[0:len(tx_signal)/2] - sig2_detect = sink_detect.data()[len(tx_signal)/2:] + sig1_detect = sink_detect.data()[0:len(tx_signal) // 2] + sig2_detect = sink_detect.data()[len(tx_signal) // 2:] self.assertTrue(abs(sig1_detect.index(1) - (n_zeros + fft_len + cp_len)) < cp_len) self.assertTrue(abs(sig2_detect.index(1) - (n_zeros + fft_len + cp_len)) < cp_len) self.assertEqual(numpy.sum(sig1_detect), 1) @@ -75,7 +77,7 @@ class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase): max_freq_offset = 2*numpy.pi/fft_len # Otherwise, it's coarse freq_offset = ((2 * random.random()) - 1) * max_freq_offset sig_len = (fft_len + cp_len) * 10 - sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len/2)] * 2 + sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len // 2)] * 2 tx_signal = sync_symbol[-cp_len:] + \ sync_symbol + \ [(random.randint(0, 1)*2)-1 for x in range(sig_len)] @@ -99,8 +101,8 @@ class qa_ofdm_sync_sc_cfb (gr_unittest.TestCase): fft_len = 32 cp_len = 4 tx_signal = [] - for i in xrange(n_bursts): - sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len/2)] * 2 + for i in range(n_bursts): + sync_symbol = [(random.randint(0, 1)*2)-1 for x in range(fft_len // 2)] * 2 tx_signal += [0,] * random.randint(0, 2*fft_len) + \ sync_symbol[-cp_len:] + \ sync_symbol + \ @@ -139,8 +141,8 @@ Detection error was: %d """ % (numpy.sum(sink_detect.data()) - n_bursts) tagname = "packet_length" min_packet_length = 10 max_packet_length = 50 - sync_sequence = [random.randint(0, 1)*2-1 for x in range(fft_len/2)] - for i in xrange(n_bursts): + sync_sequence = [random.randint(0, 1)*2-1 for x in range(fft_len // 2)] + for i in range(n_bursts): packet_length = random.randint(min_packet_length, max_packet_length+1) packet = [random.randint(0, 255) for i in range(packet_length)] diff --git a/gr-digital/python/digital/qa_ofdm_txrx.py b/gr-digital/python/digital/qa_ofdm_txrx.py index ac267d2389..2e8d101317 100755..100644 --- a/gr-digital/python/digital/qa_ofdm_txrx.py +++ b/gr-digital/python/digital/qa_ofdm_txrx.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import random import numpy diff --git a/gr-digital/python/digital/qa_packet_format.py b/gr-digital/python/digital/qa_packet_format.py index ae1a79f1f4..6b2e9e958e 100644 --- a/gr-digital/python/digital/qa_packet_format.py +++ b/gr-digital/python/digital/qa_packet_format.py @@ -21,6 +21,8 @@ # import time, struct +import six + import pmt from gnuradio import gr, gr_unittest, digital, blocks from gnuradio.digital import packet_utils @@ -57,6 +59,7 @@ class test_packet_format_fb(gr_unittest.TestCase): self.tb.start() while (snk_hdr.num_messages() < 1) and (snk_pld.num_messages() < 1): time.sleep(0.1) + self.tb.stop() self.tb.wait() @@ -65,14 +68,14 @@ class test_packet_format_fb(gr_unittest.TestCase): result_hdr = pmt.u8vector_elements(result_hdr_pmt) result_pld = pmt.u8vector_elements(result_pld_pmt) - header = "".join([chr(r) for r in result_hdr]) - payload = "".join([chr(r) for r in result_pld]) + header = "".join(chr(r) for r in result_hdr) + payload = "".join(chr(r) for r in result_pld) access_code = packet_utils.conv_1_0_string_to_packed_binary_string(packet_utils.default_access_code)[0] rx_access_code = header[0:len(access_code)] length = len(send_str) - rx_length = struct.unpack_from("!H", header, len(access_code))[0] + rx_length = struct.unpack_from(b"!H", six.b(header), len(access_code))[0] self.assertEqual(access_code, rx_access_code) self.assertEqual(length, rx_length) @@ -158,16 +161,16 @@ class test_packet_format_fb(gr_unittest.TestCase): result_hdr = pmt.u8vector_elements(result_hdr_pmt) result_pld = pmt.u8vector_elements(result_pld_pmt) - header = "".join([chr(r) for r in result_hdr]) - payload = "".join([chr(r) for r in result_pld]) + header = "".join(chr(r) for r in result_hdr) + payload = "".join(chr(r) for r in result_pld) access_code = packet_utils.conv_1_0_string_to_packed_binary_string(packet_utils.default_access_code)[0] rx_access_code = header[0:len(access_code)] length = len(send_str) - rx_length = struct.unpack_from("!H", header, len(access_code))[0] - rx_bps = struct.unpack_from("!H", header, len(access_code)+4)[0] - rx_counter = struct.unpack_from("!H", header, len(access_code)+6)[0] + rx_length = struct.unpack_from(b"!H", six.b(header), len(access_code))[0] + rx_bps = struct.unpack_from(b"!H", six.b(header), len(access_code)+4)[0] + rx_counter = struct.unpack_from(b"!H", six.b(header), len(access_code)+6)[0] self.assertEqual(access_code, rx_access_code) self.assertEqual(length, rx_length) diff --git a/gr-digital/python/digital/qa_packet_headergenerator_bb.py b/gr-digital/python/digital/qa_packet_headergenerator_bb.py index d2677ce220..1ca0e85d8d 100755..100644 --- a/gr-digital/python/digital/qa_packet_headergenerator_bb.py +++ b/gr-digital/python/digital/qa_packet_headergenerator_bb.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks from gnuradio.gr import packet_utils import pmt diff --git a/gr-digital/python/digital/qa_packet_headerparser_b.py b/gr-digital/python/digital/qa_packet_headerparser_b.py index fb4226d6fd..3e22fa9100 100755..100644 --- a/gr-digital/python/digital/qa_packet_headerparser_b.py +++ b/gr-digital/python/digital/qa_packet_headerparser_b.py @@ -19,6 +19,7 @@ # Boston, MA 02110-1301, USA. # + import time import random @@ -77,7 +78,7 @@ class qa_packet_headerparser_b (gr_unittest.TestCase): header_len = 32 packet_len_tagname = "packet_len" packet_lengths = [random.randint(1, 100) for x in range(N)] - data, tags = tagged_streams.packets_to_vectors([range(packet_lengths[i]) for i in range(N)], packet_len_tagname) + data, tags = tagged_streams.packets_to_vectors([list(range(packet_lengths[i])) for i in range(N)], packet_len_tagname) src = blocks.vector_source_b(data, False, 1, tags) header_gen = digital.packet_headergenerator_bb(header_len, packet_len_tagname) header_parser = digital.packet_headerparser_b(header_len, packet_len_tagname) @@ -89,7 +90,7 @@ class qa_packet_headerparser_b (gr_unittest.TestCase): self.tb.stop() self.tb.wait() self.assertEqual(sink.num_messages(), N) - for i in xrange(N): + for i in range(N): msg = pmt.to_python(sink.get_message(i)) self.assertEqual(msg, {'packet_len': packet_lengths[i], 'packet_num': i}) @@ -110,7 +111,7 @@ class qa_packet_headerparser_b (gr_unittest.TestCase): frame_len_tagname = "frame_len" src = blocks.vector_source_b(encoded_headers) header_formatter = digital.packet_header_ofdm( - (range(32),range(4),range(8)), # 32/4/8 carriers are occupied (which doesn't matter here) + (list(range(32)),list(range(4)),list(range(8))), # 32/4/8 carriers are occupied (which doesn't matter here) 1, # 1 OFDM symbol per header (= 32 bits) packet_len_tagname, frame_len_tagname, @@ -141,10 +142,10 @@ class qa_packet_headerparser_b (gr_unittest.TestCase): packet_length = 23 packet_len_tagname = "packet_len" frame_len_tagname = "frame_len" - data, tags = tagged_streams.packets_to_vectors([range(packet_length),range(packet_length),], packet_len_tagname) + data, tags = tagged_streams.packets_to_vectors([list(range(packet_length)),list(range(packet_length)),], packet_len_tagname) src = blocks.vector_source_b(data, False, 1, tags) header_formatter = digital.packet_header_ofdm( - (range(32),), # 32 carriers are occupied (which doesn't matter here) + (list(range(32)),), # 32 carriers are occupied (which doesn't matter here) 1, # 1 OFDM symbol per header (= 32 bits) packet_len_tagname, frame_len_tagname, diff --git a/gr-digital/python/digital/qa_pfb_clock_sync.py b/gr-digital/python/digital/qa_pfb_clock_sync.py index e16a99338e..77980d19e5 100755..100644 --- a/gr-digital/python/digital/qa_pfb_clock_sync.py +++ b/gr-digital/python/digital/qa_pfb_clock_sync.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import random import cmath import time @@ -39,9 +41,9 @@ class test_pfb_clock_sync(gr_unittest.TestCase): excess_bw = 0.35 sps = 4 - loop_bw = cmath.pi/100.0 + loop_bw = cmath.pi / 100.0 nfilts = 32 - init_phase = nfilts/2 + init_phase = nfilts / 2 max_rate_deviation = 0.5 osps = 1 @@ -92,9 +94,9 @@ class test_pfb_clock_sync(gr_unittest.TestCase): excess_bw = 0.35 sps = 4 - loop_bw = cmath.pi/100.0 + loop_bw = cmath.pi / 100.0 nfilts = 32 - init_phase = nfilts/2 + init_phase = nfilts / 2 max_rate_deviation = 0.5 osps = 1 @@ -146,9 +148,9 @@ class test_pfb_clock_sync(gr_unittest.TestCase): excess_bw1 = 0.22 sps = 4 - loop_bw = cmath.pi/100.0 + loop_bw = cmath.pi / 100.0 nfilts = 32 - init_phase = nfilts/2 + init_phase = nfilts / 2 max_rate_deviation = 0.5 osps = 1 @@ -184,9 +186,9 @@ class test_pfb_clock_sync(gr_unittest.TestCase): excess_bw1 = 0.22 sps = 4 - loop_bw = cmath.pi/100.0 + loop_bw = cmath.pi / 100.0 nfilts = 32 - init_phase = nfilts/2 + init_phase = nfilts / 2 max_rate_deviation = 0.5 osps = 1 diff --git a/gr-digital/python/digital/qa_pn_correlator_cc.py b/gr-digital/python/digital/qa_pn_correlator_cc.py index 92041d9eda..111801b5c9 100755..100644 --- a/gr-digital/python/digital/qa_pn_correlator_cc.py +++ b/gr-digital/python/digital/qa_pn_correlator_cc.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks class test_pn_correlator_cc(gr_unittest.TestCase): diff --git a/gr-digital/python/digital/qa_probe_density.py b/gr-digital/python/digital/qa_probe_density.py index 752d95da3e..e4450cd092 100755..100644 --- a/gr-digital/python/digital/qa_probe_density.py +++ b/gr-digital/python/digital/qa_probe_density.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + from gnuradio import gr, gr_unittest, digital, blocks class test_probe_density(gr_unittest.TestCase): @@ -62,7 +64,7 @@ class test_probe_density(gr_unittest.TestCase): self.tb.run() result_data = op.density() - print result_data + print(result_data) self.assertAlmostEqual(expected_data, result_data, 5) if __name__ == '__main__': diff --git a/gr-digital/python/digital/qa_scrambler.py b/gr-digital/python/digital/qa_scrambler.py index 522b23245f..8de35e8ed0 100755..100644 --- a/gr-digital/python/digital/qa_scrambler.py +++ b/gr-digital/python/digital/qa_scrambler.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks import pmt diff --git a/gr-digital/python/digital/qa_simple_correlator.py b/gr-digital/python/digital/qa_simple_correlator.py index f39fb62dda..9c0352e896 100755..100644 --- a/gr-digital/python/digital/qa_simple_correlator.py +++ b/gr-digital/python/digital/qa_simple_correlator.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks, filter, digital class test_simple_correlator(gr_unittest.TestCase): diff --git a/gr-digital/python/digital/qa_simple_framer.py b/gr-digital/python/digital/qa_simple_framer.py index cf9934648b..fb1ac0dfd6 100755..100644 --- a/gr-digital/python/digital/qa_simple_framer.py +++ b/gr-digital/python/digital/qa_simple_framer.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, digital, blocks class test_simple_framer(gr_unittest.TestCase): diff --git a/gr-digital/python/digital/qam.py b/gr-digital/python/digital/qam.py index 518be78941..be4b7efa74 100644 --- a/gr-digital/python/digital/qam.py +++ b/gr-digital/python/digital/qam.py @@ -1,37 +1,40 @@ # # Copyright 2005,2006,2011,2013 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. -# +# """ QAM modulation and demodulation. """ +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals from math import pi, sqrt, log from gnuradio import gr -from generic_mod_demod import generic_mod, generic_demod -from generic_mod_demod import shared_mod_args, shared_demod_args -from utils.gray_code import gray_code -from utils import mod_codes -import modulation_utils -import digital_swig as digital +from .generic_mod_demod import generic_mod, generic_demod +from .generic_mod_demod import shared_mod_args, shared_demod_args +from .utils.gray_code import gray_code +from .utils import mod_codes +from . import modulation_utils +from . import digital_swig as digital # Default number of points in constellation. _def_constellation_points = 16 @@ -42,7 +45,7 @@ _def_differential = True _def_mod_code = mod_codes.NO_CODE def is_power_of_four(x): - v = log(x)/log(4) + v = log(x) / log(4) return int(v) == v def get_bit(x, n): @@ -52,7 +55,7 @@ def get_bit(x, n): def get_bits(x, n, k): """ Get the k bits of integer x starting at bit n(from little end).""" # Remove the n smallest bits - v = x >> n + v = x >> n # Remove all bits bigger than n+k-1 return v % pow(2, k) @@ -74,7 +77,7 @@ def make_differential_constellation(m, gray_coded): k = int(log(m) / log(2.0)) # First create a constellation for one quadrant containing m/4 points. # The quadrant has 'side' points along each side of a quadrant. - side = int(sqrtm/2) + side = int(sqrtm / 2) if gray_coded: # Number rows and columns using gray codes. gcs = gray_code(side) @@ -83,7 +86,7 @@ def make_differential_constellation(m, gray_coded): else: i_gcs = dict([(i, i) for i in range(0, side)]) # The distance between points is found. - step = 1/(side-0.5) + step = 1 / (side-0.5) gc_to_x = [(i_gcs[gc]+0.5)*step for gc in range(0, side)] @@ -100,7 +103,7 @@ def make_differential_constellation(m, gray_coded): return complex(-gc_to_x[gc_x], -gc_to_x[gc_y]) if quad == 3: return complex(gc_to_x[gc_y], -gc_to_x[gc_x]) - raise StandardError("Impossible!") + raise Exception("Impossible!") # First two bits determine quadrant. # Next (k-2)/2 bits determine x position. @@ -108,8 +111,8 @@ def make_differential_constellation(m, gray_coded): # How x and y relate to real and imag depends on quadrant (see get_c function). const_map = [] for i in range(m): - y = get_bits(i, 0, (k-2)/2) - x = get_bits(i, (k-2)/2, (k-2)/2) + y = get_bits(i, 0, (k-2) // 2) + x = get_bits(i, (k-2) // 2, (k-2) // 2) quad = get_bits(i, k-2, 2) const_map.append(get_c(x, y, quad)) @@ -127,17 +130,17 @@ def make_non_differential_constellation(m, gray_coded): # Get inverse gray codes. i_gcs = mod_codes.invert_code(gcs) else: - i_gcs = range(0, side) + i_gcs = list(range(0, side)) # The distance between points is found. - step = 2.0/(side-1) + step = 2.0 / (side-1) gc_to_x = [-1 + i_gcs[gc]*step for gc in range(0, side)] # First k/2 bits determine x position. # Following k/2 bits determine y position. const_map = [] for i in range(m): - y = gc_to_x[get_bits(i, 0, k/2)] - x = gc_to_x[get_bits(i, k/2, k/2)] + y = gc_to_x[get_bits(i, 0, k // 2)] + x = gc_to_x[get_bits(i, k // 2, k // 2)] const_map.append(complex(x,y)) return const_map @@ -170,7 +173,7 @@ def qam_constellation(constellation_points=_def_constellation_points, else: points = make_non_differential_constellation(constellation_points, gray_coded) side = int(sqrt(constellation_points)) - width = 2.0/(side-1) + width = 2.0 / (side-1) # No pre-diff code # Should add one so that we can gray-code the quadrant bits too. @@ -242,8 +245,8 @@ def large_ampls_to_corners_mapping(side, points, width): sector = real_x * side + imag_x # If this sector is a normal constellation sector then # use the center point. - c = ((real_x-side/2.0+0.5)*width + - (imag_x-side/2.0+0.5)*width*1j) + c = ((real_x-side / 2.0+0.5)*width + + (imag_x-side / 2.0+0.5)*width*1j) if (real_x >= extra_layers and real_x < side-extra_layers and imag_x >= extra_layers and imag_x < side-extra_layers): # This is not an edge row/column. Find closest point. @@ -254,7 +257,7 @@ def large_ampls_to_corners_mapping(side, points, width): sector_values.append(index) return sector_values - + # ///////////////////////////////////////////////////////////////////////////// # QAM modulator # ///////////////////////////////////////////////////////////////////////////// @@ -262,10 +265,10 @@ def large_ampls_to_corners_mapping(side, points, width): class qam_mod(generic_mod): """ Hierarchical block for RRC-filtered QAM modulation. - + The input is a byte stream (unsigned char) and the output is the complex modulated signal at baseband. - + Args: constellation_points: Number of constellation points (must be a power of four) (integer). mod_code: Whether to use a gray_code (digital.mod_codes.GRAY_CODE) or not (digital.mod_codes.NO_CODE). @@ -280,10 +283,10 @@ class qam_mod(generic_mod): *args, **kwargs): """ - Hierarchical block for RRC-filtered QAM modulation. + Hierarchical block for RRC-filtered QAM modulation. - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. Args: constellation_points: Number of constellation points. @@ -292,7 +295,7 @@ class qam_mod(generic_mod): if we want gray coding, see digital.utils.mod_codes) See generic_mod block for list of additional parameters. - """ + """ constellation = qam_constellation(constellation_points, differential, mod_code) @@ -309,10 +312,10 @@ class qam_mod(generic_mod): class qam_demod(generic_demod): """ Hierarchical block for RRC-filtered QAM modulation. - + The input is a byte stream (unsigned char) and the output is the complex modulated signal at baseband. - + Args: constellation_points: Number of constellation points (must be a power of four) (integer). mod_code: Whether to use a gray_code (digital.mod_codes.GRAY_CODE) or not (digital.mod_codes.NO_CODE). @@ -327,10 +330,10 @@ class qam_demod(generic_demod): large_ampls_to_corner = False, *args, **kwargs): """ - Hierarchical block for RRC-filtered QAM modulation. + Hierarchical block for RRC-filtered QAM modulation. - The input is a byte stream (unsigned char) and the - output is the complex modulated signal at baseband. + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. Args: constellation_points: Number of constellation points. diff --git a/gr-digital/python/digital/qam_constellations.py b/gr-digital/python/digital/qam_constellations.py index ab58916384..dc85e90ff8 100755..100644 --- a/gr-digital/python/digital/qam_constellations.py +++ b/gr-digital/python/digital/qam_constellations.py @@ -20,8 +20,11 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals import numpy -from constellation_map_generator import * +from .constellation_map_generator import * ''' Note on the naming scheme. Each constellation is named using a prefix @@ -242,8 +245,8 @@ def sd_qam_16_0x0_0_1_2_3(x, Es=1): ''' dist = Es*numpy.sqrt(2) - boundary = dist/3.0 - dist0 = dist/6.0 + boundary = dist / 3.0 + dist0 = dist / 6.0 # print "Sample: ", x # print "Es: ", Es # print "Distance: ", dist @@ -270,7 +273,7 @@ def sd_qam_16_0x0_0_1_2_3(x, Es=1): b2 = -abs(x_re) + boundary b0 = -abs(x_im) + boundary - return [(Es/2.0)*b3, (Es/2.0)*b2, (Es/2.0)*b1, (Es/2.0)*b0] + return [(Es / 2.0)*b3, (Es / 2.0)*b2, (Es / 2.0)*b1, (Es / 2.0)*b0] sd_qam_16 = sd_qam_16_0x0_0_1_2_3 sd_qam_16_0 = sd_qam_16 diff --git a/gr-digital/python/digital/qamlike.py b/gr-digital/python/digital/qamlike.py index 2f8c855339..286eabd898 100644 --- a/gr-digital/python/digital/qamlike.py +++ b/gr-digital/python/digital/qamlike.py @@ -1,33 +1,35 @@ # Copyright 2013 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. -# +# """ This file contains constellations that are similar to QAM, but are not perfect squares. """ +from __future__ import absolute_import +from __future__ import unicode_literals -import digital_swig -from qam import large_ampls_to_corners_mapping +from . import digital_swig +from .qam import large_ampls_to_corners_mapping def qam32_holeinside_constellation(large_ampls_to_corners=False): # First make constellation for one quadrant. - # 0 1 2 + # 0 1 2 # 2 - 010 111 110 # 1 - 011 101 100 # 0 - 000 001 @@ -72,4 +74,3 @@ def qam32_holeinside_constellation(large_ampls_to_corners=False): constellation = digital_swig.constellation_expl_rect( points, pre_diff_code, 4, side, side, width, width, sector_values) return constellation - diff --git a/gr-digital/python/digital/qpsk.py b/gr-digital/python/digital/qpsk.py index c5230ef24d..8303883992 100644 --- a/gr-digital/python/digital/qpsk.py +++ b/gr-digital/python/digital/qpsk.py @@ -24,13 +24,15 @@ QPSK modulation. Demodulation is not included since the generic_mod_demod """ +from __future__ import absolute_import +from __future__ import unicode_literals from gnuradio import gr from gnuradio.digital.generic_mod_demod import generic_mod, generic_demod from gnuradio.digital.generic_mod_demod import shared_mod_args, shared_demod_args -from utils import mod_codes -import digital_swig as digital -import modulation_utils +from .utils import mod_codes +from . import digital_swig as digital +from . import modulation_utils # The default encoding (e.g. gray-code, set-partition) _def_mod_code = mod_codes.GRAY_CODE diff --git a/gr-digital/python/digital/soft_dec_lut_gen.py b/gr-digital/python/digital/soft_dec_lut_gen.py index f517277702..fc69f7f678 100644 --- a/gr-digital/python/digital/soft_dec_lut_gen.py +++ b/gr-digital/python/digital/soft_dec_lut_gen.py @@ -20,6 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + import numpy def soft_dec_table_generator(soft_dec_gen, prec, Es=1): @@ -123,6 +127,7 @@ def soft_dec_table(constel, symbols, prec, npwr=1): xrng = numpy.linspace(re_min, re_max, npts) table = [] + for y in yrng: for x in xrng: pt = complex(x, y) @@ -196,8 +201,8 @@ def calc_soft_dec(sample, constel, symbols, npwr=1): M = len(constel) k = int(numpy.log2(M)) - tmp = 2*k*[0,] - s = k*[0,] + tmp = 2*k*[0] + s = k*[0] for i in range(M): # Calculate the distance between the sample and the current @@ -206,7 +211,7 @@ def calc_soft_dec(sample, constel, symbols, npwr=1): # Calculate the probability factor from the distance and the # scaled noise power. - d = numpy.exp(-dist/npwr) + d = numpy.exp(-dist / npwr) for j in range(k): # Get the bit at the jth index @@ -235,21 +240,21 @@ def show_table(table): pp = "" subi = 1 subj = 0 - for i in reversed(xrange(prec+1)): + for i in reversed(list(range(prec+1))): if(i == prec//2): pp += "-----" + prec*((nbits*8)+3)*"-" + "\n" subi = 0 continue - for j in xrange(prec+1): + for j in range(prec+1): if(j == prec//2): pp += "| " subj = 1 else: item = table[prec*(i-subi) + (j-subj)] pp += "( " - for t in xrange(nbits-1, -1, -1): + for t in range(nbits-1, -1, -1): pp += "{0: .4f} ".format(item[t]) pp += ") " pp += "\n" subj = 0 - print pp + print(pp) diff --git a/gr-digital/python/digital/test_soft_decisions.py b/gr-digital/python/digital/test_soft_decisions.py index 78714100b7..f2ed547bd5 100755..100644 --- a/gr-digital/python/digital/test_soft_decisions.py +++ b/gr-digital/python/digital/test_soft_decisions.py @@ -1,30 +1,35 @@ #!/usr/bin/env python # # Copyright 2013 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. -# +# + +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals import numpy, pylab, sys from gnuradio import digital -from soft_dec_lut_gen import * -from psk_constellations import * -from qam_constellations import * +from .soft_dec_lut_gen import * +from .psk_constellations import * +from .qam_constellations import * def test_qpsk(i, sample, prec): qpsk_const_list = [psk_4_0, psk_4_1, psk_4_2, psk_4_3, @@ -61,7 +66,7 @@ def test_qpsk(i, sample, prec): y_cpp_table, y_cpp_raw_calc, constel, code, c) def test_qam16(i, sample, prec): - sample = sample/1 + sample = sample / 1 qam_const_list = [qam_16_0, ] qam_lut_gen_list = [sd_qam_16_0, ] @@ -114,12 +119,12 @@ if __name__ == "__main__": k = numpy.log2(len(constel)) - print "Sample: ", x - print "Python Generator Calculated: ", (y_python_gen_calc) - print "Python Generator Table: ", (y_python_table) - print "Python Raw calc: ", (y_python_raw_calc) - print "C++ Table calc: ", (y_cpp_table) - print "C++ Raw calc: ", (y_cpp_raw_calc) + print("Sample: ", x) + print("Python Generator Calculated: ", (y_python_gen_calc)) + print("Python Generator Table: ", (y_python_table)) + print("Python Raw calc: ", (y_python_raw_calc)) + print("C++ Table calc: ", (y_cpp_table)) + print("C++ Raw calc: ", (y_cpp_raw_calc)) fig = pylab.figure(1) sp1 = fig.add_subplot(1,1,1) diff --git a/gr-digital/python/digital/utils/alignment.py b/gr-digital/python/digital/utils/alignment.py index f3ad3781e2..e9292a4bcc 100644 --- a/gr-digital/python/digital/utils/alignment.py +++ b/gr-digital/python/digital/utils/alignment.py @@ -41,6 +41,8 @@ This module contains functions for aligning sequences. (100, -20) """ +from __future__ import division +from __future__ import unicode_literals import random @@ -63,7 +65,7 @@ def compare_sequences(d1, d2, offset, sample_indices=None): """ max_index = min(len(d1), len(d2)+offset) if sample_indices is None: - sample_indices = range(0, max_index) + sample_indices = list(range(0, max_index)) correct = 0 total = 0 for i in sample_indices: @@ -84,8 +86,8 @@ def random_sample(size, num_samples=def_num_samples, seed=None): if num_samples > size: indices = set(range(0, size)) else: - if num_samples > size/2: - num_samples = num_samples/2 + if num_samples > size / 2: + num_samples = num_samples / 2 indices = set([]) while len(indices) < num_samples: index = rndm.randint(0, size-1) @@ -119,8 +121,8 @@ def align_sequences(d1, d2, best_offset = None best_compared = None best_correct = None - pos_range = range(0, min(len(d1), max_offset)) - neg_range = range(-1, -min(len(d2), max_offset), -1) + pos_range = list(range(0, min(len(d1), max_offset))) + neg_range = list(range(-1, -min(len(d2), max_offset), -1)) # Interleave the positive and negative offsets. int_range = [item for items in zip(pos_range, neg_range) for item in items] for offset in int_range: diff --git a/gr-digital/python/digital/utils/gray_code.py b/gr-digital/python/digital/utils/gray_code.py index 926a1ded10..ad88274087 100644 --- a/gr-digital/python/digital/utils/gray_code.py +++ b/gr-digital/python/digital/utils/gray_code.py @@ -1,25 +1,27 @@ #!/usr/bin/env python # # Copyright 2011 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. -# +# +from __future__ import division +from __future__ import unicode_literals class GrayCodeGenerator(object): """ Generates and caches gray codes. @@ -41,7 +43,7 @@ class GrayCodeGenerator(object): if len(self.gcs) < length: self.generate_new_gray_code(length) return self.gcs[:length] - + def generate_new_gray_code(self, length): """ Generates new gray code and places into cache. @@ -49,7 +51,7 @@ class GrayCodeGenerator(object): while len(self.gcs) < length: if self.i == self.lp2: # if i is a power of two then gray number is of form 1100000... - result = self.i + self.i/2 + result = self.i + self.i // 2 else: # if not we take advantage of the symmetry of all but the last bit # around a power of two. diff --git a/gr-digital/python/digital/utils/mod_codes.py b/gr-digital/python/digital/utils/mod_codes.py index f55fe41b8b..586ab1999a 100644 --- a/gr-digital/python/digital/utils/mod_codes.py +++ b/gr-digital/python/digital/utils/mod_codes.py @@ -21,6 +21,7 @@ # # Constants used to represent what coding to use. +from __future__ import unicode_literals GRAY_CODE = 'gray' SET_PARTITION_CODE = 'set-partition' NO_CODE = 'none' diff --git a/gr-digital/python/digital/utils/tagged_streams.py b/gr-digital/python/digital/utils/tagged_streams.py index 4b393bfc20..68267a293e 100644 --- a/gr-digital/python/digital/utils/tagged_streams.py +++ b/gr-digital/python/digital/utils/tagged_streams.py @@ -1,27 +1,30 @@ #!/usr/bin/env python # # Copyright 2013 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. -# +# # DEPRECATED -- Marked for removal in 3.8 +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr import pmt @@ -30,9 +33,9 @@ def make_lengthtags(lengths, offsets, tagname='length', vlen=1): assert(len(offsets) == len(lengths)) for offset, length in zip(offsets, lengths): tag = gr.tag_t() - tag.offset = offset/vlen + tag.offset = offset / vlen tag.key = pmt.string_to_symbol(tagname) - tag.value = pmt.from_long(length/vlen) + tag.value = pmt.from_long(length / vlen) tags.append(tag) return tags @@ -75,7 +78,7 @@ def count_bursts(data, tags, lengthtagname, vlen=1): if pos in lengths: if in_packet: print("Got tag at pos {0} current packet_pos is {1}".format(pos, packet_pos)) - raise StandardError("Received packet tag while in packet.") + raise Exception("Received packet tag while in packet.") packet_pos = -1 packet_length = lengths[pos] in_packet = True @@ -127,9 +130,9 @@ def packets_to_vectors(packets, lengthtagname, vlen=1): for packet in packets: data.extend(packet) tag = gr.tag_t() - tag.offset = offset/vlen + tag.offset = offset // vlen tag.key = pmt.string_to_symbol(lengthtagname) - tag.value = pmt.from_long(len(packet)/vlen) + tag.value = pmt.from_long(len(packet) // vlen) tags.append(tag) offset = offset + len(packet) return data, tags diff --git a/gr-digital/swig/digital_swig.py.in b/gr-digital/swig/digital_swig.py.in index d5d55a0f4e..a4326d1343 100644 --- a/gr-digital/swig/digital_swig.py.in +++ b/gr-digital/swig/digital_swig.py.in @@ -19,6 +19,8 @@ # Boston, MA 02110-1301, USA. # -from digital_swig0 import * -from digital_swig1 import * -from digital_swig2 import * +from __future__ import absolute_import + +from .digital_swig0 import * +from .digital_swig1 import * +from .digital_swig2 import * diff --git a/gr-dtv/examples/atsc_ctrlport_monitor.py b/gr-dtv/examples/atsc_ctrlport_monitor.py index 7c43aebb77..9e1a7778c2 100755..100644 --- a/gr-dtv/examples/atsc_ctrlport_monitor.py +++ b/gr-dtv/examples/atsc_ctrlport_monitor.py @@ -18,6 +18,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + import sys import matplotlib matplotlib.use("QT4Agg") @@ -37,12 +41,12 @@ the link quality. This also gets the equalizer taps of the receiver and displays the frequency response. """ -class atsc_ctrlport_monitor: +class atsc_ctrlport_monitor(object): def __init__(self, host, port): argv = [None, host, port] radiosys = GNURadioControlPortClient(argv=argv, rpcmethod='thrift') self.radio = radiosys.client - print self.radio + print(self.radio) vt_init_key = 'dtv_atsc_viterbi_decoder0::decoder_metrics' @@ -108,17 +112,17 @@ class atsc_ctrlport_monitor: ntaps = len(eqdata.value) taps.set_ydata(eqdata.value) - taps.set_xdata(xrange(ntaps)) + taps.set_xdata(list(range(ntaps))) self._sp0.set_xlim(0, ntaps) self._sp0.set_ylim(min(eqdata.value), max(eqdata.value)) fs = 6.25e6 - freq = scipy.linspace(-fs/2, fs/2, 10000) + freq = scipy.linspace(-fs / 2, fs / 2, 10000) H = fftpack.fftshift(fftpack.fft(eqdata.value, 10000)) HdB = 20.0*scipy.log10(abs(H)) psd.set_ydata(HdB) psd.set_xdata(freq) - self._sp1.set_xlim(0, fs/2) + self._sp1.set_xlim(0, fs / 2) self._sp1.set_ylim([min(HdB), max(HdB)]) self._sp1.set_yticks([min(HdB), max(HdB)]) self._sp1.set_yticklabels(["min", "max"]) diff --git a/gr-dtv/python/dtv/CMakeLists.txt b/gr-dtv/python/dtv/CMakeLists.txt index e39b21cbb9..caf19d8d97 100644 --- a/gr-dtv/python/dtv/CMakeLists.txt +++ b/gr-dtv/python/dtv/CMakeLists.txt @@ -44,6 +44,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-dtv/python/dtv/__init__.py b/gr-dtv/python/dtv/__init__.py index 8d2b8bfbcf..82bd562117 100644 --- a/gr-dtv/python/dtv/__init__.py +++ b/gr-dtv/python/dtv/__init__.py @@ -24,14 +24,17 @@ ''' Blocks and utilities for digital TV module. ''' +from __future__ import absolute_import +from __future__ import unicode_literals + import os try: - from dtv_swig import * + from .dtv_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from dtv_swig import * + from .dtv_swig import * # Import pure python code here -from atsc_rx import * +from .atsc_rx import * diff --git a/gr-dtv/python/dtv/atsc_rx.py b/gr-dtv/python/dtv/atsc_rx.py index 590e5f041c..7b31e3dae2 100644 --- a/gr-dtv/python/dtv/atsc_rx.py +++ b/gr-dtv/python/dtv/atsc_rx.py @@ -19,8 +19,10 @@ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. +from __future__ import absolute_import +from __future__ import unicode_literals from gnuradio import gr, filter, analog -from atsc_rx_filter import * +from .atsc_rx_filter import * class atsc_rx(gr.hier_block2): def __init__(self, input_rate, sps): @@ -53,17 +55,17 @@ class atsc_rx(gr.hier_block2): # Remove convolutional trellis coding vit = dtv.atsc_viterbi_decoder() - # Remove convolutional interleaving - dei = dtv.atsc_deinterleaver() + # Remove convolutional interleaving + dei = dtv.atsc_deinterleaver() - # Reed-Solomon decode - rsd = dtv.atsc_rs_decoder() + # Reed-Solomon decode + rsd = dtv.atsc_rs_decoder() - # Derandomize MPEG2-TS packet - der = dtv.atsc_derandomizer() + # Derandomize MPEG2-TS packet + der = dtv.atsc_derandomizer() - # Remove padding from packet - dep = dtv.atsc_depad() + # Remove padding from packet + dep = dtv.atsc_depad() # Connect pipeline self.connect(self, rx_filt, pll, dcr, agc, btl, fsc, equ) diff --git a/gr-dtv/python/dtv/atsc_rx_filter.py b/gr-dtv/python/dtv/atsc_rx_filter.py index e860fa265a..b5df161a59 100644 --- a/gr-dtv/python/dtv/atsc_rx_filter.py +++ b/gr-dtv/python/dtv/atsc_rx_filter.py @@ -19,8 +19,10 @@ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, filter -import dtv_swig as dtv +from . import dtv_swig as dtv # FIXME move these into separate constants module ATSC_CHANNEL_BW = 6.0e6 @@ -38,10 +40,10 @@ class atsc_rx_filter(gr.hier_block2): nfilts = 16 output_rate = ATSC_SYMBOL_RATE*sps # Desired oversampled sample rate filter_rate = input_rate*nfilts - symbol_rate = ATSC_SYMBOL_RATE/2.0 # One-sided bandwidth of sideband + symbol_rate = ATSC_SYMBOL_RATE / 2.0 # One-sided bandwidth of sideband excess_bw = 0.1152 #1.0-(0.5*ATSC_SYMBOL_RATE/ATSC_CHANNEL_BW) # ~10.3% ntaps = int((2*ATSC_RRC_SYMS+1)*sps*nfilts) - interp = output_rate/input_rate + interp = output_rate / input_rate gain = nfilts*symbol_rate/filter_rate rrc_taps = filter.firdes.root_raised_cosine(gain, # Filter gain filter_rate, # PFB filter prototype rate diff --git a/gr-dtv/python/dtv/qa_dtv.py b/gr-dtv/python/dtv/qa_dtv.py index a0f6edf801..cebdeb5959 100755..100644 --- a/gr-dtv/python/dtv/qa_dtv.py +++ b/gr-dtv/python/dtv/qa_dtv.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, dtv class test_dtv(gr_unittest.TestCase): diff --git a/gr-fec/include/gnuradio/fec/polar_common.h b/gr-fec/include/gnuradio/fec/polar_common.h index 99c7d84e55..daa612cfc5 100644 --- a/gr-fec/include/gnuradio/fec/polar_common.h +++ b/gr-fec/include/gnuradio/fec/polar_common.h @@ -24,6 +24,8 @@ #ifndef INCLUDED_FEC_POLAR_COMMON_H #define INCLUDED_FEC_POLAR_COMMON_H +#include <vector> + #include <gnuradio/fec/api.h> // Forward declaration for those objects. SWIG doesn't like them to be #include'd. diff --git a/gr-fec/python/fec/CMakeLists.txt b/gr-fec/python/fec/CMakeLists.txt index 9d170b0423..013b3521a9 100644 --- a/gr-fec/python/fec/CMakeLists.txt +++ b/gr-fec/python/fec/CMakeLists.txt @@ -67,7 +67,7 @@ endif(NOT GSL_FOUND) foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-fec/python/fec/LDPC/Generate_LDPC_matrix.py b/gr-fec/python/fec/LDPC/Generate_LDPC_matrix.py index a3862a6fda..8c5b17bc43 100644 --- a/gr-fec/python/fec/LDPC/Generate_LDPC_matrix.py +++ b/gr-fec/python/fec/LDPC/Generate_LDPC_matrix.py @@ -20,7 +20,12 @@ # Boston, MA 02110-1301, USA. # -from Generate_LDPC_matrix_functions import * +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + +from .Generate_LDPC_matrix_functions import * # This is an example of how to generate a parity check matrix for # use with the LDPC Richardson Urbanke encoder. A significant amount @@ -62,18 +67,18 @@ newH = get_full_rank_H_matrix(parity_check_matrix.H) # can take a while... [bestH,g] = get_best_matrix(newH,100) -# Print out some of the resulting properties. +# Print(out some of the resulting properties.) n = bestH.shape[1] k = n - bestH.shape[0] -print "Parity check matrix properties:" -print "\tSize :", bestH.shape -print "\tRank :", linalg.matrix_rank(bestH) -print "\tRate : %.3f" % ((k*1.0)/n) -print "\tn :", n, " (codeword length)" -print "\tk :", k, " (info word length)" -print "\tgap : %i" % g +print("Parity check matrix properties:") +print("\tSize :", bestH.shape) +print("\tRank :", linalg.matrix_rank(bestH)) +print("\tRate : %.3f" % ((k*1.0) / n)) +print("\tn :", n, " (codeword length)") +print("\tk :", k, " (info word length)") +print("\tgap : %i" % g) # Save the matrix to an alist file for future use: alist_filename = "n_%04i_k_%04i_gap_%02i.alist" % (n,k,g) write_alist_file(alist_filename,bestH) -print '\nMatrix saved to alist file:', alist_filename, "\n" +print('\nMatrix saved to alist file:', alist_filename, "\n") diff --git a/gr-fec/python/fec/LDPC/Generate_LDPC_matrix_functions.py b/gr-fec/python/fec/LDPC/Generate_LDPC_matrix_functions.py index c42fee631f..5774329ecd 100644 --- a/gr-fec/python/fec/LDPC/Generate_LDPC_matrix_functions.py +++ b/gr-fec/python/fec/LDPC/Generate_LDPC_matrix_functions.py @@ -20,6 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + import string, sys from numpy import * from numpy.random import shuffle, randint @@ -46,9 +50,9 @@ def read_alist_file(filename): indices = string.split(data[lineNumber]) for index in indices: H[int(index)-1,lineNumber-4] = 1 - # The subsequent lines in the file list the indices for where - # the 1s are in the rows, but this is redundant - # information. + # The subsequent lines in the file list the indices for where + # the 1s are in the rows, but this is redundant + # information. return H @@ -68,7 +72,7 @@ def write_alist_file(filename, H, verbose=0): numRows = H.shape[0] numCols = H.shape[1] - tempstring = `numCols` + ' ' + `numRows` + '\n' + tempstring = repr(numCols) + ' ' + repr(numRows) + '\n' myfile.write(tempstring) tempstring1 = '' @@ -79,12 +83,12 @@ def write_alist_file(filename, H, verbose=0): rowWeight = nonzeros.shape[1] if rowWeight > maxRowWeight: maxRowWeight = rowWeight - tempstring1 = tempstring1 + `rowWeight` + ' ' + tempstring1 = tempstring1 + repr(rowWeight) + ' ' for tempArray in nonzeros: for index in tempArray: - tempstring2 = tempstring2 + `index+1` + ' ' - tempstring2 = tempstring2 + '\n' - tempstring1 = tempstring1 + '\n' + tempstring2 = tempstring2 + repr(index+1) + ' ' + tempstring2 = tempstring2 + '\n' + tempstring1 = tempstring1 + '\n' tempstring3 = '' tempstring4 = '' @@ -94,14 +98,14 @@ def write_alist_file(filename, H, verbose=0): colWeight = nonzeros.shape[1] if colWeight > maxColWeight: maxColWeight = colWeight - tempstring3 = tempstring3 + `colWeight` + ' ' + tempstring3 = tempstring3 + repr(colWeight) + ' ' for tempArray in nonzeros: for index in tempArray: - tempstring4 = tempstring4 + `index+1` + ' ' - tempstring4 = tempstring4 + '\n' - tempstring3 = tempstring3 + '\n' + tempstring4 = tempstring4 + repr(index+1) + ' ' + tempstring4 = tempstring4 + '\n' + tempstring3 = tempstring3 + '\n' - tempstring = `maxColWeight` + ' ' + `maxRowWeight` + '\n' + tempstring = repr(maxColWeight) + ' ' + repr(maxRowWeight) + '\n' # write out max column and row weights myfile.write(tempstring) # write out all of the column weights @@ -116,11 +120,11 @@ def write_alist_file(filename, H, verbose=0): myfile.close() -class LDPC_matrix: +class LDPC_matrix(object): """ Class for a LDPC parity check matrix """ def __init__(self, alist_filename = None, - n_p_q = None, - H_matrix = None): + n_p_q = None, + H_matrix = None): if (alist_filename != None): self.H = self.read_alist_file(alist_filename) elif (n_p_q != None): @@ -128,9 +132,9 @@ class LDPC_matrix: elif (H_matrix != None): self.H = H_matrix else: - print 'Error: provide either an alist filename,', - print 'parameters for constructing regular LDPC parity', - print 'check matrix, or a numpy array.' + print('Error: provide either an alist filename, ', end='') + print('parameters for constructing regular LDPC parity, ', end='') + print('check matrix, or a numpy array.') self.rank = linalg.matrix_rank(self.H) self.numRows = self.H.shape[0] @@ -159,31 +163,31 @@ class LDPC_matrix: # For this algorithm, n/p must be an integer, because the # number of rows in each submatrix must be a whole number. - ratioTest = (n*1.0)/q + ratioTest = (n*1.0) / q if ratioTest%1 != 0: - print '\nError in regular_LDPC_code_contructor: The' - print 'ratio of inputs n/q must be a whole number.\n' + print('\nError in regular_LDPC_code_contructor: The ', end='') + print('ratio of inputs n/q must be a whole number.\n') return # First submatrix first: - m = (n*p)/q # number of rows in H matrix - submatrix1 = zeros((m/p,n)) - for row in arange(m/p): + m = (n*p) / q # number of rows in H matrix + submatrix1 = zeros((m / p,n)) + for row in arange(m / p): range1 = row*q range2 = (row+1)*q submatrix1[row,range1:range2] = 1 - H = submatrix1 + H = submatrix1 # Create the other submatrices and vertically stack them on. submatrixNum = 2 newColumnOrder = arange(n) while submatrixNum <= p: - submatrix = zeros((m/p,n)) + submatrix = zeros((m / p,n)) shuffle(newColumnOrder) for columnNum in arange(n): submatrix[:,columnNum] = \ - submatrix1[:,newColumnOrder[columnNum]] + submatrix1[:,newColumnOrder[columnNum]] H = vstack((H,submatrix)) submatrixNum = submatrixNum + 1 @@ -197,14 +201,14 @@ class LDPC_matrix: for rowNum in arange(rows): nonzeros = array(H[rowNum,:].nonzero()) if nonzeros.shape[1] != q: - print 'Row', rowNum, 'has incorrect weight!' + print('Row', rowNum, 'has incorrect weight!') return # Check the column weights for columnNum in arange(cols): nonzeros = array(H[:,columnNum].nonzero()) if nonzeros.shape[1] != p: - print 'Row', columnNum, 'has incorrect weight!' + print('Row', columnNum, 'has incorrect weight!') return return H @@ -221,10 +225,10 @@ def greedy_upper_triangulation(H, verbose=0): # Per email from Dr. Urbanke, author of this textbook, this # algorithm requires H to be full rank if linalg.matrix_rank(H_t) != H_t.shape[0]: - print 'Rank of H:', linalg.matrix_rank(tempArray) - print 'H has', H_t.shape[0], 'rows' - print 'Error: H must be full rank.' - return + print('Rank of H:', linalg.matrix_rank(tempArray)) + print('H has', H_t.shape[0], 'rows') + print('Error: H must be full rank.') + return size = H_t.shape n = size[1] @@ -253,7 +257,7 @@ def greedy_upper_triangulation(H, verbose=0): # equal to the min positive residual degree, then pick a # random column c. indices = (minResidualDegrees == minimumResidualDegree)\ - .nonzero()[1] + .nonzero()[1] indices = indices + t if indices.shape[0] == 1: columnC = indices[0] @@ -282,7 +286,7 @@ def greedy_upper_triangulation(H, verbose=0): else: # This is the 'choose' case. rowsThatContainNonZeros = H_residual[:,columnC-t]\ - .nonzero()[0] + .nonzero()[0] # Swap column c with column t. (Book says t+1 but we # index from 0, not 1.) @@ -315,8 +319,8 @@ def greedy_upper_triangulation(H, verbose=0): while sub_index < (m - rowInH_t): Htemp[m-sub_index-1,:] = H_t[m-sub_index,:] sub_index = sub_index+1 - H_t = Htemp.copy() - Htemp = H_t.copy() + H_t = Htemp.copy() + Htemp = H_t.copy() # Save temp H as new H_t. H_t = Htemp.copy() @@ -327,7 +331,7 @@ def greedy_upper_triangulation(H, verbose=0): if g == 0: if verbose: - print 'Error: gap is 0.' + print('Error: gap is 0.') return # We need to ensure phi is nonsingular. @@ -348,22 +352,22 @@ def greedy_upper_triangulation(H, verbose=0): except linalg.linalg.LinAlgError: # Phi is singular if verbose > 1: - print 'Initial phi is singular' + print('Initial phi is singular') else: # Phi is nonsingular, so we need to use this version of H. if verbose > 1: - print 'Initial phi is nonsingular' + print('Initial phi is nonsingular') return [H_t, g, t] else: if verbose: - print 'Initial phi is all zeros:\n', phi + print('Initial phi is all zeros:\n', phi) # If the C and D submatrices are all zeros, there is no point in # shuffling them around in an attempt to find a good phi. if not (C.any() or D.any()): if verbose: - print 'C and D are all zeros. There is no hope in', - print 'finding a nonsingular phi matrix. ' + print('C and D are all zeros. There is no hope in',) + print('finding a nonsingular phi matrix. ') return # We can't look at every row/column permutation possibility @@ -378,8 +382,8 @@ def greedy_upper_triangulation(H, verbose=0): while iterationCount < maxIterations: if verbose > 1: - print 'iterationCount:', iterationCount - tempH = H_t.copy() + print('iterationCount:', iterationCount) + tempH = H_t.copy() shuffle(columnsToShuffle) shuffle(rowsToShuffle) @@ -387,7 +391,7 @@ def greedy_upper_triangulation(H, verbose=0): for newDestinationColumnNumber in arange(t,n): oldColumnNumber = columnsToShuffle[index] tempH[:,newDestinationColumnNumber] = \ - H_t[:,oldColumnNumber] + H_t[:,oldColumnNumber] index +=1 tempH2 = tempH.copy() @@ -414,23 +418,23 @@ def greedy_upper_triangulation(H, verbose=0): except linalg.linalg.LinAlgError: # Phi is singular if verbose > 1: - print 'Phi is still singular' + print('Phi is still singular') else: # Phi is nonsingular, so we're done. if verbose: - print 'Found a nonsingular phi on', - print 'iterationCount = ', iterationCount + print('Found a nonsingular phi on',) + print('iterationCount = ', iterationCount) return [H_t, g, t] else: if verbose > 1: - print 'phi is all zeros' + print('phi is all zeros') iterationCount +=1 # If we've reached this point, then we haven't found a # version of H that has a nonsingular phi. if verbose: - print '--- Error: nonsingular phi matrix not found.' + print('--- Error: nonsingular phi matrix not found.') def inv_mod2(squareMatrix, verbose=0): """ @@ -468,16 +472,16 @@ def inv_mod2(squareMatrix, verbose=0): tempTest[rowNum,colNum] = 0 else: if verbose > 1: - print 'In inv_mod2. Rounding error on this', - print 'value? Mod 2 has already been done.', - print 'value:', value + print('In inv_mod2. Rounding error on this',) + print('value? Mod 2 has already been done.',) + print('value:', value) test = tempTest.copy() if (test - eye(t,t) % 2).any(): if verbose: - print 'Error in inv_mod2: did not find inverse.' - # TODO is this the most appropriate error to raise? + print('Error in inv_mod2: did not find inverse.') + # TODO is this the most appropriate error to raise? raise linalg.linalg.LinAlgError else: return C @@ -520,7 +524,7 @@ def get_full_rank_H_matrix(H, verbose=False): tempArray = H.copy() if linalg.matrix_rank(tempArray) == tempArray.shape[0]: if verbose: - print 'Returning H; it is already full rank.' + print('Returning H; it is already full rank.') return tempArray numRows = tempArray.shape[0] @@ -538,8 +542,8 @@ def get_full_rank_H_matrix(H, verbose=False): while i < limit: if verbose: - print 'In get_full_rank_H_matrix; i:', i - # Flag indicating that the row contains a non-zero entry + print('In get_full_rank_H_matrix; i:', i) + # Flag indicating that the row contains a non-zero entry found = False for j in arange(i, numColumns): if tempArray[i, j] == 1: @@ -588,8 +592,8 @@ def get_full_rank_H_matrix(H, verbose=False): newH[:,index] = tempHarray[:,columnOrder[0,index]] if verbose: - print 'original H.shape:', H.shape - print 'newH.shape:', newH.shape + print('original H.shape:', H.shape) + print('newH.shape:', newH.shape) return newH @@ -604,13 +608,13 @@ def get_best_matrix(H, numIterations=100, verbose=False): index = 1 while index <= numIterations: if verbose: - print '--- In get_best_matrix, iteration:', index - index += 1 + print('--- In get_best_matrix, iteration:', index) + index += 1 try: ret = greedy_upper_triangulation(H, verbose) - except ValueError, e: + except ValueError as e: if verbose > 1: - print 'greedy_upper_triangulation error: ', e + print('greedy_upper_triangulation error: ', e) else: if ret: [betterH, gap, t] = ret @@ -632,8 +636,8 @@ def get_best_matrix(H, numIterations=100, verbose=False): return [bestH, bestGap] else: if verbose: - print 'Error: Could not find appropriate H form', - print 'for encoding.' + print('Error: Could not find appropriate H form',) + print('for encoding.') return def getSystematicGmatrix(GenMatrix): @@ -643,7 +647,7 @@ def getSystematicGmatrix(GenMatrix): matrix and P is the parity submatrix. If the GenMatrix matrix provided is not full rank, then dependent rows will be deleted. - This function does not convert parity check (H) matrices to the + This function does not convert parity check (H) matrices to the generator matrix format. Use the function getSystematicGmatrixFromH for that purpose. """ @@ -682,7 +686,7 @@ def getSystematicGmatrix(GenMatrix): tempArray = move_row_to_bottom(i,tempArray) # decrease limit since we just found a row of 0s limit -= 1 - # the rows below i are the dependent rows, which we discard + # the rows below i are the dependent rows, which we discard G = tempArray[0:i,:] return G @@ -696,7 +700,7 @@ def getSystematicGmatrixFromH(H, verbose=False): will be deleted first. """ if verbose: - print 'received H with size: ', H.shape + print('received H with size: ', H.shape) # First, put the H matrix into the form H = [I|m] where: # I is (n-k) x (n-k) identity matrix @@ -716,5 +720,5 @@ def getSystematicGmatrixFromH(H, verbose=False): k = m.shape[1] G = concatenate((identity(k),m.T),axis=1) if verbose: - print 'returning G with size: ', G.shape - return G
\ No newline at end of file + print('returning G with size: ', G.shape) + return G diff --git a/gr-fec/python/fec/LDPC/__init__.py b/gr-fec/python/fec/LDPC/__init__.py index 173171a24f..7ee9196d12 100644 --- a/gr-fec/python/fec/LDPC/__init__.py +++ b/gr-fec/python/fec/LDPC/__init__.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import +from __future__ import unicode_literals # # Copyright 2015 Free Software Foundation, Inc. # @@ -19,4 +21,4 @@ # Boston, MA 02110-1301, USA. # -from Generate_LDPC_matrix_functions import * +from .Generate_LDPC_matrix_functions import * diff --git a/gr-fec/python/fec/__init__.py b/gr-fec/python/fec/__init__.py index 6c82232d4f..e5458686dc 100644 --- a/gr-fec/python/fec/__init__.py +++ b/gr-fec/python/fec/__init__.py @@ -23,25 +23,28 @@ Blocks for forward error correction. ''' +from __future__ import absolute_import +from __future__ import unicode_literals + try: - from fec_swig import * + from .fec_swig import * except ImportError: import os dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from fec_swig import * + from .fec_swig import * -from bitflip import * -from extended_encoder import extended_encoder -from extended_decoder import extended_decoder -from threaded_encoder import threaded_encoder -from threaded_decoder import threaded_decoder -from capillary_threaded_decoder import capillary_threaded_decoder -from capillary_threaded_encoder import capillary_threaded_encoder -from extended_async_encoder import extended_async_encoder -from extended_tagged_encoder import extended_tagged_encoder -from extended_tagged_decoder import extended_tagged_decoder +from .bitflip import * +from .extended_encoder import extended_encoder +from .extended_decoder import extended_decoder +from .threaded_encoder import threaded_encoder +from .threaded_decoder import threaded_decoder +from .capillary_threaded_decoder import capillary_threaded_decoder +from .capillary_threaded_encoder import capillary_threaded_encoder +from .extended_async_encoder import extended_async_encoder +from .extended_tagged_encoder import extended_tagged_encoder +from .extended_tagged_decoder import extended_tagged_decoder -from fec_test import fec_test -from bercurve_generator import bercurve_generator +from .fec_test import fec_test +from .bercurve_generator import bercurve_generator diff --git a/gr-fec/python/fec/_qa_helper.py b/gr-fec/python/fec/_qa_helper.py index 8722453441..85a19ed7c5 100755..100644 --- a/gr-fec/python/fec/_qa_helper.py +++ b/gr-fec/python/fec/_qa_helper.py @@ -20,12 +20,19 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import blocks -from gnuradio import gr -import sys, numpy +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + + +import numpy + +from gnuradio import gr, blocks +# Must use absolute import here because this file is not installed as part +# of the module +from gnuradio.fec import extended_encoder +from gnuradio.fec import extended_decoder -from extended_encoder import extended_encoder -from extended_decoder import extended_decoder class map_bb(gr.sync_block): def __init__(self, bitmap): @@ -37,7 +44,7 @@ class map_bb(gr.sync_block): self.bitmap = bitmap def work(self, input_items, output_items): - output_items[0][:] = map(lambda x: self.bitmap[x], input_items[0]) + output_items[0][:] = [self.bitmap[x] for x in input_items[0]] return len(output_items[0]) @@ -85,6 +92,6 @@ if __name__ == '__main__': errs += 1 if errs == 0: - print "Decoded properly" + print("Decoded properly") else: - print "Problem Decoding" + print("Problem Decoding") diff --git a/gr-fec/python/fec/bercurve_generator.py b/gr-fec/python/fec/bercurve_generator.py index 3221a683ce..29a02c135a 100644 --- a/gr-fec/python/fec/bercurve_generator.py +++ b/gr-fec/python/fec/bercurve_generator.py @@ -20,10 +20,12 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import +from __future__ import unicode_literals from gnuradio import gr, blocks import numpy -from fec_test import fec_test +from .fec_test import fec_test class bercurve_generator(gr.hier_block2): @@ -40,7 +42,7 @@ class bercurve_generator(gr.hier_block2): self.decoder_list = decoder_list self.puncpat = puncpat - self.random_gen_b_0 = blocks.vector_source_b(map(int, numpy.random.randint(0, 256, 100000)), True) + self.random_gen_b_0 = blocks.vector_source_b(list(map(int, numpy.random.randint(0, 256, 100000))), True) self.deinterleave = blocks.deinterleave(gr.sizeof_char*1) self.connect(self.random_gen_b_0, self.deinterleave) self.ber_generators = [] diff --git a/gr-fec/python/fec/bitflip.py b/gr-fec/python/fec/bitflip.py index 235dc19a05..332a288e7e 100644 --- a/gr-fec/python/fec/bitflip.py +++ b/gr-fec/python/fec/bitflip.py @@ -20,6 +20,11 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals + + + def bitreverse(mint): res = 0; while mint != 0: @@ -51,7 +56,7 @@ def read_bitlist(bitlist): def read_big_bitlist(bitlist): ret = [] - for j in range(0, len(bitlist)/64): + for j in range(0, len(bitlist) / 64): res = 0; for i in range(0, 64): if int(bitlist[j*64+i]) == 1: @@ -72,9 +77,9 @@ def generate_symmetries(symlist): for i in range(len(symlist[0])): retlist.append(symlist[0][i:] + symlist[0][0:i]); invlist = symlist[0]; - for i in range(1, len(symlist[0])/2): - invlist[i] = symlist[0][i + len(symlist[0])/2]; - invlist[i + len(symlist[0])/2] = symlist[0][i]; + for i in range(1, len(symlist[0]) / 2): + invlist[i] = symlist[0][i + len(symlist[0]) / 2]; + invlist[i + len(symlist[0]) / 2] = symlist[0][i]; for i in range(len(symlist[0])): retlist.append(symlist[0][i:] + symlist[0][0:i]); return retlist; diff --git a/gr-fec/python/fec/capillary_threaded_decoder.py b/gr-fec/python/fec/capillary_threaded_decoder.py index 9a00cde192..821e3cf92a 100644 --- a/gr-fec/python/fec/capillary_threaded_decoder.py +++ b/gr-fec/python/fec/capillary_threaded_decoder.py @@ -20,10 +20,15 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, blocks -import fec_swig as fec +from __future__ import division +from __future__ import unicode_literals + import math +from gnuradio import gr, blocks +from . import fec_swig as fec + + class capillary_threaded_decoder(gr.hier_block2): def __init__(self, decoder_list_0, input_size, output_size): gr.hier_block2.__init__( @@ -64,7 +69,7 @@ class capillary_threaded_decoder(gr.hier_block2): branchcount += 2 codercount = 0 - for i in range(len(decoder_list_0)/2): + for i in range(len(decoder_list_0) // 2): self.connect((self.deinterleaves_0[rootcount], 0), (self.generic_decoders_0[codercount], 0)) self.connect((self.deinterleaves_0[rootcount], 1), (self.generic_decoders_0[codercount + 1], 0)) rootcount += 1 @@ -80,7 +85,7 @@ class capillary_threaded_decoder(gr.hier_block2): branchcount += 2 codercount = 0 - for i in range(len(decoder_list_0)/2): + for i in range(len(decoder_list_0) // 2): self.connect((self.generic_decoders_0[codercount], 0), (self.interleaves_0[rootcount], 0)) self.connect((self.generic_decoders_0[codercount + 1], 0), (self.interleaves_0[rootcount], 1)) rootcount += 1 diff --git a/gr-fec/python/fec/capillary_threaded_encoder.py b/gr-fec/python/fec/capillary_threaded_encoder.py index 21d4af62ca..899d10c3b7 100644 --- a/gr-fec/python/fec/capillary_threaded_encoder.py +++ b/gr-fec/python/fec/capillary_threaded_encoder.py @@ -20,10 +20,15 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, blocks -import fec_swig as fec +from __future__ import division +from __future__ import unicode_literals + import math +from gnuradio import gr, blocks +from . import fec_swig as fec + + class capillary_threaded_encoder(gr.hier_block2): def __init__(self, encoder_list_0, input_size=gr.sizeof_char, output_size=gr.sizeof_char): gr.hier_block2.__init__(self, "Capillary Threaded Encoder", @@ -43,7 +48,7 @@ class capillary_threaded_encoder(gr.hier_block2): self.deinterleaves_0.append(blocks.deinterleave(input_size, fec.get_encoder_input_size(encoder_list_0[0]))) - self.generic_encoders_0 = []; + self.generic_encoders_0 = []; for i in range(len(encoder_list_0)): self.generic_encoders_0.append(fec.encoder(encoder_list_0[i], input_size, output_size)) @@ -64,7 +69,7 @@ class capillary_threaded_encoder(gr.hier_block2): branchcount += 2; codercount = 0; - for i in range(len(encoder_list_0)/2): + for i in range(len(encoder_list_0) // 2): self.connect((self.deinterleaves_0[rootcount], 0), (self.generic_encoders_0[codercount], 0)) self.connect((self.deinterleaves_0[rootcount], 1), (self.generic_encoders_0[codercount + 1], 0)) rootcount += 1; @@ -82,13 +87,13 @@ class capillary_threaded_encoder(gr.hier_block2): codercount = 0; - for i in range(len(encoder_list_0)/2): + for i in range(len(encoder_list_0) // 2): self.connect((self.generic_encoders_0[codercount], 0), (self.interleaves_0[rootcount], 0)) self.connect((self.generic_encoders_0[codercount + 1], 0), (self.interleaves_0[rootcount], 1)) rootcount += 1; codercount += 2; - if((len(self.encoder_list_0)) > 1): + if((len(self.encoder_list_0)) > 1): self.connect((self, 0), (self.deinterleaves_0[0], 0)) self.connect((self.interleaves_0[0], 0), (self, 0)) else: diff --git a/gr-fec/python/fec/extended_async_encoder.py b/gr-fec/python/fec/extended_async_encoder.py index fffe64aeb8..cebd5c652b 100644 --- a/gr-fec/python/fec/extended_async_encoder.py +++ b/gr-fec/python/fec/extended_async_encoder.py @@ -20,11 +20,18 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr -import fec_swig as fec -from bitflip import read_bitlist +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import weakref +from gnuradio import gr + +from . import fec_swig as fec +from .bitflip import read_bitlist + + class extended_async_encoder(gr.hier_block2): def __init__(self, encoder_obj_list, puncpat=None): gr.hier_block2.__init__(self, "extended_async_encoder", diff --git a/gr-fec/python/fec/extended_decoder.py b/gr-fec/python/fec/extended_decoder.py index 7e6cf452f9..3c7ebefb49 100644 --- a/gr-fec/python/fec/extended_decoder.py +++ b/gr-fec/python/fec/extended_decoder.py @@ -20,24 +20,25 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, blocks -import fec_swig as fec -from bitflip import * -import sys +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals -if sys.modules.has_key("gnuradio.digital"): - digital = sys.modules["gnuradio.digital"] -else: - from gnuradio import digital +from gnuradio import gr, blocks, digital + +from . import fec_swig as fec + +from .bitflip import * +from .threaded_decoder import threaded_decoder +from .capillary_threaded_decoder import capillary_threaded_decoder -from threaded_decoder import threaded_decoder -from capillary_threaded_decoder import capillary_threaded_decoder class extended_decoder(gr.hier_block2): #solution to log_(1-2*t)(1-2*.0335) = 1/taps where t is thresh (syndrome density) #for i in numpy.arange(.1, .499, .01): - #print str(log((1-(2 * .035)), (1-(2 * i)))) + ':' + str(i); + #print(str(log((1-(2 * .035)), (1-(2 * i)))) + ':' + str(i);) garbletable = { 0.310786835319:0.1, 0.279118162802:0.11, @@ -127,13 +128,13 @@ class extended_decoder(gr.hier_block2): cat.append(i); synd_garble = .49 - idx_list = self.garbletable.keys() + idx_list = list(self.garbletable.keys()) idx_list.sort() for i in idx_list: - if 1.0/self.ann.count('1') >= i: + if 1.0 / self.ann.count('1') >= i: synd_garble = self.garbletable[i] - print 'using syndrom garble threshold ' + str(synd_garble) + 'for conv_bit_corr_bb' - print 'ceiling: .0335 data garble rate' + print('using syndrom garble threshold ' + str(synd_garble) + 'for conv_bit_corr_bb') + print('ceiling: .0335 data garble rate') self.blocks.append(fec.conv_bit_corr_bb(cat, len(puncpat) - puncpat.count('0'), len(ann), integration_period, flush, synd_garble)) diff --git a/gr-fec/python/fec/extended_encoder.py b/gr-fec/python/fec/extended_encoder.py index 1c6da0ecb1..992c2bdad4 100644 --- a/gr-fec/python/fec/extended_encoder.py +++ b/gr-fec/python/fec/extended_encoder.py @@ -20,12 +20,16 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import +from __future__ import unicode_literals + from gnuradio import gr, blocks -import fec_swig as fec -from threaded_encoder import threaded_encoder -from capillary_threaded_encoder import capillary_threaded_encoder -from bitflip import read_bitlist +from . import fec_swig as fec +from .threaded_encoder import threaded_encoder +from .capillary_threaded_encoder import capillary_threaded_encoder +from .bitflip import read_bitlist + class extended_encoder(gr.hier_block2): def __init__(self, encoder_obj_list, threading, puncpat=None): diff --git a/gr-fec/python/fec/extended_tagged_decoder.py b/gr-fec/python/fec/extended_tagged_decoder.py index 9713907712..c119bf9938 100644 --- a/gr-fec/python/fec/extended_tagged_decoder.py +++ b/gr-fec/python/fec/extended_tagged_decoder.py @@ -20,21 +20,23 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, blocks -import fec_swig as fec -from bitflip import * -import sys +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + +from gnuradio import gr, blocks, digital + +from . import fec_swig as fec + +from .bitflip import * -if sys.modules.has_key("gnuradio.digital"): - digital = sys.modules["gnuradio.digital"] -else: - from gnuradio import digital class extended_tagged_decoder(gr.hier_block2): #solution to log_(1-2*t)(1-2*.0335) = 1/taps where t is thresh (syndrome density) #for i in numpy.arange(.1, .499, .01): - #print str(log((1-(2 * .035)), (1-(2 * i)))) + ':' + str(i); + #print(str(log((1-(2 * .035)), (1-(2 * i)))) + ':' + str(i);) garbletable = { 0.310786835319:0.1, 0.279118162802:0.11, @@ -136,13 +138,13 @@ class extended_tagged_decoder(gr.hier_block2): cat.append(i); synd_garble = .49 - idx_list = self.garbletable.keys() + idx_list = list(self.garbletable.keys()) idx_list.sort() for i in idx_list: - if 1.0/self.ann.count('1') >= i: + if 1.0 / self.ann.count('1') >= i: synd_garble = self.garbletable[i] - print 'using syndrom garble threshold ' + str(synd_garble) + 'for conv_bit_corr_bb' - print 'ceiling: .0335 data garble rate' + print('using syndrom garble threshold ' + str(synd_garble) + 'for conv_bit_corr_bb') + print('ceiling: .0335 data garble rate') self.blocks.append(fec.conv_bit_corr_bb(cat, len(puncpat) - puncpat.count('0'), len(ann), integration_period, flush, synd_garble)) diff --git a/gr-fec/python/fec/extended_tagged_encoder.py b/gr-fec/python/fec/extended_tagged_encoder.py index d3cf1d80d2..9f4a684c4a 100644 --- a/gr-fec/python/fec/extended_tagged_encoder.py +++ b/gr-fec/python/fec/extended_tagged_encoder.py @@ -20,10 +20,16 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import +from __future__ import unicode_literals + + from gnuradio import gr, blocks -import fec_swig as fec -from bitflip import read_bitlist +from . import fec_swig as fec + +from .bitflip import read_bitlist + class extended_tagged_encoder(gr.hier_block2): def __init__(self, encoder_obj_list, puncpat=None, lentagname=None, mtu=1500): diff --git a/gr-fec/python/fec/fec_test.py b/gr-fec/python/fec/fec_test.py index 6466a0bcb4..dfb5b1b28e 100644 --- a/gr-fec/python/fec/fec_test.py +++ b/gr-fec/python/fec/fec_test.py @@ -20,18 +20,21 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals from gnuradio.fec.bitflip import read_bitlist from gnuradio import gr, blocks, analog import math import sys -if sys.modules.has_key("gnuradio.digital"): +if "gnuradio.digital" in sys.modules: digital = sys.modules["gnuradio.digital"] else: from gnuradio import digital -from extended_encoder import extended_encoder -from extended_decoder import extended_decoder +from .extended_encoder import extended_encoder +from .extended_decoder import extended_decoder class fec_test(gr.hier_block2): @@ -64,7 +67,7 @@ class fec_test(gr.hier_block2): ann=None, puncpat=puncpat, integration_period=10000, rotator=None) - noise = math.sqrt((10.0**(-esno/10.0))/2.0) + noise = math.sqrt((10.0**(old_div(-esno / 10.0)),2.0)) #self.fastnoise = analog.fastnoise_source_f(analog.GR_GAUSSIAN, noise, seed, 8192) self.fastnoise = analog.noise_source_f(analog.GR_GAUSSIAN, noise, seed) self.addnoise = blocks.add_ff(1) diff --git a/gr-fec/python/fec/polar/CMakeLists.txt b/gr-fec/python/fec/polar/CMakeLists.txt index 1efed062ff..2c126746e7 100644 --- a/gr-fec/python/fec/polar/CMakeLists.txt +++ b/gr-fec/python/fec/polar/CMakeLists.txt @@ -27,6 +27,9 @@ GR_PYTHON_INSTALL( channel_construction_awgn.py channel_construction_bec.py helper_functions.py + encoder.py + decoder.py + common.py DESTINATION ${GR_PYTHON_DIR}/gnuradio/fec/polar ) diff --git a/gr-fec/python/fec/polar/__init__.py b/gr-fec/python/fec/polar/__init__.py index ce1b1459fb..e06020b886 100644 --- a/gr-fec/python/fec/polar/__init__.py +++ b/gr-fec/python/fec/polar/__init__.py @@ -21,9 +21,12 @@ # turn this folder into a Python module -import channel_construction as cc -from channel_construction_bec import bhattacharyya_bounds -from helper_functions import is_power_of_two +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals +from . import channel_construction as cc +from .channel_construction_bec import bhattacharyya_bounds +from .helper_functions import is_power_of_two CHANNEL_TYPE_AWGN = 'AWGN' diff --git a/gr-fec/python/fec/polar/channel_construction.py b/gr-fec/python/fec/polar/channel_construction.py index b7a3dee3bd..d3b33fe3ac 100644 --- a/gr-fec/python/fec/polar/channel_construction.py +++ b/gr-fec/python/fec/polar/channel_construction.py @@ -23,12 +23,14 @@ foundational paper for polar codes. ''' +from __future__ import print_function +from __future__ import absolute_import -from channel_construction_bec import calculate_bec_channel_capacities -from channel_construction_bec import design_snr_to_bec_eta -from channel_construction_bec import bhattacharyya_bounds -from channel_construction_awgn import tal_vardy_tpm_algorithm -from helper_functions import * +from .channel_construction_bec import calculate_bec_channel_capacities +from .channel_construction_bec import design_snr_to_bec_eta +from .channel_construction_bec import bhattacharyya_bounds +from .channel_construction_awgn import tal_vardy_tpm_algorithm +from .helper_functions import * Z_PARAM_FIRST_HEADER_LINE = "Bhattacharyya parameters (Z-parameters) for a polar code" @@ -117,7 +119,7 @@ def load_z_parameters(block_size, design_snr, mu): def main(): np.set_printoptions(precision=3, linewidth=150) - print 'channel construction Bhattacharyya bounds by Arikan' + print('channel construction Bhattacharyya bounds by Arikan') n = 10 m = 2 ** n k = m // 2 diff --git a/gr-fec/python/fec/polar/channel_construction_awgn.py b/gr-fec/python/fec/polar/channel_construction_awgn.py index 7d820b2883..c75f3d1c44 100755..100644 --- a/gr-fec/python/fec/polar/channel_construction_awgn.py +++ b/gr-fec/python/fec/polar/channel_construction_awgn.py @@ -18,6 +18,11 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + ''' Based on 2 papers: [1] Ido Tal, Alexander Vardy: 'How To Construct Polar Codes', 2013 @@ -27,11 +32,10 @@ for an in-depth description of a widely used algorithm for channel construction. for an overview of different approaches ''' - from scipy.optimize import fsolve from scipy.special import erfc -from helper_functions import * -from channel_construction_bec import bhattacharyya_bounds +from .helper_functions import * +from .channel_construction_bec import bhattacharyya_bounds def solver_equation(val, s): @@ -190,7 +194,7 @@ def upper_convolve(tpm, mu): idx = -1 for i in range(mu): idx += 1 - q[0, idx] = (tpm[0, i] ** 2 + tpm[1, i] ** 2) / 2 + q[0, idx] = (tpm[0 / i] ** 2 + tpm[1, i] ** 2, 2) q[1, idx] = tpm[0, i] * tpm[1, i] for j in range(i + 1, mu): idx += 1 @@ -211,8 +215,8 @@ def lower_convolve(tpm, mu): idx = -1 for i in range(0, mu): idx += 1 - q[0, idx] = (tpm[0, i] ** 2) / 2 - q[1, idx] = (tpm[1, i] ** 2) / 2 + q[0, idx] = (tpm[0 / i] ** 2, 2) + q[1, idx] = (tpm[1 / i] ** 2, 2) if q[0, idx] < q[1, idx]: q[0, idx], q[1, idx] = swap_values(q[0, idx], q[1, idx]) idx += 1 @@ -249,7 +253,7 @@ def normalize_q(q, tpm): def main(): - print 'channel construction AWGN main' + print('channel construction AWGN main') n = 8 m = 2 ** n design_snr = 0.0 diff --git a/gr-fec/python/fec/polar/channel_construction_bec.py b/gr-fec/python/fec/polar/channel_construction_bec.py index 4b35602d96..f920024ee0 100644 --- a/gr-fec/python/fec/polar/channel_construction_bec.py +++ b/gr-fec/python/fec/polar/channel_construction_bec.py @@ -18,8 +18,13 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + import numpy as np -import helper_functions as hf +from . import helper_functions as hf def bec_channel(eta): @@ -220,7 +225,7 @@ def plot_capacity_histogram(design_snr, save_file=None): def main(): - print 'channel construction main' + print('channel construction main') n = 11 block_size = int(2 ** n) design_snr = -1.59 diff --git a/gr-fec/python/fec/polar/common.py b/gr-fec/python/fec/polar/common.py index fa5987b6d2..8604f05ba1 100644 --- a/gr-fec/python/fec/polar/common.py +++ b/gr-fec/python/fec/polar/common.py @@ -18,16 +18,20 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import numpy as np -from helper_functions import * +from .helper_functions import * ''' PolarCommon holds value checks and common initializer code for both Encoder and Decoder. ''' -class PolarCommon: +class PolarCommon(object): def __init__(self, n, k, frozen_bit_position, frozenbits=None): if not is_power_of_two(n): raise ValueError("n={0} is not a power of 2!".format(n)) @@ -81,4 +85,4 @@ class PolarCommon: return self._encode_efficient(vec) def info_print(self): - print "POLAR code ({0}, {1})".format(self.N, self.K) + print("POLAR code ({0}, {1})".format(self.N, self.K)) diff --git a/gr-fec/python/fec/polar/decoder.py b/gr-fec/python/fec/polar/decoder.py index 8748d284f7..5acd04aa72 100644 --- a/gr-fec/python/fec/polar/decoder.py +++ b/gr-fec/python/fec/polar/decoder.py @@ -18,11 +18,16 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals + import numpy as np -from common import PolarCommon +from .common import PolarCommon # for dev -from encoder import PolarEncoder +from .encoder import PolarEncoder from matplotlib import pyplot as plt @@ -239,31 +244,31 @@ def test_reverse_enc_dec(): encoder = PolarEncoder(n, k, frozenbitposition, frozenbits) decoder = PolarDecoder(n, k, frozenbitposition, frozenbits) encoded = encoder.encode(bits) - print 'encoded:', encoded + print('encoded:', encoded) rx = decoder.decode(encoded) - print 'bits:', bits - print 'rx :', rx - print (bits == rx).all() + print('bits:', bits) + print('rx :', rx) + print((bits == rx).all()) def compare_decoder_impls(): - print '\nthis is decoder test' + print('\nthis is decoder test') n = 8 k = 4 frozenbits = np.zeros(n - k) # frozenbitposition16 = np.array((0, 1, 2, 3, 4, 5, 8, 9), dtype=int) frozenbitposition = np.array((0, 1, 2, 4), dtype=int) bits = np.random.randint(2, size=k) - print 'bits:', bits + print('bits:', bits) encoder = PolarEncoder(n, k, frozenbitposition, frozenbits) decoder = PolarDecoder(n, k, frozenbitposition, frozenbits) encoded = encoder.encode(bits) - print 'encoded:', encoded + print('encoded:', encoded) rx_st = decoder._lr_sc_decoder(encoded) rx_eff = decoder._lr_sc_decoder_efficient(encoded) - print 'standard :', rx_st - print 'efficient:', rx_eff - print (rx_st == rx_eff).all() + print('standard :', rx_st) + print('efficient:', rx_eff) + print((rx_st == rx_eff).all()) def main(): @@ -279,14 +284,14 @@ def main(): # decoder = PolarDecoder(n, k, frozenbitposition, frozenbits) # # bits = np.ones(k, dtype=int) - # print "bits: ", bits + # print("bits: ", bits) # evec = encoder.encode(bits) - # print "froz: ", encoder._insert_frozen_bits(bits) - # print "evec: ", evec + # print("froz: ", encoder._insert_frozen_bits(bits)) + # print("evec: ", evec) # # evec[1] = 0 # deced = decoder._lr_sc_decoder(evec) - # print 'SC decoded:', deced + # print('SC decoded:', deced) # # test_reverse_enc_dec() # compare_decoder_impls() diff --git a/gr-fec/python/fec/polar/encoder.py b/gr-fec/python/fec/polar/encoder.py index cc8fda2d1b..c5c7c05d5b 100644 --- a/gr-fec/python/fec/polar/encoder.py +++ b/gr-fec/python/fec/polar/encoder.py @@ -18,9 +18,13 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import numpy as np -from common import PolarCommon -import helper_functions as hf +from .common import PolarCommon +from . import helper_functions as hf class PolarEncoder(PolarCommon): @@ -99,8 +103,8 @@ def test_pseudo_rate_1_encoder(encoder, ntests, k): u_hat = encoder._encode_efficient(fenc) if not (u_hat == u).all(): print('rate-1 encoder/decoder failed') - print u - print u_hat + print(u) + print(u_hat) return False return True @@ -114,11 +118,11 @@ def test_encoder_impls(): # frozenbitposition8 = np.array((0, 1, 2, 4), dtype=int) # keep it! frozenbitposition = np.array((0, 1, 2, 3, 4, 5, 8, 9), dtype=int) encoder = PolarEncoder(n, k, frozenbitposition) #, frozenbits) - print 'result:', compare_results(encoder, ntests, k) + print('result:', compare_results(encoder, ntests, k)) print('Test rate-1 encoder/decoder chain results') r1_test = test_pseudo_rate_1_encoder(encoder, ntests, k) - print 'Test rate-1 encoder/decoder:', r1_test + print('Test rate-1 encoder/decoder:', r1_test) test_systematic_encoder(encoder, ntests, k) diff --git a/gr-fec/python/fec/polar/helper_functions.py b/gr-fec/python/fec/polar/helper_functions.py index 85140c856f..6ea30c799b 100644 --- a/gr-fec/python/fec/polar/helper_functions.py +++ b/gr-fec/python/fec/polar/helper_functions.py @@ -18,6 +18,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + import numpy as np import time, sys import copy @@ -33,7 +37,7 @@ def bsc_channel(p): p denotes an erroneous transistion ''' if not (p >= 0.0 and p <= 1.0): - print "given p is out of range!" + print("given p is out of range!") return np.array([], dtype=float) # 0 -> 0, 0 -> 1, 1 -> 0, 1 -> 1 @@ -99,7 +103,7 @@ def get_Fn(n): def get_Gn(n): # this matrix is called generator matrix if not is_power_of_two(n): - print "invalid input" + print("invalid input") return None if n == 1: return np.array([1, ]) @@ -177,7 +181,7 @@ def bhattacharyya_parameter(w): def main(): - print 'helper functions' + print('helper functions') for i in range(9): print(i, 'is power of 2: ', is_power_of_two(i)) diff --git a/gr-fec/python/fec/polar/testbed.py b/gr-fec/python/fec/polar/testbed.py index 3f8e814e4f..08ef0de558 100755..100644 --- a/gr-fec/python/fec/polar/testbed.py +++ b/gr-fec/python/fec/polar/testbed.py @@ -18,11 +18,16 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division +from __future__ import unicode_literals -from encoder import PolarEncoder -from decoder import PolarDecoder -import channel_construction as cc -from helper_functions import * + +from .encoder import PolarEncoder +from .decoder import PolarDecoder +from . import channel_construction as cc +from .helper_functions import * import matplotlib.pyplot as plt @@ -58,13 +63,13 @@ def is_equal(first, second): if not (first == second).all(): result = first == second for i in range(len(result)): - print '{0:4}: {1:2} == {2:1} = {3}'.format(i, first[i], second[i], result[i]) + print('{0:4}: {1:2} == {2:1} = {3}'.format(i, first[i], second[i], result[i])) return False return True def exact_value(la, lb): - return np.log((np.exp(la + lb) + 1) / (np.exp(la) + np.exp(lb))) + return np.log((np.exp(la + lb) + 1) / (np.exp(la + np.exp(lb)))) def approx_value(la, lb): @@ -112,7 +117,7 @@ def test_1024_rate_1_code(): recv = decoder.decode(rx) channel_counter += (bits == recv) - print channel_counter + print(channel_counter) print(np.min(channel_counter), np.max(channel_counter)) np.save('channel_counter_' + str(ntests) + '.npy', channel_counter) @@ -330,7 +335,7 @@ def main(): # frozenbits = np.zeros(n - k) # frozenbitposition8 = np.array((0, 1, 2, 4), dtype=int) # frozenbitposition = np.array((0, 1, 2, 3, 4, 5, 8, 9), dtype=int) - # print frozenbitposition + # print(frozenbitposition) # test_enc_dec_chain() # test_1024_rate_1_code() diff --git a/gr-fec/python/fec/qa_ber_bf.py b/gr-fec/python/fec/qa_ber_bf.py index 5d1734de0c..0d720988cb 100644 --- a/gr-fec/python/fec/qa_ber_bf.py +++ b/gr-fec/python/fec/qa_ber_bf.py @@ -20,11 +20,15 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, blocks -import fec_swig as fec +from __future__ import print_function + + import numpy import copy +from gnuradio import gr, gr_unittest, blocks +from gnuradio import fec + class test_ber_bf(gr_unittest.TestCase): def setUp(self): @@ -132,8 +136,8 @@ class test_ber_bf(gr_unittest.TestCase): data = dst.data() expected_result = [-2.0, ] - print data - print expected_result + print(data) + print(expected_result) self.assertFloatTuplesAlmostEqual(expected_result, data, 5) diff --git a/gr-fec/python/fec/qa_depuncture.py b/gr-fec/python/fec/qa_depuncture.py index 5566e83a25..9ec57bfc41 100644 --- a/gr-fec/python/fec/qa_depuncture.py +++ b/gr-fec/python/fec/qa_depuncture.py @@ -20,11 +20,14 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest -import fec_swig as fec -import blocks_swig as blocks +from __future__ import division + from collections import deque +from gnuradio import gr, gr_unittest, blocks +from gnuradio import fec + + class test_depuncture (gr_unittest.TestCase): def depuncture_setup(self): @@ -37,7 +40,7 @@ class test_depuncture (gr_unittest.TestCase): k = 0 self.expected = [] - for n in range(len(self.src_data)/(self.puncsize - self.puncholes)): + for n in range(len(self.src_data) // (self.puncsize - self.puncholes)): for i in range(self.puncsize): if _puncpat[i] == 1: self.expected.append(self.src_data[k]); @@ -46,7 +49,7 @@ class test_depuncture (gr_unittest.TestCase): self.expected.append(self.sym) def setUp(self): - self.src_data = 2000*range(64) + self.src_data = 2000*list(range(64)) self.tb = gr.top_block () def tearDown(self): @@ -64,15 +67,15 @@ class test_depuncture (gr_unittest.TestCase): self.depuncture_setup() src = blocks.vector_source_b(self.src_data) - op = fec.depuncture_bb(self.puncsize, self.puncpat, + op = fec.depuncture_bb(self.puncsize, self.puncpat, self.delay, self.sym) - dst = blocks.vector_sink_b() + dst = blocks.vector_sink_b() - self.tb.connect(src, op, dst) - self.tb.run() + self.tb.connect(src, op, dst) + self.tb.run() - dst_data = list(dst.data()) - for i in xrange(len(dst_data)): + dst_data = list(dst.data()) + for i in range(len(dst_data)): dst_data[i] = int(dst_data[i]) self.assertEqual(self.expected, dst_data) @@ -89,15 +92,15 @@ class test_depuncture (gr_unittest.TestCase): self.depuncture_setup() src = blocks.vector_source_b(self.src_data) - op = fec.depuncture_bb(self.puncsize, self.puncpat, + op = fec.depuncture_bb(self.puncsize, self.puncpat, self.delay, self.sym) - dst = blocks.vector_sink_b() + dst = blocks.vector_sink_b() - self.tb.connect(src, op, dst) - self.tb.run() + self.tb.connect(src, op, dst) + self.tb.run() - dst_data = list(dst.data()) - for i in xrange(len(dst_data)): + dst_data = list(dst.data()) + for i in range(len(dst_data)): dst_data[i] = int(dst_data[i]) self.assertEqual(self.expected, dst_data) @@ -115,15 +118,15 @@ class test_depuncture (gr_unittest.TestCase): self.depuncture_setup() src = blocks.vector_source_b(self.src_data) - op = fec.depuncture_bb(self.puncsize, self.puncpat, + op = fec.depuncture_bb(self.puncsize, self.puncpat, self.delay, self.sym) - dst = blocks.vector_sink_b() + dst = blocks.vector_sink_b() - self.tb.connect(src, op, dst) - self.tb.run() + self.tb.connect(src, op, dst) + self.tb.run() - dst_data = list(dst.data()) - for i in xrange(len(dst_data)): + dst_data = list(dst.data()) + for i in range(len(dst_data)): dst_data[i] = int(dst_data[i]) self.assertEqual(self.expected, dst_data) @@ -141,23 +144,23 @@ class test_depuncture (gr_unittest.TestCase): self.sym = 0 src = blocks.vector_source_b(self.src_data) - op0 = fec.depuncture_bb(self.puncsize, self.puncpat0, + op0 = fec.depuncture_bb(self.puncsize, self.puncpat0, self.delay, self.sym) - op1 = fec.depuncture_bb(self.puncsize, self.puncpat1, + op1 = fec.depuncture_bb(self.puncsize, self.puncpat1, self.delay, self.sym) - dst0 = blocks.vector_sink_b() - dst1 = blocks.vector_sink_b() + dst0 = blocks.vector_sink_b() + dst1 = blocks.vector_sink_b() - self.tb.connect(src, op0, dst0) - self.tb.connect(src, op1, dst1) - self.tb.run() + self.tb.connect(src, op0, dst0) + self.tb.connect(src, op1, dst1) + self.tb.run() - dst_data0 = list(dst0.data()) - for i in xrange(len(dst_data0)): + dst_data0 = list(dst0.data()) + for i in range(len(dst_data0)): dst_data0[i] = int(dst_data0[i]) - dst_data1 = list(dst1.data()) - for i in xrange(len(dst_data1)): + dst_data1 = list(dst1.data()) + for i in range(len(dst_data1)): dst_data1[i] = int(dst_data1[i]) self.assertEqual(dst_data1, dst_data0) @@ -175,15 +178,15 @@ class test_depuncture (gr_unittest.TestCase): self.depuncture_setup() src = blocks.vector_source_b(self.src_data) - op = fec.depuncture_bb(self.puncsize, self.puncpat, + op = fec.depuncture_bb(self.puncsize, self.puncpat, self.delay) - dst = blocks.vector_sink_b() + dst = blocks.vector_sink_b() - self.tb.connect(src, op, dst) - self.tb.run() + self.tb.connect(src, op, dst) + self.tb.run() - dst_data = list(dst.data()) - for i in xrange(len(dst_data)): + dst_data = list(dst.data()) + for i in range(len(dst_data)): dst_data[i] = int(dst_data[i]) self.assertEqual(self.expected, dst_data) diff --git a/gr-fec/python/fec/qa_ecc_ccsds_27.py b/gr-fec/python/fec/qa_ecc_ccsds_27.py index 895e683345..6656c9d3ac 100755..100644 --- a/gr-fec/python/fec/qa_ecc_ccsds_27.py +++ b/gr-fec/python/fec/qa_ecc_ccsds_27.py @@ -20,9 +20,10 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest -import fec_swig as fec -import blocks_swig as blocks + +from gnuradio import gr, gr_unittest, blocks +from gnuradio import fec + class test_ccsds_27 (gr_unittest.TestCase): @@ -34,17 +35,17 @@ class test_ccsds_27 (gr_unittest.TestCase): def xtest_ccsds_27 (self): src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - expected = (0, 0, 0, 0, 1, 2, 3, 4, 5, 6) + expected = (0, 0, 0, 0, 1, 2, 3, 4, 5, 6) src = blocks.vector_source_b(src_data) - enc = fec.encode_ccsds_27_bb() - b2f = blocks.char_to_float() - add = blocks.add_const_ff(-0.5) - mul = blocks.multiply_const_ff(2.0) - dec = fec.decode_ccsds_27_fb() - dst = blocks.vector_sink_b() - self.tb.connect(src, enc, b2f, add, mul, dec, dst) - self.tb.run() - dst_data = dst.data() + enc = fec.encode_ccsds_27_bb() + b2f = blocks.char_to_float() + add = blocks.add_const_ff(-0.5) + mul = blocks.multiply_const_ff(2.0) + dec = fec.decode_ccsds_27_fb() + dst = blocks.vector_sink_b() + self.tb.connect(src, enc, b2f, add, mul, dec, dst) + self.tb.run() + dst_data = dst.data() self.assertEqual(expected, dst_data) diff --git a/gr-fec/python/fec/qa_fecapi_cc.py b/gr-fec/python/fec/qa_fecapi_cc.py index bbd500161e..053f671a0e 100644 --- a/gr-fec/python/fec/qa_fecapi_cc.py +++ b/gr-fec/python/fec/qa_fecapi_cc.py @@ -20,12 +20,14 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import + + from gnuradio import gr, gr_unittest -import fec_swig as fec +from gnuradio import fec + from _qa_helper import _qa_helper -from extended_encoder import extended_encoder -from extended_decoder import extended_decoder class test_fecapi_cc(gr_unittest.TestCase): @@ -91,8 +93,8 @@ class test_fecapi_cc(gr_unittest.TestCase): k = 7 rate = 2 polys = [109,79] - enc = map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys)), range(0,1)) - dec = map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys)), range(0,1)) + enc = list(map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys)), list(range(0,1)))) + dec = list(map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys)), list(range(0,1)))) threading = None self.test = _qa_helper(5*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -108,8 +110,8 @@ class test_fecapi_cc(gr_unittest.TestCase): k = 7 rate = 2 polys = [109,79] - enc = map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys)), range(0,1)) - dec = map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys)), range(0,1)) + enc = list(map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys)), list(range(0,1)))) + dec = list(map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys)), list(range(0,1)))) threading = 'ordinary' self.test = _qa_helper(5*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -125,8 +127,8 @@ class test_fecapi_cc(gr_unittest.TestCase): k = 7 rate = 2 polys = [109,79] - enc = map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys)), range(0,1)) - dec = map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys)), range(0,1)) + enc = list(map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys)), list(range(0,1)))) + dec = list(map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys)), list(range(0,1)))) threading = 'capillary' self.test = _qa_helper(5*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -143,8 +145,8 @@ class test_fecapi_cc(gr_unittest.TestCase): rate = 2 polys = [109,79] mode = fec.CC_TERMINATED - enc = map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys, mode=mode)), range(0,4)) - dec = map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys, mode=mode)), range(0,4)) + enc = list(map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys, mode=mode)), list(range(0,4)))) + dec = list(map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys, mode=mode)), list(range(0,4)))) threading = 'capillary' self.test = _qa_helper(4*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -161,8 +163,8 @@ class test_fecapi_cc(gr_unittest.TestCase): rate = 2 polys = [109,79] mode = fec.CC_TRUNCATED - enc = map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys, mode=mode)), range(0,4)) - dec = map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys, mode=mode)), range(0,4)) + enc = list(map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys, mode=mode)), list(range(0,4)))) + dec = list(map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys, mode=mode)), list(range(0,4)))) threading = 'capillary' self.test = _qa_helper(4*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -179,8 +181,8 @@ class test_fecapi_cc(gr_unittest.TestCase): rate = 2 polys = [109,79] mode = fec.CC_TAILBITING - enc = map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys, mode=mode)), range(0,4)) - dec = map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys, mode=mode)), range(0,4)) + enc = list(map((lambda a: fec.cc_encoder_make(frame_size*8, k, rate, polys, mode=mode)), list(range(0,4)))) + dec = list(map((lambda a: fec.cc_decoder.make(frame_size*8, k, rate, polys, mode=mode)), list(range(0,4)))) threading = 'capillary' self.test = _qa_helper(4*frame_size, enc, dec, threading) self.tb.connect(self.test) diff --git a/gr-fec/python/fec/qa_fecapi_dummy.py b/gr-fec/python/fec/qa_fecapi_dummy.py index 9471c71d74..368014d890 100644 --- a/gr-fec/python/fec/qa_fecapi_dummy.py +++ b/gr-fec/python/fec/qa_fecapi_dummy.py @@ -20,13 +20,17 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import + +import numpy as np + from gnuradio import gr, gr_unittest, blocks -import fec_swig as fec +from gnuradio import fec +from fec import extended_encoder +from fec import extended_decoder + from _qa_helper import _qa_helper -import numpy as np -from extended_encoder import extended_encoder -from extended_decoder import extended_decoder class test_fecapi_dummy(gr_unittest.TestCase): @@ -80,8 +84,8 @@ class test_fecapi_dummy(gr_unittest.TestCase): def test_parallelism1_00(self): frame_size = 30 - enc = map((lambda a: fec.dummy_encoder_make(frame_size*8)), range(0,1)) - dec = map((lambda a: fec.dummy_decoder.make(frame_size*8)), range(0,1)) + enc = list(map((lambda a: fec.dummy_encoder_make(frame_size*8)), list(range(0,1)))) + dec = list(map((lambda a: fec.dummy_decoder.make(frame_size*8)), list(range(0,1)))) threading = None self.test = _qa_helper(10*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -94,8 +98,8 @@ class test_fecapi_dummy(gr_unittest.TestCase): def test_parallelism1_01(self): frame_size = 30 - enc = map((lambda a: fec.dummy_encoder_make(frame_size*8)), range(0,1)) - dec = map((lambda a: fec.dummy_decoder.make(frame_size*8)), range(0,1)) + enc = list(map((lambda a: fec.dummy_encoder_make(frame_size*8)), list(range(0,1)))) + dec = list(map((lambda a: fec.dummy_decoder.make(frame_size*8)), list(range(0,1)))) threading = 'ordinary' self.test = _qa_helper(10*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -108,8 +112,8 @@ class test_fecapi_dummy(gr_unittest.TestCase): def test_parallelism1_02(self): frame_size = 300 - enc = map((lambda a: fec.dummy_encoder_make(frame_size*8)), range(0,1)) - dec = map((lambda a: fec.dummy_decoder.make(frame_size*8)), range(0,1)) + enc = list(map((lambda a: fec.dummy_encoder_make(frame_size*8)), list(range(0,1)))) + dec = list(map((lambda a: fec.dummy_decoder.make(frame_size*8)), list(range(0,1)))) threading = 'capillary' self.test = _qa_helper(10*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -123,8 +127,8 @@ class test_fecapi_dummy(gr_unittest.TestCase): def test_parallelism1_03(self): frame_size = 30 dims = 10 - enc = map((lambda a: fec.dummy_encoder_make(frame_size*8)), range(0,dims)) - dec = map((lambda a: fec.dummy_decoder.make(frame_size*8)), range(0,dims)) + enc = list(map((lambda a: fec.dummy_encoder_make(frame_size*8)), list(range(0,dims)))) + dec = list(map((lambda a: fec.dummy_decoder.make(frame_size*8)), list(range(0,dims)))) threading = 'ordinary' self.test = _qa_helper(dims*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -138,8 +142,8 @@ class test_fecapi_dummy(gr_unittest.TestCase): def test_parallelism1_04(self): frame_size = 30 dims = 16 - enc = map((lambda a: fec.dummy_encoder_make(frame_size*8)), range(0,dims)) - dec = map((lambda a: fec.dummy_decoder.make(frame_size*8)), range(0,dims)) + enc = list(map((lambda a: fec.dummy_encoder_make(frame_size*8)), list(range(0,dims)))) + dec = list(map((lambda a: fec.dummy_decoder.make(frame_size*8)), list(range(0,dims)))) threading = 'capillary' self.test = _qa_helper(dims*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -153,7 +157,7 @@ class test_fecapi_dummy(gr_unittest.TestCase): def test_parallelism1_05(self): frame_size = 30 dims = 5 - enc = map((lambda a: fec.dummy_encoder_make(frame_size*8)), range(0,dims)) + enc = list(map((lambda a: fec.dummy_encoder_make(frame_size*8)), list(range(0,dims)))) #dec = map((lambda a: fec.dummy_decoder.make(frame_size*8)), range(0,dims)) threading = 'capillary' @@ -163,7 +167,7 @@ class test_fecapi_dummy(gr_unittest.TestCase): frame_size = 30 dims = 5 #enc = map((lambda a: fec.dummy_encoder_make(frame_size*8)), range(0,dims)) - dec = map((lambda a: fec.dummy_decoder.make(frame_size*8)), range(0,dims)) + dec = list(map((lambda a: fec.dummy_decoder.make(frame_size*8)), list(range(0,dims)))) threading = 'capillary' self.assertRaises(AttributeError, lambda: extended_decoder(dec, threading=threading, puncpat="11")) @@ -172,7 +176,7 @@ class test_fecapi_dummy(gr_unittest.TestCase): frame_size = 30 dims1 = 16 dims2 = 16 - enc = map((lambda b: map((lambda a: fec.dummy_encoder_make(frame_size*8)), range(0,dims1))), range(0,dims2)) + enc = list(map((lambda b: list(map((lambda a: fec.dummy_encoder_make(frame_size*8)), list(range(0,dims1))))), list(range(0,dims2)))) #dec = map((lambda b: map((lambda a: fec.dummy_decoder_make(frame_size*8)), range(0,dims1))), range(0,dims2)) threading = 'capillary' @@ -182,7 +186,7 @@ class test_fecapi_dummy(gr_unittest.TestCase): frame_size = 30 dims1 = 16 dims2 = 16 - dec = map((lambda b: map((lambda a: fec.dummy_decoder_make(frame_size*8)), range(0,dims1))), range(0,dims2)) + dec = list(map((lambda b: list(map((lambda a: fec.dummy_decoder_make(frame_size*8)), list(range(0,dims1))))), list(range(0,dims2)))) threading = 'capillary' self.assertRaises(AttributeError, lambda: extended_decoder(dec, threading=threading, puncpat="11")) @@ -193,6 +197,7 @@ class test_fecapi_dummy(gr_unittest.TestCase): frame_size = 32 data = np.random.randint(0, 2, n_frames * frame_size) + data.dtype = np.uint8 packed_data = np.packbits(data) tb = gr.top_block() diff --git a/gr-fec/python/fec/qa_fecapi_ldpc.py b/gr-fec/python/fec/qa_fecapi_ldpc.py index b45ce0ee19..758a26469e 100644 --- a/gr-fec/python/fec/qa_fecapi_ldpc.py +++ b/gr-fec/python/fec/qa_fecapi_ldpc.py @@ -20,15 +20,19 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest -import fec_swig as fec -from _qa_helper import _qa_helper +from __future__ import absolute_import -from extended_encoder import extended_encoder -from extended_decoder import extended_decoder import os +from gnuradio import gr, gr_unittest +from gnuradio import fec +from fec import extended_encoder +from fec import extended_decoder + +from _qa_helper import _qa_helper + + # Get location of the alist files. If run in 'ctest' or 'make test', # the shell script sets srcdir. Otherwise, we assume we're running # from the current directory and know where to go. @@ -131,8 +135,8 @@ class test_fecapi_ldpc(gr_unittest.TestCase): gap = 4 LDPC_matrix_object = fec.ldpc_H_matrix(filename, gap) k = LDPC_matrix_object.k() - enc = map((lambda a: fec.ldpc_par_mtrx_encoder.make_H(LDPC_matrix_object)), range(0,1)) - dec = map((lambda a: fec.ldpc_bit_flip_decoder.make(LDPC_matrix_object.get_base_sptr())), range(0,1)) + enc = list(map((lambda a: fec.ldpc_par_mtrx_encoder.make_H(LDPC_matrix_object)), list(range(0,1)))) + dec = list(map((lambda a: fec.ldpc_bit_flip_decoder.make(LDPC_matrix_object.get_base_sptr())), list(range(0,1)))) threading = None self.test = _qa_helper(10*k, enc, dec, threading) self.tb.connect(self.test) @@ -148,8 +152,8 @@ class test_fecapi_ldpc(gr_unittest.TestCase): gap = 4 LDPC_matrix_object = fec.ldpc_H_matrix(filename, gap) k = LDPC_matrix_object.k() - enc = map((lambda a: fec.ldpc_par_mtrx_encoder.make_H(LDPC_matrix_object)), range(0,1)) - dec = map((lambda a: fec.ldpc_bit_flip_decoder.make(LDPC_matrix_object.get_base_sptr())), range(0,1)) + enc = list(map((lambda a: fec.ldpc_par_mtrx_encoder.make_H(LDPC_matrix_object)), list(range(0,1)))) + dec = list(map((lambda a: fec.ldpc_bit_flip_decoder.make(LDPC_matrix_object.get_base_sptr())), list(range(0,1)))) threading = 'ordinary' self.test = _qa_helper(10*k, enc, dec, threading) self.tb.connect(self.test) @@ -165,8 +169,8 @@ class test_fecapi_ldpc(gr_unittest.TestCase): gap = 4 LDPC_matrix_object = fec.ldpc_H_matrix(filename, gap) k = LDPC_matrix_object.k() - enc = map((lambda a: fec.ldpc_par_mtrx_encoder.make_H(LDPC_matrix_object)), range(0,1)) - dec = map((lambda a: fec.ldpc_bit_flip_decoder.make(LDPC_matrix_object.get_base_sptr())), range(0,1)) + enc = list(map((lambda a: fec.ldpc_par_mtrx_encoder.make_H(LDPC_matrix_object)), list(range(0,1)))) + dec = list(map((lambda a: fec.ldpc_bit_flip_decoder.make(LDPC_matrix_object.get_base_sptr())), list(range(0,1)))) threading = 'capillary' self.test = _qa_helper(10*k, enc, dec, threading) self.tb.connect(self.test) @@ -255,7 +259,7 @@ class test_fecapi_ldpc(gr_unittest.TestCase): dims = 5 LDPC_matrix_object = fec.ldpc_H_matrix(filename, gap) k = LDPC_matrix_object.k() - dec = map((lambda a: fec.ldpc_bit_flip_decoder.make(LDPC_matrix_object.get_base_sptr())), range(0,dims)) + dec = list(map((lambda a: fec.ldpc_bit_flip_decoder.make(LDPC_matrix_object.get_base_sptr())), list(range(0,dims)))) threading = 'capillary' self.assertRaises(AttributeError, lambda: extended_decoder(dec, threading=threading, puncpat="11")) @@ -267,8 +271,8 @@ class test_fecapi_ldpc(gr_unittest.TestCase): k = LDPC_matrix_object.k() dims1 = 16 dims2 = 16 - enc = map((lambda b: map((lambda a: fec.ldpc_par_mtrx_encoder.make_H(LDPC_matrix_object)), - range(0,dims1))), range(0,dims2)) + enc = list(map((lambda b: list(map((lambda a: fec.ldpc_par_mtrx_encoder.make_H(LDPC_matrix_object)), + list(range(0,dims1))))), list(range(0,dims2)))) threading = 'capillary' self.assertRaises(AttributeError, lambda: extended_encoder(enc, threading=threading, puncpat="11")) @@ -281,8 +285,8 @@ class test_fecapi_ldpc(gr_unittest.TestCase): k = LDPC_matrix_object.k() dims1 = 16 dims2 = 16 - enc = map((lambda b: map((lambda a: fec.ldpc_par_mtrx_encoder.make_H(LDPC_matrix_object)), - range(0,dims1))), range(0,dims2)) + enc = list(map((lambda b: list(map((lambda a: fec.ldpc_par_mtrx_encoder.make_H(LDPC_matrix_object)), + list(range(0,dims1))))), list(range(0,dims2)))) threading = 'capillary' self.assertRaises(AttributeError, lambda: extended_encoder(enc, threading=threading, puncpat="11")) @@ -295,8 +299,8 @@ class test_fecapi_ldpc(gr_unittest.TestCase): k = LDPC_matrix_object.k() dims1 = 16 dims2 = 16 - dec = map((lambda b: map((lambda a: fec.ldpc_bit_flip_decoder.make(LDPC_matrix_object.get_base_sptr())), - range(0,dims1))), range(0,dims2)) + dec = list(map((lambda b: list(map((lambda a: fec.ldpc_bit_flip_decoder.make(LDPC_matrix_object.get_base_sptr())), + list(range(0,dims1))))), list(range(0,dims2)))) threading = 'capillary' self.assertRaises(AttributeError, lambda: extended_decoder(dec, threading=threading, puncpat="11")) diff --git a/gr-fec/python/fec/qa_fecapi_repetition.py b/gr-fec/python/fec/qa_fecapi_repetition.py index 7998d61bd1..650aab7010 100644 --- a/gr-fec/python/fec/qa_fecapi_repetition.py +++ b/gr-fec/python/fec/qa_fecapi_repetition.py @@ -20,12 +20,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import absolute_import + + + from gnuradio import gr, gr_unittest -import fec_swig as fec +from gnuradio import fec + from _qa_helper import _qa_helper -from extended_encoder import extended_encoder -from extended_decoder import extended_decoder class test_fecapi_repetition(gr_unittest.TestCase): @@ -83,8 +86,8 @@ class test_fecapi_repetition(gr_unittest.TestCase): def test_parallelism1_00(self): frame_size = 30 rep = 3 - enc = map((lambda a: fec.repetition_encoder_make(frame_size*8, rep)), range(0,1)) - dec = map((lambda a: fec.repetition_decoder.make(frame_size*8, rep)), range(0,1)) + enc = list(map((lambda a: fec.repetition_encoder_make(frame_size*8, rep)), list(range(0,1)))) + dec = list(map((lambda a: fec.repetition_decoder.make(frame_size*8, rep)), list(range(0,1)))) threading = None self.test = _qa_helper(10*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -98,8 +101,8 @@ class test_fecapi_repetition(gr_unittest.TestCase): def test_parallelism1_01(self): frame_size = 30 rep = 3 - enc = map((lambda a: fec.repetition_encoder_make(frame_size*8, rep)), range(0,1)) - dec = map((lambda a: fec.repetition_decoder.make(frame_size*8, rep)), range(0,1)) + enc = list(map((lambda a: fec.repetition_encoder_make(frame_size*8, rep)), list(range(0,1)))) + dec = list(map((lambda a: fec.repetition_decoder.make(frame_size*8, rep)), list(range(0,1)))) threading = 'ordinary' self.test = _qa_helper(10*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -113,8 +116,8 @@ class test_fecapi_repetition(gr_unittest.TestCase): def test_parallelism1_02(self): frame_size = 300 rep = 3 - enc = map((lambda a: fec.repetition_encoder_make(frame_size*8, rep)), range(0,1)) - dec = map((lambda a: fec.repetition_decoder.make(frame_size*8, rep)), range(0,1)) + enc = list(map((lambda a: fec.repetition_encoder_make(frame_size*8, rep)), list(range(0,1)))) + dec = list(map((lambda a: fec.repetition_decoder.make(frame_size*8, rep)), list(range(0,1)))) threading = 'capillary' self.test = _qa_helper(10*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -129,8 +132,8 @@ class test_fecapi_repetition(gr_unittest.TestCase): frame_size = 30 rep = 3 dims = 10 - enc = map((lambda a: fec.repetition_encoder_make(frame_size*8, rep)), range(0,dims)) - dec = map((lambda a: fec.repetition_decoder.make(frame_size*8, rep)), range(0,dims)) + enc = list(map((lambda a: fec.repetition_encoder_make(frame_size*8, rep)), list(range(0,dims)))) + dec = list(map((lambda a: fec.repetition_decoder.make(frame_size*8, rep)), list(range(0,dims)))) threading = 'ordinary' self.test = _qa_helper(dims*frame_size, enc, dec, threading) self.tb.connect(self.test) @@ -145,8 +148,8 @@ class test_fecapi_repetition(gr_unittest.TestCase): frame_size = 30 rep = 3 dims = 16 - enc = map((lambda a: fec.repetition_encoder_make(frame_size*8, rep)), range(0,dims)) - dec = map((lambda a: fec.repetition_decoder.make(frame_size*8, rep)), range(0,dims)) + enc = list(map((lambda a: fec.repetition_encoder_make(frame_size*8, rep)), list(range(0,dims)))) + dec = list(map((lambda a: fec.repetition_decoder.make(frame_size*8, rep)), list(range(0,dims)))) threading = 'capillary' self.test = _qa_helper(dims*frame_size, enc, dec, threading) self.tb.connect(self.test) diff --git a/gr-fec/python/fec/qa_polar_decoder_sc.py b/gr-fec/python/fec/qa_polar_decoder_sc.py index 6dd1e8e481..c8d956328e 100644 --- a/gr-fec/python/fec/qa_polar_decoder_sc.py +++ b/gr-fec/python/fec/qa_polar_decoder_sc.py @@ -20,13 +20,18 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, blocks -import fec_swig as fec +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division + import numpy as np -from extended_decoder import extended_decoder -from polar.encoder import PolarEncoder -import polar.channel_construction as cc + +from gnuradio import gr, gr_unittest, blocks +from gnuradio import fec +from fec import extended_decoder +from fec.polar.encoder import PolarEncoder +from fec.polar import channel_construction as cc # import os # print('PID:', os.getpid()) diff --git a/gr-fec/python/fec/qa_polar_decoder_sc_list.py b/gr-fec/python/fec/qa_polar_decoder_sc_list.py index 36819b396f..13a8e9bc32 100644 --- a/gr-fec/python/fec/qa_polar_decoder_sc_list.py +++ b/gr-fec/python/fec/qa_polar_decoder_sc_list.py @@ -20,13 +20,17 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, blocks -import fec_swig as fec +from __future__ import print_function +from __future__ import absolute_import +from __future__ import division + + import numpy as np -from extended_decoder import extended_decoder -from polar.encoder import PolarEncoder -import polar.channel_construction as cc +from gnuradio import gr, gr_unittest, blocks, fec +from gnuradio.fec import extended_decoder +from gnuradio.fec.polar.encoder import PolarEncoder +from gnuradio.fec.polar import channel_construction as cc # import os # print('PID:', os.getpid()) @@ -56,7 +60,7 @@ class test_polar_decoder_sc_list(gr_unittest.TestCase): self.assertFalse(polar_decoder.set_frame_size(10)) def test_002_one_vector(self): - print "test_002_one_vector" + print("test_002_one_vector") expo = 6 block_size = 2 ** expo num_info_bits = 2 ** (expo - 1) @@ -89,7 +93,7 @@ class test_polar_decoder_sc_list(gr_unittest.TestCase): self.assertTupleEqual(tuple(res), tuple(bits)) def test_003_stream(self): - print "test_003_stream" + print("test_003_stream") nframes = 5 expo = 8 block_size = 2 ** expo diff --git a/gr-fec/python/fec/qa_polar_decoder_sc_systematic.py b/gr-fec/python/fec/qa_polar_decoder_sc_systematic.py index fb2381e069..525ebbc76c 100644 --- a/gr-fec/python/fec/qa_polar_decoder_sc_systematic.py +++ b/gr-fec/python/fec/qa_polar_decoder_sc_systematic.py @@ -20,13 +20,16 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, blocks -import fec_swig as fec +from __future__ import absolute_import +from __future__ import division import numpy as np -from extended_decoder import extended_decoder -from polar.encoder import PolarEncoder -import polar.channel_construction as cc + +from gnuradio import gr, gr_unittest, blocks, fec + +from gnuradio.fec.extended_decoder import extended_decoder +from gnuradio.fec.polar.encoder import PolarEncoder +from gnuradio.fec.polar import channel_construction as cc # import os # print('PID:', os.getpid()) @@ -113,5 +116,3 @@ class test_polar_decoder_sc_systematic(gr_unittest.TestCase): if __name__ == '__main__': gr_unittest.run(test_polar_decoder_sc_systematic) - - diff --git a/gr-fec/python/fec/qa_polar_encoder.py b/gr-fec/python/fec/qa_polar_encoder.py index d7362b6dc4..ba003d9070 100644 --- a/gr-fec/python/fec/qa_polar_encoder.py +++ b/gr-fec/python/fec/qa_polar_encoder.py @@ -20,13 +20,16 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, blocks -import fec_swig as fec +from __future__ import absolute_import +from __future__ import division + + import numpy as np -from extended_encoder import extended_encoder -from polar.encoder import PolarEncoder -import polar.channel_construction as cc +from gnuradio import gr, gr_unittest, blocks, fec +from gnuradio.fec.extended_encoder import extended_encoder +from gnuradio.fec.polar.encoder import PolarEncoder +from gnuradio.fec.polar import channel_construction as cc # import os # print('PID:', os.getpid()) diff --git a/gr-fec/python/fec/qa_polar_encoder_systematic.py b/gr-fec/python/fec/qa_polar_encoder_systematic.py index 015a31b3cb..18b918ddab 100644 --- a/gr-fec/python/fec/qa_polar_encoder_systematic.py +++ b/gr-fec/python/fec/qa_polar_encoder_systematic.py @@ -20,13 +20,15 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest, blocks -import fec_swig as fec +from __future__ import absolute_import +from __future__ import division + import numpy as np -from extended_encoder import extended_encoder -from polar.encoder import PolarEncoder -import polar.channel_construction as cc +from gnuradio import gr, gr_unittest, blocks, fec +from gnuradio.fec.extended_encoder import extended_encoder +from gnuradio.fec.polar.encoder import PolarEncoder +from gnuradio.fec.polar import channel_construction as cc # import os # print('PID:', os.getpid()) @@ -103,5 +105,3 @@ class test_polar_encoder_systematic(gr_unittest.TestCase): if __name__ == '__main__': gr_unittest.run(test_polar_encoder_systematic) - - diff --git a/gr-fec/python/fec/qa_puncture.py b/gr-fec/python/fec/qa_puncture.py index fdd15c9a08..f4e0ba8556 100644 --- a/gr-fec/python/fec/qa_puncture.py +++ b/gr-fec/python/fec/qa_puncture.py @@ -20,11 +20,13 @@ # Boston, MA 02110-1301, USA. # -from gnuradio import gr, gr_unittest -import fec_swig as fec -import blocks_swig as blocks +from __future__ import division + from collections import deque +from gnuradio import gr, gr_unittest, blocks, fec + + class test_puncture (gr_unittest.TestCase): def puncture_setup(self): @@ -36,13 +38,13 @@ class test_puncture (gr_unittest.TestCase): _puncpat = list(d) self.expected = [] - for n in range(len(self.src_data)/self.puncsize): + for n in range(len(self.src_data) // self.puncsize): for i in range(self.puncsize): if _puncpat[i] == 1: self.expected.append(self.src_data[n*self.puncsize+i]); def setUp(self): - self.src_data = 10000*range(64) + self.src_data = 10000*list(range(64)) self.tb = gr.top_block() def tearDown(self): @@ -58,14 +60,14 @@ class test_puncture (gr_unittest.TestCase): self.puncture_setup() src = blocks.vector_source_b(self.src_data) - op = fec.puncture_bb(self.puncsize, self.puncpat, self.delay) - dst = blocks.vector_sink_b() + op = fec.puncture_bb(self.puncsize, self.puncpat, self.delay) + dst = blocks.vector_sink_b() - self.tb.connect(src, op, dst) - self.tb.run() + self.tb.connect(src, op, dst) + self.tb.run() - dst_data = list(dst.data()) - for i in xrange(len(dst_data)): + dst_data = list(dst.data()) + for i in range(len(dst_data)): dst_data[i] = int(dst_data[i]) self.assertEqual(self.expected, dst_data) @@ -78,19 +80,19 @@ class test_puncture (gr_unittest.TestCase): self.puncpat = 0xEE self.delay = 1 - self.src_data = range(16) + self.src_data = list(range(16)) self.puncture_setup() src = blocks.vector_source_b(self.src_data) - op = fec.puncture_bb(self.puncsize, self.puncpat, self.delay) - dst = blocks.vector_sink_b() + op = fec.puncture_bb(self.puncsize, self.puncpat, self.delay) + dst = blocks.vector_sink_b() - self.tb.connect(src, op, dst) - self.tb.run() + self.tb.connect(src, op, dst) + self.tb.run() - dst_data = list(dst.data()) - for i in xrange(len(dst_data)): + dst_data = list(dst.data()) + for i in range(len(dst_data)): dst_data[i] = int(dst_data[i]) self.assertEqual(self.expected, dst_data) @@ -107,14 +109,14 @@ class test_puncture (gr_unittest.TestCase): self.puncture_setup() src = blocks.vector_source_b(self.src_data) - op = fec.puncture_bb(self.puncsize, self.puncpat, self.delay) - dst = blocks.vector_sink_b() + op = fec.puncture_bb(self.puncsize, self.puncpat, self.delay) + dst = blocks.vector_sink_b() - self.tb.connect(src, op, dst) - self.tb.run() + self.tb.connect(src, op, dst) + self.tb.run() - dst_data = list(dst.data()) - for i in xrange(len(dst_data)): + dst_data = list(dst.data()) + for i in range(len(dst_data)): dst_data[i] = int(dst_data[i]) self.assertEqual(self.expected, dst_data) @@ -131,21 +133,21 @@ class test_puncture (gr_unittest.TestCase): self.delay = 1 src = blocks.vector_source_b(self.src_data) - op0 = fec.puncture_bb(self.puncsize, self.puncpat0, self.delay) - op1 = fec.puncture_bb(self.puncsize, self.puncpat1, self.delay) - dst0 = blocks.vector_sink_b() - dst1 = blocks.vector_sink_b() + op0 = fec.puncture_bb(self.puncsize, self.puncpat0, self.delay) + op1 = fec.puncture_bb(self.puncsize, self.puncpat1, self.delay) + dst0 = blocks.vector_sink_b() + dst1 = blocks.vector_sink_b() - self.tb.connect(src, op0, dst0) - self.tb.connect(src, op1, dst1) - self.tb.run() + self.tb.connect(src, op0, dst0) + self.tb.connect(src, op1, dst1) + self.tb.run() - dst_data0 = list(dst0.data()) - for i in xrange(len(dst_data0)): + dst_data0 = list(dst0.data()) + for i in range(len(dst_data0)): dst_data0[i] = int(dst_data0[i]) - dst_data1 = list(dst1.data()) - for i in xrange(len(dst_data1)): + dst_data1 = list(dst1.data()) + for i in range(len(dst_data1)): dst_data1[i] = int(dst_data1[i]) self.assertEqual(dst_data1, dst_data0) @@ -162,13 +164,13 @@ class test_puncture (gr_unittest.TestCase): self.puncture_setup() src = blocks.vector_source_f(self.src_data) - op = fec.puncture_ff(self.puncsize, self.puncpat, self.delay) - dst = blocks.vector_sink_f() + op = fec.puncture_ff(self.puncsize, self.puncpat, self.delay) + dst = blocks.vector_sink_f() - self.tb.connect(src, op, dst) - self.tb.run() + self.tb.connect(src, op, dst) + self.tb.run() - dst_data = list(dst.data()) + dst_data = list(dst.data()) self.assertEqual(self.expected, dst_data) @@ -179,18 +181,18 @@ class test_puncture (gr_unittest.TestCase): self.puncpat = 0xEE self.delay = 1 - self.src_data = range(16) + self.src_data = list(range(16)) self.puncture_setup() src = blocks.vector_source_f(self.src_data) - op = fec.puncture_ff(self.puncsize, self.puncpat, self.delay) - dst = blocks.vector_sink_f() + op = fec.puncture_ff(self.puncsize, self.puncpat, self.delay) + dst = blocks.vector_sink_f() - self.tb.connect(src, op, dst) - self.tb.run() + self.tb.connect(src, op, dst) + self.tb.run() - dst_data = list(dst.data()) + dst_data = list(dst.data()) self.assertEqual(self.expected, dst_data) @@ -205,13 +207,13 @@ class test_puncture (gr_unittest.TestCase): self.puncture_setup() src = blocks.vector_source_f(self.src_data) - op = fec.puncture_ff(self.puncsize, self.puncpat, self.delay) - dst = blocks.vector_sink_f() + op = fec.puncture_ff(self.puncsize, self.puncpat, self.delay) + dst = blocks.vector_sink_f() - self.tb.connect(src, op, dst) - self.tb.run() + self.tb.connect(src, op, dst) + self.tb.run() - dst_data = list(dst.data()) + dst_data = list(dst.data()) self.assertEqual(self.expected, dst_data) def test_f_003(self): @@ -226,17 +228,17 @@ class test_puncture (gr_unittest.TestCase): self.delay = 1 src = blocks.vector_source_f(self.src_data) - op0 = fec.puncture_ff(self.puncsize, self.puncpat0, self.delay) - op1 = fec.puncture_ff(self.puncsize, self.puncpat1, self.delay) - dst0 = blocks.vector_sink_f() - dst1 = blocks.vector_sink_f() + op0 = fec.puncture_ff(self.puncsize, self.puncpat0, self.delay) + op1 = fec.puncture_ff(self.puncsize, self.puncpat1, self.delay) + dst0 = blocks.vector_sink_f() + dst1 = blocks.vector_sink_f() - self.tb.connect(src, op0, dst0) - self.tb.connect(src, op1, dst1) - self.tb.run() + self.tb.connect(src, op0, dst0) + self.tb.connect(src, op1, dst1) + self.tb.run() - dst_data0 = list(dst0.data()) - dst_data1 = list(dst1.data()) + dst_data0 = list(dst0.data()) + dst_data1 = list(dst1.data()) self.assertEqual(dst_data1, dst_data0) diff --git a/gr-fec/python/fec/threaded_decoder.py b/gr-fec/python/fec/threaded_decoder.py index 115ad7b5d3..adf4abfe22 100644 --- a/gr-fec/python/fec/threaded_decoder.py +++ b/gr-fec/python/fec/threaded_decoder.py @@ -20,8 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr, blocks -import fec_swig as fec +from . import fec_swig as fec + class threaded_decoder(gr.hier_block2): def __init__(self, decoder_list_0, input_size, output_size): diff --git a/gr-fec/python/fec/threaded_encoder.py b/gr-fec/python/fec/threaded_encoder.py index 391baa5442..254b4d39d8 100644 --- a/gr-fec/python/fec/threaded_encoder.py +++ b/gr-fec/python/fec/threaded_encoder.py @@ -20,8 +20,11 @@ # Boston, MA 02110-1301, USA. # +from __future__ import unicode_literals from gnuradio import gr, blocks -import fec_swig as fec + +from . import fec_swig as fec + class threaded_encoder(gr.hier_block2): def __init__(self, encoder_list_0, input_size, output_size): diff --git a/gr-fft/python/fft/CMakeLists.txt b/gr-fft/python/fft/CMakeLists.txt index 016c76d27d..f08aebc11d 100644 --- a/gr-fft/python/fft/CMakeLists.txt +++ b/gr-fft/python/fft/CMakeLists.txt @@ -40,6 +40,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-fft/python/fft/__init__.py b/gr-fft/python/fft/__init__.py index 1864353ed1..2e110f5371 100644 --- a/gr-fft/python/fft/__init__.py +++ b/gr-fft/python/fft/__init__.py @@ -22,11 +22,15 @@ ''' Fourier-transform blocks and related functions. ''' + +from __future__ import absolute_import +from __future__ import unicode_literals + import os try: - from fft_swig import * + from .fft_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from fft_swig import * + from .fft_swig import * diff --git a/gr-fft/python/fft/logpwrfft.py b/gr-fft/python/fft/logpwrfft.py index 356ec1217b..ee424f2f84 100644 --- a/gr-fft/python/fft/logpwrfft.py +++ b/gr-fft/python/fft/logpwrfft.py @@ -1,3 +1,5 @@ +from __future__ import division +from __future__ import unicode_literals # # Copyright 2008 Free Software Foundation, Inc. # @@ -23,8 +25,8 @@ from gnuradio import gr from gnuradio import blocks import sys, math -import fft_swig as fft -from fft_swig import window +from . import fft_swig as fft +from .fft_swig import window try: from gnuradio import filter @@ -63,14 +65,14 @@ class _logpwrfft_base(gr.hier_block2): if win is None: win = window.blackmanharris fft_window = win(fft_size) fft = self._fft_block[0](fft_size, True, fft_window) - window_power = sum(map(lambda x: x*x, fft_window)) + window_power = sum([x*x for x in fft_window]) c2magsq = blocks.complex_to_mag_squared(fft_size) self._avg = filter.single_pole_iir_filter_ff(1.0, fft_size) self._log = blocks.nlog10_ff(10, fft_size, -20*math.log10(fft_size) # Adjust for number of bins - -10*math.log10(window_power/fft_size) # Adjust for windowing loss - -20*math.log10(ref_scale/2)) # Adjust for reference scale + -10*math.log10(window_power / fft_size) # Adjust for windowing loss + -20*math.log10(ref_scale / 2)) # Adjust for reference scale self.connect(self, self._sd, fft, c2magsq, self._avg, self._log, self) self._average = average @@ -173,4 +175,3 @@ class logpwrfft_c(_logpwrfft_base): _name = "logpwrfft_c" _item_size = gr.sizeof_gr_complex _fft_block = (fft.fft_vcc, ) - diff --git a/gr-fft/python/fft/qa_fft.py b/gr-fft/python/fft/qa_fft.py index db3ca7778d..b1c44f2809 100755..100644 --- a/gr-fft/python/fft/qa_fft.py +++ b/gr-fft/python/fft/qa_fft.py @@ -19,6 +19,8 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, fft, blocks # Note: Octave code to verify these results: diff --git a/gr-fft/python/fft/qa_goertzel.py b/gr-fft/python/fft/qa_goertzel.py index c2c5c565e7..ebd272cb22 100755..100644 --- a/gr-fft/python/fft/qa_goertzel.py +++ b/gr-fft/python/fft/qa_goertzel.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from math import pi, cos from gnuradio import gr, gr_unittest, fft, blocks @@ -36,30 +38,30 @@ class test_goertzel(gr_unittest.TestCase): return [cos(2*pi*x*freq/rate) for x in range(rate)] def transform(self, src_data, rate, freq): - src = blocks.vector_source_f(src_data, False) + src = blocks.vector_source_f(src_data, False) dft = fft.goertzel_fc(rate, rate, freq) - dst = blocks.vector_sink_c() - self.tb.connect(src, dft, dst) - self.tb.run() - return dst.data() + dst = blocks.vector_sink_c() + self.tb.connect(src, dft, dst) + self.tb.run() + return dst.data() def test_001(self): # Measure single tone magnitude - rate = 8000 - freq = 100 - bin = freq - src_data = self.make_tone_data(rate, freq) - expected_result = 0.5 - actual_result = abs(self.transform(src_data, rate, bin)[0]) - self.assertAlmostEqual(expected_result, actual_result, places=4) + rate = 8000 + freq = 100 + bin = freq + src_data = self.make_tone_data(rate, freq) + expected_result = 0.5 + actual_result = abs(self.transform(src_data, rate, bin)[0]) + self.assertAlmostEqual(expected_result, actual_result, places=4) def test_002(self): # Measure off frequency magnitude - rate = 8000 - freq = 100 - bin = freq/2 - src_data = self.make_tone_data(rate, freq) - expected_result = 0.0 - actual_result = abs(self.transform(src_data, rate, bin)[0]) - self.assertAlmostEqual(expected_result, actual_result, places=4) + rate = 8000 + freq = 100 + bin = freq / 2 + src_data = self.make_tone_data(rate, freq) + expected_result = 0.0 + actual_result = abs(self.transform(src_data, rate, bin)[0]) + self.assertAlmostEqual(expected_result, actual_result, places=4) if __name__ == '__main__': gr_unittest.run(test_goertzel, "test_goertzel.xml") diff --git a/gr-filter/examples/benchmark_filters.py b/gr-filter/examples/benchmark_filters.py index 4da6b9f5ad..0c7aebcf64 100755..100644 --- a/gr-filter/examples/benchmark_filters.py +++ b/gr-filter/examples/benchmark_filters.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals import time import random from argparse import ArgumentParser @@ -48,8 +50,8 @@ def benchmark(name, creator, dec, ntaps, total_test_size, block_size): tb.run() stop = time.time() delta = stop - start - print "%16s: taps: %4d input: %4g, time: %6.3f taps/sec: %10.4g" % ( - name, ntaps, total_test_size, delta, ntaps*total_test_size/delta) + print("%16s: taps: %4d input: %4g, time: %6.3f taps/sec: %10.4g" % ( + name, ntaps, total_test_size, delta, ntaps*total_test_size/delta)) def main(): parser = ArgumentParser() diff --git a/gr-filter/examples/channelize.py b/gr-filter/examples/channelize.py index e70817e873..51f0bad20b 100755..100644 --- a/gr-filter/examples/channelize.py +++ b/gr-filter/examples/channelize.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from gnuradio import filter @@ -60,10 +63,10 @@ class pfb_top_block(gr.top_block): window=filter.firdes.WIN_BLACKMAN_hARRIS) # Calculate the number of taps per channel for our own information - tpc = scipy.ceil(float(len(self._taps)) / float(self._M)) - print "Number of taps: ", len(self._taps) - print "Number of channels: ", self._M - print "Taps per channel: ", tpc + tpc = scipy.ceil(float(len(self._taps)) / float(self._M)) + print("Number of taps: ", len(self._taps)) + print("Number of channels: ", self._M) + print("Taps per channel: ", tpc) # Create a set of signals at different frequencies # freqs lists the frequencies of the signals that get stored @@ -71,8 +74,8 @@ class pfb_top_block(gr.top_block): self.signals = list() self.add = blocks.add_cc() freqs = [-70, -50, -30, -10, 10, 20, 40, 60, 80] - for i in xrange(len(freqs)): - f = freqs[i] + (M/2-M+i+1)*self._fs + for i in range(len(freqs)): + f = freqs[i] + (M / 2-M+i+1)*self._fs self.signals.append(analog.sig_source_c(self._ifs, analog.GR_SIN_WAVE, f, 1)) self.connect(self.signals[i], (self.add,i)) @@ -93,7 +96,7 @@ class pfb_top_block(gr.top_block): # Create a vector sink for each of M output channels of the filter and connect it self.snks = list() - for i in xrange(self._M): + for i in range(self._M): self.snks.append(blocks.vector_sink_c()) self.connect((self.pfb, i), self.snks[i]) @@ -105,7 +108,7 @@ def main(): tb.run() tend = time.time() - print "Run time: %f" % (tend - tstart) + print("Run time: %f" % (tend - tstart)) if 1: fig_in = pylab.figure(1, figsize=(16,9), facecolor="w") @@ -123,11 +126,11 @@ def main(): d = tb.snk_i.data()[Ns:Ne] spin_f = fig_in.add_subplot(2, 1, 1) - X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs, window = lambda d: d*winfunc(fftlen), scale_by_freq=True) X_in = 10.0*scipy.log10(abs(X)) - f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + f_in = scipy.arange(-fs / 2.0, fs / 2.0, fs / float(X_in.size)) pin_f = spin_f.plot(f_in, X_in, "b") spin_f.set_xlim([min(f_in), max(f_in)+1]) spin_f.set_ylim([-200.0, 50.0]) @@ -137,7 +140,7 @@ def main(): spin_f.set_ylabel("Power (dBW)") - Ts = 1.0/fs + Ts = 1.0 / fs Tmax = len(d)*Ts t_in = scipy.arange(0, Tmax, Ts) @@ -157,20 +160,20 @@ def main(): # Plot each of the channels outputs. Frequencies on Figure 2 and # time signals on Figure 3 fs_o = tb._fs - Ts_o = 1.0/fs_o + Ts_o = 1.0 / fs_o Tmax_o = len(d)*Ts_o - for i in xrange(len(tb.snks)): + for i in range(len(tb.snks)): # remove issues with the transients at the beginning # also remove some corruption at the end of the stream # this is a bug, probably due to the corner cases d = tb.snks[i].data()[Ns:Ne] sp1_f = fig1.add_subplot(Nrows, Ncols, 1+i) - X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs_o, window = lambda d: d*winfunc(fftlen), scale_by_freq=True) X_o = 10.0*scipy.log10(abs(X)) - f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size)) + f_o = scipy.arange(-fs_o / 2.0, fs_o / 2.0, fs_o / float(X_o.size)) p2_f = sp1_f.plot(f_o, X_o, "b") sp1_f.set_xlim([min(f_o), max(f_o)+1]) sp1_f.set_ylim([-200.0, 50.0]) diff --git a/gr-filter/examples/chirp_channelize.py b/gr-filter/examples/chirp_channelize.py index aedd5c4892..471416b6a5 100755..100644 --- a/gr-filter/examples/chirp_channelize.py +++ b/gr-filter/examples/chirp_channelize.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from gnuradio import filter @@ -59,17 +62,17 @@ class pfb_top_block(gr.top_block): window=filter.firdes.WIN_BLACKMAN_hARRIS) # Calculate the number of taps per channel for our own information - tpc = scipy.ceil(float(len(self._taps)) / float(self._M)) - print "Number of taps: ", len(self._taps) - print "Number of channels: ", self._M - print "Taps per channel: ", tpc + tpc = scipy.ceil(float(len(self._taps)) / float(self._M)) + print("Number of taps: ", len(self._taps)) + print("Number of channels: ", self._M) + print("Taps per channel: ", tpc) repeated = True if(repeated): self.vco_input = analog.sig_source_f(self._fs, analog.GR_SIN_WAVE, 0.25, 110) else: amp = 100 - data = scipy.arange(0, amp, amp/float(self._N)) + data = scipy.arange(0, amp, amp / float(self._N)) self.vco_input = blocks.vector_source_f(data, False) # Build a VCO controlled by either the sinusoid or single chirp tone @@ -92,7 +95,7 @@ class pfb_top_block(gr.top_block): # Create a vector sink for each of M output channels of the filter and connect it self.snks = list() - for i in xrange(self._M): + for i in range(self._M): self.snks.append(blocks.vector_sink_c()) self.connect((self.pfb, i), self.snks[i]) @@ -104,7 +107,7 @@ def main(): tb.run() tend = time.time() - print "Run time: %f" % (tend - tstart) + print("Run time: %f" % (tend - tstart)) if 1: fig_in = pylab.figure(1, figsize=(16,9), facecolor="w") @@ -123,11 +126,11 @@ def main(): d = tb.snk_i.data()[Ns:Ne] spin_f = fig_in.add_subplot(2, 1, 1) - X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs, window = lambda d: d*winfunc(fftlen), scale_by_freq=True) X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) - f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + f_in = scipy.arange(-fs / 2.0, fs / 2.0, fs / float(X_in.size)) pin_f = spin_f.plot(f_in, X_in, "b") spin_f.set_xlim([min(f_in), max(f_in)+1]) spin_f.set_ylim([-200.0, 50.0]) @@ -137,7 +140,7 @@ def main(): spin_f.set_ylabel("Power (dBW)") - Ts = 1.0/fs + Ts = 1.0 / fs Tmax = len(d)*Ts t_in = scipy.arange(0, Tmax, Ts) @@ -157,16 +160,16 @@ def main(): # Plot each of the channels outputs. Frequencies on Figure 2 and # time signals on Figure 3 fs_o = tb._fs / tb._M - Ts_o = 1.0/fs_o + Ts_o = 1.0 / fs_o Tmax_o = len(d)*Ts_o - for i in xrange(len(tb.snks)): + for i in range(len(tb.snks)): # remove issues with the transients at the beginning # also remove some corruption at the end of the stream # this is a bug, probably due to the corner cases d = tb.snks[i].data()[Ns:Ne] sp1_f = fig1.add_subplot(Nrows, Ncols, 1+i) - X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs_o, window = lambda d: d*winfunc(fftlen), scale_by_freq=True) X_o = 10.0*scipy.log10(abs(X)) diff --git a/gr-filter/examples/decimate.py b/gr-filter/examples/decimate.py index 675073a431..fb37d8047e 100755..100644 --- a/gr-filter/examples/decimate.py +++ b/gr-filter/examples/decimate.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from gnuradio import filter @@ -60,10 +63,10 @@ class pfb_top_block(gr.top_block): window=filter.firdes.WIN_BLACKMAN_hARRIS) # Calculate the number of taps per channel for our own information - tpc = scipy.ceil(float(len(self._taps)) / float(self._decim)) - print "Number of taps: ", len(self._taps) - print "Number of filters: ", self._decim - print "Taps per channel: ", tpc + tpc = scipy.ceil(float(len(self._taps)) / float(self._decim)) + print("Number of taps: ", len(self._taps)) + print("Number of filters: ", self._decim) + print("Taps per channel: ", tpc) # Build the input signal source # We create a list of freqs, and a sine wave is generated and added to the source @@ -71,7 +74,7 @@ class pfb_top_block(gr.top_block): self.signals = list() self.add = blocks.add_cc() freqs = [10, 20, 2040] - for i in xrange(len(freqs)): + for i in range(len(freqs)): self.signals.append(analog.sig_source_c(self._fs, analog.GR_SIN_WAVE, freqs[i], 1)) self.connect(self.signals[i], (self.add,i)) @@ -100,7 +103,7 @@ def main(): tstart = time.time() tb.run() tend = time.time() - print "Run time: %f" % (tend - tstart) + print("Run time: %f" % (tend - tstart)) if 1: fig1 = pylab.figure(1, figsize=(16,9)) @@ -118,11 +121,11 @@ def main(): d = tb.snk_i.data()[Ns:Ns+Ne] sp1_f = fig1.add_subplot(2, 1, 1) - X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs, window = lambda d: d*winfunc(fftlen), scale_by_freq=True) X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) - f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + f_in = scipy.arange(-fs / 2.0, fs / 2.0, fs / float(X_in.size)) p1_f = sp1_f.plot(f_in, X_in, "b") sp1_f.set_xlim([min(f_in), max(f_in)+1]) sp1_f.set_ylim([-200.0, 50.0]) @@ -131,7 +134,7 @@ def main(): sp1_f.set_xlabel("Frequency (Hz)") sp1_f.set_ylabel("Power (dBW)") - Ts = 1.0/fs + Ts = 1.0 / fs Tmax = len(d)*Ts t_in = scipy.arange(0, Tmax, Ts) @@ -150,11 +153,11 @@ def main(): sp2_f = fig2.add_subplot(2, 1, 1) d = tb.snk.data()[Ns:Ns+Ne] - X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs_o, window = lambda d: d*winfunc(fftlen), scale_by_freq=True) X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) - f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size)) + f_o = scipy.arange(-fs_o / 2.0, fs_o / 2.0, fs_o / float(X_o.size)) p2_f = sp2_f.plot(f_o, X_o, "b") sp2_f.set_xlim([min(f_o), max(f_o)+1]) sp2_f.set_ylim([-200.0, 50.0]) @@ -164,7 +167,7 @@ def main(): sp2_f.set_ylabel("Power (dBW)") - Ts_o = 1.0/fs_o + Ts_o = 1.0 / fs_o Tmax_o = len(d)*Ts_o x_o = scipy.array(d) diff --git a/gr-filter/examples/fft_filter_ccc.py b/gr-filter/examples/fft_filter_ccc.py index 92bcc7e316..6cadddee1f 100755..100644 --- a/gr-filter/examples/fft_filter_ccc.py +++ b/gr-filter/examples/fft_filter_ccc.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, filter from gnuradio import analog from gnuradio import blocks @@ -31,13 +34,13 @@ import sys try: import scipy except ImportError: - print "Error: could not import scipy (http://www.scipy.org/)" + print("Error: could not import scipy (http://www.scipy.org/)") sys.exit(1) try: import pylab except ImportError: - print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + print("Error: could not import pylab (http://matplotlib.sourceforge.net/)") sys.exit(1) class example_fft_filter_ccc(gr.top_block): @@ -54,7 +57,7 @@ class example_fft_filter_ccc(gr.top_block): taps = filter.firdes.complex_band_pass_2(1, self._fs, self._bw0, self._bw1, self._tw, self._at) - print "Num. Taps: ", len(taps) + print("Num. Taps: ", len(taps)) self.src = analog.noise_source_c(analog.GR_GAUSSIAN, 1) self.head = blocks.head(gr.sizeof_gr_complex, self._nsamps) @@ -101,9 +104,9 @@ def main(): nfft = 1024 f1 = pylab.figure(1, figsize=(12,10)) s1 = f1.add_subplot(1,1,1) - s1.psd(data_src, NFFT=nfft, noverlap=nfft/4, + s1.psd(data_src, NFFT=nfft, noverlap=nfft / 4, Fs=args.samplerate) - s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4, + s1.psd(data_snk, NFFT=nfft, noverlap=nfft / 4, Fs=args.samplerate) f2 = pylab.figure(2, figsize=(12,10)) diff --git a/gr-filter/examples/fir_filter_ccc.py b/gr-filter/examples/fir_filter_ccc.py index 357e3d7111..fe5e7e0254 100755..100644 --- a/gr-filter/examples/fir_filter_ccc.py +++ b/gr-filter/examples/fir_filter_ccc.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, filter from gnuradio import analog from gnuradio import blocks @@ -31,13 +34,13 @@ import sys try: import scipy except ImportError: - print "Error: could not import scipy (http://www.scipy.org/)" + print("Error: could not import scipy (http://www.scipy.org/)") sys.exit(1) try: import pylab except ImportError: - print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + print("Error: could not import pylab (http://matplotlib.sourceforge.net/)") sys.exit(1) class example_fir_filter_ccc(gr.top_block): @@ -51,7 +54,7 @@ class example_fir_filter_ccc(gr.top_block): self._at = atten self._decim = D taps = filter.firdes.low_pass_2(1, self._fs, self._bw, self._tw, self._at) - print "Num. Taps: ", len(taps) + print("Num. Taps: ", len(taps)) self.src = analog.noise_source_c(analog.GR_GAUSSIAN, 1) self.head = blocks.head(gr.sizeof_gr_complex, self._nsamps) @@ -95,9 +98,9 @@ def main(): nfft = 1024 f1 = pylab.figure(1, figsize=(12,10)) s1 = f1.add_subplot(1,1,1) - s1.psd(data_src, NFFT=nfft, noverlap=nfft/4, + s1.psd(data_src, NFFT=nfft, noverlap=nfft / 4, Fs=args.samplerate) - s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4, + s1.psd(data_snk, NFFT=nfft, noverlap=nfft / 4, Fs=args.samplerate) f2 = pylab.figure(2, figsize=(12,10)) diff --git a/gr-filter/examples/fir_filter_fff.py b/gr-filter/examples/fir_filter_fff.py index 2019215f12..c4c9ea2c83 100755..100644 --- a/gr-filter/examples/fir_filter_fff.py +++ b/gr-filter/examples/fir_filter_fff.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, filter from gnuradio import analog from gnuradio import blocks @@ -31,13 +34,13 @@ import sys try: import scipy except ImportError: - print "Error: could not import scipy (http://www.scipy.org/)" + print("Error: could not import scipy (http://www.scipy.org/)") sys.exit(1) try: import pylab except ImportError: - print "Error: could not import pylab (http://matplotlib.sourceforge.net/)" + print("Error: could not import pylab (http://matplotlib.sourceforge.net/)") sys.exit(1) class example_fir_filter_fff(gr.top_block): @@ -51,7 +54,7 @@ class example_fir_filter_fff(gr.top_block): self._at = atten self._decim = D taps = filter.firdes.low_pass_2(1, self._fs, self._bw, self._tw, self._at) - print "Num. Taps: ", len(taps) + print("Num. Taps: ", len(taps)) self.src = analog.noise_source_f(analog.GR_GAUSSIAN, 1) self.head = blocks.head(gr.sizeof_float, self._nsamps) @@ -95,9 +98,9 @@ def main(): nfft = 1024 f1 = pylab.figure(1, figsize=(12,10)) s1 = f1.add_subplot(1,1,1) - s1.psd(data_src, NFFT=nfft, noverlap=nfft/4, + s1.psd(data_src, NFFT=nfft, noverlap=nfft / 4, Fs=args.samplerate) - s1.psd(data_snk, NFFT=nfft, noverlap=nfft/4, + s1.psd(data_snk, NFFT=nfft, noverlap=nfft / 4, Fs=args.samplerate) f2 = pylab.figure(2, figsize=(12,10)) diff --git a/gr-filter/examples/gr_filtdes_api.py b/gr-filter/examples/gr_filtdes_api.py index 6d7716ce49..6ef6b52f25 100755..100644 --- a/gr-filter/examples/gr_filtdes_api.py +++ b/gr-filter/examples/gr_filtdes_api.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio.filter import filter_design import sys @@ -31,7 +33,7 @@ returns b,a for IIR filter design filtobj = filter_design.launch(sys.argv) # Displaying all filter paramters -print "Filter Count:", filtobj.get_filtercount() -print "Filter type:", filtobj.get_restype() -print "Filter params", filtobj.get_params() -print "Filter Coefficients", filtobj.get_taps() +print("Filter Count:", filtobj.get_filtercount()) +print("Filter type:", filtobj.get_restype()) +print("Filter params", filtobj.get_params()) +print("Filter Coefficients", filtobj.get_taps()) diff --git a/gr-filter/examples/gr_filtdes_callback.py b/gr-filter/examples/gr_filtdes_callback.py index 9496253d7a..d99edffc46 100755..100644 --- a/gr-filter/examples/gr_filtdes_callback.py +++ b/gr-filter/examples/gr_filtdes_callback.py @@ -20,13 +20,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio.filter import filter_design import sys try: from PyQt4 import Qt, QtCore, QtGui except ImportError: - print "Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)" - raise SystemExit, 1 + print("Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)") + raise SystemExit(1) ''' Callback example @@ -36,10 +38,10 @@ launch function returns gr_filter_design mainwindow object when callback is not None ''' def print_params(filtobj): - print "Filter Count:", filtobj.get_filtercount() - print "Filter type:", filtobj.get_restype() - print "Filter params", filtobj.get_params() - print "Filter Coefficients", filtobj.get_taps() + print("Filter Count:", filtobj.get_filtercount()) + print("Filter type:", filtobj.get_restype()) + print("Filter params", filtobj.get_params()) + print("Filter Coefficients", filtobj.get_taps()) app = Qt.QApplication(sys.argv) #launch function returns gr_filter_design mainwindow object diff --git a/gr-filter/examples/gr_filtdes_live_upd.py b/gr-filter/examples/gr_filtdes_live_upd.py index 9f974dd81c..ca925eb9b4 100755..100644 --- a/gr-filter/examples/gr_filtdes_live_upd.py +++ b/gr-filter/examples/gr_filtdes_live_upd.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio.filter import filter_design from gnuradio import gr, filter from gnuradio import blocks @@ -89,8 +91,8 @@ class my_top_block(gr.top_block): pyWin.show() def update_filter(self, filtobj): - print "Filter type:", filtobj.get_restype() - print "Filter params", filtobj.get_params() + print("Filter type:", filtobj.get_restype()) + print("Filter params", filtobj.get_params()) self.filt.set_taps(filtobj.get_taps()) if __name__ == "__main__": diff --git a/gr-filter/examples/gr_filtdes_restrict.py b/gr-filter/examples/gr_filtdes_restrict.py index 1613cc6489..c18d4c1f04 100755..100644 --- a/gr-filter/examples/gr_filtdes_restrict.py +++ b/gr-filter/examples/gr_filtdes_restrict.py @@ -20,13 +20,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio.filter import filter_design import sys try: from PyQt4 import Qt, QtCore, QtGui except ImportError: - print "Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)" - raise SystemExit, 1 + print("Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)") + raise SystemExit(1) ''' @@ -35,10 +37,10 @@ Function called when "design" button is pressed or pole-zero plot is changed ''' def print_params(filtobj): - print "Filter Count:", filtobj.get_filtercount() - print "Filter type:", filtobj.get_restype() - print "Filter params", filtobj.get_params() - print "Filter Coefficients", filtobj.get_taps() + print("Filter Count:", filtobj.get_filtercount()) + print("Filter type:", filtobj.get_restype()) + print("Filter params", filtobj.get_params()) + print("Filter Coefficients", filtobj.get_taps()) app = Qt.QApplication(sys.argv) main_win = filter_design.launch(sys.argv, callback = print_params, restype = "iir") diff --git a/gr-filter/examples/interpolate.py b/gr-filter/examples/interpolate.py index 40bab7b1f1..1f1357211b 100755..100644 --- a/gr-filter/examples/interpolate.py +++ b/gr-filter/examples/interpolate.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from gnuradio import filter @@ -79,10 +82,10 @@ class pfb_top_block(gr.top_block): window=filter.firdes.WIN_BLACKMAN_hARRIS) # Calculate the number of taps per channel for our own information - tpc = scipy.ceil(float(len(self._taps)) / float(self._interp)) - print "Number of taps: ", len(self._taps) - print "Number of filters: ", self._interp - print "Taps per channel: ", tpc + tpc = scipy.ceil(float(len(self._taps)) / float(self._interp)) + print("Number of taps: ", len(self._taps)) + print("Number of filters: ", self._interp) + print("Taps per channel: ", tpc) # Create a couple of signals at different frequencies self.signal1 = analog.sig_source_c(self._fs, analog.GR_SIN_WAVE, freq1, 0.5) @@ -121,7 +124,7 @@ def main(): tstart = time.time() tb.run() tend = time.time() - print "Run time: %f" % (tend - tstart) + print("Run time: %f" % (tend - tstart)) if 1: @@ -141,11 +144,11 @@ def main(): d = tb.snk_i.data()[Ns:Ns+Ne] sp1_f = fig1.add_subplot(2, 1, 1) - X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs, window = lambda d: d*winfunc(fftlen), scale_by_freq=True) X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) - f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + f_in = scipy.arange(-fs / 2.0, fs / 2.0, fs / float(X_in.size)) p1_f = sp1_f.plot(f_in, X_in, "b") sp1_f.set_xlim([min(f_in), max(f_in)+1]) sp1_f.set_ylim([-200.0, 50.0]) @@ -155,7 +158,7 @@ def main(): sp1_f.set_xlabel("Frequency (Hz)") sp1_f.set_ylabel("Power (dBW)") - Ts = 1.0/fs + Ts = 1.0 / fs Tmax = len(d)*Ts t_in = scipy.arange(0, Tmax, Ts) @@ -175,11 +178,11 @@ def main(): sp2_f = fig2.add_subplot(2, 1, 1) d = tb.snk1.data()[Ns:Ns+(tb._interp*Ne)] - X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs, window = lambda d: d*winfunc(fftlen), scale_by_freq=True) X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) - f_o = scipy.arange(-fs_int/2.0, fs_int/2.0, fs_int/float(X_o.size)) + f_o = scipy.arange(-fs_int / 2.0, fs_int / 2.0, fs_int / float(X_o.size)) p2_f = sp2_f.plot(f_o, X_o, "b") sp2_f.set_xlim([min(f_o), max(f_o)+1]) sp2_f.set_ylim([-200.0, 50.0]) @@ -188,7 +191,7 @@ def main(): sp2_f.set_xlabel("Frequency (Hz)") sp2_f.set_ylabel("Power (dBW)") - Ts_int = 1.0/fs_int + Ts_int = 1.0 / fs_int Tmax = len(d)*Ts_int t_o = scipy.arange(0, Tmax, Ts_int) @@ -208,11 +211,11 @@ def main(): sp3_f = fig3.add_subplot(2, 1, 1) d = tb.snk2.data()[Ns:Ns+(tb._interp*Ne)] - X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen / 4, Fs=fs, window = lambda d: d*winfunc(fftlen), scale_by_freq=True) X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) - f_o = scipy.arange(-fs_aint/2.0, fs_aint/2.0, fs_aint/float(X_o.size)) + f_o = scipy.arange(-fs_aint / 2.0, fs_aint / 2.0, fs_aint / float(X_o.size)) p3_f = sp3_f.plot(f_o, X_o, "b") sp3_f.set_xlim([min(f_o), max(f_o)+1]) sp3_f.set_ylim([-200.0, 50.0]) @@ -221,7 +224,7 @@ def main(): sp3_f.set_xlabel("Frequency (Hz)") sp3_f.set_ylabel("Power (dBW)") - Ts_aint = 1.0/fs_aint + Ts_aint = 1.0 / fs_aint Tmax = len(d)*Ts_aint t_o = scipy.arange(0, Tmax, Ts_aint) diff --git a/gr-filter/examples/reconstruction.py b/gr-filter/examples/reconstruction.py index 0a83b5a4e0..c9c1cd3922 100755..100644 --- a/gr-filter/examples/reconstruction.py +++ b/gr-filter/examples/reconstruction.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, digital from gnuradio import filter from gnuradio import blocks @@ -28,20 +31,20 @@ import sys try: from gnuradio import channels except ImportError: - print "Error: Program requires gr-channels." + print("Error: Program requires gr-channels.") sys.exit(1) try: import scipy from scipy import fftpack except ImportError: - print "Error: Program requires scipy (see: www.scipy.org)." + print("Error: Program requires scipy (see: www.scipy.org).") sys.exit(1) try: import pylab except ImportError: - print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + print("Error: Program requires matplotlib (see: matplotlib.sourceforge.net).") sys.exit(1) fftlen = 8192 @@ -49,7 +52,7 @@ fftlen = 8192 def main(): N = 10000 fs = 2000.0 - Ts = 1.0/fs + Ts = 1.0 / fs t = scipy.arange(0, N*Ts, Ts) # When playing with the number of channels, be careful about the filter @@ -62,7 +65,7 @@ def main(): proto_taps = filter.firdes.low_pass_2(1, nchans*fs, bw, tb, 80, filter.firdes.WIN_BLACKMAN_hARRIS) - print "Filter length: ", len(proto_taps) + print("Filter length: ", len(proto_taps)) # Create a modulated signal @@ -95,7 +98,7 @@ def main(): tb.connect(rrc, src_snk) vsnk = [] - for i in xrange(nchans): + for i in range(nchans): tb.connect((channelizer,i), (synthesizer, i)) vsnk.append(blocks.vector_sink_c()) @@ -131,10 +134,10 @@ def main(): # Plot channels nrows = int(scipy.sqrt(nchans)) - ncols = int(scipy.ceil(float(nchans)/float(nrows))) + ncols = int(scipy.ceil(float(nchans) / float(nrows))) f2 = pylab.figure(2, figsize=(16,12), facecolor='w') - for n in xrange(nchans): + for n in range(nchans): s = f2.add_subplot(nrows, ncols, n+1) s.psd(vsnk[n].data(), NFFT=fftlen, Fs=fs_in) s.set_title("Channel {0}".format(n)) diff --git a/gr-filter/examples/resampler.py b/gr-filter/examples/resampler.py index e329f062d0..29b25629cc 100755..100644 --- a/gr-filter/examples/resampler.py +++ b/gr-filter/examples/resampler.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import filter from gnuradio import blocks @@ -48,7 +51,7 @@ class mytb(gr.top_block): gr.top_block.__init__(self) rerate = float(fs_out) / float(fs_in) - print "Resampling from %f to %f by %f " %(fs_in, fs_out, rerate) + print("Resampling from %f to %f by %f " %(fs_in, fs_out, rerate)) # Creating our own taps taps = filter.firdes.low_pass_2(32, 32, 0.25, 0.1, 80) @@ -91,31 +94,31 @@ def main(): fig1 = pylab.figure(1, figsize=(10,10), facecolor="w") sp1 = fig1.add_subplot(2,1,1) sp1.psd(tb.snk_in.data(), NFFT=nfftsize, - noverlap=nfftsize/4, Fs = fs_in) - sp1.set_title(("Input Signal at f_s=%.2f kHz" % (fs_in/1000.0))) - sp1.set_xlim([-fs_in/2, fs_in/2]) + noverlap=nfftsize / 4, Fs = fs_in) + sp1.set_title(("Input Signal at f_s=%.2f kHz" % (fs_in / 1000.0))) + sp1.set_xlim([-fs_in / 2, fs_in / 2]) sp2 = fig1.add_subplot(2,1,2) sp2.psd(tb.snk_0.data(), NFFT=nfftsize, - noverlap=nfftsize/4, Fs = fs_out, + noverlap=nfftsize / 4, Fs = fs_out, label="With our filter") sp2.psd(tb.snk_1.data(), NFFT=nfftsize, - noverlap=nfftsize/4, Fs = fs_out, + noverlap=nfftsize / 4, Fs = fs_out, label="With auto-generated filter") - sp2.set_title(("Output Signals at f_s=%.2f kHz" % (fs_out/1000.0))) - sp2.set_xlim([-fs_out/2, fs_out/2]) + sp2.set_title(("Output Signals at f_s=%.2f kHz" % (fs_out / 1000.0))) + sp2.set_xlim([-fs_out / 2, fs_out / 2]) sp2.legend() # Plot signals in time - Ts_in = 1.0/fs_in - Ts_out = 1.0/fs_out + Ts_in = 1.0 / fs_in + Ts_out = 1.0 / fs_out t_in = scipy.arange(0, len(tb.snk_in.data())*Ts_in, Ts_in) t_out = scipy.arange(0, len(tb.snk_0.data())*Ts_out, Ts_out) fig2 = pylab.figure(2, figsize=(10,10), facecolor="w") sp21 = fig2.add_subplot(2,1,1) sp21.plot(t_in, tb.snk_in.data()) - sp21.set_title(("Input Signal at f_s=%.2f kHz" % (fs_in/1000.0))) + sp21.set_title(("Input Signal at f_s=%.2f kHz" % (fs_in / 1000.0))) sp21.set_xlim([t_in[100], t_in[200]]) sp22 = fig2.add_subplot(2,1,2) @@ -123,8 +126,8 @@ def main(): label="With our filter") sp22.plot(t_out, tb.snk_1.data(), label="With auto-generated filter") - sp22.set_title(("Output Signals at f_s=%.2f kHz" % (fs_out/1000.0))) - r = float(fs_out)/float(fs_in) + sp22.set_title(("Output Signals at f_s=%.2f kHz" % (fs_out / 1000.0))) + r = float(fs_out) / float(fs_in) sp22.set_xlim([t_out[r * 100], t_out[r * 200]]) sp22.legend() diff --git a/gr-filter/examples/synth_filter.py b/gr-filter/examples/synth_filter.py index 5382127b35..b971c4a641 100755..100644 --- a/gr-filter/examples/synth_filter.py +++ b/gr-filter/examples/synth_filter.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import filter from gnuradio import blocks @@ -57,8 +60,8 @@ def main(): taps = filter.firdes.low_pass_2(len(freqs), fs, fs/float(nchans)/2, 100, 100) - print "Num. Taps = %d (taps per filter = %d)" % (len(taps), - len(taps)/nchans) + print("Num. Taps = %d (taps per filter = %d)" % (len(taps), + len(taps) / nchans)) filtbank = filter.pfb_synthesizer_ccf(nchans, taps) head = blocks.head(gr.sizeof_gr_complex, N) @@ -83,7 +86,7 @@ def main(): winfunc = scipy.blackman s2.psd(snk.data()[10000:], NFFT=fftlen, Fs = nchans*fs, - noverlap=fftlen/4, + noverlap=fftlen / 4, window = lambda d: d*winfunc(fftlen)) pylab.show() diff --git a/gr-filter/examples/synth_to_chan.py b/gr-filter/examples/synth_to_chan.py index 88fb080a65..f1f1da4ec1 100755..100644 --- a/gr-filter/examples/synth_to_chan.py +++ b/gr-filter/examples/synth_to_chan.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from gnuradio import filter @@ -59,11 +62,11 @@ def main(): fmtx.append(fm) syntaps = filter.firdes.low_pass_2(len(freqs), fs, fs/float(nchans)/2, 100, 100) - print "Synthesis Num. Taps = %d (taps per filter = %d)" % (len(syntaps), - len(syntaps)/nchans) + print("Synthesis Num. Taps = %d (taps per filter = %d)" % (len(syntaps), + len(syntaps) / nchans)) chtaps = filter.firdes.low_pass_2(len(freqs), fs, fs/float(nchans)/2, 100, 100) - print "Channelizer Num. Taps = %d (taps per filter = %d)" % (len(chtaps), - len(chtaps)/nchans) + print("Channelizer Num. Taps = %d (taps per filter = %d)" % (len(chtaps), + len(chtaps) / nchans)) filtbank = filter.pfb_synthesizer_ccf(nchans, syntaps) channelizer = filter.pfb.channelizer_ccf(nchans, chtaps) @@ -84,7 +87,7 @@ def main(): for i,si in enumerate(sigs): tb.connect(si, fmtx[i], (filtbank, i)) - for i in xrange(nchans): + for i in range(nchans): snk.append(blocks.vector_sink_c()) tb.connect((channelizer, i), snk[i]) @@ -107,7 +110,7 @@ def main(): s2 = f2.add_subplot(1,1,1) s2.psd(data, NFFT=fftlen, Fs = nchans*fs, - noverlap=fftlen/4, + noverlap=fftlen / 4, window = lambda d: d*winfunc(fftlen)) s2.set_title(("Output PSD from Channel %d" % channel)) @@ -115,7 +118,7 @@ def main(): s3 = f3.add_subplot(1,1,1) s3.psd(snk_synth.data()[1000:], NFFT=fftlen, Fs = nchans*fs, - noverlap=fftlen/4, + noverlap=fftlen / 4, window = lambda d: d*winfunc(fftlen)) s3.set_title("Output of Synthesis Filter") diff --git a/gr-filter/lib/iir_filter_ffd_impl.cc b/gr-filter/lib/iir_filter_ffd_impl.cc index f70e3a25af..c389b7c84c 100644 --- a/gr-filter/lib/iir_filter_ffd_impl.cc +++ b/gr-filter/lib/iir_filter_ffd_impl.cc @@ -32,21 +32,21 @@ namespace gr { iir_filter_ffd::sptr iir_filter_ffd::make(const std::vector<double> &fftaps, - const std::vector<double> &fbtaps, - bool oldstyle) + const std::vector<double> &fbtaps, + bool oldstyle) { return gnuradio::get_initial_sptr - (new iir_filter_ffd_impl(fftaps, fbtaps, oldstyle)); + (new iir_filter_ffd_impl(fftaps, fbtaps, oldstyle)); } iir_filter_ffd_impl::iir_filter_ffd_impl(const std::vector<double> &fftaps, - const std::vector<double> &fbtaps, - bool oldstyle) + const std::vector<double> &fbtaps, + bool oldstyle) : sync_block("iir_filter_ffd", - io_signature::make(1, 1, sizeof (float)), - io_signature::make(1, 1, sizeof (float))), - d_updated(false) + io_signature::make(1, 1, sizeof (float)), + io_signature::make(1, 1, sizeof (float))), + d_updated(false) { d_iir = new kernel::iir_filter<float,float,double,double>(fftaps, fbtaps, oldstyle); } @@ -58,7 +58,7 @@ namespace gr { void iir_filter_ffd_impl::set_taps(const std::vector<double> &fftaps, - const std::vector<double> &fbtaps) + const std::vector<double> &fbtaps) { d_new_fftaps = fftaps; d_new_fbtaps = fbtaps; @@ -67,20 +67,20 @@ namespace gr { int iir_filter_ffd_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const float *in = (const float*)input_items[0]; float *out = (float*)output_items[0]; if(d_updated) { - d_iir->set_taps(d_new_fftaps, d_new_fbtaps); - d_updated = false; + d_iir->set_taps(d_new_fftaps, d_new_fbtaps); + d_updated = false; } d_iir->filter_n(out, in, noutput_items); return noutput_items; - }; + } } /* namespace filter */ } /* namespace gr */ diff --git a/gr-filter/lib/single_pole_iir_filter_ff_impl.cc b/gr-filter/lib/single_pole_iir_filter_ff_impl.cc index d948afbc14..cbbcad4d7b 100644 --- a/gr-filter/lib/single_pole_iir_filter_ff_impl.cc +++ b/gr-filter/lib/single_pole_iir_filter_ff_impl.cc @@ -34,15 +34,15 @@ namespace gr { single_pole_iir_filter_ff::make(double alpha, unsigned int vlen) { return gnuradio::get_initial_sptr - (new single_pole_iir_filter_ff_impl(alpha, vlen)); + (new single_pole_iir_filter_ff_impl(alpha, vlen)); } single_pole_iir_filter_ff_impl::single_pole_iir_filter_ff_impl - (double alpha, unsigned int vlen) - : sync_block("single_pole_iir_filter_ff", - io_signature::make(1, 1, sizeof(float)*vlen), - io_signature::make(1, 1, sizeof(float)*vlen)), - d_vlen(vlen), d_iir(vlen) + (double alpha, unsigned int vlen) + : sync_block("single_pole_iir_filter_ff", + io_signature::make(1, 1, sizeof(float)*vlen), + io_signature::make(1, 1, sizeof(float)*vlen)), + d_vlen(vlen), d_iir(vlen) { set_taps(alpha); } @@ -55,33 +55,33 @@ namespace gr { single_pole_iir_filter_ff_impl::set_taps(double alpha) { for(unsigned int i = 0; i < d_vlen; i++) { - d_iir[i].set_taps(alpha); + d_iir[i].set_taps(alpha); } } int single_pole_iir_filter_ff_impl::work(int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { const float *in = (const float*)input_items[0]; float *out = (float*)output_items[0]; unsigned int vlen = d_vlen; if(d_vlen == 1) { - for(int i = 0; i < noutput_items; i++) { - out[i] = d_iir[0].filter (in[i]); - } + for(int i = 0; i < noutput_items; i++) { + out[i] = d_iir[0].filter (in[i]); + } } else { - for(int i = 0; i < noutput_items; i++) { - for(unsigned int j = 0; j < vlen; j++) { - *out++ = d_iir[j].filter(*in++); - } - } + for(int i = 0; i < noutput_items; i++) { + for(unsigned int j = 0; j < vlen; j++) { + *out++ = d_iir[j].filter(*in++); + } + } } return noutput_items; - }; + } } /* namespace filter */ } /* namespace gr */ diff --git a/gr-filter/python/filter/CMakeLists.txt b/gr-filter/python/filter/CMakeLists.txt index bc4892412e..f692456d0d 100644 --- a/gr-filter/python/filter/CMakeLists.txt +++ b/gr-filter/python/filter/CMakeLists.txt @@ -46,6 +46,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-filter/python/filter/__init__.py b/gr-filter/python/filter/__init__.py index cbbc80f95b..4051a9677f 100644 --- a/gr-filter/python/filter/__init__.py +++ b/gr-filter/python/filter/__init__.py @@ -22,19 +22,23 @@ ''' Filter blocks and related functions. ''' +from __future__ import absolute_import +from __future__ import unicode_literals + import os try: - from filter_swig import * + from .filter_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from filter_swig import * -from filterbank import * -from freq_xlating_fft_filter import * -from rational_resampler import * -import pfb -import optfir + from .filter_swig import * + +from .filterbank import * +from .freq_xlating_fft_filter import * +from .rational_resampler import * +from . import pfb +from . import optfir # Pull this into the filter module from gnuradio.fft import window diff --git a/gr-filter/python/filter/design/api_object.py b/gr-filter/python/filter/design/api_object.py index 7661265c75..5b3b475355 100644 --- a/gr-filter/python/filter/design/api_object.py +++ b/gr-filter/python/filter/design/api_object.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # Copyright 2012 Free Software Foundation, Inc. # # This file is part of GNU Radio @@ -18,7 +19,7 @@ # Boston, MA 02110-1301, USA. # -class ApiObject(): +class ApiObject(object): ''' Filter count variable if the filter design tool has to return multiple filter paramters in future diff --git a/gr-filter/python/filter/design/filter_design.py b/gr-filter/python/filter/design/filter_design.py index f94b6b8340..9c2c163702 100644 --- a/gr-filter/python/filter/design/filter_design.py +++ b/gr-filter/python/filter/design/filter_design.py @@ -18,65 +18,72 @@ # Boston, MA 02110-1301, USA. # -import sys, os, re, csv, copy +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + +import sys +import re +import csv import warnings from optparse import OptionParser + from gnuradio import filter try: import scipy from scipy import fftpack, poly1d, signal except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) try: from PyQt4 import Qt, QtCore, QtGui except ImportError: - print "Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)" - raise SystemExit, 1 + print("Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)") + raise SystemExit(1) try: import PyQt4.Qwt5 as Qwt except ImportError: - print "Please install PyQwt5 to run this script (http://pyqwt.sourceforge.net/)" - raise SystemExit, 1 + print("Please install PyQwt5 to run this script (http://pyqwt.sourceforge.net/)") + raise SystemExit(1) try: from gnuradio.filter.pyqt_filter_stacked import Ui_MainWindow except ImportError: - print "Could not import from pyqt_filter_stacked. Please build with \"pyuic4 pyqt_filter_stacked.ui -o pyqt_filter_stacked.py\"" - raise SystemExit, 1 + print("Could not import from pyqt_filter_stacked. Please build with \"pyuic4 pyqt_filter_stacked.ui -o pyqt_filter_stacked.py\"") + raise SystemExit(1) try: from gnuradio.filter.banditems import * except ImportError: - print "Could not import from banditems. Please check whether banditems.py is in the library path" - raise SystemExit, 1 + print("Could not import from banditems. Please check whether banditems.py is in the library path") + raise SystemExit(1) try: from gnuradio.filter.polezero_plot import * except ImportError: - print "Could not import from polezero_plot. Please check whether polezero_plot.py is in the library path" - raise SystemExit, 1 + print("Could not import from polezero_plot. Please check whether polezero_plot.py is in the library path") + raise SystemExit(1) try: from gnuradio.filter.idealbanditems import * except ImportError: - print "Could not import from idealbanditems. Please check whether idealbanditems.py is in the library path" - raise SystemExit, 1 + print("Could not import from idealbanditems. Please check whether idealbanditems.py is in the library path") + raise SystemExit(1) try: from gnuradio.filter.api_object import * except ImportError: - print "Could not import from api_object. Please check whether api_object.py is in the library path" - raise SystemExit, 1 + print("Could not import from api_object. Please check whether api_object.py is in the library path") + raise SystemExit(1) try: from gnuradio.filter.fir_design import * except ImportError: - print "Could not import from fir_design. Please check whether fir_design.py is in the library path" - raise SystemExit, 1 + print("Could not import from fir_design. Please check whether fir_design.py is in the library path") + raise SystemExit(1) try: _fromUtf8 = QtCore.QString.fromUtf8 @@ -140,72 +147,72 @@ class gr_plot_filter(QtGui.QMainWindow): self.nfft_edit_changed) self.connect(self.gui.actionQuick_Access, - Qt.SIGNAL("activated()"), - self.action_quick_access) + Qt.SIGNAL("activated()"), + self.action_quick_access) self.connect(self.gui.actionSpec_Widget, - Qt.SIGNAL("activated()"), - self.action_spec_widget) + Qt.SIGNAL("activated()"), + self.action_spec_widget) self.connect(self.gui.actionResponse_Widget, - Qt.SIGNAL("activated()"), - self.action_response_widget) + Qt.SIGNAL("activated()"), + self.action_response_widget) self.connect(self.gui.actionDesign_Widget, - Qt.SIGNAL("activated()"), - self.action_design_widget) + Qt.SIGNAL("activated()"), + self.action_design_widget) self.connect(self.gui.actionMagnitude_Response, - Qt.SIGNAL("activated()"), - self.set_actmagresponse) + Qt.SIGNAL("activated()"), + self.set_actmagresponse) self.connect(self.gui.actionGrid_2, - Qt.SIGNAL("activated()"), - self.set_actgrid) + Qt.SIGNAL("activated()"), + self.set_actgrid) self.connect(self.gui.actionPhase_Respone, - Qt.SIGNAL("activated()"), - self.set_actphase) + Qt.SIGNAL("activated()"), + self.set_actphase) self.connect(self.gui.actionGroup_Delay, - Qt.SIGNAL("activated()"), - self.set_actgdelay) + Qt.SIGNAL("activated()"), + self.set_actgdelay) self.connect(self.gui.actionFilter_Coefficients, - Qt.SIGNAL("activated()"), - self.set_actfcoeff) + Qt.SIGNAL("activated()"), + self.set_actfcoeff) self.connect(self.gui.actionBand_Diagram, - Qt.SIGNAL("activated()"), - self.set_actband) + Qt.SIGNAL("activated()"), + self.set_actband) self.connect(self.gui.actionIdeal_Band, - Qt.SIGNAL("activated()"), - self.set_drawideal) + Qt.SIGNAL("activated()"), + self.set_drawideal) self.connect(self.gui.actionPole_Zero_Plot_2, - Qt.SIGNAL("activated()"), - self.set_actpzplot) + Qt.SIGNAL("activated()"), + self.set_actpzplot) self.connect(self.gui.actionGridview, - Qt.SIGNAL("activated()"), - self.set_switchview) + Qt.SIGNAL("activated()"), + self.set_switchview) self.connect(self.gui.actionPlot_select, - Qt.SIGNAL("activated()"), - self.set_plotselect) + Qt.SIGNAL("activated()"), + self.set_plotselect) self.connect(self.gui.actionPhase_Delay, - Qt.SIGNAL("activated()"), - self.set_actpdelay) + Qt.SIGNAL("activated()"), + self.set_actpdelay) self.connect(self.gui.actionImpulse_Response, - Qt.SIGNAL("activated()"), - self.set_actimpres) + Qt.SIGNAL("activated()"), + self.set_actimpres) self.connect(self.gui.actionStep_Response, - Qt.SIGNAL("activated()"), - self.set_actstepres) + Qt.SIGNAL("activated()"), + self.set_actstepres) self.connect(self.gui.mfmagPush, Qt.SIGNAL("released()"), @@ -272,48 +279,48 @@ class gr_plot_filter(QtGui.QMainWindow): self.set_mtimpulse) self.connect(self.gui.checkKeepcur, - Qt.SIGNAL("stateChanged(int)"), - self.set_bufferplots) + Qt.SIGNAL("stateChanged(int)"), + self.set_bufferplots) self.connect(self.gui.checkGrid, - Qt.SIGNAL("stateChanged(int)"), - self.set_grid) + Qt.SIGNAL("stateChanged(int)"), + self.set_grid) self.connect(self.gui.checkMagres, - Qt.SIGNAL("stateChanged(int)"), - self.set_magresponse) + Qt.SIGNAL("stateChanged(int)"), + self.set_magresponse) self.connect(self.gui.checkGdelay, - Qt.SIGNAL("stateChanged(int)"), - self.set_gdelay) + Qt.SIGNAL("stateChanged(int)"), + self.set_gdelay) self.connect(self.gui.checkPhase, - Qt.SIGNAL("stateChanged(int)"), - self.set_phase) + Qt.SIGNAL("stateChanged(int)"), + self.set_phase) self.connect(self.gui.checkFcoeff, - Qt.SIGNAL("stateChanged(int)"), - self.set_fcoeff) + Qt.SIGNAL("stateChanged(int)"), + self.set_fcoeff) self.connect(self.gui.checkBand, - Qt.SIGNAL("stateChanged(int)"), - self.set_band) + Qt.SIGNAL("stateChanged(int)"), + self.set_band) self.connect(self.gui.checkPzplot, - Qt.SIGNAL("stateChanged(int)"), - self.set_pzplot) + Qt.SIGNAL("stateChanged(int)"), + self.set_pzplot) self.connect(self.gui.checkPdelay, - Qt.SIGNAL("stateChanged(int)"), - self.set_pdelay) + Qt.SIGNAL("stateChanged(int)"), + self.set_pdelay) self.connect(self.gui.checkImpulse, - Qt.SIGNAL("stateChanged(int)"), - self.set_impres) + Qt.SIGNAL("stateChanged(int)"), + self.set_impres) self.connect(self.gui.checkStep, - Qt.SIGNAL("stateChanged(int)"), - self.set_stepres) + Qt.SIGNAL("stateChanged(int)"), + self.set_stepres) self.gridenable = False self.mfoverlay = False @@ -387,28 +394,28 @@ class gr_plot_filter(QtGui.QMainWindow): impxtitle = Qwt.QwtText("n (Samples)") impxtitle.setFont(Qt.QFont("Helvetica", 11, Qt.QFont.Bold)) self.gui.impresPlot.setAxisTitle(self.gui.freqPlot.xBottom, - impxtitle) + impxtitle) self.gui.impresPlot.setAxisTitle(self.gui.freqPlot.yLeft, - impytitle) + impytitle) self.gui.stepresPlot.setAxisTitle(self.gui.freqPlot.xBottom, - impxtitle) + impxtitle) self.gui.stepresPlot.setAxisTitle(self.gui.freqPlot.yLeft, - impytitle) + impytitle) mtytitle = Qwt.QwtText("Amplitude") mtytitle.setFont(Qt.QFont("Helvetica", 9, Qt.QFont.Bold)) mtxtitle = Qwt.QwtText("n (Samples/taps)") mtxtitle.setFont(Qt.QFont("Helvetica", 9, Qt.QFont.Bold)) self.gui.mtimePlot.setAxisTitle(self.gui.freqPlot.xBottom, - mtxtitle) + mtxtitle) self.gui.mtimePlot.setAxisTitle(self.gui.freqPlot.yLeft, - mtytitle) + mtytitle) phytitle = Qwt.QwtText("Phase Delay") phytitle.setFont(Qt.QFont("Helvetica", 11, Qt.QFont.Bold)) self.gui.pdelayPlot.setAxisTitle(self.gui.groupPlot.xBottom, - fxtitle) + fxtitle) self.gui.pdelayPlot.setAxisTitle(self.gui.groupPlot.yLeft, - phytitle) + phytitle) # Set up plot curves self.rcurve = Qwt.QwtPlotCurve("Real") @@ -480,16 +487,16 @@ class gr_plot_filter(QtGui.QMainWindow): self.gui.timePlot.canvas()) self.mtimeZoomer = Qwt.QwtPlotZoomer(self.gui.mtimePlot.xBottom, - self.gui.mtimePlot.yLeft, - Qwt.QwtPicker.PointSelection, - Qwt.QwtPicker.AlwaysOn, - self.gui.mtimePlot.canvas()) + self.gui.mtimePlot.yLeft, + Qwt.QwtPicker.PointSelection, + Qwt.QwtPicker.AlwaysOn, + self.gui.mtimePlot.canvas()) self.mtimeZoomer2 = Qwt.QwtPlotZoomer(self.gui.mtimePlot.xBottom, - self.gui.mtimePlot.yRight, - Qwt.QwtPicker.PointSelection, - Qwt.QwtPicker.AlwaysOff, - self.gui.mtimePlot.canvas()) + self.gui.mtimePlot.yRight, + Qwt.QwtPicker.PointSelection, + Qwt.QwtPicker.AlwaysOff, + self.gui.mtimePlot.canvas()) self.freqZoomer = Qwt.QwtPlotZoomer(self.gui.freqPlot.xBottom, self.gui.freqPlot.yLeft, @@ -523,25 +530,25 @@ class gr_plot_filter(QtGui.QMainWindow): self.gui.groupPlot.canvas()) self.impresZoomer = Qwt.QwtPlotZoomer(self.gui.groupPlot.xBottom, - self.gui.groupPlot.yLeft, - Qwt.QwtPicker.PointSelection, - Qwt.QwtPicker.AlwaysOn, - self.gui.impresPlot.canvas()) + self.gui.groupPlot.yLeft, + Qwt.QwtPicker.PointSelection, + Qwt.QwtPicker.AlwaysOn, + self.gui.impresPlot.canvas()) self.stepresZoomer = Qwt.QwtPlotZoomer(self.gui.groupPlot.xBottom, - self.gui.groupPlot.yLeft, - Qwt.QwtPicker.PointSelection, - Qwt.QwtPicker.AlwaysOn, - self.gui.stepresPlot.canvas()) + self.gui.groupPlot.yLeft, + Qwt.QwtPicker.PointSelection, + Qwt.QwtPicker.AlwaysOn, + self.gui.stepresPlot.canvas()) self.pdelayZoomer = Qwt.QwtPlotZoomer(self.gui.groupPlot.xBottom, - self.gui.groupPlot.yLeft, - Qwt.QwtPicker.PointSelection, - Qwt.QwtPicker.AlwaysOn, - self.gui.pdelayPlot.canvas()) + self.gui.groupPlot.yLeft, + Qwt.QwtPicker.PointSelection, + Qwt.QwtPicker.AlwaysOn, + self.gui.pdelayPlot.canvas()) - #Assigning items + #Assigning items self.lpfitems = lpfItems self.hpfitems = hpfItems self.bpfitems = bpfItems @@ -580,7 +587,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.lpfstartproxy.setWidget(self.lpfpassEdit) self.lpfstartproxy.setPos(400,30) - self.lpfstopEdit=QtGui.QLineEdit() + self.lpfstopEdit=QtGui.QLineEdit() self.lpfstopEdit.setMaximumSize(QtCore.QSize(75,20)) self.lpfstopEdit.setText(Qt.QString("Not set")) self.lpfstopproxy=QtGui.QGraphicsProxyWidget() @@ -642,39 +649,39 @@ class gr_plot_filter(QtGui.QMainWindow): self.freqcurve.setPen(Qt.QPen(blueBrush, 1)) self.rcurve.setPen(Qt.QPen(Qt.Qt.white, 0, Qt.Qt.NoPen)) self.rcurve.setSymbol(Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse, - Qt.QBrush(Qt.Qt.gray), - Qt.QPen(Qt.Qt.blue), - Qt.QSize(8, 8))) + Qt.QBrush(Qt.Qt.gray), + Qt.QPen(Qt.Qt.blue), + Qt.QSize(8, 8))) self.icurve.setPen(Qt.QPen(Qt.Qt.white, 0, Qt.Qt.NoPen)) self.icurve.setSymbol(Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse, - Qt.QBrush(Qt.Qt.gray), - Qt.QPen(Qt.Qt.red), - Qt.QSize(8, 8))) + Qt.QBrush(Qt.Qt.gray), + Qt.QPen(Qt.Qt.red), + Qt.QSize(8, 8))) self.imprescurve.setPen(Qt.QPen(Qt.Qt.white, 0, Qt.Qt.NoPen)) self.imprescurve.setSymbol(Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse, - Qt.QBrush(Qt.Qt.gray), - Qt.QPen(Qt.Qt.blue), - Qt.QSize(8, 8))) + Qt.QBrush(Qt.Qt.gray), + Qt.QPen(Qt.Qt.blue), + Qt.QSize(8, 8))) self.imprescurve_i.setPen(Qt.QPen(Qt.Qt.white, 0, Qt.Qt.NoPen)) self.imprescurve_i.setSymbol(Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse, - Qt.QBrush(Qt.Qt.gray), - Qt.QPen(Qt.Qt.red), - Qt.QSize(8, 8))) + Qt.QBrush(Qt.Qt.gray), + Qt.QPen(Qt.Qt.red), + Qt.QSize(8, 8))) self.steprescurve.setPen(Qt.QPen(Qt.Qt.white, 0, Qt.Qt.NoPen)) self.steprescurve.setSymbol(Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse, - Qt.QBrush(Qt.Qt.gray), - Qt.QPen(Qt.Qt.blue), - Qt.QSize(8, 8))) + Qt.QBrush(Qt.Qt.gray), + Qt.QPen(Qt.Qt.blue), + Qt.QSize(8, 8))) self.steprescurve_i.setPen(Qt.QPen(Qt.Qt.white, 0, Qt.Qt.NoPen)) self.steprescurve_i.setSymbol(Qwt.QwtSymbol(Qwt.QwtSymbol.Ellipse, - Qt.QBrush(Qt.Qt.gray), - Qt.QPen(Qt.Qt.red), - Qt.QSize(8, 8))) + Qt.QBrush(Qt.Qt.gray), + Qt.QPen(Qt.Qt.red), + Qt.QSize(8, 8))) self.phasecurve.setPen(Qt.QPen(blueBrush, 1)) self.groupcurve.setPen(Qt.QPen(blueBrush, 1)) @@ -802,7 +809,7 @@ class gr_plot_filter(QtGui.QMainWindow): # filters this window type can handle currenttype = self.gui.filterTypeComboBox.currentText() items = self.gui.filterTypeComboBox.count() - for i in xrange(items): + for i in range(items): self.gui.filterTypeComboBox.removeItem(0) self.gui.filterTypeComboBox.addItems(self.optFilters) @@ -835,9 +842,9 @@ class gr_plot_filter(QtGui.QMainWindow): # filters this window type can handle currenttype = self.gui.filterTypeComboBox.currentText() items = self.gui.filterTypeComboBox.count() - for i in xrange(items): + for i in range(items): self.gui.filterTypeComboBox.removeItem(0) - self.gui.filterTypeComboBox.addItems(self.firFilters) + self.gui.filterTypeComboBox.addItems(self.firFilters) # If the last filter type was valid for this window type, # go back to it; otherwise, reset @@ -872,7 +879,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.design_iir() if len(w): reply = QtGui.QMessageBox.information(self, "BadCoefficients", - str(w[-1].message),"&Ok") + str(w[-1].message),"&Ok") # Do FIR design def design_fir(self, ftype, fs, gain, winstr): @@ -908,15 +915,15 @@ class gr_plot_filter(QtGui.QMainWindow): self.gui.nTapsEdit.setText(Qt.QString("%1").arg(self.taps.size)) else: self.draw_plots(taps,params) - zeros=self.get_zeros() - poles=self.get_poles() - self.gui.pzPlot.insertZeros(zeros) - self.gui.pzPlot.insertPoles(poles) - self.gui.mpzPlot.insertZeros(zeros) - self.gui.mpzPlot.insertPoles(poles) - self.update_fcoeff() - self.set_drawideal() - #return taps if callback is enabled + zeros=self.get_zeros() + poles=self.get_poles() + self.gui.pzPlot.insertZeros(zeros) + self.gui.pzPlot.insertPoles(poles) + self.gui.mpzPlot.insertZeros(zeros) + self.gui.mpzPlot.insertPoles(poles) + self.update_fcoeff() + self.set_drawideal() + #return taps if callback is enabled if self.callback: retobj = ApiObject() retobj.update_all("fir", self.params, self.taps, 1) @@ -935,22 +942,22 @@ class gr_plot_filter(QtGui.QMainWindow): self.cpicker.set_iir(True) self.cpicker2.set_iir(True) - iirft = {"Elliptic" : 'ellip', + iirft = {"Elliptic" : 'ellip', "Butterworth" : 'butter', "Chebyshev-1" : 'cheby1', "Chebyshev-2" : 'cheby2', "Bessel" : 'bessel' } - sanalog = {"Analog (rad/second)" : 1, - "Digital (normalized 0-1)" : 0 } + sanalog = {"Analog (rad/second)" : 1, + "Digital (normalized 0-1)" : 0 } paramtype = { 1 : "analog", 0 : "digital" } iirabbr = { - "Low Pass" : "lpf", - "High Pass" : "hpf", - "Band Pass" : "bpf", - "Band Stop" : "bnf" } + "Low Pass" : "lpf", + "High Pass" : "hpf", + "Band Pass" : "bpf", + "Band Stop" : "bnf" } iirboxes = {"Low Pass" : [self.gui.iirendofLpfPassBandEdit.text().toDouble(), self.gui.iirstartofLpfStopBandEdit.text().toDouble(), @@ -1004,33 +1011,33 @@ class gr_plot_filter(QtGui.QMainWindow): try: (self.b,self.a) = signal.iirfilter(order, besselparams, btype=iirbtype.replace(' ','').lower(), analog=sanalog[atype], ftype=iirft[iirftype], output='ba') - except StandardError, e: - reply = QtGui.QMessageBox.information(self, "IIR design error", - e.args[0], "&Ok") - (self.z,self.p,self.k) = signal.tf2zpk(self.b,self.a) - iirparams = { "filttype": iirft[iirftype],"bandtype": iirabbr[iirbtype], "filtord": order, "paramtype":paramtype[sanalog[atype]], - "critfreq": besselparams} + except Exception as e: + reply = QtGui.QMessageBox.information(self, "IIR design error", + e.args[0], "&Ok") + (self.z,self.p,self.k) = signal.tf2zpk(self.b,self.a) + iirparams = { "filttype": iirft[iirftype],"bandtype": iirabbr[iirbtype], "filtord": order, "paramtype":paramtype[sanalog[atype]], + "critfreq": besselparams} else: try: (self.b,self.a) = signal.iirdesign(params[0], params[1], params[2], - params[3], analog=sanalog[atype], ftype=iirft[iirftype], output='ba') - except StandardError, e: - reply = QtGui.QMessageBox.information(self, "IIR design error", - e.args[0], "&Ok") - (self.z,self.p,self.k) = signal.tf2zpk(self.b,self.a) - #Create params + params[3], analog=sanalog[atype], ftype=iirft[iirftype], output='ba') + except Exception as e: + reply = QtGui.QMessageBox.information(self, "IIR design error", + e.args[0], "&Ok") + (self.z,self.p,self.k) = signal.tf2zpk(self.b,self.a) + #Create params iirparams = { "filttype": iirft[iirftype], "bandtype": iirabbr[iirbtype],"paramtype":paramtype[sanalog[atype]], "pbedge": params[0], "sbedge": params[1],"gpass": params[2], "gstop": params[3]} - self.gui.pzPlot.insertZeros(self.z) - self.gui.pzPlot.insertPoles(self.p) - self.gui.mpzPlot.insertZeros(self.z) - self.gui.mpzPlot.insertPoles(self.p) - self.iir_plot_all(self.z,self.p,self.k) - self.update_fcoeff() - self.gui.nTapsEdit.setText("-") - self.params = iirparams - #return api_object if callback is enabled + self.gui.pzPlot.insertZeros(self.z) + self.gui.pzPlot.insertPoles(self.p) + self.gui.mpzPlot.insertZeros(self.z) + self.gui.mpzPlot.insertPoles(self.p) + self.iir_plot_all(self.z,self.p,self.k) + self.update_fcoeff() + self.gui.nTapsEdit.setText("-") + self.params = iirparams + #return api_object if callback is enabled if self.callback: retobj = ApiObject() retobj.update_all("iir", self.params, (self.b, self.a), 1) @@ -1041,20 +1048,20 @@ class gr_plot_filter(QtGui.QMainWindow): self.b,self.a = signal.zpk2tf(z,p,k) w,h = signal.freqz(self.b,self.a) self.fftdB = 20 * scipy.log10 (abs(h)) - self.freq = w/max(w) + self.freq = w / max(w) self.fftDeg = scipy.unwrap(scipy.arctan2(scipy.imag(h),scipy.real(h))) self.groupDelay = -scipy.diff(self.fftDeg) - self.phaseDelay = -self.fftDeg[1:]/self.freq[1:] + self.phaseDelay = -self.fftDeg[1:] / self.freq[1:] if self.gridview: - self.set_mfmagresponse() - self.set_mtimpulse() + self.set_mfmagresponse() + self.set_mtimpulse() else: - self.update_freq_curves() - self.update_phase_curves() - self.update_group_curves() - self.update_pdelay_curves() - self.update_step_curves() - self.update_imp_curves() + self.update_freq_curves() + self.update_phase_curves() + self.update_group_curves() + self.update_pdelay_curves() + self.update_step_curves() + self.update_imp_curves() def nfft_edit_changed(self, nfft): @@ -1074,9 +1081,9 @@ class gr_plot_filter(QtGui.QMainWindow): # self.update_group_curves() def get_fft(self, fs, taps, Npts): - Ts = 1.0/fs + Ts = 1.0 / fs fftpts = fftpack.fft(taps, Npts) - self.freq = scipy.arange(0, fs, 1.0/(Npts*Ts)) + self.freq = scipy.arange(0, fs, 1.0 / (Npts*Ts)) with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") self.fftdB = 20.0*scipy.log10(abs(fftpts)) @@ -1086,7 +1093,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.fftDeg = scipy.unwrap(scipy.angle(fftpts)) self.groupDelay = -scipy.diff(self.fftDeg) - self.phaseDelay = -self.fftDeg[1:]/self.freq[1:] + self.phaseDelay = -self.fftDeg[1:] / self.freq[1:] def update_time_curves(self): ntaps = len(self.taps) @@ -1119,7 +1126,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.gui.mtimePlot.enableAxis(Qwt.QwtPlot.yRight,False) self.gui.mtimePlot.setAxisScale(self.gui.mtimePlot.yLeft, ymin, ymax) - # Set the zoomer base to unzoom to the new axis + # Set the zoomer base to unzoom to the new axis self.timeZoomer.setZoomBase() self.mtimeZoomer.setZoomBase() @@ -1148,9 +1155,9 @@ class gr_plot_filter(QtGui.QMainWindow): # Reset the x-axis to the new time scale self.gui.stepresPlot.setAxisScale(self.gui.stepresPlot.xBottom, - 0, ntaps) + 0, ntaps) self.gui.stepresPlot.setAxisScale(self.gui.stepresPlot.yLeft, - symin, symax) + symin, symax) if self.mtoverlay: self.gui.mtimePlot.setAxisScale(self.steprescurve.yAxis(), symin, symax) @@ -1191,9 +1198,9 @@ class gr_plot_filter(QtGui.QMainWindow): # Reset the x-axis to the new time scale self.gui.impresPlot.setAxisScale(self.gui.impresPlot.xBottom, - 0, ntaps) + 0, ntaps) self.gui.impresPlot.setAxisScale(self.gui.impresPlot.yLeft, - iymin, iymax) + iymin, iymax) if self.mtoverlay: self.gui.mtimePlot.setAxisScale(self.imprescurve.yAxis(), @@ -1228,16 +1235,16 @@ class gr_plot_filter(QtGui.QMainWindow): ymax = self.fftdB.max() if(ymax < 0): ymax = 0.8 * self.fftdB.max() - ymin = 1.1 * self.fftdB.min() + ymin = 1.1 * self.fftdB.min() else: - xmax = self.freq[npts/2] - ymax = 1.5 * max(self.fftdB[0:npts/2]) - ymin = 1.1 * min(self.fftdB[0:npts/2]) - xmin = self.freq[0] - self.gui.freqPlot.setAxisScale(self.gui.freqPlot.xBottom, - xmin, xmax) - self.gui.freqPlot.setAxisScale(self.gui.freqPlot.yLeft, - ymin, ymax) + xmax = self.freq[npts / 2] + ymax = 1.5 * max(self.fftdB[0:npts / 2]) + ymin = 1.1 * min(self.fftdB[0:npts / 2]) + xmin = self.freq[0] + self.gui.freqPlot.setAxisScale(self.gui.freqPlot.xBottom, + xmin, xmax) + self.gui.freqPlot.setAxisScale(self.gui.freqPlot.yLeft, + ymin, ymax) if self.mfoverlay: self.gui.mfreqPlot.setAxisScale(self.gui.mfreqPlot.xBottom, @@ -1253,11 +1260,11 @@ class gr_plot_filter(QtGui.QMainWindow): xmin, xmax) self.gui.mfreqPlot.setAxisScale(self.gui.mfreqPlot.yLeft, ymin, ymax) - #Set Axis title + #Set Axis title self.gui.mfreqPlot.setAxisTitle(self.freqcurve.yAxis(), - fytitle) + fytitle) self.gui.mfreqPlot.setAxisTitle(self.freqcurve.xAxis(), - fxtitle) + fxtitle) # Set the zoomer base to unzoom to the new axis self.freqZoomer.setZoomBase() self.mfreqZoomer.setZoomBase() @@ -1279,16 +1286,16 @@ class gr_plot_filter(QtGui.QMainWindow): ymax = self.fftDeg.max() if(ymax < 0): ymax = 0.8 * self.fftDeg.max() - ymin = 1.1 * self.fftDeg.min() + ymin = 1.1 * self.fftDeg.min() else: - ymax = 1.5 * max(self.fftDeg[0:npts/2]) - ymin = 1.1 * min(self.fftDeg[0:npts/2]) - xmax = self.freq[npts/2] - xmin = self.freq[0] - self.gui.phasePlot.setAxisScale(self.gui.phasePlot.xBottom, - xmin, xmax) - self.gui.phasePlot.setAxisScale(self.gui.phasePlot.yLeft, - ymin, ymax) + ymax = 1.5 * max(self.fftDeg[0:npts / 2]) + ymin = 1.1 * min(self.fftDeg[0:npts / 2]) + xmax = self.freq[npts / 2] + xmin = self.freq[0] + self.gui.phasePlot.setAxisScale(self.gui.phasePlot.xBottom, + xmin, xmax) + self.gui.phasePlot.setAxisScale(self.gui.phasePlot.yLeft, + ymin, ymax) if self.mfoverlay: self.gui.mfreqPlot.setAxisScale(self.gui.mfreqPlot.xBottom, @@ -1307,7 +1314,7 @@ class gr_plot_filter(QtGui.QMainWindow): #Set Axis title self.gui.mfreqPlot.setAxisTitle(self.phasecurve.yAxis(), - pytitle) + pytitle) # Set the zoomer base to unzoom to the new axis self.phaseZoomer.setZoomBase() @@ -1330,16 +1337,16 @@ class gr_plot_filter(QtGui.QMainWindow): ymax = self.groupDelay.max() if(ymax < 0): ymax = 0.8 * self.groupDelay.max() - ymin = 1.1 * self.groupDelay.min() + ymin = 1.1 * self.groupDelay.min() else: - ymax = 1.5 * max(self.groupDelay[0:npts/2]) - ymin = 1.1 * min(self.groupDelay[0:npts/2]) - xmax = self.freq[npts/2] - xmin = self.freq[0] - self.gui.groupPlot.setAxisScale(self.gui.groupPlot.xBottom, - xmin, xmax) - self.gui.groupPlot.setAxisScale(self.gui.groupPlot.yLeft, - ymin, ymax) + ymax = 1.5 * max(self.groupDelay[0:npts / 2]) + ymin = 1.1 * min(self.groupDelay[0:npts / 2]) + xmax = self.freq[npts / 2] + xmin = self.freq[0] + self.gui.groupPlot.setAxisScale(self.gui.groupPlot.xBottom, + xmin, xmax) + self.gui.groupPlot.setAxisScale(self.gui.groupPlot.yLeft, + ymin, ymax) if self.mfoverlay: self.gui.mfreqPlot.setAxisScale(self.gui.mfreqPlot.xBottom, @@ -1358,7 +1365,7 @@ class gr_plot_filter(QtGui.QMainWindow): #Set Axis title self.gui.mfreqPlot.setAxisTitle(self.groupcurve.yAxis(), - gytitle) + gytitle) # Set the zoomer base to unzoom to the new axis self.groupZoomer.setZoomBase() self.mfreqZoomer.setZoomBase() @@ -1379,16 +1386,16 @@ class gr_plot_filter(QtGui.QMainWindow): ymax = self.phaseDelay.max() if(ymax < 0): ymax = 0.8 * self.phaseDelay.max() - ymin = 1.1 * self.phaseDelay.min() + ymin = 1.1 * self.phaseDelay.min() else: ymax = 1.3 * max(self.phaseDelay[0:npts]) ymin = 0.8 * min(self.phaseDelay[0:npts]) - xmax = self.freq[npts/2] - xmin = self.freq[0] - self.gui.pdelayPlot.setAxisScale(self.gui.pdelayPlot.xBottom, - xmin, xmax) - self.gui.pdelayPlot.setAxisScale(self.gui.pdelayPlot.yLeft, - ymin, ymax) + xmax = self.freq[npts / 2] + xmin = self.freq[0] + self.gui.pdelayPlot.setAxisScale(self.gui.pdelayPlot.xBottom, + xmin, xmax) + self.gui.pdelayPlot.setAxisScale(self.gui.pdelayPlot.yLeft, + ymin, ymax) if self.mfoverlay: self.gui.mfreqPlot.setAxisScale(self.gui.mfreqPlot.xBottom, @@ -1404,9 +1411,9 @@ class gr_plot_filter(QtGui.QMainWindow): xmin, xmax) self.gui.mfreqPlot.setAxisScale(self.gui.mfreqPlot.yLeft, ymin, ymax) - #Set Axis title + #Set Axis title self.gui.mfreqPlot.setAxisTitle(self.pdelaycurve.yAxis(), - phytitle) + phytitle) # Set the zoomer base to unzoom to the new axis self.pdelayZoomer.setZoomBase() @@ -1448,8 +1455,8 @@ class gr_plot_filter(QtGui.QMainWindow): #Detach and delete all plots if unchecked for c in self.bufferplots: c.detach() - self.replot_all() - self.bufferplots = [] + self.replot_all() + self.bufferplots = [] else: self.bufferplots = [] #Iterate through tabgroup children and copy curves @@ -1472,7 +1479,7 @@ class gr_plot_filter(QtGui.QMainWindow): dup.setSymbol(dsym) dup.setRenderHint(Qwt.QwtPlotItem.RenderAntialiased) dup.setData([c.x(i) for i in range(c.dataSize())], - [c.y(i) for i in range(c.dataSize())]) + [c.y(i) for i in range(c.dataSize())]) self.bufferplots.append(dup) self.bufferplots[-1].attach(item) @@ -1565,7 +1572,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.icurve.attach(self.gui.mtimePlot) self.update_freq_curves() self.update_time_curves() - self.set_drawideal() + self.set_drawideal() def set_plotselect(self): if (self.gui.actionPlot_select.isChecked() == 0 ): @@ -1605,8 +1612,8 @@ class gr_plot_filter(QtGui.QMainWindow): self.detach_allgrid() self.freqcurve.attach(self.gui.mfreqPlot) self.detach_firstattached(self.gui.mfreqPlot) - self.update_freq_curves() - self.idbanditems.detach_allidealcurves(self.gui.mfreqPlot) + self.update_freq_curves() + self.idbanditems.detach_allidealcurves(self.gui.mfreqPlot) else: self.gui.mfreqPlot.detachItems(Qwt.QwtPlotItem.Rtti_PlotItem, False) self.set_actgrid() @@ -1623,7 +1630,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.phasecurve.attach(self.gui.mfreqPlot) self.detach_firstattached(self.gui.mfreqPlot) self.update_phase_curves() - self.idbanditems.detach_allidealcurves(self.gui.mfreqPlot) + self.idbanditems.detach_allidealcurves(self.gui.mfreqPlot) else: self.gui.mfreqPlot.detachItems(Qwt.QwtPlotItem.Rtti_PlotItem, False) self.set_actgrid() @@ -1639,7 +1646,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.groupcurve.attach(self.gui.mfreqPlot) self.detach_firstattached(self.gui.mfreqPlot) self.update_group_curves() - self.idbanditems.detach_allidealcurves(self.gui.mfreqPlot) + self.idbanditems.detach_allidealcurves(self.gui.mfreqPlot) else: self.gui.mfreqPlot.detachItems(Qwt.QwtPlotItem.Rtti_PlotItem, False) self.set_actgrid() @@ -1655,7 +1662,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.pdelaycurve.attach(self.gui.mfreqPlot) self.detach_firstattached(self.gui.mfreqPlot) self.update_pdelay_curves() - self.idbanditems.detach_allidealcurves(self.gui.mfreqPlot) + self.idbanditems.detach_allidealcurves(self.gui.mfreqPlot) else: self.gui.mfreqPlot.detachItems(Qwt.QwtPlotItem.Rtti_PlotItem, False) self.set_actgrid() @@ -1688,7 +1695,7 @@ class gr_plot_filter(QtGui.QMainWindow): items[1].setYAxis(Qwt.QwtPlot.yRight) if plot is self.gui.mfreqPlot: items[1].setPen(QtGui.QPen(QtCore.Qt.red, 1, QtCore.Qt.SolidLine)) - self.set_actgrid() + self.set_actgrid() def update_fft(self, taps, params): @@ -1894,7 +1901,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.scene.addItem(item) def remove_bandview(self): - for item in self.scene.items(): + for item in list(self.scene.items()): self.scene.removeItem(item) def set_fatten(self,atten): @@ -1918,9 +1925,10 @@ class gr_plot_filter(QtGui.QMainWindow): if ftype == "Complex Band Pass": boxatten,r = self.gui.bpfStopBandAttenEdit.text().toDouble() self.gui.bpfStopBandAttenEdit.setText(Qt.QString(str(atten+boxatten))) -#self.design() + #self.design() - def set_curvetaps(self,(zr,pl)): + def set_curvetaps(self, zeros_poles): + zr, pl = zeros_poles if self.iir: self.z=zr self.p=pl @@ -1934,7 +1942,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.callback(retobj) else: hz = poly1d(zr,r=1) - #print hz.c + #print(hz.c) self.taps=hz.c*self.taps[0] self.draw_plots(self.taps,self.params) self.update_fcoeff() @@ -1949,7 +1957,8 @@ class gr_plot_filter(QtGui.QMainWindow): retobj.update_all("fir", self.params, self.taps, 1) self.callback(retobj) - def set_mcurvetaps(self,(zr,pl)): + def set_mcurvetaps(self, zeros_poles): + zr, pl = zeros_poles if self.iir: self.z=zr self.p=pl @@ -1963,7 +1972,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.callback(retobj) else: hz = poly1d(zr,r=1) - #print hz.c + #print(hz.c) self.taps=hz.c*self.taps[0] if self.gridview: self.update_fft(self.taps, self.params) @@ -1971,8 +1980,8 @@ class gr_plot_filter(QtGui.QMainWindow): self.set_mttaps() else: self.draw_plots(self.taps,self.params) - self.update_fcoeff() - #update the pzplot in other view + self.update_fcoeff() + #update the pzplot in other view zeros=self.get_zeros() poles=self.get_poles() self.gui.pzPlot.insertZeros(zeros) @@ -1983,17 +1992,19 @@ class gr_plot_filter(QtGui.QMainWindow): retobj.update_all("fir", self.params, self.taps, 1) self.callback(retobj) - def set_statusbar(self,(x,y)): + def set_statusbar(self, point): + x, y = point if x == None: - self.gui.pzstatusBar.showMessage("") + self.gui.pzstatusBar.showMessage("") else: - self.gui.pzstatusBar.showMessage("X: "+str(x)+" Y: "+str(y)) + self.gui.pzstatusBar.showMessage("X: "+str(x)+" Y: "+str(y)) - def set_mstatusbar(self,(x,y)): + def set_mstatusbar(self, point): + x, y = point if x == None: - self.gui.mpzstatusBar.showMessage("") + self.gui.mpzstatusBar.showMessage("") else: - self.gui.mpzstatusBar.showMessage("X: "+str(x)+" Y: "+str(y)) + self.gui.mpzstatusBar.showMessage("X: "+str(x)+" Y: "+str(y)) def get_zeros(self): hz = poly1d(self.taps,r=0) @@ -2053,7 +2064,7 @@ class gr_plot_filter(QtGui.QMainWindow): else: csvhandle.writerow(["restype","fir"]) - for k in self.params.keys(): + for k in list(self.params.keys()): csvhandle.writerow([k, self.params[k]]) if self.iir: csvhandle.writerow(["b",] + self.b.tolist()) @@ -2103,7 +2114,9 @@ class gr_plot_filter(QtGui.QMainWindow): params[row[0]] = float(row[1]) except ValueError: params[row[0]] = row[1] + handle.close() + if restype == "fir": self.iir = False self.gui.fselectComboBox.setCurrentIndex(0) @@ -2195,7 +2208,7 @@ class gr_plot_filter(QtGui.QMainWindow): self.params = params #Set GUI for IIR type - iirft = { "ellip" : 0, + iirft = { "ellip" : 0, "butter" : 1, "cheby1" : 2, "cheby2" : 3, @@ -2204,40 +2217,40 @@ class gr_plot_filter(QtGui.QMainWindow): paramtype = { "analog" : 1, "digital" : 0 } bandpos = { - "lpf" : 0, - "bpf" : 1, - "bnf" : 2, - "hpf" : 3} + "lpf" : 0, + "bpf" : 1, + "bnf" : 2, + "hpf" : 3} iirboxes = {"lpf" : [self.gui.iirendofLpfPassBandEdit, - self.gui.iirstartofLpfStopBandEdit, - self.gui.iirLpfPassBandAttenEdit, - self.gui.iirLpfStopBandRippleEdit], + self.gui.iirstartofLpfStopBandEdit, + self.gui.iirLpfPassBandAttenEdit, + self.gui.iirLpfStopBandRippleEdit], "hpf" : [self.gui.iirstartofHpfPassBandEdit, - self.gui.iirendofHpfStopBandEdit, - self.gui.iirHpfPassBandAttenEdit, - self.gui.iirHpfStopBandRippleEdit], + self.gui.iirendofHpfStopBandEdit, + self.gui.iirHpfPassBandAttenEdit, + self.gui.iirHpfStopBandRippleEdit], "bpf" : [self.gui.iirstartofBpfPassBandEdit, - self.gui.iirendofBpfPassBandEdit, - self.gui.iirendofBpfStopBandEdit1, - self.gui.iirstartofBpfStopBandEdit2, - self.gui.iirBpfPassBandAttenEdit, - self.gui.iirBpfStopBandRippleEdit], + self.gui.iirendofBpfPassBandEdit, + self.gui.iirendofBpfStopBandEdit1, + self.gui.iirstartofBpfStopBandEdit2, + self.gui.iirBpfPassBandAttenEdit, + self.gui.iirBpfStopBandRippleEdit], "bnf" : [self.gui.iirendofBsfPassBandEdit1, - self.gui.iirstartofBsfPassBandEdit2, - self.gui.iirstartofBsfStopBandEdit, - self.gui.iirendofBsfStopBandEdit, - self.gui.iirBsfPassBandAttenEdit, - self.gui.iirBsfStopBandRippleEdit] } + self.gui.iirstartofBsfPassBandEdit2, + self.gui.iirstartofBsfStopBandEdit, + self.gui.iirendofBsfStopBandEdit, + self.gui.iirBsfPassBandAttenEdit, + self.gui.iirBsfStopBandRippleEdit] } self.gui.fselectComboBox.setCurrentIndex(1) self.gui.iirfilterTypeComboBox.setCurrentIndex(iirft[params["filttype"]]) self.gui.iirfilterBandComboBox.setCurrentIndex(bandpos[params["bandtype"]]) if params["filttype"] == "bessel": - critfreq = map(float, params["critfreq"][1:-1].split(',')) + critfreq = list(map(float, params["critfreq"][1:-1].split(','))) self.gui.besselordEdit.setText(Qt.QString("%1").arg(params["filtord"])) self.gui.iirbesselcritEdit1.setText(Qt.QString("%1").arg(critfreq[0])) self.gui.iirbesselcritEdit2.setText(Qt.QString("%1").arg(critfreq[1])) @@ -2246,8 +2259,8 @@ class gr_plot_filter(QtGui.QMainWindow): if len(iirboxes[params["bandtype"]]) == 4: sdata = [params["pbedge"], params["sbedge"], params["gpass"], params["gstop"]] else: - pbedge = map(float, params["pbedge"][1:-1].split(',')) - sbedge = map(float, params["sbedge"][1:-1].split(',')) + pbedge = list(map(float, params["pbedge"][1:-1].split(','))) + sbedge = list(map(float, params["sbedge"][1:-1].split(','))) sdata = [pbedge[0], pbedge[1], sbedge[0], sbedge[1], params["gpass"], params["gstop"]] @@ -2260,13 +2273,13 @@ class gr_plot_filter(QtGui.QMainWindow): self.taps = scipy.array(taps) if self.params: self.get_fft(self.params["fs"], self.taps, self.nfftpts) - self.update_time_curves() - self.update_freq_curves() - self.update_phase_curves() - self.update_group_curves() - self.update_pdelay_curves() - self.update_step_curves() - self.update_imp_curves() + self.update_time_curves() + self.update_freq_curves() + self.update_phase_curves() + self.update_group_curves() + self.update_pdelay_curves() + self.update_step_curves() + self.update_imp_curves() self.gui.nTapsEdit.setText(Qt.QString("%1").arg(self.taps.size)) @@ -2309,4 +2322,3 @@ def main(args): if __name__ == '__main__': main(sys.argv) - diff --git a/gr-filter/python/filter/design/fir_design.py b/gr-filter/python/filter/design/fir_design.py index e27b065781..254595525f 100644 --- a/gr-filter/python/filter/design/fir_design.py +++ b/gr-filter/python/filter/design/fir_design.py @@ -1,3 +1,5 @@ +from __future__ import division +from __future__ import unicode_literals # Copyright 2012 Free Software Foundation, Inc. # # This file is part of GNU Radio @@ -38,7 +40,7 @@ def design_win_lpf(fs, gain, wintype, mainwin): try: taps = filter.firdes.low_pass_2(gain, fs, pb, tb, atten, wintype) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Runtime Error", e.args[0], "&Ok") return ([], [], ret) @@ -65,7 +67,7 @@ def design_win_bpf(fs, gain, wintype, mainwin): try: taps = filter.firdes.band_pass_2(gain, fs, pb1, pb2, tb, atten, wintype) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Runtime Error", e.args[0], "&Ok") return ([], [], ret) @@ -92,7 +94,7 @@ def design_win_cbpf(fs, gain, wintype, mainwin): try: taps = filter.firdes.complex_band_pass_2(gain, fs, pb1, pb2, tb, atten, wintype) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Runtime Error", e.args[0], "&Ok") return ([], [], ret) @@ -119,7 +121,7 @@ def design_win_bnf(fs, gain, wintype, mainwin): try: taps = filter.firdes.band_reject_2(gain, fs, pb1, pb2, tb, atten, wintype) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Runtime Error", e.args[0], "&Ok") return ([], [], ret) @@ -145,7 +147,7 @@ def design_win_hpf(fs, gain, wintype, mainwin): try: taps = filter.firdes.high_pass_2(gain, fs, pb, tb, atten, wintype) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Runtime Error", e.args[0], "&Ok") else: @@ -195,7 +197,7 @@ def design_win_rrc(fs, gain, wintype, mainwin): try: taps = filter.firdes.root_raised_cosine(gain, fs, sr, alpha, ntaps) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Runtime Error", e.args[0], "&Ok") else: @@ -220,7 +222,7 @@ def design_win_gaus(fs, gain, wintype, mainwin): try: taps = filter.firdes.gaussian(gain, spb, bt, ntaps) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Runtime Error", e.args[0], "&Ok") else: @@ -247,7 +249,7 @@ def design_opt_lpf(fs, gain, mainwin): try: taps = filter.optfir.low_pass(gain, fs, pb, sb, ripple, atten) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Filter did not converge", e.args[0], "&Ok") return ([],[],False) @@ -278,7 +280,7 @@ def design_opt_bpf(fs, gain, mainwin): try: taps = filter.optfir.band_pass(gain, fs, sb1, pb1, pb2, sb2, ripple, atten) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Filter did not converge", e.args[0], "&Ok") return ([],[],False) @@ -311,7 +313,7 @@ def design_opt_cbpf(fs, gain, mainwin): try: taps = filter.optfir.complex_band_pass(gain, fs, sb1, pb1, pb2, sb2, ripple, atten) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Filter did not converge", e.args[0], "&Ok") return ([],[],False) @@ -343,7 +345,7 @@ def design_opt_bnf(fs, gain, mainwin): try: taps = filter.optfir.band_reject(gain, fs, pb1, sb1, sb2, pb2, ripple, atten) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Filter did not converge", e.args[0], "&Ok") return ([],[],False) @@ -369,10 +371,10 @@ def design_opt_hb(fs, gain, mainwin): if(ret): try: - bands = [0,.25 - (trwidth/fs), .25 + (trwidth/fs), 0.5] + bands = [0,.25 - (trwidth / fs), .25 + (trwidth / fs), 0.5] taps = scipy.signal.remez(int(filtord)+1, bands, [1,0], [1,1]) taps[abs(taps) <= 1e-6] = 0. - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Filter Design Error", e.args[0], "&Ok") return ([],[],False) @@ -398,7 +400,7 @@ def design_opt_hpf(fs, gain, mainwin): try: taps = filter.optfir.high_pass(gain, fs, sb, pb, atten, ripple) - except RuntimeError, e: + except RuntimeError as e: reply = QtGui.QMessageBox.information(mainwin, "Filter did not converge", e.args[0], "&Ok") return ([],[],False) diff --git a/gr-filter/python/filter/filterbank.py b/gr-filter/python/filter/filterbank.py index 4e1456cfb1..9d8d49e719 100644 --- a/gr-filter/python/filter/filterbank.py +++ b/gr-filter/python/filter/filterbank.py @@ -19,11 +19,13 @@ # Boston, MA 02110-1301, USA. # -import sys +from __future__ import print_function +from __future__ import unicode_literals + from gnuradio import gr from gnuradio import fft from gnuradio import blocks -from filter_swig import fft_filter_ccc +from .filter_swig import fft_filter_ccc def _generate_synthesis_taps(mpoints): return [] # FIXME @@ -32,7 +34,7 @@ def _generate_synthesis_taps(mpoints): def _split_taps(taps, mpoints): assert (len(taps) % mpoints) == 0 result = [list() for x in range(mpoints)] - for i in xrange(len(taps)): + for i in range(len(taps)): (result[i % mpoints]).append(taps[i]) return [tuple(x) for x in result] @@ -119,7 +121,7 @@ class synthesis_filterbank(gr.hier_block2): self.connect((self.v2ss, i), f) self.connect(f, (self.ss2s, i)) - self.connect(self.ss2s, self) + self.connect(self.ss2s, self) class analysis_filterbank(gr.hier_block2): """ @@ -154,7 +156,7 @@ class analysis_filterbank(gr.hier_block2): # split in mpoints separate set of taps sub_taps = _split_taps(taps, mpoints) - # print >> sys.stderr, "mpoints =", mpoints, "len(sub_taps) =", len(sub_taps) + # print(>> sys.stderr, "mpoints =", mpoints, "len(sub_taps) =", len(sub_taps)) self.s2ss = blocks.stream_to_streams(item_size, mpoints) # filters here diff --git a/gr-filter/python/filter/freq_xlating_fft_filter.py b/gr-filter/python/filter/freq_xlating_fft_filter.py index f6ebe0517b..097a4c449b 100644 --- a/gr-filter/python/filter/freq_xlating_fft_filter.py +++ b/gr-filter/python/filter/freq_xlating_fft_filter.py @@ -19,13 +19,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals import math import cmath from gnuradio import gr from gnuradio.blocks import rotator_cc -from filter_swig import fft_filter_ccc +from .filter_swig import fft_filter_ccc __all__ = [ 'freq_xlating_fft_filter_ccc' ] diff --git a/gr-filter/python/filter/gui/bandgraphicsview.py b/gr-filter/python/filter/gui/bandgraphicsview.py index 9e609fe2ac..3a9cab2de5 100644 --- a/gr-filter/python/filter/gui/bandgraphicsview.py +++ b/gr-filter/python/filter/gui/bandgraphicsview.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # Copyright 2012 Free Software Foundation, Inc. # # This file is part of GNU Radio diff --git a/gr-filter/python/filter/gui/banditems.py b/gr-filter/python/filter/gui/banditems.py index 5071fe7b03..fe87bccc47 100644 --- a/gr-filter/python/filter/gui/banditems.py +++ b/gr-filter/python/filter/gui/banditems.py @@ -18,11 +18,14 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + try: from PyQt4 import Qt, QtCore, QtGui except ImportError: - print "Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)" - raise SystemExit, 1 + print("Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)") + raise SystemExit(1) #Movable solid line for filter ideal-band diagram #Enable split to cut the line into two (for bpf) diff --git a/gr-filter/python/filter/gui/icons_rc.py b/gr-filter/python/filter/gui/icons_rc.py index 0b20ecb612..e4a4558747 100644 --- a/gr-filter/python/filter/gui/icons_rc.py +++ b/gr-filter/python/filter/gui/icons_rc.py @@ -7,6 +7,7 @@ # # WARNING! All changes made in this file will be lost! +from __future__ import unicode_literals from PyQt4 import QtCore qt_resource_data = "\ diff --git a/gr-filter/python/filter/gui/idealbanditems.py b/gr-filter/python/filter/gui/idealbanditems.py index ce556577eb..67d2223258 100644 --- a/gr-filter/python/filter/gui/idealbanditems.py +++ b/gr-filter/python/filter/gui/idealbanditems.py @@ -18,11 +18,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + from PyQt4 import QtGui, QtCore, Qt import PyQt4.Qwt5 as Qwt import scipy -class IdealBandItems(): +class IdealBandItems(object): def __init__(self): self.idealbandhcurves= [ Qwt.QwtPlotCurve() for i in range(4) ] self.idealbandvcurves= [ Qwt.QwtPlotCurve() for i in range(4) ] @@ -47,27 +51,27 @@ class IdealBandItems(): x=[self.params["pbend"]]*2 y=[20.0*scipy.log10(self.params["gain"]), - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[0].setData(x, y) - x=[self.params["sbstart"], self.params["fs"]/2.0] + x=[self.params["sbstart"], self.params["fs"] / 2.0] y=[-self.params["atten"]]*2 self.idealbandhcurves[1].setData(x, y) x=[self.params["sbstart"]]*2 y=[-self.params["atten"], - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[1].setData(x, y) elif ftype == "High Pass": self.detach_unwantedcurves(plot) - x=[self.params["pbstart"],self.params["fs"]/2.0] + x=[self.params["pbstart"],self.params["fs"] / 2.0] y=[20.0*scipy.log10(self.params["gain"])]*2 self.idealbandhcurves[0].setData(x, y) x=[self.params["pbstart"]]*2 y=[20.0*scipy.log10(self.params["gain"]), - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[0].setData(x, y) x=[0,self.params["sbend"]] @@ -76,7 +80,7 @@ class IdealBandItems(): x=[self.params["sbend"]]*2 y=[-self.params["atten"], - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[1].setData(x, y) elif ftype == "Band Notch": @@ -86,12 +90,12 @@ class IdealBandItems(): x=[self.params["sbstart"]]*2 y=[-self.params["atten"], - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[0].setData(x, y) x=[self.params["sbend"]]*2 y=[-self.params["atten"], - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[1].setData(x, y) x=[0,self.params["sbstart"]-self.params["tb"]] @@ -100,16 +104,16 @@ class IdealBandItems(): x=[self.params["sbstart"]-self.params["tb"]]*2 y=[20.0*scipy.log10(self.params["gain"]), - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[2].setData(x, y) - x=[self.params["sbend"]+self.params["tb"],self.params["fs"]/2.0] + x=[self.params["sbend"]+self.params["tb"],self.params["fs"] / 2.0] y=[20.0*scipy.log10(self.params["gain"])]*2 self.idealbandhcurves[2].setData(x, y) x=[self.params["sbend"]+self.params["tb"]]*2 y=[20.0*scipy.log10(self.params["gain"]), - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[3].setData(x, y) elif ftype == "Band Pass": @@ -119,12 +123,12 @@ class IdealBandItems(): x=[self.params["pbstart"]]*2 y=[20.0*scipy.log10(self.params["gain"]), - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[0].setData(x, y) x=[self.params["pbend"]]*2 y=[20.0*scipy.log10(self.params["gain"]), - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[1].setData(x, y) x=[0,self.params["pbstart"]-self.params["tb"]] @@ -133,16 +137,16 @@ class IdealBandItems(): x=[self.params["pbstart"]-self.params["tb"]]*2 y=[-self.params["atten"], - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[2].setData(x, y) - x=[self.params["pbend"]+self.params["tb"],self.params["fs"]/2.0] + x=[self.params["pbend"]+self.params["tb"],self.params["fs"] / 2.0] y=[-self.params["atten"]]*2 self.idealbandhcurves[2].setData(x, y) x=[self.params["pbend"]+self.params["tb"]]*2 y=[-self.params["atten"], - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[3].setData(x, y) elif ftype == "Complex Band Pass": @@ -152,12 +156,12 @@ class IdealBandItems(): x=[self.params["pbstart"]]*2 y=[20.0*scipy.log10(self.params["gain"]), - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[0].setData(x, y) x=[self.params["pbend"]]*2 y=[20.0*scipy.log10(self.params["gain"]), - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[1].setData(x, y) x=[0,self.params["pbstart"]-self.params["tb"]] @@ -166,35 +170,38 @@ class IdealBandItems(): x=[self.params["pbstart"]-self.params["tb"]]*2 y=[-self.params["atten"], - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[2].setData(x, y) - x=[self.params["pbend"]+self.params["tb"],self.params["fs"]/2.0] + x=[self.params["pbend"]+self.params["tb"],self.params["fs"] / 2.0] y=[-self.params["atten"]]*2 self.idealbandhcurves[2].setData(x, y) x=[self.params["pbend"]+self.params["tb"]]*2 y=[-self.params["atten"], - plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] + plot.axisScaleDiv(Qwt.QwtPlot.yLeft).lowerBound()] self.idealbandvcurves[3].setData(x, y) else: self.detach_allidealcurves(plot) except KeyError: - print "All parameters not set for ideal band diagram" + print("All parameters not set for ideal band diagram") self.detach_allidealcurves(plot) def detach_allidealcurves(self, plot): for c in self.idealbandhcurves: c.detach() + for c in self.idealbandvcurves: c.detach() + plot.replot() def detach_unwantedcurves(self, plot): for i in range(2,4): self.idealbandvcurves[i].detach() self.idealbandhcurves[i].detach() + plot.replot() def attach_allidealcurves(self, plot): diff --git a/gr-filter/python/filter/gui/polezero_plot.py b/gr-filter/python/filter/gui/polezero_plot.py index 8f35dc8d78..e738e0e850 100644 --- a/gr-filter/python/filter/gui/polezero_plot.py +++ b/gr-filter/python/filter/gui/polezero_plot.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # Copyright 2012 Free Software Foundation, Inc. # # This file is part of GNU Radio diff --git a/gr-filter/python/filter/gui/pyqt_filter_stacked.py b/gr-filter/python/filter/gui/pyqt_filter_stacked.py index 98836180e7..813e5ef2c3 100644 --- a/gr-filter/python/filter/gui/pyqt_filter_stacked.py +++ b/gr-filter/python/filter/gui/pyqt_filter_stacked.py @@ -7,6 +7,7 @@ # # WARNING! All changes made in this file will be lost! +from __future__ import unicode_literals from PyQt4 import QtCore, QtGui try: diff --git a/gr-filter/python/filter/optfir.py b/gr-filter/python/filter/optfir.py index 8ef2a06732..6920bf02e0 100644 --- a/gr-filter/python/filter/optfir.py +++ b/gr-filter/python/filter/optfir.py @@ -27,8 +27,13 @@ For a great intro to how all this stuff works, see section 6.6 of and Barrie W. Jervis, Adison-Wesley, 1993. ISBN 0-201-54413-X. ''' +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + + import math, cmath -import filter_swig as filter +from . import filter_swig as filter # ---------------------------------------------------------------- @@ -102,11 +107,11 @@ def complex_band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2, nextra_taps: Extra taps to use in the filter (default=2) """ center_freq = (freq_pb2 + freq_pb1) / 2.0 - lp_pb = (freq_pb2 - center_freq)/1.0 + lp_pb = (freq_pb2 - center_freq) / 1.0 lp_sb = freq_sb2 - center_freq lptaps = low_pass(gain, Fs, lp_pb, lp_sb, passband_ripple_db, stopband_atten_db, nextra_taps) - spinner = [cmath.exp(2j*cmath.pi*center_freq/Fs*i) for i in xrange(len(lptaps))] + spinner = [cmath.exp(2j*cmath.pi*center_freq/Fs*i) for i in range(len(lptaps))] taps = [s*t for s,t in zip(spinner, lptaps)] return taps @@ -176,11 +181,11 @@ def high_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db, def stopband_atten_to_dev (atten_db): """Convert a stopband attenuation in dB to an absolute value""" - return 10**(-atten_db/20) + return 10**(-atten_db / 20) def passband_ripple_to_dev (ripple_db): """Convert passband ripple spec expressed in dB to an absolute value""" - return (10**(ripple_db/20)-1)/(10**(ripple_db/20)+1) + return (10**(old_div(ripple_db / 20)-1),(10**(ripple_db / 20)+1)) # ---------------------------------------------------------------- @@ -237,10 +242,10 @@ def remezord (fcuts, mags, devs, fsamp = 2): nbands = nm if nm != nd: - raise ValueError, "Length of mags and devs must be equal" + raise ValueError("Length of mags and devs must be equal") if nf != 2 * (nbands - 1): - raise ValueError, "Length of f must be 2 * len (mags) - 2" + raise ValueError("Length of f must be 2 * len (mags) - 2") for i in range (len (mags)): if mags[i] != 0: # if not stopband, get relative deviation @@ -355,4 +360,3 @@ def bporder (freq1, freq2, delta_p, delta_s): ginf = -14.6 * math.log10 (delta_p / delta_s) - 16.9 n = cinf / df + ginf * df + 1 return n - diff --git a/gr-filter/python/filter/pfb.py b/gr-filter/python/filter/pfb.py index 9f23d1061b..ea28dea45a 100644 --- a/gr-filter/python/filter/pfb.py +++ b/gr-filter/python/filter/pfb.py @@ -20,15 +20,17 @@ # Boston, MA 02110-1301, USA. # -import optfir, math +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals -from gnuradio import gr, fft -import filter_swig as filter +import math + +from gnuradio import gr, fft, blocks + +from . import optfir +from . import filter_swig as filter -try: - from gnuradio import blocks -except ImportError: - import blocks_swig as blocks class channelizer_ccf(gr.hier_block2): ''' @@ -71,7 +73,7 @@ class channelizer_ccf(gr.hier_block2): self._oversample_rate) self.connect(self, self.s2ss) - for i in xrange(self._nchans): + for i in range(self._nchans): self.connect((self.s2ss,i), (self.pfb,i)) self.connect((self.pfb,i), (self,i)) @@ -147,9 +149,9 @@ class decimator_ccf(gr.hier_block2): ''' def __init__(self, decim, taps=None, channel=0, atten=100, use_fft_rotators=True, use_fft_filters=True): - gr.hier_block2.__init__(self, "pfb_decimator_ccf", - gr.io_signature(1, 1, gr.sizeof_gr_complex), - gr.io_signature(1, 1, gr.sizeof_gr_complex)) + gr.hier_block2.__init__(self, "pfb_decimator_ccf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), + gr.io_signature(1, 1, gr.sizeof_gr_complex)) self._decim = decim self._channel = channel @@ -181,7 +183,7 @@ class decimator_ccf(gr.hier_block2): self.connect(self, self.s2ss) - for i in xrange(self._decim): + for i in range(self._decim): self.connect((self.s2ss,i), (self.pfb,i)) self.connect(self.pfb, self) @@ -227,7 +229,7 @@ class arb_resampler_ccf(gr.hier_block2): if(self._rate < 1): halfband = 0.5*self._rate bw = percent*halfband - tb = (percent/2.0)*halfband + tb = (percent / 2.0)*halfband ripple = 0.1 # As we drop the bw factor, the optfir filter has a harder time converging; @@ -237,7 +239,7 @@ class arb_resampler_ccf(gr.hier_block2): else: halfband = 0.5 bw = percent*halfband - tb = (percent/2.0)*halfband + tb = (percent / 2.0)*halfband ripple = 0.1 made = False @@ -255,7 +257,7 @@ class arb_resampler_ccf(gr.hier_block2): raise RuntimeError("optfir could not generate an appropriate filter.") self.pfb = filter.pfb_arb_resampler_ccf(self._rate, self._taps, self._size) - #print "PFB has %d taps\n" % (len(self._taps),) + #print("PFB has %d taps\n" % (len(self._taps),)) self.connect(self, self.pfb) self.connect(self.pfb, self) @@ -301,7 +303,7 @@ class arb_resampler_fff(gr.hier_block2): if(self._rate < 1): halfband = 0.5*self._rate bw = percent*halfband - tb = (percent/2.0)*halfband + tb = (percent / 2.0)*halfband ripple = 0.1 # As we drop the bw factor, the optfir filter has a harder time converging; @@ -311,7 +313,7 @@ class arb_resampler_fff(gr.hier_block2): else: halfband = 0.5 bw = percent*halfband - tb = (percent/2.0)*halfband + tb = (percent / 2.0)*halfband ripple = 0.1 made = False @@ -420,7 +422,7 @@ class channelizer_hier_ccf(gr.hier_block2): if n_filterbanks > n_chans: n_filterbanks = n_chans if outchans is None: - outchans = range(n_chans) + outchans = list(range(n_chans)) gr.hier_block2.__init__( self, "pfb_channelizer_hier_ccf", gr.io_signature(1, 1, gr.sizeof_gr_complex), @@ -436,7 +438,7 @@ class channelizer_hier_ccf(gr.hier_block2): self.s2v = blocks.stream_to_vector(gr.sizeof_gr_complex, n_chans) # Create a mapping to separate out each filterbank (a group of channels to be processed together) # And a list of sets of taps for each filterbank. - low_cpp = int(n_chans/n_filterbanks) + low_cpp = int(n_chans / n_filterbanks) extra = n_chans - low_cpp*n_filterbanks cpps = [low_cpp+1]*extra + [low_cpp]*(n_filterbanks-extra) splitter_mapping = [] @@ -460,7 +462,7 @@ class channelizer_hier_ccf(gr.hier_block2): # Add the final FFT to the channelizer. self.fft = fft.fft_vcc(n_chans, forward=True, window=[1.0]*n_chans) # Select the desired channels - if outchans != range(n_chans): + if outchans != list(range(n_chans)): selector_mapping = [[(0, i) for i in outchans]] self.selector = blocks.vector_map(gr.sizeof_gr_complex, [n_chans], selector_mapping) # Convert stream of vectors to a normal stream. @@ -469,7 +471,7 @@ class channelizer_hier_ccf(gr.hier_block2): for i in range(0, n_filterbanks): self.connect((self.splitter, i), self.fbs[i], (self.combiner, i)) self.connect(self.combiner, self.fft) - if outchans != range(n_chans): + if outchans != list(range(n_chans)): self.connect(self.fft, self.selector, self.v2ss) else: self.connect(self.fft, self.v2ss) diff --git a/gr-filter/python/filter/qa_dc_blocker.py b/gr-filter/python/filter/qa_dc_blocker.py index 66a69760de..d02af57834 100755..100644 --- a/gr-filter/python/filter/qa_dc_blocker.py +++ b/gr-filter/python/filter/qa_dc_blocker.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, filter, blocks class test_dc_blocker(gr_unittest.TestCase): diff --git a/gr-filter/python/filter/qa_fft_filter.py b/gr-filter/python/filter/qa_fft_filter.py index 172b945441..6de8ecb214 100755..100644 --- a/gr-filter/python/filter/qa_fft_filter.py +++ b/gr-filter/python/filter/qa_fft_filter.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, filter, blocks import sys @@ -88,10 +89,10 @@ def print_complex(x): class test_fft_filter(gr_unittest.TestCase): def setUp(self): - pass + pass def tearDown(self): - pass + pass def assert_fft_ok2(self, expected_result, result_data): expected_result = expected_result[:len(result_data)] @@ -104,7 +105,7 @@ class test_fft_filter(gr_unittest.TestCase): abs_eps, rel_eps) def test_ccc_001(self): - tb = gr.top_block() + tb = gr.top_block() src_data = (0,1,2,3,4,5,6,7) taps = (1,) expected_result = tuple([complex(x) for x in (0,1,2,3,4,5,6,7)]) @@ -121,7 +122,7 @@ class test_fft_filter(gr_unittest.TestCase): def test_ccc_002(self): # Test nthreads - tb = gr.top_block() + tb = gr.top_block() src_data = (0,1,2,3,4,5,6,7) taps = (2,) nthreads = 2 @@ -137,7 +138,7 @@ class test_fft_filter(gr_unittest.TestCase): self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) def test_ccc_003(self): - tb = gr.top_block() + tb = gr.top_block() src_data = (0,1,2,3,4,5,6,7) taps = (2,) expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)]) @@ -154,7 +155,7 @@ class test_fft_filter(gr_unittest.TestCase): def test_ccc_004(self): random.seed(0) - for i in xrange(25): + for i in range(25): # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) src_len = 4*1024 src_data = make_random_complex_tuple(src_len) @@ -165,16 +166,16 @@ class test_fft_filter(gr_unittest.TestCase): src = blocks.vector_source_c(src_data) op = filter.fft_filter_ccc(1, taps) dst = blocks.vector_sink_c() - tb = gr.top_block() + tb = gr.top_block() tb.connect(src, op, dst) tb.run() result_data = dst.data() - del tb + del tb self.assert_fft_ok2(expected_result, result_data) def test_ccc_005(self): random.seed(0) - for i in xrange(25): + for i in range(25): # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) dec = i + 1 src_len = 4*1024 @@ -187,10 +188,10 @@ class test_fft_filter(gr_unittest.TestCase): op = filter.fft_filter_ccc(dec, taps) dst = blocks.vector_sink_c() tb = gr.top_block() - tb.connect(src, op, dst) + tb.connect(src, op, dst) tb.run() del tb - result_data = dst.data() + result_data = dst.data() self.assert_fft_ok2(expected_result, result_data) @@ -198,7 +199,7 @@ class test_fft_filter(gr_unittest.TestCase): # Test decimating with nthreads=2 random.seed(0) nthreads = 2 - for i in xrange(25): + for i in range(25): # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) dec = i + 1 src_len = 4*1024 @@ -211,10 +212,10 @@ class test_fft_filter(gr_unittest.TestCase): op = filter.fft_filter_ccc(dec, taps, nthreads) dst = blocks.vector_sink_c() tb = gr.top_block() - tb.connect(src, op, dst) + tb.connect(src, op, dst) tb.run() del tb - result_data = dst.data() + result_data = dst.data() self.assert_fft_ok2(expected_result, result_data) @@ -223,7 +224,7 @@ class test_fft_filter(gr_unittest.TestCase): # ---------------------------------------------------------------- def test_ccf_001(self): - tb = gr.top_block() + tb = gr.top_block() src_data = (0,1,2,3,4,5,6,7) taps = (1,) expected_result = tuple([complex(x) for x in (0,1,2,3,4,5,6,7)]) @@ -240,7 +241,7 @@ class test_fft_filter(gr_unittest.TestCase): def test_ccf_002(self): # Test nthreads - tb = gr.top_block() + tb = gr.top_block() src_data = (0,1,2,3,4,5,6,7) taps = (2,) nthreads = 2 @@ -256,7 +257,7 @@ class test_fft_filter(gr_unittest.TestCase): self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) def test_ccf_003(self): - tb = gr.top_block() + tb = gr.top_block() src_data = (0,1,2,3,4,5,6,7) taps = (2,) expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)]) @@ -273,7 +274,7 @@ class test_fft_filter(gr_unittest.TestCase): def test_ccf_004(self): random.seed(0) - for i in xrange(25): + for i in range(25): # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) src_len = 4*1024 src_data = make_random_complex_tuple(src_len) @@ -284,16 +285,16 @@ class test_fft_filter(gr_unittest.TestCase): src = blocks.vector_source_c(src_data) op = filter.fft_filter_ccf(1, taps) dst = blocks.vector_sink_c() - tb = gr.top_block() + tb = gr.top_block() tb.connect(src, op, dst) tb.run() result_data = dst.data() - del tb + del tb self.assert_fft_ok2(expected_result, result_data) def test_ccf_005(self): random.seed(0) - for i in xrange(25): + for i in range(25): # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) dec = i + 1 src_len = 4*1024 @@ -306,10 +307,10 @@ class test_fft_filter(gr_unittest.TestCase): op = filter.fft_filter_ccf(dec, taps) dst = blocks.vector_sink_c() tb = gr.top_block() - tb.connect(src, op, dst) + tb.connect(src, op, dst) tb.run() del tb - result_data = dst.data() + result_data = dst.data() self.assert_fft_ok2(expected_result, result_data) @@ -317,7 +318,7 @@ class test_fft_filter(gr_unittest.TestCase): # Test decimating with nthreads=2 random.seed(0) nthreads = 2 - for i in xrange(25): + for i in range(25): # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) dec = i + 1 src_len = 4*1024 @@ -330,10 +331,10 @@ class test_fft_filter(gr_unittest.TestCase): op = filter.fft_filter_ccc(dec, taps, nthreads) dst = blocks.vector_sink_c() tb = gr.top_block() - tb.connect(src, op, dst) + tb.connect(src, op, dst) tb.run() del tb - result_data = dst.data() + result_data = dst.data() self.assert_fft_ok2(expected_result, result_data) @@ -389,7 +390,7 @@ class test_fft_filter(gr_unittest.TestCase): def xtest_fff_004(self): random.seed(0) - for i in xrange(25): + for i in range(25): sys.stderr.write("\n>>> Loop = %d\n" % (i,)) src_len = 4096 src_data = make_random_float_tuple(src_len) @@ -400,7 +401,7 @@ class test_fft_filter(gr_unittest.TestCase): src = blocks.vector_source_f(src_data) op = filter.fft_filter_fff(1, taps) dst = blocks.vector_sink_f() - tb = gr.top_block() + tb = gr.top_block() tb.connect(src, op, dst) tb.run() result_data = dst.data() @@ -411,15 +412,15 @@ class test_fft_filter(gr_unittest.TestCase): except: expected = open('expected', 'w') for x in expected_result: - expected.write(`x` + '\n') + expected.write(repr(x) + '\n') actual = open('actual', 'w') for x in result_data: - actual.write(`x` + '\n') + actual.write(repr(x) + '\n') raise def xtest_fff_005(self): random.seed(0) - for i in xrange(25): + for i in range(25): sys.stderr.write("\n>>> Loop = %d\n" % (i,)) src_len = 4*1024 src_data = make_random_float_tuple(src_len) @@ -430,7 +431,7 @@ class test_fft_filter(gr_unittest.TestCase): src = blocks.vector_source_f(src_data) op = filter.fft_filter_fff(1, taps) dst = blocks.vector_sink_f() - tb = gr.top_block() + tb = gr.top_block() tb.connect(src, op, dst) tb.run() result_data = dst.data() @@ -439,7 +440,7 @@ class test_fft_filter(gr_unittest.TestCase): def xtest_fff_006(self): random.seed(0) - for i in xrange(25): + for i in range(25): sys.stderr.write("\n>>> Loop = %d\n" % (i,)) dec = i + 1 src_len = 4*1024 @@ -451,7 +452,7 @@ class test_fft_filter(gr_unittest.TestCase): src = blocks.vector_source_f(src_data) op = filter.fft_filter_fff(dec, taps) dst = blocks.vector_sink_f() - tb = gr.top_block() + tb = gr.top_block() tb.connect(src, op, dst) tb.run() result_data = dst.data() @@ -462,7 +463,7 @@ class test_fft_filter(gr_unittest.TestCase): # test decimation with nthreads random.seed(0) nthreads = 2 - for i in xrange(25): + for i in range(25): sys.stderr.write("\n>>> Loop = %d\n" % (i,)) dec = i + 1 src_len = 4*1024 @@ -474,7 +475,7 @@ class test_fft_filter(gr_unittest.TestCase): src = blocks.vector_source_f(src_data) op = filter.fft_filter_fff(dec, taps, nthreads) dst = blocks.vector_sink_f() - tb = gr.top_block() + tb = gr.top_block() tb.connect(src, op, dst) tb.run() result_data = dst.data() @@ -483,7 +484,7 @@ class test_fft_filter(gr_unittest.TestCase): def test_fff_get0(self): random.seed(0) - for i in xrange(25): + for i in range(25): ntaps = int(random.uniform(2, 100)) taps = make_random_float_tuple(ntaps) @@ -495,7 +496,7 @@ class test_fft_filter(gr_unittest.TestCase): def test_ccc_get0(self): random.seed(0) - for i in xrange(25): + for i in range(25): ntaps = int(random.uniform(2, 100)) taps = make_random_complex_tuple(ntaps) @@ -508,4 +509,3 @@ class test_fft_filter(gr_unittest.TestCase): if __name__ == '__main__': gr_unittest.run(test_fft_filter, "test_fft_filter.xml") - diff --git a/gr-filter/python/filter/qa_filter_delay_fc.py b/gr-filter/python/filter/qa_filter_delay_fc.py index 79acace234..61567089e3 100755..100644 --- a/gr-filter/python/filter/qa_filter_delay_fc.py +++ b/gr-filter/python/filter/qa_filter_delay_fc.py @@ -20,18 +20,20 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks import math def sin_source_f(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.sin(2.*math.pi*freq*x) for x in t] return y def cos_source_f(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) for x in t] return y def fir_filter(x, taps, delay): @@ -78,7 +80,7 @@ class test_filter_delay_fc(gr_unittest.TestCase): taps = filter.firdes.hilbert(ntaps, filter.firdes.WIN_HAMMING) hd = filter.filter_delay_fc(taps) - expected_result = fir_filter(data, taps, (ntaps-1)/2) + expected_result = fir_filter(data, taps, (ntaps-1) // 2) tb.connect(src1, hd) tb.connect(hd, dst2) @@ -106,7 +108,7 @@ class test_filter_delay_fc(gr_unittest.TestCase): taps = filter.firdes.hilbert(ntaps, filter.firdes.WIN_HAMMING) hd = filter.filter_delay_fc(taps) - expected_result = fir_filter2(data, data, taps, (ntaps-1)/2) + expected_result = fir_filter2(data, data, taps, (ntaps-1) // 2) tb.connect(src1, (hd,0)) tb.connect(src1, (hd,1)) @@ -135,7 +137,7 @@ class test_filter_delay_fc(gr_unittest.TestCase): taps = filter.firdes.hilbert(ntaps, filter.firdes.WIN_HAMMING) hd = filter.filter_delay_fc(taps) - expected_result = fir_filter2(data1, data2, taps, (ntaps-1)/2) + expected_result = fir_filter2(data1, data2, taps, (ntaps-1) // 2) dst2 = blocks.vector_sink_c() diff --git a/gr-filter/python/filter/qa_filterbank.py b/gr-filter/python/filter/qa_filterbank.py index 3423b10524..9a99c6832f 100644 --- a/gr-filter/python/filter/qa_filterbank.py +++ b/gr-filter/python/filter/qa_filterbank.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + import time import random import math diff --git a/gr-filter/python/filter/qa_fir_filter.py b/gr-filter/python/filter/qa_fir_filter.py index 172d64a8dc..cfd5a7e2b2 100755..100644 --- a/gr-filter/python/filter/qa_fir_filter.py +++ b/gr-filter/python/filter/qa_fir_filter.py @@ -19,6 +19,7 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # + from gnuradio import gr, gr_unittest, filter, blocks def fir_filter(x, taps, decim=1): diff --git a/gr-filter/python/filter/qa_firdes.py b/gr-filter/python/filter/qa_firdes.py index b32e5b2f91..21521c4637 100755..100644 --- a/gr-filter/python/filter/qa_firdes.py +++ b/gr-filter/python/filter/qa_firdes.py @@ -20,16 +20,17 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, filter import sys class test_firdes(gr_unittest.TestCase): def setUp(self): - pass + pass def tearDown(self): - pass + pass def test_low_pass(self): known_taps = (0.0024871660862118006, -4.403502608370943e-18, @@ -187,4 +188,3 @@ class test_firdes(gr_unittest.TestCase): if __name__ == '__main__': gr_unittest.run(test_firdes, "test_firdes.xml") - diff --git a/gr-filter/python/filter/qa_fractional_interpolator.py b/gr-filter/python/filter/qa_fractional_interpolator.py index 839ff28d8b..05f5a2388b 100755..100644 --- a/gr-filter/python/filter/qa_fractional_interpolator.py +++ b/gr-filter/python/filter/qa_fractional_interpolator.py @@ -20,19 +20,21 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks import math def sig_source_f(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.sin(2.*math.pi*freq*x) for x in t] return y def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x) + \ - 1j*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) + \ + 1j*math.sin(2.*math.pi*freq*x) for x in t] return y class test_fractional_resampler(gr_unittest.TestCase): @@ -59,10 +61,10 @@ class test_fractional_resampler(gr_unittest.TestCase): Ntest = 5000 L = len(snk.data()) - t = map(lambda x: float(x)/(fs/rrate), xrange(L)) + t = [float(x) / (fs / rrate) for x in range(L)] phase = 0.1884 - expected_data = map(lambda x: math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() @@ -85,11 +87,11 @@ class test_fractional_resampler(gr_unittest.TestCase): Ntest = 5000 L = len(snk.data()) - t = map(lambda x: float(x)/(fs/rrate), xrange(L)) + t = [float(x) / (fs / rrate) for x in range(L)] phase = 0.1884 - expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ - 1j*math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() diff --git a/gr-filter/python/filter/qa_fractional_resampler.py b/gr-filter/python/filter/qa_fractional_resampler.py index 2580b8dd16..025bed82cb 100644 --- a/gr-filter/python/filter/qa_fractional_resampler.py +++ b/gr-filter/python/filter/qa_fractional_resampler.py @@ -20,19 +20,21 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import math from gnuradio import gr, gr_unittest, filter, blocks def sig_source_f(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.sin(2.*math.pi*freq*x) for x in t] return y def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x) + \ - 1j*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) + \ + 1j*math.sin(2.*math.pi*freq*x) for x in t] return y def const_source_f(amp, N): @@ -63,10 +65,10 @@ class test_fractional_resampler(gr_unittest.TestCase): Ntest = 5000 L = len(snk.data()) - t = map(lambda x: float(x)/(fs/rrate), xrange(L)) + t = [float(x) / (fs / rrate) for x in range(L)] phase = 0.1884 - expected_data = map(lambda x: math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() @@ -88,11 +90,11 @@ class test_fractional_resampler(gr_unittest.TestCase): Ntest = 5000 L = len(snk.data()) - t = map(lambda x: float(x)/(fs/rrate), xrange(L)) + t = [float(x) / (fs / rrate) for x in range(L)] phase = 0.1884 - expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ - 1j*math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() @@ -117,10 +119,10 @@ class test_fractional_resampler(gr_unittest.TestCase): Ntest = 5000 L = len(snk.data()) - t = map(lambda x: float(x)/(fs/rrate), xrange(L)) + t = [float(x) / (fs / rrate) for x in range(L)] phase = 0.1884 - expected_data = map(lambda x: math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() @@ -145,11 +147,11 @@ class test_fractional_resampler(gr_unittest.TestCase): Ntest = 5000 L = len(snk.data()) - t = map(lambda x: float(x)/(fs/rrate), xrange(L)) + t = [float(x) / (fs / rrate) for x in range(L)] phase = 0.1884 - expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ - 1j*math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() diff --git a/gr-filter/python/filter/qa_freq_xlating_fft_filter.py b/gr-filter/python/filter/qa_freq_xlating_fft_filter.py index d5c7d41dd9..0a7bc88178 100755..100644 --- a/gr-filter/python/filter/qa_freq_xlating_fft_filter.py +++ b/gr-filter/python/filter/qa_freq_xlating_fft_filter.py @@ -19,6 +19,8 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks import cmath, math @@ -34,14 +36,14 @@ def fir_filter(x, taps, decim=1): return y def sig_source_s(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: int(100*math.sin(2.*math.pi*freq*x)), t) + t = [float(x) / samp_rate for x in range(N)] + y = [int(100*math.sin(2.*math.pi*freq*x)) for x in t] return y def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x) + \ - 1j*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) + \ + 1j*math.sin(2.*math.pi*freq*x) for x in t] return y def mix(lo, data): @@ -60,17 +62,17 @@ class test_freq_xlating_filter(gr_unittest.TestCase): self.fs = fs = 1 self.fc = fc = 0.3 self.bw = bw = 0.1 - self.taps = filter.firdes.low_pass(1, fs, bw, bw/4) - times = xrange(1024) - self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), times) + self.taps = filter.firdes.low_pass(1, fs, bw, bw / 4) + times = list(range(1024)) + self.src_data = [cmath.exp(-2j*cmath.pi*fc/fs*(t / 100.0)) for t in times] def generate_ccc_source(self): self.fs = fs = 1 self.fc = fc = 0.3 self.bw = bw = 0.1 - self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4) - times = xrange(1024) - self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), times) + self.taps = filter.firdes.complex_band_pass(1, fs, -bw / 2, bw / 2, bw / 4) + times = list(range(1024)) + self.src_data = [cmath.exp(-2j*cmath.pi*fc/fs*(t / 100.0)) for t in times] def assert_fft_ok(self, expected_result, result_data): expected_result = expected_result[:len(result_data)] diff --git a/gr-filter/python/filter/qa_freq_xlating_fir_filter.py b/gr-filter/python/filter/qa_freq_xlating_fir_filter.py index ca5245db64..f40197b964 100755..100644 --- a/gr-filter/python/filter/qa_freq_xlating_fir_filter.py +++ b/gr-filter/python/filter/qa_freq_xlating_fir_filter.py @@ -19,6 +19,8 @@ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks import cmath, math @@ -34,14 +36,14 @@ def fir_filter(x, taps, decim=1): return y def sig_source_s(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: int(100*math.sin(2.*math.pi*freq*x)), t) + t = [float(x) / samp_rate for x in range(N)] + y = [int(100*math.sin(2.*math.pi*freq*x)) for x in t] return y def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x) + \ - 1j*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) + \ + 1j*math.sin(2.*math.pi*freq*x) for x in t] return y def mix(lo, data): @@ -60,49 +62,49 @@ class test_freq_xlating_filter(gr_unittest.TestCase): self.fs = fs = 1 self.fc = fc = 0.3 self.bw = bw = 0.1 - self.taps = filter.firdes.low_pass(1, fs, bw, bw/4) - times = xrange(100) - self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), times) + self.taps = filter.firdes.low_pass(1, fs, bw, bw / 4) + times = list(range(100)) + self.src_data = [cmath.exp(-2j*cmath.pi*fc/fs*(t / 100.0)) for t in times] def generate_ccc_source(self): self.fs = fs = 1 self.fc = fc = 0.3 self.bw = bw = 0.1 - self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4) - times = xrange(100) - self.src_data = map(lambda t: cmath.exp(-2j*cmath.pi*fc/fs*(t/100.0)), times) + self.taps = filter.firdes.complex_band_pass(1, fs, -bw / 2, bw / 2, bw / 4) + times = list(range(100)) + self.src_data = [cmath.exp(-2j*cmath.pi*fc/fs*(t / 100.0)) for t in times] def generate_fcf_source(self): self.fs = fs = 1 self.fc = fc = 0.3 self.bw = bw = 0.1 - self.taps = filter.firdes.low_pass(1, fs, bw, bw/4) - times = xrange(100) - self.src_data = map(lambda t: math.sin(2*cmath.pi*fc/fs*(t/100.0)), times) + self.taps = filter.firdes.low_pass(1, fs, bw, bw / 4) + times = list(range(100)) + self.src_data = [math.sin(2*cmath.pi*fc/fs*(t / 100.0)) for t in times] def generate_fcc_source(self): self.fs = fs = 1 self.fc = fc = 0.3 self.bw = bw = 0.1 - self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4) - times = xrange(100) - self.src_data = map(lambda t: math.sin(2*cmath.pi*fc/fs*(t/100.0)), times) + self.taps = filter.firdes.complex_band_pass(1, fs, -bw / 2, bw / 2, bw / 4) + times = list(range(100)) + self.src_data = [math.sin(2*cmath.pi*fc/fs*(t / 100.0)) for t in times] def generate_scf_source(self): self.fs = fs = 1 self.fc = fc = 0.3 self.bw = bw = 0.12 - self.taps = filter.firdes.low_pass(1, fs, bw, bw/4) - times = xrange(100) - self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times) + self.taps = filter.firdes.low_pass(1, fs, bw, bw / 4) + times = list(range(100)) + self.src_data = [int(100*math.sin(2*cmath.pi*fc/fs*(t / 100.0))) for t in times] def generate_scc_source(self): self.fs = fs = 1 self.fc = fc = 0.3 self.bw = bw = 0.12 - self.taps = filter.firdes.complex_band_pass(1, fs, -bw/2, bw/2, bw/4) - times = xrange(100) - self.src_data = map(lambda t: int(100*math.sin(2*cmath.pi*fc/fs*(t/100.0))), times) + self.taps = filter.firdes.complex_band_pass(1, fs, -bw / 2, bw / 2, bw / 4) + times = list(range(100)) + self.src_data = [int(100*math.sin(2*cmath.pi*fc/fs*(t / 100.0))) for t in times] def test_fir_filter_ccf_001(self): diff --git a/gr-filter/python/filter/qa_hilbert.py b/gr-filter/python/filter/qa_hilbert.py index e8550a5932..c1f048ba14 100755..100644 --- a/gr-filter/python/filter/qa_hilbert.py +++ b/gr-filter/python/filter/qa_hilbert.py @@ -20,18 +20,20 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks import math def sig_source_f(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.sin(2.*math.pi*freq*x) for x in t] return y def fir_filter(x, taps): y = [] x2 = (len(taps)-1)*[0,] + x - delay = (len(taps)-1)/2 + delay = (len(taps)-1) // 2 for i in range(len(x)): yi = 0 for j in range(len(taps)): diff --git a/gr-filter/python/filter/qa_iir_filter.py b/gr-filter/python/filter/qa_iir_filter.py index 0a89dc4d89..fa8a6af29d 100755..100644 --- a/gr-filter/python/filter/qa_iir_filter.py +++ b/gr-filter/python/filter/qa_iir_filter.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, filter, blocks class test_iir_filter(gr_unittest.TestCase): diff --git a/gr-filter/python/filter/qa_interp_fir_filter.py b/gr-filter/python/filter/qa_interp_fir_filter.py index 536ab1bb85..66580c9745 100755..100644 --- a/gr-filter/python/filter/qa_interp_fir_filter.py +++ b/gr-filter/python/filter/qa_interp_fir_filter.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, filter, blocks import math diff --git a/gr-filter/python/filter/qa_pfb_arb_resampler.py b/gr-filter/python/filter/qa_pfb_arb_resampler.py index 0bac3e5c15..01124f58cb 100755..100644 --- a/gr-filter/python/filter/qa_pfb_arb_resampler.py +++ b/gr-filter/python/filter/qa_pfb_arb_resampler.py @@ -20,18 +20,20 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks import math def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x) + \ - 1j*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) + \ + 1j*math.sin(2.*math.pi*freq*x) for x in t] return y def sig_source_f(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.sin(2.*math.pi*freq*x) for x in t] return y class test_pfb_arb_resampler(gr_unittest.TestCase): @@ -48,7 +50,7 @@ class test_pfb_arb_resampler(gr_unittest.TestCase): rrate = 2.3421 # resampling rate nfilts = 32 - taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs/2, fs/10, + taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs / 2, fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) @@ -69,10 +71,10 @@ class test_pfb_arb_resampler(gr_unittest.TestCase): phase = pfb.phase_offset(freq, fs) # Create a timeline offset by the filter's group delay - t = map(lambda x: float(x)/(fs*rrate), xrange(-delay, L-delay)) + t = [float(x) / (fs*rrate) for x in range(-delay, L-delay)] # Data of the sinusoid at frequency freq with the delay and phase offset. - expected_data = map(lambda x: math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() @@ -84,7 +86,7 @@ class test_pfb_arb_resampler(gr_unittest.TestCase): rrate = 2.4321 # resampling rate nfilts = 32 - taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs/2, fs/10, + taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs / 2, fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) @@ -105,11 +107,11 @@ class test_pfb_arb_resampler(gr_unittest.TestCase): phase = pfb.phase_offset(freq, fs) # Create a timeline offset by the filter's group delay - t = map(lambda x: float(x)/(fs*rrate), xrange(-delay, L-delay)) + t = [float(x) / (fs*rrate) for x in range(-delay, L-delay)] # Data of the sinusoid at frequency freq with the delay and phase offset. - expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ - 1j*math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() @@ -121,7 +123,7 @@ class test_pfb_arb_resampler(gr_unittest.TestCase): rrate = 0.75 # resampling rate nfilts = 32 - taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs/4, fs/10, + taps = filter.firdes.low_pass_2(nfilts, nfilts*fs, fs / 4, fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) @@ -142,11 +144,11 @@ class test_pfb_arb_resampler(gr_unittest.TestCase): phase = pfb.phase_offset(freq, fs) # Create a timeline offset by the filter's group delay - t = map(lambda x: float(x)/(fs*rrate), xrange(-delay, L-delay)) + t = [float(x) / (fs*rrate) for x in range(-delay, L-delay)] # Data of the sinusoid at frequency freq with the delay and phase offset. - expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ - 1j*math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() @@ -158,7 +160,7 @@ class test_pfb_arb_resampler(gr_unittest.TestCase): rrate = 3.4321 # resampling rate nfilts = 32 - taps = filter.firdes.complex_band_pass_2(nfilts, nfilts*fs, 50, 400, fs/10, + taps = filter.firdes.complex_band_pass_2(nfilts, nfilts*fs, 50, 400, fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) @@ -179,11 +181,11 @@ class test_pfb_arb_resampler(gr_unittest.TestCase): phase = pfb.phase_offset(freq, fs) # Create a timeline offset by the filter's group delay - t = map(lambda x: float(x)/(fs*rrate), xrange(-delay, L-delay)) + t = [float(x) / (fs*rrate) for x in range(-delay, L-delay)] # Data of the sinusoid at frequency freq with the delay and phase offset. - expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ - 1j*math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() @@ -195,7 +197,7 @@ class test_pfb_arb_resampler(gr_unittest.TestCase): rrate = 0.715 # resampling rate nfilts = 32 - taps = filter.firdes.complex_band_pass_2(nfilts, nfilts*fs, 50, 400, fs/10, + taps = filter.firdes.complex_band_pass_2(nfilts, nfilts*fs, 50, 400, fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) @@ -216,11 +218,11 @@ class test_pfb_arb_resampler(gr_unittest.TestCase): phase = pfb.phase_offset(freq, fs) # Create a timeline offset by the filter's group delay - t = map(lambda x: float(x)/(fs*rrate), xrange(-delay, L-delay)) + t = [float(x) / (fs*rrate) for x in range(-delay, L-delay)] # Data of the sinusoid at frequency freq with the delay and phase offset. - expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ - 1j*math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() diff --git a/gr-filter/python/filter/qa_pfb_channelizer.py b/gr-filter/python/filter/qa_pfb_channelizer.py index e370f510ea..902c360296 100755..100644 --- a/gr-filter/python/filter/qa_pfb_channelizer.py +++ b/gr-filter/python/filter/qa_pfb_channelizer.py @@ -20,13 +20,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks, analog import math, cmath def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x) + \ - 1j*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) + \ + 1j*math.sin(2.*math.pi*freq*x) for x in t] return y @@ -45,7 +47,7 @@ class test_pfb_channelizer(gr_unittest.TestCase): self.ifs = self.M*self.fs self.taps = filter.firdes.low_pass_2( - 1, self.ifs, self.fs/2, self.fs/10, + 1, self.ifs, self.fs / 2, self.fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) @@ -67,7 +69,7 @@ class test_pfb_channelizer(gr_unittest.TestCase): """Test roundig error handling for oversample rate (ok).""" channels, oversample = 36, 25. filter.pfb.channelizer_ccf(channels, taps=self.taps, - oversample_rate=channels/oversample) + oversample_rate=channels / oversample) def test_0003(self): """Test roundig error handling for oversample rate, (bad).""" @@ -83,7 +85,7 @@ class test_pfb_channelizer(gr_unittest.TestCase): tb = gr.top_block() signals = [] add = blocks.add_cc() - for i in xrange(len(self.freqs)): + for i in range(len(self.freqs)): f = self.freqs[i] + i*self.fs signals.append(analog.sig_source_c(self.ifs, analog.GR_SIN_WAVE, f, 1)) tb.connect(signals[i], (add,i)) @@ -97,7 +99,7 @@ class test_pfb_channelizer(gr_unittest.TestCase): def check_channelizer(self, channelizer_block): signals = list() add = blocks.add_cc() - for i in xrange(len(self.freqs)): + for i in range(len(self.freqs)): f = self.freqs[i] + i*self.fs data = sig_source_c(self.ifs, f, 1, self.N) signals.append(blocks.vector_source_c(data)) @@ -109,7 +111,7 @@ class test_pfb_channelizer(gr_unittest.TestCase): self.tb.connect(add, channelizer_block) snks = list() - for i in xrange(self.M): + for i in range(self.M): snks.append(blocks.vector_sink_c()) #self.tb.connect((s2ss,i), (channelizer_block,i)) self.tb.connect((channelizer_block, i), snks[i]) @@ -128,8 +130,8 @@ class test_pfb_channelizer(gr_unittest.TestCase): Ntest = 50 expected = expected[-Ntest:] received = received[-Ntest:] - expected = [x/expected[0] for x in expected] - received = [x/received[0] for x in received] + expected = [x / expected[0] for x in expected] + received = [x / received[0] for x in received] self.assertComplexTuplesAlmostEqual(expected, received, 3) @@ -142,7 +144,7 @@ class test_pfb_channelizer(gr_unittest.TestCase): if diff < -math.pi: diff += 2*math.pi freqs.append(diff) - freq = float(sum(freqs))/len(freqs) + freq = float(sum(freqs)) / len(freqs) freq /= 2*math.pi return freq @@ -154,12 +156,12 @@ class test_pfb_channelizer(gr_unittest.TestCase): delay = int(delay) # Create a time scale that's delayed to match the filter delay - t = map(lambda x: float(x)/self.fs, xrange(delay, L+delay)) + t = [float(x) / self.fs for x in range(delay, L+delay)] # Create known data as complex sinusoids at the different baseband freqs # the different channel numbering is due to channelizer output order. - expected_data = [map(lambda x: math.cos(2.*math.pi*f*x) + - 1j*math.sin(2.*math.pi*f*x), t) for f in self.freqs] + expected_data = [[math.cos(2.*math.pi*f*x) + + 1j*math.sin(2.*math.pi*f*x) for x in t] for f in self.freqs] return expected_data diff --git a/gr-filter/python/filter/qa_pfb_decimator.py b/gr-filter/python/filter/qa_pfb_decimator.py index 4366e85eec..5d11533cd4 100755..100644 --- a/gr-filter/python/filter/qa_pfb_decimator.py +++ b/gr-filter/python/filter/qa_pfb_decimator.py @@ -20,13 +20,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks import math def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x) + \ - 1j*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) + \ + 1j*math.sin(2.*math.pi*freq*x) for x in t] return y def run_test(tb, channel, fft_rotate, fft_filter): @@ -35,16 +37,16 @@ def run_test(tb, channel, fft_rotate, fft_filter): fs = 5000.0 # baseband sampling rate ifs = M*fs # input samp rate to decimator - taps = filter.firdes.low_pass_2(1, ifs, fs/2, fs/10, + taps = filter.firdes.low_pass_2(1, ifs, fs / 2, fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) signals = list() add = blocks.add_cc() freqs = [-230., 121., 110., -513., 203.] - Mch = ((len(freqs)-1)/2 + channel) % len(freqs) - for i in xrange(len(freqs)): - f = freqs[i] + (M/2-M+i+1)*fs + Mch = ((len(freqs)-1) // 2 + channel) % len(freqs) + for i in range(len(freqs)): + f = freqs[i] + (M // 2-M+i+1)*fs data = sig_source_c(ifs, f, 1, N) signals.append(blocks.vector_source_c(data)) tb.connect(signals[i], (add,i)) @@ -54,7 +56,7 @@ def run_test(tb, channel, fft_rotate, fft_filter): snk = blocks.vector_sink_c() tb.connect(add, s2ss) - for i in xrange(M): + for i in range(M): tb.connect((s2ss,i), (pfb,i)) tb.connect(pfb, snk) tb.run() @@ -75,12 +77,12 @@ def run_test(tb, channel, fft_rotate, fft_filter): delay = int(delay) # Create a time scale that's delayed to match the filter delay - t = map(lambda x: float(x)/fs, xrange(delay, L+delay)) + t = [float(x) / fs for x in range(delay, L+delay)] # Create known data as complex sinusoids for the baseband freq # of the extracted channel is due to decimator output order. - expected_data = map(lambda x: math.cos(2.*math.pi*freqs[Mch]*x+phase) + \ - 1j*math.sin(2.*math.pi*freqs[Mch]*x+phase), t) + expected_data = [math.cos(2.*math.pi*freqs[Mch]*x+phase) + \ + 1j*math.sin(2.*math.pi*freqs[Mch]*x+phase) for x in t] dst_data = snk.data() return (dst_data, expected_data) diff --git a/gr-filter/python/filter/qa_pfb_interpolator.py b/gr-filter/python/filter/qa_pfb_interpolator.py index b7ed4feef6..c6aeb8e4c2 100755..100644 --- a/gr-filter/python/filter/qa_pfb_interpolator.py +++ b/gr-filter/python/filter/qa_pfb_interpolator.py @@ -20,14 +20,16 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks import math def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x) + \ - 1j*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) + \ + 1j*math.sin(2.*math.pi*freq*x) for x in t] return y class test_pfb_interpolator(gr_unittest.TestCase): @@ -44,7 +46,7 @@ class test_pfb_interpolator(gr_unittest.TestCase): fs = 1000 # baseband sampling rate ofs = M*fs # output samp rate of interpolator - taps = filter.firdes.low_pass_2(M, ofs, fs/4, fs/10, + taps = filter.firdes.low_pass_2(M, ofs, fs / 4, fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) @@ -66,12 +68,12 @@ class test_pfb_interpolator(gr_unittest.TestCase): phase = 4.8870112969978994 # Create a time scale - t = map(lambda x: float(x)/ofs, xrange(0, L)) + t = [float(x) / ofs for x in range(0, L)] # Create known data as complex sinusoids for the baseband freq # of the extracted channel is due to decimator output order. - expected_data = map(lambda x: math.cos(2.*math.pi*freq*x+phase) + \ - 1j*math.sin(2.*math.pi*freq*x+phase), t) + expected_data = [math.cos(2.*math.pi*freq*x+phase) + \ + 1j*math.sin(2.*math.pi*freq*x+phase) for x in t] dst_data = snk.data() diff --git a/gr-filter/python/filter/qa_pfb_synthesizer.py b/gr-filter/python/filter/qa_pfb_synthesizer.py index 0b3f8b27a2..42f891a545 100755..100644 --- a/gr-filter/python/filter/qa_pfb_synthesizer.py +++ b/gr-filter/python/filter/qa_pfb_synthesizer.py @@ -20,14 +20,16 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks import math def sig_source_c(samp_rate, freq, amp, N): - t = map(lambda x: float(x)/samp_rate, xrange(N)) - y = map(lambda x: math.cos(2.*math.pi*freq*x) + \ - 1j*math.sin(2.*math.pi*freq*x), t) + t = [float(x) / samp_rate for x in range(N)] + y = [math.cos(2.*math.pi*freq*x) + \ + 1j*math.sin(2.*math.pi*freq*x) for x in t] return y class test_pfb_synthesizer(gr_unittest.TestCase): @@ -44,20 +46,20 @@ class test_pfb_synthesizer(gr_unittest.TestCase): fs = 1000 # baseband sampling rate ofs = M*fs # input samp rate to decimator - taps = filter.firdes.low_pass_2(M, ofs, fs/2, fs/10, + taps = filter.firdes.low_pass_2(M, ofs, fs / 2, fs / 10, attenuation_dB=80, window=filter.firdes.WIN_BLACKMAN_hARRIS) signals = list() freqs = [0, 100, 200, -200, -100] - for i in xrange(len(freqs)): + for i in range(len(freqs)): data = sig_source_c(fs, freqs[i], 1, N) signals.append(blocks.vector_source_c(data)) pfb = filter.pfb_synthesizer_ccf(M, taps) snk = blocks.vector_sink_c() - for i in xrange(M): + for i in range(M): self.tb.connect(signals[i], (pfb,i)) self.tb.connect(pfb, snk) @@ -73,13 +75,13 @@ class test_pfb_synthesizer(gr_unittest.TestCase): Ntest = 1000 L = len(snk.data()) - t = map(lambda x: float(x)/ofs, xrange(L)) + t = [float(x) / ofs for x in range(L)] # Create known data as sum of complex sinusoids at freqs # of the output channels. freqs = [-2200, -1100, 0, 1100, 2200] expected_data = len(t)*[0,] - for i in xrange(len(t)): + for i in range(len(t)): expected_data[i] = math.cos(2.*math.pi*freqs[0]*t[i] + p3) + \ 1j*math.sin(2.*math.pi*freqs[0]*t[i] + p3) + \ math.cos(2.*math.pi*freqs[1]*t[i] + p4) + \ diff --git a/gr-filter/python/filter/qa_pm_remez.py b/gr-filter/python/filter/qa_pm_remez.py index af85f9eedf..dd1b514f7c 100755..100644 --- a/gr-filter/python/filter/qa_pm_remez.py +++ b/gr-filter/python/filter/qa_pm_remez.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + from gnuradio import gr, gr_unittest, filter import sys, math @@ -28,11 +30,11 @@ import sys, math def stopband_atten_to_dev (atten_db): """Convert a stopband attenuation in dB to an absolute value""" - return 10**(-atten_db/20) + return 10**(-atten_db / 20) def passband_ripple_to_dev (ripple_db): """Convert passband ripple spec expressed in dB to an absolute value""" - return (10**(ripple_db/20)-1)/(10**(ripple_db/20)+1) + return (10**(ripple_db / 20)-1) / (10**(ripple_db / 20)+1) # ---------------------------------------------------------------- @@ -55,10 +57,10 @@ def remezord (fcuts, mags, devs, fsamp = 2): nbands = nm if nm != nd: - raise ValueError, "Length of mags and devs must be equal" + raise ValueError("Length of mags and devs must be equal") if nf != 2 * (nbands - 1): - raise ValueError, "Length of f must be 2 * len (mags) - 2" + raise ValueError("Length of f must be 2 * len (mags) - 2") for i in range (len (mags)): if mags[i] != 0: # if not stopband, get relative deviation @@ -140,10 +142,10 @@ def lporder (freq1, freq2, delta_p, delta_s): class test_pm_remez(gr_unittest.TestCase): def setUp(self): - pass + pass def tearDown(self): - pass + pass def test_low_pass(self): gain = 1 @@ -184,4 +186,3 @@ class test_pm_remez(gr_unittest.TestCase): if __name__ == '__main__': gr_unittest.run(test_pm_remez, "test_pm_remez.xml") - diff --git a/gr-filter/python/filter/qa_rational_resampler.py b/gr-filter/python/filter/qa_rational_resampler.py index a03673d76f..c413bb10ed 100755..100644 --- a/gr-filter/python/filter/qa_rational_resampler.py +++ b/gr-filter/python/filter/qa_rational_resampler.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division + from gnuradio import gr, gr_unittest, filter, blocks import math import random @@ -28,7 +31,7 @@ import sys def random_floats(n): r = [] - for x in xrange(n): + for x in range(n): # r.append(float(random.randint(-32768, 32768))) r.append(float(random.random())) return tuple(r) @@ -72,10 +75,10 @@ def reference_interp_dec_filter(src_data, interp, decim, taps): class test_rational_resampler (gr_unittest.TestCase): def setUp(self): - random.seed(0) + random.seed(0) def tearDown(self): - pass + pass def test_000_1_to_1(self): @@ -84,7 +87,7 @@ class test_rational_resampler (gr_unittest.TestCase): xr = (1186, -112, 339, -460, -167, 582) expected_result = tuple([float(x) for x in xr]) - tb = gr.top_block() + tb = gr.top_block() src = blocks.vector_source_f(src_data) op = filter.rational_resampler_base_fff(1, 1, taps) dst = blocks.vector_sink_f() @@ -107,7 +110,7 @@ class test_rational_resampler (gr_unittest.TestCase): 1700.0,17000.0,170000.0, 0.0) expected_result = tuple([float(x) for x in xr]) - tb = gr.top_block() + tb = gr.top_block() src = blocks.vector_source_f(src_data) op = filter.rational_resampler_base_fff(interpolation, 1, taps) dst = blocks.vector_sink_f() @@ -124,7 +127,7 @@ class test_rational_resampler (gr_unittest.TestCase): expected_result = reference_interp_filter(src_data, interpolation, taps) - tb = gr.top_block() + tb = gr.top_block() src = blocks.vector_source_f(src_data) op = filter.rational_resampler_base_fff(interpolation, 1, taps) dst = blocks.vector_sink_f() @@ -144,7 +147,7 @@ class test_rational_resampler (gr_unittest.TestCase): expected_result = reference_dec_filter(src_data, decimation, taps) - tb = gr.top_block() + tb = gr.top_block() src = blocks.vector_source_f(src_data) op = filter.rational_resampler_base_fff(1, decimation, taps) dst = blocks.vector_sink_f() @@ -155,8 +158,8 @@ class test_rational_resampler (gr_unittest.TestCase): N = 10 offset = 10#len(taps)-1 - print expected_result[100+offset:100+offset+N] - print result_data[100:100+N] + print(expected_result[100+offset:100+offset+N]) + print(result_data[100:100+N]) #self.assertEqual(expected_result[offset:offset+N], result_data[0:N]) # FIXME disabled. Triggers hang on SuSE 10.0 @@ -167,9 +170,9 @@ class test_rational_resampler (gr_unittest.TestCase): random.seed(0) # we want reproducibility - for ntaps in xrange(1, MAX_TAPS + 1): - for decim in xrange(1, MAX_DECIM+1): - for ilen in xrange(ntaps + decim, ntaps + OUTPUT_LEN*decim): + for ntaps in range(1, MAX_TAPS + 1): + for decim in range(1, MAX_DECIM+1): + for ilen in range(ntaps + decim, ntaps + OUTPUT_LEN*decim): src_data = random_floats(ilen) taps = random_floats(ntaps) expected_result = reference_dec_filter(src_data, decim, taps) @@ -201,9 +204,9 @@ class test_rational_resampler (gr_unittest.TestCase): random.seed(0) # we want reproducibility - for ntaps in xrange(1, MAX_TAPS + 1): - for interp in xrange(1, MAX_INTERP+1): - for ilen in xrange(ntaps, ntaps + INPUT_LEN): + for ntaps in range(1, MAX_TAPS + 1): + for interp in range(1, MAX_INTERP+1): + for ilen in range(ntaps, ntaps + INPUT_LEN): src_data = random_floats(ilen) taps = random_floats(ntaps) expected_result = reference_interp_filter(src_data, interp, taps) @@ -236,7 +239,7 @@ class test_rational_resampler (gr_unittest.TestCase): expected_result = reference_interp_dec_filter(src_data, interp, decimation, taps) - tb = gr.top_block() + tb = gr.top_block() src = blocks.vector_source_f(src_data) op = filter.rational_resampler_base_fff(interp, decimation, taps) dst = blocks.vector_sink_f() @@ -246,11 +249,10 @@ class test_rational_resampler (gr_unittest.TestCase): result_data = dst.data() N = 1000 - offset = len(taps)/2 + offset = len(taps) // 2 self.assertFloatTuplesAlmostEqual(expected_result[offset:offset+N], result_data[0:N], 5) if __name__ == '__main__': # FIXME: Disabled, see ticket:210 gr_unittest.run(test_rational_resampler, "test_rational_resampler.xml") - diff --git a/gr-filter/python/filter/qa_single_pole_iir.py b/gr-filter/python/filter/qa_single_pole_iir.py index 5ca9bcdb45..a1f7cddb42 100755..100644 --- a/gr-filter/python/filter/qa_single_pole_iir.py +++ b/gr-filter/python/filter/qa_single_pole_iir.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, filter, blocks class test_single_pole_iir_filter(gr_unittest.TestCase): diff --git a/gr-filter/python/filter/rational_resampler.py b/gr-filter/python/filter/rational_resampler.py index 961ffc6880..fb07e26c04 100644 --- a/gr-filter/python/filter/rational_resampler.py +++ b/gr-filter/python/filter/rational_resampler.py @@ -19,11 +19,16 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + from gnuradio import gr, gru -import filter_swig as filter +from . import filter_swig as filter _plot = None + def design_filter(interpolation, decimation, fractional_bw): """ Given the interpolation rate, decimation rate and a fractional bandwidth, @@ -38,17 +43,17 @@ def design_filter(interpolation, decimation, fractional_bw): """ if fractional_bw >= 0.5 or fractional_bw <= 0: - raise ValueError, "Invalid fractional_bandwidth, must be in (0, 0.5)" + raise ValueError("Invalid fractional_bandwidth, must be in (0, 0.5)") beta = 7.0 halfband = 0.5 - rate = float(interpolation)/float(decimation) + rate = float(interpolation) / float(decimation) if(rate >= 1.0): trans_width = halfband - fractional_bw - mid_transition_band = halfband - trans_width/2.0 + mid_transition_band = halfband - trans_width / 2.0 else: trans_width = rate*(halfband - fractional_bw) - mid_transition_band = rate*halfband - trans_width/2.0 + mid_transition_band = rate*halfband - trans_width / 2.0 taps = filter.firdes.low_pass(interpolation, # gain interpolation, # Fs @@ -82,10 +87,10 @@ class _rational_resampler_base(gr.hier_block2): """ if not isinstance(interpolation, int) or interpolation < 1: - raise ValueError, "interpolation must be an integer >= 1" + raise ValueError("interpolation must be an integer >= 1") if not isinstance(decimation, int) or decimation < 1: - raise ValueError, "decimation must be an integer >= 1" + raise ValueError("decimation must be an integer >= 1") if taps is None and fractional_bw is None: fractional_bw = 0.4 @@ -108,11 +113,11 @@ class _rational_resampler_base(gr.hier_block2): taps = design_filter(interpolation, decimation, fractional_bw) self.resampler = resampler_base(interpolation, decimation, taps) - gr.hier_block2.__init__(self, "rational_resampler", - gr.io_signature(1, 1, self.resampler.input_signature().sizeof_stream_item(0)), - gr.io_signature(1, 1, self.resampler.output_signature().sizeof_stream_item(0))) + gr.hier_block2.__init__(self, "rational_resampler", + gr.io_signature(1, 1, self.resampler.input_signature().sizeof_stream_item(0)), + gr.io_signature(1, 1, self.resampler.output_signature().sizeof_stream_item(0))) - self.connect(self, self.resampler, self) + self.connect(self, self.resampler, self) def taps(self): return self.resampler.taps() @@ -124,7 +129,7 @@ class rational_resampler_fff(_rational_resampler_base): float input, float output and float taps. """ _rational_resampler_base.__init__(self, filter.rational_resampler_base_fff, - interpolation, decimation, taps, fractional_bw) + interpolation, decimation, taps, fractional_bw) class rational_resampler_ccf(_rational_resampler_base): def __init__(self, interpolation, decimation, taps=None, fractional_bw=None): diff --git a/gr-qtgui/apps/gr_constellation_plot b/gr-qtgui/apps/gr_constellation_plot index ff5db1a9a6..fe5bdb56df 100755 --- a/gr-qtgui/apps/gr_constellation_plot +++ b/gr-qtgui/apps/gr_constellation_plot @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + from gnuradio import gr from gnuradio import blocks from gnuradio.eng_arg import eng_float, intx @@ -31,13 +33,13 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4 and gr-qtgui." + print("Error: Program requires PyQt4 and gr-qtgui.") sys.exit(1) try: import scipy except ImportError: - print "Error: Scipy required (www.scipy.org)." + print("Error: Scipy required (www.scipy.org).") sys.exit(1) try: diff --git a/gr-qtgui/apps/plot_base.py b/gr-qtgui/apps/plot_base.py index 7a039e2135..ce409000bd 100644 --- a/gr-qtgui/apps/plot_base.py +++ b/gr-qtgui/apps/plot_base.py @@ -20,6 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + from gnuradio import gr, blocks import os, sys @@ -30,13 +34,13 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4 and gr-qtgui." + print("Error: Program requires PyQt4 and gr-qtgui.") sys.exit(1) try: import scipy except ImportError: - print "Error: Scipy required (www.scipy.org)." + print("Error: Scipy required (www.scipy.org).") sys.exit(1) try: @@ -64,8 +68,8 @@ def read_samples(filename, start, in_size, min_size, dtype, dtype_size): if(min_size > 0): if(len(data) < in_size): - print "Warning: read in {0} samples but asked for {1} samples.".format( - len(data), in_size) + print("Warning: read in {0} samples but asked for {1} samples.".format( + len(data), in_size)) else: # If we have to, append 0's to create min_size samples of data if(len(data) < min_size): @@ -108,8 +112,8 @@ def read_samples_c(filename, start, in_size, min_size=0): if(min_size > 0): if(len(data) < in_size): - print "Warning: read in {0} samples but asked for {1} samples.".format( - len(data), in_size) + print("Warning: read in {0} samples but asked for {1} samples.".format( + len(data), in_size)) else: # If we have to, append 0's to create min_size samples of data if(len(data) < min_size): @@ -119,9 +123,9 @@ def read_samples_c(filename, start, in_size, min_size=0): class source_ints_to_float(gr.hier_block2): def __init__(self, data): - gr.hier_block2.__init__(self, "ints_to_floats", - gr.io_signature(0, 0, 0), - gr.io_signature(1, 1, gr.sizeof_float)) + gr.hier_block2.__init__(self, "ints_to_floats", + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, gr.sizeof_float)) self.src = blocks.vector_source_i(data) self.cvt = blocks.int_to_float() self.connect(self.src, self.cvt, self) @@ -131,9 +135,9 @@ class source_ints_to_float(gr.hier_block2): class source_shorts_to_float(gr.hier_block2): def __init__(self, data): - gr.hier_block2.__init__(self, "shorts_to_floats", - gr.io_signature(0, 0, 0), - gr.io_signature(1, 1, gr.sizeof_float)) + gr.hier_block2.__init__(self, "shorts_to_floats", + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, gr.sizeof_float)) self.src = blocks.vector_source_s(data) self.cvt = blocks.short_to_float() self.connect(self.src, self.cvt, self) @@ -143,9 +147,9 @@ class source_shorts_to_float(gr.hier_block2): class source_chars_to_float(gr.hier_block2): def __init__(self, data): - gr.hier_block2.__init__(self, "chars_to_floats", - gr.io_signature(0, 0, 0), - gr.io_signature(1, 1, gr.sizeof_float)) + gr.hier_block2.__init__(self, "chars_to_floats", + gr.io_signature(0, 0, 0), + gr.io_signature(1, 1, gr.sizeof_float)) self.src = blocks.vector_source_b(data) self.cvt = blocks.char_to_float() self.connect(self.src, self.cvt, self) diff --git a/gr-qtgui/apps/plot_constellation_form.py b/gr-qtgui/apps/plot_constellation_form.py index 01c6ed1865..81cb76e233 100644 --- a/gr-qtgui/apps/plot_constellation_form.py +++ b/gr-qtgui/apps/plot_constellation_form.py @@ -20,6 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + import sys from gnuradio import filter @@ -27,7 +31,7 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4." + print("Error: Program requires PyQt4.") sys.exit(1) try: @@ -48,8 +52,8 @@ class plot_constellation_form(plot_form): # Set the bar to go from 0.001 to max self.ybar.setMinimum(1) self.ybar.setMaximum(self._pos_scale*self.top_block._y_max) - self.ybar.setSingleStep(self._pos_scale*(max(self.top_block._y_range/10, 0.010))) - self.ybar.setPageStep(self._pos_scale*(max(self.top_block._y_range/2, 0.010))) + self.ybar.setSingleStep(self._pos_scale*(max(self.top_block._y_range / 10, 0.010))) + self.ybar.setPageStep(self._pos_scale*(max(self.top_block._y_range / 2, 0.010))) self.auto_scale = QtGui.QCheckBox("Auto Scale", self) if(self.top_block._auto_scale): diff --git a/gr-qtgui/apps/plot_form.py b/gr-qtgui/apps/plot_form.py index 931565bd3e..af262b97c3 100644 --- a/gr-qtgui/apps/plot_form.py +++ b/gr-qtgui/apps/plot_form.py @@ -20,11 +20,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4." + print("Error: Program requires PyQt4.") sys.exit(1) import numpy @@ -129,8 +133,8 @@ class plot_form(QtGui.QWidget): self.ybar = QtGui.QSlider(QtCore.Qt.Vertical, self) self.ybar.setMinimum(self._pos_scale*_ymin) self.ybar.setMaximum(self._pos_scale*_ymax) - self.ybar.setSingleStep(self._pos_scale*(_yrng/10)) - self.ybar.setPageStep(self._pos_scale*(_yrng/2)) + self.ybar.setSingleStep(self._pos_scale*(_yrng / 10)) + self.ybar.setPageStep(self._pos_scale*(_yrng / 2)) self.ybar.setValue(self._pos_scale*_ymax) self.connect(self.ybar, QtCore.SIGNAL("valueChanged(int)"), self.update_yaxis_slider) @@ -171,7 +175,7 @@ class plot_form(QtGui.QWidget): self._style_edit = [] self._marker_edit = [] self._alpha_edit = [] - for n in xrange(self.top_block._nsigs): + for n in range(self.top_block._nsigs): self._line_pages.append(QtGui.QDialog()) self._line_forms.append(QtGui.QFormLayout(self._line_pages[-1])) @@ -341,7 +345,7 @@ class plot_form(QtGui.QWidget): def update_yaxis_slider(self, value): if(not self.top_block._auto_scale): - value = value/self._pos_scale + value = value / self._pos_scale self.top_block._y_value = value self._y_min = value - self.top_block._y_range self._y_max = value diff --git a/gr-qtgui/apps/plot_psd_base.py b/gr-qtgui/apps/plot_psd_base.py index c3c03ec977..896371affb 100644 --- a/gr-qtgui/apps/plot_psd_base.py +++ b/gr-qtgui/apps/plot_psd_base.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + from gnuradio import gr, blocks from gnuradio.eng_arg import eng_float, intx from argparse import ArgumentParser @@ -30,13 +33,13 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4 and gr-qtgui." + print("Error: Program requires PyQt4 and gr-qtgui.") sys.exit(1) try: import scipy except ImportError: - print "Error: Scipy required (www.scipy.org)." + print("Error: Scipy required (www.scipy.org).") sys.exit(1) try: @@ -76,8 +79,8 @@ class plot_base(gr.top_block): n = 0 self.srcs = list() - self._data_min = sys.maxint - self._data_max = -sys.maxint - 1 + self._data_min = sys.maxsize + self._data_max = -sys.maxsize - 1 for f in self._filelist: data,_min,_max = self.read_samples(f, self._start, self._nsamps, self._psd_size) @@ -127,8 +130,8 @@ class plot_base(gr.top_block): self._start = newstart - self._data_min = sys.maxint - self._data_max = -sys.maxint - 1 + self._data_min = sys.maxsize + self._data_max = -sys.maxsize - 1 for s,f in zip(self.srcs, self._filelist): data,_min,_max = self.read_samples(f, self._start, newnsamps, self._psd_size) if(_min < self._data_min): diff --git a/gr-qtgui/apps/plot_psd_form.py b/gr-qtgui/apps/plot_psd_form.py index 2d1fcd10bc..93166f4faf 100644 --- a/gr-qtgui/apps/plot_psd_form.py +++ b/gr-qtgui/apps/plot_psd_form.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + import sys from gnuradio import filter @@ -27,7 +30,7 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4." + print("Error: Program requires PyQt4.") sys.exit(1) try: diff --git a/gr-qtgui/apps/plot_spectrogram_base.py b/gr-qtgui/apps/plot_spectrogram_base.py index f568100719..3527f3fa7b 100644 --- a/gr-qtgui/apps/plot_spectrogram_base.py +++ b/gr-qtgui/apps/plot_spectrogram_base.py @@ -20,6 +20,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + from gnuradio import gr, blocks from gnuradio.eng_arg import eng_float, intx from argparse import ArgumentParser @@ -30,13 +34,13 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4 and gr-qtgui." + print("Error: Program requires PyQt4 and gr-qtgui.") sys.exit(1) try: import scipy except ImportError: - print "Error: Scipy required (www.scipy.org)." + print("Error: Scipy required (www.scipy.org).") sys.exit(1) try: @@ -76,8 +80,8 @@ class plot_base(gr.top_block): n = 0 self.srcs = list() - self._data_min = sys.maxint - self._data_max = -sys.maxint - 1 + self._data_min = sys.maxsize + self._data_max = -sys.maxsize - 1 for f in self._filelist: data,_min,_max = self.read_samples(f, self._start, self._nsamps, self._psd_size) @@ -100,7 +104,7 @@ class plot_base(gr.top_block): self.connect(s, (self.gui_snk, i+1)) self.gui_snk.set_update_time(0); - self.gui_snk.set_time_per_fft(self._psd_size/self._samp_rate) + self.gui_snk.set_time_per_fft(self._psd_size / self._samp_rate) self.gui_snk.enable_menu(False) self.gui_snk.set_fft_average(self._avg) @@ -127,13 +131,13 @@ class plot_base(gr.top_block): self.stop() self.wait() self.gui_snk.clear_data() - self.gui_snk.set_time_per_fft(self._psd_size/self._samp_rate) + self.gui_snk.set_time_per_fft(self._psd_size / self._samp_rate) self._start = newstart self._nsamps = newnsamps - self._data_min = sys.maxint - self._data_max = -sys.maxint - 1 + self._data_min = sys.maxsize + self._data_max = -sys.maxsize - 1 for s,f in zip(self.srcs, self._filelist): data,_min,_max = self.read_samples(f, self._start, newnsamps, self._psd_size) if(_min < self._data_min): diff --git a/gr-qtgui/apps/plot_spectrogram_form.py b/gr-qtgui/apps/plot_spectrogram_form.py index 17cb0335bd..6d1b17de67 100644 --- a/gr-qtgui/apps/plot_spectrogram_form.py +++ b/gr-qtgui/apps/plot_spectrogram_form.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + import sys from gnuradio import filter @@ -27,7 +30,7 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4." + print("Error: Program requires PyQt4.") sys.exit(1) try: @@ -113,7 +116,7 @@ class plot_spectrogram_form(plot_form): self._style_edit = [] self._marker_edit = [] self._alpha_edit = [] - for n in xrange(self.top_block._nsigs): + for n in range(self.top_block._nsigs): self._line_pages.append(QtGui.QDialog()) self._line_forms.append(QtGui.QFormLayout(self._line_pages[-1])) diff --git a/gr-qtgui/apps/plot_time_base.py b/gr-qtgui/apps/plot_time_base.py index cfbe5dc6cb..7078e332cd 100644 --- a/gr-qtgui/apps/plot_time_base.py +++ b/gr-qtgui/apps/plot_time_base.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + from gnuradio import gr, blocks from gnuradio.eng_arg import eng_float, intx from argparse import ArgumentParser @@ -30,13 +33,13 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4 and gr-qtgui." + print("Error: Program requires PyQt4 and gr-qtgui.") sys.exit(1) try: import scipy except ImportError: - print "Error: Scipy required (www.scipy.org)." + print("Error: Scipy required (www.scipy.org).") sys.exit(1) try: @@ -75,8 +78,8 @@ class plot_base(gr.top_block): n = 0 self.srcs = list() - self._data_min = sys.maxint - self._data_max = -sys.maxint - 1 + self._data_min = sys.maxsize + self._data_max = -sys.maxsize - 1 for f in self._filelist: data,_min,_max = self.read_samples(f, self._start, self._nsamps) if(_min < self._data_min): @@ -131,8 +134,8 @@ class plot_base(gr.top_block): self._start = newstart - self._data_min = sys.maxint - self._data_max = -sys.maxint - 1 + self._data_min = sys.maxsize + self._data_max = -sys.maxsize - 1 for s,f in zip(self.srcs, self._filelist): data,_min,_max = self.read_samples(f, self._start, newnsamps) if(_min < self._data_min): diff --git a/gr-qtgui/apps/plot_time_form.py b/gr-qtgui/apps/plot_time_form.py index 0ab94e6cfe..0a16aa6241 100644 --- a/gr-qtgui/apps/plot_time_form.py +++ b/gr-qtgui/apps/plot_time_form.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + import sys from gnuradio import filter @@ -27,7 +30,7 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4." + print("Error: Program requires PyQt4.") sys.exit(1) try: @@ -70,7 +73,7 @@ class plot_time_form(plot_form): index = self._qwtmarkers['Circle']+1 else: index = self._qwtmarkers['None']+1 - for n in xrange(self.top_block._nsigs): + for n in range(self.top_block._nsigs): self._marker_edit[n].setCurrentIndex(index) def update_samp_rate(self): diff --git a/gr-qtgui/apps/plot_time_raster_base.py b/gr-qtgui/apps/plot_time_raster_base.py index e84b84c295..4eb6ec4613 100644 --- a/gr-qtgui/apps/plot_time_raster_base.py +++ b/gr-qtgui/apps/plot_time_raster_base.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + from gnuradio import gr, blocks from gnuradio.eng_arg import eng_float, intx from argparse import ArgumentParser @@ -30,13 +33,13 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4 and gr-qtgui." + print("Error: Program requires PyQt4 and gr-qtgui.") sys.exit(1) try: import scipy except ImportError: - print "Error: Scipy required (www.scipy.org)." + print("Error: Scipy required (www.scipy.org).") sys.exit(1) try: @@ -75,8 +78,8 @@ class plot_base(gr.top_block): n = 0 self.srcs = list() - self._data_min = sys.maxint - self._data_max = -sys.maxint - 1 + self._data_min = sys.maxsize + self._data_max = -sys.maxsize - 1 for f in self._filelist: data,_min,_max = self.read_samples(f, self._start, self._nsamps) if(_min < self._data_min): @@ -129,8 +132,8 @@ class plot_base(gr.top_block): self._start = newstart - self._data_min = sys.maxint - self._data_max = -sys.maxint - 1 + self._data_min = sys.maxsize + self._data_max = -sys.maxsize - 1 for s,f in zip(self.srcs, self._filelist): data,_min,_max = self.read_samples(f, self._start, newnsamps) if(_min < self._data_min): diff --git a/gr-qtgui/apps/plot_time_raster_form.py b/gr-qtgui/apps/plot_time_raster_form.py index 32fbba0765..fd27d9574d 100644 --- a/gr-qtgui/apps/plot_time_raster_form.py +++ b/gr-qtgui/apps/plot_time_raster_form.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + import sys, math from gnuradio import filter @@ -27,7 +30,7 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4." + print("Error: Program requires PyQt4.") sys.exit(1) try: @@ -81,7 +84,7 @@ class plot_time_raster_form(plot_form): self._style_edit = [] self._marker_edit = [] self._alpha_edit = [] - for n in xrange(self.top_block._nsigs): + for n in range(self.top_block._nsigs): self._line_pages.append(QtGui.QDialog()) self._line_forms.append(QtGui.QFormLayout(self._line_pages[-1])) @@ -153,5 +156,3 @@ class plot_time_raster_form(plot_form): nsamps = int(math.ceil(self.top_block._ncols*(n+1))) self.top_block.reset(self._start, nsamps) - - diff --git a/gr-qtgui/apps/uhd_display.py b/gr-qtgui/apps/uhd_display.py index 0e0c8a177d..58494f3af3 100755..100644 --- a/gr-qtgui/apps/uhd_display.py +++ b/gr-qtgui/apps/uhd_display.py @@ -20,6 +20,9 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import filter from gnuradio import blocks @@ -34,14 +37,14 @@ try: from PyQt4 import QtGui, QtCore import sip except ImportError: - print "Error: Program requires PyQt4 and gr-qtgui." + print("Error: Program requires PyQt4 and gr-qtgui.") sys.exit(1) try: from usrp_display_qtgui import Ui_MainWindow except ImportError: - print "Error: could not find usrp_display_qtgui.py:" - print "\t\"pyuic4 usrp_display_qtgui.ui -o usrp_display_qtgui.py\"" + print("Error: could not find usrp_display_qtgui.py:") + print("\t\"pyuic4 usrp_display_qtgui.ui -o usrp_display_qtgui.py\"") sys.exit(1) @@ -182,13 +185,13 @@ class my_top_block(gr.top_block): if options.gain is None: # if no gain was specified, use the mid-point in dB g = self.u.get_gain_range() - options.gain = float(g.start()+g.stop())/2 + options.gain = float(g.start()+g.stop()) / 2 self.set_gain(options.gain) if options.freq is None: # if no freq was specified, use the mid-point r = self.u.get_freq_range() - options.freq = float(r.start()+r.stop())/2 + options.freq = float(r.start()+r.stop()) / 2 self.set_frequency(options.freq) self._fftsize = options.fft_size @@ -212,9 +215,9 @@ class my_top_block(gr.top_block): self.connect(self.u, self.amp, self.snk) if self.show_debug_info: - print "Bandwidth: ", self.u.get_samp_rate() - print "Center Freq: ", self.u.get_center_freq() - print "Freq Range: ", self.u.get_freq_range() + print("Bandwidth: ", self.u.get_samp_rate()) + print("Center Freq: ", self.u.get_center_freq()) + print("Freq Range: ", self.u.get_freq_range()) # Get the reference pointer to the SpectrumDisplayForm QWidget # Wrap the pointer as a PyQt SIP object diff --git a/gr-qtgui/apps/usrp_display_qtgui.py b/gr-qtgui/apps/usrp_display_qtgui.py index 4c9de3a53c..68c5d6cfb7 100644 --- a/gr-qtgui/apps/usrp_display_qtgui.py +++ b/gr-qtgui/apps/usrp_display_qtgui.py @@ -7,6 +7,7 @@ # # WARNING! All changes made in this file will be lost! +from __future__ import unicode_literals from PyQt4 import QtCore, QtGui class Ui_MainWindow(object): diff --git a/gr-qtgui/examples/pyqt_const_c.py b/gr-qtgui/examples/pyqt_const_c.py index 0bb6c20d59..e789e013bf 100755..100644 --- a/gr-qtgui/examples/pyqt_const_c.py +++ b/gr-qtgui/examples/pyqt_const_c.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr, filter from gnuradio import blocks import sys @@ -109,14 +111,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq1Edit.text()) self.signal1.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp1EditText(self): try: newamp = float(self.amp1Edit.text()) self.signal1.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def freq2EditText(self): @@ -124,14 +126,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq2Edit.text()) self.signal2.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp2EditText(self): try: newamp = float(self.amp2Edit.text()) self.signal2.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") class my_top_block(gr.top_block): diff --git a/gr-qtgui/examples/pyqt_example_c.py b/gr-qtgui/examples/pyqt_example_c.py index 89ca7b2820..5854d968c0 100755..100644 --- a/gr-qtgui/examples/pyqt_example_c.py +++ b/gr-qtgui/examples/pyqt_example_c.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr, filter from gnuradio import blocks import sys @@ -110,14 +112,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq1Edit.text()) self.signal1.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp1EditText(self): try: newamp = float(self.amp1Edit.text()) self.signal1.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def freq2EditText(self): @@ -125,14 +127,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq2Edit.text()) self.signal2.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp2EditText(self): try: newamp = float(self.amp2Edit.text()) self.signal2.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") class my_top_block(gr.top_block): diff --git a/gr-qtgui/examples/pyqt_example_f.py b/gr-qtgui/examples/pyqt_example_f.py index 77a7478aa2..e2f41b57cf 100755..100644 --- a/gr-qtgui/examples/pyqt_example_f.py +++ b/gr-qtgui/examples/pyqt_example_f.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr, filter from gnuradio import blocks import sys @@ -104,14 +106,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq1Edit.text()) self.signal1.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp1EditText(self): try: newamp = float(self.amp1Edit.text()) self.signal1.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def freq2EditText(self): @@ -119,14 +121,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq2Edit.text()) self.signal2.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp2EditText(self): try: newamp = float(self.amp2Edit.text()) self.signal2.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") class my_top_block(gr.top_block): diff --git a/gr-qtgui/examples/pyqt_freq_c.py b/gr-qtgui/examples/pyqt_freq_c.py index 954a078df8..9140bbb882 100755..100644 --- a/gr-qtgui/examples/pyqt_freq_c.py +++ b/gr-qtgui/examples/pyqt_freq_c.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr, filter from gnuradio import blocks import sys @@ -110,14 +112,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq1Edit.text()) self.signal1.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp1EditText(self): try: newamp = float(self.amp1Edit.text()) self.signal1.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def freq2EditText(self): @@ -125,14 +127,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq2Edit.text()) self.signal2.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp2EditText(self): try: newamp = float(self.amp2Edit.text()) self.signal2.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") class my_top_block(gr.top_block): diff --git a/gr-qtgui/examples/pyqt_freq_f.py b/gr-qtgui/examples/pyqt_freq_f.py index d7d389b736..06a6d95b0b 100755..100644 --- a/gr-qtgui/examples/pyqt_freq_f.py +++ b/gr-qtgui/examples/pyqt_freq_f.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr, filter from gnuradio import blocks import sys @@ -105,14 +107,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq1Edit.text()) self.signal1.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp1EditText(self): try: newamp = float(self.amp1Edit.text()) self.signal1.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def freq2EditText(self): @@ -120,14 +122,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq2Edit.text()) self.signal2.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp2EditText(self): try: newamp = float(self.amp2Edit.text()) self.signal2.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") class my_top_block(gr.top_block): diff --git a/gr-qtgui/examples/pyqt_histogram_f.py b/gr-qtgui/examples/pyqt_histogram_f.py index 81f7b9d40b..cf2f59b9a3 100755..100644 --- a/gr-qtgui/examples/pyqt_histogram_f.py +++ b/gr-qtgui/examples/pyqt_histogram_f.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks import sys @@ -118,21 +120,21 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq1Edit.text()) self.signal1.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp1EditText(self): try: newamp = float(self.amp1Edit.text()) self.signal1.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def amp2EditText(self): try: newamp = float(self.amp2Edit.text()) self.signal2.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def set_nsamps(self): res = self.hist_npts.text().toInt() diff --git a/gr-qtgui/examples/pyqt_time_c.py b/gr-qtgui/examples/pyqt_time_c.py index b595c8ff85..8196b62dcc 100755..100644 --- a/gr-qtgui/examples/pyqt_time_c.py +++ b/gr-qtgui/examples/pyqt_time_c.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks import sys @@ -110,14 +112,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq1Edit.text()) self.signal1.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp1EditText(self): try: newamp = float(self.amp1Edit.text()) self.signal1.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def freq2EditText(self): @@ -125,14 +127,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq2Edit.text()) self.signal2.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp2EditText(self): try: newamp = float(self.amp2Edit.text()) self.signal2.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") class my_top_block(gr.top_block): diff --git a/gr-qtgui/examples/pyqt_time_f.py b/gr-qtgui/examples/pyqt_time_f.py index 3689ebff54..9fc9dd5e4c 100755..100644 --- a/gr-qtgui/examples/pyqt_time_f.py +++ b/gr-qtgui/examples/pyqt_time_f.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks import sys @@ -104,14 +106,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq1Edit.text()) self.signal1.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp1EditText(self): try: newamp = float(self.amp1Edit.text()) self.signal1.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def freq2EditText(self): @@ -119,14 +121,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq2Edit.text()) self.signal2.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp2EditText(self): try: newamp = float(self.amp2Edit.text()) self.signal2.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") class my_top_block(gr.top_block): diff --git a/gr-qtgui/examples/pyqt_time_raster_b.py b/gr-qtgui/examples/pyqt_time_raster_b.py index 7a94400283..278cb90ed0 100755..100644 --- a/gr-qtgui/examples/pyqt_time_raster_b.py +++ b/gr-qtgui/examples/pyqt_time_raster_b.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks from gnuradio import blocks @@ -30,7 +32,7 @@ try: from PyQt5 import QtWidgets, Qt import sip except ImportError: - print "Error: Program requires PyQt5 and gr-qtgui." + print("Error: Program requires PyQt5 and gr-qtgui.") sys.exit(1) class dialog_box(QtWidgets.QWidget): diff --git a/gr-qtgui/examples/pyqt_time_raster_f.py b/gr-qtgui/examples/pyqt_time_raster_f.py index 0f9de94bcb..249ec07010 100755..100644 --- a/gr-qtgui/examples/pyqt_time_raster_f.py +++ b/gr-qtgui/examples/pyqt_time_raster_f.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr from gnuradio import blocks import sys @@ -29,7 +31,7 @@ try: from PyQt5 import QtWidgets, Qt import sip except ImportError: - print "Error: Program requires PyQt5 and gr-qtgui." + print("Error: Program requires PyQt5 and gr-qtgui.") sys.exit(1) class dialog_box(QtWidgets.QWidget): diff --git a/gr-qtgui/examples/pyqt_waterfall_c.py b/gr-qtgui/examples/pyqt_waterfall_c.py index 3f7119f97f..2c183a99ac 100755..100644 --- a/gr-qtgui/examples/pyqt_waterfall_c.py +++ b/gr-qtgui/examples/pyqt_waterfall_c.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr, filter from gnuradio import blocks import sys @@ -110,14 +112,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq1Edit.text()) self.signal1.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp1EditText(self): try: newamp = float(self.amp1Edit.text()) self.signal1.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def freq2EditText(self): @@ -125,14 +127,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq2Edit.text()) self.signal2.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp2EditText(self): try: newamp = float(self.amp2Edit.text()) self.signal2.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") class my_top_block(gr.top_block): diff --git a/gr-qtgui/examples/pyqt_waterfall_f.py b/gr-qtgui/examples/pyqt_waterfall_f.py index 71c72afad6..660e7595f2 100755..100644 --- a/gr-qtgui/examples/pyqt_waterfall_f.py +++ b/gr-qtgui/examples/pyqt_waterfall_f.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals from gnuradio import gr, filter from gnuradio import blocks import sys @@ -104,14 +106,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq1Edit.text()) self.signal1.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp1EditText(self): try: newamp = float(self.amp1Edit.text()) self.signal1.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") def freq2EditText(self): @@ -119,14 +121,14 @@ class control_box(QtWidgets.QWidget): newfreq = float(self.freq2Edit.text()) self.signal2.set_frequency(newfreq) except ValueError: - print "Bad frequency value entered" + print("Bad frequency value entered") def amp2EditText(self): try: newamp = float(self.amp2Edit.text()) self.signal2.set_amplitude(newamp) except ValueError: - print "Bad amplitude value entered" + print("Bad amplitude value entered") class my_top_block(gr.top_block): diff --git a/gr-qtgui/python/qtgui/CMakeLists.txt b/gr-qtgui/python/qtgui/CMakeLists.txt index 5df3a7d91b..f3fc70351d 100644 --- a/gr-qtgui/python/qtgui/CMakeLists.txt +++ b/gr-qtgui/python/qtgui/CMakeLists.txt @@ -51,6 +51,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-qtgui/python/qtgui/__init__.py b/gr-qtgui/python/qtgui/__init__.py index 8b60dc6dbe..c5527410aa 100644 --- a/gr-qtgui/python/qtgui/__init__.py +++ b/gr-qtgui/python/qtgui/__init__.py @@ -22,17 +22,18 @@ ''' Provides a GUI interface using the QT backend. ''' +from __future__ import unicode_literals # The presence of this file turns this directory into a Python package import os try: - from qtgui_swig import * + from .qtgui_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from qtgui_swig import * + from .qtgui_swig import * -from range import Range, RangeWidget -import util +from .range import Range, RangeWidget +from . import util diff --git a/gr-qtgui/python/qtgui/qa_qtgui.py b/gr-qtgui/python/qtgui/qa_qtgui.py index d98cf1fc28..e46301071b 100755..100644 --- a/gr-qtgui/python/qtgui/qa_qtgui.py +++ b/gr-qtgui/python/qtgui/qa_qtgui.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, qtgui class test_qtgui(gr_unittest.TestCase): diff --git a/gr-qtgui/python/qtgui/util.py.cmakein b/gr-qtgui/python/qtgui/util.py.cmakein index ec654d9ba2..4014fc1db1 100644 --- a/gr-qtgui/python/qtgui/util.py.cmakein +++ b/gr-qtgui/python/qtgui/util.py.cmakein @@ -21,7 +21,10 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + @PY_QT_IMPORT@ + from gnuradio import gr def check_set_qss(): @@ -31,4 +34,4 @@ def check_set_qss(): try: app.setStyleSheet(open(qssfile).read()) except: - print "WARNING: bad QSS file, %s"%(qssfile) + print("WARNING: bad QSS file, %s"%(qssfile)) diff --git a/gr-trellis/doc/make_numbered_listing.py b/gr-trellis/doc/make_numbered_listing.py index c295dc8763..09a82cfaa4 100755..100644 --- a/gr-trellis/doc/make_numbered_listing.py +++ b/gr-trellis/doc/make_numbered_listing.py @@ -1,5 +1,6 @@ #!/usr/bin/env python +from __future__ import unicode_literals import sys import os, os.path from optparse import OptionParser diff --git a/gr-trellis/doc/test_tcm.py b/gr-trellis/doc/test_tcm.py index 61ab00f1c8..e9a0ba59eb 100644 --- a/gr-trellis/doc/test_tcm.py +++ b/gr-trellis/doc/test_tcm.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import trellis, digital, blocks @@ -20,14 +23,14 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): # TX src = blocks.lfsr_32k_source_s() - src_head = blocks.head (gr.sizeof_short,Kb/16) # packet size in shorts + src_head = blocks.head (gr.sizeof_short,Kb / 16) # packet size in shorts s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol,gr.GR_MSB_FIRST) # unpack shorts to symbols compatible with the FSM input cardinality enc = trellis.encoder_ss(f,0) # initial state = 0 mod = digital.chunks_to_symbols_sf(constellation,dimensionality) # CHANNEL add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) + noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0 / 2),seed) # RX metrics = trellis.metrics_f(f.O(),dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # data preprocessing to generate metrics for Viterbi @@ -67,31 +70,31 @@ def main(args): # system parameters f=trellis.fsm(fname) # get the FSM specification from a file Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) - bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps + bitspersymbol = int(round(math.log(f.I()) / math.log(2))) # bits per FSM input symbol + K=Kb / bitspersymbol # packet size in trellis steps modulation = fsm_utils.psk4 # see fsm_utlis.py for available predefined modulations dimensionality = modulation[0] constellation = modulation[1] - if len(constellation)/dimensionality != f.O(): + if len(constellation) / dimensionality != f.O(): sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') sys.exit (1) # calculate average symbol energy Es = 0 for i in range(len(constellation)): Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # noise variance + Es = Es / (old_div(len(constellation,dimensionality))) + N0=Es / pow(10.0,old_div(esn0_db,10.0)); # noise variance tot_s=0 terr_s=0 for i in range(rep): - (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-long(666+i)) # run experiment with different seed to get different noise realizations + (s,e)=run_test(f,Kb,bitspersymbol,K,dimensionality,constellation,N0,-int(666+i)) # run experiment with different seed to get different noise realizations tot_s=tot_s+s terr_s=terr_s+e if (i%100==0): - print i,s,e,tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + print(i,s,e,tot_s,terr_s, '%e' % ((1.0*terr_s) / tot_s)) # estimate of the (short) error rate - print tot_s,terr_s, '%e' % ((1.0*terr_s)/tot_s) + print(tot_s,terr_s, '%e' % ((1.0*terr_s) / tot_s)) if __name__ == '__main__': diff --git a/gr-trellis/doc/test_viterbi_equalization1.py b/gr-trellis/doc/test_viterbi_equalization1.py index c1a831d0bb..95cb119edf 100755..100644 --- a/gr-trellis/doc/test_viterbi_equalization1.py +++ b/gr-trellis/doc/test_viterbi_equalization1.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import trellis, digital, filter, blocks @@ -34,7 +37,7 @@ def run_test (f,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constel # CHANNEL isi = filter.fir_filter_fff(1,channel) add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) + noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0 / 2),seed) # RX skip = blocks.skiphead(gr.sizeof_float, L) # skip the first L samples since you know they are coming from the L zero symbols @@ -78,14 +81,14 @@ def main(args): modulation = fsm_utils.pam4 # see fsm_utlis.py for available predefined modulations channel = fsm_utils.c_channel # see fsm_utlis.py for available predefined test channels f=trellis.fsm(len(modulation[1]),len(channel)) # generate the FSM automatically - bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps + bitspersymbol = int(round(math.log(f.I()) / math.log(2))) # bits per FSM input symbol + K=Kb / bitspersymbol # packet size in trellis steps tot_channel = fsm_utils.make_isi_lookup(modulation,channel,True) # generate the lookup table (normalize energy to 1) dimensionality = tot_channel[0] tot_constellation = tot_channel[1] - N0=pow(10.0,-esn0_db/10.0); # noise variance - if len(tot_constellation)/dimensionality != f.O(): + N0=pow(10.0,-esn0_db / 10.0); # noise variance + if len(tot_constellation) / dimensionality != f.O(): sys.stderr.write ('Incompatible FSM output cardinality and lookup table size.\n') sys.exit (1) @@ -94,14 +97,14 @@ def main(args): terr_p=0 # total number of packets in error for i in range(rep): - (s,e)=run_test(f,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constellation,N0,-long(666+i)) # run experiment with different seed to get different data and noise realizations + (s,e)=run_test(f,Kb,bitspersymbol,K,channel,modulation,dimensionality,tot_constellation,N0,-int(666+i)) # run experiment with different seed to get different data and noise realizations tot_s=tot_s+s terr_s=terr_s+e terr_p=terr_p+(terr_s!=0) if ((i+1)%100==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) + print(i+1,terr_p, '%.2e' % ((1.0*terr_p) / (i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s) / tot_s)) # estimate of the (short or symbol) error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s)/tot_s) + print(rep,terr_p, '%.2e' % ((1.0*terr_p) / (i+1)),tot_s,terr_s, '%.2e' % ((1.0*terr_s) / tot_s)) if __name__ == '__main__': diff --git a/gr-trellis/examples/python/test_tcm.py b/gr-trellis/examples/python/test_tcm.py index dfc565616e..e2eb87fcd7 100755..100644 --- a/gr-trellis/examples/python/test_tcm.py +++ b/gr-trellis/examples/python/test_tcm.py @@ -1,5 +1,8 @@ #!/usr/bin/env python +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import trellis, digital, blocks from gnuradio import eng_notation @@ -33,7 +36,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): # CHANNEL add = blocks.add_ff() - noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0/2),long(seed)) + noise = analog.noise_source_f(analog.GR_GAUSSIAN,math.sqrt(N0 / 2),int(seed)) # RX va = trellis.viterbi_combined_fs(f,K,0,0,dimensionality,constellation,digital.TRELLIS_EUCLIDEAN) # Put -1 if the Initial/Final states are not set. @@ -56,7 +59,7 @@ def run_test (f,Kb,bitspersymbol,K,dimensionality,constellation,N0,seed): #print "final state = " , enc.ST() if len(dst.data()) != len(packet): - print "Error: not enough data:", len(dst.data()), len(packet) + print("Error: not enough data:", len(dst.data()), len(packet)) ntotal=len(packet) nwrong = sum(abs(packet-numpy.array(dst.data()))); return (ntotal,nwrong,abs(packet-numpy.array(dst.data()))) @@ -73,7 +76,7 @@ def main(): (options, args) = parser.parse_args () if len(args) != 0: parser.print_help() - raise SystemExit, 1 + raise SystemExit(1) fname=options.fsm_file esn0_db=float(options.esn0) @@ -84,20 +87,20 @@ def main(): # alternatively you can specify the fsm from its generator matrix #f=trellis.fsm(1,2,[5,7]) Kb=1024*16 # packet size in bits (make it multiple of 16 so it can be packed in a short) - bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol - K=Kb/bitspersymbol # packet size in trellis steps + bitspersymbol = int(round(math.log(f.I()) / math.log(2))) # bits per FSM input symbol + K=Kb / bitspersymbol # packet size in trellis steps modulation = fsm_utils.psk4 # see fsm_utlis.py for available predefined modulations dimensionality = modulation[0] constellation = modulation[1] - if len(constellation)/dimensionality != f.O(): + if len(constellation) / dimensionality != f.O(): sys.stderr.write ('Incompatible FSM output cardinality and modulation size.\n') sys.exit (1) # calculate average symbol energy Es = 0 for i in range(len(constellation)): Es = Es + constellation[i]**2 - Es = Es / (len(constellation)/dimensionality) - N0=Es/pow(10.0,esn0_db/10.0); # calculate noise variance + Es = Es / (old_div(len(constellation,dimensionality))) + N0=Es / pow(10.0,old_div(esn0_db,10.0)); # calculate noise variance tot_b=0 # total number of transmitted bits terr_b=0 # total number of bits in error @@ -108,14 +111,14 @@ def main(): terr_b=terr_b+e terr_p=terr_p+(e!=0) if ((i+1)%100==0) : # display progress - print i+1,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_b,terr_b, '%.2e' % ((1.0*terr_b)/tot_b) + print(i+1,terr_p, '%.2e' % ((1.0*terr_p) / (i+1)),tot_b,terr_b, '%.2e' % ((1.0*terr_b) / tot_b)) if e!=0: - print "rep=",i, e + print("rep=",i, e) for k in range(Kb): if pattern[k]!=0: - print k + print(k) # estimate of the bit error rate - print rep,terr_p, '%.2e' % ((1.0*terr_p)/(i+1)),tot_b,terr_b, '%.2e' % ((1.0*terr_b)/tot_b) + print(rep,terr_p, '%.2e' % ((1.0*terr_p) / (i+1)),tot_b,terr_b, '%.2e' % ((1.0*terr_b) / tot_b)) diff --git a/gr-trellis/python/trellis/CMakeLists.txt b/gr-trellis/python/trellis/CMakeLists.txt index 10fd9d5c0e..94a160b310 100644 --- a/gr-trellis/python/trellis/CMakeLists.txt +++ b/gr-trellis/python/trellis/CMakeLists.txt @@ -44,6 +44,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-trellis/python/trellis/__init__.py b/gr-trellis/python/trellis/__init__.py index a6b5ed0038..445a381424 100644 --- a/gr-trellis/python/trellis/__init__.py +++ b/gr-trellis/python/trellis/__init__.py @@ -21,15 +21,16 @@ ''' Blocks and utilities for trellis coding and related. ''' +from __future__ import unicode_literals # The presence of this file turns this directory into a Python package import os try: - from trellis_swig import * + from .trellis_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from trellis_swig import * + from .trellis_swig import * # import any pure python here diff --git a/gr-trellis/python/trellis/fsm_utils.py b/gr-trellis/python/trellis/fsm_utils.py index 72aa1d3660..efc526c0e7 100755..100644 --- a/gr-trellis/python/trellis/fsm_utils.py +++ b/gr-trellis/python/trellis/fsm_utils.py @@ -20,11 +20,13 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals -import re import math import sys -import operator + import numpy #from gnuradio import trellis @@ -32,7 +34,7 @@ import numpy try: import scipy.linalg except ImportError: - print "Error: Program requires scipy (see: www.scipy.org)." + print("Error: Program requires scipy (see: www.scipy.org).") sys.exit(1) @@ -43,13 +45,13 @@ except ImportError: # to base 'base' (most significant symbol first). ###################################################################### def dec2base(num,base,l): - s=range(l) + s=list(range(l)) n=num for i in range(l): s[l-i-1]=n%base - n=int(n/base) + n=int(n / base) if n!=0: - print 'Number ', num, ' requires more than ', l, 'digits.' + print('Number ', num, ' requires more than ', l, 'digits.') return s @@ -84,9 +86,9 @@ def make_isi_lookup(mod,channel,normalize): for i in range(len(channel)): p = p + channel[i]**2 for i in range(len(channel)): - channel[i] = channel[i]/math.sqrt(p) + channel[i] = channel[i] / math.sqrt(p) - lookup=range(len(constellation)**len(channel)) + lookup=list(range(len(constellation)**len(channel))) for o in range(len(constellation)**len(channel)): ss=dec2base(o,len(constellation),len(channel)) ll=0 @@ -109,11 +111,11 @@ def make_isi_lookup(mod,channel,normalize): ###################################################################### def make_cpm_signals(K,P,M,L,q,frac): - Q=numpy.size(q)/L - h=(1.0*K)/P + Q=numpy.size(q) / L + h=(1.0*K) / P f0=-h*(M-1)/2 dt=0.0; # maybe start at t=0.5 - t=(dt+numpy.arange(0,Q))/Q + t=(dt+numpy.arange(0 / Q),Q) qq=numpy.zeros(Q) for m in range(L): qq=qq + q[m*Q:m*Q+Q] @@ -122,46 +124,46 @@ def make_cpm_signals(K,P,M,L,q,frac): X=(M**L)*P PSI=numpy.empty((X,Q)) for x in range(X): - xv=dec2base(x/P,M,L) + xv=dec2base(x / P,M,L) xv=numpy.append(xv, x%P) qq1=numpy.zeros(Q) for m in range(L): qq1=qq1+xv[m]*q[m*Q:m*Q+Q] psi=2*math.pi*h*xv[-1]+4*math.pi*h*qq1+w - #print psi + #print(psi) PSI[x]=psi PSI = numpy.transpose(PSI) SS=numpy.exp(1j*PSI) # contains all signals as columns - #print SS + #print(SS) # Now we need to orthogonalize the signals F = scipy.linalg.orth(SS) # find an orthonormal basis for SS - #print numpy.dot(numpy.transpose(F.conjugate()),F) # check for orthonormality + #print(numpy.dot(numpy.transpose(F.conjugate()),F) # check for orthonormality) S = numpy.dot(numpy.transpose(F.conjugate()),SS) - #print F - #print S + #print(F) + #print(S) # We only want to keep those dimensions that contain most # of the energy of the overall constellation (eg, frac=0.9 ==> 90%) # evaluate mean energy in each dimension - E=numpy.sum(numpy.absolute(S)**2,axis=1)/Q - E=E/numpy.sum(E) - #print E + E=numpy.sum(numpy.absolute(S)**2, axis=1) / Q + E=E / numpy.sum(E) + #print(E) Es = -numpy.sort(-E) Esi = numpy.argsort(-E) - #print Es - #print Esi + #print(Es) + #print(Esi) Ecum=numpy.cumsum(Es) - #print Ecum + #print(Ecum) v0=numpy.searchsorted(Ecum,frac) N = v0+1 - #print v0 - #print Esi[0:v0+1] + #print(v0) + #print(Esi[0:v0+1]) Ff=numpy.transpose(numpy.transpose(F)[Esi[0:v0+1]]) - #print Ff + #print(Ff) Sf = S[Esi[0:v0+1]] - #print Sf + #print(Sf) return (f0,SS,S,F,Sf,Ff,N) diff --git a/gr-trellis/python/trellis/qa_trellis.py b/gr-trellis/python/trellis/qa_trellis.py index 86c740a730..f248832204 100755..100644 --- a/gr-trellis/python/trellis/qa_trellis.py +++ b/gr-trellis/python/trellis/qa_trellis.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import math import os @@ -71,7 +73,7 @@ class test_trellis (gr_unittest.TestCase): Runs some coding/decoding tests with a few different FSM specs. """ - for name, args in fsm_args.items(): + for name, args in list(fsm_args.items()): constellation = constells[args[2]] fsms = trellis.fsm(*args) noise = 0.1 @@ -85,7 +87,7 @@ class trellis_tb(gr.top_block): """ A simple top block for use testing gr-trellis. """ - def __init__(self, constellation, f, N0=0.25, seed=-666L): + def __init__(self, constellation, f, N0=0.25, seed=-666): """ constellation - a constellation object used for modulation. f - a finite state machine specification used for coding. @@ -96,14 +98,14 @@ class trellis_tb(gr.top_block): # packet size in bits (make it multiple of 16 so it can be packed in a short) packet_size = 1024*16 # bits per FSM input symbol - bitspersymbol = int(round(math.log(f.I())/math.log(2))) # bits per FSM input symbol + bitspersymbol = int(round(math.log(f.I()) / math.log(2))) # bits per FSM input symbol # packet size in trellis steps - K = packet_size/bitspersymbol + K = packet_size // bitspersymbol # TX src = blocks.lfsr_32k_source_s() # packet size in shorts - src_head = blocks.head(gr.sizeof_short, packet_size/16) + src_head = blocks.head(gr.sizeof_short, packet_size // 16) # unpack shorts to symbols compatible with the FSM input cardinality s2fsmi = blocks.packed_to_unpacked_ss(bitspersymbol, gr.GR_MSB_FIRST) # initial FSM state = 0 @@ -112,7 +114,7 @@ class trellis_tb(gr.top_block): # CHANNEL add = blocks.add_cc() - noise = analog.noise_source_c(analog.GR_GAUSSIAN,math.sqrt(N0/2),seed) + noise = analog.noise_source_c(analog.GR_GAUSSIAN,math.sqrt(N0 / 2),seed) # RX # data preprocessing to generate metrics for Viterbi diff --git a/gr-trellis/swig/trellis_swig.py.in b/gr-trellis/swig/trellis_swig.py.in index fac5f631e2..f49e04e0a3 100644 --- a/gr-trellis/swig/trellis_swig.py.in +++ b/gr-trellis/swig/trellis_swig.py.in @@ -19,5 +19,7 @@ # Boston, MA 02110-1301, USA. # -from trellis_swig0 import * -from trellis_swig1 import * +from __future__ import absolute_import + +from .trellis_swig0 import * +from .trellis_swig1 import * diff --git a/gr-uhd/CMakeLists.txt b/gr-uhd/CMakeLists.txt index f6d956c1e1..51b67873a9 100644 --- a/gr-uhd/CMakeLists.txt +++ b/gr-uhd/CMakeLists.txt @@ -59,7 +59,7 @@ add_subdirectory(examples/c++) if(ENABLE_PYTHON) add_subdirectory(swig) add_subdirectory(python/uhd) - add_subdirectory(grc) + #add_subdirectory(grc) add_subdirectory(apps) add_subdirectory(examples/grc) endif(ENABLE_PYTHON) diff --git a/gr-uhd/apps/uhd_app.py b/gr-uhd/apps/uhd_app.py index 5c8881ce34..5a8290fe52 100644 --- a/gr-uhd/apps/uhd_app.py +++ b/gr-uhd/apps/uhd_app.py @@ -24,6 +24,8 @@ USRP Helper Module: Common tasks for uhd-based apps. """ from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals import sys import time import argparse @@ -163,18 +165,18 @@ class UHDApp(object): self.spec = self.normalize_sel("mboards", "subdev", self.usrp.get_num_mboards(), args.spec) if self.spec: - for mb_idx in xrange(self.usrp.get_num_mboards()): + for mb_idx in range(self.usrp.get_num_mboards()): self.usrp.set_subdev_spec(self.spec[mb_idx], mb_idx) # Set the clock and/or time source: if args.clock_source is not None: self.clock_source = self.normalize_sel("mboards", "clock-source", self.usrp.get_num_mboards(), args.clock_source) - for mb_idx in xrange(self.usrp.get_num_mboards()): + for mb_idx in range(self.usrp.get_num_mboards()): self.usrp.set_clock_source(self.clock_source[mb_idx], mb_idx) if args.time_source is not None: self.time_source = self.normalize_sel("mboards", "time-source", self.usrp.get_num_mboards(), args.time_source) - for mb_idx in xrange(self.usrp.get_num_mboards()): + for mb_idx in range(self.usrp.get_num_mboards()): self.usrp.set_time_source(self.time_source[mb_idx], mb_idx) # Sampling rate: self.usrp.set_samp_rate(args.samp_rate) @@ -235,7 +237,7 @@ class UHDApp(object): self.usrp.set_time_unknown_pps(uhd.time_spec()) cmd_time = self.usrp.get_time_now() + uhd.time_spec(COMMAND_DELAY) try: - for mb_idx in xrange(self.usrp.get_num_mboards()): + for mb_idx in range(self.usrp.get_num_mboards()): self.usrp.set_command_time(cmd_time, mb_idx) command_time_set = True except RuntimeError: @@ -248,7 +250,7 @@ class UHDApp(object): )) exit(1) if command_time_set: - for mb_idx in xrange(self.usrp.get_num_mboards()): + for mb_idx in range(self.usrp.get_num_mboards()): self.usrp.clear_command_time(mb_idx) self.vprint("Syncing channels...".format(prefix=self.prefix)) time.sleep(COMMAND_DELAY) @@ -283,7 +285,7 @@ class UHDApp(object): """ Safely tune all channels to freq. """ - self.vprint("Tuning all channels to {freq} MHz.".format(freq=freq/1e6)) + self.vprint("Tuning all channels to {freq} MHz.".format(freq=freq / 1e6)) # Set frequency (tune request takes lo_offset): if hasattr(self.args, 'lo_offset') and self.args.lo_offset is not None: treq = uhd.tune_request(freq, self.args.lo_offset) @@ -310,7 +312,7 @@ class UHDApp(object): if len(self.channels) > 1 and not skip_sync: cmd_time = self.usrp.get_time_now() + uhd.time_spec(COMMAND_DELAY) try: - for mb_idx in xrange(self.usrp.get_num_mboards()): + for mb_idx in range(self.usrp.get_num_mboards()): self.usrp.set_command_time(cmd_time, mb_idx) command_time_set = True except RuntimeError: @@ -323,12 +325,12 @@ class UHDApp(object): )) exit(1) if command_time_set: - for mb_idx in xrange(self.usrp.get_num_mboards()): + for mb_idx in range(self.usrp.get_num_mboards()): self.usrp.clear_command_time(mb_idx) self.vprint("Syncing channels...".format(prefix=self.prefix)) time.sleep(COMMAND_DELAY) self.freq = self.usrp.get_center_freq(0) - self.vprint("First channel has freq: {freq} MHz.".format(freq=self.freq/1e6)) + self.vprint("First channel has freq: {freq} MHz.".format(freq=self.freq / 1e6)) @staticmethod def setup_argparser( @@ -390,4 +392,3 @@ class UHDApp(object): group.add_argument("--time-source", help="Set the time source") return parser - diff --git a/gr-uhd/apps/uhd_siggen_base.py b/gr-uhd/apps/uhd_siggen_base.py index cc699dd145..98dda1084b 100644 --- a/gr-uhd/apps/uhd_siggen_base.py +++ b/gr-uhd/apps/uhd_siggen_base.py @@ -24,6 +24,8 @@ Provide a base flow graph for USRP signal generators. """ from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals import math try: from uhd_app import UHDApp @@ -124,7 +126,7 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): """ When sampling rate is updated, also update the signal sources. """ - self.vprint("Setting sampling rate to: {rate} Msps".format(rate=samp_rate/1e6)) + self.vprint("Setting sampling rate to: {rate} Msps".format(rate=samp_rate / 1e6)) self.usrp.set_samp_rate(samp_rate) samp_rate = self.usrp.get_samp_rate() if self[TYPE_KEY] in (analog.GR_SIN_WAVE, analog.GR_CONST_WAVE): @@ -137,7 +139,7 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self._src2.set_sampling_freq(self[WAVEFORM_FREQ_KEY]*2*math.pi/self[SAMP_RATE_KEY]) else: return True # Waveform not yet set - self.vprint("Set sample rate to: {rate} Msps".format(rate=samp_rate/1e6)) + self.vprint("Set sample rate to: {rate} Msps".format(rate=samp_rate / 1e6)) return True def set_waveform_freq(self, freq): @@ -184,14 +186,14 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self._src1 = analog.sig_source_c(self[SAMP_RATE_KEY], analog.GR_SIN_WAVE, self[WAVEFORM_FREQ_KEY], - self[AMPLITUDE_KEY]/2.0, + self[AMPLITUDE_KEY] / 2.0, 0) if self[WAVEFORM2_FREQ_KEY] is None: self[WAVEFORM2_FREQ_KEY] = -self[WAVEFORM_FREQ_KEY] self._src2 = analog.sig_source_c(self[SAMP_RATE_KEY], analog.GR_SIN_WAVE, self[WAVEFORM2_FREQ_KEY], - self[AMPLITUDE_KEY]/2.0, + self[AMPLITUDE_KEY] / 2.0, 0) self._src = blocks.add_cc() self.connect(self._src1, (self._src, 0)) @@ -213,7 +215,7 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self.connect(self._src1, self._src2, self._src) else: raise RuntimeError("[UHD-SIGGEN] Unknown waveform waveform_type") - for chan in xrange(len(self.channels)): + for chan in range(len(self.channels)): self.connect(self._src, (self.usrp, chan)) if self.extra_sink is not None: self.connect(self._src, self.extra_sink) @@ -226,7 +228,7 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): self.vprint("Tone 1: %sHz" % (n2s(self[WAVEFORM_FREQ_KEY]),)) self.vprint("Tone 2: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)) elif waveform_type == "sweep": - self.vprint("Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY]/2.0), n2s(self[WAVEFORM_FREQ_KEY]/2.0))) + self.vprint("Sweeping across %sHz to %sHz" % (n2s(-self[WAVEFORM_FREQ_KEY] / 2.0), n2s(self[WAVEFORM_FREQ_KEY] / 2.0))) self.vprint("Sweep rate: %sHz" % (n2s(self[WAVEFORM2_FREQ_KEY]),)) self.vprint("TX amplitude:", self[AMPLITUDE_KEY]) @@ -240,8 +242,8 @@ class USRPSiggen(gr.top_block, pubsub, UHDApp): if self[TYPE_KEY] in (analog.GR_SIN_WAVE, analog.GR_CONST_WAVE, analog.GR_GAUSSIAN, analog.GR_UNIFORM): self._src.set_amplitude(amplitude) elif self[TYPE_KEY] == "2tone": - self._src1.set_amplitude(amplitude/2.0) - self._src2.set_amplitude(amplitude/2.0) + self._src1.set_amplitude(amplitude / 2.0) + self._src2.set_amplitude(amplitude / 2.0) elif self[TYPE_KEY] == "sweep": self._src.set_k(amplitude) else: @@ -293,7 +295,7 @@ def main(): print(ex) exit(1) tb.start() - raw_input('[UHD-SIGGEN] Press Enter to quit:\n') + eval(input('[UHD-SIGGEN] Press Enter to quit:\n')) tb.stop() tb.wait() diff --git a/gr-uhd/grc/gen_uhd_usrp_blocks.py b/gr-uhd/grc/gen_uhd_usrp_blocks.py index e99de0d7d0..8d16c4e936 100644 --- a/gr-uhd/grc/gen_uhd_usrp_blocks.py +++ b/gr-uhd/grc/gen_uhd_usrp_blocks.py @@ -21,27 +21,27 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA MAIN_TMPL = """\ <?xml version="1.0"?> <block> - <name>UHD: USRP $sourk.title()</name> - <key>uhd_usrp_$(sourk)</key> - <flags>throttle</flags> - <import>from gnuradio import uhd</import> - <import>import time</import> - <make>uhd.usrp_$(sourk)( - ",".join((\$dev_addr, \$dev_args)), - uhd.stream_args( - cpu_format="\$type", - \#if \$otw() - otw_format=\$otw, - \#end if - \#if \$stream_args() - args=\$stream_args, - \#end if - \#if \$stream_chans() - channels=\$stream_chans, - \#else - channels=range(\$nchan), - \#end if - ),$lentag_arg + <name>UHD: USRP $sourk.title()</name> + <key>uhd_usrp_$(sourk)</key> + <flags>throttle</flags> + <import>from gnuradio import uhd</import> + <import>import time</import> + <make>uhd.usrp_$(sourk)( + ",".join((\$dev_addr, \$dev_args)), + uhd.stream_args( + cpu_format="\$type", + \#if \$otw() + otw_format=\$otw, + \#end if + \#if \$stream_args() + args=\$stream_args, + \#end if + \#if \$stream_chans() + channels=\$stream_chans, + \#else + channels=range(\$nchan), + \#end if + ),$lentag_arg ) \#if \$clock_rate() self.\$(id).set_clock_rate(\$clock_rate, uhd.ALL_MBOARDS) @@ -75,309 +75,309 @@ self.\$(id).set_normalized_gain(\$gain$(n), $n) \#else self.\$(id).set_gain(\$gain$(n), $n) \#end if - \#if \$ant$(n)() + \#if \$ant$(n)() self.\$(id).set_antenna(\$ant$(n), $n) - \#end if - \#if \$bw$(n)() + \#end if + \#if \$bw$(n)() self.\$(id).set_bandwidth(\$bw$(n), $n) - \#end if + \#end if #if $sourk == 'source' - \#if \$lo_export$(n)() and not \$hide_lo_controls() + \#if \$lo_export$(n)() and not \$hide_lo_controls() self.\$(id).set_lo_export_enabled(\$lo_export$(n), uhd.ALL_LOS, $n) - \#end if + \#end if \#if \$lo_source$(n)() and not \$hide_lo_controls() self.\$(id).set_lo_source(\$lo_source$(n), uhd.ALL_LOS, $n) - \#end if - \#if \$dc_offs_enb$(n)() + \#end if + \#if \$dc_offs_enb$(n)() self.\$(id).set_auto_dc_offset(\$dc_offs_enb$(n), $n) - \#end if - \#if \$iq_imbal_enb$(n)() + \#end if + \#if \$iq_imbal_enb$(n)() self.\$(id).set_auto_iq_balance(\$iq_imbal_enb$(n), $n) - \#end if + \#end if #end if \#end if #end for </make> - <callback>set_samp_rate(\$samp_rate)</callback> - #for $n in range($max_nchan) - <callback>set_center_freq(\$center_freq$(n), $n)</callback> - <callback>\#if \$norm_gain${n}() + <callback>set_samp_rate(\$samp_rate)</callback> + #for $n in range($max_nchan) + <callback>set_center_freq(\$center_freq$(n), $n)</callback> + <callback>\#if \$norm_gain${n}() self.\$(id).set_normalized_gain(\$gain$(n), $n) \#else self.\$(id).set_gain(\$gain$(n), $n) \#end if - </callback> - <callback>\#if not \$hide_lo_controls() + </callback> + <callback>\#if not \$hide_lo_controls() set_lo_source(\$lo_source$(n), uhd.ALL_LOS, $n) \#end if - </callback> + </callback> <callback>\#if not \$hide_lo_controls() set_lo_export_enabled(\$lo_export$(n), uhd.ALL_LOS, $n) \#end if - </callback> - <callback>set_antenna(\$ant$(n), $n)</callback> - <callback>set_bandwidth(\$bw$(n), $n)</callback> - #end for - <param> - <name>$(direction.title())put Type</name> - <key>type</key> - <type>enum</type> - <option> - <name>Complex float32</name> - <key>fc32</key> - <opt>type:fc32</opt> - </option> - <option> - <name>Complex int16</name> - <key>sc16</key> - <opt>type:sc16</opt> - </option> - <option> - <name>VITA word32</name> - <key>item32</key> - <opt>type:s32</opt> - </option> - </param> - <param> - <name>Wire Format</name> - <key>otw</key> - <value></value> - <type>string</type> - <hide> - \#if \$otw() - none - \#else - part - \#end if - </hide> - <option> - <name>Automatic</name> - <key></key> - </option> - <option> - <name>Complex int16</name> - <key>sc16</key> - </option> - <option> - <name>Complex int12</name> - <key>sc12</key> - </option> - <option> - <name>Complex int8</name> - <key>sc8</key> - </option> - </param> - <param> - <name>Stream args</name> - <key>stream_args</key> - <value></value> - <type>string</type> - <hide> - \#if \$stream_args() - none - \#else - part - \#end if - </hide> - <option> - <name>peak=0.003906</name> - <key>peak=0.003906</key> - </option> - </param> - <param> - <name>Stream channels</name> - <key>stream_chans</key> - <value>[]</value> - <type>int_vector</type> - <hide> - \#if \$stream_chans() - none - \#else - part - \#end if - </hide> - </param> - <param> - <name>Device Address</name> - <key>dev_addr</key> - <value>""</value> - <type>string</type> - <hide> - \#if \$dev_addr() - none - \#else - part - \#end if - </hide> - </param> - <param> - <name>Device Arguments</name> - <key>dev_args</key> - <value>""</value> - <type>string</type> - <hide> - \#if \$dev_args() - none - \#else - part - \#end if - </hide> - </param> - <param> - <name>Sync</name> - <key>sync</key> - <value></value> - <type>enum</type> - <hide>\#if \$sync() then 'none' else 'part'#</hide> - <option> - <name>unknown PPS</name> - <key>sync</key> - </option> - <option> - <name>PC Clock</name> - <key>pc_clock</key> - </option> - <option> - <name>don't sync</name> - <key></key> - </option> - </param> - <param> - <name>Clock Rate (Hz)</name> - <key>clock_rate</key> - <value>0.0</value> - <type>real</type> - <hide>\#if \$clock_rate() then 'none' else 'part'#</hide> - <option> - <name>Default</name> - <key>0.0</key> - </option> - <option> - <name>200 MHz</name> - <key>200e6</key> - </option> - <option> - <name>184.32 MHz</name> - <key>184.32e6</key> - </option> - <option> - <name>120 MHz</name> - <key>120e6</key> - </option> - <option> - <name>30.72 MHz</name> - <key>30.72e6</key> - </option> - </param> - <param> - <name>Num Mboards</name> - <key>num_mboards</key> - <value>1</value> - <type>int</type> - <hide>part</hide> - #for $m in range(1, $max_mboards+1) - <option> - <name>$(m)</name> - <key>$m</key> - </option> - #end for - </param> - #for $m in range($max_mboards) - <param> - <name>Mb$(m): Clock Source</name> - <key>clock_source$(m)</key> - <value></value> - <type>string</type> - <hide> - \#if not \$num_mboards() > $m - all - \#elif \$clock_source$(m)() - none - \#else - part - \#end if - </hide> - <option><name>Default</name><key></key></option> - <option><name>Internal</name><key>internal</key></option> - <option><name>External</name><key>external</key></option> - <option><name>MIMO Cable</name><key>mimo</key></option> - <option><name>O/B GPSDO</name><key>gpsdo</key></option> - </param> - <param> - <name>Mb$(m): Time Source</name> - <key>time_source$(m)</key> - <value></value> - <type>string</type> - <hide> - \#if not \$num_mboards() > $m - all - \#elif \$time_source$(m)() - none - \#else - part - \#end if - </hide> - <option><name>Default</name><key></key></option> - <option><name>External</name><key>external</key></option> - <option><name>MIMO Cable</name><key>mimo</key></option> - <option><name>O/B GPSDO</name><key>gpsdo</key></option> - </param> - <param> - <name>Mb$(m): Subdev Spec</name> - <key>sd_spec$(m)</key> - <value></value> - <type>string</type> - <hide> - \#if not \$num_mboards() > $m - all - \#elif \$sd_spec$(m)() - none - \#else - part - \#end if - </hide> - </param> - #end for - <param> - <name>Num Channels</name> - <key>nchan</key> - <value>1</value> - <type>int</type> - #for $n in range(1, $max_nchan+1) - <option> - <name>$(n)</name> - <key>$n</key> - </option> - #end for - </param> - <param> - <name>Samp Rate (Sps)</name> - <key>samp_rate</key> - <value>samp_rate</value> - <type>real</type> - </param> - $params - <check>$max_nchan >= \$nchan</check> - <check>\$nchan > 0</check> - <check>$max_mboards >= \$num_mboards</check> - <check>\$num_mboards > 0</check> - <check>\$nchan >= \$num_mboards</check> - <check>(not \$stream_chans()) or (\$nchan == len(\$stream_chans))</check> - #for $n in range($max_nchan) - <check>(\$norm_gain${n} and \$gain${n} >= 0 and \$gain${n} <= 1) or not \$norm_gain${n}</check> - #end for - <sink> - <name>command</name> - <type>message</type> - <optional>1</optional> - <hide>\$hide_cmd_port</hide> - </sink> - <$sourk> - <name>$direction</name> - <type>\$type.type</type> - <nports>\$nchan</nports> - </$sourk> - <doc> + </callback> + <callback>set_antenna(\$ant$(n), $n)</callback> + <callback>set_bandwidth(\$bw$(n), $n)</callback> + #end for + <param> + <name>$(direction.title())put Type</name> + <key>type</key> + <type>enum</type> + <option> + <name>Complex float32</name> + <key>fc32</key> + <opt>type:fc32</opt> + </option> + <option> + <name>Complex int16</name> + <key>sc16</key> + <opt>type:sc16</opt> + </option> + <option> + <name>VITA word32</name> + <key>item32</key> + <opt>type:s32</opt> + </option> + </param> + <param> + <name>Wire Format</name> + <key>otw</key> + <value></value> + <type>string</type> + <hide> + \#if \$otw() + none + \#else + part + \#end if + </hide> + <option> + <name>Automatic</name> + <key></key> + </option> + <option> + <name>Complex int16</name> + <key>sc16</key> + </option> + <option> + <name>Complex int12</name> + <key>sc12</key> + </option> + <option> + <name>Complex int8</name> + <key>sc8</key> + </option> + </param> + <param> + <name>Stream args</name> + <key>stream_args</key> + <value></value> + <type>string</type> + <hide> + \#if \$stream_args() + none + \#else + part + \#end if + </hide> + <option> + <name>peak=0.003906</name> + <key>peak=0.003906</key> + </option> + </param> + <param> + <name>Stream channels</name> + <key>stream_chans</key> + <value>[]</value> + <type>int_vector</type> + <hide> + \#if \$stream_chans() + none + \#else + part + \#end if + </hide> + </param> + <param> + <name>Device Address</name> + <key>dev_addr</key> + <value>""</value> + <type>string</type> + <hide> + \#if \$dev_addr() + none + \#else + part + \#end if + </hide> + </param> + <param> + <name>Device Arguments</name> + <key>dev_args</key> + <value>""</value> + <type>string</type> + <hide> + \#if \$dev_args() + none + \#else + part + \#end if + </hide> + </param> + <param> + <name>Sync</name> + <key>sync</key> + <value></value> + <type>enum</type> + <hide>\#if \$sync() then 'none' else 'part'#</hide> + <option> + <name>unknown PPS</name> + <key>sync</key> + </option> + <option> + <name>PC Clock</name> + <key>pc_clock</key> + </option> + <option> + <name>don't sync</name> + <key></key> + </option> + </param> + <param> + <name>Clock Rate (Hz)</name> + <key>clock_rate</key> + <value>0.0</value> + <type>real</type> + <hide>\#if \$clock_rate() then 'none' else 'part'#</hide> + <option> + <name>Default</name> + <key>0.0</key> + </option> + <option> + <name>200 MHz</name> + <key>200e6</key> + </option> + <option> + <name>184.32 MHz</name> + <key>184.32e6</key> + </option> + <option> + <name>120 MHz</name> + <key>120e6</key> + </option> + <option> + <name>30.72 MHz</name> + <key>30.72e6</key> + </option> + </param> + <param> + <name>Num Mboards</name> + <key>num_mboards</key> + <value>1</value> + <type>int</type> + <hide>part</hide> + #for $m in range(1, $max_mboards+1) + <option> + <name>$(m)</name> + <key>$m</key> + </option> + #end for + </param> + #for $m in range($max_mboards) + <param> + <name>Mb$(m): Clock Source</name> + <key>clock_source$(m)</key> + <value></value> + <type>string</type> + <hide> + \#if not \$num_mboards() > $m + all + \#elif \$clock_source$(m)() + none + \#else + part + \#end if + </hide> + <option><name>Default</name><key></key></option> + <option><name>Internal</name><key>internal</key></option> + <option><name>External</name><key>external</key></option> + <option><name>MIMO Cable</name><key>mimo</key></option> + <option><name>O/B GPSDO</name><key>gpsdo</key></option> + </param> + <param> + <name>Mb$(m): Time Source</name> + <key>time_source$(m)</key> + <value></value> + <type>string</type> + <hide> + \#if not \$num_mboards() > $m + all + \#elif \$time_source$(m)() + none + \#else + part + \#end if + </hide> + <option><name>Default</name><key></key></option> + <option><name>External</name><key>external</key></option> + <option><name>MIMO Cable</name><key>mimo</key></option> + <option><name>O/B GPSDO</name><key>gpsdo</key></option> + </param> + <param> + <name>Mb$(m): Subdev Spec</name> + <key>sd_spec$(m)</key> + <value></value> + <type>string</type> + <hide> + \#if not \$num_mboards() > $m + all + \#elif \$sd_spec$(m)() + none + \#else + part + \#end if + </hide> + </param> + #end for + <param> + <name>Num Channels</name> + <key>nchan</key> + <value>1</value> + <type>int</type> + #for $n in range(1, $max_nchan+1) + <option> + <name>$(n)</name> + <key>$n</key> + </option> + #end for + </param> + <param> + <name>Samp Rate (Sps)</name> + <key>samp_rate</key> + <value>samp_rate</value> + <type>real</type> + </param> + $params + <check>$max_nchan >= \$nchan</check> + <check>\$nchan > 0</check> + <check>$max_mboards >= \$num_mboards</check> + <check>\$num_mboards > 0</check> + <check>\$nchan >= \$num_mboards</check> + <check>(not \$stream_chans()) or (\$nchan == len(\$stream_chans))</check> + #for $n in range($max_nchan) + <check>(\$norm_gain${n} and \$gain${n} >= 0 and \$gain${n} <= 1) or not \$norm_gain${n}</check> + #end for + <sink> + <name>command</name> + <type>message</type> + <optional>1</optional> + <hide>\$hide_cmd_port</hide> + </sink> + <$sourk> + <name>$direction</name> + <type>\$type.type</type> + <nports>\$nchan</nports> + </$sourk> + <doc> The UHD USRP $sourk.title() Block: Device Address: @@ -452,31 +452,31 @@ to determine transmit burst lengths. See the UHD manual for more detailed documentation: http://uhd.ettus.com - </doc> + </doc> </block> """ PARAMS_TMPL = """ <param> - <name>Ch$(n): Center Freq (Hz)</name> - <key>center_freq$(n)</key> - <value>0</value> - <type>real</type> - <hide>\#if \$nchan() > $n then 'none' else 'all'#</hide> - <tab>RF Options</tab> - </param> - <param> - <name>Ch$(n): Gain Value</name> - <key>gain$(n)</key> - <value>0</value> - <type>float</type> - <hide>\#if \$nchan() > $n then 'none' else 'all'#</hide> - <tab>RF Options</tab> - </param> - <param> - <name>Ch$(n): Gain Type</name> - <key>norm_gain$(n)</key> - <value>False</value> - <type>bool</type> + <name>Ch$(n): Center Freq (Hz)</name> + <key>center_freq$(n)</key> + <value>0</value> + <type>real</type> + <hide>\#if \$nchan() > $n then 'none' else 'all'#</hide> + <tab>RF Options</tab> + </param> + <param> + <name>Ch$(n): Gain Value</name> + <key>gain$(n)</key> + <value>0</value> + <type>float</type> + <hide>\#if \$nchan() > $n then 'none' else 'all'#</hide> + <tab>RF Options</tab> + </param> + <param> + <name>Ch$(n): Gain Type</name> + <key>norm_gain$(n)</key> + <value>False</value> + <type>bool</type> <hide>\#if \$nchan() <= $n all \#elif bool(\$norm_gain${n}()) @@ -484,227 +484,227 @@ PARAMS_TMPL = """ <param> \#else part \#end if</hide> - <option> - <name>Absolute (dB)</name> - <key>False</key> - </option> - <option> - <name>Normalized</name> - <key>True</key> - </option> - <tab>RF Options</tab> - </param> - <param> - <name>Ch$(n): Antenna</name> - <key>ant$(n)</key> - <value></value> - <type>string</type> - <hide> - \#if not \$nchan() > $n - all - \#elif \$ant$(n)() - none - \#else - part - \#end if - </hide> - <option> - <name>TX/RX</name> - <key>TX/RX</key> - </option> + <option> + <name>Absolute (dB)</name> + <key>False</key> + </option> + <option> + <name>Normalized</name> + <key>True</key> + </option> + <tab>RF Options</tab> + </param> + <param> + <name>Ch$(n): Antenna</name> + <key>ant$(n)</key> + <value></value> + <type>string</type> + <hide> + \#if not \$nchan() > $n + all + \#elif \$ant$(n)() + none + \#else + part + \#end if + </hide> + <option> + <name>TX/RX</name> + <key>TX/RX</key> + </option> #if $sourk == 'source' - <option> - <name>RX2</name> - <key>RX2</key> - </option> + <option> + <name>RX2</name> + <key>RX2</key> + </option> #end if - <tab>RF Options</tab> - </param> - <param> - <name>Ch$(n): Bandwidth (Hz)</name> - <key>bw$(n)</key> - <value>0</value> - <type>real</type> - <hide> - \#if not \$nchan() > $n - all - \#elif \$bw$(n)() - none - \#else - part - \#end if - </hide> - <tab>RF Options</tab> - </param> + <tab>RF Options</tab> + </param> + <param> + <name>Ch$(n): Bandwidth (Hz)</name> + <key>bw$(n)</key> + <value>0</value> + <type>real</type> + <hide> + \#if not \$nchan() > $n + all + \#elif \$bw$(n)() + none + \#else + part + \#end if + </hide> + <tab>RF Options</tab> + </param> #if $sourk == 'source' - <param> - <name>Ch$(n): LO Source</name> - <key>lo_source$(n)</key> - <value>internal</value> - <type>string</type> - <hide> - \#if not \$nchan() > $n - all - \#elif \$hide_lo_controls() - all - \#else - none - \#end if - </hide> - <option> - <name>Internal</name> - <key>internal</key> - </option> - <option> - <name>External</name> - <key>external</key> - </option> - <option> - <name>Companion</name> - <key>companion</key> - </option> - <tab>RF Options</tab> - </param> + <param> + <name>Ch$(n): LO Source</name> + <key>lo_source$(n)</key> + <value>internal</value> + <type>string</type> + <hide> + \#if not \$nchan() > $n + all + \#elif \$hide_lo_controls() + all + \#else + none + \#end if + </hide> + <option> + <name>Internal</name> + <key>internal</key> + </option> + <option> + <name>External</name> + <key>external</key> + </option> + <option> + <name>Companion</name> + <key>companion</key> + </option> + <tab>RF Options</tab> + </param> #end if #if $sourk == 'source' - <param> - <name>Ch$(n): LO Export</name> - <key>lo_export$(n)</key> - <value>False</value> - <type>bool</type> - <hide> - \#if not \$nchan() > $n - all - \#elif \$hide_lo_controls() - all - \#else - none - \#end if - </hide> - <option> - <name>True</name> - <key>True</key> - </option> - <option> - <name>False</name> - <key>False</key> - </option> - <tab>RF Options</tab> - </param> + <param> + <name>Ch$(n): LO Export</name> + <key>lo_export$(n)</key> + <value>False</value> + <type>bool</type> + <hide> + \#if not \$nchan() > $n + all + \#elif \$hide_lo_controls() + all + \#else + none + \#end if + </hide> + <option> + <name>True</name> + <key>True</key> + </option> + <option> + <name>False</name> + <key>False</key> + </option> + <tab>RF Options</tab> + </param> #end if #if $sourk == 'source' - <param> - <name>Ch$(n): Enable DC Offset Correction</name> - <key>dc_offs_enb$(n)</key> - <value>""</value> - <type>raw</type> - <hide> - \#if not \$nchan() > $n - all - \#else - part - \#end if - </hide> - <tab>FE Corrections</tab> - </param> - <param> - <name>Ch$(n): Enable IQ Imbalance Correction</name> - <key>iq_imbal_enb$(n)</key> - <value>""</value> - <type>raw</type> - <hide> - \#if not \$nchan() > $n - all - \#else - part - \#end if - </hide> - <tab>FE Corrections</tab> - </param> + <param> + <name>Ch$(n): Enable DC Offset Correction</name> + <key>dc_offs_enb$(n)</key> + <value>""</value> + <type>raw</type> + <hide> + \#if not \$nchan() > $n + all + \#else + part + \#end if + </hide> + <tab>FE Corrections</tab> + </param> + <param> + <name>Ch$(n): Enable IQ Imbalance Correction</name> + <key>iq_imbal_enb$(n)</key> + <value>""</value> + <type>raw</type> + <hide> + \#if not \$nchan() > $n + all + \#else + part + \#end if + </hide> + <tab>FE Corrections</tab> + </param> #end if """ SHOW_CMD_PORT_PARAM = """ - <param> - <name>Show Command Port</name> - <key>hide_cmd_port</key> - <value>False</value> - <type>enum</type> - <hide>part</hide> - <option> - <name>Yes</name> - <key>False</key> - </option> - <option> - <name>No</name> - <key>True</key> - </option> - <tab>Advanced</tab> - </param> + <param> + <name>Show Command Port</name> + <key>hide_cmd_port</key> + <value>False</value> + <type>enum</type> + <hide>part</hide> + <option> + <name>Yes</name> + <key>False</key> + </option> + <option> + <name>No</name> + <key>True</key> + </option> + <tab>Advanced</tab> + </param> """ SHOW_LO_CONTROLS_PARAM = """ - <param> - <name>Show LO Controls</name> - <key>hide_lo_controls</key> - <value>True</value> - <type>bool</type> - <hide>part</hide> - <option> - <name>Yes</name> - <key>False</key> - </option> - <option> - <name>No</name> - <key>True</key> - </option> - <tab>Advanced</tab> - </param> + <param> + <name>Show LO Controls</name> + <key>hide_lo_controls</key> + <value>True</value> + <type>bool</type> + <hide>part</hide> + <option> + <name>Yes</name> + <key>False</key> + </option> + <option> + <name>No</name> + <key>True</key> + </option> + <tab>Advanced</tab> + </param> """ TSBTAG_PARAM = """ <param> - <name>TSB tag name</name> - <key>len_tag_name</key> - <value></value> - <type>string</type> - <hide>\#if len(str(\$len_tag_name())) then 'none' else 'part'#</hide> - </param>""" + <name>TSB tag name</name> + <key>len_tag_name</key> + <value></value> + <type>string</type> + <hide>\#if len(str(\$len_tag_name())) then 'none' else 'part'#</hide> + </param>""" TSBTAG_ARG = """ - #if $len_tag_name() - $len_tag_name, - #end if""" + #if $len_tag_name() + $len_tag_name, + #end if""" def parse_tmpl(_tmpl, **kwargs): - from Cheetah import Template - return str(Template.Template(_tmpl, kwargs)) + from Cheetah import Template + return str(Template.Template(_tmpl, kwargs)) max_num_mboards = 8 max_num_channels = max_num_mboards*4 if __name__ == '__main__': - import sys - for file in sys.argv[1:]: - if file.endswith ('source.xml'): - sourk = 'source' - direction = 'out' - elif file.endswith ('sink.xml'): - sourk = 'sink' - direction = 'in' - else: raise Exception, 'is %s a source or sink?'%file + import sys + for file in sys.argv[1:]: + if file.endswith ('source.xml'): + sourk = 'source' + direction = 'out' + elif file.endswith ('sink.xml'): + sourk = 'sink' + direction = 'in' + else: raise Exception('is %s a source or sink?'%file) - params = ''.join([parse_tmpl(PARAMS_TMPL, n=n, sourk=sourk) for n in range(max_num_channels)]) - params += SHOW_CMD_PORT_PARAM - params += SHOW_LO_CONTROLS_PARAM - if sourk == 'sink': - params += TSBTAG_PARAM - lentag_arg = TSBTAG_ARG - else: lentag_arg = '' - open(file, 'w').write(parse_tmpl(MAIN_TMPL, - lentag_arg=lentag_arg, - max_nchan=max_num_channels, - max_mboards=max_num_mboards, - params=params, - sourk=sourk, - direction=direction, - )) + params = ''.join([parse_tmpl(PARAMS_TMPL, n=n, sourk=sourk) for n in range(max_num_channels)]) + params += SHOW_CMD_PORT_PARAM + params += SHOW_LO_CONTROLS_PARAM + if sourk == 'sink': + params += TSBTAG_PARAM + lentag_arg = TSBTAG_ARG + else: lentag_arg = '' + open(file, 'w').write(parse_tmpl(MAIN_TMPL, + lentag_arg=lentag_arg, + max_nchan=max_num_channels, + max_mboards=max_num_mboards, + params=params, + sourk=sourk, + direction=direction, + )) diff --git a/gr-uhd/python/uhd/CMakeLists.txt b/gr-uhd/python/uhd/CMakeLists.txt index ee69e8eb7d..e736edebf0 100644 --- a/gr-uhd/python/uhd/CMakeLists.txt +++ b/gr-uhd/python/uhd/CMakeLists.txt @@ -44,6 +44,6 @@ include(GrTest) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-uhd/python/uhd/__init__.py b/gr-uhd/python/uhd/__init__.py index 6d7f232466..ad342ee30d 100644 --- a/gr-uhd/python/uhd/__init__.py +++ b/gr-uhd/python/uhd/__init__.py @@ -25,17 +25,20 @@ Used to send and receive data between the Ettus Research, LLC product line. ''' +from __future__ import absolute_import +from __future__ import unicode_literals + ######################################################################## # Prepare uhd swig module to make it more pythonic ######################################################################## def _prepare_uhd_swig(): try: - import uhd_swig + from . import uhd_swig except ImportError: import os dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - import uhd_swig + from . import uhd_swig #some useful typedefs for the user setattr(uhd_swig, 'freq_range_t', uhd_swig.meta_range_t) @@ -50,7 +53,7 @@ def _prepare_uhd_swig(): def __float__(self): return self.target_freq def __init__(self, *args, **kwargs): super(tune_request_t, self).__init__(*args) - for key, val in kwargs.iteritems(): setattr(self, key, val) + for key, val in list(kwargs.items()): setattr(self, key, val) setattr(uhd_swig, 'tune_request_t', tune_request_t) #Make the python tune request object inherit from string @@ -64,14 +67,14 @@ def _prepare_uhd_swig(): def __init__(self, *args, **kwargs): super(device_addr_t, self).__init__(*args) if args and isinstance(args[0], device_addr_t): - for key in args[0].keys(): self[key] = args[0][key] + for key in list(args[0].keys()): self[key] = args[0][key] setattr(uhd_swig, 'device_addr_t', device_addr_t) #make the streamer args take **kwargs on init class stream_args_t(uhd_swig.stream_args_t): def __init__(self, *args, **kwargs): super(stream_args_t, self).__init__(*args) - for key, val in kwargs.iteritems(): + for key, val in list(kwargs.items()): #for some reason, i cant assign a list in the constructor #but what i can do is append the elements individually if key == 'channels': @@ -97,7 +100,7 @@ def _prepare_uhd_swig(): def find_devices(*args, **kwargs): def to_pythonized_dev_addr(dev_addr): new_dev_addr = uhd_swig.device_addr_t() - for key in dev_addr.keys(): new_dev_addr[key] = dev_addr.get(key) + for key in list(dev_addr.keys()): new_dev_addr[key] = dev_addr.get(key) return new_dev_addr return __builtins__['map'](to_pythonized_dev_addr, uhd_swig.find_devices_raw(*args, **kwargs)) setattr(uhd_swig, 'find_devices', find_devices) @@ -114,11 +117,11 @@ def _prepare_uhd_swig(): ): try: if len(args) > index: args[index] = cast(args[index]) - if kwargs.has_key(key): kwargs[key] = cast(kwargs[key]) + if key in kwargs: kwargs[key] = cast(kwargs[key]) except: pass #dont pass kwargs, it confuses swig, map into args list: for key in ('device_addr', 'stream_args', 'io_type', 'num_channels', 'msgq'): - if kwargs.has_key(key): args.append(kwargs[key]) + if key in kwargs: args.append(kwargs[key]) return old_constructor(*args) return constructor_interceptor setattr(uhd_swig, attr, constructor_factory(getattr(uhd_swig, attr))) @@ -133,4 +136,4 @@ def _prepare_uhd_swig(): # Initialize this module with the contents of uhd swig ######################################################################## _prepare_uhd_swig() -from uhd_swig import * +from .uhd_swig import * diff --git a/gr-uhd/python/uhd/qa_uhd.py b/gr-uhd/python/uhd/qa_uhd.py index 4df0d4273e..bab029a9a8 100644 --- a/gr-uhd/python/uhd/qa_uhd.py +++ b/gr-uhd/python/uhd/qa_uhd.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + from gnuradio import gr, gr_unittest, uhd class test_uhd(gr_unittest.TestCase): @@ -50,7 +52,7 @@ class test_uhd(gr_unittest.TestCase): sa = uhd.stream_args_t() sa.channels.append(1) sa.channels.append(0) - print sa.channels + print(sa.channels) self.assertEqual(len(sa.channels), 2) self.assertEqual(sa.channels[0], 1) self.assertEqual(sa.channels[1], 0) diff --git a/gr-utils/CMakeLists.txt b/gr-utils/CMakeLists.txt index d54a06abd1..a8dfd91531 100644 --- a/gr-utils/CMakeLists.txt +++ b/gr-utils/CMakeLists.txt @@ -22,7 +22,7 @@ ######################################################################## include(GrPython) -GR_PYTHON_CHECK_MODULE("Mako >= 0.4.2" mako "mako.__version__ >= '0.4.2'" MAKO_FOUND) +GR_PYTHON_CHECK_MODULE("Mako >= ${GR_MAKO_MIN_VERSION}" mako "mako.__version__ >= '${GR_MAKO_MIN_VERSION}'" MAKO_FOUND) ######################################################################## # Register component diff --git a/gr-utils/python/modtool/__init__.py b/gr-utils/python/modtool/__init__.py index 897ff97fce..b6d719ac1d 100644 --- a/gr-utils/python/modtool/__init__.py +++ b/gr-utils/python/modtool/__init__.py @@ -1,3 +1,5 @@ +from __future__ import absolute_import +from __future__ import unicode_literals # # Copyright 2013-2014 Free Software Foundation, Inc. # @@ -19,17 +21,17 @@ # Boston, MA 02110-1301, USA. # -from cmakefile_editor import CMakeFileEditor -from grc_xml_generator import GRCXMLGenerator -from modtool_base import ModTool, ModToolException, get_modtool_modules -from modtool_add import ModToolAdd -from modtool_disable import ModToolDisable -from modtool_info import ModToolInfo -from modtool_makexml import ModToolMakeXML -from modtool_newmod import ModToolNewModule -from modtool_rm import ModToolRemove -from modtool_rename import ModToolRename -from templates import Templates +from .cmakefile_editor import CMakeFileEditor +from .grc_xml_generator import GRCXMLGenerator +from .modtool_base import ModTool, ModToolException, get_modtool_modules +from .modtool_add import ModToolAdd +from .modtool_disable import ModToolDisable +from .modtool_info import ModToolInfo +from .modtool_makexml import ModToolMakeXML +from .modtool_newmod import ModToolNewModule +from .modtool_rm import ModToolRemove +from .modtool_rename import ModToolRename +from .templates import Templates # Leave this at the end -from parser_cc_block import ParserCCBlock -from util_functions import * +from .parser_cc_block import ParserCCBlock +from .util_functions import * diff --git a/gr-utils/python/modtool/cmakefile_editor.py b/gr-utils/python/modtool/cmakefile_editor.py index d57c650c5e..eee555476f 100644 --- a/gr-utils/python/modtool/cmakefile_editor.py +++ b/gr-utils/python/modtool/cmakefile_editor.py @@ -20,6 +20,9 @@ # """ Edit CMakeLists.txt files """ +from __future__ import print_function +from __future__ import unicode_literals + import re class CMakeFileEditor(object): @@ -126,9 +129,9 @@ class CMakeFileEditor(object): 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: - print "Warning: A replacement failed when commenting out %s. Check the CMakeFile.txt manually." % fname + print("Warning: A replacement failed when commenting out %s. Check the CMakeFile.txt manually." % fname) elif nsubs > 1: - print "Warning: Replaced %s %d times (instead of once). Check the CMakeFile.txt manually." % (fname, nsubs) + print("Warning: Replaced %s %d times (instead of once). Check the CMakeFile.txt manually." % (fname, nsubs)) def comment_out_lines(self, pattern, comment_str='#'): """ Comments out all lines that match with pattern """ diff --git a/gr-utils/python/modtool/code_generator.py b/gr-utils/python/modtool/code_generator.py index 326b2d5986..d95434f577 100644 --- a/gr-utils/python/modtool/code_generator.py +++ b/gr-utils/python/modtool/code_generator.py @@ -19,14 +19,16 @@ # Boston, MA 02110-1301, USA. # """ A code generator (needed by ModToolAdd) """ +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 +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', diff --git a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrMiscUtils.cmake b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrMiscUtils.cmake index 319581c05e..c65a8ca725 100644 --- a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrMiscUtils.cmake +++ b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrMiscUtils.cmake @@ -341,7 +341,7 @@ if __name__ == '__main__': add_custom_command( OUTPUT ${expanded_files_h} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}.h.t ${ARGN} ) @@ -387,7 +387,7 @@ if __name__ == '__main__': add_custom_command( OUTPUT ${expanded_files_cc} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.cc.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}.cc.t ${ARGN} ) @@ -396,7 +396,7 @@ if __name__ == '__main__': add_custom_command( OUTPUT ${expanded_files_h} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}.h.t ${ARGN} ) @@ -450,7 +450,7 @@ if __name__ == '__main__': add_custom_command( OUTPUT ${expanded_files_cc_impl} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.cc.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}_impl.cc.t ${ARGN} ) @@ -459,7 +459,7 @@ if __name__ == '__main__': add_custom_command( OUTPUT ${expanded_files_h_impl} DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}_impl.h.t - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py ${root} ${root}_impl.h.t ${ARGN} ) diff --git a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPython.cmake b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPython.cmake index 0bfa92db8d..6b997c0869 100644 --- a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPython.cmake +++ b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrPython.cmake @@ -36,11 +36,12 @@ if(PYTHON_EXECUTABLE) else(PYTHON_EXECUTABLE) #use the built-in find script + set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6) find_package(PythonInterp 2) #and if that fails use the find program routine if(NOT PYTHONINTERP_FOUND) - find_program(PYTHON_EXECUTABLE NAMES python python2 python2.7 python2.6 python2.5) + find_program(PYTHON_EXECUTABLE NAMES python python2 python2.7) if(PYTHON_EXECUTABLE) set(PYTHONINTERP_FOUND TRUE) endif(PYTHON_EXECUTABLE) @@ -86,7 +87,7 @@ macro(GR_PYTHON_CHECK_MODULE desc mod cmd have) try: import ${mod} assert ${cmd} -except ImportError, AssertionError: exit(-1) +except (ImportError, AssertionError): exit(-1) except: pass #########################################" RESULT_VARIABLE ${have} @@ -106,7 +107,7 @@ endmacro(GR_PYTHON_CHECK_MODULE) if(NOT DEFINED GR_PYTHON_DIR) execute_process(COMMAND ${PYTHON_EXECUTABLE} -c " from distutils import sysconfig -print sysconfig.get_python_lib(plat_specific=True, prefix='') +print(sysconfig.get_python_lib(plat_specific=True, prefix='')) " OUTPUT_VARIABLE GR_PYTHON_DIR OUTPUT_STRIP_TRAILING_WHITESPACE ) endif() @@ -119,7 +120,7 @@ file(TO_CMAKE_PATH ${GR_PYTHON_DIR} GR_PYTHON_DIR) function(GR_UNIQUE_TARGET desc) file(RELATIVE_PATH reldir ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import re, hashlib -unique = hashlib.md5('${reldir}${ARGN}').hexdigest()[:5] +unique = hashlib.md5(b'${reldir}${ARGN}').hexdigest()[:5] print(re.sub('\\W', '_', '${desc} ${reldir} ' + unique))" OUTPUT_VARIABLE _target OUTPUT_STRIP_TRAILING_WHITESPACE) add_custom_target(${_target} ALL DEPENDS ${ARGN}) @@ -233,7 +234,7 @@ endfunction(GR_PYTHON_INSTALL) file(WRITE ${CMAKE_BINARY_DIR}/python_compile_helper.py " import sys, py_compile files = sys.argv[1:] -srcs, gens = files[:len(files)/2], files[len(files)/2:] +srcs, gens = files[:len(files)//2], files[len(files)//2:] for src, gen in zip(srcs, gens): py_compile.compile(file=src, cfile=gen, doraise=True) ") diff --git a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrSwig.cmake b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrSwig.cmake index 58699a7be0..2c163cac01 100644 --- a/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrSwig.cmake +++ b/gr-utils/python/modtool/gr-newmod/cmake/Modules/GrSwig.cmake @@ -76,7 +76,7 @@ function(GR_SWIG_MAKE_DOCS output_file) add_custom_command( OUTPUT ${output_file} DEPENDS ${input_files} ${stamp-file} ${OUTPUT_DIRECTORY}/xml/index.xml - COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + COMMAND ${PYTHON_EXECUTABLE} -B ${CMAKE_SOURCE_DIR}/docs/doxygen/swig_doc.py ${OUTPUT_DIRECTORY}/xml ${output_file} diff --git a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/__init__.py b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/__init__.py index 5cd0b3c6c5..b7a8884519 100644 --- a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/__init__.py +++ b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/__init__.py @@ -63,8 +63,9 @@ This line is uninformative and is only to test line breaks in the comments. u'Outputs the vital aadvark statistics.' """ +from __future__ import unicode_literals -from doxyindex import DoxyIndex, DoxyFunction, DoxyParam, DoxyClass, DoxyFile, DoxyNamespace, DoxyGroup, DoxyFriend, DoxyOther +from .doxyindex import DoxyIndex, DoxyFunction, DoxyParam, DoxyClass, DoxyFile, DoxyNamespace, DoxyGroup, DoxyFriend, DoxyOther def _test(): import os diff --git a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/base.py b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/base.py index e8f026ab90..0f0adf255b 100644 --- a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/base.py +++ b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/base.py @@ -24,24 +24,26 @@ A base class is created. Classes based upon this are used to make more user-friendly interfaces to the doxygen xml docs than the generated classes provide. """ +from __future__ import print_function +from __future__ import unicode_literals import os import pdb from xml.parsers.expat import ExpatError -from generated import compound +from .generated import compound class Base(object): - class Duplicate(StandardError): + class Duplicate(Exception): pass - class NoSuchMember(StandardError): + class NoSuchMember(Exception): pass - class ParsingError(StandardError): + class ParsingError(Exception): pass def __init__(self, parse_data, top=None): @@ -94,7 +96,7 @@ class Base(object): for cls in self.mem_classes: if cls.can_parse(mem): return cls - raise StandardError(("Did not find a class for object '%s'." \ + raise Exception(("Did not find a class for object '%s'." \ % (mem.get_name()))) def convert_mem(self, mem): @@ -102,11 +104,11 @@ class Base(object): cls = self.get_cls(mem) converted = cls.from_parse_data(mem, self.top) if converted is None: - raise StandardError('No class matched this object.') + raise Exception('No class matched this object.') self.add_ref(converted) return converted - except StandardError, e: - print e + except Exception as e: + print(e) @classmethod def includes(cls, inst): diff --git a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/doxyindex.py b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/doxyindex.py index 78e8153768..4284af25ec 100644 --- a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/doxyindex.py +++ b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/doxyindex.py @@ -22,12 +22,14 @@ Classes providing more user-friendly interfaces to the doxygen xml docs than the generated classes provide. """ +from __future__ import absolute_import +from __future__ import unicode_literals import os -from generated import index -from base import Base -from text import description +from .generated import index +from .base import Base +from .text import description class DoxyIndex(Base): """ diff --git a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/__init__.py b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/__init__.py index 39823979f6..23095c1f34 100644 --- a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/__init__.py +++ b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/__init__.py @@ -5,3 +5,4 @@ These do the real work of parsing the doxygen xml files but the resultant classes are not very friendly to navigate so the rest of the doxyxml module processes them further. """ +from __future__ import unicode_literals diff --git a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/compound.py b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/compound.py index 1522ac23f1..acfa0dd5c6 100644 --- a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/compound.py +++ b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/compound.py @@ -3,15 +3,17 @@ """ Generated Mon Feb 9 19:08:05 2009 by generateDS.py. """ +from __future__ import absolute_import +from __future__ import unicode_literals + -from string import lower as str_lower from xml.dom import minidom from xml.dom import Node import sys -import compoundsuper as supermod -from compoundsuper import MixedContainer +from . import compoundsuper as supermod +from .compoundsuper import MixedContainer class DoxygenTypeSub(supermod.DoxygenType): diff --git a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/compoundsuper.py b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/compoundsuper.py index 6255dda163..6e984e13ec 100644 --- a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/compoundsuper.py +++ b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/compoundsuper.py @@ -4,12 +4,17 @@ # Generated Thu Jun 11 18:44:25 2009 by generateDS.py. # +from __future__ import print_function +from __future__ import unicode_literals + import sys -import getopt -from string import lower as str_lower + from xml.dom import minidom from xml.dom import Node +import six + + # # User methods # @@ -19,9 +24,9 @@ from xml.dom import Node try: from generatedssuper import GeneratedsSuper -except ImportError, exp: +except ImportError as exp: - class GeneratedsSuper: + class GeneratedsSuper(object): def format_string(self, input_data, input_name=''): return input_data def format_integer(self, input_data, input_name=''): @@ -64,7 +69,7 @@ def showIndent(outfile, level): outfile.write(' ') def quote_xml(inStr): - s1 = (isinstance(inStr, basestring) and inStr or + s1 = (isinstance(inStr, six.string_types) and inStr or '%s' % inStr) s1 = s1.replace('&', '&') s1 = s1.replace('<', '<') @@ -72,7 +77,7 @@ def quote_xml(inStr): return s1 def quote_attrib(inStr): - s1 = (isinstance(inStr, basestring) and inStr or + s1 = (isinstance(inStr, six.string_types) and inStr or '%s' % inStr) s1 = s1.replace('&', '&') s1 = s1.replace('<', '<') @@ -102,7 +107,7 @@ def quote_python(inStr): return '"""%s"""' % s1 -class MixedContainer: +class MixedContainer(object): # Constants for category: CategoryNone = 0 CategoryText = 1 @@ -4221,7 +4226,7 @@ class codelineType(GeneratedsSuper): if attrs.get('lineno'): try: self.lineno = int(attrs.get('lineno').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (lineno): %s' % exp) if attrs.get('refkind'): self.refkind = attrs.get('refkind').value @@ -4504,12 +4509,12 @@ class referenceType(GeneratedsSuper): if attrs.get('endline'): try: self.endline = int(attrs.get('endline').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (endline): %s' % exp) if attrs.get('startline'): try: self.startline = int(attrs.get('startline').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (startline): %s' % exp) if attrs.get('refid'): self.refid = attrs.get('refid').value @@ -4627,17 +4632,17 @@ class locationType(GeneratedsSuper): if attrs.get('bodystart'): try: self.bodystart = int(attrs.get('bodystart').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (bodystart): %s' % exp) if attrs.get('line'): try: self.line = int(attrs.get('line').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (line): %s' % exp) if attrs.get('bodyend'): try: self.bodyend = int(attrs.get('bodyend').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (bodyend): %s' % exp) if attrs.get('bodyfile'): self.bodyfile = attrs.get('bodyfile').value @@ -6778,12 +6783,12 @@ class docTableType(GeneratedsSuper): if attrs.get('rows'): try: self.rows = int(attrs.get('rows').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (rows): %s' % exp) if attrs.get('cols'): try: self.cols = int(attrs.get('cols').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (cols): %s' % exp) def buildChildren(self, child_, nodeName_): if child_.nodeType == Node.ELEMENT_NODE and \ @@ -7108,7 +7113,7 @@ class docHeadingType(GeneratedsSuper): if attrs.get('level'): try: self.level = int(attrs.get('level').value) - except ValueError, exp: + except ValueError as exp: raise ValueError('Bad integer attribute (level): %s' % exp) def buildChildren(self, child_, nodeName_): if child_.nodeType == Node.TEXT_NODE: @@ -8283,7 +8288,7 @@ Options: """ def usage(): - print USAGE_TEXT + print(USAGE_TEXT) sys.exit(1) @@ -8339,4 +8344,3 @@ if __name__ == '__main__': main() #import pdb #pdb.run('main()') - diff --git a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/index.py b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/index.py index 7a70e14a1a..0c63512119 100644 --- a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/index.py +++ b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/index.py @@ -3,14 +3,16 @@ """ Generated Mon Feb 9 19:08:05 2009 by generateDS.py. """ +from __future__ import absolute_import +from __future__ import unicode_literals from xml.dom import minidom import os import sys -import compound +from . import compound -import indexsuper as supermod +from . import indexsuper as supermod class DoxygenTypeSub(supermod.DoxygenType): def __init__(self, version=None, compound=None): diff --git a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/indexsuper.py b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/indexsuper.py index a991530198..11312db635 100644 --- a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/indexsuper.py +++ b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/generated/indexsuper.py @@ -4,12 +4,16 @@ # Generated Thu Jun 11 18:43:54 2009 by generateDS.py. # +from __future__ import print_function +from __future__ import unicode_literals + import sys -import getopt -from string import lower as str_lower + from xml.dom import minidom from xml.dom import Node +import six + # # User methods # @@ -19,9 +23,9 @@ from xml.dom import Node try: from generatedssuper import GeneratedsSuper -except ImportError, exp: +except ImportError as exp: - class GeneratedsSuper: + class GeneratedsSuper(object): def format_string(self, input_data, input_name=''): return input_data def format_integer(self, input_data, input_name=''): @@ -64,7 +68,7 @@ def showIndent(outfile, level): outfile.write(' ') def quote_xml(inStr): - s1 = (isinstance(inStr, basestring) and inStr or + s1 = (isinstance(inStr, six.string_types) and inStr or '%s' % inStr) s1 = s1.replace('&', '&') s1 = s1.replace('<', '<') @@ -72,7 +76,7 @@ def quote_xml(inStr): return s1 def quote_attrib(inStr): - s1 = (isinstance(inStr, basestring) and inStr or + s1 = (isinstance(inStr, six.string_types) and inStr or '%s' % inStr) s1 = s1.replace('&', '&') s1 = s1.replace('<', '<') @@ -102,7 +106,7 @@ def quote_python(inStr): return '"""%s"""' % s1 -class MixedContainer: +class MixedContainer(object): # Constants for category: CategoryNone = 0 CategoryText = 1 @@ -462,7 +466,7 @@ Options: """ def usage(): - print USAGE_TEXT + print(USAGE_TEXT) sys.exit(1) @@ -520,4 +524,3 @@ if __name__ == '__main__': main() #import pdb #pdb.run('main()') - diff --git a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/text.py b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/text.py index 629edd180d..de2d19b532 100644 --- a/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/text.py +++ b/gr-utils/python/modtool/gr-newmod/docs/doxygen/doxyxml/text.py @@ -21,12 +21,13 @@ """ Utilities for extracting text from generated classes. """ +from __future__ import unicode_literals def is_string(txt): if isinstance(txt, str): return True try: - if isinstance(txt, unicode): + if isinstance(txt, str): return True except NameError: pass @@ -49,7 +50,7 @@ def description_bit(obj): elif is_string(obj): return obj else: - raise StandardError('Expecting a string or something with content, content_ or value attribute') + raise Exception('Expecting a string or something with content, content_ or value attribute') # If this bit is a paragraph then add one some line breaks. if hasattr(obj, 'name') and obj.name == 'para': result += "\n\n" diff --git a/gr-utils/python/modtool/gr-newmod/docs/doxygen/swig_doc.py b/gr-utils/python/modtool/gr-newmod/docs/doxygen/swig_doc.py index d3536db8d0..c735b1291b 100644 --- a/gr-utils/python/modtool/gr-newmod/docs/doxygen/swig_doc.py +++ b/gr-utils/python/modtool/gr-newmod/docs/doxygen/swig_doc.py @@ -26,6 +26,7 @@ The file instructs SWIG to transfer the doxygen comments into the python docstrings. """ +from __future__ import unicode_literals import sys, time @@ -309,7 +310,7 @@ if __name__ == "__main__": # Parse command line options and set up doxyxml. err_msg = "Execute using: python swig_doc.py xml_path outputfilename" if len(sys.argv) != 3: - raise StandardError(err_msg) + raise Exception(err_msg) xml_path = sys.argv[1] swigdocfilename = sys.argv[2] di = DoxyIndex(xml_path) diff --git a/gr-utils/python/modtool/gr-newmod/python/__init__.py b/gr-utils/python/modtool/gr-newmod/python/__init__.py index ed385a0abe..806f287cc3 100644 --- a/gr-utils/python/modtool/gr-newmod/python/__init__.py +++ b/gr-utils/python/modtool/gr-newmod/python/__init__.py @@ -22,6 +22,7 @@ This is the GNU Radio HOWTO module. Place your Python package description here (python/__init__.py). ''' +from __future__ import unicode_literals # import swig generated symbols into the howto namespace try: diff --git a/gr-utils/python/modtool/gr-newmod/python/build_utils.py b/gr-utils/python/modtool/gr-newmod/python/build_utils.py index cf58a97637..0b26844cbf 100644 --- a/gr-utils/python/modtool/gr-newmod/python/build_utils.py +++ b/gr-utils/python/modtool/gr-newmod/python/build_utils.py @@ -21,15 +21,17 @@ """Misc utilities used at build time """ +from __future__ import absolute_import +from __future__ import unicode_literals import re, os, os.path -from build_utils_codes import * +from .build_utils_codes import * # set srcdir to the directory that contains Makefile.am try: srcdir = os.environ['srcdir'] -except KeyError, e: +except KeyError as e: srcdir = "." srcdir = srcdir + '/' @@ -39,7 +41,7 @@ try: do_makefile = False else: do_makefile = True -except KeyError, e: +except KeyError as e: do_makefile = False # set do_sources to either true or false dependeing on the environment @@ -48,7 +50,7 @@ try: do_sources = False else: do_sources = True -except KeyError, e: +except KeyError as e: do_sources = True name_dict = {} @@ -127,7 +129,7 @@ def extract_extension (template_name): # we return everything between the penultimate . and .t mo = re.search (r'\.([a-z]+)\.t$', template_name) if not mo: - raise ValueError, "Incorrectly formed template_name '%s'" % (template_name,) + raise ValueError("Incorrectly formed template_name '%s'" % (template_name,)) return mo.group (1) def open_src (name, mode): diff --git a/gr-utils/python/modtool/gr-newmod/python/build_utils_codes.py b/gr-utils/python/modtool/gr-newmod/python/build_utils_codes.py index 9ea96baae4..22a6bdb99b 100644 --- a/gr-utils/python/modtool/gr-newmod/python/build_utils_codes.py +++ b/gr-utils/python/modtool/gr-newmod/python/build_utils_codes.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2004 Free Software Foundation, Inc. # diff --git a/gr-utils/python/modtool/grc_xml_generator.py b/gr-utils/python/modtool/grc_xml_generator.py index af17ca1822..1109701f7e 100644 --- a/gr-utils/python/modtool/grc_xml_generator.py +++ b/gr-utils/python/modtool/grc_xml_generator.py @@ -1,3 +1,4 @@ +from __future__ import absolute_import # # Copyright 2013 Free Software Foundation, Inc. # @@ -19,7 +20,7 @@ # Boston, MA 02110-1301, USA. # import xml.etree.ElementTree as ET -from util_functions import is_number, xml_indent +from .util_functions import is_number, xml_indent try: import lxml.etree diff --git a/gr-utils/python/modtool/modtool_add.py b/gr-utils/python/modtool/modtool_add.py index b7d33c6113..74f11318d0 100644 --- a/gr-utils/python/modtool/modtool_add.py +++ b/gr-utils/python/modtool/modtool_add.py @@ -20,14 +20,18 @@ # """ Module to add new blocks """ +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import os import re -from util_functions import append_re_line_sequence, ask_yes_no -from cmakefile_editor import CMakeFileEditor -from modtool_base import ModTool, ModToolException -from templates import Templates -from code_generator import render_template +from .util_functions import append_re_line_sequence, ask_yes_no +from .cmakefile_editor import CMakeFileEditor +from .modtool_base import ModTool, ModToolException +from .templates import Templates +from .code_generator import render_template class ModToolAdd(ModTool): """ Add block to the out-of-tree module. """ @@ -69,44 +73,44 @@ class ModToolAdd(ModTool): self._info['blocktype'] = options.block_type if self._info['blocktype'] is None: - # Print list out of blocktypes to user for reference - print str(self._block_types) + # Print(list out of blocktypes to user for reference) + print(str(self._block_types)) while self._info['blocktype'] not in self._block_types: - self._info['blocktype'] = raw_input("Enter block type: ") + self._info['blocktype'] = eval(input("Enter block type: ")) if self._info['blocktype'] not in self._block_types: - print 'Must be one of ' + str(self._block_types) + print('Must be one of ' + str(self._block_types)) # Allow user to specify language interactively if not set self._info['lang'] = options.lang if self._info['lang'] is None: while self._info['lang'] not in ['c++', 'cpp', 'python']: - self._info['lang'] = raw_input("Language (python/cpp): ") + self._info['lang'] = eval(input("Language (python/cpp): ")) if self._info['lang'] == 'c++': self._info['lang'] = 'cpp' - print "Language: %s" % {'cpp': 'C++', 'python': 'Python'}[self._info['lang']] + print("Language: %s" % {'cpp': 'C++', 'python': 'Python'}[self._info['lang']]) 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.') if self._info['blockname'] is None: - self._info['blockname'] = raw_input("Enter name of block/code (without module name prefix): ") + self._info['blockname'] = eval(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.') - print "Block/code identifier: " + self._info['blockname'] + print("Block/code identifier: " + self._info['blockname']) self._info['fullblockname'] = self._info['modname'] + '_' + self._info['blockname'] if not options.license_file: self._info['copyrightholder'] = options.copyright if self._info['copyrightholder'] is None: self._info['copyrightholder'] = '<+YOU OR YOUR COMPANY+>' elif self._info['is_component']: - print "For GNU Radio components the FSF is added as copyright holder" + print("For GNU Radio components the FSF is added as copyright holder") self._license_file = options.license_file self._info['license'] = self.setup_choose_license() if options.argument_list is not None: self._info['arglist'] = options.argument_list else: - self._info['arglist'] = raw_input('Enter valid argument list, including default arguments: ') + self._info['arglist'] = eval(input('Enter valid argument list, including default arguments: ')) if not (self._info['blocktype'] in ('noblock') or self._skip_subdirs['python']): self._add_py_qa = options.add_python_qa @@ -118,8 +122,8 @@ class ModToolAdd(ModTool): self._add_cc_qa = ask_yes_no('Add C++ QA code?', not self._add_py_qa) self._skip_cmakefiles = options.skip_cmakefiles if self._info['version'] == 'autofoo' and not self._skip_cmakefiles: - print "Warning: Autotools modules are not supported. ", - print "Files will be created, but Makefiles will not be edited." + print("Warning: Autotools modules are not supported. ", + "Files will be created, but Makefiles will not be edited.") self._skip_cmakefiles = True def setup_choose_license(self): @@ -143,7 +147,7 @@ class ModToolAdd(ModTool): def _write_tpl(self, tpl, path, fname): """ Shorthand for writing a substituted template to a file""" path_to_file = os.path.join(path, fname) - print "Adding file '%s'..." % path_to_file + print("Adding file '%s'..." % path_to_file) open(path_to_file, 'w').write(render_template(tpl, **self._info)) self.scm.add_files((path_to_file,)) @@ -197,7 +201,7 @@ class ModToolAdd(ModTool): ) self.scm.mark_files_updated((self._file['qalib'],)) except IOError: - print "Can't add C++ QA files." + print("Can't add C++ QA files.") fname_cc = None fname_h = None if self._info['version'] == '37': @@ -218,9 +222,9 @@ class ModToolAdd(ModTool): if self._info['version'] == '37': _add_qa() elif self._info['version'] == '36': - print "Warning: C++ QA files not supported for 3.6-style OOTs." + print("Warning: C++ QA files not supported for 3.6-style OOTs.") elif self._info['version'] == 'autofoo': - print "Warning: C++ QA files not supported for autotools." + print("Warning: C++ QA files not supported for autotools.") if not self._skip_cmakefiles: ed = CMakeFileEditor(self._file['cmlib']) cmake_list_var = '[a-z]*_?' + self._info['modname'] + '_sources' @@ -237,9 +241,9 @@ class ModToolAdd(ModTool): - Edit main *.i file """ if self._get_mainswigfile() is None: - print 'Warning: No main swig file found.' + print('Warning: No main swig file found.') return - print "Editing %s..." % self._file['swig'] + print("Editing %s..." % self._file['swig']) mod_block_sep = '/' if self._info['version'] == '36': mod_block_sep = '_' @@ -266,11 +270,11 @@ class ModToolAdd(ModTool): """ fname_py_qa = 'qa_' + self._info['blockname'] + '.py' self._write_tpl('qa_python', self._info['pydir'], fname_py_qa) - os.chmod(os.path.join(self._info['pydir'], fname_py_qa), 0755) + os.chmod(os.path.join(self._info['pydir'], fname_py_qa), 0o755) self.scm.mark_files_updated((os.path.join(self._info['pydir'], fname_py_qa),)) if self._skip_cmakefiles or CMakeFileEditor(self._file['cmpython']).check_for_glob('qa_*.py'): return - print "Editing %s/CMakeLists.txt..." % self._info['pydir'] + print("Editing %s/CMakeLists.txt..." % self._info['pydir']) open(self._file['cmpython'], 'a').write( 'GR_ADD_TEST(qa_%s ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/%s)\n' % \ (self._info['blockname'], fname_py_qa)) @@ -307,7 +311,7 @@ class ModToolAdd(ModTool): ed = CMakeFileEditor(self._file['cmgrc'], '\n ') if self._skip_cmakefiles or ed.check_for_glob('*.xml'): return - print "Editing grc/CMakeLists.txt..." + print("Editing grc/CMakeLists.txt...") ed.append_value('install', fname_grc, to_ignore_end='DESTINATION[^()]+') ed.write() self.scm.mark_files_updated((self._file['cmgrc'],)) diff --git a/gr-utils/python/modtool/modtool_base.py b/gr-utils/python/modtool/modtool_base.py index 990e63af14..e0ae963f20 100644 --- a/gr-utils/python/modtool/modtool_base.py +++ b/gr-utils/python/modtool/modtool_base.py @@ -20,13 +20,17 @@ # """ Base class for the modules """ +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import os import re from argparse import ArgumentParser, RawDescriptionHelpFormatter from gnuradio import gr -from util_functions import get_modname -from scm import SCMRepoFactory +from .util_functions import get_modname +from .scm import SCMRepoFactory class ModToolException(BaseException): """ Standard exception for modtool classes. """ @@ -94,7 +98,7 @@ class ModTool(object): self._info['modname'] = get_modname() if self._info['modname'] is None: raise ModToolException('No GNU Radio module found in the given directory.') - print "GNU Radio module name identified: " + self._info['modname'] + print("GNU Radio module name identified: " + self._info['modname']) if self._info['version'] == '36' and ( os.path.isdir(os.path.join('include', self._info['modname'])) or os.path.isdir(os.path.join('include', 'gnuradio', self._info['modname'])) @@ -144,7 +148,7 @@ class ModTool(object): else: self.scm = SCMRepoFactory(self.options, '.').make_empty_scm_manager() if self.scm is None: - print "Error: Can't set up SCM." + print("Error: Can't set up SCM.") exit(1) def _check_directory(self, directory): @@ -156,7 +160,7 @@ class ModTool(object): files = os.listdir(directory) os.chdir(directory) except OSError: - print "Can't read or chdir to directory %s." % directory + print("Can't read or chdir to directory %s." % directory) return False self._info['is_component'] = False for f in files: @@ -170,11 +174,11 @@ class ModTool(object): has_makefile = True # TODO search for autofoo elif os.path.isdir(f): - if (f in self._has_subdirs.keys()): + if (f in list(self._has_subdirs.keys())): self._has_subdirs[f] = True else: self._skip_subdirs[f] = True - return bool(has_makefile and (self._has_subdirs.values())) + return bool(has_makefile and (list(self._has_subdirs.values()))) def _get_mainswigfile(self): """ Find out which name the main SWIG file has. In particular, is it diff --git a/gr-utils/python/modtool/modtool_disable.py b/gr-utils/python/modtool/modtool_disable.py index 1772a740f3..629a810cb0 100644 --- a/gr-utils/python/modtool/modtool_disable.py +++ b/gr-utils/python/modtool/modtool_disable.py @@ -20,12 +20,16 @@ # """ Disable blocks module """ +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import os import re import sys -from modtool_base import ModTool -from cmakefile_editor import CMakeFileEditor +from .modtool_base import ModTool +from .cmakefile_editor import CMakeFileEditor class ModToolDisable(ModTool): @@ -46,7 +50,7 @@ class ModToolDisable(ModTool): if options.blockname is not None: self._info['pattern'] = options.blockname else: - self._info['pattern'] = raw_input('Which blocks do you want to disable? (Regex): ') + self._info['pattern'] = eval(input('Which blocks do you want to disable? (Regex): ')) if len(self._info['pattern']) == 0: self._info['pattern'] = '.' @@ -62,7 +66,7 @@ class ModToolDisable(ModTool): try: initfile = open(self._file['pyinit']).read() except IOError: - print "Could not edit __init__.py, that might be a problem." + print("Could not edit __init__.py, that might be a problem.") return False pymodname = os.path.splitext(fname)[0] initfile = re.sub(r'((from|import)\s+\b'+pymodname+r'\b)', r'#\1', initfile) @@ -93,14 +97,14 @@ class ModToolDisable(ModTool): self._info['modname'], fname), r'//\1', swigfile) if nsubs > 0: - print "Changing %s..." % self._file['swig'] + print("Changing %s..." % self._file['swig']) if nsubs > 1: # Need to find a single BLOCK_MAGIC blockname = os.path.splitext(fname[len(self._info['modname'])+1:])[0] if self._info['version'] == '37': blockname = os.path.splitext(fname)[0] (swigfile, nsubs) = re.subn('(GR_SWIG_BLOCK_MAGIC2?.+%s.+;)' % blockname, r'//\1', swigfile) if nsubs > 1: - print "Hm, changed more then expected while editing %s." % self._file['swig'] + print("Hm, changed more then expected while editing %s." % self._file['swig']) open(self._file['swig'], 'w').write(swigfile) self.scm.mark_file_updated(self._file['swig']) return False @@ -112,7 +116,7 @@ class ModToolDisable(ModTool): if self._info['version'] == '37': blockname = os.path.splitext(fname)[0] swigfile = re.sub('(%include\s+"'+fname+'")', r'//\1', swigfile) - print "Changing %s..." % self._file['swig'] + print("Changing %s..." % self._file['swig']) swigfile = re.sub('(GR_SWIG_BLOCK_MAGIC2?.+'+blockname+'.+;)', r'//\1', swigfile) open(self._file['swig'], 'w').write(swigfile) self.scm.mark_file_updated(self._file['swig']) @@ -135,13 +139,13 @@ class ModToolDisable(ModTool): cmake = CMakeFileEditor(os.path.join(subdir, 'CMakeLists.txt')) except IOError: continue - print "Traversing %s..." % subdir + print("Traversing %s..." % subdir) filenames = cmake.find_filenames_match(self._info['pattern']) yes = self._info['yes'] for fname in filenames: file_disabled = False if not yes: - ans = raw_input("Really disable %s? [Y/n/a/q]: " % fname).lower().strip() + ans = input("Really disable %s? [Y/n/a/q]: " % fname).lower().strip() if ans == 'a': yes = True if ans == 'q': @@ -155,5 +159,5 @@ class ModToolDisable(ModTool): cmake.disable_file(fname) cmake.write() self.scm.mark_files_updated((os.path.join(subdir, 'CMakeLists.txt'),)) - print "Careful: 'gr_modtool disable' does not resolve dependencies." + print("Careful: 'gr_modtool disable' does not resolve dependencies.") diff --git a/gr-utils/python/modtool/modtool_info.py b/gr-utils/python/modtool/modtool_info.py index 317948239e..4be302e03e 100644 --- a/gr-utils/python/modtool/modtool_info.py +++ b/gr-utils/python/modtool/modtool_info.py @@ -1,4 +1,3 @@ -# # Copyright 2013 Free Software Foundation, Inc. # # This file is part of GNU Radio @@ -20,10 +19,14 @@ # """ Returns information about a module """ +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import os -from modtool_base import ModTool, ModToolException -from util_functions import get_modname +from .modtool_base import ModTool, ModToolException +from .util_functions import get_modname class ModToolInfo(ModTool): @@ -70,7 +73,7 @@ class ModToolInfo(ModTool): ): self._info['version'] = '37' mod_info['version'] = self._info['version'] - if 'is_component' in self._info.keys() and self._info['is_component']: + if 'is_component' in list(self._info.keys()) and self._info['is_component']: mod_info['is_component'] = True mod_info['incdirs'] = [] mod_incl_dir = os.path.join(mod_info['base_dir'], 'include') @@ -83,7 +86,7 @@ class ModToolInfo(ModTool): mod_info['build_dir'] = build_dir mod_info['incdirs'] += self._get_include_dirs(mod_info) if self._python_readable: - print str(mod_info) + print(str(mod_info)) else: self._pretty_print(mod_info) @@ -106,7 +109,7 @@ class ModToolInfo(ModTool): If that hasn't happened, the build dir cannot be detected, unless it's called 'build', which is then assumed to be the build dir. """ base_build_dir = mod_info['base_dir'] - if 'is_component' in mod_info.keys(): + if 'is_component' in list(mod_info.keys()): (base_build_dir, rest_dir) = os.path.split(base_build_dir) has_build_dir = os.path.isdir(os.path.join(base_build_dir , 'build')) if (has_build_dir and os.path.isfile(os.path.join(base_build_dir, 'CMakeCache.txt'))): @@ -123,7 +126,7 @@ class ModToolInfo(ModTool): """ Figure out include dirs for the make process. """ inc_dirs = [] path_or_internal = {True: 'INTERNAL', - False: 'PATH'}['is_component' in mod_info.keys()] + False: 'PATH'}['is_component' in list(mod_info.keys())] try: cmakecache_fid = open(os.path.join(mod_info['build_dir'], 'CMakeCache.txt')) for line in cmakecache_fid: @@ -135,19 +138,19 @@ class ModToolInfo(ModTool): inc_dirs = [os.path.normpath(path) for path in self._suggested_dirs.split(':') if os.path.isdir(path)] return inc_dirs - def _pretty_print(self, mod_info): + def _pretty_print(elf, mod_info): """ Output the module info in human-readable format """ index_names = {'base_dir': 'Base directory', 'modname': 'Module name', 'is_component': 'Is GR component', 'build_dir': 'Build directory', 'incdirs': 'Include directories'} - for key in mod_info.keys(): + for key in list(mod_info.keys()): if key == 'version': - print " API version: %s" % { + print(" API version: %s" % { '36': 'pre-3.7', '37': 'post-3.7', 'autofoo': 'Autotools (pre-3.5)' - }[mod_info['version']] + }[mod_info['version']]) else: - print '%19s: %s' % (index_names[key], mod_info[key]) + print('%19s: %s' % (index_names[key], mod_info[key])) diff --git a/gr-utils/python/modtool/modtool_makexml.py b/gr-utils/python/modtool/modtool_makexml.py index 311ed96cb4..dffd403a37 100644 --- a/gr-utils/python/modtool/modtool_makexml.py +++ b/gr-utils/python/modtool/modtool_makexml.py @@ -20,15 +20,19 @@ # """ Automatically create XML bindings for GRC from block code """ +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import os import re import glob -from modtool_base import ModTool, ModToolException -from parser_cc_block import ParserCCBlock -from grc_xml_generator import GRCXMLGenerator -from cmakefile_editor import CMakeFileEditor -from util_functions import ask_yes_no +from .modtool_base import ModTool, ModToolException +from .parser_cc_block import ParserCCBlock +from .grc_xml_generator import GRCXMLGenerator +from .cmakefile_editor import CMakeFileEditor +from .util_functions import ask_yes_no class ModToolMakeXML(ModTool): @@ -54,13 +58,13 @@ class ModToolMakeXML(ModTool): if options.blockname is not None: self._info['pattern'] = options.blockname else: - self._info['pattern'] = raw_input('Which blocks do you want to parse? (Regex): ') + self._info['pattern'] = eval(input('Which blocks do you want to parse? (Regex): ')) if len(self._info['pattern']) == 0: self._info['pattern'] = '.' def run(self, options): """ Go, go, go! """ - print "Warning: This is an experimental feature. Don't expect any magic." + print("Warning: This is an experimental feature. Don't expect any magic.") self.setup(options) # 1) Go through lib/ if not self._skip_subdirs['lib']: @@ -80,12 +84,12 @@ class ModToolMakeXML(ModTool): """ Search for files matching pattern in the given path. """ files = sorted(glob.glob("%s/%s"% (path, path_glob))) files_filt = [] - print "Searching for matching files in %s/:" % path + print("Searching for matching files in %s/:" % path) for f in files: if re.search(self._info['pattern'], os.path.basename(f)) is not None: files_filt.append(f) if len(files_filt) == 0: - print "None found." + print("None found.") return files_filt def _make_grc_xml_from_block_data(self, params, iosig, blockname): @@ -110,7 +114,7 @@ class ModToolMakeXML(ModTool): return else: file_exists = True - print "Warning: Overwriting existing GRC file." + print("Warning: Overwriting existing GRC file.") grc_generator = GRCXMLGenerator( modname=self._info['modname'], blockname=blockname, @@ -125,7 +129,7 @@ class ModToolMakeXML(ModTool): if not self._skip_subdirs['grc']: ed = CMakeFileEditor(self._file['cmgrc']) if re.search(fname_xml, ed.cfile) is None and not ed.check_for_glob('*.xml'): - print "Adding GRC bindings to grc/CMakeLists.txt..." + print("Adding GRC bindings to grc/CMakeLists.txt...") ed.append_value('install', fname_xml, to_ignore_end='DESTINATION[^()]+') ed.write() self.scm.mark_files_updated(self._file['cmgrc']) @@ -158,7 +162,7 @@ class ModToolMakeXML(ModTool): blockname = blockname.replace(self._info['modname']+'_', '', 1) return (blockname, fname_h) # Go, go, go - print "Making GRC bindings for %s..." % fname_cc + print("Making GRC bindings for %s..." % fname_cc) (blockname, fname_h) = _get_blockdata(fname_cc) try: parser = ParserCCBlock(fname_cc, diff --git a/gr-utils/python/modtool/modtool_newmod.py b/gr-utils/python/modtool/modtool_newmod.py index 4382d9be7d..b3e384d122 100644 --- a/gr-utils/python/modtool/modtool_newmod.py +++ b/gr-utils/python/modtool/modtool_newmod.py @@ -20,12 +20,16 @@ # """ Create a whole new out-of-tree module """ +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import shutil import os import re from gnuradio import gr -from modtool_base import ModTool, ModToolException -from scm import SCMRepoFactory +from .modtool_base import ModTool, ModToolException +from .scm import SCMRepoFactory class ModToolNewModule(ModTool): """ Create a new out-of-tree module """ @@ -49,7 +53,7 @@ class ModToolNewModule(ModTool): if options.module_name: self._info['modname'] = options.module_name else: - self._info['modname'] = raw_input('Name of the new module: ') + self._info['modname'] = eval(input('Name of the new module: ')) if not re.match('[a-zA-Z0-9_]+$', self._info['modname']): raise ModToolException('Invalid module name.') self._dir = options.directory @@ -76,7 +80,7 @@ class ModToolNewModule(ModTool): * Rename files and directories that contain the word howto """ self.setup(options) - print "Creating out-of-tree module in %s..." % self._dir, + print("Creating out-of-tree module in %s..." % (self._dir,)) try: shutil.copytree(self._srcdir, self._dir) os.chdir(self._dir) @@ -93,8 +97,8 @@ class ModToolNewModule(ModTool): os.rename(f, os.path.join(root, filename.replace('howto', self._info['modname']))) if os.path.basename(root) == 'howto': os.rename(root, os.path.join(os.path.dirname(root), self._info['modname'])) - print "Done." + print("Done.") if self.scm.init_repo(path_to_repo="."): - print "Created repository... you might want to commit before continuing." - print "Use 'gr_modtool add' to add a new block to this currently empty module." + print("Created repository... you might want to commit before continuing.") + print("Use 'gr_modtool add' to add a new block to this currently empty module.") diff --git a/gr-utils/python/modtool/modtool_rename.py b/gr-utils/python/modtool/modtool_rename.py index f0ff412a89..4973aa9e78 100644 --- a/gr-utils/python/modtool/modtool_rename.py +++ b/gr-utils/python/modtool/modtool_rename.py @@ -20,13 +20,17 @@ # """ Module to rename blocks """ +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import os import re -from util_functions import append_re_line_sequence, ask_yes_no -from cmakefile_editor import CMakeFileEditor -from modtool_base import ModTool, ModToolException -from templates import Templates +from .util_functions import append_re_line_sequence, ask_yes_no +from .cmakefile_editor import CMakeFileEditor +from .modtool_base import ModTool, ModToolException +from .templates import Templates class ModToolRename(ModTool): """ Rename a block in the out-of-tree module. """ @@ -58,20 +62,20 @@ class ModToolRename(ModTool): # first make sure the old block name is provided self._info['oldname'] = options.blockname if self._info['oldname'] is None: - self._info['oldname'] = raw_input("Enter name of block/code to rename (without module name prefix): ") + self._info['oldname'] = eval(input("Enter name of block/code to rename (without module name prefix): ")) if not re.match('[a-zA-Z0-9_]+', self._info['oldname']): raise ModToolException('Invalid block name.') - print "Block/code to rename identifier: " + self._info['oldname'] + print("Block/code to rename identifier: " + self._info['oldname']) self._info['fulloldname'] = self._info['modname'] + '_' + self._info['oldname'] # now get the new block name if options.new_name is None: - self._info['newname'] = raw_input("Enter name of block/code (without module name prefix): ") + self._info['newname'] = eval(input("Enter name of block/code (without module name prefix): ")) else: self._info['newname'] = options.new_name[0] if not re.match('[a-zA-Z0-9_]+', self._info['newname']): raise ModToolException('Invalid block name.') - print "Block/code identifier: " + self._info['newname'] + print("Block/code identifier: " + self._info['newname']) self._info['fullnewname'] = self._info['modname'] + '_' + self._info['newname'] def run(self, options): @@ -80,7 +84,7 @@ class ModToolRename(ModTool): module = self._info['modname'] oldname = self._info['oldname'] newname = self._info['newname'] - print "In module '%s' rename block '%s' to '%s'" % (module, oldname, newname) + print("In module '%s' rename block '%s' to '%s'" % (module, oldname, newname)) self._run_swig_rename(self._file['swig'], oldname, newname) self._run_grc_rename(self._info['modname'], oldname, newname) self._run_python_qa(self._info['modname'], oldname, newname) @@ -93,11 +97,11 @@ class ModToolRename(ModTool): """ Rename SWIG includes and block_magic """ nsubs = self._run_file_replace(swigfilename, old, new) if nsubs < 1: - print "Couldn't find '%s' in file '%s'." % (old, swigfilename) + print("Couldn't find '%s' in file '%s'." % (old, swigfilename)) if nsubs == 2: - print "Changing 'noblock' type file" + print("Changing 'noblock' type file") if nsubs > 3: - print "Hm, changed more then expected while editing %s." % swigfilename + print("Hm, changed more then expected while editing %s." % swigfilename) return False def _run_lib(self, module, old, new): @@ -117,7 +121,7 @@ class ModToolRename(ModTool): filename = 'qa_' + module + '.cc' nsubs = self._run_file_replace(path + filename, old, new) if nsubs > 0: - print "C++ QA code detected, renaming..." + print("C++ QA code detected, renaming...") filename = 'qa_' + old + '.cc' self._run_file_replace(path + filename, old, new) filename = 'qa_' + old + '.h' @@ -125,7 +129,7 @@ class ModToolRename(ModTool): self._run_file_replace(path + filename, old.upper(), new.upper()) self._run_file_rename(path, 'qa_' + old, 'qa_' + new) else: - print "No C++ QA code detected, skipping..." + print("No C++ QA code detected, skipping...") def _run_include(self, module, old, new): path = './include/' + module + '/' @@ -140,13 +144,13 @@ class ModToolRename(ModTool): filename = '__init__.py' nsubs = self._run_file_replace(path + filename, old, new) if nsubs > 0: - print "Python block detected, renaming..." + print("Python block detected, renaming...") filename = old + '.py' self._run_file_replace(path + filename, old, new) self._run_cmakelists(path, old, new) self._run_file_rename(path, old, new) else: - print "Not a Python block, nothing to do here..." + print("Not a Python block, nothing to do here...") def _run_python_qa(self, module, old, new): new = 'qa_' + new @@ -166,7 +170,7 @@ class ModToolRename(ModTool): filename = path + 'CMakeLists.txt' nsubs = self._run_file_replace(filename, first, second) if nsubs < 1: - print "'%s' wasn't in '%s'." % (first, filename) + print("'%s' wasn't in '%s'." % (first, filename)) def _run_file_rename(self, path, old, new): files = os.listdir(path) @@ -175,14 +179,14 @@ class ModToolRename(ModTool): nl = file.replace(old, new) src = path + file dst = path + nl - print "Renaming file '%s' to '%s'." % (src, dst) + print("Renaming file '%s' to '%s'." % (src, dst)) os.rename(src, dst) def _run_file_replace(self, filename, old, new): if not os.path.isfile(filename): return False else: - print "In '%s' renaming occurences of '%s' to '%s'" % (filename, old, new) + print("In '%s' renaming occurences of '%s' to '%s'" % (filename, old, new)) cfile = open(filename).read() (cfile, nsubs) = re.subn(old, new, cfile) diff --git a/gr-utils/python/modtool/modtool_rm.py b/gr-utils/python/modtool/modtool_rm.py index d1061aac8c..248d1b7ca8 100644 --- a/gr-utils/python/modtool/modtool_rm.py +++ b/gr-utils/python/modtool/modtool_rm.py @@ -20,14 +20,18 @@ # """ Remove blocks module """ +from __future__ import print_function +from __future__ import absolute_import +from __future__ import unicode_literals + import os import re import sys import glob -from util_functions import remove_pattern_from_file -from modtool_base import ModTool -from cmakefile_editor import CMakeFileEditor +from .util_functions import remove_pattern_from_file +from .modtool_base import ModTool +from .cmakefile_editor import CMakeFileEditor class ModToolRemove(ModTool): @@ -48,7 +52,7 @@ class ModToolRemove(ModTool): if options.blockname is not None: self._info['pattern'] = options.blockname else: - self._info['pattern'] = raw_input('Which blocks do you want to delete? (Regex): ') + self._info['pattern'] = eval(input('Which blocks do you want to delete? (Regex): ')) if len(self._info['pattern']) == 0: self._info['pattern'] = '.' @@ -132,12 +136,12 @@ class ModToolRemove(ModTool): for g in globs: files = files + sorted(glob.glob("%s/%s"% (path, g))) files_filt = [] - print "Searching for matching files in %s/:" % path + print("Searching for matching files in %s/:" % path) for f in files: if re.search(self._info['pattern'], os.path.basename(f)) is not None: files_filt.append(f) if len(files_filt) == 0: - print "None found." + print("None found.") return [] # 2. Delete files, Makefile entries and other occurrences files_deleted = [] @@ -146,7 +150,7 @@ class ModToolRemove(ModTool): for f in files_filt: b = os.path.basename(f) if not yes: - ans = raw_input("Really delete %s? [Y/n/a/q]: " % f).lower().strip() + ans = input("Really delete %s? [Y/n/a/q]: " % f).lower().strip() if ans == 'a': yes = True if ans == 'q': @@ -154,10 +158,10 @@ class ModToolRemove(ModTool): if ans == 'n': continue files_deleted.append(b) - print "Deleting %s." % f + print("Deleting %s." % f) self.scm.remove_file(f) os.unlink(f) - print "Deleting occurrences of %s from %s/CMakeLists.txt..." % (b, path) + print("Deleting occurrences of %s from %s/CMakeLists.txt..." % (b, path)) for var in makefile_vars: ed.remove_value(var, b) if cmakeedit_func is not None: diff --git a/gr-utils/python/modtool/parser_cc_block.py b/gr-utils/python/modtool/parser_cc_block.py index 703522c8fb..fffdf309d8 100644 --- a/gr-utils/python/modtool/parser_cc_block.py +++ b/gr-utils/python/modtool/parser_cc_block.py @@ -19,6 +19,10 @@ # Boston, MA 02110-1301, USA. # ''' A parser for blocks written in C++ ''' + +from __future__ import print_function +from __future__ import unicode_literals + import re import sys @@ -42,7 +46,7 @@ class ParserCCBlock(object): E.g., for sizeof(int), it will return 'int'. Returns a list! """ if 'gr::io_signature::makev' in iosigcall: - print 'tbi' + print('tbi') raise ValueError return {'type': [_typestr_to_iotype(x) for x in typestr.split(',')], 'vlen': [_typestr_to_vlen(x) for x in typestr.split(',')] @@ -82,15 +86,15 @@ class ParserCCBlock(object): iosig_match.group('intype')) iosig['in']['min_ports'] = iosig_match.group('inmin') iosig['in']['max_ports'] = iosig_match.group('inmax') - except ValueError, Exception: - print "Error: Can't parse input signature." + except Exception: + print("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 ValueError, Exception: - print "Error: Can't parse output signature." + except Exception: + print("Error: Can't parse output signature.") return iosig @@ -213,7 +217,7 @@ class ParserCCBlock(object): try: params_list = _scan_param_list(make_match.end(0)) except ValueError as ve: - print "Can't parse the argument list: ", ve.args[0] + print("Can't parse the argument list: ", ve.args[0]) sys.exit(0) params = [] for plist in params_list: diff --git a/gr-utils/python/modtool/scm.py b/gr-utils/python/modtool/scm.py index ec6023ab3b..f219cc3aaa 100644 --- a/gr-utils/python/modtool/scm.py +++ b/gr-utils/python/modtool/scm.py @@ -20,6 +20,9 @@ # """ Class to handle source code management repositories. """ +from __future__ import print_function +from __future__ import unicode_literals + import subprocess try: @@ -191,12 +194,12 @@ class SCMRepoFactory(object): """ Returns a valid, usable object of type SCMRepository. """ if self.options.scm_mode == 'no': return SCMRepository(self.path_to_repo) - for glbl in globals().values(): + for glbl in list(globals().values()): try: if issubclass(glbl, SCMRepository): the_scm = glbl(self.path_to_repo) if the_scm.is_active(): - print 'Found SCM of type:', the_scm.handles_scm_type + print('Found SCM of type:', the_scm.handles_scm_type) return the_scm except (TypeError, AttributeError, InvalidSCMError): pass @@ -208,7 +211,7 @@ class SCMRepoFactory(object): """ Returns a valid, usable object of type SCMRepository for an unitialized dir. """ if self.options.scm_mode == 'no': return SCMRepository(self.path_to_repo) - for glbl in globals().values(): + for glbl in list(globals().values()): try: if issubclass(glbl, SCMRepository): if glbl.handles_scm_type == scm_type: diff --git a/gr-utils/python/modtool/templates.py b/gr-utils/python/modtool/templates.py index 3829f7a644..64c99802fe 100644 --- a/gr-utils/python/modtool/templates.py +++ b/gr-utils/python/modtool/templates.py @@ -19,6 +19,7 @@ # Boston, MA 02110-1301, USA. # ''' All the templates for skeleton files (needed by ModToolAdd) ''' +from __future__ import unicode_literals from datetime import datetime diff --git a/gr-utils/python/modtool/util_functions.py b/gr-utils/python/modtool/util_functions.py index de7f3d29b6..6197da638a 100644 --- a/gr-utils/python/modtool/util_functions.py +++ b/gr-utils/python/modtool/util_functions.py @@ -19,6 +19,7 @@ # Boston, MA 02110-1301, USA. # """ Utility functions for gr_modtool """ +from __future__ import unicode_literals import re import sys @@ -97,7 +98,7 @@ def get_modname(): 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 modname_trans.keys(): + if modname in list(modname_trans.keys()): modname = modname_trans[modname] return modname except AttributeError: @@ -131,7 +132,7 @@ 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 raw_input(question).lower() != {True: 'n', False: 'y'}[default]: + if input(question).lower() != {True: 'n', False: 'y'}[default]: return default else: return not default diff --git a/gr-utils/python/utils/gr_modtool b/gr-utils/python/utils/gr_modtool index d9016840be..49c58f5b48 100755 --- a/gr-utils/python/utils/gr_modtool +++ b/gr-utils/python/utils/gr_modtool @@ -21,6 +21,8 @@ # """ A tool for editing GNU Radio out-of-tree modules. """ +from __future__ import print_function + from gnuradio.modtool import * @@ -46,7 +48,7 @@ def main(): try: args.module().run(args) except ModToolException as err: - print >> sys.stderr, err + print(err, file=sys.stderr) exit(1) if __name__ == '__main__': diff --git a/gr-utils/python/utils/gr_plot_char b/gr-utils/python/utils/gr_plot_char index ee644557bb..3199919fa9 100755 --- a/gr-utils/python/utils/gr_plot_char +++ b/gr-utils/python/utils/gr_plot_char @@ -20,11 +20,13 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + try: import scipy except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) from argparse import ArgumentParser from gnuradio.plot_data import plot_data diff --git a/gr-utils/python/utils/gr_plot_const b/gr-utils/python/utils/gr_plot_const index 653a2539b4..2ec54c3585 100755 --- a/gr-utils/python/utils/gr_plot_const +++ b/gr-utils/python/utils/gr_plot_const @@ -20,18 +20,20 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + try: import scipy except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) try: from pylab import * from matplotlib.font_manager import fontManager, FontProperties except ImportError: - print "Please install Matplotlib to run this script (http://matplotlib.sourceforge.net/)" - raise SystemExit, 1 + print("Please install Matplotlib to run this script (http://matplotlib.sourceforge.net/)") + raise SystemExit(1) from argparse import ArgumentParser @@ -83,7 +85,7 @@ class draw_constellation: try: iq = scipy.fromfile(self.hfile, dtype=self.datatype, count=self.block_length) except MemoryError: - print "End of File" + print("End of File") else: # retesting length here as newer version of scipy does not throw a MemoryError, just # returns a zero-length array @@ -94,7 +96,7 @@ class draw_constellation: self.time = scipy.array([i*(1/self.sample_rate) for i in range(len(self.reals))]) return True else: - print "End of File" + print("End of File") return False def make_plots(self): @@ -215,9 +217,9 @@ class draw_constellation: def find(item_in, list_search): try: - return list_search.index(item_in) != None + return list_search.index(item_in) != None except ValueError: - return False + return False def main(): @@ -241,6 +243,3 @@ if __name__ == "__main__": main() except KeyboardInterrupt: pass - - - diff --git a/gr-utils/python/utils/gr_plot_float b/gr-utils/python/utils/gr_plot_float index faf8106d70..4fd86549e2 100755 --- a/gr-utils/python/utils/gr_plot_float +++ b/gr-utils/python/utils/gr_plot_float @@ -20,11 +20,13 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + try: import scipy except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) from argparse import ArgumentParser from gnuradio.plot_data import plot_data diff --git a/gr-utils/python/utils/gr_plot_int b/gr-utils/python/utils/gr_plot_int index c687f13b17..b4051fa15f 100755 --- a/gr-utils/python/utils/gr_plot_int +++ b/gr-utils/python/utils/gr_plot_int @@ -23,8 +23,8 @@ try: import scipy except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) from argparse import ArgumentParser from gnuradio.plot_data import plot_data diff --git a/gr-utils/python/utils/gr_plot_iq b/gr-utils/python/utils/gr_plot_iq index 7409b73909..f27f75d412 100755 --- a/gr-utils/python/utils/gr_plot_iq +++ b/gr-utils/python/utils/gr_plot_iq @@ -20,17 +20,19 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + try: import scipy except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) try: from pylab import * except ImportError: - print "Please install Matplotlib to run this script (http://matplotlib.sourceforge.net/)" - raise SystemExit, 1 + print("Please install Matplotlib to run this script (http://matplotlib.sourceforge.net/)") + raise SystemExit(1) from argparse import ArgumentParser @@ -81,7 +83,7 @@ class draw_iq: try: self.iq = scipy.fromfile(self.hfile, dtype=self.datatype, count=self.block_length) except MemoryError: - print "End of File" + print("End of File") else: self.reals = scipy.array([r.real for r in self.iq]) self.imags = scipy.array([i.imag for i in self.iq]) @@ -144,9 +146,9 @@ class draw_iq: def find(item_in, list_search): try: - return list_search.index(item_in) != None + return list_search.index(item_in) != None except ValueError: - return False + return False def main(): description = "Takes a GNU Radio complex binary file and displays the I&Q data versus time. You can set the block size to specify how many points to read in at a time and the start position in the file. By default, the system assumes a sample rate of 1, so in time, each sample is plotted versus the sample number. To set a true time axis, set the sample rate (-R or --sample-rate) to the sample rate used when capturing the samples." @@ -170,6 +172,3 @@ if __name__ == "__main__": main() except KeyboardInterrupt: pass - - - diff --git a/gr-utils/python/utils/gr_plot_qt b/gr-utils/python/utils/gr_plot_qt index 9205d23a7e..cd2db87fd9 100755 --- a/gr-utils/python/utils/gr_plot_qt +++ b/gr-utils/python/utils/gr_plot_qt @@ -4,34 +4,34 @@ try: import scipy from scipy import fftpack except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) try: from matplotlib import mlab except ImportError: - print "Please install Matplotlib to run this script (http://matplotlib.sourceforge.net)" - raise SystemExit, 1 + print("Please install Matplotlib to run this script (http://matplotlib.sourceforge.net)") + raise SystemExit(1) try: from PyQt4 import Qt, QtCore, QtGui except ImportError: - print "Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)" - raise SystemExit, 1 + print("Please install PyQt4 to run this script (http://www.riverbankcomputing.co.uk/software/pyqt/download)") + raise SystemExit(1) try: import PyQt4.Qwt5 as Qwt except ImportError: - print "Please install PyQwt5 to run this script (http://pyqwt.sourceforge.net/)" - raise SystemExit, 1 + print("Please install PyQwt5 to run this script (http://pyqwt.sourceforge.net/)") + raise SystemExit(1) try: # FIXME: re-enable this before committing #from gnuradio.pyqt_plot import Ui_MainWindow from gnuradio.pyqt_plot import Ui_MainWindow except ImportError: - print "Could not import from pyqt_plot. Please build with \"pyuic4 pyqt_plot.ui -o pyqt_plot.py\"" - raise SystemExit, 1 + print("Could not import from pyqt_plot. Please build with \"pyuic4 pyqt_plot.ui -o pyqt_plot.py\"") + raise SystemExit(1) import sys, os from optparse import OptionParser @@ -284,7 +284,7 @@ class gr_plot_qt(QtGui.QMainWindow): def open_file(self): filename = Qt.QFileDialog.getOpenFileName(self, "Open", ".") if(filename != ""): - #print filename + #print(filename) self.initialize(filename) def reload_file(self): @@ -320,7 +320,7 @@ class gr_plot_qt(QtGui.QMainWindow): def init_data_input(self): self.hfile.seek(0, os.SEEK_END) self.signal_size = self.hfile.tell()/self.sizeof_data - #print "Sizeof File: ", self.signal_size + #print("Sizeof File: ", self.signal_size) self.hfile.seek(0, os.SEEK_SET) def get_data(self, start, end): diff --git a/gr-utils/python/utils/gr_plot_short b/gr-utils/python/utils/gr_plot_short index f900af1bac..d367ea381f 100755 --- a/gr-utils/python/utils/gr_plot_short +++ b/gr-utils/python/utils/gr_plot_short @@ -20,11 +20,13 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + try: import scipy except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) from argparse import ArgumentParser from gnuradio.plot_data import plot_data diff --git a/gr-utils/python/utils/gr_read_file_metadata b/gr-utils/python/utils/gr_read_file_metadata index a05e7ad2c7..1a94560ad2 100644 --- a/gr-utils/python/utils/gr_read_file_metadata +++ b/gr-utils/python/utils/gr_read_file_metadata @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function + import sys from argparse import ArgumentParser @@ -45,7 +47,7 @@ def main(filename, detached=False): sys.stderr.write("Could not deserialize header: invalid or corrupt data file.\n") sys.exit(1) - print "HEADER {0}".format(nheaders) + print("HEADER {0}".format(nheaders)) info = parse_file_metadata.parse_header(header, True) if(info["extra_len"] > 0): @@ -59,7 +61,7 @@ def main(filename, detached=False): sys.stderr.write("Could not deserialize extras: invalid or corrupt data file.\n") sys.exit(1) - print "\nExtra Header:" + print("\nExtra Header:") extra_info = parse_file_metadata.parse_extra_dict(extra, info, True) nheaders += 1 @@ -67,7 +69,7 @@ def main(filename, detached=False): if(not detached): nread += info['nbytes'] handle.seek(nread, 0) - print "\n\n" + print("\n\n") if __name__ == "__main__": diff --git a/gr-utils/python/utils/plot_data.py b/gr-utils/python/utils/plot_data.py index 7d80c714fe..a054147114 100644 --- a/gr-utils/python/utils/plot_data.py +++ b/gr-utils/python/utils/plot_data.py @@ -22,20 +22,24 @@ Utility to help plotting data from files. """ +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + try: import scipy except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) try: from pylab import * except ImportError: - print "Please install Matplotlib to run this script (http://matplotlib.sourceforge.net/)" - raise SystemExit, 1 + print("Please install Matplotlib to run this script (http://matplotlib.sourceforge.net/)") + raise SystemExit(1) -class plot_data: +class plot_data(object): def __init__(self, datatype, filenames, options): self.hfile = list() self.legend_text = list() @@ -86,10 +90,10 @@ class plot_data: try: f = scipy.fromfile(hfile, dtype=self.datatype, count=self.block_length) except MemoryError: - print "End of File" + print("End of File") else: self.f = scipy.array(f) - self.time = scipy.array([i*(1/self.sample_rate) for i in range(len(self.f))]) + self.time = scipy.array([i*(1 / self.sample_rate) for i in range(len(self.f))]) def make_plots(self): self.sp_f = self.fig.add_subplot(2,1,1, position=[0.075, 0.2, 0.875, 0.6]) @@ -162,6 +166,6 @@ class plot_data: def find(item_in, list_search): try: - return list_search.index(item_in) != None + return list_search.index(item_in) != None except ValueError: - return False + return False diff --git a/gr-utils/python/utils/plot_fft_base.py b/gr-utils/python/utils/plot_fft_base.py index c99462147d..c0651529ea 100755..100644 --- a/gr-utils/python/utils/plot_fft_base.py +++ b/gr-utils/python/utils/plot_fft_base.py @@ -20,22 +20,26 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + try: import scipy from scipy import fftpack except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) try: from pylab import * except ImportError: - print "Please install Python Matplotlib (http://matplotlib.sourceforge.net/) and Python TkInter https://wiki.python.org/moin/TkInter to run this script" - raise SystemExit, 1 + print("Please install Python Matplotlib (http://matplotlib.sourceforge.net/) and Python TkInter https://wiki.python.org/moin/TkInter to run this script") + raise SystemExit(1) from argparse import ArgumentParser -class plot_fft_base: +class plot_fft_base(object): def __init__(self, datatype, filename, options): self.hfile = open(filename, "r") self.block_length = options.block @@ -79,33 +83,33 @@ class plot_fft_base: show() def get_data(self): - self.position = self.hfile.tell()/self.sizeof_data + self.position = self.hfile.tell() / self.sizeof_data self.text_file_pos.set_text("File Position: %d" % (self.position)) try: self.iq = scipy.fromfile(self.hfile, dtype=self.datatype, count=self.block_length) except MemoryError: - print "End of File" + print("End of File") else: self.iq_fft = self.dofft(self.iq) tstep = 1.0 / self.sample_rate #self.time = scipy.array([tstep*(self.position + i) for i in xrange(len(self.iq))]) - self.time = scipy.array([tstep*(i) for i in xrange(len(self.iq))]) + self.time = scipy.array([tstep*(i) for i in range(len(self.iq))]) self.freq = self.calc_freq(self.time, self.sample_rate) def dofft(self, iq): N = len(iq) iq_fft = scipy.fftpack.fftshift(scipy.fft(iq)) # fft and shift axis - iq_fft = 20*scipy.log10(abs((iq_fft+1e-15)/N)) # convert to decibels, adjust power + iq_fft = 20*scipy.log10(abs((iq_fft+1e-15) / N)) # convert to decibels, adjust power # adding 1e-15 (-300 dB) to protect against value errors if an item in iq_fft is 0 return iq_fft def calc_freq(self, time, sample_rate): N = len(time) - Fs = 1.0 / (time.max() - time.min()) + Fs = 1.0 / (time.max( - time.min())) Fn = 0.5 * sample_rate - freq = scipy.array([-Fn + i*Fs for i in xrange(N)]) + freq = scipy.array([-Fn + i*Fs for i in range(N)]) return freq def make_plots(self): @@ -228,9 +232,9 @@ class plot_fft_base: def find(item_in, list_search): try: - return list_search.index(item_in) != None + return list_search.index(item_in) != None except ValueError: - return False + return False def main(): parser = plot_fft_base.setup_options() @@ -243,6 +247,3 @@ if __name__ == "__main__": main() except KeyboardInterrupt: pass - - - diff --git a/gr-utils/python/utils/plot_psd_base.py b/gr-utils/python/utils/plot_psd_base.py index 2611ed4be2..7c5138be4d 100755..100644 --- a/gr-utils/python/utils/plot_psd_base.py +++ b/gr-utils/python/utils/plot_psd_base.py @@ -20,24 +20,28 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import division +from __future__ import unicode_literals + try: import scipy from scipy import fftpack except ImportError: - print "Please install SciPy to run this script (http://www.scipy.org/)" - raise SystemExit, 1 + print("Please install SciPy to run this script (http://www.scipy.org/)") + raise SystemExit(1) try: from pylab import * except ImportError: - print "Please install Matplotlib to run this script (http://matplotlib.sourceforge.net/)" - raise SystemExit, 1 + print("Please install Matplotlib to run this script (http://matplotlib.sourceforge.net/)") + raise SystemExit(1) from argparse import ArgumentParser from scipy import log10 from gnuradio.eng_arg import eng_float, intx -class plot_psd_base: +class plot_psd_base(object): def __init__(self, datatype, filename, options): self.hfile = open(filename, "r") self.block_length = options.block @@ -87,12 +91,12 @@ class plot_psd_base: show() def get_data(self): - self.position = self.hfile.tell()/self.sizeof_data + self.position = self.hfile.tell() / self.sizeof_data self.text_file_pos.set_text("File Position: %d" % self.position) try: self.iq = scipy.fromfile(self.hfile, dtype=self.datatype, count=self.block_length) except MemoryError: - print "End of File" + print("End of File") return False else: # retesting length here as newer version of scipy does not throw a MemoryError, just @@ -100,17 +104,17 @@ class plot_psd_base: if(len(self.iq) > 0): tstep = 1.0 / self.sample_rate #self.time = scipy.array([tstep*(self.position + i) for i in xrange(len(self.iq))]) - self.time = scipy.array([tstep*(i) for i in xrange(len(self.iq))]) + self.time = scipy.array([tstep*(i) for i in range(len(self.iq))]) self.iq_psd, self.freq = self.dopsd(self.iq) return True else: - print "End of File" + print("End of File") return False def dopsd(self, iq): ''' Need to do this here and plot later so we can do the fftshift ''' - overlap = self.psdfftsize/4 + overlap = self.psdfftsize / 4 winfunc = scipy.blackman psd,freq = mlab.psd(iq, self.psdfftsize, self.sample_rate, window = lambda d: d*winfunc(self.psdfftsize), @@ -174,7 +178,7 @@ class plot_psd_base: self.sp_psd.set_xlim([f.min(), f.max()]) def draw_spec(self, t, s): - overlap = self.specfftsize/4 + overlap = self.specfftsize / 4 winfunc = scipy.blackman self.sp_spec.clear() self.sp_spec.specgram(s, self.specfftsize, self.sample_rate, @@ -270,9 +274,9 @@ class plot_psd_base: def find(item_in, list_search): try: - return list_search.index(item_in) != None + return list_search.index(item_in) != None except ValueError: - return False + return False def main(): parser = plot_psd_base.setup_options() @@ -285,6 +289,3 @@ if __name__ == "__main__": main() except KeyboardInterrupt: pass - - - diff --git a/gr-utils/python/utils/pyqt_filter.py b/gr-utils/python/utils/pyqt_filter.py index 0c781f2347..fac17644d3 100644 --- a/gr-utils/python/utils/pyqt_filter.py +++ b/gr-utils/python/utils/pyqt_filter.py @@ -7,6 +7,7 @@ # # WARNING! All changes made in this file will be lost! +from __future__ import unicode_literals from PyQt4 import QtCore, QtGui class Ui_MainWindow(object): diff --git a/gr-utils/python/utils/pyqt_plot.py b/gr-utils/python/utils/pyqt_plot.py index 5650135abf..80711b4e88 100644 --- a/gr-utils/python/utils/pyqt_plot.py +++ b/gr-utils/python/utils/pyqt_plot.py @@ -7,6 +7,7 @@ # # WARNING! All changes made in this file will be lost! +from __future__ import unicode_literals from PyQt4 import QtCore, QtGui class Ui_MainWindow(object): diff --git a/gr-video-sdl/python/video_sdl/CMakeLists.txt b/gr-video-sdl/python/video_sdl/CMakeLists.txt index 6465affa10..f4ae6bd29a 100644 --- a/gr-video-sdl/python/video_sdl/CMakeLists.txt +++ b/gr-video-sdl/python/video_sdl/CMakeLists.txt @@ -43,6 +43,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-video-sdl/python/video_sdl/__init__.py b/gr-video-sdl/python/video_sdl/__init__.py index 4bad11831c..1bcf83ad1d 100644 --- a/gr-video-sdl/python/video_sdl/__init__.py +++ b/gr-video-sdl/python/video_sdl/__init__.py @@ -21,6 +21,7 @@ ''' Blocks and utilities for Video SDL module ''' +from __future__ import unicode_literals # The presence of this file turns this directory into a Python package import os diff --git a/gr-video-sdl/python/video_sdl/qa_video_sdl.py b/gr-video-sdl/python/video_sdl/qa_video_sdl.py index f94957ccc4..cb0201cba2 100755..100644 --- a/gr-video-sdl/python/video_sdl/qa_video_sdl.py +++ b/gr-video-sdl/python/video_sdl/qa_video_sdl.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, video_sdl class test_video_sdl (gr_unittest.TestCase): diff --git a/gr-vocoder/examples/alaw_audio_loopback.py b/gr-vocoder/examples/alaw_audio_loopback.py index 5b800b5bfb..6f43322470 100755..100644 --- a/gr-vocoder/examples/alaw_audio_loopback.py +++ b/gr-vocoder/examples/alaw_audio_loopback.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks @@ -33,7 +35,7 @@ def build_graph(): enc = vocoder.alaw_encode_sb() dec = vocoder.alaw_decode_bs() s2f = blocks.short_to_float() - sink_scale = blocks.multiply_const_ff(1.0/32767.) + sink_scale = blocks.multiply_const_ff(1.0 / 32767.) sink = audio.sink(8000) tb.connect(src, src_scale, f2s, enc, dec, s2f, sink_scale, sink) return tb @@ -41,6 +43,6 @@ def build_graph(): if __name__ == '__main__': tb = build_graph() tb.start() - raw_input ('Press Enter to exit: ') + eval(input ('Press Enter to exit: ')) tb.stop() tb.wait() diff --git a/gr-vocoder/examples/codec2_audio_loopback.py b/gr-vocoder/examples/codec2_audio_loopback.py index b63d508025..9c51d2f49c 100755..100644 --- a/gr-vocoder/examples/codec2_audio_loopback.py +++ b/gr-vocoder/examples/codec2_audio_loopback.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks @@ -34,7 +36,7 @@ def build_graph(): enc = vocoder.codec2_encode_sp(codec2.MODE_2400) dec = vocoder.codec2_decode_ps(codec2.MODE_2400) s2f = blocks.short_to_float() - sink_scale = blocks.multiply_const_ff(1.0/32767.) + sink_scale = blocks.multiply_const_ff(1.0 / 32767.) sink = audio.sink(8000) tb.connect(src, src_scale, f2s, enc, dec, s2f, sink_scale, sink) return tb @@ -42,6 +44,6 @@ def build_graph(): if __name__ == '__main__': tb = build_graph() tb.start() - raw_input ('Press Enter to exit: ') + eval(input ('Press Enter to exit: ')) tb.stop() tb.wait() diff --git a/gr-vocoder/examples/cvsd_audio_loopback.py b/gr-vocoder/examples/cvsd_audio_loopback.py index b9385b7dc6..603a7194a4 100755..100644 --- a/gr-vocoder/examples/cvsd_audio_loopback.py +++ b/gr-vocoder/examples/cvsd_audio_loopback.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks @@ -43,7 +45,7 @@ def build_graph(): s2f = blocks.short_to_float() decim = filter.rational_resampler_fff(1, 8) - sink_scale = blocks.multiply_const_ff(1.0/scale_factor) + sink_scale = blocks.multiply_const_ff(1.0 / scale_factor) sink = audio.sink(sample_rate, "plughw:0,0") tb.connect(src, src_scale, interp, f2s, enc) @@ -65,6 +67,6 @@ def build_graph(): if __name__ == '__main__': tb = build_graph() tb.start() - raw_input ('Press Enter to exit: ') + eval(input ('Press Enter to exit: ')) tb.stop() tb.wait() diff --git a/gr-vocoder/examples/g721_audio_loopback.py b/gr-vocoder/examples/g721_audio_loopback.py index 42abbabf64..790cbfcb48 100755..100644 --- a/gr-vocoder/examples/g721_audio_loopback.py +++ b/gr-vocoder/examples/g721_audio_loopback.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks @@ -33,7 +35,7 @@ def build_graph(): enc = vocoder.g721_encode_sb() dec = vocoder.g721_decode_bs() s2f = blocks.short_to_float() - sink_scale = blocks.multiply_const_ff(1.0/32767.) + sink_scale = blocks.multiply_const_ff(1.0 / 32767.) sink = audio.sink(8000) tb.connect(src, src_scale, f2s, enc, dec, s2f, sink_scale, sink) return tb @@ -41,6 +43,6 @@ def build_graph(): if __name__ == '__main__': tb = build_graph() tb.start() - raw_input ('Press Enter to exit: ') + eval(input ('Press Enter to exit: ')) tb.stop() tb.wait() diff --git a/gr-vocoder/examples/g723_24_audio_loopback.py b/gr-vocoder/examples/g723_24_audio_loopback.py index cade33f295..7390aa0151 100755..100644 --- a/gr-vocoder/examples/g723_24_audio_loopback.py +++ b/gr-vocoder/examples/g723_24_audio_loopback.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks @@ -33,7 +35,7 @@ def build_graph(): enc = vocoder.g723_24_encode_sb() dec = vocoder.g723_24_decode_bs() s2f = blocks.short_to_float() - sink_scale = blocks.multiply_const_ff(1.0/32767.) + sink_scale = blocks.multiply_const_ff(1.0 / 32767.) sink = audio.sink(8000) tb.connect(src, src_scale, f2s, enc, dec, s2f, sink_scale, sink) return tb @@ -41,6 +43,6 @@ def build_graph(): if __name__ == '__main__': tb = build_graph() tb.start() - raw_input ('Press Enter to exit: ') + eval(input ('Press Enter to exit: ')) tb.stop() tb.wait() diff --git a/gr-vocoder/examples/g723_40_audio_loopback.py b/gr-vocoder/examples/g723_40_audio_loopback.py index 77e40884cf..c016193382 100755..100644 --- a/gr-vocoder/examples/g723_40_audio_loopback.py +++ b/gr-vocoder/examples/g723_40_audio_loopback.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks @@ -33,7 +35,7 @@ def build_graph(): enc = vocoder.g723_40_encode_sb() dec = vocoder.g723_40_decode_bs() s2f = blocks.short_to_float() - sink_scale = blocks.multiply_const_ff(1.0/32767.) + sink_scale = blocks.multiply_const_ff(1.0 / 32767.) sink = audio.sink(8000) tb.connect(src, src_scale, f2s, enc, dec, s2f, sink_scale, sink) return tb @@ -41,6 +43,6 @@ def build_graph(): if __name__ == '__main__': tb = build_graph() tb.start() - raw_input ('Press Enter to exit: ') + eval(input ('Press Enter to exit: ')) tb.stop() tb.wait() diff --git a/gr-vocoder/examples/gsm_audio_loopback.py b/gr-vocoder/examples/gsm_audio_loopback.py index 5d5bf9dd72..b21b9da410 100755..100644 --- a/gr-vocoder/examples/gsm_audio_loopback.py +++ b/gr-vocoder/examples/gsm_audio_loopback.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks @@ -33,7 +35,7 @@ def build_graph(): enc = vocoder.gsm_fr_encode_sp() dec = vocoder.gsm_fr_decode_ps() s2f = blocks.short_to_float() - sink_scale = blocks.multiply_const_ff(1.0/32767.) + sink_scale = blocks.multiply_const_ff(1.0 / 32767.) sink = audio.sink(8000) tb.connect(src, src_scale, f2s, enc, dec, s2f, sink_scale, sink) return tb @@ -41,6 +43,6 @@ def build_graph(): if __name__ == '__main__': tb = build_graph() tb.start() - raw_input ('Press Enter to exit: ') + eval(input ('Press Enter to exit: ')) tb.stop() tb.wait() diff --git a/gr-vocoder/examples/ulaw_audio_loopback.py b/gr-vocoder/examples/ulaw_audio_loopback.py index 9f0617622e..aeb7411e0b 100755..100644 --- a/gr-vocoder/examples/ulaw_audio_loopback.py +++ b/gr-vocoder/examples/ulaw_audio_loopback.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr from gnuradio import audio from gnuradio import blocks @@ -33,7 +35,7 @@ def build_graph(): enc = vocoder.ulaw_encode_sb() dec = vocoder.ulaw_decode_bs() s2f = blocks.short_to_float() - sink_scale = blocks.multiply_const_ff(1.0/32767.) + sink_scale = blocks.multiply_const_ff(1.0 / 32767.) sink = audio.sink(8000) tb.connect(src, src_scale, f2s, enc, dec, s2f, sink_scale, sink) return tb @@ -41,6 +43,6 @@ def build_graph(): if __name__ == '__main__': tb = build_graph() tb.start() - raw_input ('Press Enter to exit: ') + eval(input ('Press Enter to exit: ')) tb.stop() tb.wait() diff --git a/gr-vocoder/python/vocoder/CMakeLists.txt b/gr-vocoder/python/vocoder/CMakeLists.txt index d4fe3d9e8c..464cc4ff33 100644 --- a/gr-vocoder/python/vocoder/CMakeLists.txt +++ b/gr-vocoder/python/vocoder/CMakeLists.txt @@ -61,6 +61,6 @@ if(ENABLE_TESTING) endif() foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${CMAKE_CURRENT_SOURCE_DIR}/${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${CMAKE_CURRENT_SOURCE_DIR}/${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-vocoder/python/vocoder/__init__.py b/gr-vocoder/python/vocoder/__init__.py index 7b1b82f847..3f4c301d96 100644 --- a/gr-vocoder/python/vocoder/__init__.py +++ b/gr-vocoder/python/vocoder/__init__.py @@ -23,13 +23,16 @@ This is the gr-vocoder package. This package includes the various vocoder blocks in GNU Radio. ''' +from __future__ import absolute_import +from __future__ import unicode_literals + import os try: - from vocoder_swig import * + from .vocoder_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from vocoder_swig import * + from .vocoder_swig import * -from cvsd import * +from .cvsd import * diff --git a/gr-vocoder/python/vocoder/cvsd.py b/gr-vocoder/python/vocoder/cvsd.py index b6ce822935..00a24df25f 100644 --- a/gr-vocoder/python/vocoder/cvsd.py +++ b/gr-vocoder/python/vocoder/cvsd.py @@ -20,8 +20,11 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division +from __future__ import unicode_literals from gnuradio import gr, filter, blocks -import vocoder_swig +from . import vocoder_swig + class cvsd_encode_fb(gr.hier_block2): ''' @@ -39,9 +42,9 @@ class cvsd_encode_fb(gr.hier_block2): from 1 to 8. A rate of 8k with a resampling rate of 8 provides a good quality signal. ''' - gr.hier_block2.__init__(self, "cvsd_encode", - gr.io_signature(1, 1, gr.sizeof_float), # Input signature - gr.io_signature(1, 1, gr.sizeof_char)) # Output signature + gr.hier_block2.__init__(self, "cvsd_encode", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_char)) # Output signature scale_factor = 32000.0 self.interp = resample @@ -70,9 +73,9 @@ class cvsd_decode_bf(gr.hier_block2): When using the CVSD vocoder, appropriate sampling rates are from 8k to 64k with resampling rates from 1 to 8. A rate of 8k with a resampling rate of 8 provides a good quality signal. ''' - gr.hier_block2.__init__(self, "cvsd_decode", - gr.io_signature(1, 1, gr.sizeof_char), # Input signature - gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + gr.hier_block2.__init__(self, "cvsd_decode", + gr.io_signature(1, 1, gr.sizeof_char), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature scale_factor = 32000.0 self.decim = resample @@ -81,6 +84,6 @@ class cvsd_decode_bf(gr.hier_block2): s2f = blocks.short_to_float() taps = filter.firdes.low_pass(1, 1, bw, 2*bw) decim = filter.fir_filter_fff(self.decim, taps) - sink_scale = blocks.multiply_const_ff(1.0/scale_factor) + sink_scale = blocks.multiply_const_ff(1.0 / scale_factor) self.connect(self, dec, s2f, decim, sink_scale, self) diff --git a/gr-vocoder/python/vocoder/qa_alaw_vocoder.py b/gr-vocoder/python/vocoder/qa_alaw_vocoder.py index 4a2b4c3c8b..e2398a2016 100755..100644 --- a/gr-vocoder/python/vocoder/qa_alaw_vocoder.py +++ b/gr-vocoder/python/vocoder/qa_alaw_vocoder.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, vocoder, blocks class test_alaw_vocoder (gr_unittest.TestCase): diff --git a/gr-vocoder/python/vocoder/qa_codec2_vocoder.py b/gr-vocoder/python/vocoder/qa_codec2_vocoder.py index 8fe3ac56b5..8c7656cb49 100755..100644 --- a/gr-vocoder/python/vocoder/qa_codec2_vocoder.py +++ b/gr-vocoder/python/vocoder/qa_codec2_vocoder.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, vocoder, blocks from gnuradio.vocoder import codec2 diff --git a/gr-vocoder/python/vocoder/qa_cvsd_vocoder.py b/gr-vocoder/python/vocoder/qa_cvsd_vocoder.py index 408c6b74c9..b1516e0ef8 100755..100644 --- a/gr-vocoder/python/vocoder/qa_cvsd_vocoder.py +++ b/gr-vocoder/python/vocoder/qa_cvsd_vocoder.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, vocoder, blocks, filter from gnuradio.vocoder import cvsd diff --git a/gr-vocoder/python/vocoder/qa_g721_vocoder.py b/gr-vocoder/python/vocoder/qa_g721_vocoder.py index 8808b8fede..ad1e85471f 100755..100644 --- a/gr-vocoder/python/vocoder/qa_g721_vocoder.py +++ b/gr-vocoder/python/vocoder/qa_g721_vocoder.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, vocoder, blocks class test_g721_vocoder (gr_unittest.TestCase): diff --git a/gr-vocoder/python/vocoder/qa_g723_24_vocoder.py b/gr-vocoder/python/vocoder/qa_g723_24_vocoder.py index c587623e1d..755cde922c 100755..100644 --- a/gr-vocoder/python/vocoder/qa_g723_24_vocoder.py +++ b/gr-vocoder/python/vocoder/qa_g723_24_vocoder.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, vocoder, blocks class test_g723_24_vocoder (gr_unittest.TestCase): diff --git a/gr-vocoder/python/vocoder/qa_g723_40_vocoder.py b/gr-vocoder/python/vocoder/qa_g723_40_vocoder.py index 689102237f..911de9f66f 100755..100644 --- a/gr-vocoder/python/vocoder/qa_g723_40_vocoder.py +++ b/gr-vocoder/python/vocoder/qa_g723_40_vocoder.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, vocoder, blocks class test_g723_40_vocoder (gr_unittest.TestCase): diff --git a/gr-vocoder/python/vocoder/qa_gsm_full_rate.py b/gr-vocoder/python/vocoder/qa_gsm_full_rate.py index 69ea94bbf9..5cca230455 100755..100644 --- a/gr-vocoder/python/vocoder/qa_gsm_full_rate.py +++ b/gr-vocoder/python/vocoder/qa_gsm_full_rate.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, vocoder, blocks class test_gsm_vocoder (gr_unittest.TestCase): diff --git a/gr-vocoder/python/vocoder/qa_ulaw_vocoder.py b/gr-vocoder/python/vocoder/qa_ulaw_vocoder.py index 46c8d490a8..8cfc13fc05 100755..100644 --- a/gr-vocoder/python/vocoder/qa_ulaw_vocoder.py +++ b/gr-vocoder/python/vocoder/qa_ulaw_vocoder.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, vocoder, blocks class test_ulaw_vocoder (gr_unittest.TestCase): diff --git a/gr-wavelet/python/wavelet/CMakeLists.txt b/gr-wavelet/python/wavelet/CMakeLists.txt index 9e1961d4e0..493a24d1cd 100644 --- a/gr-wavelet/python/wavelet/CMakeLists.txt +++ b/gr-wavelet/python/wavelet/CMakeLists.txt @@ -41,6 +41,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-wavelet/python/wavelet/__init__.py b/gr-wavelet/python/wavelet/__init__.py index 7f3d9afa53..8fbab42f59 100644 --- a/gr-wavelet/python/wavelet/__init__.py +++ b/gr-wavelet/python/wavelet/__init__.py @@ -22,11 +22,12 @@ ''' Processing blocks for wavelet transforms. ''' +from __future__ import unicode_literals import os try: - from wavelet_swig import * + from .wavelet_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from wavelet_swig import * + from .wavelet_swig import * diff --git a/gr-wavelet/python/wavelet/qa_classify.py b/gr-wavelet/python/wavelet/qa_classify.py index 4752620f4d..7f562c628e 100755..100644 --- a/gr-wavelet/python/wavelet/qa_classify.py +++ b/gr-wavelet/python/wavelet/qa_classify.py @@ -20,6 +20,8 @@ # Boston, MA 02110-1301, USA. # +from __future__ import division + import numpy from gnuradio import gr, gr_unittest, wavelet, analog, blocks import copy @@ -79,14 +81,14 @@ class test_classify(gr_unittest.TestCase): def test_002_(self): src_data = numpy.array([-1.0, - -1.0/2.0, - -1.0/3.0, - -1.0/4.0, - -1.0/5.0]) + -1.0 / 2.0, + -1.0 / 3.0, + -1.0 / 4.0, + -1.0 / 5.0]) trg_data = copy.deepcopy(src_data) src = blocks.vector_source_f(src_data, False, len(src_data)) - st = blocks.stretch_ff(-1.0/5.0, len(src_data)) + st = blocks.stretch_ff(-1.0 / 5.0, len(src_data)) dst = blocks.vector_sink_f(len(src_data)) self.tb.connect(src, st) self.tb.connect(st, dst) @@ -155,11 +157,11 @@ class test_classify(gr_unittest.TestCase): dwav = numpy.array(src_data) wvps = numpy.zeros(3) # wavelet power spectrum - scl = 1.0/sqr(dwav[0]) + scl = 1.0 / sqr(dwav[0]) k = 1 for e in range(len(wvps)): - wvps[e] = scl*sqr(dwav[k:k+(01<<e)]).sum() - k += 01<<e + wvps[e] = scl*sqr(dwav[k:k+(0o1<<e)]).sum() + k += 0o1<<e src = blocks.vector_source_f(src_data, False, len(src_data)) kon = wavelet.wvps_ff(len(src_data)) diff --git a/gr-zeromq/examples/python/client.py b/gr-zeromq/examples/python/client.py index ca7ad1830a..39055bd3fb 100755..100644 --- a/gr-zeromq/examples/python/client.py +++ b/gr-zeromq/examples/python/client.py @@ -1,3 +1,5 @@ +from __future__ import print_function +from __future__ import unicode_literals # # Copyright 2013 Free Software Foundation, Inc. # @@ -67,14 +69,14 @@ class top_block(gr.top_block): self.rpc_manager.start_watcher() def start_fg(self): - print "Start Flowgraph" + print("Start Flowgraph") try: self.start() except RuntimeError: - print "Can't start, flowgraph already running!" + print("Can't start, flowgraph already running!") def stop_fg(self): - print "Stop Flowgraph" + print("Stop Flowgraph") self.stop() self.wait() @@ -110,7 +112,7 @@ if __name__ == "__main__": time.sleep(1) except KeyboardInterrupt: pass - print "Shutting down flowgraph." + print("Shutting down flowgraph.") tb.rpc_manager.stop_watcher() tb.stop() tb.wait() diff --git a/gr-zeromq/examples/python/gui.py b/gr-zeromq/examples/python/gui.py index c932549408..832392f0a2 100755..100644 --- a/gr-zeromq/examples/python/gui.py +++ b/gr-zeromq/examples/python/gui.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2013 Free Software Foundation, Inc. # @@ -112,7 +113,7 @@ class gui(QtGui.QMainWindow): # plot the data from the queues def plot_data(self, plot, samples): - self.x = range(0,len(samples),1) + self.x = list(range(0,len(samples),1)) self.y = samples # clear the previous points from the plot plot.clear() diff --git a/gr-zeromq/examples/python/server.py b/gr-zeromq/examples/python/server.py index 23951664c1..b2cd8e8ef2 100755..100644 --- a/gr-zeromq/examples/python/server.py +++ b/gr-zeromq/examples/python/server.py @@ -1,3 +1,5 @@ +from __future__ import print_function +from __future__ import unicode_literals # # Copyright 2013 Free Software Foundation, Inc. # @@ -78,14 +80,14 @@ class top_block(gr.top_block): self.rpc_manager.start_watcher() def start_fg(self): - print "Start Flowgraph" + print("Start Flowgraph") try: self.start() except RuntimeError: - print "Can't start, flowgraph already running!" + print("Can't start, flowgraph already running!") def stop_fg(self): - print "Stop Flowgraph" + print("Stop Flowgraph") self.stop() self.wait() @@ -119,7 +121,7 @@ if __name__ == "__main__": time.sleep(1) except KeyboardInterrupt: pass - print "Shutting down flowgraph." + print("Shutting down flowgraph.") tb.rpc_manager.stop_watcher() tb.stop() tb.wait() diff --git a/gr-zeromq/python/zeromq/CMakeLists.txt b/gr-zeromq/python/zeromq/CMakeLists.txt index 66fc65a4b5..100d1028fe 100644 --- a/gr-zeromq/python/zeromq/CMakeLists.txt +++ b/gr-zeromq/python/zeromq/CMakeLists.txt @@ -51,6 +51,6 @@ if(ENABLE_TESTING) file(GLOB py_qa_test_files "qa_*.py") foreach(py_qa_test_file ${py_qa_test_files}) get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) - GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) + GR_ADD_TEST(${py_qa_test_name} ${QA_PYTHON_EXECUTABLE} -B ${py_qa_test_file}) endforeach(py_qa_test_file) endif(ENABLE_TESTING) diff --git a/gr-zeromq/python/zeromq/__init__.py b/gr-zeromq/python/zeromq/__init__.py index cab4b67640..3b3e3869bd 100644 --- a/gr-zeromq/python/zeromq/__init__.py +++ b/gr-zeromq/python/zeromq/__init__.py @@ -22,15 +22,17 @@ ''' Blocks for interfacing with ZeroMQ endpoints. ''' +from __future__ import absolute_import +from __future__ import unicode_literals import os try: - from zeromq_swig import * + from .zeromq_swig import * except ImportError: dirname, filename = os.path.split(os.path.abspath(__file__)) __path__.append(os.path.join(dirname, "..", "..", "swig")) - from zeromq_swig import * + from .zeromq_swig import * -from probe_manager import probe_manager -from rpc_manager import rpc_manager +from .probe_manager import probe_manager +from .rpc_manager import rpc_manager diff --git a/gr-zeromq/python/zeromq/probe_manager.py b/gr-zeromq/python/zeromq/probe_manager.py index 9facb33b2b..c224ca7870 100644 --- a/gr-zeromq/python/zeromq/probe_manager.py +++ b/gr-zeromq/python/zeromq/probe_manager.py @@ -1,3 +1,4 @@ +from __future__ import unicode_literals # # Copyright 2013 Free Software Foundation, Inc. # @@ -20,10 +21,9 @@ # import zmq -import threading import numpy -class probe_manager(): +class probe_manager(object): def __init__(self): self.zmq_context = zmq.Context() self.poller = zmq.Poller() @@ -31,7 +31,7 @@ class probe_manager(): def add_socket(self, address, data_type, callback_func): socket = self.zmq_context.socket(zmq.SUB) - socket.setsockopt(zmq.SUBSCRIBE, "") + socket.setsockopt(zmq.SUBSCRIBE, b"") socket.connect(address) # use a tuple to store interface elements self.interfaces.append((socket, data_type, callback_func)) diff --git a/gr-zeromq/python/zeromq/qa_zeromq_pub.py b/gr-zeromq/python/zeromq/qa_zeromq_pub.py index cc856d57cc..2cee710d2a 100755..100644 --- a/gr-zeromq/python/zeromq/qa_zeromq_pub.py +++ b/gr-zeromq/python/zeromq/qa_zeromq_pub.py @@ -21,6 +21,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest from gnuradio import blocks, zeromq from gnuradio import eng_notation @@ -37,7 +38,7 @@ class qa_zeromq_pub (gr_unittest.TestCase): def test_001 (self): vlen = 10 self.rx_data = None - src_data = range(vlen)*100 + src_data = list(range(vlen))*100 src = blocks.vector_source_f(src_data, False, vlen) zeromq_pub_sink = zeromq.pub_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:5555") self.tb.connect(src, zeromq_pub_sink) diff --git a/gr-zeromq/python/zeromq/qa_zeromq_pubsub.py b/gr-zeromq/python/zeromq/qa_zeromq_pubsub.py index bb853d892f..21c96a3713 100755..100644 --- a/gr-zeromq/python/zeromq/qa_zeromq_pubsub.py +++ b/gr-zeromq/python/zeromq/qa_zeromq_pubsub.py @@ -21,6 +21,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest from gnuradio import blocks, zeromq import time @@ -37,7 +38,7 @@ class qa_zeromq_pubsub (gr_unittest.TestCase): def test_001 (self): vlen = 10 - src_data = range(vlen)*100 + src_data = list(range(vlen))*100 src = blocks.vector_source_f(src_data, False, vlen) zeromq_pub_sink = zeromq.pub_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:5556", 0) zeromq_sub_source = zeromq.sub_source(gr.sizeof_float, vlen, "tcp://127.0.0.1:5556", 0) diff --git a/gr-zeromq/python/zeromq/qa_zeromq_pushpull.py b/gr-zeromq/python/zeromq/qa_zeromq_pushpull.py index 388f7ff9cb..b4dde8b2b2 100755..100644 --- a/gr-zeromq/python/zeromq/qa_zeromq_pushpull.py +++ b/gr-zeromq/python/zeromq/qa_zeromq_pushpull.py @@ -20,6 +20,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest, blocks, zeromq import time @@ -35,7 +36,7 @@ class qa_zeromq_pushpull (gr_unittest.TestCase): def test_001 (self): vlen = 10 - src_data = range(vlen)*100 + src_data = list(range(vlen))*100 src = blocks.vector_source_f(src_data, False, vlen) zeromq_push_sink = zeromq.push_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:5557") zeromq_pull_source = zeromq.pull_source(gr.sizeof_float, vlen, "tcp://127.0.0.1:5557", 0) diff --git a/gr-zeromq/python/zeromq/qa_zeromq_reqrep.py b/gr-zeromq/python/zeromq/qa_zeromq_reqrep.py index a5a3d33f67..9fccbf300d 100755..100644 --- a/gr-zeromq/python/zeromq/qa_zeromq_reqrep.py +++ b/gr-zeromq/python/zeromq/qa_zeromq_reqrep.py @@ -21,6 +21,7 @@ # Boston, MA 02110-1301, USA. # + from gnuradio import gr, gr_unittest from gnuradio import blocks, zeromq from gnuradio import eng_notation @@ -38,7 +39,7 @@ class qa_zeromq_reqrep (gr_unittest.TestCase): def test_001 (self): vlen = 10 - src_data = range(vlen)*100 + src_data = list(range(vlen))*100 src = blocks.vector_source_f(src_data, False, vlen) zeromq_rep_sink = zeromq.rep_sink(gr.sizeof_float, vlen, "tcp://127.0.0.1:5558", 0) zeromq_req_source = zeromq.req_source(gr.sizeof_float, vlen, "tcp://127.0.0.1:5558", 0) diff --git a/gr-zeromq/python/zeromq/rpc_manager.py b/gr-zeromq/python/zeromq/rpc_manager.py index 2dce997bd4..f7c972b752 100644 --- a/gr-zeromq/python/zeromq/rpc_manager.py +++ b/gr-zeromq/python/zeromq/rpc_manager.py @@ -19,12 +19,15 @@ # Boston, MA 02110-1301, USA. # +from __future__ import print_function +from __future__ import unicode_literals + import zmq import pmt import threading -class rpc_manager(): +class rpc_manager(object): def __init__(self): self.zmq_context = zmq.Context() self.poller_rep = zmq.Poller() @@ -39,22 +42,22 @@ class rpc_manager(): def set_reply_socket(self, address): self.rep_socket = self.zmq_context.socket(zmq.REP) self.rep_socket.bind(address) - print "[RPC] reply socket bound to: ", address + print("[RPC] reply socket bound to: ", address) self.poller_rep.register(self.rep_socket, zmq.POLLIN) def set_request_socket(self, address): self.req_socket = self.zmq_context.socket(zmq.REQ) self.req_socket.connect(address) - print "[RPC] request socket connected to: ", address + print("[RPC] request socket connected to: ", address) self.poller_req_out.register(self.req_socket, zmq.POLLOUT) self.poller_req_in.register(self.req_socket, zmq.POLLIN) def add_interface(self, id_str, callback_func): - if not self.interfaces.has_key(id_str): + if id_str not in self.interfaces: self.interfaces[id_str] = callback_func - print "[RPC] added reply interface:", id_str + print("[RPC] added reply interface:", id_str) else: - print "[RPC] ERROR: duplicate id_str:", id_str + print("[RPC] ERROR: duplicate id_str:", id_str) def watcher(self): self.keep_running = True @@ -65,7 +68,7 @@ class rpc_manager(): # receive call msg = self.rep_socket.recv() (id_str, args) = pmt.to_python(pmt.deserialize_str(msg)) - print "[RPC] request:", id_str, ", args:", args + print("[RPC] request:", id_str, ", args:", args) reply = self.callback(id_str, args) self.rep_socket.send(pmt.serialize_str(pmt.to_pmt(reply))) @@ -85,11 +88,11 @@ class rpc_manager(): socks = dict(self.poller_req_in.poll(10)) if socks.get(self.req_socket) == zmq.POLLIN: reply = pmt.to_python(pmt.deserialize_str(self.req_socket.recv())) - print "[RPC] reply:", reply + print("[RPC] reply:", reply) return reply def callback(self, id_str, args): - if self.interfaces.has_key(id_str): + if id_str in self.interfaces: callback_func = self.interfaces.get(id_str) if not args == None: # use unpacking or splat operator * to unpack argument list @@ -97,5 +100,5 @@ class rpc_manager(): else: return(callback_func()) else: - print "[RPC] ERROR: id_str not found:", id_str + print("[RPC] ERROR: id_str not found:", id_str) return None diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt index eed5202657..5a32c7cd70 100644 --- a/grc/CMakeLists.txt +++ b/grc/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2011,2013 Free Software Foundation, Inc. +# Copyright 2011,2013,2017 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -22,11 +22,70 @@ ######################################################################## include(GrPython) -GR_PYTHON_CHECK_MODULE("python >= 2.5" sys "sys.version.split()[0] >= '2.5'" PYTHON_MIN_VER_FOUND) -GR_PYTHON_CHECK_MODULE("Cheetah >= 2.0.0" Cheetah "Cheetah.Version >= '2.0.0'" CHEETAH_FOUND) -GR_PYTHON_CHECK_MODULE("lxml >= 1.3.6" lxml.etree "lxml.etree.LXML_VERSION >= (1, 3, 6, 0)" LXML_FOUND) -GR_PYTHON_CHECK_MODULE("pygtk >= 2.10.0" gtk "gtk.pygtk_version >= (2, 10, 0)" PYGTK_FOUND) -GR_PYTHON_CHECK_MODULE("numpy" numpy True NUMPY_FOUND) +message(STATUS "") + +GR_PYTHON_CHECK_MODULE_RAW( + "python2 >= 2.7.6 or python3 >= 3.4.0" + "import sys; \ + requirement = (3, 4, 0) if sys.version_info.major >= 3 else (2, 7, 6); \ + assert sys.version_info[:3] >= requirement" + PYTHON_MIN_VER_FOUND +) + +GR_PYTHON_CHECK_MODULE_RAW( + "Cheetah >= 2.0.0" + "import Cheetah; assert Cheetah.Version >= '2.0.0'" + CHEETAH_FOUND +) + +GR_PYTHON_CHECK_MODULE_RAW( + "PyYAML >= 3.10" + "import yaml; assert yaml.__version__ >= '3.11'" + PYYAML_FOUND +) + +GR_PYTHON_CHECK_MODULE_RAW( + "mako >= 0.9.1" + "import mako; assert mako.__version__ >= '0.9.1'" + MAKO_FOUND +) + +GR_PYTHON_CHECK_MODULE_RAW( + "lxml >= 1.3.6" + "import lxml.etree; assert lxml.etree.LXML_VERSION >= (1, 3, 6, 0)" + LXML_FOUND +) + +GR_PYTHON_CHECK_MODULE_RAW( + "pygobject >= 2.28.6" + "import gi; assert gi.version_info >= (2, 28, 6)" + PYGI_FOUND +) + +GR_PYTHON_CHECK_MODULE_RAW( + "Gtk (GI) >= 3.10.8" + "import gi; gi.require_version('Gtk', '3.0'); \ + from gi.repository import Gtk; Gtk.check_version(3, 10, 8)" + GTK_GI_FOUND +) + +GR_PYTHON_CHECK_MODULE_RAW( + "Cairo (GI) >= 1.0" + "import gi; gi.require_foreign('cairo', 'Context')" # Cairo 1.13.0 + CAIRO_GI_FOUND +) + +GR_PYTHON_CHECK_MODULE_RAW( + "PangoCairo (GI) >= 1.0" + "import gi; gi.require_version('PangoCairo', '1.0')" # pangocairo 1.36.3 + PANGOCAIRO_GI_FOUND +) + +GR_PYTHON_CHECK_MODULE_RAW( + "numpy" + "import numpy" + NUMPY_FOUND +) ######################################################################## # Register component @@ -37,7 +96,10 @@ if(NOT CMAKE_CROSSCOMPILING) PYTHON_MIN_VER_FOUND CHEETAH_FOUND LXML_FOUND - PYGTK_FOUND + PYGI_FOUND + GTK_GI_FOUND + CAIRO_GI_FOUND + PANGOCAIRO_GI_FOUND NUMPY_FOUND ) endif(NOT CMAKE_CROSSCOMPILING) @@ -48,9 +110,6 @@ GR_REGISTER_COMPONENT("gnuradio-companion" ENABLE_GRC ${grc_python_deps} ) -######################################################################## -# Begin conditional configuration -######################################################################## if(ENABLE_GRC) ######################################################################## @@ -85,15 +144,23 @@ install( DESTINATION ${GR_PREFSDIR} ) +######################################################################## +# Install (+ compile) python sources and data files +######################################################################## file(GLOB py_files "*.py") - GR_PYTHON_INSTALL( FILES ${py_files} - DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc + DESTINATION "${GR_PYTHON_DIR}/gnuradio/grc" ) +GR_PYTHON_INSTALL( + DIRECTORY core gui + DESTINATION "${GR_PYTHON_DIR}/gnuradio/grc" + FILES_MATCHING REGEX "\\.(py|dtd|grc|tmpl|png)$" +) + ######################################################################## -# Appens NSIS commands to set environment variables +# Append NSIS commands to set environment variables ######################################################################## if(WIN32) @@ -112,8 +179,6 @@ endif(WIN32) # Add subdirectories ######################################################################## add_subdirectory(blocks) -add_subdirectory(gui) -add_subdirectory(core) add_subdirectory(scripts) endif(ENABLE_GRC) diff --git a/grc/blocks/dummy.xml b/grc/blocks/dummy.xml deleted file mode 100644 index c0ca3b6698..0000000000 --- a/grc/blocks/dummy.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0"?> -<!-- -################################################### -##Dummy Block -################################################### ---> -<block> - <name>Missing Block</name> - <key>dummy_block</key> - <make>raise NotImplementedError()</make> -</block> diff --git a/grc/blocks/variable_struct.xml.py b/grc/blocks/variable_struct.xml.py index de4411e975..c0d3dac355 100644 --- a/grc/blocks/variable_struct.xml.py +++ b/grc/blocks/variable_struct.xml.py @@ -93,5 +93,5 @@ if __name__ == '__main__': data = make_xml(MAX_NUM_FIELDS) - with open(filename, 'w') as fp: + with open(filename, 'wb') as fp: fp.write(data.encode()) diff --git a/grc/compiler.py b/grc/compiler.py index 0cda0d946d..b2361b86eb 100755 --- a/grc/compiler.py +++ b/grc/compiler.py @@ -49,7 +49,7 @@ def main(args=None): platform = Platform( name='GNU Radio Companion Compiler', - prefs_file=gr.prefs(), + prefs=gr.prefs(), version=gr.version(), version_parts=(gr.major_version(), gr.api_version(), gr.minor_version()) ) diff --git a/grc/core/Block.py b/grc/core/Block.py index fba9371963..087815b941 100644 --- a/grc/core/Block.py +++ b/grc/core/Block.py @@ -17,226 +17,202 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import + import collections import itertools +import ast + +import six +from six.moves import map, range from Cheetah.Template import Template -from .utils import epy_block_io, odict +from . import utils + from . Constants import ( BLOCK_FLAG_NEED_QT_GUI, - ADVANCED_PARAM_TAB, DEFAULT_PARAM_TAB, + ADVANCED_PARAM_TAB, BLOCK_FLAG_THROTTLE, BLOCK_FLAG_DISABLE_BYPASS, BLOCK_FLAG_DEPRECATED, - BLOCK_ENABLED, BLOCK_BYPASSED, BLOCK_DISABLED ) -from . Element import Element +from . Element import Element, lazy_property -def _get_keys(lst): - return [elem.get_key() for elem in lst] - - -def _get_elem(lst, key): - try: - return lst[_get_keys(lst).index(key)] - except ValueError: - raise ValueError('Key "{}" not found in {}.'.format(key, _get_keys(lst))) +def _get_elem(iterable, key): + items = list(iterable) + for item in items: + if item.key == key: + return item + return ValueError('Key "{}" not found in {}.'.format(key, items)) class Block(Element): is_block = True - def __init__(self, flow_graph, n): - """ - Make a new block from nested data. + STATE_LABELS = ['disabled', 'enabled', 'bypassed'] - Args: - flow: graph the parent element - n: the nested odict + def __init__(self, parent, key, name, **n): + """Make a new block from nested data.""" + super(Block, self).__init__(parent) + + self.key = key + self.name = name + self.category = [cat.strip() for cat in n.get('category', '').split('/') if cat.strip()] + self.flags = n.get('flags', '') + self._doc = n.get('doc', '').strip('\n').replace('\\\n', '') - Returns: - block a new block - """ - # Grab the data - self._doc = (n.find('doc') or '').strip('\n').replace('\\\n', '') - self._imports = map(lambda i: i.strip(), n.findall('import')) - self._make = n.find('make') - self._var_make = n.find('var_make') - self._checks = n.findall('check') - self._callbacks = n.findall('callback') - self._bus_structure_source = n.find('bus_structure_source') or '' - self._bus_structure_sink = n.find('bus_structure_sink') or '' - self.port_counters = [itertools.count(), itertools.count()] - - # Build the block - Element.__init__(self, flow_graph) - - # Grab the data - params = n.findall('param') - sources = n.findall('source') - sinks = n.findall('sink') - self._name = n.find('name') - self._key = n.find('key') - category = (n.find('category') or '').split('/') - self.category = [cat.strip() for cat in category if cat.strip()] - self._flags = n.find('flags') or '' # Backwards compatibility - if n.find('throttle') and BLOCK_FLAG_THROTTLE not in self._flags: - self._flags += BLOCK_FLAG_THROTTLE - self._grc_source = n.find('grc_source') or '' - self._block_wrapper_path = n.find('block_wrapper_path') - self._bussify_sink = n.find('bus_sink') - self._bussify_source = n.find('bus_source') - self._var_value = n.find('var_value') or '$value' + if n.get('throttle') and BLOCK_FLAG_THROTTLE not in self.flags: + self.flags += BLOCK_FLAG_THROTTLE - # Get list of param tabs - n_tabs = n.find('param_tab_order') or None - self._param_tab_labels = n_tabs.findall('tab') if n_tabs is not None else [DEFAULT_PARAM_TAB] - - # Create the param objects - self._params = list() - - # Add the id param - self.get_params().append(self.get_parent().get_parent().Param( - block=self, - n=odict({ - 'name': 'ID', - 'key': 'id', - 'type': 'id', - }) - )) - self.get_params().append(self.get_parent().get_parent().Param( - block=self, - n=odict({ - 'name': 'Enabled', - 'key': '_enabled', - 'type': 'raw', - 'value': 'True', - 'hide': 'all', - }) - )) - for param in itertools.imap(lambda n: self.get_parent().get_parent().Param(block=self, n=n), params): - key = param.get_key() - # Test against repeated keys - if key in self.get_param_keys(): - raise Exception('Key "{}" already exists in params'.format(key)) - # Store the param - self.get_params().append(param) - # Create the source objects - self._sources = list() - for source in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='source'), sources): - key = source.get_key() - # Test against repeated keys - if key in self.get_source_keys(): - raise Exception('Key "{}" already exists in sources'.format(key)) - # Store the port - self.get_sources().append(source) - self.back_ofthe_bus(self.get_sources()) - # Create the sink objects - self._sinks = list() - for sink in map(lambda n: self.get_parent().get_parent().Port(block=self, n=n, dir='sink'), sinks): - key = sink.get_key() - # Test against repeated keys - if key in self.get_sink_keys(): - raise Exception('Key "{}" already exists in sinks'.format(key)) - # Store the port - self.get_sinks().append(sink) - self.back_ofthe_bus(self.get_sinks()) - self.current_bus_structure = {'source': '', 'sink': ''} + self._imports = [i.strip() for i in n.get('import', [])] + self._make = n.get('make') + self._var_make = n.get('var_make') + self._var_value = n.get('var_value', '$value') + self._checks = n.get('check', []) + self._callbacks = n.get('callback', []) + + self._grc_source = n.get('grc_source', '') + self.block_wrapper_path = n.get('block_wrapper_path') # Virtual source/sink and pad source/sink blocks are # indistinguishable from normal GR blocks. Make explicit # checks for them here since they have no work function or # buffers to manage. - self.is_virtual_or_pad = self._key in ( + self.is_virtual_or_pad = self.key in ( "virtual_source", "virtual_sink", "pad_source", "pad_sink") - self.is_variable = self._key.startswith('variable') - self.is_import = (self._key == 'import') + self.is_variable = self.key.startswith('variable') + self.is_import = (self.key == 'import') # Disable blocks that are virtual/pads or variables if self.is_virtual_or_pad or self.is_variable: - self._flags += BLOCK_FLAG_DISABLE_BYPASS - - if not (self.is_virtual_or_pad or self.is_variable or self._key == 'options'): - self.get_params().append(self.get_parent().get_parent().Param( - block=self, - n=odict({'name': 'Block Alias', - 'key': 'alias', - 'type': 'string', - 'hide': 'part', - 'tab': ADVANCED_PARAM_TAB - }) - )) - - if (len(sources) or len(sinks)) and not self.is_virtual_or_pad: - self.get_params().append(self.get_parent().get_parent().Param( - block=self, - n=odict({'name': 'Core Affinity', - 'key': 'affinity', - 'type': 'int_vector', - 'hide': 'part', - 'tab': ADVANCED_PARAM_TAB - }) - )) - if len(sources) and not self.is_virtual_or_pad: - self.get_params().append(self.get_parent().get_parent().Param( - block=self, - n=odict({'name': 'Min Output Buffer', - 'key': 'minoutbuf', - 'type': 'int', - 'hide': 'part', - 'value': '0', - 'tab': ADVANCED_PARAM_TAB - }) - )) - self.get_params().append(self.get_parent().get_parent().Param( - block=self, - n=odict({'name': 'Max Output Buffer', - 'key': 'maxoutbuf', - 'type': 'int', - 'hide': 'part', - 'value': '0', - 'tab': ADVANCED_PARAM_TAB - }) - )) - - self.get_params().append(self.get_parent().get_parent().Param( - block=self, - n=odict({'name': 'Comment', - 'key': 'comment', - 'type': '_multiline', - 'hide': 'part', - 'value': '', - 'tab': ADVANCED_PARAM_TAB - }) - )) + self.flags += BLOCK_FLAG_DISABLE_BYPASS - self._epy_source_hash = -1 # for epy blocks - self._epy_reload_error = None + params_n = n.get('param', []) + sources_n = n.get('source', []) + sinks_n = n.get('sink', []) - if self._bussify_sink: - self.bussify({'name': 'bus', 'type': 'bus'}, 'sink') - if self._bussify_source: - self.bussify({'name': 'bus', 'type': 'bus'}, 'source') + # Get list of param tabs + self.params = collections.OrderedDict() + self._init_params( + params_n=params_n, + has_sinks=len(sinks_n), + has_sources=len(sources_n) + ) - def get_bus_structure(self, direction): - if direction == 'source': - bus_structure = self._bus_structure_source - else: - bus_structure = self._bus_structure_sink + self.sources = self._init_ports(sources_n, direction='source') + self.sinks = self._init_ports(sinks_n, direction='sink') + self.active_sources = [] # on rewrite + self.active_sinks = [] # on rewrite - bus_structure = self.resolve_dependencies(bus_structure) + self.states = {'_enabled': True} - if not bus_structure: - return '' # TODO: Don't like empty strings. should change this to None eventually + self._init_bus_ports(n) - try: - clean_bus_structure = self.get_parent().evaluate(bus_structure) - return clean_bus_structure - except: - return '' + def _init_params(self, params_n, has_sources, has_sinks): + param_factory = self.parent_platform.get_new_param + + def add_param(key, **kwargs): + self.params[key] = param_factory(self, key=key, **kwargs) + + add_param(key='id', name='ID', type='id') + + if not (self.is_virtual_or_pad or self.is_variable or self.key == 'options'): + add_param(key='alias', name='Block Alias', type='string', + hide='part', tab=ADVANCED_PARAM_TAB) + + if not self.is_virtual_or_pad and (has_sources or has_sinks): + add_param(key='affinity', name='Core Affinity', type='int_vector', + hide='part', tab=ADVANCED_PARAM_TAB) + + if not self.is_virtual_or_pad and has_sources: + add_param(key='minoutbuf', name='Min Output Buffer', type='int', + hide='part', value='0', tab=ADVANCED_PARAM_TAB) + add_param(key='maxoutbuf', name='Max Output Buffer', type='int', + hide='part', value='0', tab=ADVANCED_PARAM_TAB) + + base_params_n = {} + for param_n in params_n: + key = param_n['key'] + if key in self.params: + raise Exception('Key "{}" already exists in params'.format(key)) + + base_key = param_n.get('base_key', None) + param_n_ext = base_params_n.get(base_key, {}).copy() + param_n_ext.update(param_n) + self.params[key] = param_factory(self, **param_n_ext) + base_params_n[key] = param_n_ext + + add_param(key='comment', name='Comment', type='_multiline', hide='part', + value='', tab=ADVANCED_PARAM_TAB) + + def _init_ports(self, ports_n, direction): + port_factory = self.parent_platform.get_new_port + ports = [] + port_keys = set() + stream_port_keys = itertools.count() + for i, port_n in enumerate(ports_n): + port_n.setdefault('key', str(next(stream_port_keys))) + port = port_factory(parent=self, direction=direction, **port_n) + key = port.key + if key in port_keys: + raise Exception('Key "{}" already exists in {}'.format(key, direction)) + port_keys.add(key) + ports.append(port) + return ports + + ############################################## + # validation and rewrite + ############################################## + def rewrite(self): + """ + Add and remove ports to adjust for the nports. + """ + Element.rewrite(self) + + def rekey(ports): + """Renumber non-message/message ports""" + domain_specific_port_index = collections.defaultdict(int) + for port in [p for p in ports if p.key.isdigit()]: + domain = port.domain + port.key = str(domain_specific_port_index[domain]) + domain_specific_port_index[domain] += 1 + + # Adjust nports + for ports in (self.sources, self.sinks): + self._rewrite_nports(ports) + self.back_ofthe_bus(ports) + rekey(ports) + + self._rewrite_bus_ports() + + # disconnect hidden ports + for port in itertools.chain(self.sources, self.sinks): + if port.get_hide(): + for connection in port.get_connections(): + self.parent_flowgraph.remove_element(connection) + + + self.active_sources = [p for p in self.get_sources_gui() if not p.get_hide()] + self.active_sinks = [p for p in self.get_sinks_gui() if not p.get_hide()] + + def _rewrite_nports(self, ports): + for port in ports: + if port.is_clone: # Not a master port and no left-over clones + continue + nports = port.get_nports() or 1 + for clone in port.clones[nports-1:]: + # Remove excess connections + for connection in clone.get_connections(): + self.parent_flowgraph.remove_element(connection) + port.remove_clone(clone) + ports.remove(clone) + # Add more cloned ports + for j in range(1 + len(port.clones), nports): + clone = port.add_clone() + ports.insert(ports.index(port) + j, clone) def validate(self): """ @@ -245,114 +221,95 @@ class Block(Element): Evaluate the checks: each check must evaluate to True. """ Element.validate(self) - # Evaluate the checks + self._run_checks() + self._validate_generate_mode_compat() + self._validate_var_value() + + def _run_checks(self): + """Evaluate the checks""" for check in self._checks: check_res = self.resolve_dependencies(check) try: - if not self.get_parent().evaluate(check_res): + if not self.parent.evaluate(check_res): self.add_error_message('Check "{}" failed.'.format(check)) except: self.add_error_message('Check "{}" did not evaluate.'.format(check)) - # For variables check the value (only if var_value is used - if self.is_variable and self._var_value != '$value': - value = self._var_value - try: - value = self.get_var_value() - self.get_parent().evaluate(value) - except Exception as err: - self.add_error_message('Value "{}" cannot be evaluated:\n{}'.format(value, err)) - - # check if this is a GUI block and matches the selected generate option - current_generate_option = self.get_parent().get_option('generate_options') + def _validate_generate_mode_compat(self): + """check if this is a GUI block and matches the selected generate option""" + current_generate_option = self.parent.get_option('generate_options') def check_generate_mode(label, flag, valid_options): block_requires_mode = ( - flag in self.get_flags() or - self.get_name().upper().startswith(label) + flag in self.flags or self.name.upper().startswith(label) ) if block_requires_mode and current_generate_option not in valid_options: self.add_error_message("Can't generate this block in mode: {} ".format( repr(current_generate_option))) check_generate_mode('QT GUI', BLOCK_FLAG_NEED_QT_GUI, ('qt_gui', 'hb_qt_gui')) - if self._epy_reload_error: - self.get_param('_source_code').add_error_message(str(self._epy_reload_error)) - - def rewrite(self): - """ - Add and remove ports to adjust for the nports. - """ - Element.rewrite(self) - # Check and run any custom rewrite function for this block - getattr(self, 'rewrite_' + self._key, lambda: None)() - - # Adjust nports, disconnect hidden ports - for ports in (self.get_sources(), self.get_sinks()): - for i, master_port in enumerate(ports): - nports = master_port.get_nports() or 1 - num_ports = 1 + len(master_port.get_clones()) - if master_port.get_hide(): - for connection in master_port.get_connections(): - self.get_parent().remove_element(connection) - if not nports and num_ports == 1: # Not a master port and no left-over clones - continue - # Remove excess cloned ports - for port in master_port.get_clones()[nports-1:]: - # Remove excess connections - for connection in port.get_connections(): - self.get_parent().remove_element(connection) - master_port.remove_clone(port) - ports.remove(port) - # Add more cloned ports - for j in range(num_ports, nports): - port = master_port.add_clone() - ports.insert(ports.index(master_port) + j, port) - self.back_ofthe_bus(ports) - # Renumber non-message/message ports - domain_specific_port_index = collections.defaultdict(int) - for port in filter(lambda p: p.get_key().isdigit(), ports): - domain = port.get_domain() - port._key = str(domain_specific_port_index[domain]) - domain_specific_port_index[domain] += 1 + def _validate_var_value(self): + """or variables check the value (only if var_value is used)""" + if self.is_variable and self._var_value != '$value': + value = self._var_value + try: + value = self.get_var_value() + self.parent.evaluate(value) + except Exception as err: + self.add_error_message('Value "{}" cannot be evaluated:\n{}'.format(value, err)) - def port_controller_modify(self, direction): - """ - Change the port controller. + ############################################## + # props + ############################################## - Args: - direction: +1 or -1 + @lazy_property + def is_throtteling(self): + return BLOCK_FLAG_THROTTLE in self.flags - Returns: - true for change - """ - changed = False - # Concat the nports string from the private nports settings of all ports - nports_str = ' '.join([port._nports for port in self.get_ports()]) - # Modify all params whose keys appear in the nports string - for param in self.get_params(): - if param.is_enum() or param.get_key() not in nports_str: - continue - # Try to increment the port controller by direction - try: - value = param.get_evaluated() - value = value + direction - if 0 < value: - param.set_value(value) - changed = True - except: - pass - return changed + @lazy_property + def is_deprecated(self): + return BLOCK_FLAG_DEPRECATED in self.flags - def get_doc(self): - platform = self.get_parent().get_parent() - documentation = platform.block_docstrings.get(self._key, {}) + @property + def documentation(self): + documentation = self.parent_platform.block_docstrings.get(self.key, {}) from_xml = self._doc.strip() if from_xml: documentation[''] = from_xml return documentation + @property + def comment(self): + return self.params['comment'].get_value() + + @property + def state(self): + """Gets the block's current state.""" + try: + return self.STATE_LABELS[int(self.states['_enabled'])] + except ValueError: + return 'enabled' + + @state.setter + def state(self, value): + """Sets the state for the block.""" + try: + encoded = self.STATE_LABELS.index(value) + except ValueError: + encoded = 1 + self.states['_enabled'] = encoded + + # Enable/Disable Aliases + @property + def enabled(self): + """Get the enabled state of the block""" + return self.state != 'disabled' + + ############################################## + # Getters (old) + ############################################## + def get_imports(self, raw=False): """ Resolve all import statements. @@ -365,7 +322,8 @@ class Block(Element): """ if raw: return self._imports - return filter(lambda i: i, sum(map(lambda i: self.resolve_dependencies(i).split('\n'), self._imports), [])) + return [i for i in sum((self.resolve_dependencies(i).split('\n') + for i in self._imports), []) if i] def get_make(self, raw=False): if raw: @@ -390,176 +348,20 @@ class Block(Element): if 'self.' in callback: return callback return 'self.{}.{}'.format(self.get_id(), callback) - return map(make_callback, self._callbacks) + return [make_callback(c) for c in self._callbacks] def is_virtual_sink(self): - return self.get_key() == 'virtual_sink' + return self.key == 'virtual_sink' def is_virtual_source(self): - return self.get_key() == 'virtual_source' - - ########################################################################### - # Custom rewrite functions - ########################################################################### - - def rewrite_epy_block(self): - flowgraph = self.get_parent() - platform = flowgraph.get_parent() - param_blk = self.get_param('_io_cache') - param_src = self.get_param('_source_code') - - src = param_src.get_value() - src_hash = hash((self.get_id(), src)) - if src_hash == self._epy_source_hash: - return - - try: - blk_io = epy_block_io.extract(src) - - except Exception as e: - self._epy_reload_error = ValueError(str(e)) - try: # Load last working block io - blk_io_args = eval(param_blk.get_value()) - if len(blk_io_args) == 6: - blk_io_args += ([],) # add empty callbacks - blk_io = epy_block_io.BlockIO(*blk_io_args) - except Exception: - return - else: - self._epy_reload_error = None # Clear previous errors - param_blk.set_value(repr(tuple(blk_io))) - - # print "Rewriting embedded python block {!r}".format(self.get_id()) - - self._epy_source_hash = src_hash - self._name = blk_io.name or blk_io.cls - self._doc = blk_io.doc - self._imports[0] = 'import ' + self.get_id() - self._make = '{0}.{1}({2})'.format(self.get_id(), blk_io.cls, ', '.join( - '{0}=${{ {0} }}'.format(key) for key, _ in blk_io.params)) - self._callbacks = ['{0} = ${{ {0} }}'.format(attr) for attr in blk_io.callbacks] - - params = {} - for param in list(self._params): - if hasattr(param, '__epy_param__'): - params[param.get_key()] = param - self._params.remove(param) - - for key, value in blk_io.params: - try: - param = params[key] - param.set_default(value) - except KeyError: # need to make a new param - name = key.replace('_', ' ').title() - n = odict(dict(name=name, key=key, type='raw', value=value)) - param = platform.Param(block=self, n=n) - setattr(param, '__epy_param__', True) - self._params.append(param) - - def update_ports(label, ports, port_specs, direction): - ports_to_remove = list(ports) - iter_ports = iter(ports) - ports_new = [] - port_current = next(iter_ports, None) - for key, port_type, vlen in port_specs: - reuse_port = ( - port_current is not None and - port_current.get_type() == port_type and - port_current.get_vlen() == vlen and - (key.isdigit() or port_current.get_key() == key) - ) - if reuse_port: - ports_to_remove.remove(port_current) - port, port_current = port_current, next(iter_ports, None) - else: - n = odict(dict(name=label + str(key), type=port_type, key=key)) - if port_type == 'message': - n['name'] = key - n['optional'] = '1' - if vlen > 1: - n['vlen'] = str(vlen) - port = platform.Port(block=self, n=n, dir=direction) - ports_new.append(port) - # replace old port list with new one - del ports[:] - ports.extend(ports_new) - # remove excess port connections - for port in ports_to_remove: - for connection in port.get_connections(): - flowgraph.remove_element(connection) - - update_ports('in', self.get_sinks(), blk_io.sinks, 'sink') - update_ports('out', self.get_sources(), blk_io.sources, 'source') - self.rewrite() - - def back_ofthe_bus(self, portlist): - portlist.sort(key=lambda p: p._type == 'bus') - - def filter_bus_port(self, ports): - buslist = [p for p in ports if p._type == 'bus'] - return buslist or ports - - # Main functions to get and set the block state - # Also kept get_enabled and set_enabled to keep compatibility - def get_state(self): - """ - Gets the block's current state. - - Returns: - ENABLED - 0 - BYPASSED - 1 - DISABLED - 2 - """ - try: - return int(eval(self.get_param('_enabled').get_value())) - except: - return BLOCK_ENABLED - - def set_state(self, state): - """ - Sets the state for the block. - - Args: - ENABLED - 0 - BYPASSED - 1 - DISABLED - 2 - """ - if state in [BLOCK_ENABLED, BLOCK_BYPASSED, BLOCK_DISABLED]: - self.get_param('_enabled').set_value(str(state)) - else: - self.get_param('_enabled').set_value(str(BLOCK_ENABLED)) - - # Enable/Disable Aliases - def get_enabled(self): - """ - Get the enabled state of the block. - - Returns: - true for enabled - """ - return not (self.get_state() == BLOCK_DISABLED) - - def set_enabled(self, enabled): - """ - Set the enabled state of the block. - - Args: - enabled: true for enabled - - Returns: - True if block changed state - """ - old_state = self.get_state() - new_state = BLOCK_ENABLED if enabled else BLOCK_DISABLED - self.set_state(new_state) - return old_state != new_state + return self.key == 'virtual_source' # Block bypassing def get_bypassed(self): """ Check if the block is bypassed """ - return self.get_state() == BLOCK_BYPASSED + return self.state == 'bypassed' def set_bypassed(self): """ @@ -568,8 +370,8 @@ class Block(Element): Returns: True if block chagnes state """ - if self.get_state() != BLOCK_BYPASSED and self.can_bypass(): - self.set_state(BLOCK_BYPASSED) + if self.state != 'bypassed' and self.can_bypass(): + self.state = 'bypassed' return True return False @@ -577,112 +379,60 @@ class Block(Element): """ Check the number of sinks and sources and see if this block can be bypassed """ # Check to make sure this is a single path block # Could possibly support 1 to many blocks - if len(self.get_sources()) != 1 or len(self.get_sinks()) != 1: + if len(self.sources) != 1 or len(self.sinks) != 1: return False - if not (self.get_sources()[0].get_type() == self.get_sinks()[0].get_type()): + if not (self.sources[0].get_type() == self.sinks[0].get_type()): return False - if self.bypass_disabled(): + if BLOCK_FLAG_DISABLE_BYPASS in self.flags: return False return True def __str__(self): - return 'Block - {} - {}({})'.format(self.get_id(), self.get_name(), self.get_key()) + return 'Block - {} - {}({})'.format(self.get_id(), self.name, self.key) def get_id(self): - return self.get_param('id').get_value() - - def get_name(self): - return self._name - - def get_key(self): - return self._key + return self.params['id'].get_value() def get_ports(self): - return self.get_sources() + self.get_sinks() + return self.sources + self.sinks def get_ports_gui(self): - return self.filter_bus_port(self.get_sources()) + self.filter_bus_port(self.get_sinks()) + return self.get_sources_gui() + self.get_sinks_gui() + + def active_ports(self): + return itertools.chain(self.active_sources, self.active_sinks) def get_children(self): - return self.get_ports() + self.get_params() + return self.get_ports() + list(self.params.values()) def get_children_gui(self): - return self.get_ports_gui() + self.get_params() - - def get_block_wrapper_path(self): - return self._block_wrapper_path - - def get_comment(self): - return self.get_param('comment').get_value() - - def get_flags(self): - return self._flags - - def throtteling(self): - return BLOCK_FLAG_THROTTLE in self._flags - - def bypass_disabled(self): - return BLOCK_FLAG_DISABLE_BYPASS in self._flags - - @property - def is_deprecated(self): - return BLOCK_FLAG_DEPRECATED in self._flags + return self.get_ports_gui() + self.params.values() ############################################## - # Access Params + # Access ############################################## - def get_param_tab_labels(self): - return self._param_tab_labels - - def get_param_keys(self): - return _get_keys(self._params) def get_param(self, key): - return _get_elem(self._params, key) - - def get_params(self): - return self._params - - def has_param(self, key): - try: - _get_elem(self._params, key) - return True - except: - return False - - ############################################## - # Access Sinks - ############################################## - def get_sink_keys(self): - return _get_keys(self._sinks) + return self.params[key] def get_sink(self, key): - return _get_elem(self._sinks, key) - - def get_sinks(self): - return self._sinks + return _get_elem(self.sinks, key) def get_sinks_gui(self): - return self.filter_bus_port(self.get_sinks()) - - ############################################## - # Access Sources - ############################################## - def get_source_keys(self): - return _get_keys(self._sources) + return self.filter_bus_port(self.sinks) def get_source(self, key): - return _get_elem(self._sources, key) - - def get_sources(self): - return self._sources + return _get_elem(self.sources, key) def get_sources_gui(self): - return self.filter_bus_port(self.get_sources()) + return self.filter_bus_port(self.sources) def get_connections(self): - return sum([port.get_connections() for port in self.get_ports()], []) + return sum((port.get_connections() for port in self.get_ports()), []) + ############################################## + # Resolve + ############################################## def resolve_dependencies(self, tmpl): """ Resolve a paramater dependency with cheetah templates. @@ -696,103 +446,14 @@ class Block(Element): tmpl = str(tmpl) if '$' not in tmpl: return tmpl - n = dict((param.get_key(), param.template_arg) - for param in self.get_params()) # TODO: cache that + # TODO: cache that + n = {key: param.template_arg for key, param in six.iteritems(self.params)} try: return str(Template(tmpl, n)) except Exception as err: return "Template error: {}\n {}".format(tmpl, err) ############################################## - # Controller Modify - ############################################## - def type_controller_modify(self, direction): - """ - Change the type controller. - - Args: - direction: +1 or -1 - - Returns: - true for change - """ - changed = False - type_param = None - for param in filter(lambda p: p.is_enum(), self.get_params()): - children = self.get_ports() + self.get_params() - # Priority to the type controller - if param.get_key() in ' '.join(map(lambda p: p._type, children)): type_param = param - # Use param if type param is unset - if not type_param: - type_param = param - if type_param: - # Try to increment the enum by direction - try: - keys = type_param.get_option_keys() - old_index = keys.index(type_param.get_value()) - new_index = (old_index + direction + len(keys)) % len(keys) - type_param.set_value(keys[new_index]) - changed = True - except: - pass - return changed - - def form_bus_structure(self, direc): - if direc == 'source': - get_p = self.get_sources - get_p_gui = self.get_sources_gui - bus_structure = self.get_bus_structure('source') - else: - get_p = self.get_sinks - get_p_gui = self.get_sinks_gui - bus_structure = self.get_bus_structure('sink') - - struct = [range(len(get_p()))] - if True in map(lambda a: isinstance(a.get_nports(), int), get_p()): - structlet = [] - last = 0 - for j in [i.get_nports() for i in get_p() if isinstance(i.get_nports(), int)]: - structlet.extend(map(lambda a: a+last, range(j))) - last = structlet[-1] + 1 - struct = [structlet] - if bus_structure: - - struct = bus_structure - - self.current_bus_structure[direc] = struct - return struct - - def bussify(self, n, direc): - if direc == 'source': - get_p = self.get_sources - get_p_gui = self.get_sources_gui - bus_structure = self.get_bus_structure('source') - else: - get_p = self.get_sinks - get_p_gui = self.get_sinks_gui - bus_structure = self.get_bus_structure('sink') - - for elt in get_p(): - for connect in elt.get_connections(): - self.get_parent().remove_element(connect) - - if ('bus' not in map(lambda a: a.get_type(), get_p())) and len(get_p()) > 0: - struct = self.form_bus_structure(direc) - self.current_bus_structure[direc] = struct - if get_p()[0].get_nports(): - n['nports'] = str(1) - - for i in range(len(struct)): - n['key'] = str(len(get_p())) - n = odict(n) - port = self.get_parent().get_parent().Port(block=self, n=n, dir=direc) - get_p().append(port) - elif 'bus' in map(lambda a: a.get_type(), get_p()): - for elt in get_p_gui(): - get_p().remove(elt) - self.current_bus_structure[direc] = '' - - ############################################## # Import/Export Methods ############################################## def export_data(self): @@ -802,17 +463,19 @@ class Block(Element): Returns: a nested data odict """ - n = odict() - n['key'] = self.get_key() - n['param'] = map(lambda p: p.export_data(), sorted(self.get_params(), key=str)) - if 'bus' in map(lambda a: a.get_type(), self.get_sinks()): - n['bus_sink'] = str(1) - if 'bus' in map(lambda a: a.get_type(), self.get_sources()): - n['bus_source'] = str(1) - return n + n = collections.OrderedDict() + n['key'] = self.key + + params = (param.export_data() for param in six.itervalues(self.params)) + states = (collections.OrderedDict([('key', key), ('value', repr(value))]) + for key, value in six.iteritems(self.states)) + n['param'] = sorted(itertools.chain(states, params), key=lambda p: p['key']) - def get_hash(self): - return hash(tuple(map(hash, self.get_params()))) + if any('bus' in a.get_type() for a in self.sinks): + n['bus_sink'] = '1' + if any('bus' in a.get_type() for a in self.sources): + n['bus_source'] = '1' + return n def import_data(self, n): """ @@ -826,27 +489,296 @@ class Block(Element): Args: n: the nested data odict """ - my_hash = 0 - while self.get_hash() != my_hash: - params_n = n.findall('param') - for param_n in params_n: - key = param_n.find('key') - value = param_n.find('value') - # The key must exist in this block's params - if key in self.get_param_keys(): - self.get_param(key).set_value(value) + param_data = {p['key']: p['value'] for p in n.get('param', [])} + + for key in self.states: + try: + self.states[key] = ast.literal_eval(param_data.pop(key)) + except (KeyError, SyntaxError, ValueError): + pass + + def get_hash(): + return hash(tuple(hash(v) for v in self.params.values())) + + pre_rewrite_hash = -1 + while pre_rewrite_hash != get_hash(): + for key, value in six.iteritems(param_data): + try: + self.params[key].set_value(value) + except KeyError: + continue # Store hash and call rewrite - my_hash = self.get_hash() + pre_rewrite_hash = get_hash() self.rewrite() - bussinks = n.findall('bus_sink') - if len(bussinks) > 0 and not self._bussify_sink: - self.bussify({'name': 'bus', 'type': 'bus'}, 'sink') - elif len(bussinks) > 0: - self.bussify({'name': 'bus', 'type': 'bus'}, 'sink') - self.bussify({'name': 'bus', 'type': 'bus'}, 'sink') - bussrcs = n.findall('bus_source') - if len(bussrcs) > 0 and not self._bussify_source: - self.bussify({'name': 'bus', 'type': 'bus'}, 'source') - elif len(bussrcs) > 0: - self.bussify({'name': 'bus', 'type': 'bus'}, 'source') - self.bussify({'name': 'bus', 'type': 'bus'}, 'source') + + self._import_bus_stuff(n) + + ############################################## + # Bus ports stuff + ############################################## + + def get_bus_structure(self, direction): + bus_structure = self.resolve_dependencies(self._bus_structure[direction]) + if not bus_structure: + return + try: + return self.parent_flowgraph.evaluate(bus_structure) + except: + return + + @staticmethod + def back_ofthe_bus(portlist): + portlist.sort(key=lambda p: p._type == 'bus') + + @staticmethod + def filter_bus_port(ports): + buslist = [p for p in ports if p._type == 'bus'] + return buslist or ports + + def _import_bus_stuff(self, n): + bus_sinks = n.get('bus_sink', []) + if len(bus_sinks) > 0 and not self._bussify_sink: + self.bussify('sink') + elif len(bus_sinks) > 0: + self.bussify('sink') + self.bussify('sink') + bus_sources = n.get('bus_source', []) + if len(bus_sources) > 0 and not self._bussify_source: + self.bussify('source') + elif len(bus_sources) > 0: + self.bussify('source') + self.bussify('source') + + def form_bus_structure(self, direc): + ports = self.sources if direc == 'source' else self.sinks + struct = self.get_bus_structure(direc) + + if not struct: + struct = [list(range(len(ports)))] + + elif any(isinstance(p.get_nports(), int) for p in ports): + last = 0 + structlet = [] + for port in ports: + nports = port.get_nports() + if not isinstance(nports, int): + continue + structlet.extend(a + last for a in range(nports)) + last += nports + struct = [structlet] + + self.current_bus_structure[direc] = struct + return struct + + def bussify(self, direc): + ports = self.sources if direc == 'source' else self.sinks + + for elt in ports: + for connect in elt.get_connections(): + self.parent.remove_element(connect) + + if ports and all('bus' != p.get_type() for p in ports): + struct = self.current_bus_structure[direc] = self.form_bus_structure(direc) + n = {'type': 'bus'} + if ports[0].get_nports(): + n['nports'] = '1' + + for i, structlet in enumerate(struct): + name = 'bus{}#{}'.format(i, len(structlet)) + port = self.parent_platform.get_new_port( + self, direction=direc, key=str(len(ports)), name=name, **n) + ports.append(port) + elif any('bus' == p.get_type() for p in ports): + get_p_gui = self.get_sources_gui if direc == 'source' else self.get_sinks_gui + for elt in get_p_gui(): + ports.remove(elt) + self.current_bus_structure[direc] = '' + + def _init_bus_ports(self, n): + self.current_bus_structure = {'source': '', 'sink': ''} + self._bus_structure = {'source': n.get('bus_structure_source', ''), + 'sink': n.get('bus_structure_sink', '')} + self._bussify_sink = n.get('bus_sink') + self._bussify_source = n.get('bus_source') + if self._bussify_sink: + self.bussify('sink') + if self._bussify_source: + self.bussify('source') + + def _rewrite_bus_ports(self): + return # fixme: probably broken + + def doit(ports, ports_gui, direc): + if not self.current_bus_structure[direc]: + return + + bus_structure = self.form_bus_structure(direc) + for port in ports_gui[len(bus_structure):]: + for connect in port.get_connections(): + self.parent_flowgraph.remove_element(connect) + ports.remove(port) + + port_factory = self.parent_platform.get_new_port + + if len(ports_gui) < len(bus_structure): + for i in range(len(ports_gui), len(bus_structure)): + port = port_factory(self, direction=direc, key=str(1 + i), + name='bus', type='bus') + ports.append(port) + + doit(self.sources, self.get_sources_gui(), 'source') + doit(self.sinks, self.get_sinks_gui(), 'sink') + + if 'bus' in [a.get_type() for a in self.get_sources_gui()]: + for i in range(len(self.get_sources_gui())): + if not self.get_sources_gui()[i].get_connections(): + continue + source = self.get_sources_gui()[i] + sink = [] + + for j in range(len(source.get_connections())): + sink.append(source.get_connections()[j].sink_port) + for elt in source.get_connections(): + self.parent_flowgraph.remove_element(elt) + for j in sink: + self.parent_flowgraph.connect(source, j) + + +class EPyBlock(Block): + + def __init__(self, flow_graph, **n): + super(EPyBlock, self).__init__(flow_graph, **n) + self._epy_source_hash = -1 # for epy blocks + self._epy_reload_error = None + + def rewrite(self): + Element.rewrite(self) + + param_blk = self.params['_io_cache'] + param_src = self.params['_source_code'] + + src = param_src.get_value() + src_hash = hash((self.get_id(), src)) + if src_hash == self._epy_source_hash: + return + + try: + blk_io = utils.epy_block_io.extract(src) + + except Exception as e: + self._epy_reload_error = ValueError(str(e)) + try: # Load last working block io + blk_io_args = eval(param_blk.get_value()) + if len(blk_io_args) == 6: + blk_io_args += ([],) # add empty callbacks + blk_io = utils.epy_block_io.BlockIO(*blk_io_args) + except Exception: + return + else: + self._epy_reload_error = None # Clear previous errors + param_blk.set_value(repr(tuple(blk_io))) + + # print "Rewriting embedded python block {!r}".format(self.get_id()) + + self._epy_source_hash = src_hash + self.name = blk_io.name or blk_io.cls + self._doc = blk_io.doc + self._imports[0] = 'import ' + self.get_id() + self._make = '{0}.{1}({2})'.format(self.get_id(), blk_io.cls, ', '.join( + '{0}=${{ {0} }}'.format(key) for key, _ in blk_io.params)) + self._callbacks = ['{0} = ${{ {0} }}'.format(attr) for attr in blk_io.callbacks] + self._update_params(blk_io.params) + self._update_ports('in', self.sinks, blk_io.sinks, 'sink') + self._update_ports('out', self.sources, blk_io.sources, 'source') + + super(EPyBlock, self).rewrite() + + def _update_params(self, params_in_src): + param_factory = self.parent_platform.get_new_param + params = {} + for param in list(self.params): + if hasattr(param, '__epy_param__'): + params[param.key] = param + del self.params[param.key] + + for key, value in params_in_src: + try: + param = params[key] + if param.default == param.value: + param.set_value(value) + param.default = str(value) + except KeyError: # need to make a new param + param = param_factory( + parent=self, key=key, type='raw', value=value, + name=key.replace('_', ' ').title(), + ) + setattr(param, '__epy_param__', True) + self.params[key] = param + + def _update_ports(self, label, ports, port_specs, direction): + port_factory = self.parent_platform.get_new_port + ports_to_remove = list(ports) + iter_ports = iter(ports) + ports_new = [] + port_current = next(iter_ports, None) + for key, port_type, vlen in port_specs: + reuse_port = ( + port_current is not None and + port_current.get_type() == port_type and + port_current.get_vlen() == vlen and + (key.isdigit() or port_current.key == key) + ) + if reuse_port: + ports_to_remove.remove(port_current) + port, port_current = port_current, next(iter_ports, None) + else: + n = dict(name=label + str(key), type=port_type, key=key) + if port_type == 'message': + n['name'] = key + n['optional'] = '1' + if vlen > 1: + n['vlen'] = str(vlen) + port = port_factory(self, direction=direction, **n) + ports_new.append(port) + # replace old port list with new one + del ports[:] + ports.extend(ports_new) + # remove excess port connections + for port in ports_to_remove: + for connection in port.get_connections(): + self.parent_flowgraph.remove_element(connection) + + def validate(self): + super(EPyBlock, self).validate() + if self._epy_reload_error: + self.params['_source_code'].add_error_message(str(self._epy_reload_error)) + + +class DummyBlock(Block): + + is_dummy_block = True + build_in_param_keys = 'id alias affinity minoutbuf maxoutbuf comment' + + def __init__(self, parent, key, missing_key, params_n): + super(DummyBlock, self).__init__(parent=parent, key=missing_key, name='Missing Block') + param_factory = self.parent_platform.get_new_param + for param_n in params_n: + key = param_n['key'] + self.params.setdefault(key, param_factory(self, key=key, name=key, type='string')) + + def is_valid(self): + return False + + @property + def enabled(self): + return False + + def add_missing_port(self, key, dir): + port = self.parent_platform.get_new_port( + parent=self, direction=dir, key=key, name='?', type='', + ) + if port.is_source: + self.sources.append(port) + else: + self.sinks.append(port) + return port diff --git a/grc/core/CMakeLists.txt b/grc/core/CMakeLists.txt deleted file mode 100644 index f340127873..0000000000 --- a/grc/core/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright 2011 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. - -file(GLOB py_files "*.py") - -GR_PYTHON_INSTALL( - FILES ${py_files} - DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core -) - -file(GLOB dtd_files "*.dtd") - -install( - FILES ${dtd_files} default_flow_graph.grc - DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core -) - -add_subdirectory(generator) -add_subdirectory(utils) diff --git a/grc/core/Config.py b/grc/core/Config.py index 744ad06ba9..cc199a348f 100644 --- a/grc/core/Config.py +++ b/grc/core/Config.py @@ -17,6 +17,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import + import os from os.path import expanduser, normpath, expandvars, exists @@ -24,16 +26,14 @@ from . import Constants class Config(object): - - key = 'grc' name = 'GNU Radio Companion (no gui)' license = __doc__.strip() website = 'http://gnuradio.org' hier_block_lib_dir = os.environ.get('GRC_HIER_PATH', Constants.DEFAULT_HIER_BLOCK_LIB_DIR) - def __init__(self, prefs_file, version, version_parts=None, name=None): - self.prefs = prefs_file + def __init__(self, version, version_parts=None, name=None, prefs=None): + self._gr_prefs = prefs if prefs else DummyPrefs() self.version = version self.version_parts = version_parts or version[1:].split('-', 1)[0].split('.')[:3] if name: @@ -46,8 +46,8 @@ class Config(object): paths_sources = ( self.hier_block_lib_dir, os.environ.get('GRC_BLOCKS_PATH', ''), - self.prefs.get_string('grc', 'local_blocks_path', ''), - self.prefs.get_string('grc', 'global_blocks_path', ''), + self._gr_prefs.get_string('grc', 'local_blocks_path', ''), + self._gr_prefs.get_string('grc', 'global_blocks_path', ''), ) collected_paths = sum((paths.split(path_list_sep) @@ -62,7 +62,22 @@ class Config(object): def default_flow_graph(self): user_default = ( os.environ.get('GRC_DEFAULT_FLOW_GRAPH') or - self.prefs.get_string('grc', 'default_flow_graph', '') or + self._gr_prefs.get_string('grc', 'default_flow_graph', '') or os.path.join(self.hier_block_lib_dir, 'default_flow_graph.grc') ) return user_default if exists(user_default) else Constants.DEFAULT_FLOW_GRAPH + + +class DummyPrefs(object): + + def get_string(self, category, item, default): + return str(default) + + def set_string(self, category, item, value): + pass + + def get_long(self, category, item, default): + return int(default) + + def save(self): + pass diff --git a/grc/core/Connection.py b/grc/core/Connection.py index c028d89ddc..066532149b 100644 --- a/grc/core/Connection.py +++ b/grc/core/Connection.py @@ -17,16 +17,21 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import + +import collections + +from six.moves import range + from . import Constants -from .Element import Element -from .utils import odict +from .Element import Element, lazy_property class Connection(Element): is_connection = True - def __init__(self, flow_graph, porta, portb): + def __init__(self, parent, porta, portb): """ Make a new connection given the parent and 2 ports. @@ -39,75 +44,87 @@ class Connection(Element): Returns: a new connection """ - Element.__init__(self, flow_graph) + Element.__init__(self, parent) + + source, sink = self._get_sink_source(porta, portb) + + self.source_port = source + self.sink_port = sink + + # Ensure that this connection (source -> sink) is unique + if self in self.parent_flowgraph.connections: + raise LookupError('This connection between source and sink is not unique.') + + if self.is_bus(): + self._make_bus_connect() + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.source_port == other.source_port and self.sink_port == other.sink_port + + @staticmethod + def _get_sink_source(porta, portb): source = sink = None # Separate the source and sink for port in (porta, portb): if port.is_source: source = port - else: + if port.is_sink: sink = port if not source: raise ValueError('Connection could not isolate source') if not sink: raise ValueError('Connection could not isolate sink') - busses = len(filter(lambda a: a.get_type() == 'bus', [source, sink])) % 2 - if not busses == 0: - raise ValueError('busses must get with busses') + return source, sink - if not len(source.get_associated_ports()) == len(sink.get_associated_ports()): - raise ValueError('port connections must have same cardinality') - # Ensure that this connection (source -> sink) is unique - for connection in flow_graph.connections: - if connection.get_source() is source and connection.get_sink() is sink: - raise LookupError('This connection between source and sink is not unique.') - self._source = source - self._sink = sink - if source.get_type() == 'bus': - - sources = source.get_associated_ports() - sinks = sink.get_associated_ports() - - for i in range(len(sources)): - try: - flow_graph.connect(sources[i], sinks[i]) - except: - pass + @lazy_property + def source_block(self): + return self.source_port.parent_block + + @lazy_property + def sink_block(self): + return self.sink_port.parent_block + + @property + def enabled(self): + """ + Get the enabled state of this connection. + + Returns: + true if source and sink blocks are enabled + """ + return self.source_block.enabled and self.sink_block.enabled def __str__(self): return 'Connection (\n\t{}\n\t\t{}\n\t{}\n\t\t{}\n)'.format( - self.get_source().get_parent(), - self.get_source(), - self.get_sink().get_parent(), - self.get_sink(), + self.source_block, self.source_port, self.sink_block, self.sink_port, ) def is_bus(self): - return self.get_source().get_type() == self.get_sink().get_type() == 'bus' + return self.source_port.get_type() == 'bus' def validate(self): """ Validate the connections. The ports must match in io size. """ - """ - Validate the connections. - The ports must match in type. - """ Element.validate(self) - platform = self.get_parent().get_parent() - source_domain = self.get_source().get_domain() - sink_domain = self.get_sink().get_domain() + platform = self.parent_platform + + source_domain = self.source_port.domain + sink_domain = self.sink_port.domain + if (source_domain, sink_domain) not in platform.connection_templates: self.add_error_message('No connection known for domains "{}", "{}"'.format( - source_domain, sink_domain)) + source_domain, sink_domain)) too_many_other_sinks = ( not platform.domains.get(source_domain, []).get('multiple_sinks', False) and - len(self.get_source().get_enabled_connections()) > 1 + len(self.source_port.get_enabled_connections()) > 1 ) too_many_other_sources = ( not platform.domains.get(sink_domain, []).get('multiple_sources', False) and - len(self.get_sink().get_enabled_connections()) > 1 + len(self.sink_port.get_enabled_connections()) > 1 ) if too_many_other_sinks: self.add_error_message( @@ -116,30 +133,11 @@ class Connection(Element): self.add_error_message( 'Domain "{}" can have only one upstream block'.format(sink_domain)) - source_size = Constants.TYPE_TO_SIZEOF[self.get_source().get_type()] * self.get_source().get_vlen() - sink_size = Constants.TYPE_TO_SIZEOF[self.get_sink().get_type()] * self.get_sink().get_vlen() + source_size = Constants.TYPE_TO_SIZEOF[self.source_port.get_type()] * self.source_port.get_vlen() + sink_size = Constants.TYPE_TO_SIZEOF[self.sink_port.get_type()] * self.sink_port.get_vlen() if source_size != sink_size: self.add_error_message('Source IO size "{}" does not match sink IO size "{}".'.format(source_size, sink_size)) - def get_enabled(self): - """ - Get the enabled state of this connection. - - Returns: - true if source and sink blocks are enabled - """ - return self.get_source().get_parent().get_enabled() and \ - self.get_sink().get_parent().get_enabled() - - ############################# - # Access Ports - ############################# - def get_sink(self): - return self._sink - - def get_source(self): - return self._source - ############################################## # Import/Export Methods ############################################## @@ -150,9 +148,23 @@ class Connection(Element): Returns: a nested data odict """ - n = odict() - n['source_block_id'] = self.get_source().get_parent().get_id() - n['sink_block_id'] = self.get_sink().get_parent().get_id() - n['source_key'] = self.get_source().get_key() - n['sink_key'] = self.get_sink().get_key() + n = collections.OrderedDict() + n['source_block_id'] = self.source_block.get_id() + n['sink_block_id'] = self.sink_block.get_id() + n['source_key'] = self.source_port.key + n['sink_key'] = self.sink_port.key return n + + def _make_bus_connect(self): + source, sink = self.source_port, self.sink_port + + if source.get_type() == sink.get_type() == 'bus': + raise ValueError('busses must get with busses') + + sources = source.get_associated_ports() + sinks = sink.get_associated_ports() + if len(sources) != len(sinks): + raise ValueError('port connections must have same cardinality') + + for ports in zip(sources, sinks): + self.parent_flowgraph.connect(*ports) diff --git a/grc/core/Constants.py b/grc/core/Constants.py index edd3442a94..caf301be60 100644 --- a/grc/core/Constants.py +++ b/grc/core/Constants.py @@ -17,10 +17,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import + import os -import numpy import stat +import numpy +import six + # Data files DATA_DIR = os.path.dirname(__file__) FLOW_GRAPH_DTD = os.path.join(DATA_DIR, 'flow_graph.dtd') @@ -50,29 +54,35 @@ BLOCK_FLAG_DISABLE_BYPASS = 'disable_bypass' BLOCK_FLAG_NEED_QT_GUI = 'need_qt_gui' BLOCK_FLAG_DEPRECATED = 'deprecated' -# Block States -BLOCK_DISABLED = 0 -BLOCK_ENABLED = 1 -BLOCK_BYPASSED = 2 - # File creation modes TOP_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | \ stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH HIER_BLOCK_FILE_MODE = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH +PARAM_TYPE_NAMES = ( + 'raw', 'enum', + 'complex', 'real', 'float', 'int', + 'complex_vector', 'real_vector', 'float_vector', 'int_vector', + 'hex', 'string', 'bool', + 'file_open', 'file_save', '_multiline', '_multiline_python_external', + 'id', 'stream_id', + 'gui_hint', + 'import', +) + # Define types, native python + numpy VECTOR_TYPES = (tuple, list, set, numpy.ndarray) COMPLEX_TYPES = [complex, numpy.complex, numpy.complex64, numpy.complex128] REAL_TYPES = [float, numpy.float, numpy.float32, numpy.float64] -INT_TYPES = [int, long, numpy.int, numpy.int8, numpy.int16, numpy.int32, numpy.uint64, +INT_TYPES = [int, numpy.int, numpy.int8, numpy.int16, numpy.int32, numpy.uint64, numpy.uint, numpy.uint8, numpy.uint16, numpy.uint32, numpy.uint64] # Cast to tuple for isinstance, concat subtypes COMPLEX_TYPES = tuple(COMPLEX_TYPES + REAL_TYPES + INT_TYPES) REAL_TYPES = tuple(REAL_TYPES + INT_TYPES) INT_TYPES = tuple(INT_TYPES) -# Updating colors. Using the standard color pallette from: -# http://www.google.com/design/spec/style/color.html#color-color-palette +# Updating colors. Using the standard color palette from: +# http://www.google.com/design/spec/style/color.html#color-color-palette # Most are based on the main, primary color standard. Some are within # that color's spectrum when it was deemed necessary. GRC_COLOR_BROWN = '#795548' @@ -95,54 +105,32 @@ GRC_COLOR_GREY = '#BDBDBD' GRC_COLOR_WHITE = '#FFFFFF' CORE_TYPES = ( # name, key, sizeof, color - ('Complex Float 64', 'fc64', 16, GRC_COLOR_BROWN), - ('Complex Float 32', 'fc32', 8, GRC_COLOR_BLUE), - ('Complex Integer 64', 'sc64', 16, GRC_COLOR_LIGHT_GREEN), - ('Complex Integer 32', 'sc32', 8, GRC_COLOR_GREEN), - ('Complex Integer 16', 'sc16', 4, GRC_COLOR_AMBER), - ('Complex Integer 8', 'sc8', 2, GRC_COLOR_PURPLE), - ('Float 64', 'f64', 8, GRC_COLOR_CYAN), - ('Float 32', 'f32', 4, GRC_COLOR_ORANGE), - ('Integer 64', 's64', 8, GRC_COLOR_LIME), - ('Integer 32', 's32', 4, GRC_COLOR_TEAL), - ('Integer 16', 's16', 2, GRC_COLOR_YELLOW), - ('Integer 8', 's8', 1, GRC_COLOR_PURPLE_A400), - ('Bits (unpacked byte)', 'bit', 1, GRC_COLOR_PURPLE_A100), - ('Async Message', 'message', 0, GRC_COLOR_GREY), - ('Bus Connection', 'bus', 0, GRC_COLOR_WHITE), - ('Wildcard', '', 0, GRC_COLOR_WHITE), + ('Complex Float 64', 'fc64', 16, GRC_COLOR_BROWN), + ('Complex Float 32', 'fc32', 8, GRC_COLOR_BLUE), + ('Complex Integer 64', 'sc64', 16, GRC_COLOR_LIGHT_GREEN), + ('Complex Integer 32', 'sc32', 8, GRC_COLOR_GREEN), + ('Complex Integer 16', 'sc16', 4, GRC_COLOR_AMBER), + ('Complex Integer 8', 'sc8', 2, GRC_COLOR_PURPLE), + ('Float 64', 'f64', 8, GRC_COLOR_CYAN), + ('Float 32', 'f32', 4, GRC_COLOR_ORANGE), + ('Integer 64', 's64', 8, GRC_COLOR_LIME), + ('Integer 32', 's32', 4, GRC_COLOR_TEAL), + ('Integer 16', 's16', 2, GRC_COLOR_YELLOW), + ('Integer 8', 's8', 1, GRC_COLOR_PURPLE_A400), + ('Bits (unpacked byte)', 'bit', 1, GRC_COLOR_PURPLE_A100), + ('Async Message', 'message', 0, GRC_COLOR_GREY), + ('Bus Connection', 'bus', 0, GRC_COLOR_WHITE), + ('Wildcard', '', 0, GRC_COLOR_WHITE), ) ALIAS_TYPES = { 'complex': (8, GRC_COLOR_BLUE), - 'float': (4, GRC_COLOR_ORANGE), - 'int': (4, GRC_COLOR_TEAL), - 'short': (2, GRC_COLOR_YELLOW), - 'byte': (1, GRC_COLOR_PURPLE_A400), - 'bits': (1, GRC_COLOR_PURPLE_A100), + 'float': (4, GRC_COLOR_ORANGE), + 'int': (4, GRC_COLOR_TEAL), + 'short': (2, GRC_COLOR_YELLOW), + 'byte': (1, GRC_COLOR_PURPLE_A400), + 'bits': (1, GRC_COLOR_PURPLE_A100), } -TYPE_TO_COLOR = dict() -TYPE_TO_SIZEOF = dict() - -for name, key, sizeof, color in CORE_TYPES: - TYPE_TO_COLOR[key] = color - TYPE_TO_SIZEOF[key] = sizeof - -for key, (sizeof, color) in ALIAS_TYPES.iteritems(): - TYPE_TO_COLOR[key] = color - TYPE_TO_SIZEOF[key] = sizeof - -# Coloring -COMPLEX_COLOR_SPEC = '#3399FF' -FLOAT_COLOR_SPEC = '#FF8C69' -INT_COLOR_SPEC = '#00FF99' -SHORT_COLOR_SPEC = '#FFFF66' -BYTE_COLOR_SPEC = '#FF66FF' -COMPLEX_VECTOR_COLOR_SPEC = '#3399AA' -FLOAT_VECTOR_COLOR_SPEC = '#CC8C69' -INT_VECTOR_COLOR_SPEC = '#00CC99' -SHORT_VECTOR_COLOR_SPEC = '#CCCC33' -BYTE_VECTOR_COLOR_SPEC = '#CC66CC' -ID_COLOR_SPEC = '#DDDDDD' -WILDCARD_COLOR_SPEC = '#FFFFFF' +TYPE_TO_SIZEOF = {key: sizeof for name, key, sizeof, color in CORE_TYPES} +TYPE_TO_SIZEOF.update((key, sizeof) for key, (sizeof, _) in ALIAS_TYPES.items()) diff --git a/grc/core/Element.py b/grc/core/Element.py index 67c36e12b4..86e0746655 100644 --- a/grc/core/Element.py +++ b/grc/core/Element.py @@ -1,28 +1,50 @@ -""" -Copyright 2008, 2009, 2015 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" +# Copyright 2008, 2009, 2015, 2016 Free Software Foundation, Inc. +# This file is part of GNU Radio +# +# GNU Radio Companion 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 2 +# of the License, or (at your option) any later version. +# +# GNU Radio Companion 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +import weakref +import functools + + +class lazy_property(object): + + def __init__(self, func): + self.func = func + functools.update_wrapper(self, func) + + def __get__(self, instance, cls): + if instance is None: + return self + value = self.func(instance) + setattr(instance, self.func.__name__, value) + return value + + +def nop_write(prop): + """Make this a property with a nop setter""" + def nop(self, value): + pass + return prop.setter(nop) class Element(object): def __init__(self, parent=None): - self._parent = parent - self._error_messages = list() + self._parent = weakref.ref(parent) if parent else lambda: None + self._error_messages = [] ################################################## # Element Validation API @@ -33,6 +55,7 @@ class Element(object): Call this base method before adding error messages in the subclass. """ del self._error_messages[:] + for child in self.get_children(): child.validate() @@ -43,7 +66,9 @@ class Element(object): Returns: true when the element is enabled and has no error messages or is bypassed """ - return (not self.get_error_messages() or not self.get_enabled()) or self.get_bypassed() + if not self.enabled or self.get_bypassed(): + return True + return not next(self.iter_error_messages(), False) def add_error_message(self, msg): """ @@ -63,11 +88,20 @@ class Element(object): Returns: a list of error message strings """ - error_messages = list(self._error_messages) # Make a copy - for child in filter(lambda c: c.get_enabled() and not c.get_bypassed(), self.get_children()): - for msg in child.get_error_messages(): - error_messages.append("{}:\n\t{}".format(child, msg.replace("\n", "\n\t"))) - return error_messages + return [msg if elem is self else "{}:\n\t{}".format(elem, msg.replace("\n", "\n\t")) + for elem, msg in self.iter_error_messages()] + + def iter_error_messages(self): + """ + Iterate over error messages. Yields tuples of (element, message) + """ + for msg in self._error_messages: + yield self, msg + for child in self.get_children(): + if not child.enabled or child.get_bypassed(): + continue + for element_msg in child.iter_error_messages(): + yield element_msg def rewrite(self): """ @@ -77,7 +111,8 @@ class Element(object): for child in self.get_children(): child.rewrite() - def get_enabled(self): + @property + def enabled(self): return True def get_bypassed(self): @@ -86,8 +121,39 @@ class Element(object): ############################################## # Tree-like API ############################################## - def get_parent(self): - return self._parent + @property + def parent(self): + return self._parent() + + def get_parent_by_type(self, cls): + parent = self.parent + if parent is None: + return None + elif isinstance(parent, cls): + return parent + else: + return parent.get_parent_by_type(cls) + + @lazy_property + def parent_platform(self): + from .Platform import Platform + return self.get_parent_by_type(Platform) + + @lazy_property + def parent_flowgraph(self): + from .FlowGraph import FlowGraph + return self.get_parent_by_type(FlowGraph) + + @lazy_property + def parent_block(self): + from .Block import Block + return self.get_parent_by_type(Block) + + def reset_parents_by_type(self): + """Reset all lazy properties""" + for name, obj in vars(Element): # explicitly only in Element, not subclasses + if isinstance(obj, lazy_property): + delattr(self, name) def get_children(self): return list() diff --git a/grc/core/Element.pyi b/grc/core/Element.pyi index c81180a33e..2a2aed401c 100644 --- a/grc/core/Element.pyi +++ b/grc/core/Element.pyi @@ -1,4 +1,4 @@ -# Copyright 2008, 2009, 2015, 2016 Free Software Foundation, Inc. +# Copyright 2016 Free Software Foundation, Inc. # This file is part of GNU Radio # # GNU Radio Companion is free software; you can redistribute it and/or @@ -15,40 +15,27 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +from typing import Union + from . import Platform, FlowGraph, Block -def lazy_property(func): - return func +lazy_property = property # fixme: descriptors don't seems to be supported class Element(object): - def __init__(self, parent=None): - ... + def __init__(self, parent: Union[None, 'Element'] = None): ... - @property - def parent(self): - ... + @lazy_property + def parent(self) -> 'Element': ... - def get_parent_by_type(self, cls): - parent = self.parent - if parent is None: - return None - elif isinstance(parent, cls): - return parent - else: - return parent.get_parent_by_type(cls) + def get_parent_by_type(self, cls) -> Union[None, 'Element']: ... @lazy_property - def parent_platform(self): -> Platform.Platform - ... + def parent_platform(self) -> Platform.Platform: ... @lazy_property - def parent_flowgraph(self): -> FlowGraph.FlowGraph - ... + def parent_flowgraph(self) -> FlowGraph.FlowGraph: ... @lazy_property - def parent_block(self): -> Block.Block - ... - - + def parent_block(self) -> Block.Block: ... diff --git a/grc/core/FlowGraph.py b/grc/core/FlowGraph.py index ecae11cf1a..bf5bf6d93e 100644 --- a/grc/core/FlowGraph.py +++ b/grc/core/FlowGraph.py @@ -15,17 +15,19 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +from __future__ import absolute_import, print_function + import imp -from itertools import ifilter, chain -from operator import methodcaller, attrgetter +import time import re +from operator import methodcaller +import collections import sys -import time from . import Messages from .Constants import FLOW_GRAPH_FILE_FORMAT_VERSION from .Element import Element -from .utils import odict, expr_utils, shlex +from .utils import expr_utils, shlex _parameter_matcher = re.compile('^(parameter)$') _monitors_searcher = re.compile('(ctrlport_monitor)') @@ -39,36 +41,31 @@ class FlowGraph(Element): is_flow_graph = True - def __init__(self, platform): + def __init__(self, parent): """ Make a flow graph from the arguments. Args: - platform: a platforms with blocks and contrcutors + parent: a platforms with blocks and element factories Returns: the flow graph object """ - Element.__init__(self, platform) - self._elements = [] + Element.__init__(self, parent) self._timestamp = time.ctime() + self._options_block = self.parent_platform.get_new_block(self, 'options') - self.platform = platform # todo: make this a lazy prop - self.blocks = [] + self.blocks = [self._options_block] self.connections = [] self._eval_cache = {} self.namespace = {} self.grc_file_path = '' - self._options_block = self.new_block('options') def __str__(self): return 'FlowGraph - {}({})'.format(self.get_option('title'), self.get_option('id')) - ############################################## - # TODO: Move these to new generator package - ############################################## def get_imports(self): """ Get a set of all import statements in this flow graph namespace. @@ -87,7 +84,7 @@ class FlowGraph(Element): Returns: a sorted list of variable blocks in order of dependency (indep -> dep) """ - variables = filter(attrgetter('is_variable'), self.iter_enabled_blocks()) + variables = [block for block in self.iter_enabled_blocks() if block.is_variable] return expr_utils.sort_objects(variables, methodcaller('get_id'), methodcaller('get_var_make')) def get_parameters(self): @@ -97,54 +94,53 @@ class FlowGraph(Element): Returns: a list of parameterized variables """ - parameters = filter(lambda b: _parameter_matcher.match(b.get_key()), self.iter_enabled_blocks()) + parameters = [b for b in self.iter_enabled_blocks() if _parameter_matcher.match(b.key)] return parameters def get_monitors(self): """ Get a list of all ControlPort monitors """ - monitors = filter(lambda b: _monitors_searcher.search(b.get_key()), - self.iter_enabled_blocks()) + monitors = [b for b in self.iter_enabled_blocks() if _monitors_searcher.search(b.key)] return monitors def get_python_modules(self): """Iterate over custom code block ID and Source""" for block in self.iter_enabled_blocks(): - if block.get_key() == 'epy_module': + if block.key == 'epy_module': yield block.get_id(), block.get_param('source_code').get_value() def get_bussink(self): - bussink = filter(lambda b: _bussink_searcher.search(b.get_key()), self.get_enabled_blocks()) + bussink = [b for b in self.get_enabled_blocks() if _bussink_searcher.search(b.key)] for i in bussink: - for j in i.get_params(): - if j.get_name() == 'On/Off' and j.get_value() == 'on': + for j in i.params.values(): + if j.name == 'On/Off' and j.get_value() == 'on': return True return False def get_bussrc(self): - bussrc = filter(lambda b: _bussrc_searcher.search(b.get_key()), self.get_enabled_blocks()) + bussrc = [b for b in self.get_enabled_blocks() if _bussrc_searcher.search(b.key)] for i in bussrc: - for j in i.get_params(): - if j.get_name() == 'On/Off' and j.get_value() == 'on': + for j in i.params.values(): + if j.name == 'On/Off' and j.get_value() == 'on': return True return False def get_bus_structure_sink(self): - bussink = filter(lambda b: _bus_struct_sink_searcher.search(b.get_key()), self.get_enabled_blocks()) + bussink = [b for b in self.get_enabled_blocks() if _bus_struct_sink_searcher.search(b.key)] return bussink def get_bus_structure_src(self): - bussrc = filter(lambda b: _bus_struct_src_searcher.search(b.get_key()), self.get_enabled_blocks()) + bussrc = [b for b in self.get_enabled_blocks() if _bus_struct_src_searcher.search(b.key)] return bussrc def iter_enabled_blocks(self): """ Get an iterator of all blocks that are enabled and not bypassed. """ - return ifilter(methodcaller('get_enabled'), self.blocks) + return (block for block in self.blocks if block.enabled) def get_enabled_blocks(self): """ @@ -162,7 +158,7 @@ class FlowGraph(Element): Returns: a list of blocks """ - return filter(methodcaller('get_bypassed'), self.blocks) + return [block for block in self.blocks if block.get_bypassed()] def get_enabled_connections(self): """ @@ -171,7 +167,7 @@ class FlowGraph(Element): Returns: a list of connections """ - return filter(methodcaller('get_enabled'), self.connections) + return [connection for connection in self.connections if connection.enabled] def get_option(self, key): """ @@ -206,19 +202,6 @@ class FlowGraph(Element): raise KeyError('No block with ID {!r}'.format(id)) def get_elements(self): - """ - Get a list of all the elements. - Always ensure that the options block is in the list (only once). - - Returns: - the element list - """ - options_block_count = self.blocks.count(self._options_block) - if not options_block_count: - self.blocks.append(self._options_block) - for i in range(options_block_count-1): - self.blocks.remove(self._options_block) - return self.blocks + self.connections get_children = get_elements @@ -227,26 +210,22 @@ class FlowGraph(Element): """ Flag the namespace to be renewed. """ - self.renew_namespace() - for child in chain(self.blocks, self.connections): - child.rewrite() - - self.bus_ports_rewrite() + Element.rewrite(self) def renew_namespace(self): namespace = {} # Load imports for expr in self.get_imports(): try: - exec expr in namespace + exec(expr, namespace) except: pass for id, expr in self.get_python_modules(): try: module = imp.new_module(id) - exec expr in module.__dict__ + exec(expr, module.__dict__) namespace[id] = module except: pass @@ -293,7 +272,7 @@ class FlowGraph(Element): # Add/remove stuff ############################################## - def new_block(self, key): + def new_block(self, key, **kwargs): """ Get a new block of the specified key. Add the block to the list of elements. @@ -304,8 +283,10 @@ class FlowGraph(Element): Returns: the new block or None if not found """ + if key == 'options': + return self._options_block try: - block = self.platform.get_new_block(self, key) + block = self.parent_platform.get_new_block(self, key, **kwargs) self.blocks.append(block) except KeyError: block = None @@ -324,8 +305,8 @@ class FlowGraph(Element): the new connection """ - connection = self.platform.Connection( - flow_graph=self, porta=porta, portb=portb) + connection = self.parent_platform.Connection( + parent=self, porta=porta, portb=portb) self.connections.append(connection) return connection @@ -336,22 +317,25 @@ class FlowGraph(Element): If the element is a block, remove its connections. If the element is a connection, just remove the connection. """ + if element is self._options_block: + return + if element.is_port: # Found a port, set to parent signal block - element = element.get_parent() + element = element.parent if element in self.blocks: # Remove block, remove all involved connections for port in element.get_ports(): - map(self.remove_element, port.get_connections()) + for connection in port.get_connections(): + self.remove_element(connection) self.blocks.remove(element) elif element in self.connections: if element.is_bus(): - cons_list = [] - for i in map(lambda a: a.get_connections(), element.get_source().get_associated_ports()): - cons_list.extend(i) - map(self.remove_element, cons_list) + for port in element.source_port.get_associated_ports(): + for connection in port.get_connections(): + self.remove_element(connection) self.connections.remove(element) ############################################## @@ -367,25 +351,24 @@ class FlowGraph(Element): """ # sort blocks and connections for nicer diffs blocks = sorted(self.blocks, key=lambda b: ( - b.get_key() != 'options', # options to the front - not b.get_key().startswith('variable'), # then vars + b.key != 'options', # options to the front + not b.key.startswith('variable'), # then vars str(b) )) connections = sorted(self.connections, key=str) - n = odict() + n = collections.OrderedDict() n['timestamp'] = self._timestamp n['block'] = [b.export_data() for b in blocks] n['connection'] = [c.export_data() for c in connections] - instructions = odict({ - 'created': '.'.join(self.get_parent().config.version_parts), - 'format': FLOW_GRAPH_FILE_FORMAT_VERSION, - }) - return odict({'flow_graph': n, '_instructions': instructions}) + instructions = collections.OrderedDict() + instructions['created'] = '.'.join(self.parent.config.version_parts) + instructions['format'] = FLOW_GRAPH_FILE_FORMAT_VERSION + return {'flow_graph': n, '_instructions': instructions} def import_data(self, n): """ Import blocks and connections into this flow graph. - Clear this flowgraph of all previous blocks and connections. + Clear this flow graph of all previous blocks and connections. Any blocks or connections in error will be ignored. Args: @@ -396,38 +379,37 @@ class FlowGraph(Element): del self.connections[:] # set file format try: - instructions = n.find('_instructions') or {} + instructions = n.get('_instructions', {}) file_format = int(instructions.get('format', '0')) or _guess_file_format_1(n) except: file_format = 0 - fg_n = n and n.find('flow_graph') or odict() # use blank data if none provided - self._timestamp = fg_n.find('timestamp') or time.ctime() + fg_n = n and n.get('flow_graph', {}) # use blank data if none provided + self._timestamp = fg_n.get('timestamp', time.ctime()) # build the blocks - self._options_block = self.new_block('options') - for block_n in fg_n.findall('block'): - key = block_n.find('key') - block = self._options_block if key == 'options' else self.new_block(key) + self.blocks.append(self._options_block) + for block_n in fg_n.get('block', []): + key = block_n['key'] + block = self.new_block(key) if not block: # we're before the initial fg update(), so no evaluated values! # --> use raw value instead path_param = self._options_block.get_param('hier_block_src_path') - file_path = self.platform.find_file_in_paths( + file_path = self.parent_platform.find_file_in_paths( filename=key + '.grc', paths=path_param.get_value(), cwd=self.grc_file_path ) if file_path: # grc file found. load and get block - self.platform.load_and_generate_flow_graph(file_path, hier_only=True) + self.parent_platform.load_and_generate_flow_graph(file_path, hier_only=True) block = self.new_block(key) # can be None if not block: # looks like this block key cannot be found # create a dummy block instead - block = self.new_block('dummy_block') - # Ugly ugly ugly - _initialize_dummy_block(block, block_n) + block = self.new_block('_dummy', missing_key=key, + params_n=block_n.get('param', [])) print('Block key "%s" not found' % key) block.import_data(block_n) @@ -436,26 +418,26 @@ class FlowGraph(Element): # build the connections def verify_and_get_port(key, block, dir): - ports = block.get_sinks() if dir == 'sink' else block.get_sources() + ports = block.sinks if dir == 'sink' else block.sources for port in ports: - if key == port.get_key(): + if key == port.key: break - if not key.isdigit() and port.get_type() == '' and key == port.get_name(): + if not key.isdigit() and port.get_type() == '' and key == port.name: break else: if block.is_dummy_block: - port = _dummy_block_add_port(block, key, dir) + port = block.add_missing_port(key, dir) else: raise LookupError('%s key %r not in %s block keys' % (dir, key, dir)) return port errors = False - for connection_n in fg_n.findall('connection'): + for connection_n in fg_n.get('connection', []): # get the block ids and port keys - source_block_id = connection_n.find('source_block_id') - sink_block_id = connection_n.find('sink_block_id') - source_key = connection_n.find('source_key') - sink_key = connection_n.find('sink_key') + source_block_id = connection_n.get('source_block_id') + sink_block_id = connection_n.get('sink_block_id') + source_key = connection_n.get('source_key') + sink_key = connection_n.get('sink_key') try: source_block = self.get_block(source_block_id) sink_block = self.get_block(sink_block_id) @@ -478,61 +460,6 @@ class FlowGraph(Element): self.rewrite() # global rewrite return errors - ############################################## - # Needs to go - ############################################## - def bus_ports_rewrite(self): - # todo: move to block.rewrite() - for block in self.blocks: - for direc in ['source', 'sink']: - if direc == 'source': - get_p = block.get_sources - get_p_gui = block.get_sources_gui - bus_structure = block.form_bus_structure('source') - else: - get_p = block.get_sinks - get_p_gui = block.get_sinks_gui - bus_structure = block.form_bus_structure('sink') - - if 'bus' in map(lambda a: a.get_type(), get_p_gui()): - if len(get_p_gui()) > len(bus_structure): - times = range(len(bus_structure), len(get_p_gui())) - for i in times: - for connect in get_p_gui()[-1].get_connections(): - block.get_parent().remove_element(connect) - get_p().remove(get_p_gui()[-1]) - elif len(get_p_gui()) < len(bus_structure): - n = {'name': 'bus', 'type': 'bus'} - if True in map( - lambda a: isinstance(a.get_nports(), int), - get_p()): - n['nports'] = str(1) - - times = range(len(get_p_gui()), len(bus_structure)) - - for i in times: - n['key'] = str(len(get_p())) - n = odict(n) - port = block.get_parent().get_parent().Port( - block=block, n=n, dir=direc) - get_p().append(port) - - if 'bus' in map(lambda a: a.get_type(), - block.get_sources_gui()): - for i in range(len(block.get_sources_gui())): - if len(block.get_sources_gui()[ - i].get_connections()) > 0: - source = block.get_sources_gui()[i] - sink = [] - - for j in range(len(source.get_connections())): - sink.append( - source.get_connections()[j].get_sink()) - for elt in source.get_connections(): - self.remove_element(elt) - for j in sink: - self.connect(source, j) - def _update_old_message_port_keys(source_key, sink_key, source_block, sink_block): """ @@ -549,10 +476,10 @@ def _update_old_message_port_keys(source_key, sink_key, source_block, sink_block """ try: # get ports using the "old way" (assuming liner indexed keys) - source_port = source_block.get_sources()[int(source_key)] - sink_port = sink_block.get_sinks()[int(sink_key)] + source_port = source_block.sources[int(source_key)] + sink_port = sink_block.sinks[int(sink_key)] if source_port.get_type() == "message" and sink_port.get_type() == "message": - source_key, sink_key = source_port.get_key(), sink_port.get_key() + source_key, sink_key = source_port.key, sink_port.key except (ValueError, IndexError): pass return source_key, sink_key # do nothing @@ -564,39 +491,11 @@ def _guess_file_format_1(n): """ try: has_non_numeric_message_keys = any(not ( - connection_n.find('source_key').isdigit() and - connection_n.find('sink_key').isdigit() - ) for connection_n in n.find('flow_graph').findall('connection')) + connection_n.get('source_key', '').isdigit() and + connection_n.get('sink_key', '').isdigit() + ) for connection_n in n.get('flow_graph', []).get('connection', [])) if has_non_numeric_message_keys: return 1 except: pass return 0 - - -def _initialize_dummy_block(block, block_n): - """ - This is so ugly... dummy-fy a block - Modify block object to get the behaviour for a missing block - """ - - block._key = block_n.find('key') - block.is_dummy_block = lambda: True - block.is_valid = lambda: False - block.get_enabled = lambda: False - for param_n in block_n.findall('param'): - if param_n['key'] not in block.get_param_keys(): - new_param_n = odict({'key': param_n['key'], 'name': param_n['key'], 'type': 'string'}) - params = block.get_parent().get_parent().Param(block=block, n=new_param_n) - block.get_params().append(params) - - -def _dummy_block_add_port(block, key, dir): - """ This is so ugly... Add a port to a dummy-field block """ - port_n = odict({'name': '?', 'key': key, 'type': ''}) - port = block.get_parent().get_parent().Port(block=block, n=port_n, dir=dir) - if port.is_source: - block.get_sources().append(port) - else: - block.get_sinks().append(port) - return port diff --git a/grc/core/Messages.py b/grc/core/Messages.py index 8daa12c33f..f546c3b62e 100644 --- a/grc/core/Messages.py +++ b/grc/core/Messages.py @@ -16,9 +16,10 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +from __future__ import absolute_import + import traceback import sys -import os # A list of functions that can receive a message. MESSENGERS_LIST = list() @@ -124,8 +125,8 @@ def send_fail_save(file_path): send('>>> Error: Cannot save: %s\n' % file_path) -def send_fail_connection(): - send('>>> Error: Cannot create connection.\n') +def send_fail_connection(msg=''): + send('>>> Error: Cannot create connection.\n' + ('\t{}\n'.format(msg) if msg else '')) def send_fail_load_preferences(prefs_file_path): diff --git a/grc/core/Param.py b/grc/core/Param.py index a9a664f74a..be86f0aecb 100644 --- a/grc/core/Param.py +++ b/grc/core/Param.py @@ -17,20 +17,19 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import + import ast -import weakref import re +import collections + +from six.moves import builtins, filter, map, range, zip from . import Constants -from .Constants import VECTOR_TYPES, COMPLEX_TYPES, REAL_TYPES, INT_TYPES -from .Element import Element -from .utils import odict +from .Element import Element, nop_write # Blacklist certain ids, its not complete, but should help -import __builtin__ - - -ID_BLACKLIST = ['self', 'options', 'gr', 'math', 'firdes'] + dir(__builtin__) +ID_BLACKLIST = ['self', 'options', 'gr', 'math', 'firdes'] + dir(builtins) try: from gnuradio import gr ID_BLACKLIST.extend(attr for attr in dir(gr.top_block()) if not attr.startswith('_')) @@ -41,86 +40,6 @@ _check_id_matcher = re.compile('^[a-z|A-Z]\w*$') _show_id_matcher = re.compile('^(variable\w*|parameter|options|notebook)$') -def _get_keys(lst): - return [elem.get_key() for elem in lst] - - -def _get_elem(lst, key): - try: - return lst[_get_keys(lst).index(key)] - except ValueError: - raise ValueError('Key "{}" not found in {}.'.format(key, _get_keys(lst))) - - -def num_to_str(num): - """ Display logic for numbers """ - def eng_notation(value, fmt='g'): - """Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n""" - template = '{:' + fmt + '}{}' - magnitude = abs(value) - for exp, symbol in zip(range(9, -15-1, -3), 'GMk munpf'): - factor = 10 ** exp - if magnitude >= factor: - return template.format(value / factor, symbol.strip()) - return template.format(value, '') - - if isinstance(num, COMPLEX_TYPES): - num = complex(num) # Cast to python complex - if num == 0: - return '0' - output = eng_notation(num.real) if num.real else '' - output += eng_notation(num.imag, '+g' if output else 'g') + 'j' if num.imag else '' - return output - else: - return str(num) - - -class Option(Element): - - def __init__(self, param, n): - Element.__init__(self, param) - self._name = n.find('name') - self._key = n.find('key') - self._opts = dict() - opts = n.findall('opt') - # Test against opts when non enum - if not self.get_parent().is_enum() and opts: - raise Exception('Options for non-enum types cannot have sub-options') - # Extract opts - for opt in opts: - # Separate the key:value - try: - key, value = opt.split(':') - except: - raise Exception('Error separating "{}" into key:value'.format(opt)) - # Test against repeated keys - if key in self._opts: - raise Exception('Key "{}" already exists in option'.format(key)) - # Store the option - self._opts[key] = value - - def __str__(self): - return 'Option {}({})'.format(self.get_name(), self.get_key()) - - def get_name(self): - return self._name - - def get_key(self): - return self._key - - ############################################## - # Access Opts - ############################################## - def get_opt_keys(self): - return self._opts.keys() - - def get_opt(self, key): - return self._opts[key] - - def get_opts(self): - return self._opts.values() - - class TemplateArg(object): """ A cheetah template argument created from a param. @@ -130,10 +49,12 @@ class TemplateArg(object): """ def __init__(self, param): - self._param = weakref.proxy(param) + self._param = param def __getitem__(self, item): - return str(self._param.get_opt(item)) if self._param.is_enum() else NotImplemented + param = self._param + opts = param.options_opts[param.get_value()] + return str(opts[item]) if param.is_enum() else NotImplemented def __str__(self): return str(self._param.to_code()) @@ -146,181 +67,66 @@ class Param(Element): is_param = True - def __init__(self, block, n): - """ - Make a new param from nested data. + def __init__(self, parent, key, name, type='raw', value='', **n): + """Make a new param from nested data""" + super(Param, self).__init__(parent) + self.key = key + self._name = name + self.value = self.default = value + self._type = type - Args: - block: the parent element - n: the nested odict - """ - # If the base key is a valid param key, copy its data and overlay this params data - base_key = n.find('base_key') - if base_key and base_key in block.get_param_keys(): - n_expanded = block.get_param(base_key)._n.copy() - n_expanded.update(n) - n = n_expanded - # Save odict in case this param will be base for another - self._n = n - # Parse the data - self._name = n.find('name') - self._key = n.find('key') - value = n.find('value') or '' - self._type = n.find('type') or 'raw' - self._hide = n.find('hide') or '' - self._tab_label = n.find('tab') or block.get_param_tab_labels()[0] - if self._tab_label not in block.get_param_tab_labels(): - block.get_param_tab_labels().append(self._tab_label) - # Build the param - Element.__init__(self, block) - # Create the Option objects from the n data - self._options = list() + self._hide = n.get('hide', '') + self.tab_label = n.get('tab', Constants.DEFAULT_PARAM_TAB) self._evaluated = None - for option in map(lambda o: Option(param=self, n=o), n.findall('option')): - key = option.get_key() - # Test against repeated keys - if key in self.get_option_keys(): - raise Exception('Key "{}" already exists in options'.format(key)) - # Store the option - self.get_options().append(option) - # Test the enum options - if self.is_enum(): - # Test against options with identical keys - if len(set(self.get_option_keys())) != len(self.get_options()): - raise Exception('Options keys "{}" are not unique.'.format(self.get_option_keys())) - # Test against inconsistent keys in options - opt_keys = self.get_options()[0].get_opt_keys() - for option in self.get_options(): - if set(opt_keys) != set(option.get_opt_keys()): - raise Exception('Opt keys "{}" are not identical across all options.'.format(opt_keys)) - # If a value is specified, it must be in the options keys - if value or value in self.get_option_keys(): - self._value = value - else: - self._value = self.get_option_keys()[0] - if self.get_value() not in self.get_option_keys(): - raise Exception('The value "{}" is not in the possible values of "{}".'.format(self.get_value(), self.get_option_keys())) - else: - self._value = value or '' - self._default = value + + self.options = [] + self.options_names = [] + self.options_opts = {} + self._init_options(options_n=n.get('option', [])) + self._init = False self._hostage_cells = list() self.template_arg = TemplateArg(self) - def get_types(self): - return ( - 'raw', 'enum', - 'complex', 'real', 'float', 'int', - 'complex_vector', 'real_vector', 'float_vector', 'int_vector', - 'hex', 'string', 'bool', - 'file_open', 'file_save', '_multiline', '_multiline_python_external', - 'id', 'stream_id', - 'gui_hint', - 'import', - ) - - def __repr__(self): - """ - Get the repr (nice string format) for this param. - - Returns: - the string representation - """ - ################################################## - # Truncate helper method - ################################################## - def _truncate(string, style=0): - max_len = max(27 - len(self.get_name()), 3) - if len(string) > max_len: - if style < 0: # Front truncate - string = '...' + string[3-max_len:] - elif style == 0: # Center truncate - string = string[:max_len/2 - 3] + '...' + string[-max_len/2:] - elif style > 0: # Rear truncate - string = string[:max_len-3] + '...' - return string - - ################################################## - # Simple conditions - ################################################## - if not self.is_valid(): - return _truncate(self.get_value()) - if self.get_value() in self.get_option_keys(): - return self.get_option(self.get_value()).get_name() - - ################################################## - # Split up formatting by type - ################################################## - # Default center truncate - truncate = 0 - e = self.get_evaluated() - t = self.get_type() - if isinstance(e, bool): - return str(e) - elif isinstance(e, COMPLEX_TYPES): - dt_str = num_to_str(e) - elif isinstance(e, VECTOR_TYPES): - # Vector types - if len(e) > 8: - # Large vectors use code - dt_str = self.get_value() - truncate = 1 - else: - # Small vectors use eval - dt_str = ', '.join(map(num_to_str, e)) - elif t in ('file_open', 'file_save'): - dt_str = self.get_value() - truncate = -1 - else: - # Other types - dt_str = str(e) - - # Done - return _truncate(dt_str, truncate) - - def __repr2__(self): - """ - Get the repr (nice string format) for this param. + def _init_options(self, options_n): + """Create the Option objects from the n data""" + option_keys = set() + for option_n in options_n: + key, name = option_n['key'], option_n['name'] + # Test against repeated keys + if key in option_keys: + raise KeyError('Key "{}" already exists in options'.format(key)) + option_keys.add(key) + # Store the option + self.options.append(key) + self.options_names.append(name) - Returns: - the string representation - """ if self.is_enum(): - return self.get_option(self.get_value()).get_name() - return self.get_value() - - def __str__(self): - return 'Param - {}({})'.format(self.get_name(), self.get_key()) + self._init_enum(options_n) - def get_color(self): - """ - Get the color that represents this param's type. + def _init_enum(self, options_n): + opt_ref = None + for option_n in options_n: + key, opts_raw = option_n['key'], option_n.get('opt', []) + try: + self.options_opts[key] = opts = dict(opt.split(':') for opt in opts_raw) + except TypeError: + raise ValueError('Error separating opts into key:value') + + if opt_ref is None: + opt_ref = set(opts.keys()) + elif opt_ref != set(opts): + raise ValueError('Opt keys ({}) are not identical across all options.' + ''.format(', '.join(opt_ref))) + if not self.value: + self.value = self.default = self.options[0] + elif self.value not in self.options: + self.value = self.default = self.options[0] # TODO: warn + # raise ValueError('The value {!r} is not in the possible values of {}.' + # ''.format(self.get_value(), ', '.join(self.options))) - Returns: - a hex color code. - """ - try: - return { - # Number types - 'complex': Constants.COMPLEX_COLOR_SPEC, - 'real': Constants.FLOAT_COLOR_SPEC, - 'float': Constants.FLOAT_COLOR_SPEC, - 'int': Constants.INT_COLOR_SPEC, - # Vector types - 'complex_vector': Constants.COMPLEX_VECTOR_COLOR_SPEC, - 'real_vector': Constants.FLOAT_VECTOR_COLOR_SPEC, - 'float_vector': Constants.FLOAT_VECTOR_COLOR_SPEC, - 'int_vector': Constants.INT_VECTOR_COLOR_SPEC, - # Special - 'bool': Constants.INT_COLOR_SPEC, - 'hex': Constants.INT_COLOR_SPEC, - 'string': Constants.BYTE_VECTOR_COLOR_SPEC, - 'id': Constants.ID_COLOR_SPEC, - 'stream_id': Constants.ID_COLOR_SPEC, - 'raw': Constants.WILDCARD_COLOR_SPEC, - }[self.get_type()] - except: - return '#FFFFFF' + def __str__(self): + return 'Param - {}({})'.format(self.name, self.key) def get_hide(self): """ @@ -333,20 +139,17 @@ class Param(Element): Returns: hide the hide property string """ - hide = self.get_parent().resolve_dependencies(self._hide).strip() + hide = self.parent.resolve_dependencies(self._hide).strip() if hide: return hide # Hide ID in non variable blocks - if self.get_key() == 'id' and not _show_id_matcher.match(self.get_parent().get_key()): + if self.key == 'id' and not _show_id_matcher.match(self.parent.key): return 'part' # Hide port controllers for type and nports - if self.get_key() in ' '.join(map(lambda p: ' '.join([p._type, p._nports]), - self.get_parent().get_ports())): + if self.key in ' '.join([' '.join([p._type, p._nports]) for p in self.parent.get_ports()]): return 'part' # Hide port controllers for vlen, when == 1 - if self.get_key() in ' '.join(map( - lambda p: p._vlen, self.get_parent().get_ports()) - ): + if self.key in ' '.join(p._vlen for p in self.parent.get_ports()): try: if int(self.get_evaluated()) == 1: return 'part' @@ -360,13 +163,13 @@ class Param(Element): The value must be evaluated and type must a possible type. """ Element.validate(self) - if self.get_type() not in self.get_types(): + if self.get_type() not in Constants.PARAM_TYPE_NAMES: self.add_error_message('Type "{}" is not a possible type.'.format(self.get_type())) self._evaluated = None try: self._evaluated = self.evaluate() - except Exception, e: + except Exception as e: self.add_error_message(str(e)) def get_evaluated(self): @@ -398,22 +201,22 @@ class Param(Element): elif t in ('raw', 'complex', 'real', 'float', 'int', 'hex', 'bool'): # Raise exception if python cannot evaluate this value try: - e = self.get_parent().get_parent().evaluate(v) - except Exception, e: + e = self.parent_flowgraph.evaluate(v) + except Exception as e: raise Exception('Value "{}" cannot be evaluated:\n{}'.format(v, e)) # Raise an exception if the data is invalid if t == 'raw': return e elif t == 'complex': - if not isinstance(e, COMPLEX_TYPES): + if not isinstance(e, Constants.COMPLEX_TYPES): raise Exception('Expression "{}" is invalid for type complex.'.format(str(e))) return e elif t == 'real' or t == 'float': - if not isinstance(e, REAL_TYPES): + if not isinstance(e, Constants.REAL_TYPES): raise Exception('Expression "{}" is invalid for type float.'.format(str(e))) return e elif t == 'int': - if not isinstance(e, INT_TYPES): + if not isinstance(e, Constants.INT_TYPES): raise Exception('Expression "{}" is invalid for type integer.'.format(str(e))) return e elif t == 'hex': @@ -433,29 +236,29 @@ class Param(Element): v = '()' # Raise exception if python cannot evaluate this value try: - e = self.get_parent().get_parent().evaluate(v) - except Exception, e: + e = self.parent.parent.evaluate(v) + except Exception as e: raise Exception('Value "{}" cannot be evaluated:\n{}'.format(v, e)) # Raise an exception if the data is invalid if t == 'complex_vector': - if not isinstance(e, VECTOR_TYPES): + if not isinstance(e, Constants.VECTOR_TYPES): self._lisitify_flag = True e = [e] - if not all([isinstance(ei, COMPLEX_TYPES) for ei in e]): + if not all([isinstance(ei, Constants.COMPLEX_TYPES) for ei in e]): raise Exception('Expression "{}" is invalid for type complex vector.'.format(str(e))) return e elif t == 'real_vector' or t == 'float_vector': - if not isinstance(e, VECTOR_TYPES): + if not isinstance(e, Constants.VECTOR_TYPES): self._lisitify_flag = True e = [e] - if not all([isinstance(ei, REAL_TYPES) for ei in e]): + if not all([isinstance(ei, Constants.REAL_TYPES) for ei in e]): raise Exception('Expression "{}" is invalid for type float vector.'.format(str(e))) return e elif t == 'int_vector': - if not isinstance(e, VECTOR_TYPES): + if not isinstance(e, Constants.VECTOR_TYPES): self._lisitify_flag = True e = [e] - if not all([isinstance(ei, INT_TYPES) for ei in e]): + if not all([isinstance(ei, Constants.INT_TYPES) for ei in e]): raise Exception('Expression "{}" is invalid for type integer vector.'.format(str(e))) return e ######################### @@ -464,7 +267,7 @@ class Param(Element): elif t in ('string', 'file_open', 'file_save', '_multiline', '_multiline_python_external'): # Do not check if file/directory exists, that is a runtime issue try: - e = self.get_parent().get_parent().evaluate(v) + e = self.parent.parent.evaluate(v) if not isinstance(e, str): raise Exception() except: @@ -485,7 +288,7 @@ class Param(Element): if v in ID_BLACKLIST: raise Exception('ID "{}" is blacklisted.'.format(v)) - if self._key == 'id': + if self.key == 'id': # Id should only appear once, or zero times if block is disabled if ids.count(v) > 1: raise Exception('ID "{}" is not unique.'.format(v)) @@ -502,16 +305,16 @@ class Param(Element): elif t == 'stream_id': # Get a list of all stream ids used in the virtual sinks ids = [param.get_value() for param in filter( - lambda p: p.get_parent().is_virtual_sink(), + lambda p: p.parent.is_virtual_sink(), self.get_all_params(t), )] # Check that the virtual sink's stream id is unique - if self.get_parent().is_virtual_sink(): + if self.parent.is_virtual_sink(): # Id should only appear once, or zero times if block is disabled if ids.count(v) > 1: raise Exception('Stream ID "{}" is not unique.'.format(v)) # Check that the virtual source's steam id is found - if self.get_parent().is_virtual_source(): + if self.parent.is_virtual_source(): if v not in ids: raise Exception('Stream ID "{}" is not found.'.format(v)) return v @@ -559,12 +362,12 @@ class Param(Element): # New namespace n = dict() try: - exec v in n + exec(v, n) except ImportError: raise Exception('Import "{}" failed.'.format(v)) except Exception: raise Exception('Bad import syntax: "{}".'.format(v)) - return filter(lambda k: str(k) != '__builtins__', n.keys()) + return [k for k in list(n.keys()) if str(k) != '__builtins__'] ######################### else: @@ -610,62 +413,46 @@ class Param(Element): Returns: a list of params """ - return sum([filter(lambda p: ((p.get_type() == type) and ((key is None) or (p.get_key() == key))), block.get_params()) for block in self.get_parent().get_parent().get_enabled_blocks()], []) + params = [] + for block in self.parent_flowgraph.get_enabled_blocks(): + params.extend(p for k, p in block.params.items() if p.get_type() == type and (key is None or key == k)) + return params def is_enum(self): return self._type == 'enum' def get_value(self): - value = self._value - if self.is_enum() and value not in self.get_option_keys(): - value = self.get_option_keys()[0] + value = self.value + if self.is_enum() and value not in self.options: + value = self.options[0] self.set_value(value) return value def set_value(self, value): # Must be a string - self._value = str(value) + self.value = str(value) def set_default(self, value): - if self._default == self._value: + if self.default == self.value: self.set_value(value) - self._default = str(value) + self.default = str(value) def get_type(self): - return self.get_parent().resolve_dependencies(self._type) + return self.parent.resolve_dependencies(self._type) def get_tab_label(self): - return self._tab_label - - def get_name(self): - return self.get_parent().resolve_dependencies(self._name).strip() + return self.tab_label - def get_key(self): - return self._key + @nop_write + @property + def name(self): + return self.parent.resolve_dependencies(self._name).strip() ############################################## # Access Options ############################################## - def get_option_keys(self): - return _get_keys(self.get_options()) - - def get_option(self, key): - return _get_elem(self.get_options(), key) - - def get_options(self): - return self._options - - ############################################## - # Access Opts - ############################################## - def get_opt_keys(self): - return self.get_option(self.get_value()).get_opt_keys() - - def get_opt(self, key): - return self.get_option(self.get_value()).get_opt(key) - - def get_opts(self): - return self.get_option(self.get_value()).get_opts() + def opt_value(self, key): + return self.options_opts[self.get_value()][key] ############################################## # Import/Export Methods @@ -677,7 +464,7 @@ class Param(Element): Returns: a nested data odict """ - n = odict() - n['key'] = self.get_key() + n = collections.OrderedDict() + n['key'] = self.key n['value'] = self.get_value() return n diff --git a/grc/core/ParseXML.py b/grc/core/ParseXML.py index c9f6541ee7..430ba5b474 100644 --- a/grc/core/ParseXML.py +++ b/grc/core/ParseXML.py @@ -17,9 +17,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import + from lxml import etree -from .utils import odict +import six +from six.moves import map + xml_failures = {} etree.set_default_parser(etree.XMLParser(remove_comments=True)) @@ -75,17 +79,35 @@ def from_file(xml_file): the nested data with grc version information """ xml = etree.parse(xml_file) - nested_data = _from_file(xml.getroot()) + + tag, nested_data = _from_file(xml.getroot()) + nested_data = {tag: nested_data, '_instructions': {}} # Get the embedded instructions and build a dictionary item - nested_data['_instructions'] = {} xml_instructions = xml.xpath('/processing-instruction()') - for inst in filter(lambda i: i.target == 'grc', xml_instructions): - nested_data['_instructions'] = odict(inst.attrib) + for inst in xml_instructions: + if inst.target != 'grc': + continue + nested_data['_instructions'] = dict(inst.attrib) return nested_data -def _from_file(xml): +WANT_A_LIST = { + '/block': 'import callback param check sink source'.split(), + '/block/param_tab_order': 'tab'.split(), + '/block/param': 'option'.split(), + '/block/param/option': 'opt'.split(), + '/flow_graph': 'block connection'.split(), + '/flow_graph/block': 'param'.split(), + '/cat': 'cat block'.split(), + '/cat/cat': 'cat block'.split(), + '/cat/cat/cat': 'cat block'.split(), + '/cat/cat/cat/cat': 'cat block'.split(), + '/domain': 'connection'.split(), +} + + +def _from_file(xml, parent_tag=''): """ Recursively parse the xml tree into nested data format. @@ -96,21 +118,24 @@ def _from_file(xml): the nested data """ tag = xml.tag + tag_path = parent_tag + '/' + tag + if not len(xml): - return odict({tag: xml.text or ''}) # store empty tags (text is None) as empty string - nested_data = odict() + return tag, xml.text or '' # store empty tags (text is None) as empty string + + nested_data = {} for elem in xml: - key, value = _from_file(elem).items()[0] - if key in nested_data: - nested_data[key].append(value) + key, value = _from_file(elem, tag_path) + + if key in WANT_A_LIST.get(tag_path, []): + try: + nested_data[key].append(value) + except KeyError: + nested_data[key] = [value] else: - nested_data[key] = [value] - # Delistify if the length of values is 1 - for key, values in nested_data.iteritems(): - if len(values) == 1: - nested_data[key] = values[0] + nested_data[key] = value - return odict({tag: nested_data}) + return tag, nested_data def to_file(nested_data, xml_file): @@ -127,11 +152,11 @@ def to_file(nested_data, xml_file): if instructions: xml_data += etree.tostring(etree.ProcessingInstruction( 'grc', ' '.join( - "{0}='{1}'".format(*item) for item in instructions.iteritems()) + "{0}='{1}'".format(*item) for item in six.iteritems(instructions)) ), xml_declaration=True, pretty_print=True, encoding='utf-8') xml_data += etree.tostring(_to_file(nested_data)[0], pretty_print=True, encoding='utf-8') - with open(xml_file, 'w') as fp: + with open(xml_file, 'wb') as fp: fp.write(xml_data) @@ -146,14 +171,14 @@ def _to_file(nested_data): the xml tree filled with child nodes """ nodes = list() - for key, values in nested_data.iteritems(): + for key, values in six.iteritems(nested_data): # Listify the values if not a list if not isinstance(values, (list, set, tuple)): values = [values] for value in values: node = etree.Element(key) - if isinstance(value, (str, unicode)): - node.text = unicode(value) + if isinstance(value, (str, six.text_type)): + node.text = six.text_type(value) else: node.extend(_to_file(value)) nodes.append(node) diff --git a/grc/core/Platform.py b/grc/core/Platform.py index b73dade2e8..73937f1299 100644 --- a/grc/core/Platform.py +++ b/grc/core/Platform.py @@ -17,9 +17,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import, print_function + import os import sys +import six +from six.moves import range + from . import ParseXML, Messages, Constants from .Config import Config @@ -27,31 +32,22 @@ from .Element import Element from .generator import Generator from .FlowGraph import FlowGraph from .Connection import Connection -from .Block import Block -from .Port import Port +from . import Block +from .Port import Port, PortClone from .Param import Param -from .utils import odict, extract_docs +from .utils import extract_docs class Platform(Element): - Config = Config - Generator = Generator - FlowGraph = FlowGraph - Connection = Connection - Block = Block - Port = Port - Param = Param - is_platform = True def __init__(self, *args, **kwargs): """ Make a platform for GNU Radio """ - Element.__init__(self) + Element.__init__(self, parent=None) self.config = self.Config(*args, **kwargs) - self.block_docstrings = {} self.block_docstrings_loaded_callback = lambda: None # dummy to be replaced by BlockTreeWindow @@ -60,22 +56,23 @@ class Platform(Element): callback_finished=lambda: self.block_docstrings_loaded_callback() ) - # Create a dummy flow graph for the blocks - self._flow_graph = Element(self) - self._flow_graph.connections = [] - - self.blocks = odict() - self._blocks_n = odict() + self.blocks = {} + self._blocks_n = {} self._block_categories = {} self.domains = {} self.connection_templates = {} self._auto_hier_block_generate_chain = set() + # Create a dummy flow graph for the blocks + self._flow_graph = Element.__new__(FlowGraph) + Element.__init__(self._flow_graph, self) + self._flow_graph.connections = [] + self.build_block_library() def __str__(self): - return 'Platform - {}({})'.format(self.config.key, self.config.name) + return 'Platform - {}'.format(self.config.name) @staticmethod def find_file_in_paths(filename, paths, cwd): @@ -128,12 +125,13 @@ class Platform(Element): return None, None if flow_graph.get_option('generate_options').startswith('hb'): - self.load_block_xml(generator.get_file_path_xml()) + self.load_block_xml(generator.file_path_xml) return flow_graph, generator.file_path def build_block_library(self): """load the blocks and block tree from the search paths""" self._docstring_extractor.start() + # Reset self.blocks.clear() self._blocks_n.clear() @@ -155,10 +153,11 @@ class Platform(Element): # print >> sys.stderr, 'Warning: Block validation failed:\n\t%s\n\tIgnoring: %s' % (e, xml_file) pass except Exception as e: - print >> sys.stderr, 'Warning: XML parsing failed:\n\t%r\n\tIgnoring: %s' % (e, xml_file) + raise + print('Warning: XML parsing failed:\n\t%r\n\tIgnoring: %s' % (e, xml_file), file=sys.stderr) # Add blocks to block tree - for key, block in self.blocks.iteritems(): + for key, block in six.iteritems(self.blocks): category = self._block_categories.get(key, block.category) # Blocks with empty categories are hidden if not category: @@ -180,26 +179,27 @@ class Platform(Element): yield block_path elif os.path.isdir(block_path): for dirpath, dirnames, filenames in os.walk(block_path): - for filename in sorted(filter(lambda f: f.endswith('.xml'), filenames)): + for filename in sorted(f for f in filenames if f.endswith('.xml')): yield os.path.join(dirpath, filename) def load_block_xml(self, xml_file): """Load block description from xml file""" # Validate and import ParseXML.validate_dtd(xml_file, Constants.BLOCK_DTD) - n = ParseXML.from_file(xml_file).find('block') + n = ParseXML.from_file(xml_file).get('block', {}) n['block_wrapper_path'] = xml_file # inject block wrapper path - # Get block instance and add it to the list of blocks - block = self.Block(self._flow_graph, n) - key = block.get_key() + key = n.pop('key') + if key in self.blocks: - print >> sys.stderr, 'Warning: Block with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file) - else: # Store the block - self.blocks[key] = block - self._blocks_n[key] = n + print('Warning: Block with key "{}" already exists.\n' + '\tIgnoring: {}'.format(key, xml_file), file=sys.stderr) + return + # Store the block + self.blocks[key] = block = self.get_new_block(self._flow_graph, key, **n) + self._blocks_n[key] = n self._docstring_extractor.query( - block.get_key(), + key, block.get_imports(raw=True), block.get_make(raw=True) ) @@ -211,62 +211,62 @@ class Platform(Element): path = [] def load_category(cat_n): - path.append(cat_n.find('name').strip()) - for block_key in cat_n.findall('block'): + path.append(cat_n.get('name').strip()) + for block_key in cat_n.get('block', []): if block_key not in self._block_categories: self._block_categories[block_key] = list(path) - for sub_cat_n in cat_n.findall('cat'): + for sub_cat_n in cat_n.get('cat', []): load_category(sub_cat_n) path.pop() - load_category(xml.find('cat')) + load_category(xml.get('cat', {})) def load_domain_xml(self, xml_file): """Load a domain properties and connection templates from XML""" ParseXML.validate_dtd(xml_file, Constants.DOMAIN_DTD) - n = ParseXML.from_file(xml_file).find('domain') + n = ParseXML.from_file(xml_file).get('domain') - key = n.find('key') + key = n.get('key') if not key: - print >> sys.stderr, 'Warning: Domain with emtpy key.\n\tIgnoring: {}'.format(xml_file) + print('Warning: Domain with emtpy key.\n\tIgnoring: {}'.format(xml_file), file=sys.stderr) return if key in self.domains: # test against repeated keys - print >> sys.stderr, 'Warning: Domain with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file) + print('Warning: Domain with key "{}" already exists.\n\tIgnoring: {}'.format(key, xml_file), file=sys.stderr) return - #to_bool = lambda s, d: d if s is None else s.lower() not in ('false', 'off', '0', '') + # to_bool = lambda s, d: d if s is None else s.lower() not in ('false', 'off', '0', '') def to_bool(s, d): if s is not None: return s.lower() not in ('false', 'off', '0', '') return d - color = n.find('color') or '' + color = n.get('color') or '' try: - import gtk # ugly but handy - gtk.gdk.color_parse(color) - except (ValueError, ImportError): + chars_per_color = 2 if len(color) > 4 else 1 + tuple(int(color[o:o + 2], 16) / 255.0 for o in range(1, 3 * chars_per_color, chars_per_color)) + except ValueError: if color: # no color is okay, default set in GUI - print >> sys.stderr, 'Warning: Can\'t parse color code "{}" for domain "{}" '.format(color, key) + print('Warning: Can\'t parse color code "{}" for domain "{}" '.format(color, key), file=sys.stderr) color = None self.domains[key] = dict( - name=n.find('name') or key, - multiple_sinks=to_bool(n.find('multiple_sinks'), True), - multiple_sources=to_bool(n.find('multiple_sources'), False), + name=n.get('name') or key, + multiple_sinks=to_bool(n.get('multiple_sinks'), True), + multiple_sources=to_bool(n.get('multiple_sources'), False), color=color ) - for connection_n in n.findall('connection'): - key = (connection_n.find('source_domain'), connection_n.find('sink_domain')) + for connection_n in n.get('connection', []): + key = (connection_n.get('source_domain'), connection_n.get('sink_domain')) if not all(key): - print >> sys.stderr, 'Warning: Empty domain key(s) in connection template.\n\t{}'.format(xml_file) + print('Warning: Empty domain key(s) in connection template.\n\t{}'.format(xml_file), file=sys.stderr) elif key in self.connection_templates: - print >> sys.stderr, 'Warning: Connection template "{}" already exists.\n\t{}'.format(key, xml_file) + print('Warning: Connection template "{}" already exists.\n\t{}'.format(key, xml_file), file=sys.stderr) else: - self.connection_templates[key] = connection_n.find('make') or '' + self.connection_templates[key] = connection_n.get('make') or '' def _save_docstring_extraction_result(self, key, docstrings): docs = {} - for match, docstring in docstrings.iteritems(): + for match, docstring in six.iteritems(docstrings): if not docstring or match.endswith('_sptr'): continue docstring = docstring.replace('\n\n', '\n').strip() @@ -294,14 +294,48 @@ class Platform(Element): ParseXML.validate_dtd(flow_graph_file, Constants.FLOW_GRAPH_DTD) return ParseXML.from_file(flow_graph_file) + def get_blocks(self): + return list(self.blocks.values()) + + def get_generate_options(self): + gen_opts = self.blocks['options'].get_param('generate_options') + generate_mode_default = gen_opts.get_value() + return [(key, name, key == generate_mode_default) + for key, name in zip(gen_opts.options, gen_opts.options_names)] + + ############################################## + # Factories + ############################################## + Config = Config + Generator = Generator + FlowGraph = FlowGraph + Connection = Connection + block_classes = { + None: Block.Block, # default + 'epy_block': Block.EPyBlock, + '_dummy': Block.DummyBlock, + } + port_classes = { + None: Port, # default + 'clone': PortClone, # default + } + param_classes = { + None: Param, # default + } + def get_new_flow_graph(self): - return self.FlowGraph(platform=self) + return self.FlowGraph(parent=self) - def get_blocks(self): - return self.blocks.values() + def get_new_block(self, parent, key, **kwargs): + cls = self.block_classes.get(key, self.block_classes[None]) + if not kwargs: + kwargs = self._blocks_n[key] + return cls(parent, key=key, **kwargs) - def get_new_block(self, flow_graph, key): - return self.Block(flow_graph, n=self._blocks_n[key]) + def get_new_param(self, parent, **kwargs): + cls = self.param_classes[kwargs.pop('cls_key', None)] + return cls(parent, **kwargs) - def get_colors(self): - return [(name, color) for name, key, sizeof, color in Constants.CORE_TYPES] + def get_new_port(self, parent, **kwargs): + cls = self.port_classes[kwargs.pop('cls_key', None)] + return cls(parent, **kwargs) diff --git a/grc/core/Port.py b/grc/core/Port.py index 8549656c9b..9ca443efa1 100644 --- a/grc/core/Port.py +++ b/grc/core/Port.py @@ -17,11 +17,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import + from itertools import chain -from .Constants import DEFAULT_DOMAIN, GR_STREAM_DOMAIN, GR_MESSAGE_DOMAIN -from .Element import Element +from six.moves import filter +from .Element import Element, lazy_property from . import Constants @@ -43,7 +45,7 @@ def _sources_from_virtual_sink_port(sink_port, _traversed=None): """ source_ports_per_virtual_connection = ( # there can be multiple ports per virtual connection - _sources_from_virtual_source_port(c.get_source(), _traversed) # type: list + _sources_from_virtual_source_port(c.source_port, _traversed) # type: list for c in sink_port.get_enabled_connections() ) return list(chain(*source_ports_per_virtual_connection)) # concatenate generated lists of ports @@ -59,8 +61,8 @@ def _sources_from_virtual_source_port(source_port, _traversed=None): raise LoopError('Loop found when resolving port type') _traversed.add(source_port) - block = source_port.get_parent() - flow_graph = block.get_parent() + block = source_port.parent_block + flow_graph = source_port.parent_flow_graph if not block.is_virtual_source(): return [source_port] # nothing to resolve, we're done @@ -70,11 +72,11 @@ def _sources_from_virtual_source_port(source_port, _traversed=None): # currently the validation does not allow multiple virtual sinks and one virtual source # but in the future it may... connected_virtual_sink_blocks = ( - b for b in flow_graph.get_enabled_blocks() + b for b in flow_graph.iter_enabled_blocks() if b.is_virtual_sink() and b.get_param('stream_id').get_value() == stream_id ) source_ports_per_virtual_connection = ( - _sources_from_virtual_sink_port(b.get_sinks()[0], _traversed) # type: list + _sources_from_virtual_sink_port(b.sinks[0], _traversed) # type: list for b in connected_virtual_sink_blocks ) return list(chain(*source_ports_per_virtual_connection)) # concatenate generated lists of ports @@ -94,7 +96,7 @@ def _sinks_from_virtual_source_port(source_port, _traversed=None): """ sink_ports_per_virtual_connection = ( # there can be multiple ports per virtual connection - _sinks_from_virtual_sink_port(c.get_sink(), _traversed) # type: list + _sinks_from_virtual_sink_port(c.sink_port, _traversed) # type: list for c in source_port.get_enabled_connections() ) return list(chain(*sink_ports_per_virtual_connection)) # concatenate generated lists of ports @@ -110,8 +112,8 @@ def _sinks_from_virtual_sink_port(sink_port, _traversed=None): raise LoopError('Loop found when resolving port type') _traversed.add(sink_port) - block = sink_port.get_parent() - flow_graph = block.get_parent() + block = sink_port.parent_block + flow_graph = sink_port.parent_flow_graph if not block.is_virtual_sink(): return [sink_port] @@ -119,11 +121,11 @@ def _sinks_from_virtual_sink_port(sink_port, _traversed=None): stream_id = block.get_param('stream_id').get_value() connected_virtual_source_blocks = ( - b for b in flow_graph.get_enabled_blocks() + b for b in flow_graph.iter_enabled_blocks() if b.is_virtual_source() and b.get_param('stream_id').get_value() == stream_id ) sink_ports_per_virtual_connection = ( - _sinks_from_virtual_source_port(b.get_sources()[0], _traversed) # type: list + _sinks_from_virtual_source_port(b.sources[0], _traversed) # type: list for b in connected_virtual_source_blocks ) return list(chain(*sink_ports_per_virtual_connection)) # concatenate generated lists of ports @@ -132,8 +134,9 @@ def _sinks_from_virtual_sink_port(sink_port, _traversed=None): class Port(Element): is_port = True + is_clone = False - def __init__(self, block, n, dir): + def __init__(self, parent, direction, **n): """ Make a new port from nested data. @@ -144,50 +147,44 @@ class Port(Element): """ self._n = n if n['type'] == 'message': - n['domain'] = GR_MESSAGE_DOMAIN + n['domain'] = Constants.GR_MESSAGE_DOMAIN + if 'domain' not in n: - n['domain'] = DEFAULT_DOMAIN - elif n['domain'] == GR_MESSAGE_DOMAIN: + n['domain'] = Constants.DEFAULT_DOMAIN + elif n['domain'] == Constants.GR_MESSAGE_DOMAIN: n['key'] = n['name'] n['type'] = 'message' # For port color - if not n.find('key'): - n['key'] = str(next(block.port_counters[dir == 'source'])) # Build the port - Element.__init__(self, block) + Element.__init__(self, parent) # Grab the data - self._name = n['name'] - self._key = n['key'] - self._type = n['type'] or '' - self._domain = n['domain'] - self._hide = n.find('hide') or '' - self._dir = dir + self.name = n['name'] + self.key = n['key'] + self.domain = n.get('domain') + self._type = n.get('type', '') + self.inherit_type = not self._type + self._hide = n.get('hide', '') + self._dir = direction self._hide_evaluated = False # Updated on rewrite() - self._nports = n.find('nports') or '' - self._vlen = n.find('vlen') or '' - self._optional = n.find('optional') or '' + self._nports = n.get('nports', '') + self._vlen = n.get('vlen', '') + self._optional = bool(n.get('optional')) self._optional_evaluated = False # Updated on rewrite() - self._clones = [] # References to cloned ports (for nports > 1) + self.clones = [] # References to cloned ports (for nports > 1) def __str__(self): if self.is_source: - return 'Source - {}({})'.format(self.get_name(), self.get_key()) + return 'Source - {}({})'.format(self.name, self.key) if self.is_sink: - return 'Sink - {}({})'.format(self.get_name(), self.get_key()) - - def get_types(self): - return Constants.TYPE_TO_SIZEOF.keys() - - def is_type_empty(self): - return not self._n['type'] or not self.get_parent().resolve_dependencies(self._n['type']) + return 'Sink - {}({})'.format(self.name, self.key) def validate(self): - if self.get_type() not in self.get_types(): + Element.validate(self) + if self.get_type() not in Constants.TYPE_TO_SIZEOF.keys(): self.add_error_message('Type "{}" is not a possible type.'.format(self.get_type())) - platform = self.get_parent().get_parent().get_parent() - if self.get_domain() not in platform.domains: - self.add_error_message('Domain key "{}" is not registered.'.format(self.get_domain())) + if self.domain not in self.parent_platform.domains: + self.add_error_message('Domain key "{}" is not registered.'.format(self.domain)) if not self.get_enabled_connections() and not self.get_optional(): self.add_error_message('Port is not connected.') @@ -196,22 +193,22 @@ class Port(Element): Handle the port cloning for virtual blocks. """ del self._error_messages[:] - if self.is_type_empty(): + if self.inherit_type: self.resolve_empty_type() - hide = self.get_parent().resolve_dependencies(self._hide).strip().lower() + hide = self.parent_block.resolve_dependencies(self._hide).strip().lower() self._hide_evaluated = False if hide in ('false', 'off', '0') else bool(hide) - optional = self.get_parent().resolve_dependencies(self._optional).strip().lower() + optional = self.parent_block.resolve_dependencies(self._optional).strip().lower() self._optional_evaluated = False if optional in ('false', 'off', '0') else bool(optional) # Update domain if was deduced from (dynamic) port type type_ = self.get_type() - if self._domain == GR_STREAM_DOMAIN and type_ == "message": - self._domain = GR_MESSAGE_DOMAIN - self._key = self._name - if self._domain == GR_MESSAGE_DOMAIN and type_ != "message": - self._domain = GR_STREAM_DOMAIN - self._key = '0' # Is rectified in rewrite() + if self.domain == Constants.GR_STREAM_DOMAIN and type_ == "message": + self.domain = Constants.GR_MESSAGE_DOMAIN + self.key = self.name + if self.domain == Constants.GR_MESSAGE_DOMAIN and type_ != "message": + self.domain = Constants.GR_STREAM_DOMAIN + self.key = '0' # Is rectified in rewrite() def resolve_virtual_source(self): """Only used by Generator after validation is passed""" @@ -220,7 +217,7 @@ class Port(Element): def resolve_empty_type(self): def find_port(finder): try: - return next((p for p in finder(self) if not p.is_type_empty()), None) + return next((p for p in finder(self) if not p.inherit_type), None) except LoopError as error: self.add_error_message(str(error)) except (StopIteration, Exception) as error: @@ -242,9 +239,9 @@ class Port(Element): Returns: the vector length or 1 """ - vlen = self.get_parent().resolve_dependencies(self._vlen) + vlen = self.parent_block.resolve_dependencies(self._vlen) try: - return int(self.get_parent().get_parent().evaluate(vlen)) + return max(1, int(self.parent_flowgraph.evaluate(vlen))) except: return 1 @@ -258,52 +255,17 @@ class Port(Element): the number of ports or 1 """ if self._nports == '': - return '' + return 1 - nports = self.get_parent().resolve_dependencies(self._nports) + nports = self.parent_block.resolve_dependencies(self._nports) try: - return max(1, int(self.get_parent().get_parent().evaluate(nports))) + return max(1, int(self.parent_flowgraph.evaluate(nports))) except: return 1 def get_optional(self): return self._optional_evaluated - def get_color(self): - """ - Get the color that represents this port's type. - Codes differ for ports where the vec length is 1 or greater than 1. - - Returns: - a hex color code. - """ - try: - color = Constants.TYPE_TO_COLOR[self.get_type()] - vlen = self.get_vlen() - if vlen == 1: - return color - color_val = int(color[1:], 16) - r = (color_val >> 16) & 0xff - g = (color_val >> 8) & 0xff - b = (color_val >> 0) & 0xff - dark = (0, 0, 30, 50, 70)[min(4, vlen)] - r = max(r-dark, 0) - g = max(g-dark, 0) - b = max(b-dark, 0) - # TODO: Change this to .format() - return '#%.2x%.2x%.2x' % (r, g, b) - except: - return '#FFFFFF' - - def get_clones(self): - """ - Get the clones of this master port (nports > 1) - - Returns: - a list of ports - """ - return self._clones - def add_clone(self): """ Create a clone of this (master) port and store a reference in self._clones. @@ -315,24 +277,23 @@ class Port(Element): the cloned port """ # Add index to master port name if there are no clones yet - if not self._clones: - self._name = self._n['name'] + '0' + if not self.clones: + self.name = self._n['name'] + '0' # Also update key for none stream ports - if not self._key.isdigit(): - self._key = self._name - - # Prepare a copy of the odict for the clone - n = self._n.copy() - # Remove nports from the key so the copy cannot be a duplicator - if 'nports' in n: - n.pop('nports') - n['name'] = self._n['name'] + str(len(self._clones) + 1) + if not self.key.isdigit(): + self.key = self.name + + name = self._n['name'] + str(len(self.clones) + 1) # Dummy value 99999 will be fixed later - n['key'] = '99999' if self._key.isdigit() else n['name'] + key = '99999' if self.key.isdigit() else name # Clone - port = self.__class__(self.get_parent(), n, self._dir) - self._clones.append(port) + port_factory = self.parent_platform.get_new_port + port = port_factory(self.parent, direction=self._dir, + name=name, key=key, + master=self, cls_key='clone') + + self.clones.append(port) return port def remove_clone(self, port): @@ -340,37 +301,24 @@ class Port(Element): Remove a cloned port (from the list of clones only) Remove the index 0 of the master port name (and key9 if there are no more clones left """ - self._clones.remove(port) + self.clones.remove(port) # Remove index from master port name if there are no more clones - if not self._clones: - self._name = self._n['name'] + if not self.clones: + self.name = self._n['name'] # Also update key for none stream ports - if not self._key.isdigit(): - self._key = self._name - - def get_name(self): - number = '' - if self.get_type() == 'bus': - busses = filter(lambda a: a._dir == self._dir, self.get_parent().get_ports_gui()) - number = str(busses.index(self)) + '#' + str(len(self.get_associated_ports())) - return self._name + number - - def get_key(self): - return self._key + if not self.key.isdigit(): + self.key = self.name - @property + @lazy_property def is_sink(self): return self._dir == 'sink' - @property + @lazy_property def is_source(self): return self._dir == 'source' def get_type(self): - return self.get_parent().resolve_dependencies(self._type) - - def get_domain(self): - return self._domain + return self.parent_block.resolve_dependencies(self._type) def get_hide(self): return self._hide_evaluated @@ -382,8 +330,8 @@ class Port(Element): Returns: a list of connection objects """ - connections = self.get_parent().get_parent().connections - connections = filter(lambda c: c.get_source() is self or c.get_sink() is self, connections) + connections = self.parent_flowgraph.connections + connections = [c for c in connections if c.source_port is self or c.sink_port is self] return connections def get_enabled_connections(self): @@ -393,22 +341,51 @@ class Port(Element): Returns: a list of connection objects """ - return filter(lambda c: c.get_enabled(), self.get_connections()) + return [c for c in self.get_connections() if c.enabled] def get_associated_ports(self): if not self.get_type() == 'bus': return [self] + + block = self.parent_block + if self.is_source: + block_ports = block.sources + bus_structure = block.current_bus_structure['source'] else: - if self.is_source: - get_ports = self.get_parent().get_sources - bus_structure = self.get_parent().current_bus_structure['source'] - else: - get_ports = self.get_parent().get_sinks - bus_structure = self.get_parent().current_bus_structure['sink'] - - ports = [i for i in get_ports() if not i.get_type() == 'bus'] - if bus_structure: - busses = [i for i in get_ports() if i.get_type() == 'bus'] - bus_index = busses.index(self) - ports = filter(lambda a: ports.index(a) in bus_structure[bus_index], ports) - return ports + block_ports = block.sinks + bus_structure = block.current_bus_structure['sink'] + + ports = [i for i in block_ports if not i.get_type() == 'bus'] + if bus_structure: + bus_index = [i for i in block_ports if i.get_type() == 'bus'].index(self) + ports = [p for i, p in enumerate(ports) if i in bus_structure[bus_index]] + return ports + + +class PortClone(Port): + + is_clone = True + + def __init__(self, parent, direction, master, name, key): + """ + Make a new port from nested data. + + Args: + block: the parent element + n: the nested odict + dir: the direction + """ + Element.__init__(self, parent) + self.master = master + self.name = name + self._key = key + self._nports = '1' + + def __getattr__(self, item): + return getattr(self.master, item) + + def add_clone(self): + raise NotImplementedError() + + def remove_clone(self, port): + raise NotImplementedError() diff --git a/grc/core/generator/CMakeLists.txt b/grc/core/generator/CMakeLists.txt deleted file mode 100644 index 492ad7c4ad..0000000000 --- a/grc/core/generator/CMakeLists.txt +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright 2011 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. - -file(GLOB py_files "*.py") - -GR_PYTHON_INSTALL( - FILES ${py_files} - DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core/generator -) - -install(FILES - flow_graph.tmpl - DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core/generator -) diff --git a/grc/core/generator/FlowGraphProxy.py b/grc/core/generator/FlowGraphProxy.py index 3723005576..23ccf95c4b 100644 --- a/grc/core/generator/FlowGraphProxy.py +++ b/grc/core/generator/FlowGraphProxy.py @@ -16,13 +16,17 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -class FlowGraphProxy(object): +from __future__ import absolute_import +from six.moves import range + + +class FlowGraphProxy(object): # TODO: move this in a refactored Generator def __init__(self, fg): - self._fg = fg + self.orignal_flowgraph = fg def __getattr__(self, item): - return getattr(self._fg, item) + return getattr(self.orignal_flowgraph, item) def get_hier_block_stream_io(self, direction): """ @@ -34,7 +38,7 @@ class FlowGraphProxy(object): Returns: a list of dicts with: type, label, vlen, size, optional """ - return filter(lambda p: p['type'] != "message", self.get_hier_block_io(direction)) + return [p for p in self.get_hier_block_io(direction) if p['type'] != "message"] def get_hier_block_message_io(self, direction): """ @@ -46,7 +50,7 @@ class FlowGraphProxy(object): Returns: a list of dicts with: type, label, vlen, size, optional """ - return filter(lambda p: p['type'] == "message", self.get_hier_block_io(direction)) + return [p for p in self.get_hier_block_io(direction) if p['type'] == "message"] def get_hier_block_io(self, direction): """ @@ -66,12 +70,12 @@ class FlowGraphProxy(object): 'label': str(pad.get_param('label').get_evaluated()), 'type': str(pad.get_param('type').get_evaluated()), 'vlen': str(pad.get_param('vlen').get_value()), - 'size': pad.get_param('type').get_opt('size'), + 'size': pad.get_param('type').opt_value('size'), 'optional': bool(pad.get_param('optional').get_evaluated()), } num_ports = pad.get_param('num_streams').get_evaluated() if num_ports > 1: - for i in xrange(num_ports): + for i in range(num_ports): clone = master.copy() clone['label'] += str(i) ports.append(clone) @@ -86,7 +90,7 @@ class FlowGraphProxy(object): Returns: a list of pad source blocks in this flow graph """ - pads = filter(lambda b: b.get_key() == 'pad_source', self.get_enabled_blocks()) + pads = [b for b in self.get_enabled_blocks() if b.key == 'pad_source'] return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id())) def get_pad_sinks(self): @@ -96,7 +100,7 @@ class FlowGraphProxy(object): Returns: a list of pad sink blocks in this flow graph """ - pads = filter(lambda b: b.get_key() == 'pad_sink', self.get_enabled_blocks()) + pads = [b for b in self.get_enabled_blocks() if b.key == 'pad_sink'] return sorted(pads, lambda x, y: cmp(x.get_id(), y.get_id())) def get_pad_port_global_key(self, port): @@ -113,14 +117,14 @@ class FlowGraphProxy(object): # using the block param 'type' instead of the port domain here # to emphasize that hier block generation is domain agnostic is_message_pad = pad.get_param('type').get_evaluated() == "message" - if port.get_parent() == pad: + if port.parent == pad: if is_message_pad: key = pad.get_param('label').get_value() else: - key = str(key_offset + int(port.get_key())) + key = str(key_offset + int(port.key)) return key else: # assuming we have either only sources or sinks if not is_message_pad: key_offset += len(pad.get_ports()) - return -1
\ No newline at end of file + return -1 diff --git a/grc/core/generator/Generator.py b/grc/core/generator/Generator.py index dda226c6b2..316ed5014d 100644 --- a/grc/core/generator/Generator.py +++ b/grc/core/generator/Generator.py @@ -16,11 +16,16 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +from __future__ import absolute_import + import codecs import os import tempfile +import operator +import collections from Cheetah.Template import Template +import six from .FlowGraphProxy import FlowGraphProxy from .. import ParseXML, Messages @@ -28,7 +33,7 @@ from ..Constants import ( TOP_BLOCK_FILE_MODE, BLOCK_FLAG_NEED_QT_GUI, HIER_BLOCK_FILE_MODE, BLOCK_DTD ) -from ..utils import expr_utils, odict +from ..utils import expr_utils DATA_DIR = os.path.dirname(__file__) FLOW_GRAPH_TEMPLATE = os.path.join(DATA_DIR, 'flow_graph.tmpl') @@ -83,20 +88,18 @@ class TopBlockGenerator(object): self.file_path = os.path.join(dirname, filename) self._dirname = dirname - def get_file_path(self): - return self.file_path - def write(self): """generate output and write it to files""" # Do throttle warning - throttling_blocks = filter(lambda b: b.throtteling(), self._flow_graph.get_enabled_blocks()) + throttling_blocks = [b for b in self._flow_graph.get_enabled_blocks() + if b.is_throtteling] if not throttling_blocks and not self._generate_options.startswith('hb'): Messages.send_warning("This flow graph may not have flow control: " "no audio or RF hardware blocks found. " "Add a Misc->Throttle block to your flow " "graph to avoid CPU congestion.") if len(throttling_blocks) > 1: - keys = set(map(lambda b: b.get_key(), throttling_blocks)) + keys = set([b.key for b in throttling_blocks]) if len(keys) > 1 and 'blocks_throttle' in keys: Messages.send_warning("This flow graph contains a throttle " "block and another rate limiting block, " @@ -139,18 +142,18 @@ class TopBlockGenerator(object): return code blocks_all = expr_utils.sort_objects( - filter(lambda b: b.get_enabled() and not b.get_bypassed(), fg.blocks), - lambda b: b.get_id(), _get_block_sort_text + [b for b in fg.blocks if b.enabled and not b.get_bypassed()], + operator.methodcaller('get_id'), _get_block_sort_text ) - deprecated_block_keys = set(block.get_name() for block in blocks_all if block.is_deprecated) + deprecated_block_keys = set(b.name for b in blocks_all if b.is_deprecated) for key in deprecated_block_keys: Messages.send_warning("The block {!r} is deprecated.".format(key)) # List of regular blocks (all blocks minus the special ones) - blocks = filter(lambda b: b not in (imports + parameters), blocks_all) + blocks = [b for b in blocks_all if b not in imports and b not in parameters] for block in blocks: - key = block.get_key() + key = block.key file_path = os.path.join(self._dirname, block.get_id() + '.py') if key == 'epy_block': src = block.get_param('_source_code').get_value() @@ -159,17 +162,17 @@ class TopBlockGenerator(object): src = block.get_param('source_code').get_value() output.append((file_path, src)) - # Filter out virtual sink connections - def cf(c): - return not (c.is_bus() or c.get_sink().get_parent().is_virtual_sink()) - connections = filter(cf, fg.get_enabled_connections()) + # Filter out bus and virtual sink connections + connections = [con for con in fg.get_enabled_connections() + if not (con.is_bus() or con.sink_block.is_virtual_sink())] # Get the virtual blocks and resolve their connections - virtual = filter(lambda c: c.get_source().get_parent().is_virtual_source(), connections) + connection_factory = fg.parent_platform.Connection + virtual = [c for c in connections if c.source_block.is_virtual_source()] for connection in virtual: - sink = connection.get_sink() - for source in connection.get_source().resolve_virtual_source(): - resolved = fg.get_parent().Connection(flow_graph=fg, porta=source, portb=sink) + sink = connection.sink_port + for source in connection.source_port.resolve_virtual_source(): + resolved = connection_factory(fg.orignal_flowgraph, source, sink) connections.append(resolved) # Remove the virtual connection connections.remove(connection) @@ -183,20 +186,19 @@ class TopBlockGenerator(object): for block in bypassed_blocks: # Get the upstream connection (off of the sink ports) # Use *connections* not get_connections() - source_connection = filter(lambda c: c.get_sink() == block.get_sinks()[0], connections) + source_connection = [c for c in connections if c.sink_port == block.sinks[0]] # The source connection should never have more than one element. assert (len(source_connection) == 1) # Get the source of the connection. - source_port = source_connection[0].get_source() + source_port = source_connection[0].source_port # Loop through all the downstream connections - for sink in filter(lambda c: c.get_source() == block.get_sources()[0], connections): - if not sink.get_enabled(): + for sink in (c for c in connections if c.source_port == block.sources[0]): + if not sink.enabled: # Ignore disabled connections continue - sink_port = sink.get_sink() - connection = fg.get_parent().Connection(flow_graph=fg, porta=source_port, portb=sink_port) + connection = connection_factory(fg.orignal_flowgraph, source_port, sink.sink_port) connections.append(connection) # Remove this sink connection connections.remove(sink) @@ -205,11 +207,11 @@ class TopBlockGenerator(object): # List of connections where each endpoint is enabled (sorted by domains, block names) connections.sort(key=lambda c: ( - c.get_source().get_domain(), c.get_sink().get_domain(), - c.get_source().get_parent().get_id(), c.get_sink().get_parent().get_id() + c.source_port.domain, c.sink_port.domain, + c.source_block.get_id(), c.sink_block.get_id() )) - connection_templates = fg.get_parent().connection_templates + connection_templates = fg.parent.connection_templates # List of variable names var_ids = [var.get_id() for var in parameters + variables] @@ -259,7 +261,7 @@ class HierBlockGenerator(TopBlockGenerator): file_path: where to write the py file (the xml goes into HIER_BLOCK_LIB_DIR) """ TopBlockGenerator.__init__(self, flow_graph, file_path) - platform = flow_graph.get_parent() + platform = flow_graph.parent hier_block_lib_dir = platform.config.hier_block_lib_dir if not os.path.exists(hier_block_lib_dir): @@ -267,18 +269,15 @@ class HierBlockGenerator(TopBlockGenerator): self._mode = HIER_BLOCK_FILE_MODE self.file_path = os.path.join(hier_block_lib_dir, self._flow_graph.get_option('id') + '.py') - self._file_path_xml = self.file_path + '.xml' - - def get_file_path_xml(self): - return self._file_path_xml + self.file_path_xml = self.file_path + '.xml' def write(self): """generate output and write it to files""" TopBlockGenerator.write(self) - ParseXML.to_file(self._build_block_n_from_flow_graph_io(), self.get_file_path_xml()) - ParseXML.validate_dtd(self.get_file_path_xml(), BLOCK_DTD) + ParseXML.to_file(self._build_block_n_from_flow_graph_io(), self.file_path_xml) + ParseXML.validate_dtd(self.file_path_xml, BLOCK_DTD) try: - os.chmod(self.get_file_path_xml(), self._mode) + os.chmod(self.file_path_xml, self._mode) except: pass @@ -294,12 +293,12 @@ class HierBlockGenerator(TopBlockGenerator): parameters = self._flow_graph.get_parameters() def var_or_value(name): - if name in map(lambda p: p.get_id(), parameters): - return "$"+name + if name in (p.get_id() for p in parameters): + return "$" + name return name # Build the nested data - block_n = odict() + block_n = collections.OrderedDict() block_n['name'] = self._flow_graph.get_option('title') or \ self._flow_graph.get_option('id').replace('_', ' ').title() block_n['key'] = block_key @@ -324,7 +323,7 @@ class HierBlockGenerator(TopBlockGenerator): # Parameters block_n['param'] = list() for param in parameters: - param_n = odict() + param_n = collections.OrderedDict() param_n['name'] = param.get_param('label').get_value() or param.get_id() param_n['key'] = param.get_id() param_n['value'] = param.get_param('value').get_value() @@ -342,7 +341,7 @@ class HierBlockGenerator(TopBlockGenerator): for direction in ('sink', 'source'): block_n[direction] = list() for port in self._flow_graph.get_hier_block_io(direction): - port_n = odict() + port_n = collections.OrderedDict() port_n['name'] = port['label'] port_n['type'] = port['type'] if port['type'] != "message": @@ -375,14 +374,18 @@ class QtHierBlockGenerator(HierBlockGenerator): def _build_block_n_from_flow_graph_io(self): n = HierBlockGenerator._build_block_n_from_flow_graph_io(self) - block_n = n['block'] + block_n = collections.OrderedDict() + + # insert flags after category + for key, value in six.iteritems(n['block']): + block_n[key] = value + if key == 'category': + block_n['flags'] = BLOCK_FLAG_NEED_QT_GUI if not block_n['name'].upper().startswith('QT GUI'): block_n['name'] = 'QT GUI ' + block_n['name'] - block_n.insert_after('category', 'flags', BLOCK_FLAG_NEED_QT_GUI) - - gui_hint_param = odict() + gui_hint_param = collections.OrderedDict() gui_hint_param['name'] = 'GUI Hint' gui_hint_param['key'] = 'gui_hint' gui_hint_param['value'] = '' @@ -394,4 +397,5 @@ class QtHierBlockGenerator(HierBlockGenerator): "\n#set $win = 'self.%s' % $id" "\n${gui_hint()($win)}" ) - return n + + return {'block': block_n} diff --git a/grc/core/generator/__init__.py b/grc/core/generator/__init__.py index f44b94a85d..98f410c8d4 100644 --- a/grc/core/generator/__init__.py +++ b/grc/core/generator/__init__.py @@ -15,4 +15,5 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -from Generator import Generator +from __future__ import absolute_import +from .Generator import Generator diff --git a/grc/core/generator/flow_graph.tmpl b/grc/core/generator/flow_graph.tmpl index 2adb555486..202362c925 100644 --- a/grc/core/generator/flow_graph.tmpl +++ b/grc/core/generator/flow_graph.tmpl @@ -206,17 +206,17 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) $indent($blk.get_make()) #else self.$blk.get_id() = $indent($blk.get_make()) - #if $blk.has_param('alias') and $blk.get_param('alias').get_evaluated() - (self.$blk.get_id()).set_block_alias("$blk.get_param('alias').get_evaluated()") + #if 'alias' in $blk.params and $blk.params['alias'].get_evaluated() + (self.$blk.get_id()).set_block_alias("$blk.params['alias'].get_evaluated()") #end if - #if $blk.has_param('affinity') and $blk.get_param('affinity').get_evaluated() - (self.$blk.get_id()).set_processor_affinity($blk.get_param('affinity').get_evaluated()) + #if 'affinity' in $blk.params and $blk.params['affinity'].get_evaluated() + (self.$blk.get_id()).set_processor_affinity($blk.params['affinity'].get_evaluated()) #end if - #if (len($blk.get_sources())>0) and $blk.has_param('minoutbuf') and (int($blk.get_param('minoutbuf').get_evaluated()) > 0) - (self.$blk.get_id()).set_min_output_buffer($blk.get_param('minoutbuf').get_evaluated()) + #if len($blk.sources) > 0 and 'minoutbuf' in $blk.params and int($blk.params['minoutbuf'].get_evaluated()) > 0 + (self.$blk.get_id()).set_min_output_buffer($blk.params['minoutbuf'].get_evaluated()) #end if - #if (len($blk.get_sources())>0) and $blk.has_param('maxoutbuf') and (int($blk.get_param('maxoutbuf').get_evaluated()) > 0) - (self.$blk.get_id()).set_max_output_buffer($blk.get_param('maxoutbuf').get_evaluated()) + #if len($blk.sources) > 0 and 'maxoutbuf' in $blk.params and int($blk.params['maxoutbuf'].get_evaluated()) > 0 + (self.$blk.get_id()).set_max_output_buffer($blk.params['maxoutbuf'].get_evaluated()) #end if #end if #end for @@ -226,12 +226,12 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) ## However, port names for IO pads should be self. ######################################################## #def make_port_sig($port) - #if $port.get_parent().get_key() in ('pad_source', 'pad_sink') + #if $port.parent.key in ('pad_source', 'pad_sink') #set block = 'self' #set key = $flow_graph.get_pad_port_global_key($port) #else - #set block = 'self.' + $port.get_parent().get_id() - #set key = $port.get_key() + #set block = 'self.' + $port.parent.get_id() + #set key = $port.key #end if #if not $key.isdigit() #set key = repr($key) @@ -245,9 +245,9 @@ gr.io_signaturev($(len($io_sigs)), $(len($io_sigs)), [$(', '.join($size_strs))]) $DIVIDER #end if #for $con in $connections - #set global $source = $con.get_source() - #set global $sink = $con.get_sink() - #include source=$connection_templates[($source.get_domain(), $sink.get_domain())] + #set global $source = $con.source_port + #set global $sink = $con.sink_port + #include source=$connection_templates[($source.domain, $sink.domain)] #end for ######################################################## @@ -377,8 +377,8 @@ def main(top_block_cls=$(class_name), options=None): tb.wait() qapp.aboutToQuit.connect(quitting) #for $m in $monitors - if $m.has_param('en'): - if $m.get_param('en').get_value(): + if 'en' in $m.params: + if $m.params['en'].get_value(): (tb.$m.get_id()).start() else: sys.stderr.write("Monitor '{0}' does not have an enable ('en') parameter.".format("tb.$m.get_id()")) diff --git a/grc/core/utils/CMakeLists.txt b/grc/core/utils/CMakeLists.txt deleted file mode 100644 index 3ba65258a5..0000000000 --- a/grc/core/utils/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright 2015 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. - -file(GLOB py_files "*.py") - -GR_PYTHON_INSTALL( - FILES ${py_files} - DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/core/utils -) diff --git a/grc/core/utils/__init__.py b/grc/core/utils/__init__.py index 6b23da2723..d095179a10 100644 --- a/grc/core/utils/__init__.py +++ b/grc/core/utils/__init__.py @@ -15,8 +15,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -import expr_utils -import epy_block_io -import extract_docs +from __future__ import absolute_import -from odict import odict +from . import expr_utils +from . import epy_block_io +from . import extract_docs + +from ._complexity import calculate_flowgraph_complexity diff --git a/grc/core/utils/complexity.py b/grc/core/utils/_complexity.py index baa8040db4..c0f3ae9de4 100644 --- a/grc/core/utils/complexity.py +++ b/grc/core/utils/_complexity.py @@ -4,12 +4,12 @@ def calculate_flowgraph_complexity(flowgraph): dbal = 0 for block in flowgraph.blocks: # Skip options block - if block.get_key() == 'options': + if block.key == 'options': continue # Don't worry about optional sinks? - sink_list = filter(lambda c: not c.get_optional(), block.get_sinks()) - source_list = filter(lambda c: not c.get_optional(), block.get_sources()) + sink_list = [c for c in block.sinks if not c.get_optional()] + source_list = [c for c in block.sources if not c.get_optional()] sinks = float(len(sink_list)) sources = float(len(source_list)) base = max(min(sinks, sources), 1) @@ -22,14 +22,15 @@ def calculate_flowgraph_complexity(flowgraph): multi = 1 # Connection ratio multiplier - sink_multi = max(float(sum(map(lambda c: len(c.get_connections()), sink_list)) / max(sinks, 1.0)), 1.0) - source_multi = max(float(sum(map(lambda c: len(c.get_connections()), source_list)) / max(sources, 1.0)), 1.0) - dbal = dbal + (base * multi * sink_multi * source_multi) + sink_multi = max(float(sum(len(c.get_connections()) for c in sink_list) / max(sinks, 1.0)), 1.0) + source_multi = max(float(sum(len(c.get_connections()) for c in source_list) / max(sources, 1.0)), 1.0) + dbal += base * multi * sink_multi * source_multi blocks = float(len(flowgraph.blocks)) connections = float(len(flowgraph.connections)) elements = blocks + connections - disabled_connections = len(filter(lambda c: not c.get_enabled(), flowgraph.connections)) + disabled_connections = sum(not c.enabled for c in flowgraph.connections) + variables = elements - blocks - connections enabled = float(len(flowgraph.get_enabled_blocks())) diff --git a/grc/core/utils/epy_block_io.py b/grc/core/utils/epy_block_io.py index a094ab7ad5..823116adb9 100644 --- a/grc/core/utils/epy_block_io.py +++ b/grc/core/utils/epy_block_io.py @@ -1,7 +1,12 @@ +from __future__ import absolute_import + import inspect import collections +import six +from six.moves import zip + TYPE_MAP = { 'complex64': 'complex', 'complex': 'complex', @@ -32,10 +37,10 @@ def _ports(sigs, msgs): def _find_block_class(source_code, cls): ns = {} try: - exec source_code in ns + exec(source_code, ns) except Exception as e: raise ValueError("Can't interpret source code: " + str(e)) - for var in ns.itervalues(): + for var in six.itervalues(ns): if inspect.isclass(var) and issubclass(var, cls): return var raise ValueError('No python block class found in code') @@ -53,7 +58,7 @@ def extract(cls): spec = inspect.getargspec(cls.__init__) init_args = spec.args[1:] - defaults = map(repr, spec.defaults or ()) + defaults = [repr(arg) for arg in (spec.defaults or ())] doc = cls.__doc__ or cls.__init__.__doc__ or '' cls_name = cls.__name__ diff --git a/grc/core/utils/expr_utils.py b/grc/core/utils/expr_utils.py index 2059ceff9f..cc03e9cb1c 100644 --- a/grc/core/utils/expr_utils.py +++ b/grc/core/utils/expr_utils.py @@ -17,8 +17,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import, print_function + import string -VAR_CHARS = string.letters + string.digits + '_' + +import six + +VAR_CHARS = string.ascii_letters + string.digits + '_' class graph(object): @@ -50,7 +55,7 @@ class graph(object): self._graph[src_node_key].remove(dest_node_key) def get_nodes(self): - return self._graph.keys() + return list(self._graph.keys()) def get_edges(self, node_key): return self._graph[node_key] @@ -85,7 +90,7 @@ def expr_split(expr, var_chars=VAR_CHARS): toks.append(char) tok = '' toks.append(tok) - return filter(lambda t: t, toks) + return [t for t in toks if t] def expr_replace(expr, replace_dict): @@ -101,7 +106,7 @@ def expr_replace(expr, replace_dict): """ expr_splits = expr_split(expr, var_chars=VAR_CHARS + '.') for i, es in enumerate(expr_splits): - if es in replace_dict.keys(): + if es in list(replace_dict.keys()): expr_splits[i] = replace_dict[es] return ''.join(expr_splits) @@ -118,7 +123,7 @@ def get_variable_dependencies(expr, vars): a subset of vars used in the expression """ expr_toks = expr_split(expr) - return set(var for var in vars if var in expr_toks) + return set(v for v in vars if v in expr_toks) def get_graph(exprs): @@ -131,12 +136,12 @@ def get_graph(exprs): Returns: a graph of variable deps """ - vars = exprs.keys() + vars = list(exprs.keys()) # Get dependencies for each expression, load into graph var_graph = graph() for var in vars: var_graph.add_node(var) - for var, expr in exprs.iteritems(): + for var, expr in six.iteritems(exprs): for dep in get_variable_dependencies(expr, vars): if dep != var: var_graph.add_edge(dep, var) @@ -159,7 +164,7 @@ def sort_variables(exprs): # Determine dependency order while var_graph.get_nodes(): # Get a list of nodes with no edges - indep_vars = filter(lambda var: not var_graph.get_edges(var), var_graph.get_nodes()) + indep_vars = [var for var in var_graph.get_nodes() if not var_graph.get_edges(var)] if not indep_vars: raise Exception('circular dependency caught in sort_variables') # Add the indep vars to the end of the list diff --git a/grc/core/utils/extract_docs.py b/grc/core/utils/extract_docs.py index a6e0bc971e..cff8a81099 100644 --- a/grc/core/utils/extract_docs.py +++ b/grc/core/utils/extract_docs.py @@ -17,15 +17,19 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import, print_function + import sys import re import subprocess import threading import json -import Queue import random import itertools +import six +from six.moves import queue, filter, range + ############################################################################### # The docstring extraction @@ -124,7 +128,7 @@ class SubprocessLoader(object): self.callback_query_result = callback_query_result self.callback_finished = callback_finished or (lambda: None) - self._queue = Queue.Queue() + self._queue = queue.Queue() self._thread = None self._worker = None self._shutdown = threading.Event() @@ -157,14 +161,14 @@ class SubprocessLoader(object): cmd, args = self._last_cmd if cmd == 'query': msg += " (crashed while loading {0!r})".format(args[0]) - print >> sys.stderr, msg + print(msg, file=sys.stderr) continue # restart else: break # normal termination, return finally: self._worker.terminate() else: - print >> sys.stderr, "Warning: docstring loader crashed too often" + print("Warning: docstring loader crashed too often", file=sys.stderr) self._thread = None self._worker = None self.callback_finished() @@ -203,9 +207,9 @@ class SubprocessLoader(object): key, docs = args self.callback_query_result(key, docs) elif cmd == 'error': - print args + print(args) else: - print >> sys.stderr, "Unknown response:", cmd, args + print("Unknown response:", cmd, args, file=sys.stderr) def query(self, key, imports=None, make=None): """ Request docstring extraction for a certain key """ @@ -270,12 +274,12 @@ if __name__ == '__worker__': elif __name__ == '__main__': def callback(key, docs): - print key - for match, doc in docs.iteritems(): - print '-->', match - print doc.strip() - print - print + print(key) + for match, doc in six.iteritems(docs): + print('-->', match) + print(doc.strip()) + print() + print() r = SubprocessLoader(callback) diff --git a/grc/core/utils/odict.py b/grc/core/utils/odict.py deleted file mode 100644 index 85927e869f..0000000000 --- a/grc/core/utils/odict.py +++ /dev/null @@ -1,115 +0,0 @@ -""" -Copyright 2008-2015 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from UserDict import DictMixin - - -class odict(DictMixin): - - def __init__(self, d={}): - self._keys = list(d.keys()) - self._data = dict(d.copy()) - - def __setitem__(self, key, value): - if key not in self._data: - self._keys.append(key) - self._data[key] = value - - def __getitem__(self, key): - return self._data[key] - - def __delitem__(self, key): - del self._data[key] - self._keys.remove(key) - - def keys(self): - return list(self._keys) - - def copy(self): - copy_dict = odict() - copy_dict._data = self._data.copy() - copy_dict._keys = list(self._keys) - return copy_dict - - def insert_after(self, pos_key, key, val): - """ - Insert the new key, value entry after the entry given by the position key. - If the positional key is None, insert at the end. - - Args: - pos_key: the positional key - key: the key for the new entry - val: the value for the new entry - """ - index = (pos_key is None) and len(self._keys) or self._keys.index(pos_key) - if key in self._keys: - raise KeyError('Cannot insert, key "{}" already exists'.format(str(key))) - self._keys.insert(index+1, key) - self._data[key] = val - - def insert_before(self, pos_key, key, val): - """ - Insert the new key, value entry before the entry given by the position key. - If the positional key is None, insert at the begining. - - Args: - pos_key: the positional key - key: the key for the new entry - val: the value for the new entry - """ - index = (pos_key is not None) and self._keys.index(pos_key) or 0 - if key in self._keys: - raise KeyError('Cannot insert, key "{}" already exists'.format(str(key))) - self._keys.insert(index, key) - self._data[key] = val - - def find(self, key): - """ - Get the value for this key if exists. - - Args: - key: the key to search for - - Returns: - the value or None - """ - if key in self: - return self[key] - return None - - def findall(self, key): - """ - Get a list of values for this key. - - Args: - key: the key to search for - - Returns: - a list of values or empty list - """ - obj = self.find(key) - if obj is None: - obj = list() - if isinstance(obj, list): - return obj - return [obj] - - def clear(self): - self._data.clear() - del self._keys[:]
\ No newline at end of file diff --git a/grc/gui/Actions.py b/grc/gui/Actions.py index 6eccab75fb..d214f28049 100644 --- a/grc/gui/Actions.py +++ b/grc/gui/Actions.py @@ -17,284 +17,326 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import pygtk -pygtk.require('2.0') -import gtk +from __future__ import absolute_import -import Preferences +import six +import logging -NO_MODS_MASK = 0 +from gi.repository import Gtk, Gdk, Gio, GLib, GObject -######################################################################## -# Actions API -######################################################################## -_actions_keypress_dict = dict() -_keymap = gtk.gdk.keymap_get_default() -_used_mods_mask = NO_MODS_MASK - - -def handle_key_press(event): - """ - Call the action associated with the key press event. - Both the key value and the mask must have a match. - - Args: - event: a gtk key press event - - Returns: - true if handled - """ - _used_mods_mask = reduce(lambda x, y: x | y, [mod_mask for keyval, mod_mask in _actions_keypress_dict], NO_MODS_MASK) - # extract the key value and the consumed modifiers - keyval, egroup, level, consumed = _keymap.translate_keyboard_state( - event.hardware_keycode, event.state, event.group) - # get the modifier mask and ignore irrelevant modifiers - mod_mask = event.state & ~consumed & _used_mods_mask - # look up the keypress and call the action - try: - _actions_keypress_dict[(keyval, mod_mask)]() - except KeyError: - return False # not handled - else: - return True # handled here - -_all_actions_list = list() - - -def get_all_actions(): - return _all_actions_list - -_accel_group = gtk.AccelGroup() - - -def get_accel_group(): - return _accel_group - - -class _ActionBase(object): - """ - Base class for Action and ToggleAction - Register actions and keypresses with this module. - """ - def __init__(self, label, keypresses): - _all_actions_list.append(self) - for i in range(len(keypresses)/2): - keyval, mod_mask = keypresses[i*2:(i+1)*2] - # register this keypress - if _actions_keypress_dict.has_key((keyval, mod_mask)): - raise KeyError('keyval/mod_mask pair already registered "%s"' % str((keyval, mod_mask))) - _actions_keypress_dict[(keyval, mod_mask)] = self - # set the accelerator group, and accelerator path - # register the key name and mod mask with the accelerator path - if label is None: - continue # dont register accel - accel_path = '<main>/' + self.get_name() - self.set_accel_group(get_accel_group()) - self.set_accel_path(accel_path) - gtk.accel_map_add_entry(accel_path, keyval, mod_mask) - self.args = None + +log = logging.getLogger(__name__) + + +def filter_from_dict(vars): + return filter(lambda x: isinstance(x[1], Action), vars.items()) + + +class Namespace(object): + + def __init__(self): + self._actions = {} + + def add(self, action): + key = action.props.name + self._actions[key] = action + + def connect(self, name, handler): + #log.debug("Connecting action <{}> to handler <{}>".format(name, handler.__name__)) + self._actions[name].connect('activate', handler) + + def register(self, name, parameter=None, handler=None, label=None, tooltip=None, + icon_name=None, keypresses=None, preference_name=None, default=None): + # Check types + if not isinstance(name, str): + raise TypeError("Cannot register fuction: 'name' must be a str") + if parameter and not isinstance(parameter, str): + raise TypeError("Cannot register fuction: 'parameter' must be a str") + if handler and not callable(handler): + raise TypeError("Cannot register fuction: 'handler' must be callable") + + # Check if the name has a prefix. + prefix = None + if name.startswith("app.") or name.startswith("win."): + # Set a prefix for later and remove it + prefix = name[0:3] + name = name[4:] + + if handler: + log.debug("Register action [{}, prefix={}, param={}, handler={}]".format( + name, prefix, parameter, handler.__name__)) + else: + log.debug("Register action [{}, prefix={}, param={}, handler=None]".format( + name, prefix, parameter)) + + action = Action(name, parameter, label=label, tooltip=tooltip, + icon_name=icon_name, keypresses=keypresses, prefix=prefix, + preference_name=preference_name, default=default) + if handler: + action.connect('activate', handler) + + key = name + if prefix: + key = "{}.{}".format(prefix, name) + if prefix == "app": + pass + #self.app.add_action(action) + elif prefix == "win": + pass + #self.win.add_action(action) + + #log.debug("Registering action as '{}'".format(key)) + self._actions[key] = action + return action + + + # If the actions namespace is called, trigger an action + def __call__(self, name): + # Try to parse the action string. + valid, action_name, target_value = Action.parse_detailed_name(name) + if not valid: + raise Exception("Invalid action string: '{}'".format(name)) + if action_name not in self._actions: + raise Exception("Action '{}' is not registered!".format(action_name)) + + if target_value: + self._actions[action_name].activate(target_value) + else: + self._actions[action_name].activate() + + def __getitem__(self, key): + return self._actions[key] + + def __iter__(self): + return self._actions.itervalues() + + def __repr__(self): + return str(self) + + def get_actions(self): + return self._actions def __str__(self): - """ - The string representation should be the name of the action id. - Try to find the action id for this action by searching this module. - """ - for name, value in globals().iteritems(): - if value == self: - return name - return self.get_name() - - def __repr__(self): return str(self) - - def __call__(self, *args): - """ - Emit the activate signal when called with (). - """ - self.args = args - self.emit('activate') - - -class Action(gtk.Action, _ActionBase): - """ - A custom Action class based on gtk.Action. - Pass additional arguments such as keypresses. - """ - - def __init__(self, keypresses=(), name=None, label=None, tooltip=None, - stock_id=None): - """ - Create a new Action instance. - - Args: - key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...) - the: regular gtk.Action parameters (defaults to None) - """ - if name is None: - name = label - gtk.Action.__init__(self, name=name, label=label, tooltip=tooltip, - stock_id=stock_id) - _ActionBase.__init__(self, label, keypresses) - - -class ToggleAction(gtk.ToggleAction, _ActionBase): - """ - A custom Action class based on gtk.ToggleAction. - Pass additional arguments such as keypresses. - """ - - def __init__(self, keypresses=(), name=None, label=None, tooltip=None, - stock_id=None, preference_name=None, default=True): - """ - Create a new ToggleAction instance. - - Args: - key_presses: a tuple of (keyval1, mod_mask1, keyval2, mod_mask2, ...) - the: regular gtk.Action parameters (defaults to None) - """ - if name is None: - name = label - gtk.ToggleAction.__init__(self, name=name, label=label, - tooltip=tooltip, stock_id=stock_id) - _ActionBase.__init__(self, label, keypresses) + s = "{Actions:" + for key in self._actions: + s += " {},".format(key) + s = s.rstrip(",") + "}" + return s + + +class Action(Gio.SimpleAction): + + # Change these to normal python properties. + #prefs_name + + def __init__(self, name, parameter=None, label=None, tooltip=None, + icon_name=None, keypresses=None, prefix=None, + preference_name=None, default=None): + self.name = name + self.label = label + self.tooltip = tooltip + self.icon_name = icon_name + self.keypresses = keypresses + self.prefix = prefix self.preference_name = preference_name self.default = default - def load_from_preferences(self): + # Don't worry about checking types here, since it's done in register() + # Save the parameter type to use for converting in __call__ + self.type = None + + variant = None + state = None + if parameter: + variant = GLib.VariantType.new(parameter) + if preference_name: + state = GLib.Variant.new_boolean(True) + Gio.SimpleAction.__init__(self, name=name, parameter_type=variant, state=state) + + def enable(self): + self.props.enabled = True + + def disable(self): + self.props.enabled = False + + def set_enabled(self, state): + if not isinstance(state, bool): + raise TypeError("State must be True/False.") + self.props.enabled = state + + def __str__(self): + return self.props.name + + def __repr__(self): + return str(self) + + def get_active(self): + if self.props.state: + return self.props.state.get_boolean() + return False + + def set_active(self, state): + if not isinstance(state, bool): + raise TypeError("State must be True/False.") + self.change_state(GLib.Variant.new_boolean(state)) + + # Allows actions to be directly called. + def __call__(self, parameter=None): + if self.type and parameter: + # Try to convert it to the correct type. + try: + param = GLib.Variant(self.type, parameter) + self.activate(param) + except TypeError: + raise TypeError("Invalid parameter type for action '{}'. Expected: '{}'".format(self.get_name(), self.type)) + else: + self.activate() + + def load_from_preferences(self, *args): + log.debug("load_from_preferences({})".format(args)) if self.preference_name is not None: - self.set_active(Preferences.entry( - self.preference_name, default=bool(self.default))) + config = Gtk.Application.get_default().config + self.set_active(config.entry(self.preference_name, default=bool(self.default))) - def save_to_preferences(self): + def save_to_preferences(self, *args): + log.debug("save_to_preferences({})".format(args)) if self.preference_name is not None: - Preferences.entry(self.preference_name, value=self.get_active()) + config = Gtk.Application.get_default().config + config.entry(self.preference_name, value=self.get_active()) + + +actions = Namespace() + + +def get_actions(): + return actions.get_actions() + + +def connect(action, handler=None): + return actions.connect(action, handler=handler) + ######################################################################## -# Actions +# Old Actions ######################################################################## -PAGE_CHANGE = Action() -EXTERNAL_UPDATE = Action() -VARIABLE_EDITOR_UPDATE = Action() -FLOW_GRAPH_NEW = Action( +PAGE_CHANGE = actions.register("win.page_change") +EXTERNAL_UPDATE = actions.register("app.external_update") +VARIABLE_EDITOR_UPDATE = actions.register("app.variable_editor_update") +FLOW_GRAPH_NEW = actions.register("app.flowgraph.new", label='_New', tooltip='Create a new flow graph', - stock_id=gtk.STOCK_NEW, - keypresses=(gtk.keysyms.n, gtk.gdk.CONTROL_MASK), + icon_name='document-new', + keypresses=["<Ctrl>n"], + parameter="s", ) -FLOW_GRAPH_OPEN = Action( +FLOW_GRAPH_OPEN = actions.register("app.flowgraph.open", label='_Open', tooltip='Open an existing flow graph', - stock_id=gtk.STOCK_OPEN, - keypresses=(gtk.keysyms.o, gtk.gdk.CONTROL_MASK), + icon_name='document-open', + keypresses=["<Ctrl>o"], ) -FLOW_GRAPH_OPEN_RECENT = Action( +FLOW_GRAPH_OPEN_RECENT = actions.register("app.flowgraph.open_recent", label='Open _Recent', tooltip='Open a recently used flow graph', - stock_id=gtk.STOCK_OPEN, + icon_name='document-open-recent', + parameter="s", ) -FLOW_GRAPH_SAVE = Action( +FLOW_GRAPH_CLEAR_RECENT = actions.register("app.flowgraph.clear_recent") +FLOW_GRAPH_SAVE = actions.register("app.flowgraph.save", label='_Save', tooltip='Save the current flow graph', - stock_id=gtk.STOCK_SAVE, - keypresses=(gtk.keysyms.s, gtk.gdk.CONTROL_MASK), + icon_name='document-save', + keypresses=["<Ctrl>s"], ) -FLOW_GRAPH_SAVE_AS = Action( +FLOW_GRAPH_SAVE_AS = actions.register("app.flowgraph.save_as", label='Save _As', tooltip='Save the current flow graph as...', - stock_id=gtk.STOCK_SAVE_AS, - keypresses=(gtk.keysyms.s, gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK), + icon_name='document-save-as', + keypresses=["<Ctrl><Shift>s"], ) -FLOW_GRAPH_SAVE_A_COPY = Action( - label='Save A Copy', - tooltip='Save the copy of current flowgraph', +FLOW_GRAPH_SAVE_COPY = actions.register("app.flowgraph.save_copy", + label='Save Copy', + tooltip='Save a copy of current flow graph', ) -FLOW_GRAPH_DUPLICATE = Action( +FLOW_GRAPH_DUPLICATE = actions.register("app.flowgraph.duplicate", label='_Duplicate', - tooltip='Create a duplicate of current flowgraph', - stock_id=gtk.STOCK_COPY, - keypresses=(gtk.keysyms.d, gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK), + tooltip='Create a duplicate of current flow graph', + #stock_id=Gtk.STOCK_COPY, + keypresses=["<Ctrl><Shift>d"], ) -FLOW_GRAPH_CLOSE = Action( +FLOW_GRAPH_CLOSE = actions.register("app.flowgraph.close", label='_Close', tooltip='Close the current flow graph', - stock_id=gtk.STOCK_CLOSE, - keypresses=(gtk.keysyms.w, gtk.gdk.CONTROL_MASK), + icon_name='window-close', + keypresses=["<Ctrl>w"], ) -APPLICATION_INITIALIZE = Action() -APPLICATION_QUIT = Action( +APPLICATION_INITIALIZE = actions.register("app.initialize") +APPLICATION_QUIT = actions.register("app.quit", label='_Quit', tooltip='Quit program', - stock_id=gtk.STOCK_QUIT, - keypresses=(gtk.keysyms.q, gtk.gdk.CONTROL_MASK), + icon_name='application-exit', + keypresses=["<Ctrl>q"], ) -FLOW_GRAPH_UNDO = Action( +FLOW_GRAPH_UNDO = actions.register("win.undo", label='_Undo', tooltip='Undo a change to the flow graph', - stock_id=gtk.STOCK_UNDO, - keypresses=(gtk.keysyms.z, gtk.gdk.CONTROL_MASK), + icon_name='edit-undo', + keypresses=["<Ctrl>z"], ) -FLOW_GRAPH_REDO = Action( +FLOW_GRAPH_REDO = actions.register("win.redo", label='_Redo', tooltip='Redo a change to the flow graph', - stock_id=gtk.STOCK_REDO, - keypresses=(gtk.keysyms.y, gtk.gdk.CONTROL_MASK), + icon_name='edit-redo', + keypresses=["<Ctrl>y"], ) -NOTHING_SELECT = Action() -SELECT_ALL = Action( +NOTHING_SELECT = actions.register("win.unselect") +SELECT_ALL = actions.register("win.select_all", label='Select _All', tooltip='Select all blocks and connections in the flow graph', - stock_id=gtk.STOCK_SELECT_ALL, - keypresses=(gtk.keysyms.a, gtk.gdk.CONTROL_MASK), + icon_name='edit-select-all', + keypresses=["<Ctrl>a"], ) -ELEMENT_SELECT = Action() -ELEMENT_CREATE = Action() -ELEMENT_DELETE = Action( +ELEMENT_SELECT = actions.register("win.select") +ELEMENT_CREATE = actions.register("win.add") +ELEMENT_DELETE = actions.register("win.delete", label='_Delete', tooltip='Delete the selected blocks', - stock_id=gtk.STOCK_DELETE, - keypresses=(gtk.keysyms.Delete, NO_MODS_MASK), + icon_name='edit-delete', ) -BLOCK_MOVE = Action() -BLOCK_ROTATE_CCW = Action( +BLOCK_MOVE = actions.register("win.block_move") +BLOCK_ROTATE_CCW = actions.register("win.block_rotate_ccw", label='Rotate Counterclockwise', tooltip='Rotate the selected blocks 90 degrees to the left', - stock_id=gtk.STOCK_GO_BACK, - keypresses=(gtk.keysyms.Left, NO_MODS_MASK), + icon_name='object-rotate-left', ) -BLOCK_ROTATE_CW = Action( +BLOCK_ROTATE_CW = actions.register("win.block_rotate", label='Rotate Clockwise', tooltip='Rotate the selected blocks 90 degrees to the right', - stock_id=gtk.STOCK_GO_FORWARD, - keypresses=(gtk.keysyms.Right, NO_MODS_MASK), + icon_name='object-rotate-right', ) -BLOCK_VALIGN_TOP = Action( +BLOCK_VALIGN_TOP = actions.register("win.block_align_top", label='Vertical Align Top', tooltip='Align tops of selected blocks', - keypresses=(gtk.keysyms.t, gtk.gdk.SHIFT_MASK), ) -BLOCK_VALIGN_MIDDLE = Action( +BLOCK_VALIGN_MIDDLE = actions.register("win.block_align_middle", label='Vertical Align Middle', tooltip='Align centers of selected blocks vertically', - keypresses=(gtk.keysyms.m, gtk.gdk.SHIFT_MASK), ) -BLOCK_VALIGN_BOTTOM = Action( +BLOCK_VALIGN_BOTTOM = actions.register("win.block_align_bottom", label='Vertical Align Bottom', tooltip='Align bottoms of selected blocks', - keypresses=(gtk.keysyms.b, gtk.gdk.SHIFT_MASK), ) -BLOCK_HALIGN_LEFT = Action( +BLOCK_HALIGN_LEFT = actions.register("win.block_align_left", label='Horizontal Align Left', tooltip='Align left edges of blocks selected blocks', - keypresses=(gtk.keysyms.l, gtk.gdk.SHIFT_MASK), ) -BLOCK_HALIGN_CENTER = Action( +BLOCK_HALIGN_CENTER = actions.register("win.block_align_center", label='Horizontal Align Center', tooltip='Align centers of selected blocks horizontally', - keypresses=(gtk.keysyms.c, gtk.gdk.SHIFT_MASK), ) -BLOCK_HALIGN_RIGHT = Action( +BLOCK_HALIGN_RIGHT = actions.register("win.block_align_right", label='Horizontal Align Right', tooltip='Align right edges of selected blocks', - keypresses=(gtk.keysyms.r, gtk.gdk.SHIFT_MASK), ) BLOCK_ALIGNMENTS = [ BLOCK_VALIGN_TOP, @@ -305,234 +347,222 @@ BLOCK_ALIGNMENTS = [ BLOCK_HALIGN_CENTER, BLOCK_HALIGN_RIGHT, ] -BLOCK_PARAM_MODIFY = Action( +BLOCK_PARAM_MODIFY = actions.register("win.block_modify", label='_Properties', tooltip='Modify params for the selected block', - stock_id=gtk.STOCK_PROPERTIES, - keypresses=(gtk.keysyms.Return, NO_MODS_MASK), + icon_name='document-properties', ) -BLOCK_ENABLE = Action( +BLOCK_ENABLE = actions.register("win.block_enable", label='E_nable', tooltip='Enable the selected blocks', - stock_id=gtk.STOCK_CONNECT, - keypresses=(gtk.keysyms.e, NO_MODS_MASK), + icon_name='network-wired', ) -BLOCK_DISABLE = Action( +BLOCK_DISABLE = actions.register("win.block_disable", label='D_isable', tooltip='Disable the selected blocks', - stock_id=gtk.STOCK_DISCONNECT, - keypresses=(gtk.keysyms.d, NO_MODS_MASK), + icon_name='network-wired-disconnected', ) -BLOCK_BYPASS = Action( +BLOCK_BYPASS = actions.register("win.block_bypass", label='_Bypass', tooltip='Bypass the selected block', - stock_id=gtk.STOCK_MEDIA_FORWARD, - keypresses=(gtk.keysyms.b, NO_MODS_MASK), + icon_name='media-seek-forward', ) -TOGGLE_SNAP_TO_GRID = ToggleAction( +TOGGLE_SNAP_TO_GRID = actions.register("win.snap_to_grid", label='_Snap to grid', tooltip='Snap blocks to a grid for an easier connection alignment', - preference_name='snap_to_grid' + preference_name='snap_to_grid', ) -TOGGLE_HIDE_DISABLED_BLOCKS = ToggleAction( +TOGGLE_HIDE_DISABLED_BLOCKS = actions.register("win.hide_disabled", label='Hide _Disabled Blocks', tooltip='Toggle visibility of disabled blocks and connections', - stock_id=gtk.STOCK_MISSING_IMAGE, - keypresses=(gtk.keysyms.d, gtk.gdk.CONTROL_MASK), + icon_name='image-missing', + keypresses=["<Ctrl>d"], + preference_name='hide_disabled', ) -TOGGLE_HIDE_VARIABLES = ToggleAction( +TOGGLE_HIDE_VARIABLES = actions.register("win.hide_variables", label='Hide Variables', tooltip='Hide all variable blocks', preference_name='hide_variables', default=False, ) -TOGGLE_FLOW_GRAPH_VAR_EDITOR = ToggleAction( +TOGGLE_FLOW_GRAPH_VAR_EDITOR = actions.register("win.toggle_variable_editor", label='Show _Variable Editor', tooltip='Show the variable editor. Modify variables and imports in this flow graph', - stock_id=gtk.STOCK_EDIT, + icon_name='accessories-text-editor', default=True, - keypresses=(gtk.keysyms.e, gtk.gdk.CONTROL_MASK), + keypresses=["<Ctrl>e"], preference_name='variable_editor_visable', ) -TOGGLE_FLOW_GRAPH_VAR_EDITOR_SIDEBAR = ToggleAction( +TOGGLE_FLOW_GRAPH_VAR_EDITOR_SIDEBAR = actions.register("win.toggle_variable_editor_sidebar", label='Move the Variable Editor to the Sidebar', tooltip='Move the variable editor to the sidebar', default=False, preference_name='variable_editor_sidebar', ) -TOGGLE_AUTO_HIDE_PORT_LABELS = ToggleAction( +TOGGLE_AUTO_HIDE_PORT_LABELS = actions.register("win.auto_hide_port_labels", label='Auto-Hide _Port Labels', tooltip='Automatically hide port labels', preference_name='auto_hide_port_labels' ) -TOGGLE_SHOW_BLOCK_COMMENTS = ToggleAction( +TOGGLE_SHOW_BLOCK_COMMENTS = actions.register("win.show_block_comments", label='Show Block Comments', tooltip="Show comment beneath each block", preference_name='show_block_comments' ) -TOGGLE_SHOW_CODE_PREVIEW_TAB = ToggleAction( +TOGGLE_SHOW_CODE_PREVIEW_TAB = actions.register("win.toggle_code_preview", label='Generated Code Preview', tooltip="Show a preview of the code generated for each Block in its " "Properties Dialog", preference_name='show_generated_code_tab', default=False, ) -TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY = ToggleAction( +TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY = actions.register("win.show_flowgraph_complexity", label='Show Flowgraph Complexity', tooltip="How many Balints is the flowgraph...", preference_name='show_flowgraph_complexity', default=False, ) -BLOCK_CREATE_HIER = Action( +BLOCK_CREATE_HIER = actions.register("win.block_create_hier", label='C_reate Hier', tooltip='Create hier block from selected blocks', - stock_id=gtk.STOCK_CONNECT, -# keypresses=(gtk.keysyms.c, NO_MODS_MASK), + icon_name='document-new', ) -BLOCK_CUT = Action( +BLOCK_CUT = actions.register("win.block_cut", label='Cu_t', tooltip='Cut', - stock_id=gtk.STOCK_CUT, - keypresses=(gtk.keysyms.x, gtk.gdk.CONTROL_MASK), + icon_name='edit-cut', + keypresses=["<Ctrl>x"], ) -BLOCK_COPY = Action( +BLOCK_COPY = actions.register("win.block_copy", label='_Copy', tooltip='Copy', - stock_id=gtk.STOCK_COPY, - keypresses=(gtk.keysyms.c, gtk.gdk.CONTROL_MASK), + icon_name='edit-copy', + keypresses=["<Ctrl>c"], ) -BLOCK_PASTE = Action( +BLOCK_PASTE = actions.register("win.block_paste", label='_Paste', tooltip='Paste', - stock_id=gtk.STOCK_PASTE, - keypresses=(gtk.keysyms.v, gtk.gdk.CONTROL_MASK), + icon_name='edit-paste', + keypresses=["<Ctrl>v"], ) -ERRORS_WINDOW_DISPLAY = Action( +ERRORS_WINDOW_DISPLAY = actions.register("app.errors", label='Flowgraph _Errors', tooltip='View flow graph errors', - stock_id=gtk.STOCK_DIALOG_ERROR, + icon_name='dialog-error', ) -TOGGLE_CONSOLE_WINDOW = ToggleAction( +TOGGLE_CONSOLE_WINDOW = actions.register("win.toggle_console_window", label='Show _Console Panel', tooltip='Toggle visibility of the console', - keypresses=(gtk.keysyms.r, gtk.gdk.CONTROL_MASK), + keypresses=["<Ctrl>r"], preference_name='console_window_visible' ) -TOGGLE_BLOCKS_WINDOW = ToggleAction( +# TODO: Might be able to convert this to a Gio.PropertyAction eventually. +# actions would need to be defined in the correct class and not globally +TOGGLE_BLOCKS_WINDOW = actions.register("win.toggle_blocks_window", label='Show _Block Tree Panel', tooltip='Toggle visibility of the block tree widget', - keypresses=(gtk.keysyms.b, gtk.gdk.CONTROL_MASK), + keypresses=["<Ctrl>b"], preference_name='blocks_window_visible' ) -TOGGLE_SCROLL_LOCK = ToggleAction( +TOGGLE_SCROLL_LOCK = actions.register("win.console.scroll_lock", label='Console Scroll _Lock', tooltip='Toggle scroll lock for the console window', preference_name='scroll_lock' ) -ABOUT_WINDOW_DISPLAY = Action( +ABOUT_WINDOW_DISPLAY = actions.register("app.about", label='_About', tooltip='About this program', - stock_id=gtk.STOCK_ABOUT, + icon_name='help-about', ) -HELP_WINDOW_DISPLAY = Action( +HELP_WINDOW_DISPLAY = actions.register("app.help", label='_Help', tooltip='Usage tips', - stock_id=gtk.STOCK_HELP, - keypresses=(gtk.keysyms.F1, NO_MODS_MASK), + icon_name='help-contents', + keypresses=["F1"], ) -TYPES_WINDOW_DISPLAY = Action( +TYPES_WINDOW_DISPLAY = actions.register("app.types", label='_Types', tooltip='Types color mapping', - stock_id=gtk.STOCK_DIALOG_INFO, + icon_name='dialog-information', ) -FLOW_GRAPH_GEN = Action( +FLOW_GRAPH_GEN = actions.register("app.flowgraph.generate", label='_Generate', tooltip='Generate the flow graph', - stock_id=gtk.STOCK_CONVERT, - keypresses=(gtk.keysyms.F5, NO_MODS_MASK), + icon_name='insert-object', + keypresses=["F5"], ) -FLOW_GRAPH_EXEC = Action( +FLOW_GRAPH_EXEC = actions.register("app.flowgraph.execute", label='_Execute', tooltip='Execute the flow graph', - stock_id=gtk.STOCK_MEDIA_PLAY, - keypresses=(gtk.keysyms.F6, NO_MODS_MASK), + icon_name='media-playback-start', + keypresses=["F6"], ) -FLOW_GRAPH_KILL = Action( +FLOW_GRAPH_KILL = actions.register("app.flowgraph.kill", label='_Kill', tooltip='Kill the flow graph', - stock_id=gtk.STOCK_STOP, - keypresses=(gtk.keysyms.F7, NO_MODS_MASK), + icon_name='media-playback-stop', + keypresses=["F7"], ) -FLOW_GRAPH_SCREEN_CAPTURE = Action( +FLOW_GRAPH_SCREEN_CAPTURE = actions.register("app.flowgraph.screen_capture", label='Screen Ca_pture', tooltip='Create a screen capture of the flow graph', - stock_id=gtk.STOCK_PRINT, - keypresses=(gtk.keysyms.Print, NO_MODS_MASK), -) -PORT_CONTROLLER_DEC = Action( - keypresses=(gtk.keysyms.minus, NO_MODS_MASK, gtk.keysyms.KP_Subtract, NO_MODS_MASK), -) -PORT_CONTROLLER_INC = Action( - keypresses=(gtk.keysyms.plus, NO_MODS_MASK, gtk.keysyms.KP_Add, NO_MODS_MASK), -) -BLOCK_INC_TYPE = Action( - keypresses=(gtk.keysyms.Down, NO_MODS_MASK), -) -BLOCK_DEC_TYPE = Action( - keypresses=(gtk.keysyms.Up, NO_MODS_MASK), -) -RELOAD_BLOCKS = Action( + icon_name='printer', + keypresses=["<Ctrl>p"], +) +PORT_CONTROLLER_DEC = actions.register("win.port_controller_dec") +PORT_CONTROLLER_INC = actions.register("win.port_controller_inc") +BLOCK_INC_TYPE = actions.register("win.block_inc_type") +BLOCK_DEC_TYPE = actions.register("win.block_dec_type") +RELOAD_BLOCKS = actions.register("app.reload_blocks", label='Reload _Blocks', tooltip='Reload Blocks', - stock_id=gtk.STOCK_REFRESH + icon_name='view-refresh' ) -FIND_BLOCKS = Action( +FIND_BLOCKS = actions.register("win.find_blocks", label='_Find Blocks', tooltip='Search for a block by name (and key)', - stock_id=gtk.STOCK_FIND, - keypresses=(gtk.keysyms.f, gtk.gdk.CONTROL_MASK, - gtk.keysyms.slash, NO_MODS_MASK), + icon_name='edit-find', + keypresses=["<Ctrl>f", "slash"], ) -CLEAR_CONSOLE = Action( +CLEAR_CONSOLE = actions.register("win.console.clear", label='_Clear Console', tooltip='Clear Console', - stock_id=gtk.STOCK_CLEAR, + icon_name='edit-clear', ) -SAVE_CONSOLE = Action( +SAVE_CONSOLE = actions.register("win.console.save", label='_Save Console', tooltip='Save Console', - stock_id=gtk.STOCK_SAVE, + icon_name='edit-save', ) -OPEN_HIER = Action( +OPEN_HIER = actions.register("win.open_hier", label='Open H_ier', tooltip='Open the source of the selected hierarchical block', - stock_id=gtk.STOCK_JUMP_TO, + icon_name='go-jump', ) -BUSSIFY_SOURCES = Action( +BUSSIFY_SOURCES = actions.register("win.bussify_sources", label='Toggle So_urce Bus', tooltip='Gang source ports into a single bus port', - stock_id=gtk.STOCK_JUMP_TO, + icon_name='go-jump', ) -BUSSIFY_SINKS = Action( +BUSSIFY_SINKS = actions.register("win.bussify_sinks", label='Toggle S_ink Bus', tooltip='Gang sink ports into a single bus port', - stock_id=gtk.STOCK_JUMP_TO, + icon_name='go-jump', ) -XML_PARSER_ERRORS_DISPLAY = Action( +XML_PARSER_ERRORS_DISPLAY = actions.register("app.xml_errors", label='_Parser Errors', tooltip='View errors that occurred while parsing XML files', - stock_id=gtk.STOCK_DIALOG_ERROR, + icon_name='dialog-error', ) -FLOW_GRAPH_OPEN_QSS_THEME = Action( +FLOW_GRAPH_OPEN_QSS_THEME = actions.register("app.open_qss_theme", label='Set Default QT GUI _Theme', tooltip='Set a default QT Style Sheet file to use for QT GUI', - stock_id=gtk.STOCK_OPEN, + icon_name='document-open', ) -TOOLS_RUN_FDESIGN = Action( +TOOLS_RUN_FDESIGN = actions.register("app.filter_design", label='Filter Design Tool', tooltip='Execute gr_filter_design', - stock_id=gtk.STOCK_EXECUTE, -) -TOOLS_MORE_TO_COME = Action( - label='More to come', + icon_name='media-playback-start', ) +POST_HANDLER = actions.register("app.post_handler") +READY = actions.register("app.ready") diff --git a/grc/gui/ActionHandler.py b/grc/gui/Application.py index 5d48485238..c1456c3a8d 100644 --- a/grc/gui/ActionHandler.py +++ b/grc/gui/Application.py @@ -18,33 +18,35 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import gobject -import gtk +from __future__ import absolute_import, print_function + import os import subprocess +import logging + +from gi.repository import Gtk, Gio, GLib, GObject -from . import Dialogs, Preferences, Actions, Executor, Constants, Utils -from .FileDialogs import (OpenFlowGraphFileDialog, SaveFlowGraphFileDialog, - SaveConsoleFileDialog, SaveScreenShotDialog, - OpenQSSFileDialog) +from . import Dialogs, Actions, Executor, FileDialogs, Utils, Bars from .MainWindow import MainWindow from .ParserErrorsDialog import ParserErrorsDialog from .PropsDialog import PropsDialog from ..core import ParseXML, Messages -gobject.threads_init() + +log = logging.getLogger(__name__) -class ActionHandler: +class Application(Gtk.Application): """ The action handler will setup all the major window components, and handle button presses and flow graph operations from the GUI. """ def __init__(self, file_paths, platform): + Gtk.Application.__init__(self) """ - ActionHandler constructor. + Application constructor. Create the main window, setup the message handler, import the preferences, and connect all of the action handlers. Finally, enter the gtk main loop and block. @@ -54,41 +56,57 @@ class ActionHandler: """ self.clipboard = None self.dialog = None - for action in Actions.get_all_actions(): action.connect('activate', self._handle_action) - #setup the main window + + # Setup the main window self.platform = platform - self.main_window = MainWindow(platform, self._handle_action) + self.config = platform.config + + log.debug("Application()") + # Connect all actions to _handle_action + for x in Actions.get_actions(): + Actions.connect(x, handler=self._handle_action) + Actions.actions[x].enable() + if x.startswith("app."): + self.add_action(Actions.actions[x]) + # Setup the shortcut keys + # These are the globally defined shortcuts + keypress = Actions.actions[x].keypresses + if keypress: + self.set_accels_for_action(x, keypress) + + # Initialize + self.init_file_paths = [os.path.abspath(file_path) for file_path in file_paths] + self.init = False + + def do_startup(self): + Gtk.Application.do_startup(self) + log.debug("Application.do_startup()") + + # Setup the menu + log.debug("Creating menu") + ''' + self.menu = Bars.Menu() + self.set_menu() + if self.prefers_app_menu(): + self.set_app_menu(self.menu) + else: + self.set_menubar(self.menu) + ''' + + def do_activate(self): + Gtk.Application.do_activate(self) + log.debug("Application.do_activate()") + + self.main_window = MainWindow(self, self.platform) self.main_window.connect('delete-event', self._quit) - self.main_window.connect('key-press-event', self._handle_key_press) - self.get_page = self.main_window.get_page self.get_focus_flag = self.main_window.get_focus_flag + #setup the messages Messages.register_messenger(self.main_window.add_console_line) - Messages.send_init(platform) - #initialize - self.init_file_paths = [os.path.abspath(file_path) for file_path in file_paths] - self.init = False - Actions.APPLICATION_INITIALIZE() + Messages.send_init(self.platform) - def _handle_key_press(self, widget, event): - """ - Handle key presses from the keyboard and translate key combinations into actions. - This key press handler is called prior to the gtk key press handler. - This handler bypasses built in accelerator key handling when in focus because - * some keys are ignored by the accelerators like the direction keys, - * some keys are not registered to any accelerators but are still used. - When not in focus, gtk and the accelerators handle the the key press. - - Returns: - false to let gtk handle the key action - """ - # prevent key event stealing while the search box is active - # .has_focus() only in newer versions 2.17+? - # .is_focus() seems to work, but exactly the same - if self.main_window.btwin.search_entry.flags() & gtk.HAS_FOCUS: - return False - if not self.get_focus_flag(): return False - return Actions.handle_key_press(event) + log.debug("Calling Actions.APPLICATION_INITIALIZE") + Actions.APPLICATION_INITIALIZE() def _quit(self, window, event): """ @@ -103,61 +121,111 @@ class ActionHandler: return True def _handle_action(self, action, *args): - #print action + log.debug("_handle_action({0}, {1})".format(action, args)) main = self.main_window - page = main.get_page() - flow_graph = page.get_flow_graph() if page else None + page = main.current_page + flow_graph = page.flow_graph if page else None def flow_graph_update(fg=flow_graph): - main.vars.update_gui() + main.vars.update_gui(fg.blocks) fg.update() ################################################## # Initialize/Quit ################################################## if action == Actions.APPLICATION_INITIALIZE: - file_path_to_show = Preferences.file_open() - for file_path in (self.init_file_paths or Preferences.get_open_files()): + log.debug("APPLICATION_INITIALIZE") + file_path_to_show = self.config.file_open() + for file_path in (self.init_file_paths or self.config.get_open_files()): if os.path.exists(file_path): main.new_page(file_path, show=file_path_to_show == file_path) - if not self.get_page(): + if not main.current_page: main.new_page() # ensure that at least a blank page exists main.btwin.search_entry.hide() - # Disable all actions, then re-enable a few - for action in Actions.get_all_actions(): - action.set_sensitive(False) # set all actions disabled + """ + Only disable certain actions on startup. Each of these actions are + conditionally enabled in _handle_action, so disable them first. + - FLOW_GRAPH_UNDO/REDO are set in gui/StateCache.py + - XML_PARSER_ERRORS_DISPLAY is set in RELOAD_BLOCKS + + TODO: These 4 should probably be included, but they are not currently + enabled anywhere else: + - PORT_CONTROLLER_DEC, PORT_CONTROLLER_INC + - BLOCK_INC_TYPE, BLOCK_DEC_TYPE + + TODO: These should be handled better. They are set in + update_exec_stop(), but not anywhere else + - FLOW_GRAPH_GEN, FLOW_GRAPH_EXEC, FLOW_GRAPH_KILL + """ + for action in ( + Actions.ERRORS_WINDOW_DISPLAY, + Actions.ELEMENT_DELETE, + Actions.BLOCK_PARAM_MODIFY, + Actions.BLOCK_ROTATE_CCW, + Actions.BLOCK_ROTATE_CW, + Actions.BLOCK_VALIGN_TOP, + Actions.BLOCK_VALIGN_MIDDLE, + Actions.BLOCK_VALIGN_BOTTOM, + Actions.BLOCK_HALIGN_LEFT, + Actions.BLOCK_HALIGN_CENTER, + Actions.BLOCK_HALIGN_RIGHT, + Actions.BLOCK_CUT, + Actions.BLOCK_COPY, + Actions.BLOCK_PASTE, + Actions.BLOCK_ENABLE, + Actions.BLOCK_DISABLE, + Actions.BLOCK_BYPASS, + Actions.BLOCK_CREATE_HIER, + Actions.OPEN_HIER, + Actions.BUSSIFY_SOURCES, + Actions.BUSSIFY_SINKS, + Actions.FLOW_GRAPH_SAVE, + Actions.FLOW_GRAPH_UNDO, + Actions.FLOW_GRAPH_REDO, + Actions.XML_PARSER_ERRORS_DISPLAY + ): + action.disable() + + # Load preferences for action in ( - Actions.APPLICATION_QUIT, Actions.FLOW_GRAPH_NEW, - Actions.FLOW_GRAPH_OPEN, Actions.FLOW_GRAPH_SAVE_AS, - Actions.FLOW_GRAPH_DUPLICATE, Actions.FLOW_GRAPH_SAVE_A_COPY, - Actions.FLOW_GRAPH_CLOSE, Actions.ABOUT_WINDOW_DISPLAY, - Actions.FLOW_GRAPH_SCREEN_CAPTURE, Actions.HELP_WINDOW_DISPLAY, - Actions.TYPES_WINDOW_DISPLAY, Actions.TOGGLE_BLOCKS_WINDOW, - Actions.TOGGLE_CONSOLE_WINDOW, Actions.TOGGLE_HIDE_DISABLED_BLOCKS, - Actions.TOOLS_RUN_FDESIGN, Actions.TOGGLE_SCROLL_LOCK, - Actions.CLEAR_CONSOLE, Actions.SAVE_CONSOLE, - Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, Actions.TOGGLE_SNAP_TO_GRID, + Actions.TOGGLE_BLOCKS_WINDOW, + Actions.TOGGLE_CONSOLE_WINDOW, + Actions.TOGGLE_HIDE_DISABLED_BLOCKS, + Actions.TOGGLE_SCROLL_LOCK, + Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, + Actions.TOGGLE_SNAP_TO_GRID, Actions.TOGGLE_SHOW_BLOCK_COMMENTS, Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB, Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY, - Actions.FLOW_GRAPH_OPEN_QSS_THEME, Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR, Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR_SIDEBAR, Actions.TOGGLE_HIDE_VARIABLES, - Actions.SELECT_ALL, ): - action.set_sensitive(True) + action.set_enabled(True) if hasattr(action, 'load_from_preferences'): action.load_from_preferences() + + # Hide the panels *IF* it's saved in preferences + main.update_panel_visibility(main.BLOCKS, Actions.TOGGLE_BLOCKS_WINDOW.get_active()) + main.update_panel_visibility(main.CONSOLE, Actions.TOGGLE_CONSOLE_WINDOW.get_active()) + main.update_panel_visibility(main.VARIABLES, Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR.get_active()) + if ParseXML.xml_failures: Messages.send_xml_errors_if_any(ParseXML.xml_failures) - Actions.XML_PARSER_ERRORS_DISPLAY.set_sensitive(True) + Actions.XML_PARSER_ERRORS_DISPLAY.set_enabled(True) + + # Force an update on the current page to match loaded preferences. + # In the future, change the __init__ order to load preferences first + page = main.current_page + if page: + page.flow_graph.update() + self.init = True elif action == Actions.APPLICATION_QUIT: if main.close_pages(): - gtk.main_quit() + Gtk.main_quit() exit(0) ################################################## # Selections @@ -171,21 +239,16 @@ class ActionHandler: ################################################## # Enable/Disable ################################################## - elif action == Actions.BLOCK_ENABLE: - if flow_graph.enable_selected(True): - flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) - elif action == Actions.BLOCK_DISABLE: - if flow_graph.enable_selected(False): - flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) - elif action == Actions.BLOCK_BYPASS: - if flow_graph.bypass_selected(): + elif action in (Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, Actions.BLOCK_BYPASS): + changed = flow_graph.change_state_selected(new_state={ + Actions.BLOCK_ENABLE: 'enabled', + Actions.BLOCK_DISABLE: 'disabled', + Actions.BLOCK_BYPASS: 'bypassed', + }[action]) + if changed: flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False ################################################## # Cut/Copy/Paste ################################################## @@ -198,15 +261,15 @@ class ActionHandler: if self.clipboard: flow_graph.paste_from_clipboard(self.clipboard) flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False ################################################## # Create heir block ################################################## elif action == Actions.BLOCK_CREATE_HIER: # keeping track of coordinates for pasting later - coords = flow_graph.get_selected_blocks()[0].get_coordinate() + coords = flow_graph.selected_blocks()[0].coordinate x,y = coords x_min = x y_min = y @@ -215,10 +278,10 @@ class ActionHandler: params = []; # Save the state of the leaf blocks - for block in flow_graph.get_selected_blocks(): + for block in flow_graph.selected_blocks(): # Check for string variables within the blocks - for param in block.get_params(): + for param in block.params.values(): for variable in flow_graph.get_variables(): # If a block parameter exists that is a variable, create a parameter for it if param.get_value() == variable.get_id(): @@ -230,7 +293,7 @@ class ActionHandler: # keep track of x,y mins for pasting later - (x,y) = block.get_coordinate() + (x,y) = block.coordinate if x < x_min: x_min = x if y < y_min: @@ -239,15 +302,15 @@ class ActionHandler: for connection in block.connections: # Get id of connected blocks - source_id = connection.get_source().get_parent().get_id() - sink_id = connection.get_sink().get_parent().get_id() + source_id = connection.source_block.get_id() + sink_id = connection.sink_block.get_id() # If connected block is not in the list of selected blocks create a pad for it - if flow_graph.get_block(source_id) not in flow_graph.get_selected_blocks(): - pads.append({'key': connection.get_sink().get_key(), 'coord': connection.get_source().get_coordinate(), 'block_id' : block.get_id(), 'direction': 'source'}) + if flow_graph.get_block(source_id) not in flow_graph.selected_blocks(): + pads.append({'key': connection.sink_port.key, 'coord': connection.source_port.coordinate, 'block_id' : block.get_id(), 'direction': 'source'}) - if flow_graph.get_block(sink_id) not in flow_graph.get_selected_blocks(): - pads.append({'key': connection.get_source().get_key(), 'coord': connection.get_sink().get_coordinate(), 'block_id' : block.get_id(), 'direction': 'sink'}) + if flow_graph.get_block(sink_id) not in flow_graph.selected_blocks(): + pads.append({'key': connection.source_port.key, 'coord': connection.sink_port.coordinate, 'block_id' : block.get_id(), 'direction': 'sink'}) # Copy the selected blocks and paste them into a new page @@ -288,7 +351,7 @@ class ActionHandler: # setup the references to the sink and source pad_block = flow_graph.get_block(pad_id) - pad_sink = pad_block.get_sinks()[0] + pad_sink = pad_block.sinks[0] source_block = flow_graph.get_block(pad['block_id']) source = source_block.get_source(pad['key']) @@ -309,7 +372,7 @@ class ActionHandler: # setup the references to the sink and source pad_block = flow_graph.get_block(pad_id) - pad_source = pad_block.get_sources()[0] + pad_source = pad_block.sources[0] sink_block = flow_graph.get_block(pad['block_id']) sink = sink_block.get_sink(pad['key']) @@ -332,162 +395,174 @@ class ActionHandler: # Move/Rotate/Delete/Create ################################################## elif action == Actions.BLOCK_MOVE: - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False elif action in Actions.BLOCK_ALIGNMENTS: if flow_graph.align_selected(action): - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False elif action == Actions.BLOCK_ROTATE_CCW: if flow_graph.rotate_selected(90): flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False elif action == Actions.BLOCK_ROTATE_CW: if flow_graph.rotate_selected(-90): flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False elif action == Actions.ELEMENT_DELETE: if flow_graph.remove_selected(): flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) + page.state_cache.save_new_state(flow_graph.export_data()) Actions.NOTHING_SELECT() - page.set_saved(False) + page.saved = False elif action == Actions.ELEMENT_CREATE: flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) + page.state_cache.save_new_state(flow_graph.export_data()) Actions.NOTHING_SELECT() - page.set_saved(False) + page.saved = False elif action == Actions.BLOCK_INC_TYPE: if flow_graph.type_controller_modify_selected(1): flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False elif action == Actions.BLOCK_DEC_TYPE: if flow_graph.type_controller_modify_selected(-1): flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False elif action == Actions.PORT_CONTROLLER_INC: if flow_graph.port_controller_modify_selected(1): flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False elif action == Actions.PORT_CONTROLLER_DEC: if flow_graph.port_controller_modify_selected(-1): flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False ################################################## # Window stuff ################################################## elif action == Actions.ABOUT_WINDOW_DISPLAY: - platform = flow_graph.get_parent() - Dialogs.AboutDialog(platform.config) + Dialogs.show_about(main, self.platform.config) elif action == Actions.HELP_WINDOW_DISPLAY: - Dialogs.HelpDialog() + Dialogs.show_help(main) elif action == Actions.TYPES_WINDOW_DISPLAY: - Dialogs.TypesDialog(flow_graph.get_parent()) + Dialogs.show_types(main) elif action == Actions.ERRORS_WINDOW_DISPLAY: - Dialogs.ErrorsDialog(flow_graph) + Dialogs.ErrorsDialog(main, flow_graph).run_and_destroy() elif action == Actions.TOGGLE_CONSOLE_WINDOW: + action.set_active(not action.get_active()) main.update_panel_visibility(main.CONSOLE, action.get_active()) action.save_to_preferences() elif action == Actions.TOGGLE_BLOCKS_WINDOW: + # This would be better matched to a Gio.PropertyAction, but to do + # this, actions would have to be defined in the window not globally + action.set_active(not action.get_active()) main.update_panel_visibility(main.BLOCKS, action.get_active()) action.save_to_preferences() elif action == Actions.TOGGLE_SCROLL_LOCK: + action.set_active(not action.get_active()) active = action.get_active() - main.text_display.scroll_lock = active + main.console.text_display.scroll_lock = active if active: - main.text_display.scroll_to_end() + main.console.text_display.scroll_to_end() action.save_to_preferences() elif action == Actions.CLEAR_CONSOLE: - main.text_display.clear() + main.console.text_display.clear() elif action == Actions.SAVE_CONSOLE: - file_path = SaveConsoleFileDialog(page.get_file_path()).run() + file_path = FileDialogs.SaveConsole(main, page.file_path).run() if file_path is not None: - main.text_display.save(file_path) + main.console.text_display.save(file_path) elif action == Actions.TOGGLE_HIDE_DISABLED_BLOCKS: + action.set_active(not action.get_active()) Actions.NOTHING_SELECT() elif action == Actions.TOGGLE_AUTO_HIDE_PORT_LABELS: + action.set_active(not action.get_active()) action.save_to_preferences() for page in main.get_pages(): - page.get_flow_graph().create_shapes() + page.flow_graph.create_shapes() elif action in (Actions.TOGGLE_SNAP_TO_GRID, Actions.TOGGLE_SHOW_BLOCK_COMMENTS, Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB): + action.set_active(not action.get_active()) action.save_to_preferences() elif action == Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY: + action.set_active(not action.get_active()) action.save_to_preferences() for page in main.get_pages(): - flow_graph_update(page.get_flow_graph()) + flow_graph_update(page.flow_graph) elif action == Actions.TOGGLE_HIDE_VARIABLES: - # Call the variable editor TOGGLE in case it needs to be showing - Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR() + action.set_active(not action.get_active()) + active = action.get_active() + # Either way, triggering this should simply trigger the variable editor + # to be visible. + varedit = Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR + if active: + log.debug("Variables are hidden. Forcing the variable panel to be visible.") + varedit.disable() + else: + varedit.enable() + # Just force it to show. + varedit.set_active(True) + main.update_panel_visibility(main.VARIABLES) Actions.NOTHING_SELECT() action.save_to_preferences() + varedit.save_to_preferences() + flow_graph_update() elif action == Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR: - # See if the variables are hidden - if Actions.TOGGLE_HIDE_VARIABLES.get_active(): - # Force this to be shown - main.update_panel_visibility(main.VARIABLES, True) - action.set_active(True) - action.set_sensitive(False) - else: - if action.get_sensitive(): - main.update_panel_visibility(main.VARIABLES, action.get_active()) - else: # This is occurring after variables are un-hidden - # Leave it enabled - action.set_sensitive(True) - action.set_active(True) - #Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR_SIDEBAR.set_sensitive(action.get_active()) + # TODO: There may be issues at startup since these aren't triggered + # the same was as Gtk.Actions when loading preferences. + action.set_active(not action.get_active()) + # Just assume this was triggered because it was enabled. + main.update_panel_visibility(main.VARIABLES, action.get_active()) + action.save_to_preferences() + + # Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR_SIDEBAR.set_enabled(action.get_active()) action.save_to_preferences() elif action == Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR_SIDEBAR: + action.set_active(not action.get_active()) if self.init: - md = gtk.MessageDialog(main, - gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_INFO, - gtk.BUTTONS_CLOSE, "Moving the variable editor requires a restart of GRC.") - md.run() - md.destroy() + Dialogs.MessageDialogWrapper( + main, Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, + markup="Moving the variable editor requires a restart of GRC." + ).run_and_destroy() action.save_to_preferences() ################################################## # Param Modifications ################################################## elif action == Actions.BLOCK_PARAM_MODIFY: - if action.args: - selected_block = action.args[0] - else: - selected_block = flow_graph.get_selected_block() + selected_block = args[0] if args[0] else flow_graph.selected_block if selected_block: - self.dialog = PropsDialog(selected_block) - response = gtk.RESPONSE_APPLY - while response == gtk.RESPONSE_APPLY: # rerun the dialog if Apply was hit + self.dialog = PropsDialog(self.main_window, selected_block) + response = Gtk.ResponseType.APPLY + while response == Gtk.ResponseType.APPLY: # rerun the dialog if Apply was hit response = self.dialog.run() - if response in (gtk.RESPONSE_APPLY, gtk.RESPONSE_ACCEPT): + if response in (Gtk.ResponseType.APPLY, Gtk.ResponseType.ACCEPT): flow_graph_update() - page.get_state_cache().save_new_state(flow_graph.export_data()) - page.set_saved(False) + page.state_cache.save_new_state(flow_graph.export_data()) + page.saved = False else: # restore the current state - n = page.get_state_cache().get_current_state() + n = page.state_cache.get_current_state() flow_graph.import_data(n) flow_graph_update() - if response == gtk.RESPONSE_APPLY: + if response == Gtk.ResponseType.APPLY: # null action, that updates the main window Actions.ELEMENT_SELECT() self.dialog.destroy() self.dialog = None elif action == Actions.EXTERNAL_UPDATE: - page.get_state_cache().save_new_state(flow_graph.export_data()) + page.state_cache.save_new_state(flow_graph.export_data()) flow_graph_update() if self.dialog is not None: self.dialog.update_gui(force=True) - page.set_saved(False) + page.saved = False elif action == Actions.VARIABLE_EDITOR_UPDATE: - page.get_state_cache().save_new_state(flow_graph.export_data()) + page.state_cache.save_new_state(flow_graph.export_data()) flow_graph_update() - page.set_saved(False) + page.saved = False ################################################## # View Parser Errors ################################################## @@ -497,144 +572,144 @@ class ActionHandler: # Undo/Redo ################################################## elif action == Actions.FLOW_GRAPH_UNDO: - n = page.get_state_cache().get_prev_state() + n = page.state_cache.get_prev_state() if n: flow_graph.unselect() flow_graph.import_data(n) flow_graph_update() - page.set_saved(False) + page.saved = False elif action == Actions.FLOW_GRAPH_REDO: - n = page.get_state_cache().get_next_state() + n = page.state_cache.get_next_state() if n: flow_graph.unselect() flow_graph.import_data(n) flow_graph_update() - page.set_saved(False) + page.saved = False ################################################## # New/Open/Save/Close ################################################## elif action == Actions.FLOW_GRAPH_NEW: main.new_page() if args: - flow_graph = main.get_flow_graph() + flow_graph = main.current_page.flow_graph flow_graph._options_block.get_param('generate_options').set_value(args[0]) flow_graph_update(flow_graph) elif action == Actions.FLOW_GRAPH_OPEN: - file_paths = args if args else OpenFlowGraphFileDialog(page.get_file_path()).run() - if file_paths: #open a new page for each file, show only the first + file_paths = args[0] if args[0] else FileDialogs.OpenFlowGraph(main, page.file_path).run() + if file_paths: # Open a new page for each file, show only the first for i,file_path in enumerate(file_paths): main.new_page(file_path, show=(i==0)) - Preferences.add_recent_file(file_path) + self.config.add_recent_file(file_path) main.tool_bar.refresh_submenus() - main.menu_bar.refresh_submenus() - main.vars.update_gui() - + #main.menu_bar.refresh_submenus() elif action == Actions.FLOW_GRAPH_OPEN_QSS_THEME: - file_paths = OpenQSSFileDialog(self.platform.config.install_prefix + - '/share/gnuradio/themes/').run() + file_paths = FileDialogs.OpenQSS(main, self.platform.config.install_prefix + + '/share/gnuradio/themes/').run() if file_paths: - try: - prefs = self.platform.config.prefs - prefs.set_string("qtgui", "qss", file_paths[0]) - prefs.save() - except Exception as e: - Messages.send("Failed to save QSS preference: " + str(e)) + self.platform.config.default_qss_theme = file_paths[0] elif action == Actions.FLOW_GRAPH_CLOSE: main.close_page() elif action == Actions.FLOW_GRAPH_SAVE: #read-only or undefined file path, do save-as - if page.get_read_only() or not page.get_file_path(): + if page.get_read_only() or not page.file_path: Actions.FLOW_GRAPH_SAVE_AS() #otherwise try to save else: try: - ParseXML.to_file(flow_graph.export_data(), page.get_file_path()) - flow_graph.grc_file_path = page.get_file_path() - page.set_saved(True) + ParseXML.to_file(flow_graph.export_data(), page.file_path) + flow_graph.grc_file_path = page.file_path + page.saved = True except IOError: - Messages.send_fail_save(page.get_file_path()) - page.set_saved(False) + Messages.send_fail_save(page.file_path) + page.saved = False elif action == Actions.FLOW_GRAPH_SAVE_AS: - file_path = SaveFlowGraphFileDialog(page.get_file_path()).run() + file_path = FileDialogs.SaveFlowGraph(main, page.file_path).run() if file_path is not None: - page.set_file_path(file_path) + page.file_path = os.path.abspath(file_path) Actions.FLOW_GRAPH_SAVE() - Preferences.add_recent_file(file_path) + self.config.add_recent_file(file_path) main.tool_bar.refresh_submenus() - main.menu_bar.refresh_submenus() - elif action == Actions.FLOW_GRAPH_SAVE_A_COPY: + #TODO + #main.menu_bar.refresh_submenus() + elif action == Actions.FLOW_GRAPH_SAVE_COPY: try: - if not page.get_file_path(): + if not page.file_path: + # Make sure the current flowgraph has been saved Actions.FLOW_GRAPH_SAVE_AS() else: - dup_file_path = page.get_file_path() + dup_file_path = page.file_path dup_file_name = '.'.join(dup_file_path.split('.')[:-1]) + "_copy" # Assuming .grc extension at the end of file_path dup_file_path_temp = dup_file_name+'.grc' count = 1 while os.path.exists(dup_file_path_temp): dup_file_path_temp = dup_file_name+'('+str(count)+').grc' count += 1 - dup_file_path_user = SaveFlowGraphFileDialog(dup_file_path_temp).run() + dup_file_path_user = FileDialogs.SaveFlowGraph(main, dup_file_path_temp).run() if dup_file_path_user is not None: ParseXML.to_file(flow_graph.export_data(), dup_file_path_user) Messages.send('Saved Copy to: "' + dup_file_path_user + '"\n') except IOError: Messages.send_fail_save("Can not create a copy of the flowgraph\n") elif action == Actions.FLOW_GRAPH_DUPLICATE: - flow_graph = main.get_flow_graph() + previous = flow_graph + # Create a new page main.new_page() - curr_page = main.get_page() - new_flow_graph = main.get_flow_graph() - new_flow_graph.import_data(flow_graph.export_data()) + page = main.current_page + new_flow_graph = page.flow_graph + # Import the old data and mark the current as not saved + new_flow_graph.import_data(previous.export_data()) flow_graph_update(new_flow_graph) - curr_page.set_saved(False) + page.saved = False elif action == Actions.FLOW_GRAPH_SCREEN_CAPTURE: - file_path, background_transparent = SaveScreenShotDialog(page.get_file_path()).run() + file_path, background_transparent = FileDialogs.SaveScreenShot(main, page.file_path).run() if file_path is not None: - pixbuf = flow_graph.get_drawing_area().get_screenshot(background_transparent) - pixbuf.save(file_path, Constants.IMAGE_FILE_EXTENSION[1:]) + try: + Utils.make_screenshot(flow_graph, file_path, background_transparent) + except ValueError: + Messages.send('Failed to generate screen shot\n') ################################################## # Gen/Exec/Stop ################################################## elif action == Actions.FLOW_GRAPH_GEN: - if not page.get_proc(): - if not page.get_saved() or not page.get_file_path(): - Actions.FLOW_GRAPH_SAVE() #only save if file path missing or not saved - if page.get_saved() and page.get_file_path(): + if not page.process: + if not page.saved or not page.file_path: + Actions.FLOW_GRAPH_SAVE() # only save if file path missing or not saved + if page.saved and page.file_path: generator = page.get_generator() try: - Messages.send_start_gen(generator.get_file_path()) + Messages.send_start_gen(generator.file_path) generator.write() except Exception as e: Messages.send_fail_gen(e) else: self.generator = None elif action == Actions.FLOW_GRAPH_EXEC: - if not page.get_proc(): + if not page.process: Actions.FLOW_GRAPH_GEN() xterm = self.platform.config.xterm_executable - if Preferences.xterm_missing() != xterm: + Dialogs.show_missing_xterm(main, xterm) + if self.config.xterm_missing() != xterm: if not os.path.exists(xterm): - Dialogs.MissingXTermDialog(xterm) - Preferences.xterm_missing(xterm) - if page.get_saved() and page.get_file_path(): + Dialogs.show_missing_xterm(main, xterm) + self.config.xterm_missing(xterm) + if page.saved and page.file_path: Executor.ExecFlowGraphThread( flow_graph_page=page, xterm_executable=xterm, callback=self.update_exec_stop ) elif action == Actions.FLOW_GRAPH_KILL: - if page.get_proc(): + if page.process: try: - page.get_proc().kill() + page.process.kill() except: - print "could not kill process: %d" % page.get_proc().pid + print("could not kill process: %d" % page.process.pid) elif action == Actions.PAGE_CHANGE: # pass and run the global actions pass elif action == Actions.RELOAD_BLOCKS: self.platform.build_block_library() main.btwin.repopulate() - Actions.XML_PARSER_ERRORS_DISPLAY.set_sensitive(bool( + Actions.XML_PARSER_ERRORS_DISPLAY.set_enabled(bool( ParseXML.xml_failures)) Messages.send_xml_errors_if_any(ParseXML.xml_failures) # Force a redraw of the graph, by getting the current state and re-importing it @@ -645,21 +720,19 @@ class ActionHandler: main.btwin.search_entry.show() main.btwin.search_entry.grab_focus() elif action == Actions.OPEN_HIER: - for b in flow_graph.get_selected_blocks(): + for b in flow_graph.selected_blocks(): if b._grc_source: main.new_page(b._grc_source, show=True) elif action == Actions.BUSSIFY_SOURCES: - n = {'name':'bus', 'type':'bus'} - for b in flow_graph.get_selected_blocks(): - b.bussify(n, 'source') + for b in flow_graph.selected_blocks(): + b.bussify('source') flow_graph._old_selected_port = None flow_graph._new_selected_port = None Actions.ELEMENT_CREATE() elif action == Actions.BUSSIFY_SINKS: - n = {'name':'bus', 'type':'bus'} - for b in flow_graph.get_selected_blocks(): - b.bussify(n, 'sink') + for b in flow_graph.selected_blocks(): + b.bussify('sink') flow_graph._old_selected_port = None flow_graph._new_selected_port = None Actions.ELEMENT_CREATE() @@ -669,71 +742,67 @@ class ActionHandler: shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) else: - print '!!! Action "%s" not handled !!!' % action + log.warning('!!! Action "%s" not handled !!!' % action) ################################################## # Global Actions for all States ################################################## - page = main.get_page() # page and flowgraph might have changed - flow_graph = page.get_flow_graph() if page else None + page = main.current_page # page and flow graph might have changed + flow_graph = page.flow_graph if page else None - selected_blocks = flow_graph.get_selected_blocks() + selected_blocks = list(flow_graph.selected_blocks()) selected_block = selected_blocks[0] if selected_blocks else None #update general buttons - Actions.ERRORS_WINDOW_DISPLAY.set_sensitive(not flow_graph.is_valid()) - Actions.ELEMENT_DELETE.set_sensitive(bool(flow_graph.get_selected_elements())) - Actions.BLOCK_PARAM_MODIFY.set_sensitive(bool(selected_block)) - Actions.BLOCK_ROTATE_CCW.set_sensitive(bool(selected_blocks)) - Actions.BLOCK_ROTATE_CW.set_sensitive(bool(selected_blocks)) + Actions.ERRORS_WINDOW_DISPLAY.set_enabled(not flow_graph.is_valid()) + Actions.ELEMENT_DELETE.set_enabled(bool(flow_graph.selected_elements)) + Actions.BLOCK_PARAM_MODIFY.set_enabled(bool(selected_block)) + Actions.BLOCK_ROTATE_CCW.set_enabled(bool(selected_blocks)) + Actions.BLOCK_ROTATE_CW.set_enabled(bool(selected_blocks)) #update alignment options for act in Actions.BLOCK_ALIGNMENTS: if act: - act.set_sensitive(len(selected_blocks) > 1) + act.set_enabled(len(selected_blocks) > 1) #update cut/copy/paste - Actions.BLOCK_CUT.set_sensitive(bool(selected_blocks)) - Actions.BLOCK_COPY.set_sensitive(bool(selected_blocks)) - Actions.BLOCK_PASTE.set_sensitive(bool(self.clipboard)) + Actions.BLOCK_CUT.set_enabled(bool(selected_blocks)) + Actions.BLOCK_COPY.set_enabled(bool(selected_blocks)) + Actions.BLOCK_PASTE.set_enabled(bool(self.clipboard)) #update enable/disable/bypass - can_enable = any(block.get_state() != Constants.BLOCK_ENABLED + can_enable = any(block.state != 'enabled' for block in selected_blocks) - can_disable = any(block.get_state() != Constants.BLOCK_DISABLED + can_disable = any(block.state != 'disabled' for block in selected_blocks) - can_bypass_all = all(block.can_bypass() for block in selected_blocks) \ - and any (not block.get_bypassed() for block in selected_blocks) - Actions.BLOCK_ENABLE.set_sensitive(can_enable) - Actions.BLOCK_DISABLE.set_sensitive(can_disable) - Actions.BLOCK_BYPASS.set_sensitive(can_bypass_all) - - Actions.BLOCK_CREATE_HIER.set_sensitive(bool(selected_blocks)) - Actions.OPEN_HIER.set_sensitive(bool(selected_blocks)) - Actions.BUSSIFY_SOURCES.set_sensitive(bool(selected_blocks)) - Actions.BUSSIFY_SINKS.set_sensitive(bool(selected_blocks)) - Actions.RELOAD_BLOCKS.set_sensitive(True) - Actions.FIND_BLOCKS.set_sensitive(True) - #set the exec and stop buttons + can_bypass_all = ( + all(block.can_bypass() for block in selected_blocks) and + any(not block.get_bypassed() for block in selected_blocks) + ) + Actions.BLOCK_ENABLE.set_enabled(can_enable) + Actions.BLOCK_DISABLE.set_enabled(can_disable) + Actions.BLOCK_BYPASS.set_enabled(can_bypass_all) + + Actions.BLOCK_CREATE_HIER.set_enabled(bool(selected_blocks)) + Actions.OPEN_HIER.set_enabled(bool(selected_blocks)) + Actions.BUSSIFY_SOURCES.set_enabled(bool(selected_blocks)) + Actions.BUSSIFY_SINKS.set_enabled(bool(selected_blocks)) + Actions.RELOAD_BLOCKS.enable() + Actions.FIND_BLOCKS.enable() + self.update_exec_stop() - #saved status - Actions.FLOW_GRAPH_SAVE.set_sensitive(not page.get_saved()) + + Actions.FLOW_GRAPH_SAVE.set_enabled(not page.saved) main.update() - try: #set the size of the flow graph area (if changed) - new_size = Utils.scale( - flow_graph.get_option('window_size') or - self.platform.config.default_canvas_size - ) - if flow_graph.get_size() != tuple(new_size): - flow_graph.set_size(*new_size) - except: pass - #draw the flow graph + flow_graph.update_selected() - flow_graph.queue_draw() - return True #action was handled + page.drawing_area.queue_draw() + + return True # Action was handled def update_exec_stop(self): """ Update the exec and stop buttons. Lock and unlock the mutex for race conditions with exec flow graph threads. """ - sensitive = self.main_window.get_flow_graph().is_valid() and not self.get_page().get_proc() - Actions.FLOW_GRAPH_GEN.set_sensitive(sensitive) - Actions.FLOW_GRAPH_EXEC.set_sensitive(sensitive) - Actions.FLOW_GRAPH_KILL.set_sensitive(self.get_page().get_proc() is not None) + page = self.main_window.current_page + sensitive = page.flow_graph.is_valid() and not page.process + Actions.FLOW_GRAPH_GEN.set_enabled(sensitive) + Actions.FLOW_GRAPH_EXEC.set_enabled(sensitive) + Actions.FLOW_GRAPH_KILL.set_enabled(page.process is not None) diff --git a/grc/gui/Bars.py b/grc/gui/Bars.py index d9bc2aedb7..2a8040f5d5 100644 --- a/grc/gui/Bars.py +++ b/grc/gui/Bars.py @@ -1,5 +1,5 @@ """ -Copyright 2007, 2008, 2009, 2015 Free Software Foundation, Inc. +Copyright 2007, 2008, 2009, 2015, 2016 Free Software Foundation, Inc. This file is part of GNU Radio GNU Radio Companion is free software; you can redistribute it and/or @@ -17,304 +17,301 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import pygtk -pygtk.require('2.0') -import gtk +from __future__ import absolute_import + +import logging + +from gi.repository import Gtk, GObject, Gio, GLib from . import Actions +log = logging.getLogger(__name__) + + +''' +# Menu/Toolbar Lists: +# +# Sub items can be 1 of 3 types +# - List Creates a section within the current menu +# - Tuple Creates a submenu using a string or action as the parent. The child +# can be another menu list or an identifier used to call a helper function. +# - Action Appends a new menu item to the current menu +# + +LIST_NAME = [ + [Action1, Action2], # New section + (Action3, [Action4, Action5]), # Submenu with action as parent + ("Label", [Action6, Action7]), # Submenu with string as parent + ("Label2", "helper") # Submenu with helper function. Calls 'create_helper()' +] +''' + + # The list of actions for the toolbar. -TOOLBAR_LIST = ( - (Actions.FLOW_GRAPH_NEW, 'flow_graph_new'), - (Actions.FLOW_GRAPH_OPEN, 'flow_graph_recent'), - Actions.FLOW_GRAPH_SAVE, - Actions.FLOW_GRAPH_CLOSE, - None, - Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR, - Actions.FLOW_GRAPH_SCREEN_CAPTURE, - None, - Actions.BLOCK_CUT, - Actions.BLOCK_COPY, - Actions.BLOCK_PASTE, - Actions.ELEMENT_DELETE, - None, - Actions.FLOW_GRAPH_UNDO, - Actions.FLOW_GRAPH_REDO, - None, - Actions.ERRORS_WINDOW_DISPLAY, - Actions.FLOW_GRAPH_GEN, - Actions.FLOW_GRAPH_EXEC, - Actions.FLOW_GRAPH_KILL, - None, - Actions.BLOCK_ROTATE_CCW, - Actions.BLOCK_ROTATE_CW, - None, - Actions.BLOCK_ENABLE, - Actions.BLOCK_DISABLE, - Actions.BLOCK_BYPASS, - Actions.TOGGLE_HIDE_DISABLED_BLOCKS, - None, - Actions.FIND_BLOCKS, - Actions.RELOAD_BLOCKS, - Actions.OPEN_HIER, -) +TOOLBAR_LIST = [ + [(Actions.FLOW_GRAPH_NEW, 'flow_graph_new'), Actions.FLOW_GRAPH_OPEN, + (Actions.FLOW_GRAPH_OPEN_RECENT, 'flow_graph_recent'), Actions.FLOW_GRAPH_SAVE, Actions.FLOW_GRAPH_CLOSE], + [Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR, Actions.FLOW_GRAPH_SCREEN_CAPTURE], + [Actions.BLOCK_CUT, Actions.BLOCK_COPY, Actions.BLOCK_PASTE, Actions.ELEMENT_DELETE], + [Actions.FLOW_GRAPH_UNDO, Actions.FLOW_GRAPH_REDO], + [Actions.ERRORS_WINDOW_DISPLAY, Actions.FLOW_GRAPH_GEN, Actions.FLOW_GRAPH_EXEC, Actions.FLOW_GRAPH_KILL], + [Actions.BLOCK_ROTATE_CCW, Actions.BLOCK_ROTATE_CW], + [Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, Actions.BLOCK_BYPASS, Actions.TOGGLE_HIDE_DISABLED_BLOCKS], + [Actions.FIND_BLOCKS, Actions.RELOAD_BLOCKS, Actions.OPEN_HIER] +] + # The list of actions and categories for the menu bar. -MENU_BAR_LIST = ( - (gtk.Action('File', '_File', None, None), [ - 'flow_graph_new', - Actions.FLOW_GRAPH_DUPLICATE, - Actions.FLOW_GRAPH_OPEN, - 'flow_graph_recent', - None, - Actions.FLOW_GRAPH_SAVE, - Actions.FLOW_GRAPH_SAVE_AS, - Actions.FLOW_GRAPH_SAVE_A_COPY, - None, - Actions.FLOW_GRAPH_SCREEN_CAPTURE, - None, - Actions.FLOW_GRAPH_CLOSE, - Actions.APPLICATION_QUIT, - ]), - (gtk.Action('Edit', '_Edit', None, None), [ - Actions.FLOW_GRAPH_UNDO, - Actions.FLOW_GRAPH_REDO, - None, - Actions.BLOCK_CUT, - Actions.BLOCK_COPY, - Actions.BLOCK_PASTE, - Actions.ELEMENT_DELETE, - Actions.SELECT_ALL, - None, - Actions.BLOCK_ROTATE_CCW, - Actions.BLOCK_ROTATE_CW, - (gtk.Action('Align', '_Align', None, None), Actions.BLOCK_ALIGNMENTS), - None, - Actions.BLOCK_ENABLE, - Actions.BLOCK_DISABLE, - Actions.BLOCK_BYPASS, - None, - Actions.BLOCK_PARAM_MODIFY, - ]), - (gtk.Action('View', '_View', None, None), [ - Actions.TOGGLE_BLOCKS_WINDOW, - None, - Actions.TOGGLE_CONSOLE_WINDOW, - Actions.TOGGLE_SCROLL_LOCK, - Actions.SAVE_CONSOLE, - Actions.CLEAR_CONSOLE, - None, - Actions.TOGGLE_HIDE_VARIABLES, - Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR, - Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR_SIDEBAR, - None, - Actions.TOGGLE_HIDE_DISABLED_BLOCKS, - Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, - Actions.TOGGLE_SNAP_TO_GRID, - Actions.TOGGLE_SHOW_BLOCK_COMMENTS, - None, - Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB, - None, - Actions.ERRORS_WINDOW_DISPLAY, - Actions.FIND_BLOCKS, - ]), - (gtk.Action('Run', '_Run', None, None), [ - Actions.FLOW_GRAPH_GEN, - Actions.FLOW_GRAPH_EXEC, - Actions.FLOW_GRAPH_KILL, - ]), - (gtk.Action('Tools', '_Tools', None, None), [ - Actions.TOOLS_RUN_FDESIGN, - Actions.FLOW_GRAPH_OPEN_QSS_THEME, - None, - Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY, - None, - Actions.TOOLS_MORE_TO_COME, - ]), - (gtk.Action('Help', '_Help', None, None), [ - Actions.HELP_WINDOW_DISPLAY, - Actions.TYPES_WINDOW_DISPLAY, - Actions.XML_PARSER_ERRORS_DISPLAY, - None, - Actions.ABOUT_WINDOW_DISPLAY, - ]), -) +MENU_BAR_LIST = [ + ('_File', [ + [(Actions.FLOW_GRAPH_NEW, 'flow_graph_new'), Actions.FLOW_GRAPH_DUPLICATE, + Actions.FLOW_GRAPH_OPEN, (Actions.FLOW_GRAPH_OPEN_RECENT, 'flow_graph_recent')], + [Actions.FLOW_GRAPH_SAVE, Actions.FLOW_GRAPH_SAVE_AS, Actions.FLOW_GRAPH_SAVE_COPY], + [Actions.FLOW_GRAPH_SCREEN_CAPTURE], + [Actions.FLOW_GRAPH_CLOSE, Actions.APPLICATION_QUIT] + ]), + ('_Edit', [ + [Actions.FLOW_GRAPH_UNDO, Actions.FLOW_GRAPH_REDO], + [Actions.BLOCK_CUT, Actions.BLOCK_COPY, Actions.BLOCK_PASTE, Actions.ELEMENT_DELETE, Actions.SELECT_ALL], + [Actions.BLOCK_ROTATE_CCW, Actions.BLOCK_ROTATE_CW, ('_Align', Actions.BLOCK_ALIGNMENTS)], + [Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, Actions.BLOCK_BYPASS], + [Actions.BLOCK_PARAM_MODIFY] + ]), + ('_View', [ + [Actions.TOGGLE_BLOCKS_WINDOW], + [Actions.TOGGLE_CONSOLE_WINDOW, Actions.TOGGLE_SCROLL_LOCK, Actions.SAVE_CONSOLE, Actions.CLEAR_CONSOLE], + [Actions.TOGGLE_HIDE_VARIABLES, Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR, Actions.TOGGLE_FLOW_GRAPH_VAR_EDITOR_SIDEBAR], + [Actions.TOGGLE_HIDE_DISABLED_BLOCKS, Actions.TOGGLE_AUTO_HIDE_PORT_LABELS, Actions.TOGGLE_SNAP_TO_GRID, Actions.TOGGLE_SHOW_BLOCK_COMMENTS], + [Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB], + [Actions.ERRORS_WINDOW_DISPLAY, Actions.FIND_BLOCKS], + ]), + ('_Run', [ + Actions.FLOW_GRAPH_GEN, Actions.FLOW_GRAPH_EXEC, Actions.FLOW_GRAPH_KILL + ]), + ('_Tools', [ + [Actions.TOOLS_RUN_FDESIGN, Actions.FLOW_GRAPH_OPEN_QSS_THEME], + [Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY] + ]), + ('_Help', [ + [Actions.HELP_WINDOW_DISPLAY, Actions.TYPES_WINDOW_DISPLAY, Actions.XML_PARSER_ERRORS_DISPLAY], + [Actions.ABOUT_WINDOW_DISPLAY] + ])] + # The list of actions for the context menu. CONTEXT_MENU_LIST = [ - Actions.BLOCK_CUT, - Actions.BLOCK_COPY, - Actions.BLOCK_PASTE, - Actions.ELEMENT_DELETE, - None, - Actions.BLOCK_ROTATE_CCW, - Actions.BLOCK_ROTATE_CW, - Actions.BLOCK_ENABLE, - Actions.BLOCK_DISABLE, - Actions.BLOCK_BYPASS, - None, - (gtk.Action('More', '_More', None, None), [ - Actions.BLOCK_CREATE_HIER, - Actions.OPEN_HIER, - None, - Actions.BUSSIFY_SOURCES, - Actions.BUSSIFY_SINKS, - ]), - Actions.BLOCK_PARAM_MODIFY + [Actions.BLOCK_CUT, Actions.BLOCK_COPY, Actions.BLOCK_PASTE, Actions.ELEMENT_DELETE], + [Actions.BLOCK_ROTATE_CCW, Actions.BLOCK_ROTATE_CW, Actions.BLOCK_ENABLE, Actions.BLOCK_DISABLE, Actions.BLOCK_BYPASS], + [("_More", [ + [Actions.BLOCK_CREATE_HIER, Actions.OPEN_HIER], + [Actions.BUSSIFY_SOURCES, Actions.BUSSIFY_SINKS]] + )], + [Actions.BLOCK_PARAM_MODIFY], ] -class SubMenuCreator(object): +class SubMenuHelper(object): + ''' Generates custom submenus for the main menu or toolbar. ''' - def __init__(self, generate_modes, action_handler_callback): - self.generate_modes = generate_modes - self.action_handler_callback = action_handler_callback - self.submenus = [] + def __init__(self): + self.submenus = {} - def create_submenu(self, action_tuple, item): - func = getattr(self, '_fill_' + action_tuple[1] + "_submenu") - self.submenus.append((action_tuple[0], func, item)) - self.refresh_submenus() + def build_submenu(self, name, obj, set_func): + # Get the correct helper function + create_func = getattr(self, "create_{}".format(name)) + # Save the helper functions for rebuilding the menu later + self.submenus[name] = (create_func, obj, set_func) + # Actually build the menu + set_func(obj, create_func()) def refresh_submenus(self): - for action, func, item in self.submenus: - try: - item.set_property("menu", func(action)) - except TypeError: - item.set_property("submenu", func(action)) - item.set_property('sensitive', True) - - def callback_adaptor(self, item, action_key): - action, key = action_key - self.action_handler_callback(action, key) - - def _fill_flow_graph_new_submenu(self, action): - """Sub menu to create flow-graph with pre-set generate mode""" - menu = gtk.Menu() - for key, name, default in self.generate_modes: - if default: - item = Actions.FLOW_GRAPH_NEW.create_menu_item() - item.set_label(name) - else: - item = gtk.MenuItem(name, use_underline=False) - item.connect('activate', self.callback_adaptor, (action, key)) - menu.append(item) - menu.show_all() + for name in self.submenus: + create_func, obj, set_func = self.submenus[name] + print ("refresh", create_func, obj, set_func) + set_func(obj, create_func()) + + def create_flow_graph_new(self): + """ Different flowgraph types """ + menu = Gio.Menu() + platform = Gtk.Application.get_default().platform + generate_modes = platform.get_generate_options() + for key, name, default in generate_modes: + target = "app.flowgraph.new::{}".format(key) + menu.append(name, target) return menu - def _fill_flow_graph_recent_submenu(self, action): - """menu showing recent flow-graphs""" - import Preferences - menu = gtk.Menu() - recent_files = Preferences.get_recent_files() + def create_flow_graph_recent(self): + """ Recent flow graphs """ + + config = Gtk.Application.get_default().config + recent_files = config.get_recent_files() + menu = Gio.Menu() if len(recent_files) > 0: + files = Gio.Menu() for i, file_name in enumerate(recent_files): - item = gtk.MenuItem("%d. %s" % (i+1, file_name), use_underline=False) - item.connect('activate', self.callback_adaptor, - (action, file_name)) - menu.append(item) - menu.show_all() - return menu - return None + target = "app.flowgraph.open_recent::{}".format(file_name) + files.append(file_name, target) + menu.append_section(None, files) + #clear = Gio.Menu() + #clear.append("Clear recent files", "app.flowgraph.clear_recent") + #menu.append_section(None, clear) + else: + # Show an empty menu + menuitem = Gio.MenuItem.new("No items found", "app.none") + menu.append_item(menuitem) + return menu -class Toolbar(gtk.Toolbar, SubMenuCreator): - """The gtk toolbar with actions added from the toolbar list.""" +class MenuHelper(SubMenuHelper): + """ + Recursively builds a menu from a given list of actions. - def __init__(self, generate_modes, action_handler_callback): - """ - Parse the list of action names in the toolbar list. - Look up the action for each name in the action list and add it to the - toolbar. - """ - gtk.Toolbar.__init__(self) - self.set_style(gtk.TOOLBAR_ICONS) - SubMenuCreator.__init__(self, generate_modes, action_handler_callback) - - for action in TOOLBAR_LIST: - if isinstance(action, tuple) and isinstance(action[1], str): - # create a button with a sub-menu - action[0].set_tool_item_type(gtk.MenuToolButton) - item = action[0].create_tool_item() - self.create_submenu(action, item) - self.refresh_submenus() - - elif action is None: - item = gtk.SeparatorToolItem() - - else: - action.set_tool_item_type(gtk.ToolButton) - item = action.create_tool_item() - # this reset of the tooltip property is required - # (after creating the tool item) for the tooltip to show - action.set_property('tooltip', action.get_property('tooltip')) - self.add(item) - - -class MenuHelperMixin(object): - """Mixin class to help build menus from the above action lists""" - - def _fill_menu(self, actions, menu=None): - """Create a menu from list of actions""" - menu = menu or gtk.Menu() + Args: + - actions: List of actions to build the menu + - menu: Current menu being built + + Notes: + - Tuple: Create a new submenu from the parent (1st) and child (2nd) elements + - Action: Append to current menu + - List: Start a new section + """ + + def __init__(self): + SubMenuHelper.__init__(self) + + def build_menu(self, actions, menu): for item in actions: if isinstance(item, tuple): - menu_item = self._make_sub_menu(*item) - elif isinstance(item, str): - menu_item = getattr(self, 'create_' + item)() - elif item is None: - menu_item = gtk.SeparatorMenuItem() - else: - menu_item = item.create_menu_item() - menu.append(menu_item) - menu.show_all() - return menu + # Create a new submenu + parent, child = (item[0], item[1]) + + # Create the parent + label, target = (parent, None) + if isinstance(parent, Actions.Action): + label = parent.label + target = "{}.{}".format(parent.prefix, parent.name) + menuitem = Gio.MenuItem.new(label, None) + if hasattr(parent, "icon_name"): + menuitem.set_icon(Gio.Icon.new_for_string(parent.icon_name)) + + # Create the new submenu + if isinstance(child, list): + submenu = Gio.Menu() + self.build_menu(child, submenu) + menuitem.set_submenu(submenu) + elif isinstance(child, str): + # Child is the name of the submenu to create + def set_func(obj, menu): + obj.set_submenu(menu) + self.build_submenu(child, menuitem, set_func) + menu.append_item(menuitem) + + elif isinstance(item, list): + # Create a new section + section = Gio.Menu() + self.build_menu(item, section) + menu.append_section(None, section) + + elif isinstance(item, Actions.Action): + # Append a new menuitem + target = "{}.{}".format(item.prefix, item.name) + menuitem = Gio.MenuItem.new(item.label, target) + if item.icon_name: + menuitem.set_icon(Gio.Icon.new_for_string(item.icon_name)) + menu.append_item(menuitem) + + +class ToolbarHelper(SubMenuHelper): + """ + Builds a toolbar from a given list of actions. + + Args: + - actions: List of actions to build the menu + - item: Current menu being built + + Notes: + - Tuple: Create a new submenu from the parent (1st) and child (2nd) elements + - Action: Append to current menu + - List: Start a new section + """ - def _make_sub_menu(self, main, actions): - """Create a submenu from a main action and a list of actions""" - main = main.create_menu_item() - main.set_submenu(self._fill_menu(actions)) - return main + def __init__(self): + SubMenuHelper.__init__(self) + def build_toolbar(self, actions, current): + for item in actions: + if isinstance(item, list): + # Toolbar's don't have sections like menus, so call this function + # recursively with the "section" and just append a separator. + self.build_toolbar(item, self) + current.insert(Gtk.SeparatorToolItem.new(), -1) + + elif isinstance(item, tuple): + parent, child = (item[0], item[1]) + # Create an item with a submenu + # Generate the submenu and add to the item. + # Add the item to the toolbar + button = Gtk.MenuToolButton.new() + # The tuple should be made up of an Action and something. + button.set_label(parent.label) + button.set_tooltip_text(parent.tooltip) + button.set_icon_name(parent.icon_name) + + target = "{}.{}".format(parent.prefix, parent.name) + button.set_action_name(target) + + def set_func(obj, menu): + obj.set_menu(Gtk.Menu.new_from_model(menu)) + + self.build_submenu(child, button, set_func) + current.insert(button, -1) + + elif isinstance(item, Actions.Action): + button = Gtk.ToolButton.new() + button.set_label(item.label) + button.set_tooltip_text(item.tooltip) + button.set_icon_name(item.icon_name) + target = "{}.{}".format(item.prefix, item.name) + button.set_action_name(target) + current.insert(button, -1) + + +class Menu(Gio.Menu, MenuHelper): + """ Main Menu """ -class MenuBar(gtk.MenuBar, MenuHelperMixin, SubMenuCreator): - """The gtk menu bar with actions added from the menu bar list.""" + def __init__(self): + GObject.GObject.__init__(self) + MenuHelper.__init__(self) - def __init__(self, generate_modes, action_handler_callback): - """ - Parse the list of submenus from the menubar list. - For each submenu, get a list of action names. - Look up the action for each name in the action list and add it to the - submenu. Add the submenu to the menu bar. - """ - gtk.MenuBar.__init__(self) - SubMenuCreator.__init__(self, generate_modes, action_handler_callback) - for main_action, actions in MENU_BAR_LIST: - self.append(self._make_sub_menu(main_action, actions)) + log.debug("Building the main menu") + self.build_menu(MENU_BAR_LIST, self) - def create_flow_graph_new(self): - main = gtk.ImageMenuItem(gtk.STOCK_NEW) - main.set_label(Actions.FLOW_GRAPH_NEW.get_label()) - func = self._fill_flow_graph_new_submenu - self.submenus.append((Actions.FLOW_GRAPH_NEW, func, main)) - self.refresh_submenus() - return main - def create_flow_graph_recent(self): - main = gtk.ImageMenuItem(gtk.STOCK_OPEN) - main.set_label(Actions.FLOW_GRAPH_OPEN_RECENT.get_label()) - func = self._fill_flow_graph_recent_submenu - self.submenus.append((Actions.FLOW_GRAPH_OPEN, func, main)) - self.refresh_submenus() - if main.get_submenu() is None: - main.set_property('sensitive', False) - return main +class ContextMenu(Gio.Menu, MenuHelper): + """ Context menu for the drawing area """ + + def __init__(self): + GObject.GObject.__init__(self) + log.debug("Building the context menu") + self.build_menu(CONTEXT_MENU_LIST, self) -class ContextMenu(gtk.Menu, MenuHelperMixin): - """The gtk menu with actions added from the context menu list.""" + +class Toolbar(Gtk.Toolbar, ToolbarHelper): + """ The gtk toolbar with actions added from the toolbar list. """ def __init__(self): - gtk.Menu.__init__(self) - self._fill_menu(CONTEXT_MENU_LIST, self) + """ + Parse the list of action names in the toolbar list. + Look up the action for each name in the action list and add it to the + toolbar. + """ + GObject.GObject.__init__(self) + ToolbarHelper.__init__(self) + + self.set_style(Gtk.ToolbarStyle.ICONS) + #self.get_style_context().add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR) + + #SubMenuCreator.__init__(self) + self.build_toolbar(TOOLBAR_LIST, self) diff --git a/grc/gui/Block.py b/grc/gui/Block.py deleted file mode 100644 index b90ea485ee..0000000000 --- a/grc/gui/Block.py +++ /dev/null @@ -1,350 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import pygtk -pygtk.require('2.0') -import gtk -import pango - -from . import Actions, Colors, Utils, Constants - -from . Element import Element -from ..core.Param import num_to_str -from ..core.utils import odict -from ..core.utils.complexity import calculate_flowgraph_complexity -from ..core.Block import Block as _Block - -BLOCK_MARKUP_TMPL="""\ -#set $foreground = $block.is_valid() and 'black' or 'red' -<span foreground="$foreground" font_desc="$font"><b>$encode($block.get_name())</b></span>""" - -# Includes the additional complexity markup if enabled -COMMENT_COMPLEXITY_MARKUP_TMPL="""\ -#set $foreground = $block.get_enabled() and '#444' or '#888' -#if $complexity -<span foreground="#444" size="medium" font_desc="$font"><b>$encode($complexity)</b></span>#slurp -#end if -#if $complexity and $comment -<span></span> -#end if -#if $comment -<span foreground="$foreground" font_desc="$font">$encode($comment)</span>#slurp -#end if -""" - - -class Block(Element, _Block): - """The graphical signal block.""" - - def __init__(self, flow_graph, n): - """ - Block contructor. - Add graphics related params to the block. - """ - _Block.__init__(self, flow_graph, n) - - self.W = 0 - self.H = 0 - #add the position param - self.get_params().append(self.get_parent().get_parent().Param( - block=self, - n=odict({ - 'name': 'GUI Coordinate', - 'key': '_coordinate', - 'type': 'raw', - 'value': '(0, 0)', - 'hide': 'all', - }) - )) - self.get_params().append(self.get_parent().get_parent().Param( - block=self, - n=odict({ - 'name': 'GUI Rotation', - 'key': '_rotation', - 'type': 'raw', - 'value': '0', - 'hide': 'all', - }) - )) - Element.__init__(self) - self._comment_pixmap = None - self.has_busses = [False, False] # source, sink - - def get_coordinate(self): - """ - Get the coordinate from the position param. - - Returns: - the coordinate tuple (x, y) or (0, 0) if failure - """ - proximity = Constants.BORDER_PROXIMITY_SENSITIVITY - try: #should evaluate to tuple - x, y = Utils.scale(eval(self.get_param('_coordinate').get_value())) - fgW, fgH = self.get_parent().get_size() - if x <= 0: - x = 0 - elif x >= fgW - proximity: - x = fgW - proximity - if y <= 0: - y = 0 - elif y >= fgH - proximity: - y = fgH - proximity - return (x, y) - except: - self.set_coordinate((0, 0)) - return (0, 0) - - def set_coordinate(self, coor): - """ - Set the coordinate into the position param. - - Args: - coor: the coordinate tuple (x, y) - """ - if Actions.TOGGLE_SNAP_TO_GRID.get_active(): - offset_x, offset_y = (0, self.H/2) if self.is_horizontal() else (self.H/2, 0) - coor = ( - Utils.align_to_grid(coor[0] + offset_x) - offset_x, - Utils.align_to_grid(coor[1] + offset_y) - offset_y - ) - self.get_param('_coordinate').set_value(str(Utils.scale(coor, reverse=True))) - - def bound_move_delta(self, delta_coor): - """ - Limit potential moves from exceeding the bounds of the canvas - - Args: - delta_coor: requested delta coordinate (dX, dY) to move - - Returns: - The delta coordinate possible to move while keeping the block on the canvas - or the input (dX, dY) on failure - """ - dX, dY = delta_coor - - try: - fgW, fgH = self.get_parent().get_size() - x, y = Utils.scale(eval(self.get_param('_coordinate').get_value())) - if self.is_horizontal(): - sW, sH = self.W, self.H - else: - sW, sH = self.H, self.W - - if x + dX < 0: - dX = -x - elif dX + x + sW >= fgW: - dX = fgW - x - sW - if y + dY < 0: - dY = -y - elif dY + y + sH >= fgH: - dY = fgH - y - sH - except: - pass - - return ( dX, dY ) - - def get_rotation(self): - """ - Get the rotation from the position param. - - Returns: - the rotation in degrees or 0 if failure - """ - try: #should evaluate to dict - rotation = eval(self.get_param('_rotation').get_value()) - return int(rotation) - except: - self.set_rotation(Constants.POSSIBLE_ROTATIONS[0]) - return Constants.POSSIBLE_ROTATIONS[0] - - def set_rotation(self, rot): - """ - Set the rotation into the position param. - - Args: - rot: the rotation in degrees - """ - self.get_param('_rotation').set_value(str(rot)) - - def create_shapes(self): - """Update the block, parameters, and ports when a change occurs.""" - Element.create_shapes(self) - if self.is_horizontal(): self.add_area((0, 0), (self.W, self.H)) - elif self.is_vertical(): self.add_area((0, 0), (self.H, self.W)) - - def create_labels(self): - """Create the labels for the signal block.""" - Element.create_labels(self) - self._bg_color = self.is_dummy_block and Colors.MISSING_BLOCK_BACKGROUND_COLOR or \ - self.get_bypassed() and Colors.BLOCK_BYPASSED_COLOR or \ - self.get_enabled() and Colors.BLOCK_ENABLED_COLOR or Colors.BLOCK_DISABLED_COLOR - - layouts = list() - #create the main layout - layout = gtk.DrawingArea().create_pango_layout('') - layouts.append(layout) - layout.set_markup(Utils.parse_template(BLOCK_MARKUP_TMPL, block=self, font=Constants.BLOCK_FONT)) - self.label_width, self.label_height = layout.get_pixel_size() - #display the params - if self.is_dummy_block: - markups = [ - '<span foreground="black" font_desc="{font}"><b>key: </b>{key}</span>' - ''.format(font=Constants.PARAM_FONT, key=self._key) - ] - else: - markups = [param.get_markup() for param in self.get_params() if param.get_hide() not in ('all', 'part')] - if markups: - layout = gtk.DrawingArea().create_pango_layout('') - layout.set_spacing(Constants.LABEL_SEPARATION * pango.SCALE) - layout.set_markup('\n'.join(markups)) - layouts.append(layout) - w, h = layout.get_pixel_size() - self.label_width = max(w, self.label_width) - self.label_height += h + Constants.LABEL_SEPARATION - width = self.label_width - height = self.label_height - #setup the pixmap - pixmap = self.get_parent().new_pixmap(width, height) - gc = pixmap.new_gc() - gc.set_foreground(self._bg_color) - pixmap.draw_rectangle(gc, True, 0, 0, width, height) - #draw the layouts - h_off = 0 - for i,layout in enumerate(layouts): - w,h = layout.get_pixel_size() - if i == 0: w_off = (width-w)/2 - else: w_off = 0 - pixmap.draw_layout(gc, w_off, h_off, layout) - h_off = h + h_off + Constants.LABEL_SEPARATION - #create vertical and horizontal pixmaps - self.horizontal_label = pixmap - if self.is_vertical(): - self.vertical_label = self.get_parent().new_pixmap(height, width) - Utils.rotate_pixmap(gc, self.horizontal_label, self.vertical_label) - #calculate width and height needed - W = self.label_width + 2 * Constants.BLOCK_LABEL_PADDING - - def get_min_height_for_ports(): - visible_ports = filter(lambda p: not p.get_hide(), ports) - min_height = 2*Constants.PORT_BORDER_SEPARATION + len(visible_ports) * Constants.PORT_SEPARATION - if visible_ports: - min_height -= ports[0].H - return min_height - H = max( - [ # labels - self.label_height + 2 * Constants.BLOCK_LABEL_PADDING - ] + - [ # ports - get_min_height_for_ports() for ports in (self.get_sources_gui(), self.get_sinks_gui()) - ] + - [ # bus ports only - 2 * Constants.PORT_BORDER_SEPARATION + - sum([port.H + Constants.PORT_SPACING for port in ports if port.get_type() == 'bus']) - Constants.PORT_SPACING - for ports in (self.get_sources_gui(), self.get_sinks_gui()) - ] - ) - self.W, self.H = Utils.align_to_grid((W, H)) - self.has_busses = [ - any(port.get_type() == 'bus' for port in ports) - for ports in (self.get_sources_gui(), self.get_sinks_gui()) - ] - self.create_comment_label() - - def create_comment_label(self): - comment = self.get_comment() # Returns None if there are no comments - complexity = None - - # Show the flowgraph complexity on the top block if enabled - if Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY.get_active() and self.get_key() == "options": - complexity = calculate_flowgraph_complexity(self.get_parent()) - complexity = "Complexity: {}bal".format(num_to_str(complexity)) - - layout = gtk.DrawingArea().create_pango_layout('') - layout.set_markup(Utils.parse_template(COMMENT_COMPLEXITY_MARKUP_TMPL, - block=self, - comment=comment, - complexity=complexity, - font=Constants.BLOCK_FONT)) - - # Setup the pixel map. Make sure that layout not empty - width, height = layout.get_pixel_size() - if width and height: - padding = Constants.BLOCK_LABEL_PADDING - pixmap = self.get_parent().new_pixmap(width + 2 * padding, - height + 2 * padding) - gc = pixmap.new_gc() - gc.set_foreground(Colors.COMMENT_BACKGROUND_COLOR) - pixmap.draw_rectangle( - gc, True, 0, 0, width + 2 * padding, height + 2 * padding) - pixmap.draw_layout(gc, padding, padding, layout) - self._comment_pixmap = pixmap - else: - self._comment_pixmap = None - - def draw(self, gc, window): - """ - Draw the signal block with label and inputs/outputs. - - Args: - gc: the graphics context - window: the gtk window to draw on - """ - # draw ports - for port in self.get_ports_gui(): - port.draw(gc, window) - # draw main block - x, y = self.get_coordinate() - Element.draw( - self, gc, window, bg_color=self._bg_color, - border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or - self.is_dummy_block and Colors.MISSING_BLOCK_BORDER_COLOR or Colors.BORDER_COLOR, - ) - #draw label image - if self.is_horizontal(): - window.draw_drawable(gc, self.horizontal_label, 0, 0, x+Constants.BLOCK_LABEL_PADDING, y+(self.H-self.label_height)/2, -1, -1) - elif self.is_vertical(): - window.draw_drawable(gc, self.vertical_label, 0, 0, x+(self.H-self.label_height)/2, y+Constants.BLOCK_LABEL_PADDING, -1, -1) - - def what_is_selected(self, coor, coor_m=None): - """ - Get the element that is selected. - - Args: - coor: the (x,y) tuple - coor_m: the (x_m, y_m) tuple - - Returns: - this block, a port, or None - """ - for port in self.get_ports_gui(): - port_selected = port.what_is_selected(coor, coor_m) - if port_selected: return port_selected - return Element.what_is_selected(self, coor, coor_m) - - def draw_comment(self, gc, window): - if not self._comment_pixmap: - return - x, y = self.get_coordinate() - - if self.is_horizontal(): - y += self.H + Constants.BLOCK_LABEL_PADDING - else: - x += self.H + Constants.BLOCK_LABEL_PADDING - - window.draw_drawable(gc, self._comment_pixmap, 0, 0, x, y, -1, -1) diff --git a/grc/gui/BlockTreeWindow.py b/grc/gui/BlockTreeWindow.py index 900cbd3151..8504200459 100644 --- a/grc/gui/BlockTreeWindow.py +++ b/grc/gui/BlockTreeWindow.py @@ -1,5 +1,5 @@ """ -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +Copyright 2007, 2008, 2009, 2016 Free Software Foundation, Inc. This file is part of GNU Radio GNU Radio Companion is free software; you can redistribute it and/or @@ -17,71 +17,56 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import pygtk -pygtk.require('2.0') -import gtk -import gobject - -from . import Actions, Utils -from . import Constants - - -NAME_INDEX = 0 -KEY_INDEX = 1 -DOC_INDEX = 2 - -DOC_MARKUP_TMPL = """\ -#set $docs = [] -#if $doc.get('') - #set $docs += $doc.pop('').splitlines() + [''] -#end if -#for b, d in $doc.iteritems() - #set $docs += ['--- {0} ---'.format(b)] + d.splitlines() + [''] -#end for -#set $len_out = 0 -#for $n, $line in $enumerate($docs[:-1]) -#if $n - -#end if -$encode($line)#slurp -#set $len_out += $len($line) -#if $n > 10 or $len_out > 500 - -...#slurp -#break -#end if -#end for -#if $len_out == 0 -undocumented#slurp -#end if""" - -CAT_MARKUP_TMPL = """ -#set $name = $cat[-1] -#if len($cat) > 1 -Category: $cat[-1] -## -#elif $name == 'Core' -Module: Core - -This subtree is meant for blocks included with GNU Radio (in-tree). -## -#elif $name == $default_module -This subtree holds all blocks (from OOT modules) that specify no module name. \ -The module name is the root category enclosed in square brackets. - -Please consider contacting OOT module maintainer for any block in here \ -and kindly ask to update their GRC Block Descriptions or Block Tree to include a module name. -#else -Module: $name -## -#end if -""".strip() - - -class BlockTreeWindow(gtk.VBox): +from __future__ import absolute_import +import six + +from gi.repository import Gtk, Gdk, GObject + +from . import Actions, Utils, Constants + + +NAME_INDEX, KEY_INDEX, DOC_INDEX = range(3) + + +def _format_doc(doc): + docs = [] + if doc.get(''): + docs += doc.pop('').splitlines() + [''] + for block_name, docstring in six.iteritems(doc): + docs.append('--- {0} ---'.format(block_name)) + docs += docstring.splitlines() + docs.append('') + out = '' + for n, line in enumerate(docs[:-1]): + if n: + out += '\n' + out += Utils.encode(line) + if n > 10 or len(out) > 500: + out += '\n...' + break + return out or 'undocumented' + + +def _format_cat_tooltip(category): + tooltip = '{}: {}'.format('Category' if len(category) > 1 else 'Module', category[-1]) + + if category == ('Core',): + tooltip += '\n\nThis subtree is meant for blocks included with GNU Radio (in-tree).' + + elif category == (Constants.DEFAULT_BLOCK_MODULE_NAME,): + tooltip += '\n\n' + Constants.DEFAULT_BLOCK_MODULE_TOOLTIP + + return tooltip + + +class BlockTreeWindow(Gtk.VBox): """The block selection panel.""" - def __init__(self, platform, get_flow_graph): + __gsignals__ = { + 'create_new_block': (GObject.SignalFlags.RUN_FIRST, None, (str,)) + } + + def __init__(self, platform): """ BlockTreeWindow constructor. Create a tree view of the possible blocks in the platform. @@ -90,58 +75,52 @@ class BlockTreeWindow(gtk.VBox): Args: platform: the particular platform will all block prototypes - get_flow_graph: get the selected flow graph """ - gtk.VBox.__init__(self) + Gtk.VBox.__init__(self) self.platform = platform - self.get_flow_graph = get_flow_graph # search entry - self.search_entry = gtk.Entry() + self.search_entry = Gtk.Entry() try: - self.search_entry.set_icon_from_stock(gtk.ENTRY_ICON_PRIMARY, gtk.STOCK_FIND) - self.search_entry.set_icon_activatable(gtk.ENTRY_ICON_PRIMARY, False) - self.search_entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, gtk.STOCK_CLOSE) + self.search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.PRIMARY, 'edit-find') + self.search_entry.set_icon_activatable(Gtk.EntryIconPosition.PRIMARY, False) + self.search_entry.set_icon_from_icon_name(Gtk.EntryIconPosition.SECONDARY, 'window-close') self.search_entry.connect('icon-release', self._handle_icon_event) except AttributeError: pass # no icon for old pygtk self.search_entry.connect('changed', self._update_search_tree) self.search_entry.connect('key-press-event', self._handle_search_key_press) - self.pack_start(self.search_entry, False) + self.pack_start(self.search_entry, False, False, 0) # make the tree model for holding blocks and a temporary one for search results - self.treestore = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) - self.treestore_search = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) + self.treestore = Gtk.TreeStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) + self.treestore_search = Gtk.TreeStore(GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_STRING) - self.treeview = gtk.TreeView(self.treestore) + self.treeview = Gtk.TreeView(model=self.treestore) self.treeview.set_enable_search(False) # disable pop up search box self.treeview.set_search_column(-1) # really disable search self.treeview.set_headers_visible(False) - self.treeview.add_events(gtk.gdk.BUTTON_PRESS_MASK) + self.treeview.add_events(Gdk.EventMask.BUTTON_PRESS_MASK) self.treeview.connect('button-press-event', self._handle_mouse_button_press) self.treeview.connect('key-press-event', self._handle_search_key_press) - self.treeview.get_selection().set_mode('single') - renderer = gtk.CellRendererText() - column = gtk.TreeViewColumn('Blocks', renderer, text=NAME_INDEX) + self.treeview.get_selection().set_mode(Gtk.SelectionMode.SINGLE) + renderer = Gtk.CellRendererText() + column = Gtk.TreeViewColumn('Blocks', renderer, text=NAME_INDEX) self.treeview.append_column(column) - # try to enable the tooltips (available in pygtk 2.12 and above) - try: - self.treeview.set_tooltip_column(DOC_INDEX) - except: - pass + self.treeview.set_tooltip_column(DOC_INDEX) # setup sort order column.set_sort_column_id(0) - self.treestore.set_sort_column_id(0, gtk.SORT_ASCENDING) + self.treestore.set_sort_column_id(0, Gtk.SortType.ASCENDING) # setup drag and drop - self.treeview.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, Constants.DND_TARGETS, gtk.gdk.ACTION_COPY) + self.treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, Constants.DND_TARGETS, Gdk.DragAction.COPY) self.treeview.connect('drag-data-get', self._handle_drag_get_data) # make the scrolled window to hold the tree view - scrolled_window = gtk.ScrolledWindow() - scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolled_window.add_with_viewport(self.treeview) + scrolled_window = Gtk.ScrolledWindow() + scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolled_window.add(self.treeview) scrolled_window.set_size_request(Constants.DEFAULT_BLOCKS_WINDOW_WIDTH, -1) - self.pack_start(scrolled_window) + self.pack_start(scrolled_window, True, True, 0) # map categories to iters, automatic mapping for root self._categories = {tuple(): None} self._categories_search = {tuple(): None} @@ -154,7 +133,7 @@ class BlockTreeWindow(gtk.VBox): def repopulate(self): self.clear() - for block in self.platform.blocks.itervalues(): + for block in six.itervalues(self.platform.blocks): if block.category: self.add_block(block) self.expand_module_in_tree() @@ -188,15 +167,13 @@ class BlockTreeWindow(gtk.VBox): iter_ = treestore.insert_before(categories[parent_category[:-1]], None) treestore.set_value(iter_, NAME_INDEX, parent_cat_name) treestore.set_value(iter_, KEY_INDEX, '') - treestore.set_value(iter_, DOC_INDEX, Utils.parse_template( - CAT_MARKUP_TMPL, cat=parent_category, default_module=Constants.DEFAULT_BLOCK_MODULE_NAME)) + treestore.set_value(iter_, DOC_INDEX, _format_cat_tooltip(parent_cat_name)) categories[parent_category] = iter_ - # add block iter_ = treestore.insert_before(categories[category], None) - treestore.set_value(iter_, NAME_INDEX, block.get_name()) - treestore.set_value(iter_, KEY_INDEX, block.get_key()) - treestore.set_value(iter_, DOC_INDEX, Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc())) + treestore.set_value(iter_, KEY_INDEX, block.key) + treestore.set_value(iter_, NAME_INDEX, block.name) + treestore.set_value(iter_, DOC_INDEX, _format_doc(block.documentation)) def update_docs(self): """Update the documentation column of every block""" @@ -206,8 +183,7 @@ class BlockTreeWindow(gtk.VBox): if not key: return # category node, no doc string block = self.platform.blocks[key] - doc = Utils.parse_template(DOC_MARKUP_TMPL, doc=block.get_doc()) - model.set_value(iter_, DOC_INDEX, doc) + model.set_value(iter_, DOC_INDEX, _format_doc(block.documentation)) self.treestore.foreach(update_doc) self.treestore_search.foreach(update_doc) @@ -226,16 +202,6 @@ class BlockTreeWindow(gtk.VBox): treestore, iter = selection.get_selected() return iter and treestore.get_value(iter, KEY_INDEX) or '' - def _add_selected_block(self): - """ - Add the selected block with the given key to the flow graph. - """ - key = self._get_selected_block_key() - if key: - self.get_flow_graph().add_new_block(key) - return True - return False - def _expand_category(self): treestore, iter = self.treeview.get_selection().get_selected() if iter and treestore.iter_has_child(iter): @@ -246,9 +212,9 @@ class BlockTreeWindow(gtk.VBox): ## Event Handlers ############################################################ def _handle_icon_event(self, widget, icon, event): - if icon == gtk.ENTRY_ICON_PRIMARY: + if icon == Gtk.EntryIconPosition.PRIMARY: pass - elif icon == gtk.ENTRY_ICON_SECONDARY: + elif icon == Gtk.EntryIconPosition.SECONDARY: widget.set_text('') self.search_entry.hide() @@ -258,8 +224,8 @@ class BlockTreeWindow(gtk.VBox): self.treeview.set_model(self.treestore) self.expand_module_in_tree() else: - matching_blocks = filter(lambda b: key in b.get_key().lower() or key in b.get_name().lower(), - self.platform.blocks.values()) + matching_blocks = [b for b in list(self.platform.blocks.values()) + if key in b.key.lower() or key in b.name.lower()] self.treestore_search.clear() self._categories_search = {tuple(): None} @@ -270,7 +236,7 @@ class BlockTreeWindow(gtk.VBox): def _handle_search_key_press(self, widget, event): """Handle Return and Escape key events in search entry and treeview""" - if event.keyval == gtk.keysyms.Return: + if event.keyval == Gdk.KEY_Return: # add block on enter if widget == self.search_entry: @@ -280,24 +246,28 @@ class BlockTreeWindow(gtk.VBox): selected = self.treestore_search.iter_children(selected) if selected is not None: key = self.treestore_search.get_value(selected, KEY_INDEX) - if key: self.get_flow_graph().add_new_block(key) + if key: self.emit('create_new_block', key) elif widget == self.treeview: - self._add_selected_block() or self._expand_category() + key = self._get_selected_block_key() + if key: + self.emit('create_new_block', key) + else: + self._expand_category() else: return False # propagate event - elif event.keyval == gtk.keysyms.Escape: + elif event.keyval == Gdk.KEY_Escape: # reset the search self.search_entry.set_text('') self.search_entry.hide() - elif (event.state & gtk.gdk.CONTROL_MASK and event.keyval == gtk.keysyms.f) \ - or event.keyval == gtk.keysyms.slash: + elif (event.get_state() & Gdk.ModifierType.CONTROL_MASK and event.keyval == Gdk.KEY_f) \ + or event.keyval == Gdk.KEY_slash: # propagation doesn't work although treeview search is disabled =( # manually trigger action... Actions.FIND_BLOCKS.activate() - elif event.state & gtk.gdk.CONTROL_MASK and event.keyval == gtk.keysyms.b: + elif event.get_state() & Gdk.ModifierType.CONTROL_MASK and event.keyval == Gdk.KEY_b: # ugly... Actions.TOGGLE_BLOCKS_WINDOW.activate() @@ -313,12 +283,15 @@ class BlockTreeWindow(gtk.VBox): Only call set when the key is valid to ignore DND from categories. """ key = self._get_selected_block_key() - if key: selection_data.set(selection_data.target, 8, key) + if key: + selection_data.set_text(key, len(key)) def _handle_mouse_button_press(self, widget, event): """ Handle the mouse button press. If a left double click is detected, call add selected block. """ - if event.button == 1 and event.type == gtk.gdk._2BUTTON_PRESS: - self._add_selected_block() + if event.button == 1 and event.type == Gdk.EventType._2BUTTON_PRESS: + key = self._get_selected_block_key() + if key: + self.emit('create_new_block', key) diff --git a/grc/gui/CMakeLists.txt b/grc/gui/CMakeLists.txt deleted file mode 100644 index dc661c44ed..0000000000 --- a/grc/gui/CMakeLists.txt +++ /dev/null @@ -1,32 +0,0 @@ -# Copyright 2011 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. - -file(GLOB py_files "*.py") - -GR_PYTHON_INSTALL( - FILES ${py_files} - DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/gui -) - -install( - FILES - ${CMAKE_CURRENT_SOURCE_DIR}/icon.png - DESTINATION ${GR_PYTHON_DIR}/gnuradio/grc/gui - COMPONENT "grc" -) diff --git a/grc/gui/Colors.py b/grc/gui/Colors.py deleted file mode 100644 index d322afa410..0000000000 --- a/grc/gui/Colors.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -Copyright 2008,2013 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" -try: - import pygtk - pygtk.require('2.0') - import gtk - - _COLORMAP = gtk.gdk.colormap_get_system() #create all of the colors - def get_color(color_code): return _COLORMAP.alloc_color(color_code, True, True) - - HIGHLIGHT_COLOR = get_color('#00FFFF') - BORDER_COLOR = get_color('#444444') - # missing blocks stuff - MISSING_BLOCK_BACKGROUND_COLOR = get_color('#FFF2F2') - MISSING_BLOCK_BORDER_COLOR = get_color('red') - #param entry boxes - PARAM_ENTRY_TEXT_COLOR = get_color('black') - ENTRYENUM_CUSTOM_COLOR = get_color('#EEEEEE') - #flow graph color constants - FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFFFFF') - COMMENT_BACKGROUND_COLOR = get_color('#F3F3F3') - FLOWGRAPH_EDGE_COLOR = COMMENT_BACKGROUND_COLOR - #block color constants - BLOCK_ENABLED_COLOR = get_color('#F1ECFF') - BLOCK_DISABLED_COLOR = get_color('#CCCCCC') - BLOCK_BYPASSED_COLOR = get_color('#F4FF81') - #connection color constants - CONNECTION_ENABLED_COLOR = get_color('black') - CONNECTION_DISABLED_COLOR = get_color('#BBBBBB') - CONNECTION_ERROR_COLOR = get_color('red') -except: - print 'Unable to import Colors' - -DEFAULT_DOMAIN_COLOR_CODE = '#777777' diff --git a/grc/gui/Config.py b/grc/gui/Config.py index 9b0c5d4afe..6135296660 100644 --- a/grc/gui/Config.py +++ b/grc/gui/Config.py @@ -17,13 +17,26 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import, print_function + import sys import os -from ..core.Config import Config as _Config + +from ..core.Config import Config as CoreConfig from . import Constants +from six.moves import configparser -class Config(_Config): +HEADER = """\ +# This contains only GUI settings for GRC and is not meant for users to edit. +# +# GRC settings not accessible through the GUI are in gnuradio.conf under +# section [grc]. + +""" + + +class Config(CoreConfig): name = 'GNU Radio Companion' @@ -31,44 +44,163 @@ class Config(_Config): 'GRC_PREFS_PATH', os.path.expanduser('~/.gnuradio/grc.conf')) def __init__(self, install_prefix, *args, **kwargs): - _Config.__init__(self, *args, **kwargs) + CoreConfig.__init__(self, *args, **kwargs) self.install_prefix = install_prefix Constants.update_font_size(self.font_size) + self.parser = configparser.ConfigParser() + for section in ['main', 'files_open', 'files_recent']: + try: + self.parser.add_section(section) + except Exception as e: + print(e) + try: + self.parser.read(self.gui_prefs_file) + except Exception as err: + print(err, file=sys.stderr) + + def save(self): + try: + with open(self.gui_prefs_file, 'w') as fp: + fp.write(HEADER) + self.parser.write(fp) + except Exception as err: + print(err, file=sys.stderr) + + def entry(self, key, value=None, default=None): + if value is not None: + self.parser.set('main', key, str(value)) + result = value + else: + _type = type(default) if default is not None else str + getter = { + bool: self.parser.getboolean, + int: self.parser.getint, + }.get(_type, self.parser.get) + try: + result = getter('main', key) + except (AttributeError, configparser.Error): + result = _type() if default is None else default + return result + @property def editor(self): - return self.prefs.get_string('grc', 'editor', '') + return self._gr_prefs.get_string('grc', 'editor', '') @editor.setter def editor(self, value): - self.prefs.get_string('grc', 'editor', value) - self.prefs.save() + self._gr_prefs.get_string('grc', 'editor', value) + self._gr_prefs.save() @property def xterm_executable(self): - return self.prefs.get_string('grc', 'xterm_executable', 'xterm') + return self._gr_prefs.get_string('grc', 'xterm_executable', 'xterm') @property def default_canvas_size(self): try: # ugly, but matches current code style - raw = self.prefs.get_string('grc', 'canvas_default_size', '1280, 1024') + raw = self._gr_prefs.get_string('grc', 'canvas_default_size', '1280, 1024') value = tuple(int(x.strip('() ')) for x in raw.split(',')) if len(value) != 2 or not all(300 < x < 4096 for x in value): raise Exception() return value except: - print >> sys.stderr, "Error: invalid 'canvas_default_size' setting." + print("Error: invalid 'canvas_default_size' setting.", file=sys.stderr) return Constants.DEFAULT_CANVAS_SIZE_DEFAULT @property def font_size(self): try: # ugly, but matches current code style - font_size = self.prefs.get_long('grc', 'canvas_font_size', - Constants.DEFAULT_FONT_SIZE) + font_size = self._gr_prefs.get_long('grc', 'canvas_font_size', + Constants.DEFAULT_FONT_SIZE) if font_size <= 0: raise Exception() except: font_size = Constants.DEFAULT_FONT_SIZE - print >> sys.stderr, "Error: invalid 'canvas_font_size' setting." + print("Error: invalid 'canvas_font_size' setting.", file=sys.stderr) return font_size + + @property + def default_qss_theme(self): + return self._gr_prefs.get_string('qtgui', 'qss', '') + + @default_qss_theme.setter + def default_qss_theme(self, value): + self._gr_prefs.set_string("qtgui", "qss", value) + self._gr_prefs.save() + + ##### Originally from Preferences.py ##### + def main_window_size(self, size=None): + if size is None: + size = [None, None] + w = self.entry('main_window_width', size[0], default=1) + h = self.entry('main_window_height', size[1], default=1) + return w, h + + def file_open(self, filename=None): + return self.entry('file_open', filename, default='') + + def set_file_list(self, key, files): + self.parser.remove_section(key) # clear section + self.parser.add_section(key) + for i, filename in enumerate(files): + self.parser.set(key, '%s_%d' % (key, i), filename) + + def get_file_list(self, key): + try: + files = [value for name, value in self.parser.items(key) + if name.startswith('%s_' % key)] + except (AttributeError, configparser.Error): + files = [] + return files + + def get_open_files(self): + return self.get_file_list('files_open') + + def set_open_files(self, files): + return self.set_file_list('files_open', files) + + def get_recent_files(self): + """ Gets recent files, removes any that do not exist and re-saves it """ + files = list(filter(os.path.exists, self.get_file_list('files_recent'))) + self.set_recent_files(files) + return files + + def set_recent_files(self, files): + return self.set_file_list('files_recent', files) + + def add_recent_file(self, file_name): + # double check file_name + if os.path.exists(file_name): + recent_files = self.get_recent_files() + if file_name in recent_files: + recent_files.remove(file_name) # Attempt removal + recent_files.insert(0, file_name) # Insert at start + self.set_recent_files(recent_files[:10]) # Keep up to 10 files + + def console_window_position(self, pos=None): + return self.entry('console_window_position', pos, default=-1) or 1 + + def blocks_window_position(self, pos=None): + return self.entry('blocks_window_position', pos, default=-1) or 1 + + def variable_editor_position(self, pos=None, sidebar=False): + # Figure out default + if sidebar: + w, h = self.main_window_size() + return self.entry('variable_editor_sidebar_position', pos, default=int(h*0.7)) + else: + return self.entry('variable_editor_position', pos, default=int(self.blocks_window_position()*0.5)) + + def variable_editor_sidebar(self, pos=None): + return self.entry('variable_editor_sidebar', pos, default=False) + + def variable_editor_confirm_delete(self, pos=None): + return self.entry('variable_editor_confirm_delete', pos, default=True) + + def xterm_missing(self, cmd=None): + return self.entry('xterm_missing', cmd, default='INVALID_XTERM_SETTING') + + def screen_shot_background_transparent(self, transparent=None): + return self.entry('screen_shot_background_transparent', transparent, default=False) diff --git a/grc/gui/Connection.py b/grc/gui/Connection.py deleted file mode 100644 index 50361c19d0..0000000000 --- a/grc/gui/Connection.py +++ /dev/null @@ -1,181 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import gtk - -import Colors -import Utils -from Constants import CONNECTOR_ARROW_BASE, CONNECTOR_ARROW_HEIGHT -from Element import Element - -from ..core.Constants import GR_MESSAGE_DOMAIN -from ..core.Connection import Connection as _Connection - - -class Connection(Element, _Connection): - """ - A graphical connection for ports. - The connection has 2 parts, the arrow and the wire. - The coloring of the arrow and wire exposes the status of 3 states: - enabled/disabled, valid/invalid, highlighted/non-highlighted. - The wire coloring exposes the enabled and highlighted states. - The arrow coloring exposes the enabled and valid states. - """ - - def __init__(self, **kwargs): - Element.__init__(self) - _Connection.__init__(self, **kwargs) - # can't use Colors.CONNECTION_ENABLED_COLOR here, might not be defined (grcc) - self._bg_color = self._arrow_color = self._color = None - - def get_coordinate(self): - """ - Get the 0,0 coordinate. - Coordinates are irrelevant in connection. - - Returns: - 0, 0 - """ - return 0, 0 - - def get_rotation(self): - """ - Get the 0 degree rotation. - Rotations are irrelevant in connection. - - Returns: - 0 - """ - return 0 - - def create_shapes(self): - """Precalculate relative coordinates.""" - Element.create_shapes(self) - self._sink_rot = None - self._source_rot = None - self._sink_coor = None - self._source_coor = None - #get the source coordinate - try: - connector_length = self.get_source().get_connector_length() - except: - return - self.x1, self.y1 = Utils.get_rotated_coordinate((connector_length, 0), self.get_source().get_rotation()) - #get the sink coordinate - connector_length = self.get_sink().get_connector_length() + CONNECTOR_ARROW_HEIGHT - self.x2, self.y2 = Utils.get_rotated_coordinate((-connector_length, 0), self.get_sink().get_rotation()) - #build the arrow - self.arrow = [(0, 0), - Utils.get_rotated_coordinate((-CONNECTOR_ARROW_HEIGHT, -CONNECTOR_ARROW_BASE/2), self.get_sink().get_rotation()), - Utils.get_rotated_coordinate((-CONNECTOR_ARROW_HEIGHT, CONNECTOR_ARROW_BASE/2), self.get_sink().get_rotation()), - ] - source_domain = self.get_source().get_domain() - sink_domain = self.get_sink().get_domain() - self.line_attributes[0] = 2 if source_domain != sink_domain else 0 - self.line_attributes[1] = gtk.gdk.LINE_DOUBLE_DASH \ - if not source_domain == sink_domain == GR_MESSAGE_DOMAIN \ - else gtk.gdk.LINE_ON_OFF_DASH - get_domain_color = lambda d: Colors.get_color(( - self.get_parent().get_parent().domains.get(d, {}) - ).get('color') or Colors.DEFAULT_DOMAIN_COLOR_CODE) - self._color = get_domain_color(source_domain) - self._bg_color = get_domain_color(sink_domain) - self._arrow_color = self._bg_color if self.is_valid() else Colors.CONNECTION_ERROR_COLOR - self._update_after_move() - - def _update_after_move(self): - """Calculate coordinates.""" - self.clear() #FIXME do i want this here? - #source connector - source = self.get_source() - X, Y = source.get_connector_coordinate() - x1, y1 = self.x1 + X, self.y1 + Y - self.add_line((x1, y1), (X, Y)) - #sink connector - sink = self.get_sink() - X, Y = sink.get_connector_coordinate() - x2, y2 = self.x2 + X, self.y2 + Y - self.add_line((x2, y2), (X, Y)) - #adjust arrow - self._arrow = [(x+X, y+Y) for x,y in self.arrow] - #add the horizontal and vertical lines in this connection - if abs(source.get_connector_direction() - sink.get_connector_direction()) == 180: - #2 possible point sets to create a 3-line connector - mid_x, mid_y = (x1 + x2)/2.0, (y1 + y2)/2.0 - points = [((mid_x, y1), (mid_x, y2)), ((x1, mid_y), (x2, mid_y))] - #source connector -> points[0][0] should be in the direction of source (if possible) - if Utils.get_angle_from_coordinates((x1, y1), points[0][0]) != source.get_connector_direction(): points.reverse() - #points[0][0] -> sink connector should not be in the direction of sink - if Utils.get_angle_from_coordinates(points[0][0], (x2, y2)) == sink.get_connector_direction(): points.reverse() - #points[0][0] -> source connector should not be in the direction of source - if Utils.get_angle_from_coordinates(points[0][0], (x1, y1)) == source.get_connector_direction(): points.reverse() - #create 3-line connector - p1, p2 = map(int, points[0][0]), map(int, points[0][1]) - self.add_line((x1, y1), p1) - self.add_line(p1, p2) - self.add_line((x2, y2), p2) - else: - #2 possible points to create a right-angled connector - points = [(x1, y2), (x2, y1)] - #source connector -> points[0] should be in the direction of source (if possible) - if Utils.get_angle_from_coordinates((x1, y1), points[0]) != source.get_connector_direction(): points.reverse() - #points[0] -> sink connector should not be in the direction of sink - if Utils.get_angle_from_coordinates(points[0], (x2, y2)) == sink.get_connector_direction(): points.reverse() - #points[0] -> source connector should not be in the direction of source - if Utils.get_angle_from_coordinates(points[0], (x1, y1)) == source.get_connector_direction(): points.reverse() - #create right-angled connector - self.add_line((x1, y1), points[0]) - self.add_line((x2, y2), points[0]) - - def draw(self, gc, window): - """ - Draw the connection. - - Args: - gc: the graphics context - window: the gtk window to draw on - """ - sink = self.get_sink() - source = self.get_source() - #check for changes - if self._sink_rot != sink.get_rotation() or self._source_rot != source.get_rotation(): self.create_shapes() - elif self._sink_coor != sink.get_coordinate() or self._source_coor != source.get_coordinate(): - try: - self._update_after_move() - except: - return - #cache values - self._sink_rot = sink.get_rotation() - self._source_rot = source.get_rotation() - self._sink_coor = sink.get_coordinate() - self._source_coor = source.get_coordinate() - #draw - mod_color = lambda color: ( - Colors.HIGHLIGHT_COLOR if self.is_highlighted() else - Colors.CONNECTION_DISABLED_COLOR if not self.get_enabled() else - color - ) - Element.draw(self, gc, window, mod_color(self._color), mod_color(self._bg_color)) - # draw arrow on sink port - try: - gc.set_foreground(mod_color(self._arrow_color)) - gc.set_line_attributes(0, gtk.gdk.LINE_SOLID, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER) - window.draw_polygon(gc, True, self._arrow) - except: - pass diff --git a/grc/gui/Console.py b/grc/gui/Console.py new file mode 100644 index 0000000000..0ae862493d --- /dev/null +++ b/grc/gui/Console.py @@ -0,0 +1,57 @@ +""" +Copyright 2008, 2009, 2011 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion 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 2 +of the License, or (at your option) any later version. + +GNU Radio Companion 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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from __future__ import absolute_import + +import os +import logging + +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk, Gdk, GObject + +from .Constants import DEFAULT_CONSOLE_WINDOW_WIDTH +from .Dialogs import TextDisplay, MessageDialogWrapper + +from ..core import Messages + + +log = logging.getLogger(__name__) + + +class Console(Gtk.ScrolledWindow): + def __init__(self): + Gtk.ScrolledWindow.__init__(self) + log.debug("console()") + self.app = Gtk.Application.get_default() + + self.text_display = TextDisplay() + + self.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + self.add(self.text_display) + self.set_size_request(-1, DEFAULT_CONSOLE_WINDOW_WIDTH) + + def add_line(self, line): + """ + Place line at the end of the text buffer, then scroll its window all the way down. + + Args: + line: the new text + """ + self.text_display.insert(line) diff --git a/grc/gui/Constants.py b/grc/gui/Constants.py index f77221e52d..a3d08cbe38 100644 --- a/grc/gui/Constants.py +++ b/grc/gui/Constants.py @@ -17,17 +17,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import gtk +from __future__ import absolute_import + +from gi.repository import Gtk, Gdk from ..core.Constants import * # default path for the open/save dialogs DEFAULT_FILE_PATH = os.getcwd() if os.name != 'nt' else os.path.expanduser("~/Documents") - -# file extensions -IMAGE_FILE_EXTENSION = '.png' -TEXT_FILE_EXTENSION = '.txt' +FILE_EXTENSION = '.grc' # name for new/unsaved flow graphs NEW_FLOGRAPH_TITLE = 'untitled' @@ -36,7 +35,7 @@ NEW_FLOGRAPH_TITLE = 'untitled' MIN_WINDOW_WIDTH = 600 MIN_WINDOW_HEIGHT = 400 # dialog constraints -MIN_DIALOG_WIDTH = 500 +MIN_DIALOG_WIDTH = 600 MIN_DIALOG_HEIGHT = 500 # default sizes DEFAULT_BLOCKS_WINDOW_WIDTH = 100 @@ -53,7 +52,7 @@ PARAM_FONT = "Sans 7.5" STATE_CACHE_SIZE = 42 # Shared targets for drag and drop of blocks -DND_TARGETS = [('STRING', gtk.TARGET_SAME_APP, 0)] +DND_TARGETS = [('STRING', Gtk.TargetFlags.SAME_APP, 0)] # label constraint dimensions LABEL_SEPARATION = 3 @@ -70,6 +69,7 @@ PORT_SEPARATION = 32 PORT_MIN_WIDTH = 20 PORT_LABEL_HIDDEN_WIDTH = 10 +PORT_EXTRA_BUS_HEIGHT = 40 # minimal length of connector CONNECTOR_EXTENSION_MINIMAL = 11 @@ -78,17 +78,14 @@ CONNECTOR_EXTENSION_MINIMAL = 11 CONNECTOR_EXTENSION_INCREMENT = 11 # connection arrow dimensions -CONNECTOR_ARROW_BASE = 13 -CONNECTOR_ARROW_HEIGHT = 17 +CONNECTOR_ARROW_BASE = 10 +CONNECTOR_ARROW_HEIGHT = 13 # possible rotations in degrees POSSIBLE_ROTATIONS = (0, 90, 180, 270) -# How close can the mouse get to the window border before mouse events are ignored. -BORDER_PROXIMITY_SENSITIVITY = 50 - # How close the mouse can get to the edge of the visible window before scrolling is invoked. -SCROLL_PROXIMITY_SENSITIVITY = 30 +SCROLL_PROXIMITY_SENSITIVITY = 50 # When the window has to be scrolled, move it this distance in the required direction. SCROLL_DISTANCE = 15 @@ -96,8 +93,18 @@ SCROLL_DISTANCE = 15 # How close the mouse click can be to a line and register a connection select. LINE_SELECT_SENSITIVITY = 5 -_SCREEN_RESOLUTION = gtk.gdk.screen_get_default().get_resolution() -DPI_SCALING = _SCREEN_RESOLUTION / 96.0 if _SCREEN_RESOLUTION > 0 else 1.0 +DEFAULT_BLOCK_MODULE_TOOLTIP = """\ +This subtree holds all blocks (from OOT modules) that specify no module name. \ +The module name is the root category enclosed in square brackets. + +Please consider contacting OOT module maintainer for any block in here \ +and kindly ask to update their GRC Block Descriptions or Block Tree to include a module name.""" + + +# _SCREEN = Gdk.Screen.get_default() +# _SCREEN_RESOLUTION = _SCREEN.get_resolution() if _SCREEN else -1 +# DPI_SCALING = _SCREEN_RESOLUTION / 96.0 if _SCREEN_RESOLUTION > 0 else 1.0 +DPI_SCALING = 1.0 # todo: figure out the GTK3 way (maybe cairo does this for us def update_font_size(font_size): diff --git a/grc/gui/Dialogs.py b/grc/gui/Dialogs.py index 83ad9651b2..51213a6154 100644 --- a/grc/gui/Dialogs.py +++ b/grc/gui/Dialogs.py @@ -1,33 +1,36 @@ -""" -Copyright 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import gtk +# Copyright 2008, 2009, 2016 Free Software Foundation, Inc. +# This file is part of GNU Radio +# +# GNU Radio Companion 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 2 +# of the License, or (at your option) any later version. +# +# GNU Radio Companion 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +from __future__ import absolute_import import sys +import textwrap from distutils.spawn import find_executable -from . import Utils, Actions +from gi.repository import Gtk + +from . import Utils, Actions, Constants from ..core import Messages -class SimpleTextDisplay(gtk.TextView): - """A non editable gtk text view.""" +class SimpleTextDisplay(Gtk.TextView): + """ + A non user-editable gtk text view. + """ def __init__(self, text=''): """ @@ -36,16 +39,18 @@ class SimpleTextDisplay(gtk.TextView): Args: text: the text to display (string) """ - text_buffer = gtk.TextBuffer() - text_buffer.set_text(text) - self.set_text = text_buffer.set_text - gtk.TextView.__init__(self, text_buffer) + Gtk.TextView.__init__(self) + self.set_text = self.get_buffer().set_text + self.set_text(text) self.set_editable(False) self.set_cursor_visible(False) - self.set_wrap_mode(gtk.WRAP_WORD_CHAR) + self.set_wrap_mode(Gtk.WrapMode.WORD_CHAR) class TextDisplay(SimpleTextDisplay): + """ + A non user-editable scrollable text view with popup menu. + """ def __init__(self, text=''): """ @@ -59,220 +64,311 @@ class TextDisplay(SimpleTextDisplay): self.connect("populate-popup", self.populate_popup) def insert(self, line): - # make backspaces work + """ + Append text after handling backspaces and auto-scroll. + + Args: + line: the text to append (string) + """ line = self._consume_backspaces(line) - # add the remaining text to buffer self.get_buffer().insert(self.get_buffer().get_end_iter(), line) - # Automatically scroll on insert self.scroll_to_end() def _consume_backspaces(self, line): - """removes text from the buffer if line starts with \b*""" - if not line: return + """ + Removes text from the buffer if line starts with '\b' + + Args: + line: a string which may contain backspaces + + Returns: + The string that remains from 'line' with leading '\b's removed. + """ + if not line: + return + # for each \b delete one char from the buffer back_count = 0 start_iter = self.get_buffer().get_end_iter() while len(line) > back_count and line[back_count] == '\b': # stop at the beginning of a line - if not start_iter.starts_line(): start_iter.backward_char() + if not start_iter.starts_line(): + start_iter.backward_char() back_count += 1 - # remove chars + # remove chars from buffer self.get_buffer().delete(start_iter, self.get_buffer().get_end_iter()) - # return remaining text return line[back_count:] def scroll_to_end(self): + """ Update view's scroll position. """ if self.scroll_lock: - buffer = self.get_buffer() - buffer.move_mark(buffer.get_insert(), buffer.get_end_iter()) - self.scroll_to_mark(buffer.get_insert(), 0.0) + buf = self.get_buffer() + mark = buf.get_insert() + buf.move_mark(mark, buf.get_end_iter()) + self.scroll_mark_onscreen(mark) def clear(self): - buffer = self.get_buffer() - buffer.delete(buffer.get_start_iter(), buffer.get_end_iter()) + """ Clear all text from buffer. """ + buf = self.get_buffer() + buf.delete(buf.get_start_iter(), buf.get_end_iter()) def save(self, file_path): - console_file = open(file_path, 'w') - buffer = self.get_buffer() - console_file.write(buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), True)) - console_file.close() + """ + Save context of buffer to the given file. - # Callback functions to handle the scrolling lock and clear context menus options - # Action functions are set by the ActionHandler's init function + Args: + file_path: location to save buffer contents + """ + with open(file_path, 'w') as logfile: + buf = self.get_buffer() + logfile.write(buf.get_text(buf.get_start_iter(), + buf.get_end_iter(), True)) + + # Action functions are set by the Application's init function def clear_cb(self, menu_item, web_view): + """ Callback function to clear the text buffer """ Actions.CLEAR_CONSOLE() def scroll_back_cb(self, menu_item, web_view): + """ Callback function to toggle scroll lock """ Actions.TOGGLE_SCROLL_LOCK() def save_cb(self, menu_item, web_view): + """ Callback function to save the buffer """ Actions.SAVE_CONSOLE() def populate_popup(self, view, menu): """Create a popup menu for the scroll lock and clear functions""" - menu.append(gtk.SeparatorMenuItem()) + menu.append(Gtk.SeparatorMenuItem()) - lock = gtk.CheckMenuItem("Scroll Lock") + lock = Gtk.CheckMenuItem("Scroll Lock") menu.append(lock) lock.set_active(self.scroll_lock) lock.connect('activate', self.scroll_back_cb, view) - save = gtk.ImageMenuItem(gtk.STOCK_SAVE) + save = Gtk.ImageMenuItem(Gtk.STOCK_SAVE) menu.append(save) save.connect('activate', self.save_cb, view) - clear = gtk.ImageMenuItem(gtk.STOCK_CLEAR) + clear = Gtk.ImageMenuItem(Gtk.STOCK_CLEAR) menu.append(clear) clear.connect('activate', self.clear_cb, view) menu.show_all() return False -def MessageDialogHelper(type, buttons, title=None, markup=None, default_response=None, extra_buttons=None): - """ - Create a modal message dialog and run it. +class MessageDialogWrapper(Gtk.MessageDialog): + """ Run a message dialog. """ - Args: - type: the type of message: gtk.MESSAGE_INFO, gtk.MESSAGE_WARNING, gtk.MESSAGE_QUESTION or gtk.MESSAGE_ERROR - buttons: the predefined set of buttons to use: - gtk.BUTTONS_NONE, gtk.BUTTONS_OK, gtk.BUTTONS_CLOSE, gtk.BUTTONS_CANCEL, gtk.BUTTONS_YES_NO, gtk.BUTTONS_OK_CANCEL + def __init__(self, parent, message_type, buttons, title=None, markup=None, + default_response=None, extra_buttons=None): + """ + Create a modal message dialog. - Args: - title: the title of the window (string) - markup: the message text with pango markup - default_response: if set, determines which button is highlighted by default - extra_buttons: a tuple containing pairs of values; each value is the button's text and the button's return value + Args: + message_type: the type of message may be one of: + Gtk.MessageType.INFO + Gtk.MessageType.WARNING + Gtk.MessageType.QUESTION or Gtk.MessageType.ERROR + buttons: the predefined set of buttons to use: + Gtk.ButtonsType.NONE + Gtk.ButtonsType.OK + Gtk.ButtonsType.CLOSE + Gtk.ButtonsType.CANCEL + Gtk.ButtonsType.YES_NO + Gtk.ButtonsType.OK_CANCEL + title: the title of the window (string) + markup: the message text with pango markup + default_response: if set, determines which button is highlighted by default + extra_buttons: a tuple containing pairs of values: + each value is the button's text and the button's return value - Returns: - the gtk response from run() - """ - message_dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, type, buttons) - if title: message_dialog.set_title(title) - if markup: message_dialog.set_markup(markup) - if extra_buttons: message_dialog.add_buttons(*extra_buttons) - if default_response: message_dialog.set_default_response(default_response) - response = message_dialog.run() - message_dialog.destroy() - return response - - -ERRORS_MARKUP_TMPL="""\ -#for $i, $err_msg in enumerate($errors) -<b>Error $i:</b> -$encode($err_msg.replace('\t', ' ')) - -#end for""" - - -def ErrorsDialog(flowgraph): MessageDialogHelper( - type=gtk.MESSAGE_ERROR, - buttons=gtk.BUTTONS_CLOSE, - title='Flow Graph Errors', - markup=Utils.parse_template(ERRORS_MARKUP_TMPL, errors=flowgraph.get_error_messages()), -) - - -class AboutDialog(gtk.AboutDialog): - """A cute little about dialog.""" - - def __init__(self, config): - """AboutDialog constructor.""" - gtk.AboutDialog.__init__(self) - self.set_name(config.name) - self.set_version(config.version) - self.set_license(config.license) - self.set_copyright(config.license.splitlines()[0]) - self.set_website(config.website) - self.run() - self.destroy() - - -def HelpDialog(): MessageDialogHelper( - type=gtk.MESSAGE_INFO, - buttons=gtk.BUTTONS_CLOSE, - title='Help', - markup="""\ -<b>Usage Tips</b> - -<u>Add block</u>: drag and drop or double click a block in the block selection window. -<u>Rotate block</u>: Select a block, press left/right on the keyboard. -<u>Change type</u>: Select a block, press up/down on the keyboard. -<u>Edit parameters</u>: double click on a block in the flow graph. -<u>Make connection</u>: click on the source port of one block, then click on the sink port of another block. -<u>Remove connection</u>: select the connection and press delete, or drag the connection. - -* See the menu for other keyboard shortcuts.""") - -COLORS_DIALOG_MARKUP_TMPL = """\ -<b>Color Mapping</b> - -#if $colors - #set $max_len = max([len(color[0]) for color in $colors]) + 10 - #for $title, $color_spec in $colors -<span background="$color_spec"><tt>$($encode($title).center($max_len))</tt></span> - #end for -#end if -""" - - -def TypesDialog(platform): - MessageDialogHelper( - type=gtk.MESSAGE_INFO, - buttons=gtk.BUTTONS_CLOSE, - title='Types', - markup=Utils.parse_template(COLORS_DIALOG_MARKUP_TMPL, - colors=platform.get_colors()) + """ + Gtk.MessageDialog.__init__( + self, transient_for=parent, modal=True, destroy_with_parent=True, + message_type=message_type, buttons=buttons + ) + if title: + self.set_title(title) + if markup: + self.set_markup(markup) + if extra_buttons: + self.add_buttons(*extra_buttons) + if default_response: + self.set_default_response(default_response) + + def run_and_destroy(self): + response = self.run() + self.hide() + return response + + +class ErrorsDialog(Gtk.Dialog): + """ Display flowgraph errors. """ + + def __init__(self, parent, flowgraph): + """Create a listview of errors""" + Gtk.Dialog.__init__( + self, + title='Errors and Warnings', + transient_for=parent, + modal=True, + destroy_with_parent=True, + ) + self.add_buttons(Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT) + self.set_size_request(750, Constants.MIN_DIALOG_HEIGHT) + self.set_border_width(10) + + self.store = Gtk.ListStore(str, str, str) + self.update(flowgraph) + + self.treeview = Gtk.TreeView(model=self.store) + for i, column_title in enumerate(["Block", "Aspect", "Message"]): + renderer = Gtk.CellRendererText() + column = Gtk.TreeViewColumn(column_title, renderer, text=i) + column.set_sort_column_id(i) # liststore id matches treeview id + column.set_resizable(True) + self.treeview.append_column(column) + + self.scrollable = Gtk.ScrolledWindow() + self.scrollable.set_vexpand(True) + self.scrollable.add(self.treeview) + + self.vbox.pack_start(self.scrollable, True, True, 0) + self.show_all() + + def update(self, flowgraph): + self.store.clear() + for element, message in flowgraph.iter_error_messages(): + if element.is_block: + src, aspect = element.get_id(), '' + elif element.is_connection: + src = element.source_block.get_id() + aspect = "Connection to '{}'".format(element.sink_block.get_id()) + elif element.is_port: + src = element.parent_block.get_id() + aspect = "{} '{}'".format('Sink' if element.is_sink else 'Source', element.name) + elif element.is_param: + src = element.parent_block.get_id() + aspect = "Param '{}'".format(element.name) + else: + src = aspect = '' + self.store.append([src, aspect, message]) + + def run_and_destroy(self): + response = self.run() + self.hide() + return response + + +def show_about(parent, config): + ad = Gtk.AboutDialog(transient_for=parent) + ad.set_program_name(config.name) + ad.set_name('') + ad.set_version(config.version) + ad.set_license(config.license) + + try: + ad.set_logo(Gtk.IconTheme().load_icon('gnuradio-grc', 64, 0)) + except: + pass + + ad.set_copyright(config.license.splitlines()[0]) + ad.set_website(config.website) + + ad.connect("response", lambda action, param: action.hide()) + ad.show() + + +def show_help(parent): + """ Display basic usage tips. """ + markup = textwrap.dedent("""\ + <b>Usage Tips</b> + \n\ + <u>Add block</u>: drag and drop or double click a block in the block selection window. + <u>Rotate block</u>: Select a block, press left/right on the keyboard. + <u>Change type</u>: Select a block, press up/down on the keyboard. + <u>Edit parameters</u>: double click on a block in the flow graph. + <u>Make connection</u>: click on the source port of one block, then click on the sink port of another block. + <u>Remove connection</u>: select the connection and press delete, or drag the connection. + \n\ + * See the menu for other keyboard shortcuts.\ + """) + + MessageDialogWrapper( + parent, Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, title='Help', markup=markup + ).run_and_destroy() + + +def show_types(parent): + """ Display information about standard data types. """ + colors = [(name, color) for name, key, sizeof, color in Constants.CORE_TYPES] + max_len = 10 + max(len(name) for name, code in colors) + + message = '\n'.join( + '<span background="{color}"><tt>{name}</tt></span>' + ''.format(color=color, name=Utils.encode(name).center(max_len)) + for name, color in colors ) + MessageDialogWrapper( + parent, Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, title='Types - Color Mapping', markup=message + ).run_and_destroy() -def MissingXTermDialog(xterm): - MessageDialogHelper( - type=gtk.MESSAGE_WARNING, - buttons=gtk.BUTTONS_OK, - title='Warning: missing xterm executable', - markup=("The xterm executable {0!r} is missing.\n\n" - "You can change this setting in your gnuradio.conf, in " - "section [grc], 'xterm_executable'.\n" - "\n" - "(This message is shown only once)").format(xterm) - ) +def show_missing_xterm(parent, xterm): + markup = textwrap.dedent("""\ + The xterm executable {0!r} is missing. + You can change this setting in your gnurado.conf, in section [grc], 'xterm_executable'. + \n\ + (This message is shown only once)\ + """).format(xterm) + + MessageDialogWrapper( + parent, message_type=Gtk.MessageType.WARNING, buttons=Gtk.ButtonsType.OK, + title='Warning: missing xterm executable', markup=markup + ).run_and_destroy() + + +def choose_editor(parent, config): + """ + Give the option to either choose an editor or use the default. + """ + if config.editor and find_executable(config.editor): + return config.editor -def ChooseEditorDialog(config): - # Give the option to either choose an editor or use the default - # Always return true/false so the caller knows it was successful buttons = ( - 'Choose Editor', gtk.RESPONSE_YES, - 'Use Default', gtk.RESPONSE_NO, - gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL - ) - response = MessageDialogHelper( - gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, 'Choose Editor', - 'Would you like to choose the editor to use?', gtk.RESPONSE_YES, buttons + 'Choose Editor', Gtk.ResponseType.YES, + 'Use Default', Gtk.ResponseType.NO, + Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL ) + response = MessageDialogWrapper( + parent, message_type=Gtk.MessageType.QUESTION, buttons=Gtk.ButtonsType.NONE, + title='Choose Editor', markup='Would you like to choose the editor to use?', + default_response=Gtk.ResponseType.YES, extra_buttons=buttons + ).run_and_destroy() - # Handle the inital default/choose/cancel response + # Handle the initial default/choose/cancel response # User wants to choose the editor to use - if response == gtk.RESPONSE_YES: - file_dialog = gtk.FileChooserDialog( + editor = '' + if response == Gtk.ResponseType.YES: + file_dialog = Gtk.FileChooserDialog( 'Select an Editor...', None, - gtk.FILE_CHOOSER_ACTION_OPEN, - ('gtk-cancel', gtk.RESPONSE_CANCEL, 'gtk-open', gtk.RESPONSE_OK) + Gtk.FileChooserAction.OPEN, + ('gtk-cancel', Gtk.ResponseType.CANCEL, 'gtk-open', Gtk.ResponseType.OK), + transient_for=parent ) file_dialog.set_select_multiple(False) file_dialog.set_local_only(True) file_dialog.set_current_folder('/usr/bin') try: - if file_dialog.run() == gtk.RESPONSE_OK: - config.editor = file_path = file_dialog.get_filename() - file_dialog.destroy() - return file_path + if file_dialog.run() == Gtk.ResponseType.OK: + editor = file_dialog.get_filename() finally: - file_dialog.destroy() + file_dialog.hide() # Go with the default editor - elif response == gtk.RESPONSE_NO: - # Determine the platform + elif response == Gtk.ResponseType.NO: try: process = None if sys.platform.startswith('linux'): @@ -282,13 +378,10 @@ def ChooseEditorDialog(config): if process is None: raise ValueError("Can't find default editor executable") # Save - config.editor = process - return process + editor = config.editor = process except Exception: Messages.send('>>> Unable to load the default editor. Please choose an editor.\n') - # Just reset of the constant and force the user to select an editor the next time - config.editor = '' - return - Messages.send('>>> No editor selected.\n') - return + if editor == '': + Messages.send('>>> No editor selected.\n') + return editor diff --git a/grc/gui/DrawingArea.py b/grc/gui/DrawingArea.py index 6a1df27a8c..648f1df849 100644 --- a/grc/gui/DrawingArea.py +++ b/grc/gui/DrawingArea.py @@ -17,15 +17,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import pygtk -pygtk.require('2.0') -import gtk +from __future__ import absolute_import -from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT, DND_TARGETS -import Colors +from gi.repository import Gtk, Gdk +from .canvas.colors import FLOWGRAPH_BACKGROUND_COLOR +from . import Constants +from . import Actions -class DrawingArea(gtk.DrawingArea): + +class DrawingArea(Gtk.DrawingArea): """ DrawingArea is the gtk pixel map that graphical elements may draw themselves on. The drawing area also responds to mouse and key events. @@ -39,137 +40,225 @@ class DrawingArea(gtk.DrawingArea): Args: main_window: the main_window containing all flow graphs """ + Gtk.DrawingArea.__init__(self) + + self._flow_graph = flow_graph + self.set_property('can_focus', True) + + self.zoom_factor = 1.0 + self._update_after_zoom = False self.ctrl_mask = False self.mod1_mask = False - self._flow_graph = flow_graph - gtk.DrawingArea.__init__(self) - self.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) + self.button_state = [False] * 10 + + # self.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) self.connect('realize', self._handle_window_realize) - self.connect('configure-event', self._handle_window_configure) - self.connect('expose-event', self._handle_window_expose) + self.connect('draw', self.draw) self.connect('motion-notify-event', self._handle_mouse_motion) self.connect('button-press-event', self._handle_mouse_button_press) self.connect('button-release-event', self._handle_mouse_button_release) self.connect('scroll-event', self._handle_mouse_scroll) self.add_events( - gtk.gdk.BUTTON_PRESS_MASK | \ - gtk.gdk.POINTER_MOTION_MASK | \ - gtk.gdk.BUTTON_RELEASE_MASK | \ - gtk.gdk.LEAVE_NOTIFY_MASK | \ - gtk.gdk.ENTER_NOTIFY_MASK | \ - gtk.gdk.FOCUS_CHANGE_MASK + Gdk.EventMask.BUTTON_PRESS_MASK | + Gdk.EventMask.POINTER_MOTION_MASK | + Gdk.EventMask.BUTTON_RELEASE_MASK | + Gdk.EventMask.SCROLL_MASK | + Gdk.EventMask.LEAVE_NOTIFY_MASK | + Gdk.EventMask.ENTER_NOTIFY_MASK + # Gdk.EventMask.FOCUS_CHANGE_MASK ) - #setup drag and drop - self.drag_dest_set(gtk.DEST_DEFAULT_ALL, DND_TARGETS, gtk.gdk.ACTION_COPY) + + # This may not be the correct place to be handling the user events + # Should this be in the page instead? + # Or should more of the page functionality move here? + self.connect('key_press_event', self._handle_key_press) + + # setup drag and drop + self.drag_dest_set(Gtk.DestDefaults.ALL, [], Gdk.DragAction.COPY) self.connect('drag-data-received', self._handle_drag_data_received) - #setup the focus flag + self.drag_dest_set_target_list(None) + self.drag_dest_add_text_targets() + + # setup the focus flag self._focus_flag = False self.get_focus_flag = lambda: self._focus_flag - def _handle_notify_event(widget, event, focus_flag): self._focus_flag = focus_flag + + def _handle_notify_event(widget, event, focus_flag): + self._focus_flag = focus_flag + self.connect('leave-notify-event', _handle_notify_event, False) self.connect('enter-notify-event', _handle_notify_event, True) - self.set_flags(gtk.CAN_FOCUS) # self.set_can_focus(True) - self.connect('focus-out-event', self._handle_focus_lost_event) - - def new_pixmap(self, width, height): - return gtk.gdk.Pixmap(self.window, width, height, -1) + # todo: fix +# self.set_flags(Gtk.CAN_FOCUS) # self.set_can_focus(True) +# self.connect('focus-out-event', self._handle_focus_lost_event) - def get_screenshot(self, transparent_bg=False): - pixmap = self._pixmap - W, H = pixmap.get_size() - pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, 0, 8, W, H) - pixbuf.fill(0xFF + Colors.FLOWGRAPH_BACKGROUND_COLOR.pixel << 8) - pixbuf.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, W-1, H-1) - if transparent_bg: - bgc = Colors.FLOWGRAPH_BACKGROUND_COLOR - pixbuf = pixbuf.add_alpha(True, bgc.red, bgc.green, bgc.blue) - return pixbuf + # Setup a map of the accelerator keys to the action to trigger + self.accels = { + Gtk.accelerator_parse('d'): Actions.BLOCK_DISABLE, + Gtk.accelerator_parse('e'): Actions.BLOCK_ENABLE, + Gtk.accelerator_parse('b'): Actions.BLOCK_BYPASS, + Gtk.accelerator_parse('c'): Actions.BLOCK_CREATE_HIER, + Gtk.accelerator_parse('Up'): Actions.BLOCK_DEC_TYPE, + Gtk.accelerator_parse('Down'): Actions.BLOCK_INC_TYPE, + Gtk.accelerator_parse('Left'): Actions.BLOCK_ROTATE_CCW, + Gtk.accelerator_parse('Right'): Actions.BLOCK_ROTATE_CW, + Gtk.accelerator_parse('minus'): Actions.PORT_CONTROLLER_DEC, + Gtk.accelerator_parse('plus'): Actions.PORT_CONTROLLER_INC, + Gtk.accelerator_parse('Add'): Actions.PORT_CONTROLLER_INC, + Gtk.accelerator_parse('Subtract'): Actions.PORT_CONTROLLER_DEC, + Gtk.accelerator_parse('Return'): Actions.BLOCK_PARAM_MODIFY, + Gtk.accelerator_parse('<Shift>t'): Actions.BLOCK_VALIGN_TOP, + Gtk.accelerator_parse('<Shift>m'): Actions.BLOCK_VALIGN_MIDDLE, + Gtk.accelerator_parse('<Shift>b'): Actions.BLOCK_VALIGN_BOTTOM, + Gtk.accelerator_parse('<Shift>l'): Actions.BLOCK_HALIGN_LEFT, + Gtk.accelerator_parse('<Shift>c'): Actions.BLOCK_HALIGN_CENTER, + Gtk.accelerator_parse('<Shift>r'): Actions.BLOCK_HALIGN_RIGHT, + } ########################################################################## - ## Handlers + # Handlers ########################################################################## def _handle_drag_data_received(self, widget, drag_context, x, y, selection_data, info, time): """ Handle a drag and drop by adding a block at the given coordinate. """ - self._flow_graph.add_new_block(selection_data.data, (x, y)) + coords = x / self.zoom_factor, y / self.zoom_factor + self._flow_graph.add_new_block(selection_data.get_text(), coords) def _handle_mouse_scroll(self, widget, event): - if event.state & gtk.gdk.SHIFT_MASK: - if event.direction == gtk.gdk.SCROLL_UP: - event.direction = gtk.gdk.SCROLL_LEFT - else: - event.direction = gtk.gdk.SCROLL_RIGHT + if event.get_state() & Gdk.ModifierType.CONTROL_MASK: + change = 1.2 if event.direction == Gdk.ScrollDirection.UP else 1/1.2 + zoom_factor = min(max(self.zoom_factor * change, 0.1), 5.0) + + if zoom_factor != self.zoom_factor: + self.zoom_factor = zoom_factor + self._update_after_zoom = True + self.queue_draw() + return True + + return False def _handle_mouse_button_press(self, widget, event): """ Forward button click information to the flow graph. """ self.grab_focus() - self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK - self.mod1_mask = event.state & gtk.gdk.MOD1_MASK - if event.button == 1: self._flow_graph.handle_mouse_selector_press( - double_click=(event.type == gtk.gdk._2BUTTON_PRESS), - coordinate=(event.x, event.y), - ) - if event.button == 3: self._flow_graph.handle_mouse_context_press( - coordinate=(event.x, event.y), - event=event, - ) + self.ctrl_mask = event.get_state() & Gdk.ModifierType.CONTROL_MASK + self.mod1_mask = event.get_state() & Gdk.ModifierType.MOD1_MASK + self.button_state[event.button] = True + + if event.button == 1: + double_click = (event.type == Gdk.EventType._2BUTTON_PRESS) + self.button_state[1] = not double_click + self._flow_graph.handle_mouse_selector_press( + double_click=double_click, + coordinate=self._translate_event_coords(event), + ) + elif event.button == 3: + self._flow_graph.handle_mouse_context_press( + coordinate=self._translate_event_coords(event), + event=event, + ) def _handle_mouse_button_release(self, widget, event): """ Forward button release information to the flow graph. """ - self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK - self.mod1_mask = event.state & gtk.gdk.MOD1_MASK - if event.button == 1: self._flow_graph.handle_mouse_selector_release( - coordinate=(event.x, event.y), - ) + self.ctrl_mask = event.get_state() & Gdk.ModifierType.CONTROL_MASK + self.mod1_mask = event.get_state() & Gdk.ModifierType.MOD1_MASK + self.button_state[event.button] = False + if event.button == 1: + self._flow_graph.handle_mouse_selector_release( + coordinate=self._translate_event_coords(event), + ) def _handle_mouse_motion(self, widget, event): """ Forward mouse motion information to the flow graph. """ - self.ctrl_mask = event.state & gtk.gdk.CONTROL_MASK - self.mod1_mask = event.state & gtk.gdk.MOD1_MASK + self.ctrl_mask = event.get_state() & Gdk.ModifierType.CONTROL_MASK + self.mod1_mask = event.get_state() & Gdk.ModifierType.MOD1_MASK + + if self.button_state[1]: + self._auto_scroll(event) + self._flow_graph.handle_mouse_motion( - coordinate=(event.x, event.y), + coordinate=self._translate_event_coords(event), ) + def _handle_key_press(self, widget, event): + """ + Handle specific keypresses when the drawing area has focus that + triggers actions by the user. + """ + key = event.keyval + mod = event.state + + try: + action = self.accels[(key, mod)] + action() + return True + except KeyError: + return False + + def _update_size(self): + w, h = self._flow_graph.get_extents()[2:] + self.set_size_request(w * self.zoom_factor + 100, h * self.zoom_factor + 100) + + def _auto_scroll(self, event): + x, y = event.x, event.y + scrollbox = self.get_parent().get_parent() + + self._update_size() + + def scroll(pos, adj): + """scroll if we moved near the border""" + adj_val = adj.get_value() + adj_len = adj.get_page_size() + if pos - adj_val > adj_len - Constants.SCROLL_PROXIMITY_SENSITIVITY: + adj.set_value(adj_val + Constants.SCROLL_DISTANCE) + adj.emit('changed') + elif pos - adj_val < Constants.SCROLL_PROXIMITY_SENSITIVITY: + adj.set_value(adj_val - Constants.SCROLL_DISTANCE) + adj.emit('changed') + + scroll(x, scrollbox.get_hadjustment()) + scroll(y, scrollbox.get_vadjustment()) + def _handle_window_realize(self, widget): """ Called when the window is realized. Update the flowgraph, which calls new pixmap. """ self._flow_graph.update() + self._update_size() - def _handle_window_configure(self, widget, event): - """ - Called when the window is resized. - Create a new pixmap for background buffer. - """ - self._pixmap = self.new_pixmap(*self.get_size_request()) + def draw(self, widget, cr): + width = widget.get_allocated_width() + height = widget.get_allocated_height() - def _handle_window_expose(self, widget, event): - """ - Called when window is exposed, or queue_draw is called. - Double buffering: draw to pixmap, then draw pixmap to window. - """ - gc = self.window.new_gc() - self._flow_graph.draw(gc, self._pixmap) - self.window.draw_drawable(gc, self._pixmap, 0, 0, 0, 0, -1, -1) - # draw a light grey line on the bottom and right end of the canvas. - # this is useful when the theme uses the same panel bg color as the canvas - W, H = self._pixmap.get_size() - gc.set_foreground(Colors.FLOWGRAPH_EDGE_COLOR) - self.window.draw_line(gc, 0, H-1, W, H-1) - self.window.draw_line(gc, W-1, 0, W-1, H) + cr.set_source_rgba(*FLOWGRAPH_BACKGROUND_COLOR) + cr.rectangle(0, 0, width, height) + cr.fill() + + cr.scale(self.zoom_factor, self.zoom_factor) + cr.set_line_width(2.0 / self.zoom_factor) + + if self._update_after_zoom: + self._flow_graph.create_labels(cr) + self._flow_graph.create_shapes() + self._update_size() + self._update_after_zoom = False + + self._flow_graph.draw(cr) + + def _translate_event_coords(self, event): + return event.x / self.zoom_factor, event.y / self.zoom_factor def _handle_focus_lost_event(self, widget, event): # don't clear selection while context menu is active - if not self._flow_graph.get_context_menu().flags() & gtk.VISIBLE: + if not self._flow_graph.context_menu.get_take_focus(): self._flow_graph.unselect() self._flow_graph.update_selected() self._flow_graph.queue_draw() diff --git a/grc/gui/Element.py b/grc/gui/Element.py deleted file mode 100644 index 9385424772..0000000000 --- a/grc/gui/Element.py +++ /dev/null @@ -1,278 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -from Constants import LINE_SELECT_SENSITIVITY -from Constants import POSSIBLE_ROTATIONS - -import gtk - - -class Element(object): - """ - GraphicalElement is the base class for all graphical elements. - It contains an X,Y coordinate, a list of rectangular areas that the element occupies, - and methods to detect selection of those areas. - """ - - def __init__(self): - """ - Make a new list of rectangular areas and lines, and set the coordinate and the rotation. - """ - self.set_rotation(POSSIBLE_ROTATIONS[0]) - self.set_coordinate((0, 0)) - self.clear() - self.set_highlighted(False) - self.line_attributes = [ - 0, gtk.gdk.LINE_SOLID, gtk.gdk.CAP_BUTT, gtk.gdk.JOIN_MITER - ] - - def is_horizontal(self, rotation=None): - """ - Is this element horizontal? - If rotation is None, use this element's rotation. - - Args: - rotation: the optional rotation - - Returns: - true if rotation is horizontal - """ - rotation = rotation or self.get_rotation() - return rotation in (0, 180) - - def is_vertical(self, rotation=None): - """ - Is this element vertical? - If rotation is None, use this element's rotation. - - Args: - rotation: the optional rotation - - Returns: - true if rotation is vertical - """ - rotation = rotation or self.get_rotation() - return rotation in (90, 270) - - def create_labels(self): - """ - Create labels (if applicable) and call on all children. - Call this base method before creating labels in the element. - """ - for child in self.get_children():child.create_labels() - - def create_shapes(self): - """ - Create shapes (if applicable) and call on all children. - Call this base method before creating shapes in the element. - """ - self.clear() - for child in self.get_children(): child.create_shapes() - - def draw(self, gc, window, border_color, bg_color): - """ - Draw in the given window. - - Args: - gc: the graphics context - window: the gtk window to draw on - border_color: the color for lines and rectangle borders - bg_color: the color for the inside of the rectangle - """ - X, Y = self.get_coordinate() - gc.set_line_attributes(*self.line_attributes) - for (rX, rY), (W, H) in self._areas_list: - aX = X + rX - aY = Y + rY - gc.set_foreground(bg_color) - window.draw_rectangle(gc, True, aX, aY, W, H) - gc.set_foreground(border_color) - window.draw_rectangle(gc, False, aX, aY, W, H) - for (x1, y1), (x2, y2) in self._lines_list: - gc.set_foreground(border_color) - gc.set_background(bg_color) - window.draw_line(gc, X+x1, Y+y1, X+x2, Y+y2) - - def rotate(self, rotation): - """ - Rotate all of the areas by 90 degrees. - - Args: - rotation: multiple of 90 degrees - """ - self.set_rotation((self.get_rotation() + rotation)%360) - - def clear(self): - """Empty the lines and areas.""" - self._areas_list = list() - self._lines_list = list() - - def set_coordinate(self, coor): - """ - Set the reference coordinate. - - Args: - coor: the coordinate tuple (x,y) - """ - self.coor = coor - - # def get_parent(self): - # """ - # Get the parent of this element. - # - # Returns: - # the parent - # """ - # return self.parent - - def set_highlighted(self, highlighted): - """ - Set the highlight status. - - Args: - highlighted: true to enable highlighting - """ - self.highlighted = highlighted - - def is_highlighted(self): - """ - Get the highlight status. - - Returns: - true if highlighted - """ - return self.highlighted - - def get_coordinate(self): - """Get the coordinate. - - Returns: - the coordinate tuple (x,y) - """ - return self.coor - - def move(self, delta_coor): - """ - Move the element by adding the delta_coor to the current coordinate. - - Args: - delta_coor: (delta_x,delta_y) tuple - """ - deltaX, deltaY = delta_coor - X, Y = self.get_coordinate() - self.set_coordinate((X+deltaX, Y+deltaY)) - - def add_area(self, rel_coor, area): - """ - Add an area to the area list. - An area is actually a coordinate relative to the main coordinate - with a width/height pair relative to the area coordinate. - A positive width is to the right of the coordinate. - A positive height is above the coordinate. - The area is associated with a rotation. - - Args: - rel_coor: (x,y) offset from this element's coordinate - area: (width,height) tuple - """ - self._areas_list.append((rel_coor, area)) - - def add_line(self, rel_coor1, rel_coor2): - """ - Add a line to the line list. - A line is defined by 2 relative coordinates. - Lines must be horizontal or vertical. - The line is associated with a rotation. - - Args: - rel_coor1: relative (x1,y1) tuple - rel_coor2: relative (x2,y2) tuple - """ - self._lines_list.append((rel_coor1, rel_coor2)) - - def what_is_selected(self, coor, coor_m=None): - """ - One coordinate specified: - Is this element selected at given coordinate? - ie: is the coordinate encompassed by one of the areas or lines? - Both coordinates specified: - Is this element within the rectangular region defined by both coordinates? - ie: do any area corners or line endpoints fall within the region? - - Args: - coor: the selection coordinate, tuple x, y - coor_m: an additional selection coordinate. - - Returns: - self if one of the areas/lines encompasses coor, else None. - """ - #function to test if p is between a and b (inclusive) - in_between = lambda p, a, b: p >= min(a, b) and p <= max(a, b) - #relative coordinate - x, y = [a-b for a,b in zip(coor, self.get_coordinate())] - if coor_m: - x_m, y_m = [a-b for a,b in zip(coor_m, self.get_coordinate())] - #handle rectangular areas - for (x1,y1), (w,h) in self._areas_list: - if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \ - in_between(x1+w, x, x_m) and in_between(y1, y, y_m) or \ - in_between(x1, x, x_m) and in_between(y1+h, y, y_m) or \ - in_between(x1+w, x, x_m) and in_between(y1+h, y, y_m): - return self - #handle horizontal or vertical lines - for (x1, y1), (x2, y2) in self._lines_list: - if in_between(x1, x, x_m) and in_between(y1, y, y_m) or \ - in_between(x2, x, x_m) and in_between(y2, y, y_m): - return self - return None - else: - #handle rectangular areas - for (x1,y1), (w,h) in self._areas_list: - if in_between(x, x1, x1+w) and in_between(y, y1, y1+h): return self - #handle horizontal or vertical lines - for (x1, y1), (x2, y2) in self._lines_list: - if x1 == x2: x1, x2 = x1-LINE_SELECT_SENSITIVITY, x2+LINE_SELECT_SENSITIVITY - if y1 == y2: y1, y2 = y1-LINE_SELECT_SENSITIVITY, y2+LINE_SELECT_SENSITIVITY - if in_between(x, x1, x2) and in_between(y, y1, y2): return self - return None - - def get_rotation(self): - """ - Get the rotation in degrees. - - Returns: - the rotation - """ - return self.rotation - - def set_rotation(self, rotation): - """ - Set the rotation in degrees. - - Args: - rotation: the rotation""" - if rotation not in POSSIBLE_ROTATIONS: - raise Exception('"%s" is not one of the possible rotations: (%s)'%(rotation, POSSIBLE_ROTATIONS)) - self.rotation = rotation - - def mouse_over(self): - pass - - def mouse_out(self): - pass diff --git a/grc/gui/Executor.py b/grc/gui/Executor.py index f5a75ab55b..552a7554dc 100644 --- a/grc/gui/Executor.py +++ b/grc/gui/Executor.py @@ -15,14 +15,16 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +from __future__ import absolute_import + +import os +import shlex import subprocess import threading from distutils.spawn import find_executable -import gobject -import os +from gi.repository import GLib -from ..core.utils import shlex from ..core import Messages @@ -32,20 +34,16 @@ class ExecFlowGraphThread(threading.Thread): def __init__(self, flow_graph_page, xterm_executable, callback): """ ExecFlowGraphThread constructor. - - Args: - action_handler: an instance of an ActionHandler """ threading.Thread.__init__(self) self.page = flow_graph_page # store page and dont use main window calls in run - self.flow_graph = self.page.get_flow_graph() + self.flow_graph = self.page.flow_graph self.xterm_executable = xterm_executable self.update_callback = callback try: - self.process = self._popen() - self.page.set_proc(self.process) + self.process = self.page.process = self._popen() self.update_callback() self.start() except Exception as e: @@ -79,18 +77,18 @@ class ExecFlowGraphThread(threading.Thread): def run(self): """ Wait on the executing process by reading from its stdout. - Use gobject.idle_add when calling functions that modify gtk objects. + Use GObject.idle_add when calling functions that modify gtk objects. """ # handle completion r = "\n" while r: - gobject.idle_add(Messages.send_verbose_exec, r) + GLib.idle_add(Messages.send_verbose_exec, r) r = os.read(self.process.stdout.fileno(), 1024) self.process.poll() - gobject.idle_add(self.done) + GLib.idle_add(self.done) def done(self): """Perform end of execution tasks.""" Messages.send_end_exec(self.process.returncode) - self.page.set_proc(None) + self.page.process = None self.update_callback() diff --git a/grc/gui/FileDialogs.py b/grc/gui/FileDialogs.py index 9d047b1ffd..dbcecf91ab 100644 --- a/grc/gui/FileDialogs.py +++ b/grc/gui/FileDialogs.py @@ -17,140 +17,99 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import pygtk -pygtk.require('2.0') -import gtk -from Dialogs import MessageDialogHelper -from Constants import \ - DEFAULT_FILE_PATH, IMAGE_FILE_EXTENSION, TEXT_FILE_EXTENSION, \ - NEW_FLOGRAPH_TITLE -import Preferences -from os import path -import Utils - -################################################## -# Constants -################################################## -OPEN_FLOW_GRAPH = 'open flow graph' -SAVE_FLOW_GRAPH = 'save flow graph' -SAVE_CONSOLE = 'save console' -SAVE_IMAGE = 'save image' -OPEN_QSS_THEME = 'open qss theme' - -FILE_OVERWRITE_MARKUP_TMPL="""\ -File <b>$encode($filename)</b> Exists!\nWould you like to overwrite the existing file?""" - -FILE_DNE_MARKUP_TMPL="""\ -File <b>$encode($filename)</b> Does not Exist!""" - - - -# File Filters -def get_flow_graph_files_filter(): - filter = gtk.FileFilter() - filter.set_name('Flow Graph Files') - filter.add_pattern('*'+Preferences.file_extension()) - return filter - - -def get_text_files_filter(): - filter = gtk.FileFilter() - filter.set_name('Text Files') - filter.add_pattern('*'+TEXT_FILE_EXTENSION) - return filter - - -def get_image_files_filter(): - filter = gtk.FileFilter() - filter.set_name('Image Files') - filter.add_pattern('*'+IMAGE_FILE_EXTENSION) - return filter +from __future__ import absolute_import +from os import path -def get_all_files_filter(): - filter = gtk.FileFilter() - filter.set_name('All Files') - filter.add_pattern('*') - return filter - +from gi.repository import Gtk -def get_qss_themes_filter(): - filter = gtk.FileFilter() - filter.set_name('QSS Themes') - filter.add_pattern('*.qss') - return filter +from . import Constants, Utils, Dialogs -# File Dialogs -class FileDialogHelper(gtk.FileChooserDialog): +class FileDialogHelper(Gtk.FileChooserDialog, object): """ A wrapper class for the gtk file chooser dialog. Implement a file chooser dialog with only necessary parameters. """ + title = '' + action = Gtk.FileChooserAction.OPEN + filter_label = '' + filter_ext = '' - def __init__(self, action, title): + def __init__(self, parent, current_file_path): """ FileDialogHelper contructor. Create a save or open dialog with cancel and ok buttons. Use standard settings: no multiple selection, local files only, and the * filter. Args: - action: gtk.FILE_CHOOSER_ACTION_OPEN or gtk.FILE_CHOOSER_ACTION_SAVE + action: Gtk.FileChooserAction.OPEN or Gtk.FileChooserAction.SAVE title: the title of the dialog (string) """ - ok_stock = {gtk.FILE_CHOOSER_ACTION_OPEN : 'gtk-open', gtk.FILE_CHOOSER_ACTION_SAVE : 'gtk-save'}[action] - gtk.FileChooserDialog.__init__(self, title, None, action, ('gtk-cancel', gtk.RESPONSE_CANCEL, ok_stock, gtk.RESPONSE_OK)) + ok_stock = { + Gtk.FileChooserAction.OPEN: 'gtk-open', + Gtk.FileChooserAction.SAVE: 'gtk-save' + }[self.action] + + Gtk.FileChooserDialog.__init__(self, title=self.title, action=self.action, + transient_for=parent) + self.add_buttons('gtk-cancel', Gtk.ResponseType.CANCEL, ok_stock, Gtk.ResponseType.OK) self.set_select_multiple(False) self.set_local_only(True) - self.add_filter(get_all_files_filter()) + + self.parent = parent + self.current_file_path = current_file_path or path.join( + Constants.DEFAULT_FILE_PATH, Constants.NEW_FLOGRAPH_TITLE + Constants.FILE_EXTENSION) + + self.set_current_folder(path.dirname(current_file_path)) # current directory + self.setup_filters() + + def setup_filters(self, filters=None): + set_default = True + filters = filters or ([(self.filter_label, self.filter_ext)] if self.filter_label else []) + filters.append(('All Files', '')) + for label, ext in filters: + if not label: + continue + f = Gtk.FileFilter() + f.set_name(label) + f.add_pattern('*' + ext) + self.add_filter(f) + if not set_default: + self.set_filter(f) + set_default = True + + def run(self): + """Get the filename and destroy the dialog.""" + response = Gtk.FileChooserDialog.run(self) + filename = self.get_filename() if response == Gtk.ResponseType.OK else None + self.destroy() + return filename -class FileDialog(FileDialogHelper): +class SaveFileDialog(FileDialogHelper): """A dialog box to save or open flow graph files. This is a base class, do not use.""" + action = Gtk.FileChooserAction.SAVE - def __init__(self, current_file_path=''): - """ - FileDialog constructor. + def __init__(self, parent, current_file_path): + super(SaveFileDialog, self).__init__(parent, current_file_path) + self.set_current_name(path.splitext(path.basename(self.current_file_path))[0] + self.filter_ext) + self.set_create_folders(True) + self.set_do_overwrite_confirmation(True) - Args: - current_file_path: the current directory or path to the open flow graph - """ - if not current_file_path: current_file_path = path.join(DEFAULT_FILE_PATH, NEW_FLOGRAPH_TITLE + Preferences.file_extension()) - if self.type == OPEN_FLOW_GRAPH: - FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 'Open a Flow Graph from a File...') - self.add_and_set_filter(get_flow_graph_files_filter()) - self.set_select_multiple(True) - elif self.type == SAVE_FLOW_GRAPH: - FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph to a File...') - self.add_and_set_filter(get_flow_graph_files_filter()) - self.set_current_name(path.basename(current_file_path)) - elif self.type == SAVE_CONSOLE: - FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save Console to a File...') - self.add_and_set_filter(get_text_files_filter()) - file_path = path.splitext(path.basename(current_file_path))[0] - self.set_current_name(file_path) #show the current filename - elif self.type == SAVE_IMAGE: - FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_SAVE, 'Save a Flow Graph Screen Shot...') - self.add_and_set_filter(get_image_files_filter()) - current_file_path = current_file_path + IMAGE_FILE_EXTENSION - self.set_current_name(path.basename(current_file_path)) #show the current filename - elif self.type == OPEN_QSS_THEME: - FileDialogHelper.__init__(self, gtk.FILE_CHOOSER_ACTION_OPEN, 'Open a QSS theme...') - self.add_and_set_filter(get_qss_themes_filter()) - self.set_select_multiple(False) - self.set_current_folder(path.dirname(current_file_path)) #current directory - - def add_and_set_filter(self, filter): - """ - Add the gtk file filter to the list of filters and set it as the default file filter. - Args: - filter: a gtk file filter. - """ - self.add_filter(filter) - self.set_filter(filter) +class OpenFileDialog(FileDialogHelper): + """A dialog box to save or open flow graph files. This is a base class, do not use.""" + action = Gtk.FileChooserAction.OPEN + + def show_missing_message(self, filename): + Dialogs.MessageDialogWrapper( + self.parent, + Gtk.MessageType.WARNING, Gtk.ButtonsType.CLOSE, 'Cannot Open!', + 'File <b>{filename}</b> Does not Exist!'.format(filename=Utils.encode(filename)), + ).run_and_destroy() - def get_rectified_filename(self): + def get_filename(self): """ Run the dialog and get the filename. If this is a save dialog and the file name is missing the extension, append the file extension. @@ -160,82 +119,82 @@ class FileDialog(FileDialogHelper): Returns: the complete file path """ - if gtk.FileChooserDialog.run(self) != gtk.RESPONSE_OK: return None #response was cancel - ############################################# - # Handle Save Dialogs - ############################################# - if self.type in (SAVE_FLOW_GRAPH, SAVE_CONSOLE, SAVE_IMAGE): - filename = self.get_filename() - extension = { - SAVE_FLOW_GRAPH: Preferences.file_extension(), - SAVE_CONSOLE: TEXT_FILE_EXTENSION, - SAVE_IMAGE: IMAGE_FILE_EXTENSION, - }[self.type] - #append the missing file extension if the filter matches - if path.splitext(filename)[1].lower() != extension: filename += extension - self.set_current_name(path.basename(filename)) #show the filename with extension - if path.exists(filename): #ask the user to confirm overwrite - if MessageDialogHelper( - gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO, 'Confirm Overwrite!', - Utils.parse_template(FILE_OVERWRITE_MARKUP_TMPL, filename=filename), - ) == gtk.RESPONSE_NO: return self.get_rectified_filename() - return filename - ############################################# - # Handle Open Dialogs - ############################################# - elif self.type in (OPEN_FLOW_GRAPH, OPEN_QSS_THEME): - filenames = self.get_filenames() - for filename in filenames: - if not path.exists(filename): #show a warning and re-run - MessageDialogHelper( - gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, 'Cannot Open!', - Utils.parse_template(FILE_DNE_MARKUP_TMPL, filename=filename), - ) - return self.get_rectified_filename() - return filenames + filenames = Gtk.FileChooserDialog.get_filenames(self) + for filename in filenames: + if not path.exists(filename): + self.show_missing_message(filename) + return None # rerun + return filenames - def run(self): - """ - Get the filename and destroy the dialog. - - Returns: - the filename or None if a close/cancel occurred. - """ - filename = self.get_rectified_filename() - self.destroy() - return filename +class OpenFlowGraph(OpenFileDialog): + title = 'Open a Flow Graph from a File...' + filter_label = 'Flow Graph Files' + filter_ext = Constants.FILE_EXTENSION -class OpenFlowGraphFileDialog(FileDialog): - type = OPEN_FLOW_GRAPH + def __init__(self, parent, current_file_path=''): + super(OpenFlowGraph, self).__init__(parent, current_file_path) + self.set_select_multiple(True) -class SaveFlowGraphFileDialog(FileDialog): - type = SAVE_FLOW_GRAPH +class OpenQSS(OpenFileDialog): + title = 'Open a QSS theme...' + filter_label = 'QSS Themes' + filter_ext = '.qss' -class OpenQSSFileDialog(FileDialog): - type = OPEN_QSS_THEME +class SaveFlowGraph(SaveFileDialog): + title = 'Save a Flow Graph to a File...' + filter_label = 'Flow Graph Files' + filter_ext = Constants.FILE_EXTENSION -class SaveConsoleFileDialog(FileDialog): - type = SAVE_CONSOLE +class SaveConsole(SaveFileDialog): + title = 'Save Console to a File...' + filter_label = 'Test Files' + filter_ext = '.txt' -class SaveImageFileDialog(FileDialog): - type = SAVE_IMAGE +class SaveScreenShot(SaveFileDialog): + title = 'Save a Flow Graph Screen Shot...' + filters = [('PDF Files', '.pdf'), ('PNG Files', '.png'), ('SVG Files', '.svg')] + filter_ext = '.pdf' # the default + def __init__(self, parent, current_file_path=''): + super(SaveScreenShot, self).__init__(parent, current_file_path) -class SaveScreenShotDialog(SaveImageFileDialog): + self.config = Gtk.Application.get_default().config - def __init__(self, current_file_path=''): - SaveImageFileDialog.__init__(self, current_file_path) - self._button = button = gtk.CheckButton('_Background transparent') - self._button.set_active(Preferences.screen_shot_background_transparent()) + self._button = button = Gtk.CheckButton(label='Background transparent') + self._button.set_active(self.config.screen_shot_background_transparent()) self.set_extra_widget(button) + def setup_filters(self, filters=None): + super(SaveScreenShot, self).setup_filters(self.filters) + + def show_missing_message(self, filename): + Dialogs.MessageDialogWrapper( + self.parent, + Gtk.MessageType.ERROR, Gtk.ButtonsType.CLOSE, 'Can not Save!', + 'File Extention of <b>{filename}</b> not supported!'.format(filename=Utils.encode(filename)), + ).run_and_destroy() + def run(self): - filename = SaveImageFileDialog.run(self) + valid_exts = {ext for label, ext in self.filters} + filename = None + while True: + response = Gtk.FileChooserDialog.run(self) + if response != Gtk.ResponseType.OK: + filename = None + break + + filename = self.get_filename() + if path.splitext(filename)[1] in valid_exts: + break + + self.show_missing_message(filename) + bg_transparent = self._button.get_active() - Preferences.screen_shot_background_transparent(bg_transparent) + self.config.screen_shot_background_transparent(bg_transparent) + self.destroy() return filename, bg_transparent diff --git a/grc/gui/MainWindow.py b/grc/gui/MainWindow.py index 54141af547..f913d63966 100644 --- a/grc/gui/MainWindow.py +++ b/grc/gui/MainWindow.py @@ -17,52 +17,32 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import + import os +import logging -import gtk +from gi.repository import Gtk, Gdk, GObject -from . import Bars, Actions, Preferences, Utils +from . import Bars, Actions, Utils from .BlockTreeWindow import BlockTreeWindow +from .Console import Console from .VariableEditor import VariableEditor from .Constants import \ NEW_FLOGRAPH_TITLE, DEFAULT_CONSOLE_WINDOW_WIDTH -from .Dialogs import TextDisplay, MessageDialogHelper -from .NotebookPage import NotebookPage +from .Dialogs import TextDisplay, MessageDialogWrapper +from .Notebook import Notebook, Page from ..core import Messages -MAIN_WINDOW_TITLE_TMPL = """\ -#if not $saved -*#slurp -#end if -#if $basename -$basename#slurp -#else -$new_flowgraph_title#slurp -#end if -#if $read_only - (read only)#slurp -#end if -#if $dirname - - $dirname#slurp -#end if - - $platform_name#slurp -""" -PAGE_TITLE_MARKUP_TMPL = """\ -#set $foreground = $saved and 'black' or 'red' -<span foreground="$foreground">$encode($title or $new_flowgraph_title)</span>#slurp -#if $read_only - (ro)#slurp -#end if -""" +log = logging.getLogger(__name__) ############################################################ # Main window ############################################################ - -class MainWindow(gtk.Window): +class MainWindow(Gtk.ApplicationWindow): """The topmost window with menus, the tool bar, and other major windows.""" # Constants the action handler can use to indicate which panel visibility to change. @@ -70,102 +50,111 @@ class MainWindow(gtk.Window): CONSOLE = 1 VARIABLES = 2 - def __init__(self, platform, action_handler_callback): + def __init__(self, app, platform): """ MainWindow constructor Setup the menu, toolbar, flow graph editor notebook, block selection window... """ - self._platform = platform + Gtk.ApplicationWindow.__init__(self, title="GNU Radio Companion", application=app) + log.debug("__init__()") - gen_opts = platform.blocks['options'].get_param('generate_options') - generate_mode_default = gen_opts.get_value() - generate_modes = [ - (o.get_key(), o.get_name(), o.get_key() == generate_mode_default) - for o in gen_opts.get_options()] + self._platform = platform + self.app = app + self.config = platform.config - # Load preferences - Preferences.load(platform) + # Add all "win" actions to the local + for x in Actions.get_actions(): + if x.startswith("win."): + self.add_action(Actions.actions[x]) # Setup window - gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) - vbox = gtk.VBox() + vbox = Gtk.VBox() self.add(vbox) # Set window icon self.set_icon_from_file(os.path.dirname(os.path.abspath(__file__)) + "/icon.png") # Create the menu bar and toolbar - self.add_accel_group(Actions.get_accel_group()) - self.menu_bar = Bars.MenuBar(generate_modes, action_handler_callback) - vbox.pack_start(self.menu_bar, False) - self.tool_bar = Bars.Toolbar(generate_modes, action_handler_callback) - vbox.pack_start(self.tool_bar, False) + generate_modes = platform.get_generate_options() + + # This needs to be replaced + # Have an option for either the application menu or this menu + self.menu_bar = Gtk.MenuBar.new_from_model(Bars.Menu()) + vbox.pack_start(self.menu_bar, False, False, 0) + + self.tool_bar = Bars.Toolbar() + self.tool_bar.set_hexpand(True) + # Show the toolbar + self.tool_bar.show() + vbox.pack_start(self.tool_bar, False, False, 0) # Main parent container for the different panels - self.container = gtk.HPaned() - vbox.pack_start(self.container) + self.main = Gtk.HPaned() #(orientation=Gtk.Orientation.HORIZONTAL) + vbox.pack_start(self.main, True, True, 0) # Create the notebook - self.notebook = gtk.Notebook() + self.notebook = Notebook() self.page_to_be_closed = None - self.current_page = None - self.notebook.set_show_border(False) - self.notebook.set_scrollable(True) # scroll arrows for page tabs - self.notebook.connect('switch-page', self._handle_page_change) + + self.current_page = None # type: Page # Create the console window - self.text_display = TextDisplay() - self.console_window = gtk.ScrolledWindow() - self.console_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.console_window.add(self.text_display) - self.console_window.set_size_request(-1, DEFAULT_CONSOLE_WINDOW_WIDTH) + self.console = Console() # Create the block tree and variable panels - self.btwin = BlockTreeWindow(platform, self.get_flow_graph) - self.vars = VariableEditor(platform, self.get_flow_graph) + self.btwin = BlockTreeWindow(platform) + self.btwin.connect('create_new_block', self._add_block_to_current_flow_graph) + self.vars = VariableEditor() + self.vars.connect('create_new_block', self._add_block_to_current_flow_graph) + self.vars.connect('remove_block', self._remove_block_from_current_flow_graph) # Figure out which place to put the variable editor - self.left = gtk.VPaned() - self.right = gtk.VPaned() - self.left_subpanel = gtk.HPaned() + self.left = Gtk.VPaned() #orientation=Gtk.Orientation.VERTICAL) + self.right = Gtk.VPaned() #orientation=Gtk.Orientation.VERTICAL) + self.left_subpanel = Gtk.HPaned() #orientation=Gtk.Orientation.HORIZONTAL) - self.variable_panel_sidebar = Preferences.variable_editor_sidebar() + self.variable_panel_sidebar = self.config.variable_editor_sidebar() if self.variable_panel_sidebar: self.left.pack1(self.notebook) - self.left.pack2(self.console_window, False) + self.left.pack2(self.console, False) self.right.pack1(self.btwin) self.right.pack2(self.vars, False) else: # Put the variable editor in a panel with the console self.left.pack1(self.notebook) - self.left_subpanel.pack1(self.console_window, shrink=False) + self.left_subpanel.pack1(self.console, shrink=False) self.left_subpanel.pack2(self.vars, resize=False, shrink=True) self.left.pack2(self.left_subpanel, False) # Create the right panel self.right.pack1(self.btwin) - self.container.pack1(self.left) - self.container.pack2(self.right, False) + self.main.pack1(self.left) + self.main.pack2(self.right, False) - # load preferences and show the main window - self.resize(*Preferences.main_window_size()) - self.container.set_position(Preferences.blocks_window_position()) - self.left.set_position(Preferences.console_window_position()) + # Load preferences and show the main window + self.resize(*self.config.main_window_size()) + self.main.set_position(self.config.blocks_window_position()) + self.left.set_position(self.config.console_window_position()) if self.variable_panel_sidebar: - self.right.set_position(Preferences.variable_editor_position(sidebar=True)) + self.right.set_position(self.config.variable_editor_position(sidebar=True)) else: - self.left_subpanel.set_position(Preferences.variable_editor_position()) + self.left_subpanel.set_position(self.config.variable_editor_position()) self.show_all() - self.console_window.hide() - self.vars.hide() - self.btwin.hide() + log.debug("Main window ready") ############################################################ # Event Handlers ############################################################ + def _add_block_to_current_flow_graph(self, widget, key): + self.current_flow_graph.add_new_block(key) + + def _remove_block_from_current_flow_graph(self, widget, key): + block = self.current_flow_graph.get_block(key) + self.current_flow_graph.remove_element(block) + def _quit(self, window, event): """ Handle the delete event from the main window. @@ -178,20 +167,6 @@ class MainWindow(gtk.Window): Actions.APPLICATION_QUIT() return True - def _handle_page_change(self, notebook, page, page_num): - """ - Handle a page change. When the user clicks on a new tab, - reload the flow graph to update the vars window and - call handle states (select nothing) to update the buttons. - - Args: - notebook: the notebook - page: new page - page_num: new page number - """ - self.current_page = self.notebook.get_nth_page(page_num) - Actions.PAGE_CHANGE() - def update_panel_visibility(self, panel, visibility=True): """ Handles changing visibility of panels. @@ -201,19 +176,19 @@ class MainWindow(gtk.Window): if panel == self.BLOCKS: if visibility: - self.btwin.show() + self.btwin.show() else: - self.btwin.hide() + self.btwin.hide() elif panel == self.CONSOLE: if visibility: - self.console_window.show() + self.console.show() else: - self.console_window.hide() + self.console.hide() elif panel == self.VARIABLES: if visibility: - self.vars.show() + self.vars.show() else: - self.vars.hide() + self.vars.hide() else: return @@ -228,7 +203,7 @@ class MainWindow(gtk.Window): self.right.hide() else: self.right.show() - if not (self.vars.get_property('visible')) and not (self.console_window.get_property('visible')): + if not (self.vars.get_property('visible')) and not (self.console.get_property('visible')): self.left_subpanel.hide() else: self.left_subpanel.show() @@ -237,6 +212,14 @@ class MainWindow(gtk.Window): # Console Window ############################################################ + @property + def current_page(self): + return self.notebook.current_page + + @current_page.setter + def current_page(self, page): + self.notebook.current_page = page + def add_console_line(self, line): """ Place line at the end of the text buffer, then scroll its window all the way down. @@ -244,7 +227,7 @@ class MainWindow(gtk.Window): Args: line: the new text """ - self.text_display.insert(line) + self.console.add_line(line) ############################################################ # Pages: create and close @@ -269,23 +252,21 @@ class MainWindow(gtk.Window): flow_graph = self._platform.get_new_flow_graph() flow_graph.grc_file_path = file_path #print flow_graph - page = NotebookPage( + page = Page( self, flow_graph=flow_graph, file_path=file_path, ) if file_path: Messages.send_end_load() - except Exception, e: #return on failure + except Exception as e: #return on failure Messages.send_fail_load(e) if isinstance(e, KeyError) and str(e) == "'options'": # This error is unrecoverable, so crash gracefully exit(-1) return #add this page to the notebook - self.notebook.append_page(page, page.get_tab()) - try: self.notebook.set_tab_reorderable(page, True) - except: pass #gtk too old - self.notebook.set_tab_label_packing(page, False, False, gtk.PACK_START) + self.notebook.append_page(page, page.tab) + self.notebook.set_tab_reorderable(page, True) #only show if blank or manual if not file_path or show: self._set_page(page) @@ -296,26 +277,26 @@ class MainWindow(gtk.Window): Returns: true if all closed """ - open_files = filter(lambda file: file, self._get_files()) #filter blank files - open_file = self.get_page().get_file_path() + open_files = [file for file in self._get_files() if file] #filter blank files + open_file = self.current_page.file_path #close each page - for page in sorted(self.get_pages(), key=lambda p: p.get_saved()): + for page in sorted(self.get_pages(), key=lambda p: p.saved): self.page_to_be_closed = page closed = self.close_page(False) if not closed: break if self.notebook.get_n_pages(): return False #save state before closing - Preferences.set_open_files(open_files) - Preferences.file_open(open_file) - Preferences.main_window_size(self.get_size()) - Preferences.console_window_position(self.left.get_position()) - Preferences.blocks_window_position(self.container.get_position()) + self.config.set_open_files(open_files) + self.config.file_open(open_file) + self.config.main_window_size(self.get_size()) + self.config.console_window_position(self.left.get_position()) + self.config.blocks_window_position(self.main.get_position()) if self.variable_panel_sidebar: - Preferences.variable_editor_position(self.right.get_position(), sidebar=True) + self.config.variable_editor_position(self.right.get_position(), sidebar=True) else: - Preferences.variable_editor_position(self.left_subpanel.get_position()) - Preferences.save() + self.config.variable_editor_position(self.left_subpanel.get_position()) + self.config.save() return True def close_page(self, ensure=True): @@ -327,23 +308,24 @@ class MainWindow(gtk.Window): Args: ensure: boolean """ - if not self.page_to_be_closed: self.page_to_be_closed = self.get_page() + if not self.page_to_be_closed: self.page_to_be_closed = self.current_page #show the page if it has an executing flow graph or is unsaved - if self.page_to_be_closed.get_proc() or not self.page_to_be_closed.get_saved(): + if self.page_to_be_closed.process or not self.page_to_be_closed.saved: self._set_page(self.page_to_be_closed) #unsaved? ask the user - if not self.page_to_be_closed.get_saved(): + if not self.page_to_be_closed.saved: response = self._save_changes() # return value is either OK, CLOSE, or CANCEL - if response == gtk.RESPONSE_OK: + if response == Gtk.ResponseType.OK: Actions.FLOW_GRAPH_SAVE() #try to save - if not self.page_to_be_closed.get_saved(): #still unsaved? + if not self.page_to_be_closed.saved: #still unsaved? self.page_to_be_closed = None #set the page to be closed back to None return False - elif response == gtk.RESPONSE_CANCEL: + elif response == Gtk.ResponseType.CANCEL: self.page_to_be_closed = None return False #stop the flow graph if executing - if self.page_to_be_closed.get_proc(): Actions.FLOW_GRAPH_KILL() + if self.page_to_be_closed.process: + Actions.FLOW_GRAPH_KILL() #remove the page self.notebook.remove_page(self.notebook.page_num(self.page_to_be_closed)) if ensure and self.notebook.get_n_pages() == 0: self.new_page() #no pages, make a new one @@ -359,69 +341,49 @@ class MainWindow(gtk.Window): Set the title of the main window. Set the titles on the page tabs. Show/hide the console window. - - Args: - title: the window title """ - gtk.Window.set_title(self, Utils.parse_template(MAIN_WINDOW_TITLE_TMPL, - basename=os.path.basename(self.get_page().get_file_path()), - dirname=os.path.dirname(self.get_page().get_file_path()), - new_flowgraph_title=NEW_FLOGRAPH_TITLE, - read_only=self.get_page().get_read_only(), - saved=self.get_page().get_saved(), - platform_name=self._platform.config.name, - ) - ) - #set tab titles - for page in self.get_pages(): page.set_markup( - Utils.parse_template(PAGE_TITLE_MARKUP_TMPL, - #get filename and strip out file extension - title=os.path.splitext(os.path.basename(page.get_file_path()))[0], - read_only=page.get_read_only(), saved=page.get_saved(), - new_flowgraph_title=NEW_FLOGRAPH_TITLE, - ) - ) - #show/hide notebook tabs + page = self.current_page + + basename = os.path.basename(page.file_path) + dirname = os.path.dirname(page.file_path) + Gtk.Window.set_title(self, ''.join(( + '*' if not page.saved else '', basename if basename else NEW_FLOGRAPH_TITLE, + '(read only)' if page.get_read_only() else '', ' - ', + dirname if dirname else self._platform.config.name, + ))) + # set tab titles + for page in self.get_pages(): + file_name = os.path.splitext(os.path.basename(page.file_path))[0] + page.set_markup('<span foreground="{foreground}">{title}{ro}</span>'.format( + foreground='black' if page.saved else 'red', ro=' (ro)' if page.get_read_only() else '', + title=Utils.encode(file_name or NEW_FLOGRAPH_TITLE), + )) + # show/hide notebook tabs self.notebook.set_show_tabs(len(self.get_pages()) > 1) - # Need to update the variable window when changing - self.vars.update_gui() + # Need to update the variable window when changing + self.vars.update_gui(self.current_flow_graph.blocks) def update_pages(self): """ Forces a reload of all the pages in this notebook. """ for page in self.get_pages(): - success = page.get_flow_graph().reload() + success = page.flow_graph.reload() if success: # Only set saved if errors occurred during import - page.set_saved(False) - - def get_page(self): - """ - Get the selected page. + page.saved = False - Returns: - the selected page - """ - return self.current_page - - def get_flow_graph(self): - """ - Get the selected flow graph. - - Returns: - the selected flow graph - """ - return self.get_page().get_flow_graph() + @property + def current_flow_graph(self): + return self.current_page.flow_graph def get_focus_flag(self): """ Get the focus flag from the current page. - Returns: the focus flag """ - return self.get_page().get_drawing_area().get_focus_flag() + return self.current_page.drawing_area.get_focus_flag() ############################################################ # Helpers @@ -445,14 +407,14 @@ class MainWindow(gtk.Window): the response_id (see buttons variable below) """ buttons = ( - 'Close without saving', gtk.RESPONSE_CLOSE, - gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - gtk.STOCK_SAVE, gtk.RESPONSE_OK - ) - return MessageDialogHelper( - gtk.MESSAGE_QUESTION, gtk.BUTTONS_NONE, 'Unsaved Changes!', - 'Would you like to save changes before closing?', gtk.RESPONSE_OK, buttons + 'Close without saving', Gtk.ResponseType.CLOSE, + Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, + Gtk.STOCK_SAVE, Gtk.ResponseType.OK ) + return MessageDialogWrapper( + self, Gtk.MessageType.QUESTION, Gtk.ButtonsType.NONE, 'Unsaved Changes!', + 'Would you like to save changes before closing?', Gtk.ResponseType.OK, buttons + ).run_and_destroy() def _get_files(self): """ @@ -461,7 +423,7 @@ class MainWindow(gtk.Window): Returns: list of file paths """ - return map(lambda page: page.get_file_path(), self.get_pages()) + return [page.file_path for page in self.get_pages()] def get_pages(self): """ @@ -470,4 +432,5 @@ class MainWindow(gtk.Window): Returns: list of pages """ - return [self.notebook.get_nth_page(page_num) for page_num in range(self.notebook.get_n_pages())] + return [self.notebook.get_nth_page(page_num) + for page_num in range(self.notebook.get_n_pages())] diff --git a/grc/gui/Notebook.py b/grc/gui/Notebook.py new file mode 100644 index 0000000000..21db913c0e --- /dev/null +++ b/grc/gui/Notebook.py @@ -0,0 +1,187 @@ +""" +Copyright 2008, 2009, 2011 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion 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 2 +of the License, or (at your option) any later version. + +GNU Radio Companion 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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from __future__ import absolute_import +import os +import logging + +from gi.repository import Gtk, Gdk, GObject + +from . import Actions +from .StateCache import StateCache +from .Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT +from .DrawingArea import DrawingArea + + +log = logging.getLogger(__name__) + + +class Notebook(Gtk.Notebook): + def __init__(self): + Gtk.Notebook.__init__(self) + log.debug("notebook()") + self.app = Gtk.Application.get_default() + self.current_page = None + + self.set_show_border(False) + self.set_scrollable(True) + self.connect('switch-page', self._handle_page_change) + + self.add_events(Gdk.EventMask.SCROLL_MASK) + self.connect('scroll-event', self._handle_scroll) + self._ignore_consecutive_scrolls = 0 + + def _handle_page_change(self, notebook, page, page_num): + """ + Handle a page change. When the user clicks on a new tab, + reload the flow graph to update the vars window and + call handle states (select nothing) to update the buttons. + + Args: + notebook: the notebook + page: new page + page_num: new page number + """ + self.current_page = self.get_nth_page(page_num) + Actions.PAGE_CHANGE() + + def _handle_scroll(self, widget, event): + # Not sure how to handle this at the moment. + natural = True + # Slow it down + if self._ignore_consecutive_scrolls == 0: + if event.direction in (Gdk.ScrollDirection.UP, Gdk.ScrollDirection.LEFT): + if natural: + self.prev_page() + else: + self.next_page() + elif event.direction in (Gdk.ScrollDirection.DOWN, Gdk.ScrollDirection.RIGHT): + if natural: + self.next_page() + else: + self.prev_page() + self._ignore_consecutive_scrolls = 3 + else: + self._ignore_consecutive_scrolls -= 1 + return False + + +class Page(Gtk.HBox): + """A page in the notebook.""" + + def __init__(self, main_window, flow_graph, file_path=''): + """ + Page constructor. + + Args: + main_window: main window + file_path: path to a flow graph file + """ + Gtk.HBox.__init__(self) + + self.main_window = main_window + self.flow_graph = flow_graph + self.file_path = file_path + + self.process = None + self.saved = True + + # import the file + initial_state = flow_graph.parent_platform.parse_flow_graph(file_path) + flow_graph.import_data(initial_state) + self.state_cache = StateCache(initial_state) + + # tab box to hold label and close button + self.label = Gtk.Label() + image = Gtk.Image.new_from_icon_name('window-close', Gtk.IconSize.MENU) + image_box = Gtk.HBox(homogeneous=False, spacing=0) + image_box.pack_start(image, True, False, 0) + button = Gtk.Button() + button.connect("clicked", self._handle_button) + button.set_relief(Gtk.ReliefStyle.NONE) + button.add(image_box) + + tab = self.tab = Gtk.HBox(homogeneous=False, spacing=0) + tab.pack_start(self.label, False, False, 0) + tab.pack_start(button, False, False, 0) + tab.show_all() + + # setup scroll window and drawing area + self.drawing_area = DrawingArea(flow_graph) + flow_graph.drawing_area = self.drawing_area + + self.scrolled_window = Gtk.ScrolledWindow() + self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) + self.scrolled_window.set_policy(Gtk.PolicyType.ALWAYS, Gtk.PolicyType.ALWAYS) + self.scrolled_window.connect('key-press-event', self._handle_scroll_window_key_press) + + self.scrolled_window.add(self.drawing_area) + self.pack_start(self.scrolled_window, True, True, 0) + self.show_all() + + def _handle_scroll_window_key_press(self, widget, event): + is_ctrl_pg = ( + event.state & Gdk.ModifierType.CONTROL_MASK and + event.keyval in (Gdk.KEY_Page_Up, Gdk.KEY_Page_Down) + ) + if is_ctrl_pg: + return self.get_parent().event(event) + + def get_generator(self): + """ + Get the generator object for this flow graph. + + Returns: + generator + """ + platform = self.flow_graph.parent_platform + return platform.Generator(self.flow_graph, self.file_path) + + def _handle_button(self, button): + """ + The button was clicked. + Make the current page selected, then close. + + Args: + the: button + """ + self.main_window.page_to_be_closed = self + Actions.FLOW_GRAPH_CLOSE() + + def set_markup(self, markup): + """ + Set the markup in this label. + + Args: + markup: the new markup text + """ + self.label.set_markup(markup) + + def get_read_only(self): + """ + Get the read-only state of the file. + Always false for empty path. + + Returns: + true for read-only + """ + if not self.file_path: + return False + return (os.path.exists(self.file_path) and + not os.access(self.file_path, os.W_OK)) diff --git a/grc/gui/NotebookPage.py b/grc/gui/NotebookPage.py deleted file mode 100644 index c9e8d0f186..0000000000 --- a/grc/gui/NotebookPage.py +++ /dev/null @@ -1,219 +0,0 @@ -""" -Copyright 2008, 2009, 2011 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import pygtk -pygtk.require('2.0') -import gtk -import Actions -from StateCache import StateCache -from Constants import MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT -from DrawingArea import DrawingArea -import os - - -class NotebookPage(gtk.HBox): - """A page in the notebook.""" - - def __init__(self, main_window, flow_graph, file_path=''): - """ - Page constructor. - - Args: - main_window: main window - file_path: path to a flow graph file - """ - self._flow_graph = flow_graph - self.process = None - #import the file - self.main_window = main_window - self.file_path = file_path - initial_state = flow_graph.get_parent().parse_flow_graph(file_path) - self.state_cache = StateCache(initial_state) - self.saved = True - #import the data to the flow graph - self.get_flow_graph().import_data(initial_state) - #initialize page gui - gtk.HBox.__init__(self, False, 0) - self.show() - #tab box to hold label and close button - self.tab = gtk.HBox(False, 0) - #setup tab label - self.label = gtk.Label() - self.tab.pack_start(self.label, False) - #setup button image - image = gtk.Image() - image.set_from_stock('gtk-close', gtk.ICON_SIZE_MENU) - #setup image box - image_box = gtk.HBox(False, 0) - image_box.pack_start(image, True, False, 0) - #setup the button - button = gtk.Button() - button.connect("clicked", self._handle_button) - button.set_relief(gtk.RELIEF_NONE) - button.add(image_box) - #button size - w, h = gtk.icon_size_lookup_for_settings(button.get_settings(), gtk.ICON_SIZE_MENU) - button.set_size_request(w+6, h+6) - self.tab.pack_start(button, False) - self.tab.show_all() - #setup scroll window and drawing area - self.scrolled_window = gtk.ScrolledWindow() - self.scrolled_window.set_size_request(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT) - self.scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.scrolled_window.connect('key-press-event', self._handle_scroll_window_key_press) - self.drawing_area = DrawingArea(self.get_flow_graph()) - self.scrolled_window.add_with_viewport(self.get_drawing_area()) - self.pack_start(self.scrolled_window) - #inject drawing area into flow graph - self.get_flow_graph().drawing_area = self.get_drawing_area() - self.show_all() - - def get_drawing_area(self): return self.drawing_area - - def _handle_scroll_window_key_press(self, widget, event): - """forward Ctrl-PgUp/Down to NotebookPage (switch fg instead of horiz. scroll""" - is_ctrl_pg = ( - event.state & gtk.gdk.CONTROL_MASK and - event.keyval in (gtk.keysyms.Page_Up, gtk.keysyms.Page_Down) - ) - if is_ctrl_pg: - return self.get_parent().event(event) - - def get_generator(self): - """ - Get the generator object for this flow graph. - - Returns: - generator - """ - platform = self.get_flow_graph().get_parent() - return platform.Generator(self.get_flow_graph(), self.get_file_path()) - - def _handle_button(self, button): - """ - The button was clicked. - Make the current page selected, then close. - - Args: - the: button - """ - self.main_window.page_to_be_closed = self - Actions.FLOW_GRAPH_CLOSE() - - def set_markup(self, markup): - """ - Set the markup in this label. - - Args: - markup: the new markup text - """ - self.label.set_markup(markup) - - def get_tab(self): - """ - Get the gtk widget for this page's tab. - - Returns: - gtk widget - """ - return self.tab - - def get_proc(self): - """ - Get the subprocess for the flow graph. - - Returns: - the subprocess object - """ - return self.process - - def set_proc(self, process): - """ - Set the subprocess object. - - Args: - process: the new subprocess - """ - self.process = process - - def get_flow_graph(self): - """ - Get the flow graph. - - Returns: - the flow graph - """ - return self._flow_graph - - def get_read_only(self): - """ - Get the read-only state of the file. - Always false for empty path. - - Returns: - true for read-only - """ - if not self.get_file_path(): return False - return os.path.exists(self.get_file_path()) and \ - not os.access(self.get_file_path(), os.W_OK) - - def get_file_path(self): - """ - Get the file path for the flow graph. - - Returns: - the file path or '' - """ - return self.file_path - - def set_file_path(self, file_path=''): - """ - Set the file path, '' for no file path. - - Args: - file_path: file path string - """ - self.file_path = os.path.abspath(file_path) if file_path else '' - - def get_saved(self): - """ - Get the saved status for the flow graph. - - Returns: - true if saved - """ - return self.saved - - def set_saved(self, saved=True): - """ - Set the saved status. - - Args: - saved: boolean status - """ - self.saved = saved - - def get_state_cache(self): - """ - Get the state cache for the flow graph. - - Returns: - the state cache - """ - return self.state_cache diff --git a/grc/gui/Param.py b/grc/gui/Param.py deleted file mode 100644 index c71e1c0aa5..0000000000 --- a/grc/gui/Param.py +++ /dev/null @@ -1,442 +0,0 @@ -""" -Copyright 2007-2011 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import os - -import pygtk -pygtk.require('2.0') -import gtk - -from . import Colors, Utils, Constants -from .Element import Element -from . import Utils - -from ..core.Param import Param as _Param - - -class InputParam(gtk.HBox): - """The base class for an input parameter inside the input parameters dialog.""" - expand = False - - def __init__(self, param, changed_callback=None, editing_callback=None): - gtk.HBox.__init__(self) - self.param = param - self._changed_callback = changed_callback - self._editing_callback = editing_callback - self.label = gtk.Label() #no label, markup is added by set_markup - self.label.set_size_request(Utils.scale_scalar(150), -1) - self.pack_start(self.label, False) - self.set_markup = lambda m: self.label.set_markup(m) - self.tp = None - self._have_pending_changes = False - #connect events - self.connect('show', self._update_gui) - - def set_color(self, color): - pass - - def set_tooltip_text(self, text): - pass - - def get_text(self): - raise NotImplementedError() - - def _update_gui(self, *args): - """ - Set the markup, color, tooltip, show/hide. - """ - #set the markup - has_cb = \ - hasattr(self.param.get_parent(), 'get_callbacks') and \ - filter(lambda c: self.param.get_key() in c, self.param.get_parent()._callbacks) - self.set_markup(Utils.parse_template(PARAM_LABEL_MARKUP_TMPL, - param=self.param, has_cb=has_cb, - modified=self._have_pending_changes)) - #set the color - self.set_color(self.param.get_color()) - #set the tooltip - self.set_tooltip_text( - Utils.parse_template(TIP_MARKUP_TMPL, param=self.param).strip(), - ) - #show/hide - if self.param.get_hide() == 'all': self.hide_all() - else: self.show_all() - - def _mark_changed(self, *args): - """ - Mark this param as modified on change, but validate only on focus-lost - """ - self._have_pending_changes = True - self._update_gui() - if self._editing_callback: - self._editing_callback(self, None) - - def _apply_change(self, *args): - """ - Handle a gui change by setting the new param value, - calling the callback (if applicable), and updating. - """ - #set the new value - self.param.set_value(self.get_text()) - #call the callback - if self._changed_callback: - self._changed_callback(self, None) - else: - self.param.validate() - #gui update - self._have_pending_changes = False - self._update_gui() - - def _handle_key_press(self, widget, event): - if event.keyval == gtk.keysyms.Return and event.state & gtk.gdk.CONTROL_MASK: - self._apply_change(widget, event) - return True - return False - - def apply_pending_changes(self): - if self._have_pending_changes: - self._apply_change() - - -class EntryParam(InputParam): - """Provide an entry box for strings and numbers.""" - - def __init__(self, *args, **kwargs): - InputParam.__init__(self, *args, **kwargs) - self._input = gtk.Entry() - self._input.set_text(self.param.get_value()) - self._input.connect('changed', self._mark_changed) - self._input.connect('focus-out-event', self._apply_change) - self._input.connect('key-press-event', self._handle_key_press) - self.pack_start(self._input, True) - - def get_text(self): - return self._input.get_text() - - def set_color(self, color): - need_status_color = self.label not in self.get_children() - text_color = ( - Colors.PARAM_ENTRY_TEXT_COLOR if not need_status_color else - gtk.gdk.color_parse('blue') if self._have_pending_changes else - gtk.gdk.color_parse('red') if not self.param.is_valid() else - Colors.PARAM_ENTRY_TEXT_COLOR) - base_color = ( - Colors.BLOCK_DISABLED_COLOR - if need_status_color and not self.param.get_parent().get_enabled() - else gtk.gdk.color_parse(color) - ) - self._input.modify_base(gtk.STATE_NORMAL, base_color) - self._input.modify_text(gtk.STATE_NORMAL, text_color) - - def set_tooltip_text(self, text): - try: - self._input.set_tooltip_text(text) - except AttributeError: - pass # no tooltips for old GTK - - -class MultiLineEntryParam(InputParam): - """Provide an multi-line box for strings.""" - expand = True - - def __init__(self, *args, **kwargs): - InputParam.__init__(self, *args, **kwargs) - self._buffer = gtk.TextBuffer() - self._buffer.set_text(self.param.get_value()) - self._buffer.connect('changed', self._mark_changed) - - self._view = gtk.TextView(self._buffer) - self._view.connect('focus-out-event', self._apply_change) - self._view.connect('key-press-event', self._handle_key_press) - - self._sw = gtk.ScrolledWindow() - self._sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self._sw.add_with_viewport(self._view) - - self.pack_start(self._sw, True) - - def get_text(self): - buf = self._buffer - return buf.get_text(buf.get_start_iter(), - buf.get_end_iter()).strip() - - def set_color(self, color): - self._view.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) - self._view.modify_text(gtk.STATE_NORMAL, Colors.PARAM_ENTRY_TEXT_COLOR) - - def set_tooltip_text(self, text): - try: - self._view.set_tooltip_text(text) - except AttributeError: - pass # no tooltips for old GTK - - -# try: -# import gtksourceview -# lang_manager = gtksourceview.SourceLanguagesManager() -# py_lang = lang_manager.get_language_from_mime_type('text/x-python') -# -# class PythonEditorParam(InputParam): -# expand = True -# -# def __init__(self, *args, **kwargs): -# InputParam.__init__(self, *args, **kwargs) -# -# buf = self._buffer = gtksourceview.SourceBuffer() -# buf.set_language(py_lang) -# buf.set_highlight(True) -# buf.set_text(self.param.get_value()) -# buf.connect('changed', self._mark_changed) -# -# view = self._view = gtksourceview.SourceView(self._buffer) -# view.connect('focus-out-event', self._apply_change) -# view.connect('key-press-event', self._handle_key_press) -# view.set_tabs_width(4) -# view.set_insert_spaces_instead_of_tabs(True) -# view.set_auto_indent(True) -# view.set_border_width(2) -# -# scroll = gtk.ScrolledWindow() -# scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) -# scroll.add_with_viewport(view) -# self.pack_start(scroll, True) -# -# def get_text(self): -# buf = self._buffer -# return buf.get_text(buf.get_start_iter(), -# buf.get_end_iter()).strip() -# -# except ImportError: -# print "Package 'gtksourceview' not found. No Syntax highlighting." -# PythonEditorParam = MultiLineEntryParam - -class PythonEditorParam(InputParam): - - def __init__(self, *args, **kwargs): - InputParam.__init__(self, *args, **kwargs) - button = self._button = gtk.Button('Open in Editor') - button.connect('clicked', self.open_editor) - self.pack_start(button, True) - - def open_editor(self, widget=None): - flowgraph = self.param.get_parent().get_parent() - flowgraph.install_external_editor(self.param) - - def get_text(self): - pass # we never update the value from here - - def set_color(self, color): - # self._button.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) - self._button.modify_text(gtk.STATE_NORMAL, Colors.PARAM_ENTRY_TEXT_COLOR) - - def _apply_change(self, *args): - pass - - -class EnumParam(InputParam): - """Provide an entry box for Enum types with a drop down menu.""" - - def __init__(self, *args, **kwargs): - InputParam.__init__(self, *args, **kwargs) - self._input = gtk.combo_box_new_text() - for option in self.param.get_options(): self._input.append_text(option.get_name()) - self._input.set_active(self.param.get_option_keys().index(self.param.get_value())) - self._input.connect('changed', self._editing_callback) - self._input.connect('changed', self._apply_change) - self.pack_start(self._input, False) - - def get_text(self): - return self.param.get_option_keys()[self._input.get_active()] - - def set_tooltip_text(self, text): - try: - self._input.set_tooltip_text(text) - except AttributeError: - pass # no tooltips for old GTK - - -class EnumEntryParam(InputParam): - """Provide an entry box and drop down menu for Raw Enum types.""" - - def __init__(self, *args, **kwargs): - InputParam.__init__(self, *args, **kwargs) - self._input = gtk.combo_box_entry_new_text() - for option in self.param.get_options(): self._input.append_text(option.get_name()) - try: self._input.set_active(self.param.get_option_keys().index(self.param.get_value())) - except: - self._input.set_active(-1) - self._input.get_child().set_text(self.param.get_value()) - self._input.connect('changed', self._apply_change) - self._input.get_child().connect('changed', self._mark_changed) - self._input.get_child().connect('focus-out-event', self._apply_change) - self._input.get_child().connect('key-press-event', self._handle_key_press) - self.pack_start(self._input, False) - - def get_text(self): - if self._input.get_active() == -1: return self._input.get_child().get_text() - return self.param.get_option_keys()[self._input.get_active()] - - def set_tooltip_text(self, text): - try: - if self._input.get_active() == -1: #custom entry - self._input.get_child().set_tooltip_text(text) - else: - self._input.set_tooltip_text(text) - except AttributeError: - pass # no tooltips for old GTK - - def set_color(self, color): - if self._input.get_active() == -1: #custom entry, use color - self._input.get_child().modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse(color)) - self._input.get_child().modify_text(gtk.STATE_NORMAL, Colors.PARAM_ENTRY_TEXT_COLOR) - else: #from enum, make pale background - self._input.get_child().modify_base(gtk.STATE_NORMAL, Colors.ENTRYENUM_CUSTOM_COLOR) - self._input.get_child().modify_text(gtk.STATE_NORMAL, Colors.PARAM_ENTRY_TEXT_COLOR) - - -class FileParam(EntryParam): - """Provide an entry box for filename and a button to browse for a file.""" - - def __init__(self, *args, **kwargs): - EntryParam.__init__(self, *args, **kwargs) - input = gtk.Button('...') - input.connect('clicked', self._handle_clicked) - self.pack_start(input, False) - - def _handle_clicked(self, widget=None): - """ - If the button was clicked, open a file dialog in open/save format. - Replace the text in the entry with the new filename from the file dialog. - """ - #get the paths - file_path = self.param.is_valid() and self.param.get_evaluated() or '' - (dirname, basename) = os.path.isfile(file_path) and os.path.split(file_path) or (file_path, '') - # check for qss theme default directory - if self.param.get_key() == 'qt_qss_theme': - dirname = os.path.dirname(dirname) # trim filename - if not os.path.exists(dirname): - platform = self.param.get_parent().get_parent().get_parent() - dirname = os.path.join(platform.config.install_prefix, - '/share/gnuradio/themes') - if not os.path.exists(dirname): - dirname = os.getcwd() # fix bad paths - - #build the dialog - if self.param.get_type() == 'file_open': - file_dialog = gtk.FileChooserDialog('Open a Data File...', None, - gtk.FILE_CHOOSER_ACTION_OPEN, ('gtk-cancel',gtk.RESPONSE_CANCEL,'gtk-open',gtk.RESPONSE_OK)) - elif self.param.get_type() == 'file_save': - file_dialog = gtk.FileChooserDialog('Save a Data File...', None, - gtk.FILE_CHOOSER_ACTION_SAVE, ('gtk-cancel',gtk.RESPONSE_CANCEL, 'gtk-save',gtk.RESPONSE_OK)) - file_dialog.set_do_overwrite_confirmation(True) - file_dialog.set_current_name(basename) #show the current filename - else: - raise ValueError("Can't open file chooser dialog for type " + repr(self.param.get_type())) - file_dialog.set_current_folder(dirname) #current directory - file_dialog.set_select_multiple(False) - file_dialog.set_local_only(True) - if gtk.RESPONSE_OK == file_dialog.run(): #run the dialog - file_path = file_dialog.get_filename() #get the file path - self._input.set_text(file_path) - self._editing_callback() - self._apply_change() - file_dialog.destroy() #destroy the dialog - - -PARAM_MARKUP_TMPL="""\ -#set $foreground = $param.is_valid() and 'black' or 'red' -<span foreground="$foreground" font_desc="$font"><b>$encode($param.get_name()): </b>$encode(repr($param).replace('\\n',' '))</span>""" - -PARAM_LABEL_MARKUP_TMPL="""\ -#set $foreground = $modified and 'blue' or $param.is_valid() and 'black' or 'red' -#set $underline = $has_cb and 'low' or 'none' -<span underline="$underline" foreground="$foreground" font_desc="Sans 9">$encode($param.get_name())</span>""" - -TIP_MARKUP_TMPL="""\ -######################################## -#def truncate(string) - #set $max_len = 100 - #set $string = str($string) - #if len($string) > $max_len -$('%s...%s'%($string[:$max_len/2], $string[-$max_len/2:]))#slurp - #else -$string#slurp - #end if -#end def -######################################## -Key: $param.get_key() -Type: $param.get_type() -#if $param.is_valid() -Value: $truncate($param.get_evaluated()) -#elif len($param.get_error_messages()) == 1 -Error: $(param.get_error_messages()[0]) -#else -Error: - #for $error_msg in $param.get_error_messages() - * $error_msg - #end for -#end if""" - - -class Param(Element, _Param): - """The graphical parameter.""" - - def __init__(self, **kwargs): - Element.__init__(self) - _Param.__init__(self, **kwargs) - - def get_input(self, *args, **kwargs): - """ - Get the graphical gtk class to represent this parameter. - An enum requires and combo parameter. - A non-enum with options gets a combined entry/combo parameter. - All others get a standard entry parameter. - - Returns: - gtk input class - """ - if self.get_type() in ('file_open', 'file_save'): - input_widget = FileParam(self, *args, **kwargs) - - elif self.is_enum(): - input_widget = EnumParam(self, *args, **kwargs) - - elif self.get_options(): - input_widget = EnumEntryParam(self, *args, **kwargs) - - elif self.get_type() == '_multiline': - input_widget = MultiLineEntryParam(self, *args, **kwargs) - - elif self.get_type() == '_multiline_python_external': - input_widget = PythonEditorParam(self, *args, **kwargs) - - else: - input_widget = EntryParam(self, *args, **kwargs) - - return input_widget - - def get_markup(self): - """ - Get the markup for this param. - - Returns: - a pango markup string - """ - return Utils.parse_template(PARAM_MARKUP_TMPL, - param=self, font=Constants.PARAM_FONT) diff --git a/grc/gui/ParamWidgets.py b/grc/gui/ParamWidgets.py new file mode 100644 index 0000000000..71cb1b7a7d --- /dev/null +++ b/grc/gui/ParamWidgets.py @@ -0,0 +1,325 @@ +# Copyright 2007-2016 Free Software Foundation, Inc. +# This file is part of GNU Radio +# +# GNU Radio Companion 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 2 +# of the License, or (at your option) any later version. +# +# GNU Radio Companion 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +from __future__ import absolute_import +import os + +from gi.repository import Gtk, Gdk + +from . import Utils + + +style_provider = Gtk.CssProvider() + +style_provider.load_from_data(b""" + #dtype_complex { background-color: #3399FF; } + #dtype_real { background-color: #FF8C69; } + #dtype_float { background-color: #FF8C69; } + #dtype_int { background-color: #00FF99; } + + #dtype_complex_vector { background-color: #3399AA; } + #dtype_real_vector { background-color: #CC8C69; } + #dtype_float_vector { background-color: #CC8C69; } + #dtype_int_vector { background-color: #00CC99; } + + #dtype_bool { background-color: #00FF99; } + #dtype_hex { background-color: #00FF99; } + #dtype_string { background-color: #CC66CC; } + #dtype_id { background-color: #DDDDDD; } + #dtype_stream_id { background-color: #DDDDDD; } + #dtype_raw { background-color: #FFFFFF; } + + #enum_custom { background-color: #EEEEEE; } +""") + +Gtk.StyleContext.add_provider_for_screen( + Gdk.Screen.get_default(), + style_provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION +) + + +class InputParam(Gtk.HBox): + """The base class for an input parameter inside the input parameters dialog.""" + expand = False + + def __init__(self, param, changed_callback=None, editing_callback=None): + Gtk.HBox.__init__(self) + + self.param = param + self._changed_callback = changed_callback + self._editing_callback = editing_callback + + self.label = Gtk.Label() + self.label.set_size_request(Utils.scale_scalar(150), -1) + self.label.show() + self.pack_start(self.label, False, False, 0) + + self.tp = None + self._have_pending_changes = False + + self.connect('show', self._update_gui) + + def set_color(self, css_name): + pass + + def set_tooltip_text(self, text): + pass + + def get_text(self): + raise NotImplementedError() + + def _update_gui(self, *args): + """ + Set the markup, color, tooltip, show/hide. + """ + self.label.set_markup(self.param.format_label_markup(self._have_pending_changes)) + self.set_color('dtype_' + self.param.get_type()) + + self.set_tooltip_text(self.param.format_tooltip_text()) + + if self.param.get_hide() == 'all': + self.hide() + else: + self.show_all() + + def _mark_changed(self, *args): + """ + Mark this param as modified on change, but validate only on focus-lost + """ + self._have_pending_changes = True + self._update_gui() + if self._editing_callback: + self._editing_callback(self, None) + + def _apply_change(self, *args): + """ + Handle a gui change by setting the new param value, + calling the callback (if applicable), and updating. + """ + #set the new value + self.param.set_value(self.get_text()) + #call the callback + if self._changed_callback: + self._changed_callback(self, None) + else: + self.param.validate() + #gui update + self._have_pending_changes = False + self._update_gui() + + def _handle_key_press(self, widget, event): + if event.keyval == Gdk.KEY_Return and event.get_state() & Gdk.ModifierType.CONTROL_MASK: + self._apply_change(widget, event) + return True + return False + + def apply_pending_changes(self): + if self._have_pending_changes: + self._apply_change() + + +class EntryParam(InputParam): + """Provide an entry box for strings and numbers.""" + + def __init__(self, *args, **kwargs): + InputParam.__init__(self, *args, **kwargs) + self._input = Gtk.Entry() + self._input.set_text(self.param.get_value()) + self._input.connect('changed', self._mark_changed) + self._input.connect('focus-out-event', self._apply_change) + self._input.connect('key-press-event', self._handle_key_press) + self.pack_start(self._input, True, True, 0) + + def get_text(self): + return self._input.get_text() + + def set_color(self, css_name): + self._input.set_name(css_name) + + def set_tooltip_text(self, text): + self._input.set_tooltip_text(text) + + +class MultiLineEntryParam(InputParam): + """Provide an multi-line box for strings.""" + expand = True + + def __init__(self, *args, **kwargs): + InputParam.__init__(self, *args, **kwargs) + self._buffer = Gtk.TextBuffer() + self._buffer.set_text(self.param.get_value()) + self._buffer.connect('changed', self._mark_changed) + + self._view = Gtk.TextView() + self._view.set_buffer(self._buffer) + self._view.connect('focus-out-event', self._apply_change) + self._view.connect('key-press-event', self._handle_key_press) + + self._sw = Gtk.ScrolledWindow() + self._sw.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + self._sw.set_shadow_type(type=Gtk.ShadowType.IN) + self._sw.add(self._view) + + self.pack_start(self._sw, True, True, True) + + def get_text(self): + buf = self._buffer + text = buf.get_text(buf.get_start_iter(), buf.get_end_iter(), + include_hidden_chars=False) + return text.strip() + + def set_color(self, css_name): + self._view.set_name(css_name) + + def set_tooltip_text(self, text): + self._view.set_tooltip_text(text) + + +class PythonEditorParam(InputParam): + + def __init__(self, *args, **kwargs): + InputParam.__init__(self, *args, **kwargs) + button = self._button = Gtk.Button(label='Open in Editor') + button.connect('clicked', self.open_editor) + self.pack_start(button, True, True, True) + + def open_editor(self, widget=None): + self.param.parent_flowgraph.install_external_editor(self.param) + + def get_text(self): + pass # we never update the value from here + + def _apply_change(self, *args): + pass + + +class EnumParam(InputParam): + """Provide an entry box for Enum types with a drop down menu.""" + + def __init__(self, *args, **kwargs): + InputParam.__init__(self, *args, **kwargs) + self._input = Gtk.ComboBoxText() + for option_name in self.param.options_names: + self._input.append_text(option_name) + + value = self.param.get_value() + active_index = self.param.options.index(value) + self._input.set_active(active_index) + + self._input.connect('changed', self._editing_callback) + self._input.connect('changed', self._apply_change) + self.pack_start(self._input, False, False, 0) + + def get_text(self): + return self.param.options[self._input.get_active()] + + def set_tooltip_text(self, text): + self._input.set_tooltip_text(text) + + +class EnumEntryParam(InputParam): + """Provide an entry box and drop down menu for Raw Enum types.""" + + def __init__(self, *args, **kwargs): + InputParam.__init__(self, *args, **kwargs) + self._input = Gtk.ComboBoxText.new_with_entry() + for option_name in self.param.options_names: + self._input.append_text(option_name) + + value = self.param.get_value() + try: + active_index = self.param.options.index(value) + self._input.set_active(active_index) + except ValueError: + self._input.set_active(-1) + self._input.get_child().set_text(value) + + self._input.connect('changed', self._apply_change) + self._input.get_child().connect('changed', self._mark_changed) + self._input.get_child().connect('focus-out-event', self._apply_change) + self._input.get_child().connect('key-press-event', self._handle_key_press) + self.pack_start(self._input, False, False, 0) + + @property + def has_custom_value(self): + return self._input.get_active() == -1 + + def get_text(self): + if self.has_custom_value: + return self._input.get_child().get_text() + else: + return self.param.options[self._input.get_active()] + + def set_tooltip_text(self, text): + if self.has_custom_value: # custom entry + self._input.get_child().set_tooltip_text(text) + else: + self._input.set_tooltip_text(text) + + def set_color(self, css_name): + self._input.get_child().set_name( + css_name if not self.has_custom_value else 'enum_custom' + ) + + +class FileParam(EntryParam): + """Provide an entry box for filename and a button to browse for a file.""" + + def __init__(self, *args, **kwargs): + EntryParam.__init__(self, *args, **kwargs) + self._open_button = Gtk.Button(label='...') + self._open_button.connect('clicked', self._handle_clicked) + self.pack_start(self._open_button, False, False, 0) + + def _handle_clicked(self, widget=None): + """ + If the button was clicked, open a file dialog in open/save format. + Replace the text in the entry with the new filename from the file dialog. + """ + #get the paths + file_path = self.param.is_valid() and self.param.get_evaluated() or '' + (dirname, basename) = os.path.isfile(file_path) and os.path.split(file_path) or (file_path, '') + # check for qss theme default directory + if self.param.key == 'qt_qss_theme': + dirname = os.path.dirname(dirname) # trim filename + if not os.path.exists(dirname): + config = self.param.parent_platform.config + dirname = os.path.join(config.install_prefix, '/share/gnuradio/themes') + if not os.path.exists(dirname): + dirname = os.getcwd() # fix bad paths + + #build the dialog + if self.param.get_type() == 'file_open': + file_dialog = Gtk.FileChooserDialog('Open a Data File...', None, + Gtk.FileChooserAction.OPEN, ('gtk-cancel',Gtk.ResponseType.CANCEL,'gtk-open',Gtk.ResponseType.OK)) + elif self.param.get_type() == 'file_save': + file_dialog = Gtk.FileChooserDialog('Save a Data File...', None, + Gtk.FileChooserAction.SAVE, ('gtk-cancel',Gtk.ResponseType.CANCEL, 'gtk-save',Gtk.ResponseType.OK)) + file_dialog.set_do_overwrite_confirmation(True) + file_dialog.set_current_name(basename) #show the current filename + else: + raise ValueError("Can't open file chooser dialog for type " + repr(self.param.get_type())) + file_dialog.set_current_folder(dirname) #current directory + file_dialog.set_select_multiple(False) + file_dialog.set_local_only(True) + if Gtk.ResponseType.OK == file_dialog.run(): #run the dialog + file_path = file_dialog.get_filename() #get the file path + self._input.set_text(file_path) + self._editing_callback() + self._apply_change() + file_dialog.destroy() # destroy the dialog diff --git a/grc/gui/ParserErrorsDialog.py b/grc/gui/ParserErrorsDialog.py index 68ee459414..050b9a4f98 100644 --- a/grc/gui/ParserErrorsDialog.py +++ b/grc/gui/ParserErrorsDialog.py @@ -17,14 +17,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import pygtk -pygtk.require('2.0') -import gtk +from __future__ import absolute_import -from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT +import six +from gi.repository import Gtk, GObject -class ParserErrorsDialog(gtk.Dialog): +from .Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT + + +class ParserErrorsDialog(Gtk.Dialog): """ A dialog for viewing parser errors """ @@ -36,32 +38,32 @@ class ParserErrorsDialog(gtk.Dialog): Args: block: a block instance """ - gtk.Dialog.__init__(self, title='Parser Errors', buttons=(gtk.STOCK_CLOSE, gtk.RESPONSE_ACCEPT)) + GObject.GObject.__init__(self, title='Parser Errors', buttons=(Gtk.STOCK_CLOSE, Gtk.ResponseType.ACCEPT)) self._error_logs = None - self.tree_store = gtk.TreeStore(str) + self.tree_store = Gtk.TreeStore(str) self.update_tree_store(error_logs) - column = gtk.TreeViewColumn('XML Parser Errors by Filename') - renderer = gtk.CellRendererText() + column = Gtk.TreeViewColumn('XML Parser Errors by Filename') + renderer = Gtk.CellRendererText() column.pack_start(renderer, True) column.add_attribute(renderer, 'text', 0) column.set_sort_column_id(0) - self.tree_view = tree_view = gtk.TreeView(self.tree_store) + self.tree_view = tree_view = Gtk.TreeView(self.tree_store) tree_view.set_enable_search(False) # disable pop up search box tree_view.set_search_column(-1) # really disable search tree_view.set_reorderable(False) tree_view.set_headers_visible(False) - tree_view.get_selection().set_mode(gtk.SELECTION_NONE) + tree_view.get_selection().set_mode(Gtk.SelectionMode.NONE) tree_view.append_column(column) for row in self.tree_store: tree_view.expand_row(row.path, False) - scrolled_window = gtk.ScrolledWindow() - scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolled_window.add_with_viewport(tree_view) + scrolled_window = Gtk.ScrolledWindow() + scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolled_window.add(tree_view) self.vbox.pack_start(scrolled_window, True) self.set_size_request(2*MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT) @@ -71,7 +73,7 @@ class ParserErrorsDialog(gtk.Dialog): """set up data model""" self.tree_store.clear() self._error_logs = error_logs - for filename, errors in error_logs.iteritems(): + for filename, errors in six.iteritems(error_logs): parent = self.tree_store.append(None, [str(filename)]) try: with open(filename, 'r') as fp: @@ -95,6 +97,6 @@ class ParserErrorsDialog(gtk.Dialog): Returns: true if the response was accept """ - response = gtk.Dialog.run(self) + response = Gtk.Dialog.run(self) self.destroy() - return response == gtk.RESPONSE_ACCEPT + return response == Gtk.ResponseType.ACCEPT diff --git a/grc/gui/Platform.py b/grc/gui/Platform.py index 500df1cce4..aeade75d78 100644 --- a/grc/gui/Platform.py +++ b/grc/gui/Platform.py @@ -17,25 +17,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import os -import sys +from __future__ import absolute_import, print_function -from ..core.Platform import Platform as _Platform +import sys +import os -from .Config import Config as _Config -from .Block import Block as _Block -from .Connection import Connection as _Connection -from .Element import Element -from .FlowGraph import FlowGraph as _FlowGraph -from .Param import Param as _Param -from .Port import Port as _Port +from .Config import Config +from . import canvas +from ..core.Platform import Platform as CorePlatform -class Platform(Element, _Platform): +class Platform(CorePlatform): def __init__(self, *args, **kwargs): - Element.__init__(self) - _Platform.__init__(self, *args, **kwargs) + CorePlatform.__init__(self, *args, **kwargs) # Ensure conf directories gui_prefs_file = self.config.gui_prefs_file @@ -58,14 +53,17 @@ class Platform(Element, _Platform): import shutil shutil.move(old_gui_prefs_file, gui_prefs_file) except Exception as e: - print >> sys.stderr, e + print(e, file=sys.stderr) ############################################## - # Constructors + # Factories ############################################## - FlowGraph = _FlowGraph - Connection = _Connection - Block = _Block - Port = _Port - Param = _Param - Config = _Config + Config = Config + FlowGraph = canvas.FlowGraph + Connection = canvas.Connection + block_classes = {key: canvas.Block.make_cls_with_base(cls) + for key, cls in CorePlatform.block_classes.items()} + port_classes = {key: canvas.Port.make_cls_with_base(cls) + for key, cls in CorePlatform.port_classes.items()} + param_classes = {key: canvas.Param.make_cls_with_base(cls) + for key, cls in CorePlatform.param_classes.items()} diff --git a/grc/gui/Port.py b/grc/gui/Port.py deleted file mode 100644 index 6314b7ede8..0000000000 --- a/grc/gui/Port.py +++ /dev/null @@ -1,277 +0,0 @@ -""" -Copyright 2007, 2008, 2009 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import pygtk -pygtk.require('2.0') -import gtk - -from . import Actions, Colors, Utils -from .Constants import ( - PORT_SEPARATION, PORT_SPACING, CONNECTOR_EXTENSION_MINIMAL, - CONNECTOR_EXTENSION_INCREMENT, PORT_LABEL_PADDING, PORT_MIN_WIDTH, PORT_LABEL_HIDDEN_WIDTH, PORT_FONT -) -from .Element import Element -from ..core.Constants import DEFAULT_DOMAIN, GR_MESSAGE_DOMAIN - -from ..core.Port import Port as _Port - -PORT_MARKUP_TMPL="""\ -<span foreground="black" font_desc="$font">$encode($port.get_name())</span>""" - - -class Port(_Port, Element): - """The graphical port.""" - - def __init__(self, block, n, dir): - """ - Port contructor. - Create list of connector coordinates. - """ - _Port.__init__(self, block, n, dir) - Element.__init__(self) - self.W = self.H = self.w = self.h = 0 - self._connector_coordinate = (0, 0) - self._connector_length = 0 - self._hovering = True - self._force_label_unhidden = False - - def create_shapes(self): - """Create new areas and labels for the port.""" - Element.create_shapes(self) - if self.get_hide(): - return # this port is hidden, no need to create shapes - if self.get_domain() == GR_MESSAGE_DOMAIN: - pass - elif self.get_domain() != DEFAULT_DOMAIN: - self.line_attributes[0] = 2 - #get current rotation - rotation = self.get_rotation() - #get all sibling ports - ports = self.get_parent().get_sources_gui() \ - if self.is_source else self.get_parent().get_sinks_gui() - ports = filter(lambda p: not p.get_hide(), ports) - #get the max width - self.W = max([port.W for port in ports] + [PORT_MIN_WIDTH]) - W = self.W if not self._label_hidden() else PORT_LABEL_HIDDEN_WIDTH - #get a numeric index for this port relative to its sibling ports - try: - index = ports.index(self) - except: - if hasattr(self, '_connector_length'): - del self._connector_length - return - length = len(filter(lambda p: not p.get_hide(), ports)) - #reverse the order of ports for these rotations - if rotation in (180, 270): - index = length-index-1 - - port_separation = PORT_SEPARATION \ - if not self.get_parent().has_busses[self.is_source] \ - else max([port.H for port in ports]) + PORT_SPACING - - offset = (self.get_parent().H - (length-1)*port_separation - self.H)/2 - #create areas and connector coordinates - if (self.is_sink and rotation == 0) or (self.is_source and rotation == 180): - x = -W - y = port_separation*index+offset - self.add_area((x, y), (W, self.H)) - self._connector_coordinate = (x-1, y+self.H/2) - elif (self.is_source and rotation == 0) or (self.is_sink and rotation == 180): - x = self.get_parent().W - y = port_separation*index+offset - self.add_area((x, y), (W, self.H)) - self._connector_coordinate = (x+1+W, y+self.H/2) - elif (self.is_source and rotation == 90) or (self.is_sink and rotation == 270): - y = -W - x = port_separation*index+offset - self.add_area((x, y), (self.H, W)) - self._connector_coordinate = (x+self.H/2, y-1) - elif (self.is_sink and rotation == 90) or (self.is_source and rotation == 270): - y = self.get_parent().W - x = port_separation*index+offset - self.add_area((x, y), (self.H, W)) - self._connector_coordinate = (x+self.H/2, y+1+W) - #the connector length - self._connector_length = CONNECTOR_EXTENSION_MINIMAL + CONNECTOR_EXTENSION_INCREMENT*index - - def create_labels(self): - """Create the labels for the socket.""" - Element.create_labels(self) - self._bg_color = Colors.get_color(self.get_color()) - # create the layout - layout = gtk.DrawingArea().create_pango_layout('') - layout.set_markup(Utils.parse_template(PORT_MARKUP_TMPL, port=self, font=PORT_FONT)) - self.w, self.h = layout.get_pixel_size() - self.W = 2 * PORT_LABEL_PADDING + self.w - self.H = 2 * PORT_LABEL_PADDING + self.h * ( - 3 if self.get_type() == 'bus' else 1) - self.H += self.H % 2 - # create the pixmap - pixmap = self.get_parent().get_parent().new_pixmap(self.w, self.h) - gc = pixmap.new_gc() - gc.set_foreground(self._bg_color) - pixmap.draw_rectangle(gc, True, 0, 0, self.w, self.h) - pixmap.draw_layout(gc, 0, 0, layout) - # create vertical and horizontal pixmaps - self.horizontal_label = pixmap - if self.is_vertical(): - self.vertical_label = self.get_parent().get_parent().new_pixmap(self.h, self.w) - Utils.rotate_pixmap(gc, self.horizontal_label, self.vertical_label) - - def draw(self, gc, window): - """ - Draw the socket with a label. - - Args: - gc: the graphics context - window: the gtk window to draw on - """ - Element.draw( - self, gc, window, bg_color=self._bg_color, - border_color=self.is_highlighted() and Colors.HIGHLIGHT_COLOR or - self.get_parent().is_dummy_block and Colors.MISSING_BLOCK_BORDER_COLOR or - Colors.BORDER_COLOR, - ) - if not self._areas_list or self._label_hidden(): - return # this port is either hidden (no areas) or folded (no label) - X, Y = self.get_coordinate() - (x, y), (w, h) = self._areas_list[0] # use the first area's sizes to place the labels - if self.is_horizontal(): - window.draw_drawable(gc, self.horizontal_label, 0, 0, x+X+(self.W-self.w)/2, y+Y+(self.H-self.h)/2, -1, -1) - elif self.is_vertical(): - window.draw_drawable(gc, self.vertical_label, 0, 0, x+X+(self.H-self.h)/2, y+Y+(self.W-self.w)/2, -1, -1) - - def get_connector_coordinate(self): - """ - Get the coordinate where connections may attach to. - - Returns: - the connector coordinate (x, y) tuple - """ - x, y = self._connector_coordinate - X, Y = self.get_coordinate() - return (x + X, y + Y) - - def get_connector_direction(self): - """ - Get the direction that the socket points: 0,90,180,270. - This is the rotation degree if the socket is an output or - the rotation degree + 180 if the socket is an input. - - Returns: - the direction in degrees - """ - if self.is_source: return self.get_rotation() - elif self.is_sink: return (self.get_rotation() + 180)%360 - - def get_connector_length(self): - """ - Get the length of the connector. - The connector length increases as the port index changes. - - Returns: - the length in pixels - """ - return self._connector_length - - def get_rotation(self): - """ - Get the parent's rotation rather than self. - - Returns: - the parent's rotation - """ - return self.get_parent().get_rotation() - - def move(self, delta_coor): - """ - Move the parent rather than self. - - Args: - delta_corr: the (delta_x, delta_y) tuple - """ - self.get_parent().move(delta_coor) - - def rotate(self, direction): - """ - Rotate the parent rather than self. - - Args: - direction: degrees to rotate - """ - self.get_parent().rotate(direction) - - def get_coordinate(self): - """ - Get the parent's coordinate rather than self. - - Returns: - the parents coordinate - """ - return self.get_parent().get_coordinate() - - def set_highlighted(self, highlight): - """ - Set the parent highlight rather than self. - - Args: - highlight: true to enable highlighting - """ - self.get_parent().set_highlighted(highlight) - - def is_highlighted(self): - """ - Get the parent's is highlight rather than self. - - Returns: - the parent's highlighting status - """ - return self.get_parent().is_highlighted() - - def _label_hidden(self): - """ - Figure out if the label should be hidden - - Returns: - true if the label should not be shown - """ - return self._hovering and not self._force_label_unhidden and Actions.TOGGLE_AUTO_HIDE_PORT_LABELS.get_active() - - def force_label_unhidden(self, enable=True): - """ - Disable showing the label on mouse-over for this port - - Args: - enable: true to override the mouse-over behaviour - """ - self._force_label_unhidden = enable - - def mouse_over(self): - """ - Called from flow graph on mouse-over - """ - self._hovering = False - return Actions.TOGGLE_AUTO_HIDE_PORT_LABELS.get_active() # only redraw if necessary - - def mouse_out(self): - """ - Called from flow graph on mouse-out - """ - self._hovering = True - return Actions.TOGGLE_AUTO_HIDE_PORT_LABELS.get_active() # only redraw if necessary diff --git a/grc/gui/Preferences.py b/grc/gui/Preferences.py deleted file mode 100644 index d377018eb4..0000000000 --- a/grc/gui/Preferences.py +++ /dev/null @@ -1,173 +0,0 @@ -""" -Copyright 2008 Free Software Foundation, Inc. -This file is part of GNU Radio - -GNU Radio Companion 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 2 -of the License, or (at your option) any later version. - -GNU Radio Companion 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 this program; if not, write to the Free Software -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -""" - -import os -import sys -import ConfigParser - - -HEADER = """\ -# This contains only GUI settings for GRC and is not meant for users to edit. -# -# GRC settings not accessible through the GUI are in gnuradio.conf under -# section [grc]. - -""" - -_platform = None -_config_parser = ConfigParser.SafeConfigParser() - - -def file_extension(): - return '.grc' - - -def load(platform): - global _platform - _platform = platform - # create sections - for section in ['main', 'files_open', 'files_recent']: - try: - _config_parser.add_section(section) - except Exception, e: - print e - try: - _config_parser.read(_platform.get_prefs_file()) - except Exception as err: - print >> sys.stderr, err - - -def save(): - try: - with open(_platform.get_prefs_file(), 'w') as fp: - fp.write(HEADER) - _config_parser.write(fp) - except Exception as err: - print >> sys.stderr, err - - -def entry(key, value=None, default=None): - if value is not None: - _config_parser.set('main', key, str(value)) - result = value - else: - _type = type(default) if default is not None else str - getter = { - bool: _config_parser.getboolean, - int: _config_parser.getint, - }.get(_type, _config_parser.get) - try: - result = getter('main', key) - except (AttributeError, ConfigParser.Error): - result = _type() if default is None else default - return result - - -########################################################################### -# Special methods for specific program functionalities -########################################################################### - -def main_window_size(size=None): - if size is None: - size = [None, None] - w = entry('main_window_width', size[0], default=1) - h = entry('main_window_height', size[1], default=1) - return w, h - - -def file_open(filename=None): - return entry('file_open', filename, default='') - - -def set_file_list(key, files): - _config_parser.remove_section(key) # clear section - _config_parser.add_section(key) - for i, filename in enumerate(files): - _config_parser.set(key, '%s_%d' % (key, i), filename) - - -def get_file_list(key): - try: - files = [value for name, value in _config_parser.items(key) - if name.startswith('%s_' % key)] - except (AttributeError, ConfigParser.Error): - files = [] - return files - - -def get_open_files(): - return get_file_list('files_open') - - -def set_open_files(files): - return set_file_list('files_open', files) - - -def get_recent_files(): - """ Gets recent files, removes any that do not exist and re-saves it """ - files = filter(os.path.exists, get_file_list('files_recent')) - set_recent_files(files) - return files - - -def set_recent_files(files): - return set_file_list('files_recent', files) - - -def add_recent_file(file_name): - # double check file_name - if os.path.exists(file_name): - recent_files = get_recent_files() - if file_name in recent_files: - recent_files.remove(file_name) # Attempt removal - recent_files.insert(0, file_name) # Insert at start - set_recent_files(recent_files[:10]) # Keep up to 10 files - - -def console_window_position(pos=None): - return entry('console_window_position', pos, default=-1) or 1 - - -def blocks_window_position(pos=None): - return entry('blocks_window_position', pos, default=-1) or 1 - - -def variable_editor_position(pos=None, sidebar=False): - # Figure out default - if sidebar: - w, h = main_window_size() - return entry('variable_editor_sidebar_position', pos, default=int(h*0.7)) - else: - return entry('variable_editor_position', pos, default=int(blocks_window_position()*0.5)) - - -def variable_editor_sidebar(pos=None): - return entry('variable_editor_sidebar', pos, default=False) - - -def variable_editor_confirm_delete(pos=None): - return entry('variable_editor_confirm_delete', pos, default=True) - - -def xterm_missing(cmd=None): - return entry('xterm_missing', cmd, default='INVALID_XTERM_SETTING') - - -def screen_shot_background_transparent(transparent=None): - return entry('screen_shot_background_transparent', transparent, default=False) diff --git a/grc/gui/PropsDialog.py b/grc/gui/PropsDialog.py index a5b46cbbac..5f39770e78 100644 --- a/grc/gui/PropsDialog.py +++ b/grc/gui/PropsDialog.py @@ -17,116 +17,91 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import pygtk -pygtk.require('2.0') -import gtk +from __future__ import absolute_import +from gi.repository import Gtk, Gdk, GObject, Pango -import Actions -from Dialogs import SimpleTextDisplay -from Constants import MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT, FONT_SIZE -import Utils -import pango +from . import Actions, Utils, Constants +from .Dialogs import SimpleTextDisplay +import six -TAB_LABEL_MARKUP_TMPL="""\ -#set $foreground = $valid and 'black' or 'red' -<span foreground="$foreground">$encode($tab)</span>""" - -def get_title_label(title): - """ - Get a title label for the params window. - The title will be bold, underlined, and left justified. - - Args: - title: the text of the title - - Returns: - a gtk object - """ - label = gtk.Label() - label.set_markup('\n<b><span underline="low">%s</span>:</b>\n'%title) - hbox = gtk.HBox() - hbox.pack_start(label, False, False, padding=11) - return hbox - - -class PropsDialog(gtk.Dialog): +class PropsDialog(Gtk.Dialog): """ A dialog to set block parameters, view errors, and view documentation. """ - def __init__(self, block): + def __init__(self, parent, block): """ Properties dialog constructor. - Args: + Args:% block: a block instance """ - self._hash = 0 - gtk.Dialog.__init__( + Gtk.Dialog.__init__( self, - title='Properties: %s' % block.get_name(), - buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, - gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, - gtk.STOCK_APPLY, gtk.RESPONSE_APPLY) + title='Properties: ' + block.name, + transient_for=parent, + modal=True, + destroy_with_parent=True, + ) + self.add_buttons( + Gtk.STOCK_OK, Gtk.ResponseType.ACCEPT, + Gtk.STOCK_CANCEL, Gtk.ResponseType.REJECT, + Gtk.STOCK_APPLY, Gtk.ResponseType.APPLY, ) - self.set_response_sensitive(gtk.RESPONSE_APPLY, False) + self.set_response_sensitive(Gtk.ResponseType.APPLY, False) self.set_size_request(*Utils.scale( - (MIN_DIALOG_WIDTH, MIN_DIALOG_HEIGHT) + (Constants.MIN_DIALOG_WIDTH, Constants.MIN_DIALOG_HEIGHT) )) + self._block = block + self._hash = 0 - vpaned = gtk.VPaned() - self.vbox.pack_start(vpaned) + vpaned = Gtk.VPaned() + self.vbox.pack_start(vpaned, True, True, 0) # Notebook to hold param boxes - notebook = gtk.Notebook() + notebook = self.notebook = Gtk.Notebook() notebook.set_show_border(False) notebook.set_scrollable(True) # scroll arrows for page tabs - notebook.set_tab_pos(gtk.POS_TOP) + notebook.set_tab_pos(Gtk.PositionType.TOP) vpaned.pack1(notebook, True) # Params boxes for block parameters - self._params_boxes = list() - for tab in block.get_param_tab_labels(): - label = gtk.Label() - vbox = gtk.VBox() - scroll_box = gtk.ScrolledWindow() - scroll_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scroll_box.add_with_viewport(vbox) - notebook.append_page(scroll_box, label) - self._params_boxes.append((tab, label, vbox)) + self._params_boxes = [] + self._build_param_tab_boxes(block.params) # Docs for the block self._docs_text_display = doc_view = SimpleTextDisplay() - doc_view.get_buffer().create_tag('b', weight=pango.WEIGHT_BOLD) - self._docs_box = gtk.ScrolledWindow() - self._docs_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self._docs_box.add_with_viewport(self._docs_text_display) - notebook.append_page(self._docs_box, gtk.Label("Documentation")) + doc_view.get_buffer().create_tag('b', weight=Pango.Weight.BOLD) + self._docs_box = Gtk.ScrolledWindow() + self._docs_box.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + self._docs_box.add(self._docs_text_display) + notebook.append_page(self._docs_box, Gtk.Label(label="Documentation")) # Generated code for the block if Actions.TOGGLE_SHOW_CODE_PREVIEW_TAB.get_active(): self._code_text_display = code_view = SimpleTextDisplay() - code_view.set_wrap_mode(gtk.WRAP_NONE) - code_view.get_buffer().create_tag('b', weight=pango.WEIGHT_BOLD) - code_view.modify_font(pango.FontDescription( - 'monospace %d' % FONT_SIZE)) - code_box = gtk.ScrolledWindow() - code_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - code_box.add_with_viewport(self._code_text_display) - notebook.append_page(code_box, gtk.Label("Generated Code")) + code_view.set_wrap_mode(Gtk.WrapMode.NONE) + code_view.get_buffer().create_tag('b', weight=Pango.Weight.BOLD) + code_view.set_monospace(True) + # todo: set font size in non-deprecated way + # code_view.override_font(Pango.FontDescription('monospace %d' % Constants.FONT_SIZE)) + code_box = Gtk.ScrolledWindow() + code_box.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + code_box.add(self._code_text_display) + notebook.append_page(code_box, Gtk.Label(label="Generated Code")) else: self._code_text_display = None # Error Messages for the block self._error_messages_text_display = SimpleTextDisplay() - self._error_box = gtk.ScrolledWindow() - self._error_box.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self._error_box.add_with_viewport(self._error_messages_text_display) + self._error_box = Gtk.ScrolledWindow() + self._error_box.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + self._error_box.add(self._error_messages_text_display) vpaned.pack2(self._error_box) - vpaned.set_position(int(0.65 * MIN_DIALOG_HEIGHT)) + vpaned.set_position(int(0.65 * Constants.MIN_DIALOG_HEIGHT)) # Connect events self.connect('key-press-event', self._handle_key_press) @@ -134,6 +109,27 @@ class PropsDialog(gtk.Dialog): self.connect('response', self._handle_response) self.show_all() # show all (performs initial gui update) + def _build_param_tab_boxes(self, params): + tab_labels = (p.tab_label for p in self._block.params.values()) + + def unique_tab_labels(): + seen = {Constants.DEFAULT_PARAM_TAB} + yield Constants.DEFAULT_PARAM_TAB + for tab_label in tab_labels: + if tab_label in seen: + continue + yield tab_label + seen.add(tab_label) + + for tab in unique_tab_labels(): + label = Gtk.Label() + vbox = Gtk.VBox() + scroll_box = Gtk.ScrolledWindow() + scroll_box.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scroll_box.add(vbox) + self.notebook.append_page(scroll_box, label) + self._params_boxes.append((tab, label, vbox)) + def _params_changed(self): """ Have the params in this dialog changed? @@ -146,25 +142,23 @@ class PropsDialog(gtk.Dialog): true if changed """ old_hash = self._hash - # create a tuple of things from each param that affects the params box - self._hash = hash(tuple([( - hash(param), param.get_name(), param.get_type(), - param.get_hide() == 'all', - ) for param in self._block.get_params()])) - return self._hash != old_hash + new_hash = self._hash = hash(tuple( + (hash(param), param.name, param.get_type(), param.get_hide() == 'all',) + for param in self._block.params.values() + )) + return new_hash != old_hash def _handle_changed(self, *args): """ A change occurred within a param: Rewrite/validate the block and update the gui. """ - # update for the block self._block.rewrite() self._block.validate() self.update_gui() def _activate_apply(self, *args): - self.set_response_sensitive(gtk.RESPONSE_APPLY, True) + self.set_response_sensitive(Gtk.ResponseType.APPLY, True) def update_gui(self, widget=None, force=False): """ @@ -175,45 +169,48 @@ class PropsDialog(gtk.Dialog): Update the documentation block. Hide the box if there are no docs. """ - # update the params box if force or self._params_changed(): # hide params box before changing for tab, label, vbox in self._params_boxes: - vbox.hide_all() + vbox.hide() # empty the params box for child in vbox.get_children(): vbox.remove(child) - child.destroy() + # child.destroy() # disabled because it throws errors... # repopulate the params box box_all_valid = True - for param in filter(lambda p: p.get_tab_label() == tab, self._block.get_params()): - if param.get_hide() == 'all': + for param in self._block.params.values(): + # todo: why do we even rebuild instead of really hiding params? + if param.get_tab_label() != tab or param.get_hide() == 'all': continue box_all_valid = box_all_valid and param.is_valid() + input_widget = param.get_input(self._handle_changed, self._activate_apply) - vbox.pack_start(input_widget, input_widget.expand) - label.set_markup(Utils.parse_template(TAB_LABEL_MARKUP_TMPL, valid=box_all_valid, tab=tab)) - # show params box with new params - vbox.show_all() - # update the errors box + input_widget.show_all() + vbox.pack_start(input_widget, input_widget.expand, True, 1) + + label.set_markup('<span foreground="{color}">{name}</span>'.format( + color='black' if box_all_valid else 'red', name=Utils.encode(tab) + )) + vbox.show() # show params box with new params + if self._block.is_valid(): self._error_box.hide() else: self._error_box.show() messages = '\n\n'.join(self._block.get_error_messages()) self._error_messages_text_display.set_text(messages) - # update the docs box + self._update_docs_page() - # update the generated code self._update_generated_code_page() def _update_docs_page(self): """Show documentation from XML and try to display best matching docstring""" - buffer = self._docs_text_display.get_buffer() - buffer.delete(buffer.get_start_iter(), buffer.get_end_iter()) - pos = buffer.get_end_iter() + buf = self._docs_text_display.get_buffer() + buf.delete(buf.get_start_iter(), buf.get_end_iter()) + pos = buf.get_end_iter() - docstrings = self._block.get_doc() + docstrings = self._block.documentation if not docstrings: return @@ -221,11 +218,11 @@ class PropsDialog(gtk.Dialog): from_xml = docstrings.pop('', '') for line in from_xml.splitlines(): if line.lstrip() == line and line.endswith(':'): - buffer.insert_with_tags_by_name(pos, line + '\n', 'b') + buf.insert_with_tags_by_name(pos, line + '\n', 'b') else: - buffer.insert(pos, line + '\n') + buf.insert(pos, line + '\n') if from_xml: - buffer.insert(pos, '\n') + buf.insert(pos, '\n') # if given the current parameters an exact match can be made block_constructor = self._block.get_make().rsplit('.', 2)[-1] @@ -234,19 +231,19 @@ class PropsDialog(gtk.Dialog): docstrings = {block_class: docstrings[block_class]} # show docstring(s) extracted from python sources - for cls_name, docstring in docstrings.iteritems(): - buffer.insert_with_tags_by_name(pos, cls_name + '\n', 'b') - buffer.insert(pos, docstring + '\n\n') + for cls_name, docstring in six.iteritems(docstrings): + buf.insert_with_tags_by_name(pos, cls_name + '\n', 'b') + buf.insert(pos, docstring + '\n\n') pos.backward_chars(2) - buffer.delete(pos, buffer.get_end_iter()) + buf.delete(pos, buf.get_end_iter()) def _update_generated_code_page(self): if not self._code_text_display: return # user disabled code preview - buffer = self._code_text_display.get_buffer() + buf = self._code_text_display.get_buffer() block = self._block - key = block.get_key() + key = block.key if key == 'epy_block': src = block.get_param('_source_code').get_value() @@ -258,40 +255,34 @@ class PropsDialog(gtk.Dialog): def insert(header, text): if not text: return - buffer.insert_with_tags_by_name(buffer.get_end_iter(), header, 'b') - buffer.insert(buffer.get_end_iter(), text) + buf.insert_with_tags_by_name(buf.get_end_iter(), header, 'b') + buf.insert(buf.get_end_iter(), text) - buffer.delete(buffer.get_start_iter(), buffer.get_end_iter()) + buf.delete(buf.get_start_iter(), buf.get_end_iter()) insert('# Imports\n', '\n'.join(block.get_imports())) - if key.startswith('variable'): + if block.is_variable: insert('\n\n# Variables\n', block.get_var_make()) insert('\n\n# Blocks\n', block.get_make()) if src: insert('\n\n# External Code ({}.py)\n'.format(block.get_id()), src) def _handle_key_press(self, widget, event): - """ - Handle key presses from the keyboard. - Call the ok response when enter is pressed. - - Returns: - false to forward the keypress - """ - if (event.keyval == gtk.keysyms.Return and - event.state & gtk.gdk.CONTROL_MASK == 0 and - not isinstance(widget.get_focus(), gtk.TextView) - ): - self.response(gtk.RESPONSE_ACCEPT) + close_dialog = ( + event.keyval == Gdk.KEY_Return and + event.get_state() & Gdk.ModifierType.CONTROL_MASK == 0 and + not isinstance(widget.get_focus(), Gtk.TextView) + ) + if close_dialog: + self.response(Gtk.ResponseType.ACCEPT) return True # handled here + return False # forward the keypress def _handle_response(self, widget, response): - if response in (gtk.RESPONSE_APPLY, gtk.RESPONSE_ACCEPT): + if response in (Gtk.ResponseType.APPLY, Gtk.ResponseType.ACCEPT): for tab, label, vbox in self._params_boxes: for child in vbox.get_children(): child.apply_pending_changes() - self.set_response_sensitive(gtk.RESPONSE_APPLY, False) + self.set_response_sensitive(Gtk.ResponseType.APPLY, False) return True return False - - diff --git a/grc/gui/StateCache.py b/grc/gui/StateCache.py index 3cdb5f30ce..ef260d6091 100644 --- a/grc/gui/StateCache.py +++ b/grc/gui/StateCache.py @@ -17,8 +17,9 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import Actions -from Constants import STATE_CACHE_SIZE +from __future__ import absolute_import +from . import Actions +from .Constants import STATE_CACHE_SIZE class StateCache(object): """ @@ -98,5 +99,5 @@ class StateCache(object): """ Update the undo and redo actions based on the number of next and prev states. """ - Actions.FLOW_GRAPH_REDO.set_sensitive(self.num_next_states != 0) - Actions.FLOW_GRAPH_UNDO.set_sensitive(self.num_prev_states != 0) + Actions.FLOW_GRAPH_REDO.set_enabled(self.num_next_states != 0) + Actions.FLOW_GRAPH_UNDO.set_enabled(self.num_prev_states != 0) diff --git a/grc/gui/Utils.py b/grc/gui/Utils.py index 3ab8d2009e..969f3759f2 100644 --- a/grc/gui/Utils.py +++ b/grc/gui/Utils.py @@ -17,37 +17,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -import pygtk -pygtk.require('2.0') -import gtk -import gobject +from __future__ import absolute_import -from Cheetah.Template import Template +from gi.repository import GLib +import cairo +import six -from Constants import POSSIBLE_ROTATIONS, CANVAS_GRID_SIZE, DPI_SCALING - - -def rotate_pixmap(gc, src_pixmap, dst_pixmap, angle=gtk.gdk.PIXBUF_ROTATE_COUNTERCLOCKWISE): - """ - Load the destination pixmap with a rotated version of the source pixmap. - The source pixmap will be loaded into a pixbuf, rotated, and drawn to the destination pixmap. - The pixbuf is a client-side drawable, where a pixmap is a server-side drawable. - - Args: - gc: the graphics context - src_pixmap: the source pixmap - dst_pixmap: the destination pixmap - angle: the angle to rotate by - """ - width, height = src_pixmap.get_size() - pixbuf = gtk.gdk.Pixbuf( - colorspace=gtk.gdk.COLORSPACE_RGB, - has_alpha=False, bits_per_sample=8, - width=width, height=height, - ) - pixbuf.get_from_drawable(src_pixmap, src_pixmap.get_colormap(), 0, 0, 0, 0, -1, -1) - pixbuf = pixbuf.rotate_simple(angle) - dst_pixmap.draw_pixbuf(gc, pixbuf, 0, 0, 0, 0) +from .canvas.colors import FLOWGRAPH_BACKGROUND_COLOR +from . import Constants def get_rotated_coordinate(coor, rotation): @@ -62,8 +39,8 @@ def get_rotated_coordinate(coor, rotation): the rotated coordinates """ # handles negative angles - rotation = (rotation + 360)%360 - if rotation not in POSSIBLE_ROTATIONS: + rotation = (rotation + 360) % 360 + if rotation not in Constants.POSSIBLE_ROTATIONS: raise ValueError('unusable rotation angle "%s"'%str(rotation)) # determine the number of degrees to rotate cos_r, sin_r = { @@ -73,7 +50,7 @@ def get_rotated_coordinate(coor, rotation): return x * cos_r + y * sin_r, -x * sin_r + y * cos_r -def get_angle_from_coordinates((x1, y1), (x2, y2)): +def get_angle_from_coordinates(p1, p2): """ Given two points, calculate the vector direction from point1 to point2, directions are multiples of 90 degrees. @@ -84,59 +61,100 @@ def get_angle_from_coordinates((x1, y1), (x2, y2)): Returns: the direction in degrees """ + (x1, y1) = p1 + (x2, y2) = p2 if y1 == y2: # 0 or 180 return 0 if x2 > x1 else 180 else: # 90 or 270 return 270 if y2 > y1 else 90 +def align_to_grid(coor, mode=round): + def align(value): + return int(mode(value / (1.0 * Constants.CANVAS_GRID_SIZE)) * Constants.CANVAS_GRID_SIZE) + try: + return [align(c) for c in coor] + except TypeError: + x = coor + return align(coor) + + +def num_to_str(num): + """ Display logic for numbers """ + def eng_notation(value, fmt='g'): + """Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n""" + template = '{:' + fmt + '}{}' + magnitude = abs(value) + for exp, symbol in zip(range(9, -15-1, -3), 'GMk munpf'): + factor = 10 ** exp + if magnitude >= factor: + return template.format(value / factor, symbol.strip()) + return template.format(value, '') + + if isinstance(num, Constants.COMPLEX_TYPES): + num = complex(num) # Cast to python complex + if num == 0: + return '0' + output = eng_notation(num.real) if num.real else '' + output += eng_notation(num.imag, '+g' if output else 'g') + 'j' if num.imag else '' + return output + else: + return str(num) + + def encode(value): """Make sure that we pass only valid utf-8 strings into markup_escape_text. Older versions of glib seg fault if the last byte starts a multi-byte character. """ - - valid_utf8 = value.decode('utf-8', errors='replace').encode('utf-8') - return gobject.markup_escape_text(valid_utf8) + if six.PY2: + valid_utf8 = value.decode('utf-8', errors='replace').encode('utf-8') + else: + valid_utf8 = value + return GLib.markup_escape_text(valid_utf8) -class TemplateParser(object): - def __init__(self): - self.cache = {} +def make_screenshot(flow_graph, file_path, transparent_bg=False): + if not file_path: + return - def __call__(self, tmpl_str, **kwargs): - """ - Parse the template string with the given args. - Pass in the xml encode method for pango escape chars. + x_min, y_min, x_max, y_max = flow_graph.get_extents() + padding = Constants.CANVAS_GRID_SIZE + width = x_max - x_min + 2 * padding + height = y_max - y_min + 2 * padding - Args: - tmpl_str: the template as a string + if file_path.endswith('.png'): + psurf = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + elif file_path.endswith('.pdf'): + psurf = cairo.PDFSurface(file_path, width, height) + elif file_path.endswith('.svg'): + psurf = cairo.SVGSurface(file_path, width, height) + else: + raise ValueError('Unknown file format') - Returns: - a string of the parsed template - """ - kwargs['encode'] = encode - template = self.cache.setdefault(tmpl_str, Template.compile(tmpl_str)) - return str(template(namespaces=kwargs)) + cr = cairo.Context(psurf) -parse_template = TemplateParser() + if not transparent_bg: + cr.set_source_rgba(*FLOWGRAPH_BACKGROUND_COLOR) + cr.rectangle(0, 0, width, height) + cr.fill() + cr.translate(padding - x_min, padding - y_min) + flow_graph.draw(cr) -def align_to_grid(coor, mode=round): - def align(value): - return int(mode(value / (1.0 * CANVAS_GRID_SIZE)) * CANVAS_GRID_SIZE) - try: - return map(align, coor) - except TypeError: - x = coor - return align(coor) + if file_path.endswith('.png'): + psurf.write_to_png(file_path) + if file_path.endswith('.pdf') or file_path.endswith('.svg'): + cr.show_page() + psurf.finish() def scale(coor, reverse=False): - factor = DPI_SCALING if not reverse else 1 / DPI_SCALING + factor = Constants.DPI_SCALING if not reverse else 1 / Constants.DPI_SCALING return tuple(int(x * factor) for x in coor) + def scale_scalar(coor, reverse=False): - factor = DPI_SCALING if not reverse else 1 / DPI_SCALING + factor = Constants.DPI_SCALING if not reverse else 1 / Constants.DPI_SCALING return int(coor * factor) diff --git a/grc/gui/VariableEditor.py b/grc/gui/VariableEditor.py index 45f0bb75fc..e310676420 100644 --- a/grc/gui/VariableEditor.py +++ b/grc/gui/VariableEditor.py @@ -1,5 +1,5 @@ """ -Copyright 2015 Free Software Foundation, Inc. +Copyright 2015, 2016 Free Software Foundation, Inc. This file is part of GNU Radio GNU Radio Companion is free software; you can redistribute it and/or @@ -17,50 +17,45 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ -from operator import attrgetter +from __future__ import absolute_import -import pygtk -pygtk.require('2.0') -import gtk -import gobject +from gi.repository import Gtk, Gdk, GObject -from . import Actions -from . import Preferences -from . import Utils -from .Constants import DEFAULT_BLOCKS_WINDOW_WIDTH +from . import Actions, Constants, Utils BLOCK_INDEX = 0 ID_INDEX = 1 -class VariableEditorContextMenu(gtk.Menu): +class VariableEditorContextMenu(Gtk.Menu): """ A simple context menu for our variable editor """ + def __init__(self, var_edit): - gtk.Menu.__init__(self) + Gtk.Menu.__init__(self) - self.imports = gtk.MenuItem("Add _Import") + self.imports = Gtk.MenuItem(label="Add _Import") self.imports.connect('activate', var_edit.handle_action, var_edit.ADD_IMPORT) self.add(self.imports) - self.variables = gtk.MenuItem("Add _Variable") + self.variables = Gtk.MenuItem(label="Add _Variable") self.variables.connect('activate', var_edit.handle_action, var_edit.ADD_VARIABLE) self.add(self.variables) - self.add(gtk.SeparatorMenuItem()) + self.add(Gtk.SeparatorMenuItem()) - self.enable = gtk.MenuItem("_Enable") + self.enable = Gtk.MenuItem(label="_Enable") self.enable.connect('activate', var_edit.handle_action, var_edit.ENABLE_BLOCK) - self.disable = gtk.MenuItem("_Disable") + self.disable = Gtk.MenuItem(label="_Disable") self.disable.connect('activate', var_edit.handle_action, var_edit.DISABLE_BLOCK) self.add(self.enable) self.add(self.disable) - self.add(gtk.SeparatorMenuItem()) + self.add(Gtk.SeparatorMenuItem()) - self.delete = gtk.MenuItem("_Delete") + self.delete = Gtk.MenuItem(label="_Delete") self.delete.connect('activate', var_edit.handle_action, var_edit.DELETE_BLOCK) self.add(self.delete) - self.add(gtk.SeparatorMenuItem()) + self.add(Gtk.SeparatorMenuItem()) - self.properties = gtk.MenuItem("_Properties...") + self.properties = Gtk.MenuItem(label="_Properties...") self.properties.connect('activate', var_edit.handle_action, var_edit.OPEN_PROPERTIES) self.add(self.properties) self.show_all() @@ -72,7 +67,7 @@ class VariableEditorContextMenu(gtk.Menu): self.disable.set_sensitive(selected and enabled) -class VariableEditor(gtk.VBox): +class VariableEditor(Gtk.VBox): # Actions that are handled by the editor ADD_IMPORT = 0 @@ -83,23 +78,30 @@ class VariableEditor(gtk.VBox): ENABLE_BLOCK = 5 DISABLE_BLOCK = 6 - def __init__(self, platform, get_flow_graph): - gtk.VBox.__init__(self) - self.platform = platform - self.get_flow_graph = get_flow_graph + __gsignals__ = { + 'create_new_block': (GObject.SignalFlags.RUN_FIRST, None, (str,)), + 'remove_block': (GObject.SignalFlags.RUN_FIRST, None, (str,)) + } + + def __init__(self): + Gtk.VBox.__init__(self) + config = Gtk.Application.get_default().config + self._block = None self._mouse_button_pressed = False + self._imports = [] + self._variables = [] # Only use the model to store the block reference and name. # Generate everything else dynamically - self.treestore = gtk.TreeStore(gobject.TYPE_PYOBJECT, # Block reference - gobject.TYPE_STRING) # Category and block name - self.treeview = gtk.TreeView(self.treestore) + self.treestore = Gtk.TreeStore(GObject.TYPE_PYOBJECT, # Block reference + GObject.TYPE_STRING) # Category and block name + self.treeview = Gtk.TreeView(model=self.treestore) self.treeview.set_enable_search(False) self.treeview.set_search_column(-1) #self.treeview.set_enable_search(True) #self.treeview.set_search_column(ID_INDEX) - self.treeview.get_selection().set_mode('single') + self.treeview.get_selection().set_mode(Gtk.SelectionMode.SINGLE) self.treeview.set_headers_visible(True) self.treeview.connect('button-press-event', self._handle_mouse_button_press) self.treeview.connect('button-release-event', self._handle_mouse_button_release) @@ -107,67 +109,63 @@ class VariableEditor(gtk.VBox): self.treeview.connect('key-press-event', self._handle_key_button_press) # Block Name or Category - self.id_cell = gtk.CellRendererText() + self.id_cell = Gtk.CellRendererText() self.id_cell.connect('edited', self._handle_name_edited_cb) - id_column = gtk.TreeViewColumn("Id", self.id_cell, text=ID_INDEX) + id_column = Gtk.TreeViewColumn("Id", self.id_cell, text=ID_INDEX) id_column.set_name("id") id_column.set_resizable(True) id_column.set_max_width(Utils.scale_scalar(300)) id_column.set_min_width(Utils.scale_scalar(80)) id_column.set_fixed_width(Utils.scale_scalar(100)) - id_column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) + id_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED) id_column.set_cell_data_func(self.id_cell, self.set_properties) self.id_column = id_column self.treeview.append_column(id_column) - self.treestore.set_sort_column_id(ID_INDEX, gtk.SORT_ASCENDING) + self.treestore.set_sort_column_id(ID_INDEX, Gtk.SortType.ASCENDING) # For forcing resize self._col_width = 0 # Block Value - self.value_cell = gtk.CellRendererText() + self.value_cell = Gtk.CellRendererText() self.value_cell.connect('edited', self._handle_value_edited_cb) - value_column = gtk.TreeViewColumn("Value", self.value_cell) + value_column = Gtk.TreeViewColumn("Value", self.value_cell) value_column.set_name("value") value_column.set_resizable(False) value_column.set_expand(True) value_column.set_min_width(Utils.scale_scalar(100)) - value_column.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE) + value_column.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE) value_column.set_cell_data_func(self.value_cell, self.set_value) self.value_column = value_column self.treeview.append_column(value_column) # Block Actions (Add, Remove) - self.action_cell = gtk.CellRendererPixbuf() + self.action_cell = Gtk.CellRendererPixbuf() value_column.pack_start(self.action_cell, False) value_column.set_cell_data_func(self.action_cell, self.set_icon) # Make the scrolled window to hold the tree view - scrolled_window = gtk.ScrolledWindow() - scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scrolled_window.add_with_viewport(self.treeview) - scrolled_window.set_size_request(DEFAULT_BLOCKS_WINDOW_WIDTH, -1) - self.pack_start(scrolled_window) + scrolled_window = Gtk.ScrolledWindow() + scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) + scrolled_window.add(self.treeview) + scrolled_window.set_size_request(Constants.DEFAULT_BLOCKS_WINDOW_WIDTH, -1) + self.pack_start(scrolled_window, True, True, 0) # Context menus self._context_menu = VariableEditorContextMenu(self) - self._confirm_delete = Preferences.variable_editor_confirm_delete() + self._confirm_delete = config.variable_editor_confirm_delete() # Sets cell contents - def set_icon(self, col, cell, model, iter): + def set_icon(self, col, cell, model, iter, data): block = model.get_value(iter, BLOCK_INDEX) - if block: - pb = self.treeview.render_icon(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU, None) - else: - pb = self.treeview.render_icon(gtk.STOCK_ADD, gtk.ICON_SIZE_MENU, None) - cell.set_property('pixbuf', pb) + cell.set_property('icon-name', 'window-close' if block else 'list-add') - def set_value(self, col, cell, model, iter): + def set_value(self, col, cell, model, iter, data): sp = cell.set_property block = model.get_value(iter, BLOCK_INDEX) # Set the default properties for this column first. # Some set in set_properties() may be overridden (editable for advanced variable blocks) - self.set_properties(col, cell, model, iter) + self.set_properties(col, cell, model, iter, data) # Set defaults value = None @@ -175,9 +173,9 @@ class VariableEditor(gtk.VBox): # Block specific values if block: - if block.get_key() == 'import': + if block.key == 'import': value = block.get_param('import').get_value() - elif block.get_key() != "variable": + elif block.key != "variable": value = "<Open Properties>" sp('editable', False) sp('foreground', '#0D47A1') @@ -193,13 +191,13 @@ class VariableEditor(gtk.VBox): self.set_tooltip_text(error_message[-1]) else: # Evaluate and show the value (if it is a variable) - if block.get_key() == "variable": + if block.key == "variable": evaluated = str(block.get_param('value').evaluate()) self.set_tooltip_text(evaluated) # Always set the text value. sp('text', value) - def set_properties(self, col, cell, model, iter): + def set_properties(self, col, cell, model, iter, data): sp = cell.set_property block = model.get_value(iter, BLOCK_INDEX) # Set defaults @@ -209,7 +207,7 @@ class VariableEditor(gtk.VBox): # Block specific changes if block: - if not block.get_enabled(): + if not block.enabled: # Disabled block. But, this should still be editable sp('editable', True) sp('foreground', 'gray') @@ -218,19 +216,12 @@ class VariableEditor(gtk.VBox): if block.get_error_messages(): sp('foreground', 'red') - def update_gui(self): - if not self.get_flow_graph(): - return - self._update_blocks() + def update_gui(self, blocks): + self._imports = [block for block in blocks if block.is_import] + self._variables = [block for block in blocks if block.is_variable] self._rebuild() self.treeview.expand_all() - def _update_blocks(self): - self._imports = filter(attrgetter('is_import'), - self.get_flow_graph().blocks) - self._variables = filter(attrgetter('is_variable'), - self.get_flow_graph().blocks) - def _rebuild(self, *args): self.treestore.clear() imports = self.treestore.append(None, [None, 'Imports']) @@ -259,29 +250,31 @@ class VariableEditor(gtk.VBox): key presses or mouse clicks. Also triggers an update of the flow graph and editor. """ if key == self.ADD_IMPORT: - self.get_flow_graph().add_new_block('import') + self.emit('create_new_block', 'import') elif key == self.ADD_VARIABLE: - self.get_flow_graph().add_new_block('variable') + self.emit('create_new_block', 'variable') elif key == self.OPEN_PROPERTIES: - Actions.BLOCK_PARAM_MODIFY(self._block) + # TODO: This probably isn't working because the action doesn't expect a parameter + #Actions.BLOCK_PARAM_MODIFY() + pass elif key == self.DELETE_BLOCK: - self.get_flow_graph().remove_element(self._block) + self.emit('remove_block', self._block.get_id()) elif key == self.DELETE_CONFIRM: if self._confirm_delete: # Create a context menu to confirm the delete operation - confirmation_menu = gtk.Menu() + confirmation_menu = Gtk.Menu() block_id = self._block.get_param('id').get_value().replace("_", "__") - confirm = gtk.MenuItem("Delete {}".format(block_id)) + confirm = Gtk.MenuItem(label="Delete {}".format(block_id)) confirm.connect('activate', self.handle_action, self.DELETE_BLOCK) confirmation_menu.add(confirm) confirmation_menu.show_all() - confirmation_menu.popup(None, None, None, event.button, event.time) + confirmation_menu.popup(None, None, None, None, event.button, event.time) else: self.handle_action(None, self.DELETE_BLOCK, None) elif key == self.ENABLE_BLOCK: - self._block.set_enabled(True) + self._block.state = 'enabled' elif key == self.DISABLE_BLOCK: - self._block.set_enabled(False) + self._block.state = 'disabled' Actions.VARIABLE_EDITOR_UPDATE() def _handle_mouse_button_press(self, widget, event): @@ -303,12 +296,12 @@ class VariableEditor(gtk.VBox): if event.button == 1 and col.get_name() == "value": # Make sure this has a block (not the import/variable rows) - if self._block and event.type == gtk.gdk._2BUTTON_PRESS: + if self._block and event.type == Gdk.EventType._2BUTTON_PRESS: # Open the advanced dialog if it is a gui variable - if self._block.get_key() not in ("variable", "import"): + if self._block.key not in ("variable", "import"): self.handle_action(None, self.OPEN_PROPERTIES, event=event) return True - if event.type == gtk.gdk.BUTTON_PRESS: + if event.type == Gdk.EventType.BUTTON_PRESS: # User is adding/removing blocks # Make sure this is the action cell (Add/Remove Icons) if path[2] > col.cell_get_position(self.action_cell)[0]: @@ -321,15 +314,15 @@ class VariableEditor(gtk.VBox): else: self.handle_action(None, self.DELETE_CONFIRM, event=event) return True - elif event.button == 3 and event.type == gtk.gdk.BUTTON_PRESS: + elif event.button == 3 and event.type == Gdk.EventType.BUTTON_PRESS: if self._block: - self._context_menu.update_sensitive(True, enabled=self._block.get_enabled()) + self._context_menu.update_sensitive(True, enabled=self._block.enabled) else: self._context_menu.update_sensitive(False) - self._context_menu.popup(None, None, None, event.button, event.time) + self._context_menu.popup(None, None, None, None, event.button, event.time) # Null handler. Stops the treeview from handling double click events. - if event.type == gtk.gdk._2BUTTON_PRESS: + if event.type == Gdk.EventType._2BUTTON_PRESS: return True return False @@ -346,10 +339,10 @@ class VariableEditor(gtk.VBox): def _handle_key_button_press(self, widget, event): model, path = self.treeview.get_selection().get_selected_rows() if path and self._block: - if self._block.get_enabled() and event.string == "d": + if self._block.enabled and event.string == "d": self.handle_action(None, self.DISABLE_BLOCK, None) return True - elif not self._block.get_enabled() and event.string == "e": + elif not self._block.enabled and event.string == "e": self.handle_action(None, self.ENABLE_BLOCK, None) return True return False diff --git a/grc/gui/canvas/__init__.py b/grc/gui/canvas/__init__.py new file mode 100644 index 0000000000..f90d10c4e6 --- /dev/null +++ b/grc/gui/canvas/__init__.py @@ -0,0 +1,22 @@ +# Copyright 2016 Free Software Foundation, Inc. +# This file is part of GNU Radio +# +# GNU Radio Companion 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 2 +# of the License, or (at your option) any later version. +# +# GNU Radio Companion 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +from .block import Block +from .connection import Connection +from .flowgraph import FlowGraph +from .param import Param +from .port import Port diff --git a/grc/gui/canvas/block.py b/grc/gui/canvas/block.py new file mode 100644 index 0000000000..d336bc139a --- /dev/null +++ b/grc/gui/canvas/block.py @@ -0,0 +1,398 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion 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 2 +of the License, or (at your option) any later version. + +GNU Radio Companion 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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from __future__ import absolute_import, division + +import math + +import six +from gi.repository import Gtk, Pango, PangoCairo + +from . import colors +from .drawable import Drawable +from .. import Actions, Utils, Constants +from ..Constants import ( + BLOCK_LABEL_PADDING, PORT_SPACING, PORT_SEPARATION, LABEL_SEPARATION, + PORT_BORDER_SEPARATION, BLOCK_FONT, PARAM_FONT +) +from ...core import utils +from ...core.Block import Block as CoreBlock + + +class Block(CoreBlock, Drawable): + """The graphical signal block.""" + + def __init__(self, parent, **n): + """ + Block constructor. + Add graphics related params to the block. + """ + super(self.__class__, self).__init__(parent, **n) + + self.states.update(_coordinate=(0, 0), _rotation=0) + self.width = self.height = 0 + Drawable.__init__(self) # needs the states and initial sizes + + self._surface_layouts = [ + None, # title + None, # params + ] + self._surface_layouts_offsets = 0, 0 + self._comment_layout = None + + self._area = [] + self._border_color = self._bg_color = colors.BLOCK_ENABLED_COLOR + self._font_color = list(colors.FONT_COLOR) + + @property + def coordinate(self): + """ + Get the coordinate from the position param. + + Returns: + the coordinate tuple (x, y) or (0, 0) if failure + """ + return Utils.scale(self.states['_coordinate']) + + @coordinate.setter + def coordinate(self, coor): + """ + Set the coordinate into the position param. + + Args: + coor: the coordinate tuple (x, y) + """ + coor = Utils.scale(coor, reverse=True) + if Actions.TOGGLE_SNAP_TO_GRID.get_active(): + offset_x, offset_y = (0, self.height / 2) if self.is_horizontal() else (self.height / 2, 0) + coor = ( + Utils.align_to_grid(coor[0] + offset_x) - offset_x, + Utils.align_to_grid(coor[1] + offset_y) - offset_y + ) + self.states['_coordinate'] = coor + + @property + def rotation(self): + """ + Get the rotation from the position param. + + Returns: + the rotation in degrees or 0 if failure + """ + return self.states['_rotation'] + + @rotation.setter + def rotation(self, rot): + """ + Set the rotation into the position param. + + Args: + rot: the rotation in degrees + """ + self.states['_rotation'] = rot + + def _update_colors(self): + self._bg_color = ( + colors.MISSING_BLOCK_BACKGROUND_COLOR if self.is_dummy_block else + colors.BLOCK_BYPASSED_COLOR if self.state == 'bypassed' else + colors.BLOCK_ENABLED_COLOR if self.state == 'enabled' else + colors.BLOCK_DISABLED_COLOR + ) + self._font_color[-1] = 1.0 if self.state == 'enabled' else 0.4 + self._border_color = ( + colors.MISSING_BLOCK_BORDER_COLOR if self.is_dummy_block else + colors.BORDER_COLOR_DISABLED if not self.state == 'enabled' else colors.BORDER_COLOR + ) + + def create_shapes(self): + """Update the block, parameters, and ports when a change occurs.""" + if self.is_horizontal(): + self._area = (0, 0, self.width, self.height) + elif self.is_vertical(): + self._area = (0, 0, self.height, self.width) + self.bounds_from_area(self._area) + + bussified = self.current_bus_structure['source'], self.current_bus_structure['sink'] + for ports, has_busses in zip((self.active_sources, self.active_sinks), bussified): + if not ports: + continue + port_separation = PORT_SEPARATION if not has_busses else ports[0].height + PORT_SPACING + offset = (self.height - (len(ports) - 1) * port_separation - ports[0].height) / 2 + for port in ports: + port.create_shapes() + + port.coordinate = { + 0: (+self.width, offset), + 90: (offset, -port.width), + 180: (-port.width, offset), + 270: (offset, +self.width), + }[port.connector_direction] + + offset += PORT_SEPARATION if not has_busses else port.height + PORT_SPACING + + def create_labels(self, cr=None): + """Create the labels for the signal block.""" + + # (Re-)creating layouts here, because layout.context_changed() doesn't seems to work (after zoom) + title_layout, params_layout = self._surface_layouts = [ + Gtk.DrawingArea().create_pango_layout(''), # title + Gtk.DrawingArea().create_pango_layout(''), # params + ] + + if cr: # to fix up extents after zooming + PangoCairo.update_layout(cr, title_layout) + PangoCairo.update_layout(cr, params_layout) + + title_layout.set_markup( + '<span {foreground} font_desc="{font}"><b>{name}</b></span>'.format( + foreground='foreground="red"' if not self.is_valid() else '', font=BLOCK_FONT, + name=Utils.encode(self.name) + ) + ) + title_width, title_height = title_layout.get_size() + + # update the params layout + if not self.is_dummy_block: + markups = [param.format_block_surface_markup() + for param in self.params.values() if param.get_hide() not in ('all', 'part')] + else: + markups = ['<span font_desc="{font}"><b>key: </b>{key}</span>'.format(font=PARAM_FONT, key=self.key)] + + params_layout.set_spacing(LABEL_SEPARATION * Pango.SCALE) + params_layout.set_markup('\n'.join(markups)) + params_width, params_height = params_layout.get_size() if markups else (0, 0) + + label_width = max(title_width, params_width) / Pango.SCALE + label_height = title_height / Pango.SCALE + if markups: + label_height += LABEL_SEPARATION + params_height / Pango.SCALE + + # calculate width and height needed + width = label_width + 2 * BLOCK_LABEL_PADDING + height = label_height + 2 * BLOCK_LABEL_PADDING + + self._update_colors() + self.create_port_labels() + + def get_min_height_for_ports(ports): + min_height = 2 * PORT_BORDER_SEPARATION + len(ports) * PORT_SEPARATION + if ports: + min_height -= ports[-1].height + return min_height + + height = max(height, + get_min_height_for_ports(self.active_sinks), + get_min_height_for_ports(self.active_sources)) + + def get_min_height_for_bus_ports(ports): + return 2 * PORT_BORDER_SEPARATION + sum( + port.height + PORT_SPACING for port in ports if port.get_type() == 'bus' + ) - PORT_SPACING + + if self.current_bus_structure['sink']: + height = max(height, get_min_height_for_bus_ports(self.active_sinks)) + if self.current_bus_structure['source']: + height = max(height, get_min_height_for_bus_ports(self.active_sources)) + + self.width, self.height = width, height = Utils.align_to_grid((width, height)) + + self._surface_layouts_offsets = [ + (0, (height - label_height) / 2.0), + (0, (height - label_height) / 2.0 + LABEL_SEPARATION + title_height / Pango.SCALE) + ] + + title_layout.set_width(width * Pango.SCALE) + title_layout.set_alignment(Pango.Alignment.CENTER) + params_layout.set_indent((width - label_width) / 2.0 * Pango.SCALE) + + self.create_comment_layout() + + def create_port_labels(self): + for ports in (self.active_sinks, self.active_sources): + max_width = 0 + for port in ports: + port.create_labels() + max_width = max(max_width, port.width_with_label) + for port in ports: + port.width = max_width + + def create_comment_layout(self): + markups = [] + + # Show the flow graph complexity on the top block if enabled + if Actions.TOGGLE_SHOW_FLOWGRAPH_COMPLEXITY.get_active() and self.key == "options": + complexity = utils.calculate_flowgraph_complexity(self.parent) + markups.append( + '<span foreground="#444" size="medium" font_desc="{font}">' + '<b>Complexity: {num}bal</b></span>'.format(num=Utils.num_to_str(complexity), font=BLOCK_FONT) + ) + comment = self.comment # Returns None if there are no comments + if comment: + if markups: + markups.append('<span></span>') + + markups.append('<span foreground="{foreground}" font_desc="{font}">{comment}</span>'.format( + foreground='#444' if self.enabled else '#888', font=BLOCK_FONT, comment=Utils.encode(comment) + )) + if markups: + layout = self._comment_layout = Gtk.DrawingArea().create_pango_layout('') + layout.set_markup(''.join(markups)) + else: + self._comment_layout = None + + def draw(self, cr): + """ + Draw the signal block with label and inputs/outputs. + """ + border_color = colors.HIGHLIGHT_COLOR if self.highlighted else self._border_color + cr.translate(*self.coordinate) + + for port in self.active_ports(): # ports first + cr.save() + port.draw(cr) + cr.restore() + + cr.rectangle(*self._area) + cr.set_source_rgba(*self._bg_color) + cr.fill_preserve() + cr.set_source_rgba(*border_color) + cr.stroke() + + # title and params label + if self.is_vertical(): + cr.rotate(-math.pi / 2) + cr.translate(-self.width, 0) + cr.set_source_rgba(*self._font_color) + for layout, offset in zip(self._surface_layouts, self._surface_layouts_offsets): + cr.save() + cr.translate(*offset) + PangoCairo.update_layout(cr, layout) + PangoCairo.show_layout(cr, layout) + cr.restore() + + def what_is_selected(self, coor, coor_m=None): + """ + Get the element that is selected. + + Args: + coor: the (x,y) tuple + coor_m: the (x_m, y_m) tuple + + Returns: + this block, a port, or None + """ + for port in self.active_ports(): + port_selected = port.what_is_selected( + coor=[a - b for a, b in zip(coor, self.coordinate)], + coor_m=[a - b for a, b in zip(coor, self.coordinate)] if coor_m is not None else None + ) + if port_selected: + return port_selected + return Drawable.what_is_selected(self, coor, coor_m) + + def draw_comment(self, cr): + if not self._comment_layout: + return + x, y = self.coordinate + + if self.is_horizontal(): + y += self.height + BLOCK_LABEL_PADDING + else: + x += self.height + BLOCK_LABEL_PADDING + + cr.save() + cr.translate(x, y) + PangoCairo.update_layout(cr, self._comment_layout) + PangoCairo.show_layout(cr, self._comment_layout) + cr.restore() + + def get_extents(self): + extent = Drawable.get_extents(self) + x, y = self.coordinate + for port in self.active_ports(): + extent = (min_or_max(xy, offset + p_xy) for offset, min_or_max, xy, p_xy in zip( + (x, y, x, y), (min, min, max, max), extent, port.get_extents() + )) + return tuple(extent) + + ############################################## + # Controller Modify + ############################################## + def type_controller_modify(self, direction): + """ + Change the type controller. + + Args: + direction: +1 or -1 + + Returns: + true for change + """ + type_templates = ' '.join(p._type for p in self.get_children()) + type_param = None + for key, param in six.iteritems(self.params): + if not param.is_enum(): + continue + # Priority to the type controller + if param.key in type_templates: + type_param = param + break + # Use param if type param is unset + if not type_param: + type_param = param + if not type_param: + return False + + # Try to increment the enum by direction + try: + keys = list(type_param.options) + old_index = keys.index(type_param.get_value()) + new_index = (old_index + direction + len(keys)) % len(keys) + type_param.set_value(keys[new_index]) + return True + except: + return False + + def port_controller_modify(self, direction): + """ + Change the port controller. + + Args: + direction: +1 or -1 + + Returns: + true for change + """ + changed = False + # Concat the nports string from the private nports settings of all ports + nports_str = ' '.join(port._nports for port in self.get_ports()) + # Modify all params whose keys appear in the nports string + for key, param in six.iteritems(self.params): + if param.is_enum() or param.key not in nports_str: + continue + # Try to increment the port controller by direction + try: + value = param.get_evaluated() + direction + if value > 0: + param.set_value(value) + changed = True + except: + pass + return changed + diff --git a/grc/gui/canvas/colors.py b/grc/gui/canvas/colors.py new file mode 100644 index 0000000000..77d3203e78 --- /dev/null +++ b/grc/gui/canvas/colors.py @@ -0,0 +1,78 @@ +""" +Copyright 2008,2013 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion 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 2 +of the License, or (at your option) any later version. + +GNU Radio Companion 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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from __future__ import absolute_import + +from gi.repository import Gtk, Gdk, cairo +# import pycairo + +from .. import Constants + + +def get_color(color_code): + color = Gdk.RGBA() + color.parse(color_code) + return color.red, color.green, color.blue, color.alpha + # chars_per_color = 2 if len(color_code) > 4 else 1 + # offsets = range(1, 3 * chars_per_color + 1, chars_per_color) + # return tuple(int(color_code[o:o + 2], 16) / 255.0 for o in offsets) + +################################################################################# +# fg colors +################################################################################# + +HIGHLIGHT_COLOR = get_color('#00FFFF') +BORDER_COLOR = get_color('#616161') +BORDER_COLOR_DISABLED = get_color('#888888') +FONT_COLOR = get_color('#000000') + +# Missing blocks stuff +MISSING_BLOCK_BACKGROUND_COLOR = get_color('#FFF2F2') +MISSING_BLOCK_BORDER_COLOR = get_color('#FF0000') + +# Flow graph color constants +FLOWGRAPH_BACKGROUND_COLOR = get_color('#FFFFFF') +COMMENT_BACKGROUND_COLOR = get_color('#F3F3F3') +FLOWGRAPH_EDGE_COLOR = COMMENT_BACKGROUND_COLOR + +# Block color constants +BLOCK_ENABLED_COLOR = get_color('#F1ECFF') +BLOCK_DISABLED_COLOR = get_color('#CCCCCC') +BLOCK_BYPASSED_COLOR = get_color('#F4FF81') + +# Connection color constants +CONNECTION_ENABLED_COLOR = get_color('#000000') +CONNECTION_DISABLED_COLOR = get_color('#BBBBBB') +CONNECTION_ERROR_COLOR = get_color('#FF0000') + +DEFAULT_DOMAIN_COLOR = get_color('#777777') + + +################################################################################# +# port colors +################################################################################# + +PORT_TYPE_TO_COLOR = {key: get_color(color) for name, key, sizeof, color in Constants.CORE_TYPES} +PORT_TYPE_TO_COLOR.update((key, get_color(color)) for key, (_, color) in Constants.ALIAS_TYPES.items()) + + +################################################################################# +# param box colors +################################################################################# + diff --git a/grc/gui/canvas/connection.py b/grc/gui/canvas/connection.py new file mode 100644 index 0000000000..ff790503ef --- /dev/null +++ b/grc/gui/canvas/connection.py @@ -0,0 +1,254 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion 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 2 +of the License, or (at your option) any later version. + +GNU Radio Companion 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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from __future__ import absolute_import, division + +from argparse import Namespace +from math import pi + +from . import colors +from .drawable import Drawable +from .. import Utils +from ..Constants import ( + CONNECTOR_ARROW_BASE, + CONNECTOR_ARROW_HEIGHT, + GR_MESSAGE_DOMAIN, + LINE_SELECT_SENSITIVITY, +) +from ...core.Connection import Connection as CoreConnection +from ...core.Element import nop_write + + +class Connection(CoreConnection, Drawable): + """ + A graphical connection for ports. + The connection has 2 parts, the arrow and the wire. + The coloring of the arrow and wire exposes the status of 3 states: + enabled/disabled, valid/invalid, highlighted/non-highlighted. + The wire coloring exposes the enabled and highlighted states. + The arrow coloring exposes the enabled and valid states. + """ + + def __init__(self, *args, **kwargs): + super(self.__class__, self).__init__(*args, **kwargs) + Drawable.__init__(self) + + self._line = [] + self._line_width_factor = 1.0 + self._color1 = self._color2 = None + + self._current_port_rotations = self._current_coordinates = None + + self._rel_points = None # connection coordinates relative to sink/source + self._arrow_rotation = 0.0 # rotation of the arrow in radians + self._current_cr = None # for what_is_selected() of curved line + self._line_path = None + + @nop_write + @property + def coordinate(self): + return self.source_port.connector_coordinate_absolute + + @nop_write + @property + def rotation(self): + """ + Get the 0 degree rotation. + Rotations are irrelevant in connection. + + Returns: + 0 + """ + return 0 + + def create_shapes(self): + """Pre-calculate relative coordinates.""" + source = self.source_port + sink = self.sink_port + rotate = Utils.get_rotated_coordinate + + # first two components relative to source connector, rest relative to sink connector + self._rel_points = [ + rotate((15, 0), source.rotation), # line from 0,0 to here, bezier curve start + rotate((50, 0), source.rotation), # bezier curve control point 1 + rotate((-50, 0), sink.rotation), # bezier curve control point 2 + rotate((-15, 0), sink.rotation), # bezier curve end + rotate((-CONNECTOR_ARROW_HEIGHT, 0), sink.rotation), # line to arrow head + ] + self._current_coordinates = None # triggers _make_path() + + def get_domain_color(domain_name): + domain = self.parent_platform.domains.get(domain_name, {}) + color_spec = domain.get('color') + return colors.get_color(color_spec) if color_spec else colors.DEFAULT_DOMAIN_COLOR + + if source.domain == GR_MESSAGE_DOMAIN: + self._line_width_factor = 1.0 + self._color1 = None + self._color2 = colors.CONNECTION_ENABLED_COLOR + else: + if source.domain != sink.domain: + self._line_width_factor = 2.0 + self._color1 = get_domain_color(source.domain) + self._color2 = get_domain_color(sink.domain) + + self._arrow_rotation = -sink.rotation / 180 * pi + + if not self._bounding_points: + self._make_path() # no cr set --> only sets bounding_points for extent + + def _make_path(self, cr=None): + x_pos, y_pos = self.coordinate # is source connector coordinate + # x_start, y_start = self.source_port.get_connector_coordinate() + x_end, y_end = self.sink_port.connector_coordinate_absolute + + # sink connector relative to sink connector + x_e, y_e = x_end - x_pos, y_end - y_pos + + # make rel_point all relative to source connector + p0 = 0, 0 # x_start - x_pos, y_start - y_pos + p1, p2, (dx_e1, dy_e1), (dx_e2, dy_e2), (dx_e3, dy_e3) = self._rel_points + p3 = x_e + dx_e1, y_e + dy_e1 + p4 = x_e + dx_e2, y_e + dy_e2 + p5 = x_e + dx_e3, y_e + dy_e3 + self._bounding_points = p0, p1, p4, p5 # ignores curved part =( + + if cr: + cr.move_to(*p0) + cr.line_to(*p1) + cr.curve_to(*(p2 + p3 + p4)) + cr.line_to(*p5) + self._line_path = cr.copy_path() + + def draw(self, cr): + """ + Draw the connection. + """ + self._current_cr = cr + sink = self.sink_port + source = self.source_port + + # check for changes + port_rotations = (source.rotation, sink.rotation) + if self._current_port_rotations != port_rotations: + self.create_shapes() # triggers _make_path() call below + self._current_port_rotations = port_rotations + + new_coordinates = (source.parent_block.coordinate, sink.parent_block.coordinate) + if self._current_coordinates != new_coordinates: + self._make_path(cr) + self._current_coordinates = new_coordinates + + color1, color2 = ( + None if color is None else + colors.HIGHLIGHT_COLOR if self.highlighted else + colors.CONNECTION_DISABLED_COLOR if not self.enabled else + colors.CONNECTION_ERROR_COLOR if not self.is_valid() else + color + for color in (self._color1, self._color2) + ) + + cr.translate(*self.coordinate) + cr.set_line_width(self._line_width_factor * cr.get_line_width()) + cr.new_path() + cr.append_path(self._line_path) + + arrow_pos = cr.get_current_point() + + if color1: # not a message connection + cr.set_source_rgba(*color1) + cr.stroke_preserve() + + if color1 != color2: + cr.save() + cr.set_dash([5.0, 5.0], 5.0 if color1 else 0.0) + cr.set_source_rgba(*color2) + cr.stroke() + cr.restore() + else: + cr.new_path() + + cr.move_to(*arrow_pos) + cr.set_source_rgba(*color2) + cr.rotate(self._arrow_rotation) + cr.rel_move_to(CONNECTOR_ARROW_HEIGHT, 0) + cr.rel_line_to(-CONNECTOR_ARROW_HEIGHT, -CONNECTOR_ARROW_BASE/2) + cr.rel_line_to(0, CONNECTOR_ARROW_BASE) + cr.close_path() + cr.fill() + + def what_is_selected(self, coor, coor_m=None): + """ + Returns: + self if one of the areas/lines encompasses coor, else None. + """ + if coor_m: + return Drawable.what_is_selected(self, coor, coor_m) + + x, y = [a - b for a, b in zip(coor, self.coordinate)] + + cr = self._current_cr + + if cr is None: + return + cr.save() + cr.new_path() + cr.append_path(self._line_path) + cr.set_line_width(cr.get_line_width() * LINE_SELECT_SENSITIVITY) + hit = cr.in_stroke(x, y) + cr.restore() + + if hit: + return self + + +class DummyCoreConnection(object): + def __init__(self, source_port, **kwargs): + self.parent_platform = source_port.parent_platform + self.source_port = source_port + self.sink_port = self._dummy_port = Namespace( + domain=source_port.domain, + rotation=0, + coordinate=(0, 0), + connector_coordinate_absolute=(0, 0), + connector_direction=0, + parent_block=Namespace(coordinate=(0, 0)), + ) + + self.enabled = True + self.highlighted = False, + self.is_valid = lambda: True + self.update(**kwargs) + + def update(self, coordinate=None, rotation=None, sink_port=None): + dp = self._dummy_port + self.sink_port = sink_port if sink_port else dp + if coordinate: + dp.coordinate = coordinate + dp.connector_coordinate_absolute = coordinate + dp.parent_block.coordinate = coordinate + if rotation is not None: + dp.rotation = rotation + dp.connector_direction = (180 + rotation) % 360 + + @property + def has_real_sink(self): + return self.sink_port is not self._dummy_port + +DummyConnection = Connection.make_cls_with_base(DummyCoreConnection) diff --git a/grc/gui/canvas/drawable.py b/grc/gui/canvas/drawable.py new file mode 100644 index 0000000000..d755d4418d --- /dev/null +++ b/grc/gui/canvas/drawable.py @@ -0,0 +1,183 @@ +""" +Copyright 2007, 2008, 2009, 2016 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion 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 2 +of the License, or (at your option) any later version. + +GNU Radio Companion 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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from __future__ import absolute_import +from ..Constants import LINE_SELECT_SENSITIVITY + +from six.moves import zip + + +class Drawable(object): + """ + GraphicalElement is the base class for all graphical elements. + It contains an X,Y coordinate, a list of rectangular areas that the element occupies, + and methods to detect selection of those areas. + """ + + @classmethod + def make_cls_with_base(cls, super_cls): + name = super_cls.__name__ + bases = (super_cls,) + cls.__bases__[1:] + namespace = cls.__dict__.copy() + return type(name, bases, namespace) + + def __init__(self): + """ + Make a new list of rectangular areas and lines, and set the coordinate and the rotation. + """ + self.coordinate = (0, 0) + self.rotation = 0 + self.highlighted = False + + self._bounding_rects = [] + self._bounding_points = [] + + def is_horizontal(self, rotation=None): + """ + Is this element horizontal? + If rotation is None, use this element's rotation. + + Args: + rotation: the optional rotation + + Returns: + true if rotation is horizontal + """ + rotation = rotation or self.rotation + return rotation in (0, 180) + + def is_vertical(self, rotation=None): + """ + Is this element vertical? + If rotation is None, use this element's rotation. + + Args: + rotation: the optional rotation + + Returns: + true if rotation is vertical + """ + rotation = rotation or self.rotation + return rotation in (90, 270) + + def rotate(self, rotation): + """ + Rotate all of the areas by 90 degrees. + + Args: + rotation: multiple of 90 degrees + """ + self.rotation = (self.rotation + rotation) % 360 + + def move(self, delta_coor): + """ + Move the element by adding the delta_coor to the current coordinate. + + Args: + delta_coor: (delta_x,delta_y) tuple + """ + x, y = self.coordinate + dx, dy = delta_coor + self.coordinate = (x + dx, y + dy) + + def create_labels(self, cr=None): + """ + Create labels (if applicable) and call on all children. + Call this base method before creating labels in the element. + """ + + def create_shapes(self): + """ + Create shapes (if applicable) and call on all children. + Call this base method before creating shapes in the element. + """ + + def draw(self, cr): + raise NotImplementedError() + + def bounds_from_area(self, area): + x1, y1, w, h = area + x2 = x1 + w + y2 = y1 + h + self._bounding_rects = [(x1, y1, x2, y2)] + self._bounding_points = [(x1, y1), (x2, y1), (x1, y2), (x2, y2)] + + def bounds_from_line(self, line): + self._bounding_rects = rects = [] + self._bounding_points = list(line) + last_point = line[0] + for x2, y2 in line[1:]: + (x1, y1), last_point = last_point, (x2, y2) + if x1 == x2: + x1, x2 = x1 - LINE_SELECT_SENSITIVITY, x2 + LINE_SELECT_SENSITIVITY + if y2 < y1: + y1, y2 = y2, y1 + elif y1 == y2: + y1, y2 = y1 - LINE_SELECT_SENSITIVITY, y2 + LINE_SELECT_SENSITIVITY + if x2 < x1: + x1, x2 = x2, x1 + + rects.append((x1, y1, x2, y2)) + + def what_is_selected(self, coor, coor_m=None): + """ + One coordinate specified: + Is this element selected at given coordinate? + ie: is the coordinate encompassed by one of the areas or lines? + Both coordinates specified: + Is this element within the rectangular region defined by both coordinates? + ie: do any area corners or line endpoints fall within the region? + + Args: + coor: the selection coordinate, tuple x, y + coor_m: an additional selection coordinate. + + Returns: + self if one of the areas/lines encompasses coor, else None. + """ + x, y = [a - b for a, b in zip(coor, self.coordinate)] + + if not coor_m: + for x1, y1, x2, y2 in self._bounding_rects: + if x1 <= x <= x2 and y1 <= y <= y2: + return self + else: + x_m, y_m = [a - b for a, b in zip(coor_m, self.coordinate)] + if y_m < y: + y, y_m = y_m, y + if x_m < x: + x, x_m = x_m, x + + for x1, y1 in self._bounding_points: + if x <= x1 <= x_m and y <= y1 <= y_m: + return self + + def get_extents(self): + x_min, y_min = x_max, y_max = self.coordinate + x_min += min(x for x, y in self._bounding_points) + y_min += min(y for x, y in self._bounding_points) + x_max += max(x for x, y in self._bounding_points) + y_max += max(y for x, y in self._bounding_points) + return x_min, y_min, x_max, y_max + + def mouse_over(self): + pass + + def mouse_out(self): + pass diff --git a/grc/gui/FlowGraph.py b/grc/gui/canvas/flowgraph.py index 5bcf018120..14326fd3f6 100644 --- a/grc/gui/FlowGraph.py +++ b/grc/gui/canvas/flowgraph.py @@ -1,5 +1,5 @@ """ -Copyright 2007-2011 Free Software Foundation, Inc. +Copyright 2007-2011, 2016q Free Software Foundation, Inc. This file is part of GNU Radio GNU Radio Companion is free software; you can redistribute it and/or @@ -17,53 +17,58 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import + +import ast import functools import random from distutils.spawn import find_executable -from itertools import chain, count -from operator import methodcaller - -import gobject +from itertools import count -from . import Actions, Colors, Constants, Utils, Bars, Dialogs -from .Constants import SCROLL_PROXIMITY_SENSITIVITY, SCROLL_DISTANCE -from .Element import Element -from .external_editor import ExternalEditor +import six +from gi.repository import GLib +from six.moves import filter -from ..core.FlowGraph import FlowGraph as _Flowgraph -from ..core import Messages +from . import colors +from .drawable import Drawable +from .connection import DummyConnection +from .. import Actions, Constants, Utils, Bars, Dialogs +from ..external_editor import ExternalEditor +from ...core import Messages +from ...core.FlowGraph import FlowGraph as CoreFlowgraph -class FlowGraph(Element, _Flowgraph): +class FlowGraph(CoreFlowgraph, Drawable): """ FlowGraph is the data structure to store graphical signal blocks, graphical inputs and outputs, and the connections between inputs and outputs. """ - def __init__(self, **kwargs): + def __init__(self, parent, **kwargs): """ FlowGraph constructor. Create a list for signal blocks and connections. Connect mouse handlers. """ - Element.__init__(self) - _Flowgraph.__init__(self, **kwargs) - #when is the flow graph selected? (used by keyboard event handler) - self.is_selected = lambda: bool(self.get_selected_elements()) - #important vars dealing with mouse event tracking + super(self.__class__, self).__init__(parent, **kwargs) + Drawable.__init__(self) + self.drawing_area = None + # important vars dealing with mouse event tracking self.element_moved = False self.mouse_pressed = False - self._selected_elements = [] self.press_coor = (0, 0) - #selected ports + # selected + self.selected_elements = set() self._old_selected_port = None self._new_selected_port = None # current mouse hover element self.element_under_mouse = None - #context menu + # context menu self._context_menu = Bars.ContextMenu() self.get_context_menu = lambda: self._context_menu + self._new_connection = None + self._elements_to_draw = [] self._external_updaters = {} def _get_unique_id(self, base_id=''): @@ -76,21 +81,22 @@ class FlowGraph(Element, _Flowgraph): Returns: a unique id """ + block_ids = set(b.get_id() for b in self.blocks) for index in count(): block_id = '{}_{}'.format(base_id, index) - if block_id not in (b.get_id() for b in self.blocks): + if block_id not in block_ids: break return block_id def install_external_editor(self, param): - target = (param.get_parent().get_id(), param.get_key()) + target = (param.parent_block.get_id(), param.key) if target in self._external_updaters: editor = self._external_updaters[target] else: - config = self.get_parent().config + config = self.parent_platform.config editor = (find_executable(config.editor) or - Dialogs.ChooseEditorDialog(config)) + Dialogs.choose_editor(None, config)) # todo: pass in parent if not editor: return updater = functools.partial( @@ -98,7 +104,7 @@ class FlowGraph(Element, _Flowgraph): editor = self._external_updaters[target] = ExternalEditor( editor=editor, name=target[0], value=param.get_value(), - callback=functools.partial(gobject.idle_add, updater) + callback=functools.partial(GLib.idle_add, updater) ) editor.start() try: @@ -107,7 +113,7 @@ class FlowGraph(Element, _Flowgraph): # Problem launching the editor. Need to select a new editor. Messages.send('>>> Error opening an external editor. Please select a different editor.\n') # Reset the editor to force the user to select a new one. - self.get_parent().config.editor = '' + self.parent_platform.config.editor = '' def handle_external_editor_change(self, new_value, target): try: @@ -120,19 +126,6 @@ class FlowGraph(Element, _Flowgraph): return Actions.EXTERNAL_UPDATE() - - ########################################################################### - # Access Drawing Area - ########################################################################### - def get_drawing_area(self): return self.drawing_area - def queue_draw(self): self.get_drawing_area().queue_draw() - def get_size(self): return self.get_drawing_area().get_size_request() - def set_size(self, *args): self.get_drawing_area().set_size_request(*args) - def get_scroll_pane(self): return self.drawing_area.get_parent() - def get_ctrl_mask(self): return self.drawing_area.ctrl_mask - def get_mod1_mask(self): return self.drawing_area.mod1_mask - def new_pixmap(self, *args): return self.get_drawing_area().new_pixmap(*args) - def add_new_block(self, key, coor=None): """ Add a block of the given key to this flow graph. @@ -142,24 +135,65 @@ class FlowGraph(Element, _Flowgraph): coor: an optional coordinate or None for random """ id = self._get_unique_id(key) - #calculate the position coordinate - W, H = self.get_size() - h_adj = self.get_scroll_pane().get_hadjustment() - v_adj = self.get_scroll_pane().get_vadjustment() + scroll_pane = self.drawing_area.get_parent().get_parent() + # calculate the position coordinate + h_adj = scroll_pane.get_hadjustment() + v_adj = scroll_pane.get_vadjustment() if coor is None: coor = ( - int(random.uniform(.25, .75) * min(h_adj.page_size, W) + - h_adj.get_value()), - int(random.uniform(.25, .75) * min(v_adj.page_size, H) + - v_adj.get_value()), + int(random.uniform(.25, .75)*h_adj.get_page_size() + h_adj.get_value()), + int(random.uniform(.25, .75)*v_adj.get_page_size() + v_adj.get_value()), ) - #get the new block + # get the new block block = self.new_block(key) - block.set_coordinate(coor) - block.set_rotation(0) + block.coordinate = coor block.get_param('id').set_value(id) Actions.ELEMENT_CREATE() return id + def make_connection(self): + """this selection and the last were ports, try to connect them""" + if self._new_connection and self._new_connection.has_real_sink: + self._old_selected_port = self._new_connection.source_port + self._new_selected_port = self._new_connection.sink_port + if self._old_selected_port and self._new_selected_port: + try: + self.connect(self._old_selected_port, self._new_selected_port) + Actions.ELEMENT_CREATE() + except Exception as e: + Messages.send_fail_connection(e) + self._old_selected_port = None + self._new_selected_port = None + return True + return False + + def update(self): + """ + Call the top level rewrite and validate. + Call the top level create labels and shapes. + """ + self.rewrite() + self.validate() + self.update_elements_to_draw() + self.create_labels() + self.create_shapes() + + def reload(self): + """ + Reload flow-graph (with updated blocks) + + Args: + page: the page to reload (None means current) + Returns: + False if some error occurred during import + """ + success = False + data = self.export_data() + if data: + self.unselect() + success = self.import_data(data) + self.update() + return success + ########################################################################### # Copy Paste ########################################################################### @@ -171,19 +205,20 @@ class FlowGraph(Element, _Flowgraph): the clipboard """ #get selected blocks - blocks = self.get_selected_blocks() - if not blocks: return None + blocks = list(self.selected_blocks()) + if not blocks: + return None #calc x and y min - x_min, y_min = blocks[0].get_coordinate() + x_min, y_min = blocks[0].coordinate for block in blocks: - x, y = block.get_coordinate() + x, y = block.coordinate x_min = min(x, x_min) y_min = min(y, y_min) #get connections between selected blocks - connections = filter( - lambda c: c.get_source().get_parent() in blocks and c.get_sink().get_parent() in blocks, + connections = list(filter( + lambda c: c.source_block in blocks and c.sink_block in blocks, self.connections, - ) + )) clipboard = ( (x_min, y_min), [block.export_data() for block in blocks], @@ -198,32 +233,39 @@ class FlowGraph(Element, _Flowgraph): Args: clipboard: the nested data of blocks, connections """ + # todo: rewrite this... selected = set() (x_min, y_min), blocks_n, connections_n = clipboard old_id2block = dict() - #recalc the position - h_adj = self.get_scroll_pane().get_hadjustment() - v_adj = self.get_scroll_pane().get_vadjustment() - x_off = h_adj.get_value() - x_min + h_adj.page_size/4 - y_off = v_adj.get_value() - y_min + v_adj.page_size/4 + # recalc the position + scroll_pane = self.drawing_area.get_parent().get_parent() + h_adj = scroll_pane.get_hadjustment() + v_adj = scroll_pane.get_vadjustment() + x_off = h_adj.get_value() - x_min + h_adj.get_page_size() / 4 + y_off = v_adj.get_value() - y_min + v_adj.get_page_size() / 4 if len(self.get_elements()) <= 1: x_off, y_off = 0, 0 #create blocks for block_n in blocks_n: - block_key = block_n.find('key') - if block_key == 'options': continue + block_key = block_n.get('key') + if block_key == 'options': + continue block = self.new_block(block_key) if not block: continue # unknown block was pasted (e.g. dummy block) selected.add(block) #set params - params = dict((n.find('key'), n.find('value')) - for n in block_n.findall('param')) + param_data = {n['key']: n['value'] for n in block_n.get('param', [])} + for key in block.states: + try: + block.states[key] = ast.literal_eval(param_data.pop(key)) + except (KeyError, SyntaxError, ValueError): + pass if block_key == 'epy_block': - block.get_param('_io_cache').set_value(params.pop('_io_cache')) - block.get_param('_source_code').set_value(params.pop('_source_code')) + block.get_param('_io_cache').set_value(param_data.pop('_io_cache')) + block.get_param('_source_code').set_value(param_data.pop('_source_code')) block.rewrite() # this creates the other params - for param_key, param_value in params.iteritems(): + for param_key, param_value in six.iteritems(param_data): #setup id parameter if param_key == 'id': old_id2block[param_value] = block @@ -238,12 +280,13 @@ class FlowGraph(Element, _Flowgraph): self.update() #create connections for connection_n in connections_n: - source = old_id2block[connection_n.find('source_block_id')].get_source(connection_n.find('source_key')) - sink = old_id2block[connection_n.find('sink_block_id')].get_sink(connection_n.find('sink_key')) + source = old_id2block[connection_n.get('source_block_id')].get_source(connection_n.get('source_key')) + sink = old_id2block[connection_n.get('sink_block_id')].get_sink(connection_n.get('sink_key')) self.connect(source, sink) #set all pasted elements selected - for block in selected: selected = selected.union(set(block.get_connections())) - self._selected_elements = list(selected) + for block in selected: + selected = selected.union(set(block.get_connections())) + self.selected_elements = set(selected) ########################################################################### # Modify Selected @@ -258,7 +301,7 @@ class FlowGraph(Element, _Flowgraph): Returns: true for change """ - return any([sb.type_controller_modify(direction) for sb in self.get_selected_blocks()]) + return any(sb.type_controller_modify(direction) for sb in self.selected_blocks()) def port_controller_modify_selected(self, direction): """ @@ -270,35 +313,22 @@ class FlowGraph(Element, _Flowgraph): Returns: true for changed """ - return any([sb.port_controller_modify(direction) for sb in self.get_selected_blocks()]) + return any(sb.port_controller_modify(direction) for sb in self.selected_blocks()) - def enable_selected(self, enable): + def change_state_selected(self, new_state): """ Enable/disable the selected blocks. Args: - enable: true to enable + new_state: a block state Returns: true if changed """ changed = False - for selected_block in self.get_selected_blocks(): - if selected_block.set_enabled(enable): changed = True - return changed - - def bypass_selected(self): - """ - Bypass the selected blocks. - - Args: - None - Returns: - true if changed - """ - changed = False - for selected_block in self.get_selected_blocks(): - if selected_block.set_bypassed(): changed = True + for block in self.selected_blocks(): + changed |= block.state != new_state + block.state = new_state return changed def move_selected(self, delta_coordinate): @@ -308,10 +338,7 @@ class FlowGraph(Element, _Flowgraph): Args: delta_coordinate: the change in coordinates """ - for selected_block in self.get_selected_blocks(): - delta_coordinate = selected_block.bound_move_delta(delta_coordinate) - - for selected_block in self.get_selected_blocks(): + for selected_block in self.selected_blocks(): selected_block.move(delta_coordinate) self.element_moved = True @@ -325,34 +352,34 @@ class FlowGraph(Element, _Flowgraph): Returns: True if changed, otherwise False """ - blocks = self.get_selected_blocks() + blocks = list(self.selected_blocks()) if calling_action is None or not blocks: return False # compute common boundary of selected objects - min_x, min_y = max_x, max_y = blocks[0].get_coordinate() + min_x, min_y = max_x, max_y = blocks[0].coordinate for selected_block in blocks: - x, y = selected_block.get_coordinate() + x, y = selected_block.coordinate min_x, min_y = min(min_x, x), min(min_y, y) - x += selected_block.W - y += selected_block.H + x += selected_block.width + y += selected_block.height max_x, max_y = max(max_x, x), max(max_y, y) ctr_x, ctr_y = (max_x + min_x)/2, (max_y + min_y)/2 # align the blocks as requested transform = { - Actions.BLOCK_VALIGN_TOP: lambda x, y, w, h: (x, min_y), - Actions.BLOCK_VALIGN_MIDDLE: lambda x, y, w, h: (x, ctr_y - h/2), - Actions.BLOCK_VALIGN_BOTTOM: lambda x, y, w, h: (x, max_y - h), - Actions.BLOCK_HALIGN_LEFT: lambda x, y, w, h: (min_x, y), - Actions.BLOCK_HALIGN_CENTER: lambda x, y, w, h: (ctr_x-w/2, y), - Actions.BLOCK_HALIGN_RIGHT: lambda x, y, w, h: (max_x - w, y), + Actions.BLOCK_VALIGN_TOP: lambda x, y, w, h: (x, min_y), + Actions.BLOCK_VALIGN_MIDDLE: lambda x, y, w, h: (x, ctr_y - h/2), + Actions.BLOCK_VALIGN_BOTTOM: lambda x, y, w, h: (x, max_y - h), + Actions.BLOCK_HALIGN_LEFT: lambda x, y, w, h: (min_x, y), + Actions.BLOCK_HALIGN_CENTER: lambda x, y, w, h: (ctr_x-w/2, y), + Actions.BLOCK_HALIGN_RIGHT: lambda x, y, w, h: (max_x - w, y), }.get(calling_action, lambda *args: args) for selected_block in blocks: - x, y = selected_block.get_coordinate() - w, h = selected_block.W, selected_block.H - selected_block.set_coordinate(transform(x, y, w, h)) + x, y = selected_block.coordinate + w, h = selected_block.width, selected_block.height + selected_block.coordinate = transform(x, y, w, h) return True @@ -366,25 +393,24 @@ class FlowGraph(Element, _Flowgraph): Returns: true if changed, otherwise false. """ - if not self.get_selected_blocks(): + if not any(self.selected_blocks()): return False #initialize min and max coordinates - min_x, min_y = self.get_selected_block().get_coordinate() - max_x, max_y = self.get_selected_block().get_coordinate() - #rotate each selected block, and find min/max coordinate - for selected_block in self.get_selected_blocks(): + min_x, min_y = max_x, max_y = self.selected_block.coordinate + # rotate each selected block, and find min/max coordinate + for selected_block in self.selected_blocks(): selected_block.rotate(rotation) #update the min/max coordinate - x, y = selected_block.get_coordinate() + x, y = selected_block.coordinate min_x, min_y = min(min_x, x), min(min_y, y) max_x, max_y = max(max_x, x), max(max_y, y) #calculate center point of slected blocks ctr_x, ctr_y = (max_x + min_x)/2, (max_y + min_y)/2 #rotate the blocks around the center point - for selected_block in self.get_selected_blocks(): - x, y = selected_block.get_coordinate() + for selected_block in self.selected_blocks(): + x, y = selected_block.coordinate x, y = Utils.get_rotated_coordinate((x - ctr_x, y - ctr_y), rotation) - selected_block.set_coordinate((x + ctr_x, y + ctr_y)) + selected_block.coordinate = (x + ctr_x, y + ctr_y) return True def remove_selected(self): @@ -395,116 +421,149 @@ class FlowGraph(Element, _Flowgraph): true if changed. """ changed = False - for selected_element in self.get_selected_elements(): + for selected_element in self.selected_elements: self.remove_element(selected_element) changed = True return changed - def draw(self, gc, window): - """ - Draw the background and grid if enabled. - Draw all of the elements in this flow graph onto the pixmap. - Draw the pixmap to the drawable window of this flow graph. - """ - - W, H = self.get_size() - hide_disabled_blocks = Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active() - hide_variables = Actions.TOGGLE_HIDE_VARIABLES.get_active() - - #draw the background - gc.set_foreground(Colors.FLOWGRAPH_BACKGROUND_COLOR) - window.draw_rectangle(gc, True, 0, 0, W, H) - - # draw comments first - if Actions.TOGGLE_SHOW_BLOCK_COMMENTS.get_active(): - for block in self.blocks: - if hide_variables and (block.is_variable or block.is_import): - continue # skip hidden disabled blocks and connections - if block.get_enabled(): - block.draw_comment(gc, window) - #draw multi select rectangle - if self.mouse_pressed and (not self.get_selected_elements() or self.get_ctrl_mask()): - #coordinates - x1, y1 = self.press_coor - x2, y2 = self.get_coordinate() - #calculate top-left coordinate and width/height - x, y = int(min(x1, x2)), int(min(y1, y2)) - w, h = int(abs(x1 - x2)), int(abs(y1 - y2)) - #draw - gc.set_foreground(Colors.HIGHLIGHT_COLOR) - window.draw_rectangle(gc, True, x, y, w, h) - gc.set_foreground(Colors.BORDER_COLOR) - window.draw_rectangle(gc, False, x, y, w, h) - #draw blocks on top of connections - blocks = sorted(self.blocks, key=methodcaller('get_enabled')) - for element in chain(self.connections, blocks): - if hide_disabled_blocks and not element.get_enabled(): - continue # skip hidden disabled blocks and connections - if hide_variables and (element.is_variable or element.is_import): - continue # skip hidden disabled blocks and connections - element.draw(gc, window) - #draw selected blocks on top of selected connections - for selected_element in self.get_selected_connections() + self.get_selected_blocks(): - selected_element.draw(gc, window) - def update_selected(self): """ Remove deleted elements from the selected elements list. Update highlighting so only the selected are highlighted. """ - selected_elements = self.get_selected_elements() + selected_elements = self.selected_elements elements = self.get_elements() - #remove deleted elements - for selected in selected_elements: - if selected in elements: continue + # remove deleted elements + for selected in list(selected_elements): + if selected in elements: + continue selected_elements.remove(selected) - if self._old_selected_port and self._old_selected_port.get_parent() not in elements: + if self._old_selected_port and self._old_selected_port.parent not in elements: self._old_selected_port = None - if self._new_selected_port and self._new_selected_port.get_parent() not in elements: + if self._new_selected_port and self._new_selected_port.parent not in elements: self._new_selected_port = None - #update highlighting + # update highlighting for element in elements: - element.set_highlighted(element in selected_elements) + element.highlighted = element in selected_elements - def update(self): - """ - Call the top level rewrite and validate. - Call the top level create labels and shapes. - """ - self.rewrite() - self.validate() - self.create_labels() - self.create_shapes() + ########################################################################### + # Draw stuff + ########################################################################### - def reload(self): - """ - Reload flow-graph (with updated blocks) + def update_elements_to_draw(self): + hide_disabled_blocks = Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active() + hide_variables = Actions.TOGGLE_HIDE_VARIABLES.get_active() - Args: - page: the page to reload (None means current) - Returns: - False if some error occurred during import - """ - success = False - data = self.export_data() - if data: - self.unselect() - success = self.import_data(data) - self.update() - return success + def draw_order(elem): + return elem.highlighted, elem.is_block, elem.enabled + + elements = sorted(self.get_elements(), key=draw_order) + del self._elements_to_draw[:] + + for element in elements: + if hide_disabled_blocks and not element.enabled: + continue # skip hidden disabled blocks and connections + if hide_variables and (element.is_variable or element.is_import): + continue # skip hidden disabled blocks and connections + self._elements_to_draw.append(element) + + def create_labels(self, cr=None): + for element in self._elements_to_draw: + element.create_labels(cr) + + def create_shapes(self): + for element in self._elements_to_draw: + element.create_shapes() + + def _drawables(self): + # todo: cache that + show_comments = Actions.TOGGLE_SHOW_BLOCK_COMMENTS.get_active() + for element in self._elements_to_draw: + if element.is_block and show_comments and element.enabled: + yield element.draw_comment + if self._new_connection is not None: + yield self._new_connection.draw + for element in self._elements_to_draw: + yield element.draw + + def draw(self, cr): + """Draw blocks connections comment and select rectangle""" + for draw_element in self._drawables(): + cr.save() + draw_element(cr) + cr.restore() + + draw_multi_select_rectangle = ( + self.mouse_pressed and + (not self.selected_elements or self.drawing_area.ctrl_mask) and + not self._new_connection + ) + if draw_multi_select_rectangle: + x1, y1 = self.press_coor + x2, y2 = self.coordinate + x, y = int(min(x1, x2)), int(min(y1, y2)) + w, h = int(abs(x1 - x2)), int(abs(y1 - y2)) + cr.set_source_rgba( + colors.HIGHLIGHT_COLOR[0], + colors.HIGHLIGHT_COLOR[1], + colors.HIGHLIGHT_COLOR[2], + 0.5, + ) + cr.rectangle(x, y, w, h) + cr.fill() + cr.rectangle(x, y, w, h) + cr.stroke() ########################################################################## - ## Get Selected + # selection handling ########################################################################## - def unselect(self): + def update_selected_elements(self): """ - Set selected elements to an empty set. + Update the selected elements. + The update behavior depends on the state of the mouse button. + When the mouse button pressed the selection will change when + the control mask is set or the new selection is not in the current group. + When the mouse button is released the selection will change when + the mouse has moved and the control mask is set or the current group is empty. + Attempt to make a new connection if the old and ports are filled. + If the control mask is set, merge with the current elements. """ - self._selected_elements = [] + selected_elements = None + if self.mouse_pressed: + new_selections = self.what_is_selected(self.coordinate) + # update the selections if the new selection is not in the current selections + # allows us to move entire selected groups of elements + if not new_selections: + selected_elements = set() + elif self.drawing_area.ctrl_mask or self.selected_elements.isdisjoint(new_selections): + selected_elements = new_selections - def select_all(self): - """Select all blocks in the flow graph""" - self._selected_elements = list(self.get_elements()) + if self._old_selected_port: + self._old_selected_port.force_show_label = False + self.create_shapes() + self.drawing_area.queue_draw() + elif self._new_selected_port: + self._new_selected_port.force_show_label = True + + else: # called from a mouse release + if not self.element_moved and (not self.selected_elements or self.drawing_area.ctrl_mask) and not self._new_connection: + selected_elements = self.what_is_selected(self.coordinate, self.press_coor) + + # this selection and the last were ports, try to connect them + if self.make_connection(): + return + + # update selected elements + if selected_elements is None: + return + + # if ctrl, set the selected elements to the union - intersection of old and new + if self.drawing_area.ctrl_mask: + self.selected_elements ^= selected_elements + else: + self.selected_elements.clear() + self.selected_elements.update(selected_elements) + Actions.ELEMENT_SELECT() def what_is_selected(self, coor, coor_m=None): """ @@ -524,68 +583,60 @@ class FlowGraph(Element, _Flowgraph): """ selected_port = None selected = set() - #check the elements - hide_disabled_blocks = Actions.TOGGLE_HIDE_DISABLED_BLOCKS.get_active() - hide_variables = Actions.TOGGLE_HIDE_VARIABLES.get_active() - for element in reversed(self.get_elements()): - if hide_disabled_blocks and not element.get_enabled(): - continue # skip hidden disabled blocks and connections - if hide_variables and (element.is_variable or element.is_import): - continue # skip hidden disabled blocks and connections + # check the elements + for element in reversed(self._elements_to_draw): selected_element = element.what_is_selected(coor, coor_m) if not selected_element: continue - #update the selected port information + # update the selected port information if selected_element.is_port: - if not coor_m: selected_port = selected_element - selected_element = selected_element.get_parent() + if not coor_m: + selected_port = selected_element + selected_element = selected_element.parent_block + selected.add(selected_element) - #place at the end of the list - self.get_elements().remove(element) - self.get_elements().append(element) - #single select mode, break - if not coor_m: break - #update selected ports + if not coor_m: + break + + if selected_port and selected_port.is_source: + selected.remove(selected_port.parent_block) + self._new_connection = DummyConnection(selected_port, coordinate=coor) + self.drawing_area.queue_draw() + # update selected ports if selected_port is not self._new_selected_port: self._old_selected_port = self._new_selected_port self._new_selected_port = selected_port - return list(selected) + return selected - def get_selected_connections(self): + def unselect(self): """ - Get a group of selected connections. - - Returns: - sub set of connections in this flow graph + Set selected elements to an empty set. """ - selected = set() - for selected_element in self.get_selected_elements(): - if selected_element.is_connection: - selected.add(selected_element) - return list(selected) + self.selected_elements.clear() + + def select_all(self): + """Select all blocks in the flow graph""" + self.selected_elements.clear() + self.selected_elements.update(self._elements_to_draw) - def get_selected_blocks(self): + def selected_blocks(self): """ Get a group of selected blocks. Returns: sub set of blocks in this flow graph """ - selected = set() - for selected_element in self.get_selected_elements(): - if selected_element.is_block: - selected.add(selected_element) - return list(selected) + return (e for e in self.selected_elements if e.is_block) - def get_selected_block(self): + @property + def selected_block(self): """ Get the selected block when a block or port is selected. Returns: a block or None """ - selected_blocks = self.get_selected_blocks() - return selected_blocks[0] if selected_blocks else None + return next(self.selected_blocks(), None) def get_selected_elements(self): """ @@ -594,7 +645,7 @@ class FlowGraph(Element, _Flowgraph): Returns: sub set of elements in this flow graph """ - return self._selected_elements + return self.selected_elements def get_selected_element(self): """ @@ -603,60 +654,10 @@ class FlowGraph(Element, _Flowgraph): Returns: a block, port, or connection or None """ - selected_elements = self.get_selected_elements() - return selected_elements[0] if selected_elements else None - - def update_selected_elements(self): - """ - Update the selected elements. - The update behavior depends on the state of the mouse button. - When the mouse button pressed the selection will change when - the control mask is set or the new selection is not in the current group. - When the mouse button is released the selection will change when - the mouse has moved and the control mask is set or the current group is empty. - Attempt to make a new connection if the old and ports are filled. - If the control mask is set, merge with the current elements. - """ - selected_elements = None - if self.mouse_pressed: - new_selections = self.what_is_selected(self.get_coordinate()) - #update the selections if the new selection is not in the current selections - #allows us to move entire selected groups of elements - if self.get_ctrl_mask() or not ( - new_selections and new_selections[0] in self.get_selected_elements() - ): selected_elements = new_selections - if self._old_selected_port: - self._old_selected_port.force_label_unhidden(False) - self.create_shapes() - self.queue_draw() - elif self._new_selected_port: - self._new_selected_port.force_label_unhidden() - else: # called from a mouse release - if not self.element_moved and (not self.get_selected_elements() or self.get_ctrl_mask()): - selected_elements = self.what_is_selected(self.get_coordinate(), self.press_coor) - #this selection and the last were ports, try to connect them - if self._old_selected_port and self._new_selected_port: - try: - self.connect(self._old_selected_port, self._new_selected_port) - Actions.ELEMENT_CREATE() - except: Messages.send_fail_connection() - self._old_selected_port = None - self._new_selected_port = None - return - #update selected elements - if selected_elements is None: return - old_elements = set(self.get_selected_elements()) - self._selected_elements = list(set(selected_elements)) - new_elements = set(self.get_selected_elements()) - #if ctrl, set the selected elements to the union - intersection of old and new - if self.get_ctrl_mask(): - self._selected_elements = list( - set.union(old_elements, new_elements) - set.intersection(old_elements, new_elements) - ) - Actions.ELEMENT_SELECT() + return next(iter(self.selected_elements), None) ########################################################################## - ## Event Handlers + # Event Handlers ########################################################################## def handle_mouse_context_press(self, coordinate, event): """ @@ -665,12 +666,15 @@ class FlowGraph(Element, _Flowgraph): Then, show the context menu at the mouse click location. """ selections = self.what_is_selected(coordinate) - if not set(selections).intersection(self.get_selected_elements()): - self.set_coordinate(coordinate) + if not selections.intersection(self.selected_elements): + self.coordinate = coordinate self.mouse_pressed = True self.update_selected_elements() self.mouse_pressed = False - self._context_menu.popup(None, None, None, event.button, event.time) + if self._new_connection: + self._new_connection = None + self.drawing_area.queue_draw() + self._context_menu.popup(None, None, None, None, event.button, event.time) def handle_mouse_selector_press(self, double_click, coordinate): """ @@ -680,13 +684,13 @@ class FlowGraph(Element, _Flowgraph): Update the selection state of the flow graph. """ self.press_coor = coordinate - self.set_coordinate(coordinate) - self.time = 0 + self.coordinate = coordinate self.mouse_pressed = True - if double_click: self.unselect() + if double_click: + self.unselect() self.update_selected_elements() - #double click detected, bring up params dialog if possible - if double_click and self.get_selected_block(): + + if double_click and self.selected_block: self.mouse_pressed = False Actions.BLOCK_PARAM_MODIFY() @@ -696,13 +700,15 @@ class FlowGraph(Element, _Flowgraph): Update the state, handle motion (dragging). And update the selected flowgraph elements. """ - self.set_coordinate(coordinate) - self.time = 0 + self.coordinate = coordinate self.mouse_pressed = False if self.element_moved: Actions.BLOCK_MOVE() self.element_moved = False self.update_selected_elements() + if self._new_connection: + self._new_connection = None + self.drawing_area.queue_draw() def handle_mouse_motion(self, coordinate): """ @@ -710,56 +716,70 @@ class FlowGraph(Element, _Flowgraph): Move a selected element to the new coordinate. Auto-scroll the scroll bars at the boundaries. """ - #to perform a movement, the mouse must be pressed - # (no longer checking pending events via gtk.events_pending() - always true in Windows) - if not self.mouse_pressed: - # only continue if mouse-over stuff is enabled (just the auto-hide port label stuff for now) - if not Actions.TOGGLE_AUTO_HIDE_PORT_LABELS.get_active(): return - redraw = False - for element in reversed(self.get_elements()): - over_element = element.what_is_selected(coordinate) - if not over_element: continue - if over_element != self.element_under_mouse: # over sth new - if self.element_under_mouse: - redraw |= self.element_under_mouse.mouse_out() or False - self.element_under_mouse = over_element - redraw |= over_element.mouse_over() or False - break - else: + # to perform a movement, the mouse must be pressed + # (no longer checking pending events via Gtk.events_pending() - always true in Windows) + redraw = False + if not self.mouse_pressed or self._new_connection: + redraw = self._handle_mouse_motion_move(coordinate) + if self.mouse_pressed: + redraw = redraw or self._handle_mouse_motion_drag(coordinate) + if redraw: + self.drawing_area.queue_draw() + + def _handle_mouse_motion_move(self, coordinate): + # only continue if mouse-over stuff is enabled (just the auto-hide port label stuff for now) + if not Actions.TOGGLE_AUTO_HIDE_PORT_LABELS.get_active(): + return + redraw = False + for element in self._elements_to_draw: + over_element = element.what_is_selected(coordinate) + if not over_element: + continue + if over_element != self.element_under_mouse: # over sth new if self.element_under_mouse: redraw |= self.element_under_mouse.mouse_out() or False - self.element_under_mouse = None - if redraw: - #self.create_labels() - self.create_shapes() - self.queue_draw() + self.element_under_mouse = over_element + redraw |= over_element.mouse_over() or False + break else: - #perform auto-scrolling - width, height = self.get_size() - x, y = coordinate - h_adj = self.get_scroll_pane().get_hadjustment() - v_adj = self.get_scroll_pane().get_vadjustment() - for pos, length, adj, adj_val, adj_len in ( - (x, width, h_adj, h_adj.get_value(), h_adj.page_size), - (y, height, v_adj, v_adj.get_value(), v_adj.page_size), - ): - #scroll if we moved near the border - if pos-adj_val > adj_len-SCROLL_PROXIMITY_SENSITIVITY and adj_val+SCROLL_DISTANCE < length-adj_len: - adj.set_value(adj_val+SCROLL_DISTANCE) - adj.emit('changed') - elif pos-adj_val < SCROLL_PROXIMITY_SENSITIVITY: - adj.set_value(adj_val-SCROLL_DISTANCE) - adj.emit('changed') - #remove the connection if selected in drag event - if len(self.get_selected_elements()) == 1 and self.get_selected_element().is_connection: - Actions.ELEMENT_DELETE() - #move the selected elements and record the new coordinate - if not self.get_ctrl_mask(): - X, Y = self.get_coordinate() - dX, dY = int(x - X), int(y - Y) - active = Actions.TOGGLE_SNAP_TO_GRID.get_active() or self.get_mod1_mask() - if not active or abs(dX) >= Utils.CANVAS_GRID_SIZE or abs(dY) >= Utils.CANVAS_GRID_SIZE: - self.move_selected((dX, dY)) - self.set_coordinate((x, y)) - #queue draw for animation - self.queue_draw() + if self.element_under_mouse: + redraw |= self.element_under_mouse.mouse_out() or False + self.element_under_mouse = None + if redraw: + # self.create_labels() + self.create_shapes() + return redraw + + def _handle_mouse_motion_drag(self, coordinate): + redraw = False + # remove the connection if selected in drag event + if len(self.selected_elements) == 1 and self.get_selected_element().is_connection: + Actions.ELEMENT_DELETE() + redraw = True + + if self._new_connection: + e = self.element_under_mouse + if e and e.is_port and e.is_sink: + self._new_connection.update(sink_port=self.element_under_mouse) + else: + self._new_connection.update(coordinate=coordinate, rotation=0) + return True + # move the selected elements and record the new coordinate + x, y = coordinate + if not self.drawing_area.ctrl_mask: + X, Y = self.coordinate + dX, dY = int(x - X), int(y - Y) + active = Actions.TOGGLE_SNAP_TO_GRID.get_active() or self.drawing_area.mod1_mask + if not active or abs(dX) >= Constants.CANVAS_GRID_SIZE or abs(dY) >= Constants.CANVAS_GRID_SIZE: + self.move_selected((dX, dY)) + self.coordinate = (x, y) + redraw = True + return redraw + + def get_extents(self): + extent = 100000, 100000, 0, 0 + for element in self._elements_to_draw: + extent = (min_or_max(xy, e_xy) for min_or_max, xy, e_xy in zip( + (min, min, max, max), extent, element.get_extents() + )) + return tuple(extent) diff --git a/grc/gui/canvas/param.py b/grc/gui/canvas/param.py new file mode 100644 index 0000000000..b027b7653a --- /dev/null +++ b/grc/gui/canvas/param.py @@ -0,0 +1,162 @@ +# Copyright 2007-2016 Free Software Foundation, Inc. +# This file is part of GNU Radio +# +# GNU Radio Companion 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 2 +# of the License, or (at your option) any later version. +# +# GNU Radio Companion 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +from __future__ import absolute_import + +from .drawable import Drawable + +from .. import ParamWidgets, Utils, Constants + +from ...core.Param import Param as CoreParam + + +class Param(CoreParam): + """The graphical parameter.""" + + make_cls_with_base = classmethod(Drawable.make_cls_with_base.__func__) + + def get_input(self, *args, **kwargs): + """ + Get the graphical gtk class to represent this parameter. + An enum requires and combo parameter. + A non-enum with options gets a combined entry/combo parameter. + All others get a standard entry parameter. + + Returns: + gtk input class + """ + type_ = self.get_type() + if type_ in ('file_open', 'file_save'): + input_widget_cls = ParamWidgets.FileParam + + elif self.is_enum(): + input_widget_cls = ParamWidgets.EnumParam + + elif self.options: + input_widget_cls = ParamWidgets.EnumEntryParam + + elif type_ == '_multiline': + input_widget_cls = ParamWidgets.MultiLineEntryParam + + elif type_ == '_multiline_python_external': + input_widget_cls = ParamWidgets.PythonEditorParam + + else: + input_widget_cls = ParamWidgets.EntryParam + + return input_widget_cls(self, *args, **kwargs) + + def format_label_markup(self, have_pending_changes=False): + block = self.parent + # fixme: using non-public attribute here + has_callback = \ + hasattr(block, 'get_callbacks') and \ + any(self.key in callback for callback in block._callbacks) + + return '<span {underline} {foreground} font_desc="Sans 9">{label}</span>'.format( + underline='underline="low"' if has_callback else '', + foreground='foreground="blue"' if have_pending_changes else + 'foreground="red"' if not self.is_valid() else '', + label=Utils.encode(self.name) + ) + + def format_tooltip_text(self): + errors = self.get_error_messages() + tooltip_lines = ['Key: ' + self.key, 'Type: ' + self.get_type()] + if self.is_valid(): + value = str(self.get_evaluated()) + if len(value) > 100: + value = '{}...{}'.format(value[:50], value[-50:]) + tooltip_lines.append('Value: ' + value) + elif len(errors) == 1: + tooltip_lines.append('Error: ' + errors[0]) + elif len(errors) > 1: + tooltip_lines.append('Error:') + tooltip_lines.extend(' * ' + msg for msg in errors) + return '\n'.join(tooltip_lines) + + def pretty_print(self): + """ + Get the repr (nice string format) for this param. + + Returns: + the string representation + """ + ################################################## + # Truncate helper method + ################################################## + def _truncate(string, style=0): + max_len = max(27 - len(self.name), 3) + if len(string) > max_len: + if style < 0: # Front truncate + string = '...' + string[3-max_len:] + elif style == 0: # Center truncate + string = string[:max_len//2 - 3] + '...' + string[-max_len//2:] + elif style > 0: # Rear truncate + string = string[:max_len-3] + '...' + return string + + ################################################## + # Simple conditions + ################################################## + value = self.get_value() + if not self.is_valid(): + return _truncate(value) + if value in self.options: + return self.options_names[self.options.index(value)] + + ################################################## + # Split up formatting by type + ################################################## + # Default center truncate + truncate = 0 + e = self.get_evaluated() + t = self.get_type() + if isinstance(e, bool): + return str(e) + elif isinstance(e, Constants.COMPLEX_TYPES): + dt_str = Utils.num_to_str(e) + elif isinstance(e, Constants.VECTOR_TYPES): + # Vector types + if len(e) > 8: + # Large vectors use code + dt_str = self.get_value() + truncate = 1 + else: + # Small vectors use eval + dt_str = ', '.join(map(Utils.num_to_str, e)) + elif t in ('file_open', 'file_save'): + dt_str = self.get_value() + truncate = -1 + else: + # Other types + dt_str = str(e) + + # Done + return _truncate(dt_str, truncate) + + def format_block_surface_markup(self): + """ + Get the markup for this param. + + Returns: + a pango markup string + """ + return '<span {foreground} font_desc="{font}"><b>{label}:</b> {value}</span>'.format( + foreground='foreground="red"' if not self.is_valid() else '', font=Constants.PARAM_FONT, + label=Utils.encode(self.name), value=Utils.encode(self.pretty_print().replace('\n', ' ')) + ) diff --git a/grc/gui/canvas/port.py b/grc/gui/canvas/port.py new file mode 100644 index 0000000000..b74e4adfcc --- /dev/null +++ b/grc/gui/canvas/port.py @@ -0,0 +1,225 @@ +""" +Copyright 2007, 2008, 2009 Free Software Foundation, Inc. +This file is part of GNU Radio + +GNU Radio Companion 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 2 +of the License, or (at your option) any later version. + +GNU Radio Companion 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 this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +""" + +from __future__ import absolute_import, division + +import math + +from gi.repository import Gtk, PangoCairo, Pango + +from . import colors +from .drawable import Drawable +from .. import Actions, Utils, Constants +from ...core.Element import nop_write +from ...core.Port import Port as CorePort + + +class Port(CorePort, Drawable): + """The graphical port.""" + + def __init__(self, parent, direction, **n): + """ + Port constructor. + Create list of connector coordinates. + """ + super(self.__class__, self).__init__(parent, direction, **n) + Drawable.__init__(self) + self._connector_coordinate = (0, 0) + self._hovering = False + self.force_show_label = False + + self._area = [] + self._bg_color = self._border_color = 0, 0, 0, 0 + self._font_color = list(colors.FONT_COLOR) + + self._line_width_factor = 1.0 + self._label_layout_offsets = 0, 0 + + self.width_with_label = self.height = 0 + + self.label_layout = None + + @property + def width(self): + return self.width_with_label if self._show_label else Constants.PORT_LABEL_HIDDEN_WIDTH + + @width.setter + def width(self, value): + self.width_with_label = value + self.label_layout.set_width(value * Pango.SCALE) + + def _update_colors(self): + """ + Get the color that represents this port's type. + Codes differ for ports where the vec length is 1 or greater than 1. + + Returns: + a hex color code. + """ + if not self.parent_block.enabled: + self._font_color[-1] = 0.4 + color = colors.BLOCK_DISABLED_COLOR + else: + self._font_color[-1] = 1.0 + color = colors.PORT_TYPE_TO_COLOR.get(self.get_type()) or colors.PORT_TYPE_TO_COLOR.get('') + vlen = self.get_vlen() + if vlen > 1: + dark = (0, 0, 30 / 255.0, 50 / 255.0, 70 / 255.0)[min(4, vlen)] + color = tuple(max(c - dark, 0) for c in color) + self._bg_color = color + self._border_color = tuple(max(c - 0.3, 0) for c in color) + + def create_shapes(self): + """Create new areas and labels for the port.""" + if self.is_horizontal(): + self._area = (0, 0, self.width, self.height) + elif self.is_vertical(): + self._area = (0, 0, self.height, self.width) + self.bounds_from_area(self._area) + + self._connector_coordinate = { + 0: (self.width, self.height / 2), + 90: (self.height / 2, 0), + 180: (0, self.height / 2), + 270: (self.height / 2, self.width) + }[self.connector_direction] + + def create_labels(self, cr=None): + """Create the labels for the socket.""" + self.label_layout = Gtk.DrawingArea().create_pango_layout('') + self.label_layout.set_alignment(Pango.Alignment.CENTER) + + if cr: + PangoCairo.update_layout(cr, self.label_layout) + + if self.domain in (Constants.GR_MESSAGE_DOMAIN, Constants.DEFAULT_DOMAIN): + self._line_width_factor = 1.0 + else: + self._line_width_factor = 2.0 + + self._update_colors() + + layout = self.label_layout + layout.set_markup('<span font_desc="{font}">{name}</span>'.format( + name=Utils.encode(self.name), font=Constants.PORT_FONT + )) + label_width, label_height = self.label_layout.get_size() + + self.width = 2 * Constants.PORT_LABEL_PADDING + label_width / Pango.SCALE + self.height = 2 * Constants.PORT_LABEL_PADDING + label_height / Pango.SCALE + self._label_layout_offsets = [0, Constants.PORT_LABEL_PADDING] + if self.get_type() == 'bus': + self.height += Constants.PORT_EXTRA_BUS_HEIGHT + self._label_layout_offsets[1] += Constants.PORT_EXTRA_BUS_HEIGHT / 2 + self.height += self.height % 2 # uneven height + + def draw(self, cr): + """ + Draw the socket with a label. + """ + border_color = self._border_color + cr.set_line_width(self._line_width_factor * cr.get_line_width()) + cr.translate(*self.coordinate) + + cr.rectangle(*self._area) + cr.set_source_rgba(*self._bg_color) + cr.fill_preserve() + cr.set_source_rgba(*border_color) + cr.stroke() + + if not self._show_label: + return # this port is folded (no label) + + if self.is_vertical(): + cr.rotate(-math.pi / 2) + cr.translate(-self.width, 0) + cr.translate(*self._label_layout_offsets) + + cr.set_source_rgba(*self._font_color) + PangoCairo.update_layout(cr, self.label_layout) + PangoCairo.show_layout(cr, self.label_layout) + + @property + def connector_coordinate_absolute(self): + """the coordinate where connections may attach to""" + return [sum(c) for c in zip( + self._connector_coordinate, # relative to port + self.coordinate, # relative to block + self.parent_block.coordinate # abs + )] + + @property + def connector_direction(self): + """Get the direction that the socket points: 0,90,180,270.""" + if self.is_source: + return self.rotation + elif self.is_sink: + return (self.rotation + 180) % 360 + + @nop_write + @property + def rotation(self): + return self.parent_block.rotation + + def rotate(self, direction): + """ + Rotate the parent rather than self. + + Args: + direction: degrees to rotate + """ + self.parent_block.rotate(direction) + + def move(self, delta_coor): + """Move the parent rather than self.""" + self.parent_block.move(delta_coor) + + @property + def highlighted(self): + return self.parent_block.highlighted + + @highlighted.setter + def highlighted(self, value): + self.parent_block.highlighted = value + + @property + def _show_label(self): + """ + Figure out if the label should be hidden + + Returns: + true if the label should not be shown + """ + return self._hovering or self.force_show_label or not Actions.TOGGLE_AUTO_HIDE_PORT_LABELS.get_active() + + def mouse_over(self): + """ + Called from flow graph on mouse-over + """ + changed = not self._show_label + self._hovering = True + return changed + + def mouse_out(self): + """ + Called from flow graph on mouse-out + """ + label_was_shown = self._show_label + self._hovering = False + return label_was_shown != self._show_label diff --git a/grc/gui/external_editor.py b/grc/gui/external_editor.py index 010bd71d1a..155b0915c5 100644 --- a/grc/gui/external_editor.py +++ b/grc/gui/external_editor.py @@ -17,6 +17,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA """ +from __future__ import absolute_import, print_function + import os import sys import time @@ -67,7 +69,7 @@ class ExternalEditor(threading.Thread): time.sleep(1) except Exception as e: - print >> sys.stderr, "file monitor crashed:", str(e) + print("file monitor crashed:", str(e), file=sys.stderr) finally: try: os.remove(self.filename) @@ -76,10 +78,7 @@ class ExternalEditor(threading.Thread): if __name__ == '__main__': - def p(data): - print data - - e = ExternalEditor('/usr/bin/gedit', "test", "content", p) + e = ExternalEditor('/usr/bin/gedit', "test", "content", print) e.open_editor() e.start() time.sleep(15) diff --git a/grc/main.py b/grc/main.py index 0edab40769..4d04608269 100755 --- a/grc/main.py +++ b/grc/main.py @@ -15,13 +15,12 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -import argparse +import argparse, logging, sys -import gtk -from gnuradio import gr - -from .gui.Platform import Platform -from .gui.ActionHandler import ActionHandler +import gi +gi.require_version('Gtk', '3.0') +gi.require_version('PangoCairo', '1.0') +from gi.repository import Gtk VERSION_AND_DISCLAIMER_TEMPLATE = """\ @@ -32,24 +31,61 @@ GRC comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it. """ +LOG_LEVELS = { + 'debug': logging.DEBUG, + 'info': logging.INFO, + 'warning': logging.WARNING, + 'error': logging.ERROR, + 'critical': logging.CRITICAL, +} + def main(): + from gnuradio import gr parser = argparse.ArgumentParser( description=VERSION_AND_DISCLAIMER_TEMPLATE % gr.version()) parser.add_argument('flow_graphs', nargs='*') + parser.add_argument('--log', choices=['debug', 'info', 'warning', 'error', 'critical'], default='warning') args = parser.parse_args() try: - gtk.window_set_default_icon(gtk.IconTheme().load_icon('gnuradio-grc', 256, 0)) + Gtk.window_set_default_icon(Gtk.IconTheme().load_icon('gnuradio-grc', 256, 0)) except: pass + # Enable logging + # Note: All other modules need to use the 'grc.<module>' convention + log = logging.getLogger('grc') + log.setLevel(logging.DEBUG) + + # Console formatting + console = logging.StreamHandler() + console.setLevel(LOG_LEVELS[args.log]) + + #msg_format = '[%(asctime)s - %(levelname)8s] --- %(message)s (%(filename)s:%(lineno)s)' + msg_format = '[%(levelname)s] %(message)s (%(filename)s:%(lineno)s)' + date_format = '%I:%M' + formatter = logging.Formatter(msg_format, datefmt=date_format) + + #formatter = utils.log.ConsoleFormatter() + console.setFormatter(formatter) + log.addHandler(console) + + log.debug("Running main") + + # Delay importing until the logging is setup + from .gui.Platform import Platform + from .gui.Application import Application + + log.debug("Loading platform") platform = Platform( - prefs_file=gr.prefs(), version=gr.version(), version_parts=(gr.major_version(), gr.api_version(), gr.minor_version()), + prefs=gr.prefs(), install_prefix=gr.prefix() ) - ActionHandler(args.flow_graphs, platform) - gtk.main() + log.debug("Loading application") + app = Application(args.flow_graphs, platform) + log.debug("Running") + sys.exit(app.run()) diff --git a/grc/scripts/gnuradio-companion b/grc/scripts/gnuradio-companion index bacbbe2334..de776f22a7 100755 --- a/grc/scripts/gnuradio-companion +++ b/grc/scripts/gnuradio-companion @@ -37,11 +37,13 @@ Is the library path environment variable set correctly? def die(error, message): msg = "{0}\n\n({1})".format(message, error) try: - import gtk - d = gtk.MessageDialog( - type=gtk.MESSAGE_ERROR, - buttons=gtk.BUTTONS_CLOSE, - message_format=msg, + import gi + gi.require_version('Gtk', '3.0') + from gi.repository import Gtk + d = Gtk.MessageDialog( + message_type=Gtk.MessageType.ERROR, + buttons=Gtk.ButtonsType.CLOSE, + text=msg, ) d.set_title(type(error).__name__) d.run() @@ -53,10 +55,13 @@ def die(error, message): def check_gtk(): try: warnings.filterwarnings("error") - import pygtk - pygtk.require('2.0') - import gtk - gtk.init_check() + import gi + gi.require_version('Gtk', '3.0') + gi.require_version('PangoCairo', '1.0') + gi.require_foreign('cairo', 'Context') + + from gi.repository import Gtk + Gtk.init_check() warnings.filterwarnings("always") except Exception as err: die(err, "Failed to initialize GTK. If you are running over ssh, " @@ -76,6 +81,11 @@ def check_blocks_path(): "Can't find block definitions. Use config.conf or GRC_BLOCKS_PATH.") +def check_python_version(): + if sys.version_info.major > 2: + die(RuntimeError('No python3 support yet.'), 'Stay tuned...') + + def run_main(): script_path = os.path.dirname(os.path.abspath(__file__)) source_tree_subpath = "/grc/scripts" @@ -93,5 +103,6 @@ def run_main(): if __name__ == '__main__': check_gnuradio_import() check_gtk() + check_python_version() check_blocks_path() run_main() diff --git a/volk b/volk -Subproject 4465f9b26354e555e583a7d654710cb63cf914c +Subproject 018498173344ccc10c6911a828c56136e523b14 |