Skip to content

Commit

Permalink
Gross monkey patch to fix simplejson issue (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
polyatail committed Nov 15, 2018
1 parent 38260f7 commit 5a4ec69
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 51 deletions.
73 changes: 63 additions & 10 deletions onecodex/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
import os
import warnings

from potion_client import Client as PotionClient
from potion_client.converter import PotionJSONSchemaDecoder, PotionJSONDecoder, PotionJSONEncoder
from potion_client.utils import upper_camel_case
import potion_client

from requests.auth import HTTPBasicAuth

from onecodex.lib.auth import BearerTokenAuth
Expand All @@ -23,6 +22,60 @@
log = logging.getLogger(__name__)


# begin gross monkey patch (see #66)
class MPPotionJSONSchemaDecoder(potion_client.converter.PotionJSONSchemaDecoder):
def __init__(*args, **kwargs):
if 'encoding' in kwargs:
del kwargs['encoding']

potion_client.converter.PotionJSONSchemaDecoder.__init__(*args, **kwargs)


class MPPotionJSONDecoder(potion_client.converter.PotionJSONDecoder):
def __init__(*args, **kwargs):
if 'encoding' in kwargs:
del kwargs['encoding']

potion_client.converter.PotionJSONDecoder.__init__(*args, **kwargs)


class MPPotionJSONEncoder(potion_client.converter.PotionJSONEncoder):
def __init__(*args, **kwargs):
if 'encoding' in kwargs:
del kwargs['encoding']

potion_client.converter.PotionJSONEncoder.__init__(*args, **kwargs)


class MPJSONSchemaReference(potion_client.resource.Reference):
@classmethod
def _resolve(self, client, uri):
return client.fetch(uri, cls=MPPotionJSONSchemaDecoder)


def mp_make_request(self, data, params):
req = self.request_factory(data, params)
prepared_request = self.owner._client.session.prepare_request(req)

response = self.owner._client.session.send(prepared_request)

# return error for some error conditions
self.raise_for_status(response)

if response.status_code == 204:
return response, None

return response, response.json(cls=MPPotionJSONDecoder,
client=self.owner._client,
default_instance=self.instance)


potion_client.converter.JSONSchemaReference = MPJSONSchemaReference
potion_client.links.LinkBinding.make_request = mp_make_request
PotionClient = potion_client.Client
# end gross monkey patch


class Api(object):
"""
This is the base One Codex Api object class. It instantiates a Potion-Client
Expand Down Expand Up @@ -121,7 +174,7 @@ class ExtendedPotionClient(PotionClient):
DATE_FORMAT = "%Y-%m-%d %H:%M"
SCHEMA_SAVE_DURATION = 1 # day

def fetch(self, uri, cls=PotionJSONDecoder, **kwargs):
def fetch(self, uri, cls=MPPotionJSONDecoder, **kwargs):
if uri in self._cached_schema:
return self._cached_schema[uri]
return super(ExtendedPotionClient, self).fetch(uri, cls=cls, **kwargs)
Expand Down Expand Up @@ -154,19 +207,19 @@ def _fetch_schema(self, cache_schema=False, creds_file=None):
# Catch schema caching issues and fall back to remote URL
try:
base_schema = serialized_schema.pop(self._schema_url)
schema = json.loads(base_schema, cls=PotionJSONSchemaDecoder,
schema = json.loads(base_schema, cls=MPPotionJSONSchemaDecoder,
referrer=self._schema_url, client=self)

for route, route_schema in serialized_schema.items():
object_schema = json.loads(route_schema, cls=PotionJSONSchemaDecoder,
object_schema = json.loads(route_schema, cls=MPPotionJSONSchemaDecoder,
referrer=self._schema_url, client=self)
self._cached_schema[route] = object_schema
except KeyError: # Caches issue with schema_url not existing
pass

if schema is None:
# if the schema wasn't cached or if it was expired, get it anew
schema = self.session.get(self._schema_url).json(cls=PotionJSONSchemaDecoder,
schema = self.session.get(self._schema_url).json(cls=MPPotionJSONSchemaDecoder,
referrer=self._schema_url,
client=self)
if cache_schema:
Expand All @@ -175,12 +228,12 @@ def _fetch_schema(self, cache_schema=False, creds_file=None):

# serialize the main schema
serialized_schema = {}
serialized_schema[self._schema_url] = json.dumps(schema, cls=PotionJSONEncoder)
serialized_schema[self._schema_url] = json.dumps(schema, cls=MPPotionJSONEncoder)

# serialize the object schemas
for schema_ref in schema['properties'].values():
serialized_schema[schema_ref._uri] = json.dumps(schema_ref._properties,
cls=PotionJSONEncoder)
cls=MPPotionJSONEncoder)

creds['schema'] = serialized_schema
else:
Expand All @@ -194,5 +247,5 @@ def _fetch_schema(self, cache_schema=False, creds_file=None):
json.dump(creds, open(creds_fp, mode='w'))

for name, resource_schema in schema['properties'].items():
class_name = upper_camel_case(name)
class_name = potion_client.utils.upper_camel_case(name)
setattr(self, class_name, self.resource_factory(name, resource_schema))
7 changes: 1 addition & 6 deletions onecodex/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@

from onecodex.utils import (cli_resource_fetcher, download_file_helper,
valid_api_key, OPTION_HELP, pprint, pretty_errors,
warn_if_insecure_platform, is_simplejson_installed,
warn_simplejson, telemetry, snake_case)
warn_if_insecure_platform, telemetry, snake_case)
from onecodex.api import Api
from onecodex.exceptions import (OneCodexException, ValidationWarning,
ValidationError, UploadException)
Expand Down Expand Up @@ -63,10 +62,6 @@ def onecodex(ctx, api_key, no_pprint, verbose, telemetry):
if verbose:
log.setLevel(logging.INFO)

# Show a warning if simplejson is installed
if is_simplejson_installed():
warn_simplejson()

# create the api
no_api_subcommands = ["login", "logout"]
if ctx.invoked_subcommand not in no_api_subcommands:
Expand Down
27 changes: 0 additions & 27 deletions onecodex/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,33 +187,6 @@ def warn_if_insecure_platform():
return False


def is_simplejson_installed():
try:
import simplejson # noqa
except ImportError:
return False
else:
return True


def warn_simplejson():
"""
Right now, potion-client is incompatible with requests when simplejson is
installed. Until this is patched upstream, we display this warning to
users when simplejson is installed.
"""
m = ("\n"
"######################################################################################\n" # noqa
"# #\n" # noqa
"# You currently have simplejson installed. Unfortunately, this library does not #\n" # noqa
"# work properly alongside simplejson. Please install this library in a separate #\n" # noqa
"# virtual environment using a tool such as virtualenv or uninstall simplejson. #\n" # noqa
"# For more information, see https://virtualenv.pypa.io/en/stable/. #\n" # noqa
"# #\n" # noqa
"######################################################################################\n") # noqa)
echo(m, err=True)


def get_download_dest(input_path, url):
original_filename = urlparse(url).path.split("/")[-1]
if os.path.isdir(input_path):
Expand Down
8 changes: 0 additions & 8 deletions tests/test_simplejson.py

This file was deleted.

0 comments on commit 5a4ec69

Please sign in to comment.