Skip to content
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

Alternative PR for: Some bytes/str issues in py3 w/ zlib and json #2558

Merged
merged 8 commits into from
Apr 6, 2017
3 changes: 1 addition & 2 deletions superset/sql_lab.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import pandas as pd
import sqlalchemy
import uuid
import zlib

from sqlalchemy.pool import NullPool
from sqlalchemy.orm import sessionmaker
Expand Down Expand Up @@ -185,7 +184,7 @@ def handle_error(msg):
if store_results:
key = '{}'.format(uuid.uuid4())
logging.info("Storing results in results backend, key: {}".format(key))
results_backend.set(key, zlib.compress(payload))
results_backend.set(key, utils.zlib_compress(payload))
query.results_key = key

session.merge(query)
Expand Down
36 changes: 35 additions & 1 deletion superset/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import sqlalchemy as sa
import signal
import uuid
import sys
import zlib

from builtins import object
from datetime import date, datetime, time
Expand All @@ -41,7 +43,7 @@

logging.getLogger('MARKDOWN').setLevel(logging.INFO)


PY3K = sys.version_info >= (3, 0)
EPOCH = datetime(1970, 1, 1)
DTTM_ALIAS = '__timestamp'

Expand Down Expand Up @@ -572,3 +574,35 @@ def setup_cache(app, cache_config):
"""Setup the flask-cache on a flask app"""
if cache_config and cache_config.get('CACHE_TYPE') != 'null':
return Cache(app, config=cache_config)


def zlib_compress(data):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too many blank lines, should be 2 blank lines above a function (PEP8)

"""
Compress things in a py2/3 safe fashion
>>> json_str = '{"test": 1}'
>>> blob = zlib_compress(json_str)
"""
if PY3K:
if isinstance(data, str):
return zlib.compress(bytes(data, "utf-8"))
else:
Copy link
Contributor

@xrmx xrmx Apr 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may put a single return zlib.compress(data) outside the if PY3K instead of the following 4 lines.

Copy link
Contributor

@xrmx xrmx Apr 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can drop the else, it'll be handled by the last return

return zlib.compress(data)
return zlib.compress(data)


def zlib_decompress_to_string(blob):
"""
Decompress things to a string in a py2/3 safe fashion
>>> json_str = '{"test": 1}'
>>> blob = zlib_compress(json_str)
>>> got_str = zlib_decompress_to_string(blob)
>>> got_str == json_str
True
"""
if PY3K:
if isinstance(blob, bytes):
decompressed = zlib.decompress(blob)
else:
decompressed = zlib.decompress(bytes(blob, "utf-8"))
return decompressed.decode("utf-8")
return zlib.decompress(blob)
5 changes: 2 additions & 3 deletions superset/views/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import re
import time
import traceback
import zlib

import sqlalchemy as sqla

Expand Down Expand Up @@ -1878,7 +1877,7 @@ def results(self, key):
return json_error_response(get_datasource_access_error_msg(
'{}'.format(rejected_tables)))

payload = zlib.decompress(blob)
payload = utils.zlib_decompress_to_string(blob)
display_limit = app.config.get('DISPLAY_SQL_MAX_ROW', None)
if display_limit:
payload_json = json.loads(payload)
Expand Down Expand Up @@ -2018,7 +2017,7 @@ def csv(self, client_id):
if results_backend and query.results_key:
blob = results_backend.get(query.results_key)
if blob:
json_payload = zlib.decompress(blob)
json_payload = utils.zlib_decompress_to_string(blob)
obj = json.loads(json_payload)
columns = [c['name'] for c in obj['columns']]
df = pd.DataFrame.from_records(obj['data'], columns=columns)
Expand Down
9 changes: 8 additions & 1 deletion tests/utils_tests.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import datetime, date, timedelta, time
from decimal import Decimal
from superset.utils import (
json_int_dttm_ser, json_iso_dttm_ser, base_json_conv, parse_human_timedelta
json_int_dttm_ser, json_iso_dttm_ser, base_json_conv, parse_human_timedelta, zlib_compress, zlib_decompress_to_string
)
import unittest
import uuid
Expand Down Expand Up @@ -45,3 +45,10 @@ def test_base_json_conv(self):
def test_parse_human_timedelta(self, mock_now):
mock_now.return_value = datetime(2016, 12, 1)
self.assertEquals(parse_human_timedelta('now'), timedelta(0))

def test_zlib_compression(self):
json_str = """{"test": 1}"""
blob = zlib_compress(json_str)
got_str = zlib_decompress_to_string(blob)
self.assertEquals(json_str, got_str)