-
Notifications
You must be signed in to change notification settings - Fork 115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Python 3 support for ShinySDR #145
base: master
Are you sure you want to change the base?
Changes from 19 commits
fa08731
5d8c982
f16517b
c7a0606
1267477
7b882d4
9d77173
97e2ef0
c9dd568
480d0cf
55f2ece
48bcccc
9089b68
1529d7f
291496f
b5b609c
3a7529b
11b6d2f
9835805
d4d6684
0f0992b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -302,8 +302,8 @@ def __do_connect(self): | |
# It would make slightly more sense to use unsigned chars, but blocks.float_to_uchar does not support vlen. | ||
self.__fft_converter = blocks.float_to_char(vlen=self.__freq_resolution, scale=1.0) | ||
|
||
fft_sink = self.__fft_cell.create_sink_internal(numpy.dtype((numpy.int8, output_length))) | ||
scope_sink = self.__scope_cell.create_sink_internal(numpy.dtype(('c8', self.__time_length))) | ||
self.__fft_sink = self.__fft_cell.create_sink_internal(numpy.dtype((numpy.int8, output_length))) | ||
self.__scope_sink = self.__scope_cell.create_sink_internal(numpy.dtype(('c8', self.__time_length))) | ||
Comment on lines
+305
to
+306
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are these being made attributes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Letting Python garbage collect them while they're still in the flowgraph causes crashes now. |
||
scope_chunker = blocks.stream_to_vector_decimator( | ||
item_size=gr.sizeof_gr_complex, | ||
sample_rate=sample_rate, | ||
|
@@ -324,15 +324,15 @@ def __do_connect(self): | |
logarithmizer) | ||
if self.__after_fft is not None: | ||
self.connect(logarithmizer, self.__after_fft) | ||
self.connect(self.__after_fft, self.__fft_converter, fft_sink) | ||
self.connect(self.__after_fft, self.__fft_converter, self.__fft_sink) | ||
self.connect((self.__after_fft, 1), blocks.null_sink(gr.sizeof_float * self.__freq_resolution)) | ||
else: | ||
self.connect(logarithmizer, self.__fft_converter, fft_sink) | ||
self.connect(logarithmizer, self.__fft_converter, self.__fft_sink) | ||
if self.__enable_scope: | ||
self.connect( | ||
self.__gate, | ||
scope_chunker, | ||
scope_sink) | ||
self.__scope_sink) | ||
finally: | ||
self.__context.unlock() | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -140,10 +140,10 @@ class DatabasesResource(resource.Resource): | |
|
||
def __init__(self, databases): | ||
resource.Resource.__init__(self) | ||
self.putChild('', ElementRenderingResource(_DbsIndexListElement(self))) | ||
self.putChild(b'', ElementRenderingResource(_DbsIndexListElement(self))) | ||
self.names = [] | ||
for (name, database) in six.iteritems(databases): | ||
self.putChild(name, DatabaseResource(database)) | ||
self.putChild(name.encode(), DatabaseResource(database)) | ||
self.names.append(name) | ||
self.names.sort() # TODO reconsider case/locale | ||
|
||
|
@@ -170,9 +170,9 @@ def __init__(self, database): | |
resource.Resource.__init__(self) | ||
|
||
def instantiate(rkey): | ||
self.putChild(str(rkey), _RecordResource(database, database.records[rkey])) | ||
self.putChild(str(rkey).encode(), _RecordResource(database, database.records[rkey])) | ||
|
||
self.putChild('', _DbIndexResource(database, instantiate)) | ||
self.putChild(b'', _DbIndexResource(database, instantiate)) | ||
for rkey in database.records: | ||
instantiate(rkey) | ||
|
||
|
@@ -186,11 +186,11 @@ def __init__(self, db, instantiate): | |
self.__instantiate = instantiate | ||
|
||
def render_GET(self, request): | ||
request.setHeader(b'Content-Type', b'application/json') | ||
request.setHeader(b'Content-Type', b'application/json; charset=utf-8') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. application/json does not have a charset parameter; this change and its other instances below should be reverted. https://tools.ietf.org/html/rfc7159 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I get what the RFC says, but I believe this was in fact necessary to make it work because something else started setting/requiring it. I'll try to reproduce the error so I can post it here. (I certainly didn't spontaneously decide to add this all over the place!) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't reproduce whatever error I saw (and this was months ago so I've long since forgotten). I reverted these changes for now as a separate commit so I can easily re-add them if/when I figure out why they were necessary in the first place. |
||
return json.dumps({ | ||
u'records': self.__database.records, | ||
u'writable': self.__database.writable | ||
}) | ||
}).encode('utf-8') | ||
|
||
def render_POST(self, request): | ||
desc = json.load(request.content) | ||
|
@@ -207,7 +207,7 @@ 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) | ||
|
@@ -223,11 +223,11 @@ def __init__(self, database, record): | |
self.__record = record | ||
|
||
def render_GET(self, request): | ||
request.setHeader(b'Content-Type', b'application/json') | ||
return json.dumps(self.__record) | ||
request.setHeader(b'Content-Type', b'application/json; charset=utf-8') | ||
return json.dumps(self.__record).encode('utf-8') | ||
|
||
def render_POST(self, request): | ||
assert request.getHeader(b'Content-Type') == b'application/json' | ||
assert request.getHeader(b'Content-Type') in (b'application/json', b'application/json; charset=utf-8') | ||
if not self.__database.writable: | ||
request.setResponseCode(http.FORBIDDEN) | ||
request.setHeader(b'Content-Type', b'text/plain') | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,23 +38,23 @@ def __init__(self, session, wcommon, read_only_dbs, writable_db): | |
SlashedResource.__init__(self) | ||
|
||
# UI entry point | ||
self.putChild('', ElementRenderingResource(_RadioIndexHtmlElement(wcommon))) | ||
self.putChild(b'', ElementRenderingResource(_RadioIndexHtmlElement(wcommon))) | ||
|
||
# Exported radio control objects | ||
self.putChild(CAP_OBJECT_PATH_ELEMENT, BlockResource(session, wcommon, _not_deletable)) | ||
self.putChild(CAP_OBJECT_PATH_ELEMENT.encode(), BlockResource(session, wcommon, _not_deletable)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about using b'' for the constant value since it's always used in this context? If that doesn't work, I'd rather see .encode('utf-8') here because it's the right thing for all URL components, rather than depending on the default encoding under Python 2. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I actually buy that utf-8 is correct; arguably it should be utf-8 + urlencode, but since it's a constant that's pure ASCII it's kind of moot. Done. |
||
|
||
# Frequency DB | ||
self.putChild('dbs', shinysdr.i.db.DatabasesResource(read_only_dbs)) | ||
self.putChild('wdb', shinysdr.i.db.DatabaseResource(writable_db)) | ||
self.putChild(b'dbs', shinysdr.i.db.DatabasesResource(read_only_dbs)) | ||
self.putChild(b'wdb', shinysdr.i.db.DatabaseResource(writable_db)) | ||
|
||
# Debug graph | ||
self.putChild('flow-graph', FlowgraphVizResource(wcommon.reactor, session.flowgraph_for_debug())) | ||
self.putChild(b'flow-graph', FlowgraphVizResource(wcommon.reactor, session.flowgraph_for_debug())) | ||
|
||
# Ephemeris | ||
self.putChild('ephemeris', EphemerisResource()) | ||
self.putChild(b'ephemeris', EphemerisResource()) | ||
|
||
# Standard audio-file-over-HTTP audio stream (the ShinySDR web client uses WebSockets instead, but both have the same path modulo protocol) | ||
self.putChild(AUDIO_STREAM_PATH_ELEMENT, AudioStreamResource(session)) | ||
self.putChild(AUDIO_STREAM_PATH_ELEMENT.encode(), AudioStreamResource(session)) | ||
quentinmit marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
class _RadioIndexHtmlElement(EntryPointIndexElement): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment indicating this is for version compatibility so we can strip it out later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done