diff --git a/shinysdr/i/config.py b/shinysdr/i/config.py index fe4decb1..597efdbd 100755 --- a/shinysdr/i/config.py +++ b/shinysdr/i/config.py @@ -41,7 +41,7 @@ # Note that gnuradio-dependent modules are loaded lazily, to avoid the startup time if all we're going to do is give a usage message from shinysdr.i.db import DatabaseModel, database_from_csv, databases_from_directory from shinysdr.i.network.base import UNIQUE_PUBLIC_CAP -from shinysdr.i.pycompat import bytes_or_ascii, repr_no_string_tag +from shinysdr.i.pycompat import repr_no_string_tag from shinysdr.i.roots import CapTable, generate_cap @@ -127,8 +127,8 @@ def serve_web(self, self._not_finished() # TODO: See if we're reinventing bits of Twisted service stuff here - http_base_url = _coerce_and_validate_base_url(http_base_url, 'http_base_url', ('http', 'https')) - ws_base_url = _coerce_and_validate_base_url(ws_base_url, 'ws_base_url', ('ws', 'wss'), allow_path=True) + http_base_url = _coerce_and_validate_base_url(http_base_url, 'http_base_url', (b'http', b'https')) + ws_base_url = _coerce_and_validate_base_url(ws_base_url, 'ws_base_url', (b'ws', b'wss'), allow_path=True) if root_cap is not None: root_cap = six.text_type(root_cap) @@ -198,11 +198,11 @@ def _coerce_and_validate_base_url(url_value, label, allowed_schemes, allow_path= if url_value is not None: url_value = str(url_value) - scheme, _netloc, path_bytes, _params, _query_bytes, _fragment = urlparse(bytes_or_ascii(url_value)) + scheme, _netloc, path_bytes, _params, _query_bytes, _fragment = urlparse(six.ensure_binary(url_value)) # Ensure that the protocol is compatible. if scheme.lower() not in allowed_schemes: - raise ConfigException('config.serve_web: {} must be a {} URL but was {}'.format(label, ' or '.join(repr_no_string_tag(s + ':') for s in allowed_schemes), repr_no_string_tag(url_value))) + raise ConfigException('config.serve_web: {} must be a {} URL but was {}'.format(label, ' or '.join(repr_no_string_tag(six.ensure_str(s) + ':') for s in allowed_schemes), repr_no_string_tag(url_value))) # Ensure that there are no path components. There are two reasons for this: # 1. The client makes use of host-relative URLs. diff --git a/shinysdr/i/db.py b/shinysdr/i/db.py index 21f364f1..63510a84 100644 --- a/shinysdr/i/db.py +++ b/shinysdr/i/db.py @@ -207,11 +207,11 @@ def render_POST(self, request): dbdict[rkey] = record self.__database.dirty() # TODO: There is no test that this is done. self.__instantiate(rkey) - url = request.prePathURL() + str(rkey) + url = request.prePathURL() + six.ensure_binary(str(rkey)) request.setResponseCode(http.CREATED) request.setHeader(b'Content-Type', b'text/plain') request.setHeader(b'Location', url) - return url.encode() + return url class _RecordResource(resource.Resource): diff --git a/shinysdr/i/depgraph.py b/shinysdr/i/depgraph.py index 7d727948..ddc5b9a8 100644 --- a/shinysdr/i/depgraph.py +++ b/shinysdr/i/depgraph.py @@ -20,6 +20,8 @@ from __future__ import absolute_import, division, print_function, unicode_literals +import six + from twisted.internet import defer from twisted.internet.task import deferLater from twisted.logger import Logger @@ -115,7 +117,7 @@ def get_fitting(self, other_ff, requester_ff=None): def _schedule_change(self, reason): """Internal for _ActiveFittingHolder -- asynchronously trigger a reevaluation of the graph""" - self.__log.debug('scheduled change ({reason})', reason=unicode(reason)) + self.__log.debug('scheduled change ({reason})', reason=six.ensure_text(reason)) self.__scheduled_change.start() def _mark_for_rebuild(self, fitting_factory): @@ -153,7 +155,7 @@ def add_factory(ff, reason): self.__log.debug('CHANGE: ...completed analysis') - newly_inactive_ffs = (set(self.__active_holders.iterkeys()) + newly_inactive_ffs = (set(self.__active_holders.keys()) .difference(active_ffs) .union(self.__do_not_reuse)) needs_configuration = newly_active_ffs or newly_inactive_ffs diff --git a/shinysdr/i/network/export_http.py b/shinysdr/i/network/export_http.py index 7660cbcf..9ceab6a8 100644 --- a/shinysdr/i/network/export_http.py +++ b/shinysdr/i/network/export_http.py @@ -204,7 +204,7 @@ def render_GET(self, request): 1: 'r', 2: 2 }) - process.pipes[0].write(self.__block.dot_graph()) + process.pipes[0].write(self.__block.dot_graph().encode('utf-8')) process.pipes[0].loseConnection() return NOT_DONE_YET diff --git a/shinysdr/i/test_config.py b/shinysdr/i/test_config.py index 43370595..0c6f7abb 100644 --- a/shinysdr/i/test_config.py +++ b/shinysdr/i/test_config.py @@ -354,7 +354,8 @@ def test_traceback_processing(self): self.assertEqual( file_obj.getvalue() .replace(self.__files.dir, '') - .replace(__file__, ''), + .replace(__file__, '') + .replace('shinysdr.i.config.ConfigException', 'ConfigException'), # Python 3 uses the full name textwrap.dedent("""\ An error occurred while executing the ShinySDR configuration file: File "/config", line 1, in diff --git a/shinysdr/i/test_db.py b/shinysdr/i/test_db.py index a2b2264e..10c61fb5 100644 --- a/shinysdr/i/test_db.py +++ b/shinysdr/i/test_db.py @@ -240,7 +240,7 @@ def test_index_response(self): # TODO: Actually parse/check-that-parses the document self.assertSubstring(textwrap.dedent('''\
  • foo&bar
  • - '''), data) + '''), six.ensure_str(data)) class TestDatabaseResource(unittest.TestCase): diff --git a/shinysdr/i/test_dependencies.py b/shinysdr/i/test_dependencies.py index cb591326..0b52aee9 100644 --- a/shinysdr/i/test_dependencies.py +++ b/shinysdr/i/test_dependencies.py @@ -47,7 +47,7 @@ def test_module_broken_import(self): 'The following libraries/programs are not installed correctly:\n\t (Check: shinysdr.i.test_dependencies_cases.imports failed to import (No module named nonexistent_module_in_dep).)\nPlease (re)install current versions.') else: self.assertEqual(self.t.report(), - 'The following libraries/programs are not installed correctly:\n\t (Check: shinysdr.i.test_dependencies_cases.imports failed to import (No module named \'shinysdr.test.nonexistent_module_in_dep\').)\nPlease (re)install current versions.') + 'The following libraries/programs are not installed correctly:\n\t (Check: shinysdr.i.test_dependencies_cases.imports failed to import (No module named \'shinysdr.nonexistent_module_in_dep\').)\nPlease (re)install current versions.') def test_module_broken_other(self): self.t.check_module('shinysdr.i.test_dependencies_cases.misc', '') diff --git a/shinysdr/plugins/osmosdr.py b/shinysdr/plugins/osmosdr.py index ad487baf..408ef029 100644 --- a/shinysdr/plugins/osmosdr.py +++ b/shinysdr/plugins/osmosdr.py @@ -115,8 +115,8 @@ def __repr__(self): def profile_from_device_string(device_string): # TODO: The input is actually an "args" string, which contains multiple devices space-separated. We should support this, but it is hard because osmosdr does not export the internal args_to_vector function and parsing it ourselves would need to be escaping-aware. - params = {k: v for k, v in osmosdr.device_t(device_string).items()} - for param_key in params.iterkeys(): + params = {k: v for k, v in osmosdr.device_t(six.ensure_str(device_string)).items()} + for param_key in params: if param_key in _default_profiles: # is a device of this type return _default_profiles[param_key] @@ -232,7 +232,7 @@ def OsmoSDRDevice( if profile is None: profile = profile_from_device_string(osmo_device) - source = osmosdr.source(b'numchan=1 ' + osmo_device) + source = osmosdr.source(six.ensure_str('numchan=1 ' + osmo_device)) if source.get_num_channels() < 1: # osmosdr.source doesn't throw an exception, allegedly because gnuradio can't handle it in a hier_block2 initializer. But we want to fail understandably, so recover by detecting it (sample rate = 0, which is otherwise nonsense) raise LookupError('OsmoSDR device not found (device string = %r)' % osmo_device) @@ -392,7 +392,7 @@ def set_agc(self, value): label='Antenna') def get_antenna(self): if self.__source is None: return '' - return six.text_type(self.__source.get_antenna(ch), 'ascii') + return six.ensure_text(self.__source.get_antenna(ch), 'ascii') @setter def set_antenna(self, value): diff --git a/shinysdr/plugins/rtl_433.py b/shinysdr/plugins/rtl_433.py index b0b1ca38..517036c1 100644 --- a/shinysdr/plugins/rtl_433.py +++ b/shinysdr/plugins/rtl_433.py @@ -97,7 +97,7 @@ def __init__(self, mode='433', input_rate=0, context=None): args=[ b'env', b'rtl_433', b'-F', b'json', # output format - b'-r', str(demod_rate) + b'sps:iq:cf32:-', # specify input format and to use stdin + b'-r', b'%dsps:iq:cf32:-' % (demod_rate), # specify input format and to use stdin b'-M', 'newmodel', ], childFDs={ diff --git a/shinysdr/test_devices.py b/shinysdr/test_devices.py index f9a9b0a6..081ec2f0 100644 --- a/shinysdr/test_devices.py +++ b/shinysdr/test_devices.py @@ -19,6 +19,7 @@ from __future__ import absolute_import, division, print_function, unicode_literals +import six from twisted.trial import unittest from gnuradio import blocks @@ -121,7 +122,7 @@ def test_components_disjoint(self): Device(components={'b': StubComponent()}) ]) self.assertEqual(d, IDevice(d)) - self.assertEqual(sorted(d.get_components_dict().iterkeys()), ['a', 'b']) + self.assertEqual(sorted(six.iterkeys(d.get_components_dict())), ['a', 'b']) def test_components_conflict(self): d = merge_devices([ @@ -129,7 +130,7 @@ def test_components_conflict(self): Device(components={'a': StubComponent()}) ]) self.assertEqual(d, IDevice(d)) - self.assertEqual(sorted(d.get_components_dict().iterkeys()), ['0-a', '1-a']) + self.assertEqual(sorted(six.iterkeys(d.get_components_dict())), ['0-a', '1-a']) def test_vfos(self): d = merge_devices([ diff --git a/shinysdr/testutil.py b/shinysdr/testutil.py index 9b6ef28b..391c801e 100644 --- a/shinysdr/testutil.py +++ b/shinysdr/testutil.py @@ -505,12 +505,12 @@ def _assert_http_response_properties(test_case, response, data): if data is not None: # not a HEAD request content_type = response.headers.getRawHeaders(b'Content-Type')[0] - if content_type in ('application/json', 'application/json; charset=utf-8'): + if content_type in (b'application/json', b'application/json; charset=utf-8'): json.loads(data) # raises error if it doesn't parse - elif content_type.startswith('text/html'): - test_case.assertRegex(content_type, r'(?i)text/html;\s*charset=utf-8') + elif content_type.startswith(b'text/html'): + test_case.assertRegex(content_type, br'(?i)text/html;\s*charset=utf-8') test_case.assertRegex(data, br'(?i)') - elif content_type in ('application/javascript', 'text/javascript', 'audio/wav'): + elif content_type in (b'application/javascript', b'text/javascript', b'audio/wav'): pass else: raise Exception('Don\'t know what content type checking to do', data[0], content_type)