diff --git a/mapr/ojai/ojai_query/OJAIQueryCondition.py b/mapr/ojai/ojai_query/OJAIQueryCondition.py index b3768c8..6542c68 100644 --- a/mapr/ojai/ojai_query/OJAIQueryCondition.py +++ b/mapr/ojai/ojai_query/OJAIQueryCondition.py @@ -105,11 +105,11 @@ def not_matches_(self, field_path, regex): return self def like_(self, field_path, like_expression, escape_char=None): - self.__tokens.append({'$like': {field_path: like_expression}}) + self.__tokens.append({'$like': {field_path: [like_expression, escape_char] if escape_char else like_expression}}) return self def not_like_(self, field_path, like_expression, escape_char=None): - self.__tokens.append({'$notlike': {field_path: like_expression}}) + self.__tokens.append({'$notlike': {field_path: [like_expression, escape_char] if escape_char else like_expression}}) return self def is_(self, field_path, op, value): diff --git a/mapr/ojai/storage/OJAIConnection.py b/mapr/ojai/storage/OJAIConnection.py index d55d602..3e29325 100644 --- a/mapr/ojai/storage/OJAIConnection.py +++ b/mapr/ojai/storage/OJAIConnection.py @@ -22,6 +22,7 @@ from mapr.ojai.exceptions.ConnectionError import ConnectionError from mapr.ojai.exceptions.IllegalArgumentError import IllegalArgumentError from mapr.ojai.exceptions.PathNotFoundError import PathNotFoundError +from mapr.ojai.exceptions.AccessDeniedError import AccessDeniedError from mapr.ojai.exceptions.StoreAlreadyExistsError import StoreAlreadyExistsError from mapr.ojai.exceptions.StoreNotFoundError import StoreNotFoundError from mapr.ojai.exceptions.UnknownServerError import UnknownServerError @@ -112,31 +113,28 @@ def __parse_connection_url(connection_str): .format(e, 'Common url string format' ' is [:][?].')) - options_dict = ( - urllib.parse.parse_qs(urllib.parse.urlparse(connection_str).query)) - auth = urllib.parse.unquote(options_dict.get('auth', ['basic'])[0]) - user = urllib.parse.unquote(options_dict.get('user', [''])[0]) - password = urllib.parse.unquote(options_dict.get('password', [''])[0]) - key = '{0}:{1}'.format(user, password).encode() + + options_dict = dict() + for pair in urllib.parse.urlparse(connection_str).query.split(';'): + entry = pair.split('=') + if entry[1:]: + options_dict[entry[0]] = urllib.parse.unquote(entry[1]) + + key = '{0}:{1}'.format(options_dict.get('user', ''), options_dict.get('password', '')).encode() encoded_user_metadata = base64.b64encode(key).decode() - ssl = \ - True if urllib.parse.unquote( - options_dict.get('ssl', ['true'])[0]) == 'true' else False - ssl_ca = urllib.parse.unquote(options_dict.get('sslCA', [''])[0]) - ssl_target_name_override = \ - urllib.parse.unquote( - options_dict.get('sslTargetNameOverride', [''])[0]) - - if ssl and ssl_ca == '': + ssl = json.loads(options_dict.get('ssl', 'true')) + ssl_ca = options_dict.get('sslCA', '') + + if ssl and not ssl_ca: raise AttributeError( 'sslCa path must be specified when ssl enabled.') return url, \ - auth, \ + options_dict.get('auth', 'basic'), \ encoded_user_metadata, \ ssl, \ ssl_ca, \ - ssl_target_name_override + options_dict.get('sslTargetNameOverride', '') @staticmethod def __get_channel(url, @@ -211,6 +209,8 @@ def __validate_response(response): raise StoreAlreadyExistsError(m=response.error.error_message) elif response.error.err_code == ErrorCode.Value('PATH_NOT_FOUND'): raise PathNotFoundError(m=response.error.error_message) + elif response.error.err_code == ErrorCode.Value('ACCESS_DENIED'): + raise AccessDeniedError(m=response.error.error_message) elif response.error.err_code == ErrorCode.Value('TABLE_NOT_FOUND'): return False else: diff --git a/setup.py b/setup.py index dc76947..07a1310 100644 --- a/setup.py +++ b/setup.py @@ -2,12 +2,13 @@ setup(name='maprdb_python_client', - version='1.1.5', + version='1.1.7', description='MapR-DB Python Client', url='https://github.com/mapr/maprdb-python-client/', author='MapR, Inc.', keywords='ojai python client mapr maprdb', packages=find_packages(exclude=['test*', 'docs*', 'examples*']), + setup_requires=['wheel'], install_requires=['aenum>=2.0.10', 'grpcio>=1.9.1', 'grpcio-tools>=1.9.1', 'ojai-python-api>=1.1', 'python-dateutil>=2.6.1', 'retrying>=1.3.3', 'future>=0.16.0'], python_requires='>=2.7.*', diff --git a/test/query_test/test_query.py b/test/query_test/test_query.py index 2f98095..32c0a62 100644 --- a/test/query_test/test_query.py +++ b/test/query_test/test_query.py @@ -206,10 +206,18 @@ def test_like(self): qc = OJAIQueryCondition().like_('card', 'visa').close().build() self.assertEqual(qc.as_dictionary(), {'$like': {'card': 'visa'}}) + def test_like_with_escape_character(self): + qc = OJAIQueryCondition().like_('_id', '00\\\\%2%', '\\\\').close().build() + self.assertEqual(qc.as_dictionary(), {'$like': {'_id': ['00\\\\%2%', '\\\\']}}) + def test_not_like(self): qc = OJAIQueryCondition().not_like_('card', 'visa').close().build() self.assertEqual(qc.as_dictionary(), {'$notlike': {'card': 'visa'}}) + def test_not_like_with_escape_character(self): + qc = OJAIQueryCondition().not_like_('_id', '00|%2%', '|').close().build() + self.assertEqual(qc.as_dictionary(), {'$notlike': {'_id': ['00|%2%', '|']}}) + def test_empty_condition(self): qc = OJAIQueryCondition() self.assertTrue(qc.is_empty())