diff --git a/CHANGELOG.md b/CHANGELOG.md index 443f70f..970a309 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] - +### Fixed +- Escape slashes in entity keys when they appear in the URL path - Jon Friesen ### Removed - Python 3.7 (long after its EOL) is no longer supported by pyodata. Python 3.8 is now minimal supported version. - Petr Hanak diff --git a/pyodata/v2/service.py b/pyodata/v2/service.py index 0ed7741..18d6b13 100644 --- a/pyodata/v2/service.py +++ b/pyodata/v2/service.py @@ -405,7 +405,7 @@ def expand(self, expand): def get_path(self): if self.get_encode_path(): - return quote(self._entity_set_proxy.last_segment + self._entity_key.to_key_string()) + return quote(self._entity_set_proxy.last_segment) + quote(self._entity_key.to_key_string(), safe='') return self._entity_set_proxy.last_segment + self._entity_key.to_key_string() def get_default_headers(self): @@ -563,7 +563,7 @@ def __init__(self, url, connection, handler, entity_set, entity_key, encode_path def get_path(self): if self.get_encode_path(): - return quote(self._entity_set.name + self._entity_key.to_key_string()) + return quote(self._entity_set.name) + quote(self._entity_key.to_key_string(), safe='') return self._entity_set.name + self._entity_key.to_key_string() def get_encode_path(self): @@ -607,7 +607,7 @@ def __init__(self, url, connection, handler, entity_set, entity_key, method="PAT def get_path(self): if self.get_encode_path(): - return quote(self._entity_set.name + self._entity_key.to_key_string()) + return quote(self._entity_set.name) + quote(self._entity_key.to_key_string(), safe='') return self._entity_set.name + self._entity_key.to_key_string() def get_method(self): diff --git a/tests/test_service_v2.py b/tests/test_service_v2.py index f0d5bc5..0294903 100644 --- a/tests/test_service_v2.py +++ b/tests/test_service_v2.py @@ -243,6 +243,22 @@ def test_entity_url(service): entity = service.entity_sets.MasterEntities.get_entity('12345').execute() assert entity.url == URL_ROOT + "/MasterEntities('12345')" +@responses.activate +def test_entity_url_with_slashes(service): + """Test correct build of entity url""" + + # pylint: disable=redefined-outer-name + path = quote("MasterEntities('FOO/BAR')", safe='') + responses.add( + responses.GET, + f"{service.url}/{path}", + headers={'Content-type': 'application/json'}, + json={'d': {'Key': 'FOO/BAR'}}, + status=200) + + entity = service.entity_sets.MasterEntities.get_entity('FOO/BAR').execute() + assert entity.url == URL_ROOT + "/MasterEntities('FOO/BAR')" + @responses.activate def test_entity_entity_set_name(service): @@ -631,6 +647,7 @@ def test_delete_entity(service): assert isinstance(request, pyodata.v2.service.EntityDeleteRequest) assert request.execute() is None + @responses.activate def test_delete_entity_not_encoded_path(service): """Check deleting of entity"""