From ab2961132c358fc33c4402782509af4069c34f0d Mon Sep 17 00:00:00 2001 From: Sebastian Molenda Date: Tue, 20 Sep 2022 12:13:49 +0200 Subject: [PATCH] Users and Spaces V3 implementation --- pubnub/endpoints/endpoint.py | 4 +- pubnub/endpoints/entities/space.py | 228 ++++++++++++ pubnub/endpoints/entities/space/__init__.py | 0 .../endpoints/entities/space/create_space.py | 70 ---- .../endpoints/entities/space/fetch_space.py | 31 -- .../endpoints/entities/space/fetch_spaces.py | 29 -- .../endpoints/entities/space/remove_space.py | 30 -- .../endpoints/entities/space/update_space.py | 69 ---- pubnub/endpoints/entities/user.py | 225 ++++++++++++ pubnub/endpoints/entities/user/__init__.py | 0 pubnub/endpoints/entities/user/create_user.py | 75 ---- pubnub/endpoints/entities/user/fetch_user.py | 31 -- pubnub/endpoints/entities/user/fetch_users.py | 28 -- pubnub/endpoints/entities/user/remove_user.py | 30 -- pubnub/endpoints/entities/user/update_user.py | 75 ---- pubnub/enums.py | 15 +- pubnub/models/consumer/entities/result.py | 2 +- pubnub/models/consumer/entities/space.py | 4 + pubnub/models/consumer/entities/user.py | 4 + pubnub/pubnub_core.py | 332 ++++++------------ pubnub/request_handlers/requests_handler.py | 2 +- pubnub/structures.py | 7 +- .../native_sync/spaces/create_space.yaml | 83 +++++ .../spaces/create_space_id_collision.yaml | 122 +++++++ .../spaces/fetch_space_existing.yaml | 120 +++++++ .../spaces/fetch_space_not_existing.yaml | 38 ++ .../spaces/fetch_spaces_existing.yaml | 120 +++++++ .../spaces/fetch_spaces_multiple.yaml | 272 ++++++++++++++ .../spaces/fetch_spaces_not_existing.yaml | 38 ++ .../native_sync/spaces/update_space.yaml | 123 +++++++ .../spaces/update_space_id_missing.yaml | 82 +++++ .../native_sync/spaces/upsert_space.yaml | 83 +++++ .../spaces/upsert_update_space.yaml | 123 +++++++ .../native_sync/users/create_user.yaml | 83 +++++ .../users/create_user_id_collision.yaml | 123 +++++++ .../users/fetch_user_existing.yaml | 158 +++++++++ .../users/fetch_user_not_existing.yaml | 38 ++ .../users/fetch_users_existing.yaml | 158 +++++++++ .../users/fetch_users_multiple.yaml | 275 +++++++++++++++ .../users/fetch_users_not_existing.yaml | 38 ++ .../native_sync/users/update_user.yaml | 124 +++++++ .../users/update_user_id_missing.yaml | 120 +++++++ .../native_sync/users/upsert_create_user.yaml | 121 +++++++ .../native_sync/users/upsert_update_user.yaml | 124 +++++++ .../integrational/native_sync/test_spaces.py | 240 +++++++++++++ tests/integrational/native_sync/test_users.py | 275 +++++++++++++++ 46 files changed, 3672 insertions(+), 700 deletions(-) create mode 100644 pubnub/endpoints/entities/space.py delete mode 100644 pubnub/endpoints/entities/space/__init__.py delete mode 100644 pubnub/endpoints/entities/space/create_space.py delete mode 100644 pubnub/endpoints/entities/space/fetch_space.py delete mode 100644 pubnub/endpoints/entities/space/fetch_spaces.py delete mode 100644 pubnub/endpoints/entities/space/remove_space.py delete mode 100644 pubnub/endpoints/entities/space/update_space.py create mode 100644 pubnub/endpoints/entities/user.py delete mode 100644 pubnub/endpoints/entities/user/__init__.py delete mode 100644 pubnub/endpoints/entities/user/create_user.py delete mode 100644 pubnub/endpoints/entities/user/fetch_user.py delete mode 100644 pubnub/endpoints/entities/user/fetch_users.py delete mode 100644 pubnub/endpoints/entities/user/remove_user.py delete mode 100644 pubnub/endpoints/entities/user/update_user.py create mode 100644 tests/integrational/fixtures/native_sync/spaces/create_space.yaml create mode 100644 tests/integrational/fixtures/native_sync/spaces/create_space_id_collision.yaml create mode 100644 tests/integrational/fixtures/native_sync/spaces/fetch_space_existing.yaml create mode 100644 tests/integrational/fixtures/native_sync/spaces/fetch_space_not_existing.yaml create mode 100644 tests/integrational/fixtures/native_sync/spaces/fetch_spaces_existing.yaml create mode 100644 tests/integrational/fixtures/native_sync/spaces/fetch_spaces_multiple.yaml create mode 100644 tests/integrational/fixtures/native_sync/spaces/fetch_spaces_not_existing.yaml create mode 100644 tests/integrational/fixtures/native_sync/spaces/update_space.yaml create mode 100644 tests/integrational/fixtures/native_sync/spaces/update_space_id_missing.yaml create mode 100644 tests/integrational/fixtures/native_sync/spaces/upsert_space.yaml create mode 100644 tests/integrational/fixtures/native_sync/spaces/upsert_update_space.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/create_user.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/create_user_id_collision.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/fetch_user_existing.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/fetch_user_not_existing.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/fetch_users_existing.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/fetch_users_multiple.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/fetch_users_not_existing.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/update_user.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/update_user_id_missing.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/upsert_create_user.yaml create mode 100644 tests/integrational/fixtures/native_sync/users/upsert_update_user.yaml create mode 100644 tests/integrational/native_sync/test_spaces.py create mode 100644 tests/integrational/native_sync/test_users.py diff --git a/pubnub/endpoints/endpoint.py b/pubnub/endpoints/endpoint.py index 4df91bf6..40434254 100644 --- a/pubnub/endpoints/endpoint.py +++ b/pubnub/endpoints/endpoint.py @@ -25,6 +25,7 @@ class Endpoint(object): __metaclass__ = ABCMeta _path = None + _custom_headers = None def __init__(self, pubnub): self.pubnub = pubnub @@ -99,7 +100,8 @@ def request_headers(self): headers["Content-Encoding"] = "gzip" if self.http_method() == HttpMethod.POST: headers["Content-type"] = "application/json" - + if self._custom_headers: + headers.update(self._custom_headers) return headers def build_file_upload_request(self): diff --git a/pubnub/endpoints/entities/space.py b/pubnub/endpoints/entities/space.py new file mode 100644 index 00000000..6550f553 --- /dev/null +++ b/pubnub/endpoints/entities/space.py @@ -0,0 +1,228 @@ +from pubnub.endpoints.entities.endpoint import EntitiesEndpoint +from pubnub.enums import PNOperationType +from pubnub.enums import HttpMethod +from pubnub.errors import PNERR_SPACE_MISSING +from pubnub.exceptions import PubNubException +from pubnub.models.consumer.entities.page import Next, Previous +from pubnub.models.consumer.entities.space import PNCreateSpaceResult, PNRemoveSpaceResult, PNUpdateSpaceResult, \ + PNUpsertSpaceResult, PNFetchSpaceResult, PNFetchSpacesResult +from pubnub.models.consumer.objects_v2.page import PNPage +from pubnub.utils import write_value_as_string + + +class EntitiesSpaceEndpoint(EntitiesEndpoint): + SPACE_PATH = "/v3/objects/%s/spaces/%s" + _space_id = None + _name = None + _description = None + _space_type = None + _space_status = None + _custom = None + _operation_type = None + _operation_name = None + _operation_http_method = None + + def __init__(self, pubnub, space_id, name: str = None, description: str = None, space_type: str = None, + space_status: str = None, custom: dict = None): + EntitiesEndpoint.__init__(self, pubnub) + + self._space_id = str(space_id) + if name is not None: + self._name = str(name) + + if description is not None: + self._description = str(description) + + if custom is not None: + self._custom = dict(custom) if custom else None + self._include_custom = True + + if space_type is not None: + self._space_type = str(space_type) + self._include_type = True + + if space_status is not None: + self._space_status = str(space_status) + self._include_status = True + + def _validate_space_id(self): + if self._space_id is None or len(self._space_id) == 0: + raise PubNubException(pn_error=PNERR_SPACE_MISSING) + + def build_path(self): + return self.SPACE_PATH % (self.pubnub.config.subscribe_key, self._space_id) + + def build_data(self): + payload = {} + + if self._name: + payload['name'] = self._name + if self._description: + payload['description'] = self._description + if self._custom: + payload['custom'] = self._custom + if self._space_status: + payload['status'] = self._space_status + if self._space_type: + payload['type'] = self._space_type + + return write_value_as_string(payload) + + def validate_specific_params(self): + self._validate_space_id() + + def operation_type(self): + return self._operation_type + + def name(self): + return self._operation_name + + def http_method(self): + return self._operation_http_method + + +class CreateSpace(EntitiesSpaceEndpoint): + def __init__(self, pubnub, space_id, name: str = None, description: str = None, space_type: str = None, + space_status: str = None, custom: dict = None): + super().__init__(pubnub, space_id, name, description, space_type, space_status, custom) + + self._operation_type = PNOperationType.PNCreateSpaceOperation + self._operation_name = "Create Space V3" + self._operation_http_method = HttpMethod.POST + + def create_response(self, envelope) -> PNCreateSpaceResult: + return PNCreateSpaceResult(envelope) + + +class UpdateSpace(EntitiesSpaceEndpoint): + def __init__(self, pubnub, space_id, name: str = None, description: str = None, space_type: str = None, + space_status: str = None, custom: dict = None): + super().__init__(pubnub, space_id, name, description, space_type, space_status, custom) + + self._operation_type = PNOperationType.PNUpdateSpaceOperation + self._operation_name = "Update Space V3" + self._operation_http_method = HttpMethod.PATCH + self._custom_headers = {"Content-type": "application/json"} + + def create_response(self, envelope) -> PNUpdateSpaceResult: + return PNUpdateSpaceResult(envelope) + + +class UpsertSpace(EntitiesSpaceEndpoint): + def __init__(self, pubnub, space_id, name: str = None, description: str = None, space_type: str = None, + space_status: str = None, custom: dict = None): + super().__init__(pubnub, space_id, name, description, space_type, space_status, custom) + + self._operation_type = PNOperationType.PNUpsertSpaceOperation + self._operation_name = "Upsert Space V3" + self._operation_http_method = HttpMethod.PUT + self._custom_headers = {"Content-type": "application/json"} + + def create_response(self, envelope) -> PNUpsertSpaceResult: + return PNUpsertSpaceResult(envelope) + + +class RemoveSpace(EntitiesSpaceEndpoint): + def __init__(self, pubnub, space_id: str): + super().__init__(pubnub, space_id) + + self._operation_type = PNOperationType.PNRemoveSpaceOperation + self._operation_name = "Remove Space V3" + self._operation_http_method = HttpMethod.DELETE + + def create_response(self, envelope): + return PNRemoveSpaceResult(envelope) + + def build_data(self): + return '' + + +class FetchSpace(EntitiesSpaceEndpoint): + def __init__(self, pubnub, space_id: str, include: list = []): + super().__init__(pubnub, space_id) + + self._operation_type = PNOperationType.PNFetchSpaceOperation + self._operation_name = "Fetch Space V3" + + self._operation_http_method = HttpMethod.GET + + if 'custom' in include: + self._include_custom = True + + if 'status' in include: + self._include_status = True + + if 'type' in include: + self._include_type = True + + def create_response(self, envelope): + return PNFetchSpaceResult(envelope) + + def build_data(self): + return '' + + +class FetchSpaces(EntitiesEndpoint): + SPACE_PATH = "/v3/objects/%s/spaces" + + def __init__(self, pubnub, limit: str = None, filter_string: str = None, include_total_count: bool = None, + include_custom: bool = None, page: PNPage = None, sort_keys=None): + super().__init__(pubnub) + + self._limit = limit + self._filter = filter_string + self._include_total_count = include_total_count + self._sort_keys = sort_keys + self._page = page + self._include_custom = include_custom + + def build_path(self): + return self.SPACE_PATH % self.pubnub.config.subscribe_key + + def create_response(self, envelope): + return PNFetchSpacesResult(envelope) + + def operation_type(self): + return PNOperationType.PNFetchSpacesOperation + + def name(self): + return "Fetch Spaces" + + def http_method(self): + return HttpMethod.GET + + def custom_params(self): + params = {} + inclusions = [] + + if self._include_custom: + inclusions.append("custom") + + if self._filter: + params["filter"] = str(self._filter) + + if self._limit: + params["limit"] = int(self._limit) + + if self._include_total_count: + params["count"] = bool(self._include_total_count) + + if self._sort_keys: + joined_sort_params_array = [] + for sort_key in self._sort_keys: + joined_sort_params_array.append("%s:%s" % (sort_key.key_str(), sort_key.dir_str())) + + params["sort"] = ",".join(joined_sort_params_array) + + if self._page: + if isinstance(self._page, Next): + params["start"] = self._page.hash + elif isinstance(self._page, Previous): + params["end"] = self._page.hash + else: + raise ValueError() + + if len(inclusions) > 0: + params["include"] = ",".join(inclusions) + + return params diff --git a/pubnub/endpoints/entities/space/__init__.py b/pubnub/endpoints/entities/space/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pubnub/endpoints/entities/space/create_space.py b/pubnub/endpoints/entities/space/create_space.py deleted file mode 100644 index bb82244c..00000000 --- a/pubnub/endpoints/entities/space/create_space.py +++ /dev/null @@ -1,70 +0,0 @@ -from pubnub.endpoints.entities.endpoint import EntitiesEndpoint, SpaceEndpoint, IncludeCustomEndpoint, \ - CustomAwareEndpoint -from pubnub.enums import PNOperationType -from pubnub.enums import HttpMethod -from pubnub.models.consumer.entities.space import PNCreateSpaceResult -from pubnub.utils import write_value_as_string - - -class CreateSpace(EntitiesEndpoint, SpaceEndpoint, IncludeCustomEndpoint, CustomAwareEndpoint): - CREATE_SPACE_PATH = "/v2/objects/%s/channels/%s" - - def __init__(self, pubnub): - EntitiesEndpoint.__init__(self, pubnub) - SpaceEndpoint.__init__(self) - CustomAwareEndpoint.__init__(self) - IncludeCustomEndpoint.__init__(self) - - self._name = None - self._description = None - self._status = None - self._type = None - - def space_status(self, space_status): - self._status = space_status - self._include_status = True - return self - - def space_type(self, space_type): - self._type = space_type - self._include_type = True - return self - - def set_name(self, name): - self._name = str(name) - return self - - def description(self, description): - self._description = str(description) - return self - - def validate_specific_params(self): - self._validate_space_id() - - def build_path(self): - return CreateSpace.CREATE_SPACE_PATH % (self.pubnub.config.subscribe_key, self._space_id) - - def build_data(self): - payload = { - "name": self._name, - "description": self._description, - "custom": self._custom - } - if self._status: - payload['status'] = self._status - if self._type: - payload['type'] = self._type - - return write_value_as_string(payload) - - def create_response(self, envelope): - return PNCreateSpaceResult(envelope) - - def operation_type(self): - return PNOperationType.PNCreateSpaceOperation - - def name(self): - return "Create space" - - def http_method(self): - return HttpMethod.PATCH diff --git a/pubnub/endpoints/entities/space/fetch_space.py b/pubnub/endpoints/entities/space/fetch_space.py deleted file mode 100644 index 2de78fcd..00000000 --- a/pubnub/endpoints/entities/space/fetch_space.py +++ /dev/null @@ -1,31 +0,0 @@ -from pubnub.endpoints.entities.endpoint import EntitiesEndpoint, SpaceEndpoint, IncludeCustomEndpoint -from pubnub.enums import PNOperationType -from pubnub.enums import HttpMethod -from pubnub.models.consumer.entities.space import PNFetchSpaceResult - - -class FetchSpace(EntitiesEndpoint, SpaceEndpoint, IncludeCustomEndpoint): - FETCH_SPACE_PATH = "/v2/objects/%s/channels/%s" - - def __init__(self, pubnub): - EntitiesEndpoint.__init__(self, pubnub) - SpaceEndpoint.__init__(self) - IncludeCustomEndpoint.__init__(self) - - def build_path(self): - return FetchSpace.FETCH_SPACE_PATH % (self.pubnub.config.subscribe_key, self._space_id) - - def validate_specific_params(self): - self._validate_space_id() - - def create_response(self, envelope): - return PNFetchSpaceResult(envelope) - - def operation_type(self): - return PNOperationType.PNFetchSpaceOperation - - def name(self): - return "Fetch Space" - - def http_method(self): - return HttpMethod.GET diff --git a/pubnub/endpoints/entities/space/fetch_spaces.py b/pubnub/endpoints/entities/space/fetch_spaces.py deleted file mode 100644 index 0bce8866..00000000 --- a/pubnub/endpoints/entities/space/fetch_spaces.py +++ /dev/null @@ -1,29 +0,0 @@ -from pubnub.endpoints.entities.endpoint import EntitiesEndpoint, IncludeCustomEndpoint, ListEndpoint -from pubnub.enums import PNOperationType -from pubnub.enums import HttpMethod -from pubnub.models.consumer.entities.space import PNFetchSpacesResult - - -class FetchSpaces(EntitiesEndpoint, ListEndpoint, IncludeCustomEndpoint): - FETCH_SPACES_PATH = "/v2/objects/%s/channels" - inclusions = ['status', 'type'] - - def __init__(self, pubnub): - EntitiesEndpoint.__init__(self, pubnub) - ListEndpoint.__init__(self) - IncludeCustomEndpoint.__init__(self) - - def build_path(self): - return FetchSpaces.FETCH_SPACES_PATH % self.pubnub.config.subscribe_key - - def create_response(self, envelope): - return PNFetchSpacesResult(envelope) - - def operation_type(self): - return PNOperationType.PNFetchSpacesOperation - - def name(self): - return "Fetch Spaces" - - def http_method(self): - return HttpMethod.GET diff --git a/pubnub/endpoints/entities/space/remove_space.py b/pubnub/endpoints/entities/space/remove_space.py deleted file mode 100644 index 5a693a27..00000000 --- a/pubnub/endpoints/entities/space/remove_space.py +++ /dev/null @@ -1,30 +0,0 @@ -from pubnub.endpoints.entities.endpoint import EntitiesEndpoint, SpaceEndpoint -from pubnub.enums import PNOperationType -from pubnub.enums import HttpMethod -from pubnub.models.consumer.entities.space import PNRemoveSpaceResult - - -class RemoveSpace(EntitiesEndpoint, SpaceEndpoint): - REMOVE_SPACE_PATH = "/v2/objects/%s/channels/%s" - - def __init__(self, pubnub): - EntitiesEndpoint.__init__(self, pubnub) - SpaceEndpoint.__init__(self) - - def build_path(self): - return RemoveSpace.REMOVE_SPACE_PATH % (self.pubnub.config.subscribe_key, self._space_id) - - def validate_specific_params(self): - self._validate_space_id() - - def create_response(self, envelope): - return PNRemoveSpaceResult(envelope) - - def operation_type(self): - return PNOperationType.PNRemoveSpaceOperation - - def name(self): - return "Remove Space" - - def http_method(self): - return HttpMethod.DELETE diff --git a/pubnub/endpoints/entities/space/update_space.py b/pubnub/endpoints/entities/space/update_space.py deleted file mode 100644 index 5cca2855..00000000 --- a/pubnub/endpoints/entities/space/update_space.py +++ /dev/null @@ -1,69 +0,0 @@ -from pubnub.endpoints.entities.endpoint import EntitiesEndpoint, SpaceEndpoint, IncludeCustomEndpoint, \ - CustomAwareEndpoint -from pubnub.enums import PNOperationType -from pubnub.enums import HttpMethod -from pubnub.models.consumer.entities.space import PNUpdateSpaceResult -from pubnub.utils import write_value_as_string - - -class UpdateSpace(EntitiesEndpoint, SpaceEndpoint, IncludeCustomEndpoint, CustomAwareEndpoint): - UPDATE_SPACE_PATH = "/v2/objects/%s/channels/%s" - - def __init__(self, pubnub): - EntitiesEndpoint.__init__(self, pubnub) - SpaceEndpoint.__init__(self) - CustomAwareEndpoint.__init__(self) - IncludeCustomEndpoint.__init__(self) - - self._name = None - self._description = None - self._status = None - self._type = None - - def space_status(self, space_status): - self._status = space_status - self._include_status = True - return self - - def space_type(self, space_type): - self._type = space_type - self._include_type = True - return self - - def set_name(self, name): - self._name = str(name) - return self - - def description(self, description): - self._description = str(description) - return self - - def validate_specific_params(self): - self._validate_space_id() - - def build_path(self): - return UpdateSpace.UPDATE_SPACE_PATH % (self.pubnub.config.subscribe_key, self._space_id) - - def build_data(self): - payload = { - "name": self._name, - "description": self._description, - "custom": self._custom - } - if self._status: - payload['status'] = self._status - if self._type: - payload['type'] = self._type - return write_value_as_string(payload) - - def create_response(self, envelope): - return PNUpdateSpaceResult(envelope) - - def operation_type(self): - return PNOperationType.PNUpdateSpaceOperation - - def name(self): - return "Updatea space" - - def http_method(self): - return HttpMethod.PATCH diff --git a/pubnub/endpoints/entities/user.py b/pubnub/endpoints/entities/user.py new file mode 100644 index 00000000..0198da12 --- /dev/null +++ b/pubnub/endpoints/entities/user.py @@ -0,0 +1,225 @@ +from pubnub.endpoints.entities.endpoint import EntitiesEndpoint +from pubnub.enums import PNOperationType +from pubnub.enums import HttpMethod +from pubnub.errors import PNERR_USER_ID_MISSING +from pubnub.exceptions import PubNubException +from pubnub.models.consumer.entities.page import Next, Previous +from pubnub.models.consumer.entities.user import PNCreateUserResult, PNFetchUserResult, PNFetchUsersResult, \ + PNRemoveUserResult, PNUpdateUserResult, PNUpsertUserResult +from pubnub.models.consumer.objects_v2.page import PNPage +from pubnub.utils import write_value_as_string + + +class EntitiesUserEndpoint(EntitiesEndpoint): + USER_PATH = "/v3/objects/%s/users/%s" + + def __init__(self, pubnub, user_id: str, name: str = None, email: str = None, external_id: str = None, + profile_url: str = None, user_type: str = None, user_status: str = None, custom: dict = None): + EntitiesEndpoint.__init__(self, pubnub) + self._operation_type = None + self._operation_name = None + self._operation_http_method = None + + self._user_id = str(user_id) + self._name = str(name) + self._email = str(email) + self._external_id = str(external_id) + self._profile_url = str(profile_url) + self._user_type = str(user_type) + self._user_status = str(user_status) + self._custom = dict(custom) if custom else None + + if custom is not None: + self._custom = custom + self._include_custom = True + + if user_status is not None: + self._user_status = user_status + self._include_status = True + + if user_type is not None: + self._user_type = user_type + self._include_type = True + + def _effective_user_id(self): + if self._user_id is not None: + return self._user_id + else: + return self.pubnub.config.user_id + + def _validate_user_id(self): + if self._effective_user_id() is None or len(self._effective_user_id()) == 0: + raise PubNubException(pn_error=PNERR_USER_ID_MISSING) + + def build_path(self): + return self.USER_PATH % (self.pubnub.config.subscribe_key, self._effective_user_id()) + + def build_data(self): + payload = { + "name": self._name, + "email": self._email, + "externalId": self._external_id, + "profileUrl": self._profile_url, + "custom": self._custom, + "status": self._user_status, + "type": self._user_type, + } + return write_value_as_string(payload) + + def validate_specific_params(self): + self._validate_user_id() + + def operation_type(self): + return self._operation_type + + def name(self): + return self._operation_name + + def http_method(self): + return self._operation_http_method + + +class CreateUser(EntitiesUserEndpoint): + def __init__(self, pubnub, user_id: str, name: str = None, email: str = None, external_id: str = None, + profile_url: str = None, user_type: str = None, user_status: str = None, custom: dict = None): + super().__init__(pubnub, user_id, name, email, external_id, profile_url, user_type, user_status, custom) + + self._operation_type = PNOperationType.PNCreateUserOperation + self._operation_name = "Create User V3" + self._operation_http_method = HttpMethod.POST + + def create_response(self, envelope): + return PNCreateUserResult(envelope) + + +class UpdateUser(EntitiesUserEndpoint): + def __init__(self, pubnub, user_id: str, name: str = None, email: str = None, external_id: str = None, + profile_url: str = None, user_type: str = None, user_status: str = None, custom: dict = None): + super().__init__(pubnub, user_id, name, email, external_id, profile_url, user_type, user_status, custom) + + self._operation_type = PNOperationType.PNUpdateUserOperation + self._operation_name = "Update User V3" + self._operation_http_method = HttpMethod.PATCH + self._custom_headers = {"Content-type": "application/json"} + + def create_response(self, envelope): + return PNUpdateUserResult(envelope) + + +class UpsertUser(EntitiesUserEndpoint): + def __init__(self, pubnub, user_id: str, name: str = None, email: str = None, external_id: str = None, + profile_url: str = None, user_type: str = None, user_status: str = None, custom: dict = None): + super().__init__(pubnub, user_id, name, email, external_id, profile_url, user_type, user_status, custom) + + self._operation_type = PNOperationType.PNUpsertUserOperation + self._operation_name = "Upsert User V3" + self._operation_http_method = HttpMethod.PUT + self._custom_headers = {"Content-type": "application/json"} + + def create_response(self, envelope): + return PNUpsertUserResult(envelope) + + +class RemoveUser(EntitiesUserEndpoint): + def __init__(self, pubnub, user_id: str): + super().__init__(pubnub, user_id) + + self._operation_type = PNOperationType.PNRemoveUserOperation + self._operation_name = "Remove User V3" + self._operation_http_method = HttpMethod.DELETE + + def create_response(self, envelope): + return PNRemoveUserResult(envelope) + + def build_data(self): + return '' + + +class FetchUser(EntitiesUserEndpoint): + def __init__(self, pubnub, user_id: str, include: list = []): + super().__init__(pubnub, user_id) + + self._operation_type = PNOperationType.PNFetchUserOperation + self._operation_name = "Fetch User V3" + self._operation_http_method = HttpMethod.GET + + if 'custom' in include: + self._include_custom = True + + if 'status' in include: + self._include_status = True + + if 'type' in include: + self._include_type = True + + def create_response(self, envelope): + return PNFetchUserResult(envelope) + + def build_data(self): + return '' + + +class FetchUsers(EntitiesEndpoint): + USER_PATH = "/v3/objects/%s/users" + + def __init__(self, pubnub, limit: str = None, filter_string: str = None, include_total_count: bool = None, + include_custom: bool = None, page: PNPage = None, sort_keys=None): + super().__init__(pubnub) + + self._limit = limit + self._filter = filter_string + self._include_total_count = include_total_count + self._sort_keys = sort_keys + self._page = page + self._include_custom = include_custom + + def build_path(self): + return self.USER_PATH % self.pubnub.config.subscribe_key + + def create_response(self, envelope): + return PNFetchUsersResult(envelope) + + def operation_type(self): + return PNOperationType.PNFetchUsersOperation + + def name(self): + return "Fetch Users" + + def http_method(self): + return HttpMethod.GET + + def custom_params(self): + params = {} + inclusions = [] + + if self._include_custom: + inclusions.append("custom") + + if self._filter: + params["filter"] = str(self._filter) + + if self._limit: + params["limit"] = int(self._limit) + + if self._include_total_count: + params["count"] = bool(self._include_total_count) + + if self._sort_keys: + joined_sort_params_array = [] + for sort_key in self._sort_keys: + joined_sort_params_array.append("%s:%s" % (sort_key.key_str(), sort_key.dir_str())) + + params["sort"] = ",".join(joined_sort_params_array) + + if self._page: + if isinstance(self._page, Next): + params["start"] = self._page.hash + elif isinstance(self._page, Previous): + params["end"] = self._page.hash + else: + raise ValueError() + + if len(inclusions) > 0: + params["include"] = ",".join(inclusions) + + return params diff --git a/pubnub/endpoints/entities/user/__init__.py b/pubnub/endpoints/entities/user/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pubnub/endpoints/entities/user/create_user.py b/pubnub/endpoints/entities/user/create_user.py deleted file mode 100644 index 506f8f6d..00000000 --- a/pubnub/endpoints/entities/user/create_user.py +++ /dev/null @@ -1,75 +0,0 @@ -from pubnub.endpoints.entities.endpoint import EntitiesEndpoint, UserEndpoint, IncludeCustomEndpoint, \ - CustomAwareEndpoint -from pubnub.enums import PNOperationType -from pubnub.enums import HttpMethod -from pubnub.models.consumer.entities.user import PNCreateUserResult -from pubnub.utils import write_value_as_string - - -class CreateUser(EntitiesEndpoint, UserEndpoint, IncludeCustomEndpoint, CustomAwareEndpoint): - CREATE_USER_PATH = "/v2/objects/%s/uuids/%s" - - def __init__(self, pubnub): - EntitiesEndpoint.__init__(self, pubnub) - UserEndpoint.__init__(self) - IncludeCustomEndpoint.__init__(self) - CustomAwareEndpoint.__init__(self) - - self._name = None - self._email = None - self._external_id = None - self._profile_url = None - - def user_status(self, user_status): - self._status = user_status - self._include_status = True - return self - - def user_type(self, user_type): - self._type = user_type - self._include_type = True - return self - - def set_name(self, name): - self._name = str(name) - return self - - def email(self, email): - self._email = str(email) - return self - - def external_id(self, external_id): - self._external_id = str(external_id) - return self - - def profile_url(self, profile_url): - self._profile_url = str(profile_url) - return self - - def build_path(self): - return CreateUser.CREATE_USER_PATH % (self.pubnub.config.subscribe_key, self._effective_user_id()) - - def build_data(self): - payload = { - "name": self._name, - "email": self._email, - "externalId": self._external_id, - "profileUrl": self._profile_url, - "custom": self._custom - } - return write_value_as_string(payload) - - def validate_specific_params(self): - self._validate_user_id() - - def create_response(self, envelope): - return PNCreateUserResult(envelope) - - def operation_type(self): - return PNOperationType.PNCreateUserOperation - - def name(self): - return "Create User" - - def http_method(self): - return HttpMethod.PATCH diff --git a/pubnub/endpoints/entities/user/fetch_user.py b/pubnub/endpoints/entities/user/fetch_user.py deleted file mode 100644 index 6aa8fc5b..00000000 --- a/pubnub/endpoints/entities/user/fetch_user.py +++ /dev/null @@ -1,31 +0,0 @@ -from pubnub.endpoints.entities.endpoint import EntitiesEndpoint, IncludeCustomEndpoint, UserEndpoint -from pubnub.enums import PNOperationType -from pubnub.enums import HttpMethod -from pubnub.models.consumer.entities.user import PNFetchUserResult - - -class FetchUser(EntitiesEndpoint, UserEndpoint, IncludeCustomEndpoint): - FETCH_USER_PATH = "/v2/objects/%s/uuids/%s" - - def __init__(self, pubnub): - EntitiesEndpoint.__init__(self, pubnub) - UserEndpoint.__init__(self) - IncludeCustomEndpoint.__init__(self) - - def build_path(self): - return FetchUser.FETCH_USER_PATH % (self.pubnub.config.subscribe_key, self._effective_user_id()) - - def validate_specific_params(self): - self._validate_user_id() - - def create_response(self, envelope): - return PNFetchUserResult(envelope) - - def operation_type(self): - return PNOperationType.PNFetchUserOperation - - def name(self): - return "Fetch User" - - def http_method(self): - return HttpMethod.GET diff --git a/pubnub/endpoints/entities/user/fetch_users.py b/pubnub/endpoints/entities/user/fetch_users.py deleted file mode 100644 index cd52ccc1..00000000 --- a/pubnub/endpoints/entities/user/fetch_users.py +++ /dev/null @@ -1,28 +0,0 @@ -from pubnub.endpoints.entities.endpoint import EntitiesEndpoint, ListEndpoint, IncludeCustomEndpoint -from pubnub.enums import PNOperationType -from pubnub.enums import HttpMethod -from pubnub.models.consumer.entities.user import PNFetchUsersResult - - -class FetchUsers(EntitiesEndpoint, ListEndpoint, IncludeCustomEndpoint): - FETCH_USERS_PATH = "/v2/objects/%s/uuids" - - def __init__(self, pubnub): - EntitiesEndpoint.__init__(self, pubnub) - ListEndpoint.__init__(self) - IncludeCustomEndpoint.__init__(self) - - def build_path(self): - return FetchUsers.FETCH_USERS_PATH % self.pubnub.config.subscribe_key - - def create_response(self, envelope): - return PNFetchUsersResult(envelope) - - def operation_type(self): - return PNOperationType.PNFetchUsersOperation - - def name(self): - return "Fetch Users" - - def http_method(self): - return HttpMethod.GET diff --git a/pubnub/endpoints/entities/user/remove_user.py b/pubnub/endpoints/entities/user/remove_user.py deleted file mode 100644 index 5f60f33b..00000000 --- a/pubnub/endpoints/entities/user/remove_user.py +++ /dev/null @@ -1,30 +0,0 @@ -from pubnub.endpoints.entities.endpoint import EntitiesEndpoint, UserEndpoint -from pubnub.enums import PNOperationType -from pubnub.enums import HttpMethod -from pubnub.models.consumer.entities.user import PNRemoveUserResult - - -class RemoveUser(EntitiesEndpoint, UserEndpoint): - REMOVE_USER_PATH = "/v2/objects/%s/uuids/%s" - - def __init__(self, pubnub): - EntitiesEndpoint.__init__(self, pubnub) - UserEndpoint.__init__(self) - - def build_path(self): - return RemoveUser.REMOVE_USER_PATH % (self.pubnub.config.subscribe_key, self._effective_user_id()) - - def validate_specific_params(self): - self._validate_user_id() - - def create_response(self, envelope): - return PNRemoveUserResult(envelope) - - def operation_type(self): - return PNOperationType.PNRemoveUserOperation - - def name(self): - return "Remove User" - - def http_method(self): - return HttpMethod.DELETE diff --git a/pubnub/endpoints/entities/user/update_user.py b/pubnub/endpoints/entities/user/update_user.py deleted file mode 100644 index b5c7abd1..00000000 --- a/pubnub/endpoints/entities/user/update_user.py +++ /dev/null @@ -1,75 +0,0 @@ -from pubnub.endpoints.entities.endpoint import EntitiesEndpoint, UserEndpoint,\ - IncludeCustomEndpoint, CustomAwareEndpoint -from pubnub.enums import PNOperationType -from pubnub.enums import HttpMethod -from pubnub.models.consumer.entities.user import PNUpdateUserResult -from pubnub.utils import write_value_as_string - - -class UpdateUser(EntitiesEndpoint, UserEndpoint, IncludeCustomEndpoint, CustomAwareEndpoint): - UPDATE_USER_PATH = "/v2/objects/%s/uuids/%s" - - def __init__(self, pubnub): - EntitiesEndpoint.__init__(self, pubnub) - UserEndpoint.__init__(self) - IncludeCustomEndpoint.__init__(self) - CustomAwareEndpoint.__init__(self) - - self._name = None - self._email = None - self._external_id = None - self._profile_url = None - - def user_status(self, user_status): - self._status = user_status - self._include_status = True - return self - - def user_type(self, user_type): - self._type = user_type - self._include_type = True - return self - - def set_name(self, name): - self._name = str(name) - return self - - def email(self, email): - self._email = str(email) - return self - - def external_id(self, external_id): - self._external_id = str(external_id) - return self - - def profile_url(self, profile_url): - self._profile_url = str(profile_url) - return self - - def build_path(self): - return UpdateUser.UPDATE_USER_PATH % (self.pubnub.config.subscribe_key, self._effective_user_id()) - - def build_data(self): - payload = { - "name": self._name, - "email": self._email, - "externalId": self._external_id, - "profileUrl": self._profile_url, - "custom": self._custom - } - return write_value_as_string(payload) - - def validate_specific_params(self): - self._validate_user_id() - - def create_response(self, envelope): - return PNUpdateUserResult(envelope) - - def operation_type(self): - return PNOperationType.PNUpdateUserOperation - - def name(self): - return "Update User" - - def http_method(self): - return HttpMethod.PATCH diff --git a/pubnub/enums.py b/pubnub/enums.py index 5dddd2c6..b54ab62e 100644 --- a/pubnub/enums.py +++ b/pubnub/enums.py @@ -6,17 +6,13 @@ class HttpMethod(object): POST = 2 DELETE = 3 PATCH = 4 + PUT = 5 + + mapping = {1: 'GET', 2: 'POST', 3: 'DELETE', 4: 'PATCH', 5: 'PUT'} @classmethod def string(cls, method): - if method == cls.GET: - return "GET" - elif method == cls.POST: - return "POST" - elif method == cls.DELETE: - return "DELETE" - elif method == cls.PATCH: - return "PATCH" + return cls.mapping.get(method, False) class PNStatusCategory(object): @@ -126,6 +122,9 @@ class PNOperationType(object): PNFetchUserMembershipsOperation = 85 PNFetchSpaceMembershipsOperation = 86 + PNUpsertSpaceOperation = 87 + PNUpsertUserOperation = 88 + class PNHeartbeatNotificationOptions(object): NONE = 1 diff --git a/pubnub/models/consumer/entities/result.py b/pubnub/models/consumer/entities/result.py index ae3dcabd..0da6ca19 100644 --- a/pubnub/models/consumer/entities/result.py +++ b/pubnub/models/consumer/entities/result.py @@ -3,7 +3,7 @@ class PNEntityResult(object): def __init__(self, result): - self.data = result["data"] + self.data = result["data"] if "data" in result else None self.status = result["status"] def __str__(self): diff --git a/pubnub/models/consumer/entities/space.py b/pubnub/models/consumer/entities/space.py index e49f3180..435f94c4 100644 --- a/pubnub/models/consumer/entities/space.py +++ b/pubnub/models/consumer/entities/space.py @@ -10,6 +10,10 @@ class PNUpdateSpaceResult(PNEntityResult): _description = "Update Space: %s" +class PNUpsertSpaceResult(PNEntityResult): + _description = "Upsert Space: %s" + + class PNFetchSpaceResult(PNEntityResult): _description = "Fetch Space: %s" diff --git a/pubnub/models/consumer/entities/user.py b/pubnub/models/consumer/entities/user.py index 051748c2..caf15615 100644 --- a/pubnub/models/consumer/entities/user.py +++ b/pubnub/models/consumer/entities/user.py @@ -11,6 +11,10 @@ class PNUpdateUserResult(PNEntityResult): _description = "Update User: %s" +class PNUpsertUserResult(PNEntityResult): + _description = "Upsert User: %s" + + class PNFetchUserResult(PNEntityResult): _description = "Fetch User: %s" diff --git a/pubnub/pubnub_core.py b/pubnub/pubnub_core.py index 604c6302..0b52efd4 100644 --- a/pubnub/pubnub_core.py +++ b/pubnub/pubnub_core.py @@ -4,17 +4,8 @@ from pubnub.endpoints.entities.membership.update_memberships import UpdateSpaceMembers, UpdateUserSpaces from pubnub.endpoints.entities.membership.fetch_memberships import FetchSpaceMemberships, FetchUserMemberships from pubnub.endpoints.entities.membership.remove_memberships import RemoveSpaceMembers, RemoveUserSpaces - -from pubnub.endpoints.entities.space.update_space import UpdateSpace -from pubnub.endpoints.entities.user.create_user import CreateUser -from pubnub.endpoints.entities.space.remove_space import RemoveSpace -from pubnub.endpoints.entities.space.fetch_spaces import FetchSpaces -from pubnub.endpoints.entities.space.fetch_space import FetchSpace -from pubnub.endpoints.entities.space.create_space import CreateSpace -from pubnub.endpoints.entities.user.remove_user import RemoveUser -from pubnub.endpoints.entities.user.update_user import UpdateUser -from pubnub.endpoints.entities.user.fetch_user import FetchUser -from pubnub.endpoints.entities.user.fetch_users import FetchUsers +from pubnub.endpoints.entities.user import CreateUser, FetchUser, FetchUsers, RemoveUser, UpdateUser, UpsertUser +from pubnub.endpoints.entities.space import CreateSpace, FetchSpace, FetchSpaces, RemoveSpace, UpdateSpace, UpsertSpace from pubnub.errors import PNERR_MISUSE_OF_USER_AND_SPACE, PNERR_USER_SPACE_PAIRS_MISSING from pubnub.exceptions import PubNubException from pubnub.features import feature_flag @@ -341,206 +332,8 @@ def _validate_subscribe_manager_enabled(self): """ Entities code -- all of methods bellow should be decorated with pubnub.features.feature_flag """ @feature_flag('PN_ENABLE_ENTITIES') - def create_space( - self, space_id, name=None, description=None, custom=None, space_type=None, space_status=None, sync=None - ): - space = CreateSpace(self).space_id(space_id) - - if name is not None: - space.set_name(name) - - if description is not None: - space.description(description) - - if custom is not None: - space.custom(custom) - - if space_status is not None: - space.space_status(space_status) - - if space_type is not None: - space.space_type(space_type) - - if sync: - return space.sync() - - return space - - @feature_flag('PN_ENABLE_ENTITIES') - def update_space( - self, space_id, name=None, description=None, custom=None, space_type=None, space_status=None, sync=None - ): - space = UpdateSpace(self).space_id(space_id) - - if name is not None: - space.set_name(name) - - if description is not None: - space.description(description) - - if custom is not None: - space.custom(custom) - - if space_status is not None: - space.space_status(space_status) - - if space_type is not None: - space.space_type(space_type) - - if sync: - return space.sync() - - return space - - @feature_flag('PN_ENABLE_ENTITIES') - def remove_space(self, space_id, sync=None): - remove_space = RemoveSpace(self).space_id(space_id) - - if sync: - return remove_space.sync() - - return remove_space - - @feature_flag('PN_ENABLE_ENTITIES') - def fetch_space(self, space_id, include_custom=None, sync=None): - space = FetchSpace(self).space_id(space_id) - - if include_custom is not None: - space.include_custom(include_custom) - - if sync: - return space.sync() - return space - - @feature_flag('PN_ENABLE_ENTITIES') - def fetch_spaces(self, limit=None, page=None, filter=None, sort=None, include_total_count=None, include_custom=None, - sync=None): - - spaces = FetchSpaces(self) - - if limit is not None: - spaces.limit(limit) - - if page is not None: - spaces.page(page) - - if filter is not None: - spaces.filter(filter) - - if sort is not None: - spaces.sort(sort) - - if include_total_count is not None: - spaces.include_total_count(include_total_count) - - if include_custom is not None: - spaces.include_custom(include_custom) - - if sync: - return spaces.sync() - return spaces - - @feature_flag('PN_ENABLE_ENTITIES') - def create_user(self, user_id, name=None, email=None, custom=None, user_type=None, user_status=None, sync=None): - user = CreateUser(self).user_id(user_id) - - if name is not None: - user.set_name(name) - - if email is not None: - user.email(email) - - if custom is not None: - user.custom(custom) - - if user_status is not None: - user.user_status(user_status) - - if user_type is not None: - user.user_type(user_type) - - if sync: - return user.sync() - return user - - @feature_flag('PN_ENABLE_ENTITIES') - def update_user(self, user_id, name=None, email=None, custom=None, user_type=None, user_status=None, sync=None): - user = UpdateUser(self).user_id(user_id) - - if name is not None: - user.set_name(name) - - if email is not None: - user.email(email) - - if custom is not None: - user.custom(custom) - - if user_status is not None: - user.user_status(user_status) - - if user_type is not None: - user.user_type(user_type) - - if sync: - return user.sync() - return user - - @feature_flag('PN_ENABLE_ENTITIES') - def remove_user(self, user_id, sync=None): - user = RemoveUser(self).user_id(user_id) - - if sync: - return user.sync() - return user - - @feature_flag('PN_ENABLE_ENTITIES') - def fetch_user(self, user_id, include_custom=None, sync=None): - user = FetchUser(self).user_id(user_id) - - if include_custom is not None: - user.include_custom(include_custom) - - if sync: - return user.sync() - return user - - @feature_flag('PN_ENABLE_ENTITIES') - def fetch_users(self, limit=None, page=None, filter=None, sort=None, include_total_count=None, include_custom=None, - sync=None): - users = FetchUsers(self) - - if limit is not None: - users.limit(limit) - - if page is not None: - users.page(page) - - if filter is not None: - users.filter(filter) - - if sort is not None: - users.sort(sort) - - if include_total_count is not None: - users.include_total_count(include_total_count) - - if include_custom is not None: - users.include_custom(include_custom) - - if sync: - return users.sync() - return users - - @feature_flag('PN_ENABLE_ENTITIES') - def add_memberships( - self, - user_id: str = None, - users: list = None, - space_id: str = None, - spaces: list = None, - sync=None - ): + def add_memberships(self, user_id: str = None, users: list = None, space_id: str = None, spaces: list = None, + sync: bool = None): if user_id and space_id: raise (PubNubException(pn_error=PNERR_MISUSE_OF_USER_AND_SPACE)) if user_id and spaces: @@ -555,14 +348,8 @@ def add_memberships( return membership @feature_flag('PN_ENABLE_ENTITIES') - def update_memberships( - self, - user_id: str = None, - users: list = None, - space_id: str = None, - spaces: list = None, - sync=None - ): + def update_memberships(self, user_id: str = None, users: list = None, space_id: str = None, spaces: list = None, + sync: bool = None): if user_id and space_id: raise (PubNubException(pn_error=PNERR_MISUSE_OF_USER_AND_SPACE)) if user_id and spaces: @@ -628,3 +415,110 @@ def fetch_memberships(self, user_id: str = None, space_id: str = None, limit=Non if sync: return memberships.sync() return memberships + + @feature_flag('PN_ENABLE_ENTITIES') + def create_user(self, user_id: str, name: str = None, email: str = None, external_id: str = None, + profile_url: str = None, user_type: str = None, user_status: str = None, custom: dict = None, + sync: bool = None): + user = CreateUser(self, user_id, name, email, external_id, profile_url, user_type, user_status, custom) + + if sync: + return user.sync() + return user + + @feature_flag('PN_ENABLE_ENTITIES') + def update_user(self, user_id: str, name: str = None, email: str = None, external_id: str = None, + profile_url: str = None, user_type: str = None, user_status: str = None, custom: dict = None, + sync: bool = None): + user = UpdateUser(self, user_id, name, email, external_id, profile_url, user_type, user_status, custom) + + if sync: + return user.sync() + return user + + @feature_flag('PN_ENABLE_ENTITIES') + def upsert_user(self, user_id: str, name: str = None, email: str = None, external_id: str = None, + profile_url: str = None, user_type: str = None, user_status: str = None, custom: dict = None, + sync: bool = None): + user = UpsertUser(self, user_id, name, email, external_id, profile_url, user_type, user_status, custom) + + if sync: + return user.sync() + return user + + @feature_flag('PN_ENABLE_ENTITIES') + def remove_user(self, user_id: str, sync: bool = None): + user = RemoveUser(self, user_id) + + if sync: + return user.sync() + return user + + @feature_flag('PN_ENABLE_ENTITIES') + def fetch_user(self, user_id: str, include: list = [], sync: bool = None): + user = FetchUser(self, user_id, include) + + if sync: + return user.sync() + return user + + @feature_flag('PN_ENABLE_ENTITIES') + def fetch_users(self, limit: str = None, filter_string: str = None, include_total_count: bool = None, + include_custom: bool = None, page=None, sort_keys=None, sync: bool = None): + user = FetchUsers(self, limit, filter_string, include_total_count, include_custom, page, sort_keys) + + if sync: + return user.sync() + return user + + @feature_flag('PN_ENABLE_ENTITIES') + def create_space(self, space_id: str, name: str = None, description: str = None, space_type: str = None, + space_status: str = None, custom: dict = None, sync: bool = None): + space = CreateSpace(self, space_id, name, description, space_type, space_status, custom) + + if sync: + return space.sync() + return space + + @feature_flag('PN_ENABLE_ENTITIES') + def update_space(self, space_id: str, name: str = None, description: str = None, space_type: str = None, + space_status: str = None, custom: dict = None, sync: bool = None): + space = UpdateSpace(self, space_id, name, description, space_type, space_status, custom) + + if sync: + return space.sync() + return space + + @feature_flag('PN_ENABLE_ENTITIES') + def upsert_space(self, space_id: str, name: str = None, description: str = None, space_type: str = None, + space_status: str = None, custom: dict = None, sync: bool = None): + space = UpsertSpace(self, space_id, name, description, space_type, space_status, custom) + + if sync: + return space.sync() + return space + + @feature_flag('PN_ENABLE_ENTITIES') + def remove_space(self, space_id: str, sync: bool = None): + space = RemoveSpace(self, space_id) + + if sync: + return space.sync() + return space + + @feature_flag('PN_ENABLE_ENTITIES') + def fetch_space(self, space_id: str, include: list = [], sync: bool = None): + space = FetchSpace(self, space_id, include) + + if sync: + return space.sync() + return space + + @feature_flag('PN_ENABLE_ENTITIES') + def fetch_spaces(self, limit: str = None, filter_string: str = None, include_total_count: bool = None, + include_custom: bool = None, page=None, sort_keys=None, sync: bool = None): + spaces = FetchSpaces(self, limit, filter_string, include_total_count, include_custom, page, sort_keys) + + if sync: + return spaces.sync() + return spaces diff --git a/pubnub/request_handlers/requests_handler.py b/pubnub/request_handlers/requests_handler.py index 75fb5512..52548fe8 100644 --- a/pubnub/request_handlers/requests_handler.py +++ b/pubnub/request_handlers/requests_handler.py @@ -243,7 +243,7 @@ def _invoke_request(self, p_options, e_options, base_origin): "allow_redirects": e_options.allow_redirects } - if e_options.is_post() or e_options.is_patch(): + if e_options.is_post() or e_options.is_patch() or e_options.is_put(): args["data"] = e_options.data args["files"] = e_options.files logger.debug("%s %s %s" % ( diff --git a/pubnub/structures.py b/pubnub/structures.py index 036a8d69..29e8e12e 100644 --- a/pubnub/structures.py +++ b/pubnub/structures.py @@ -15,8 +15,8 @@ def __init__( assert isinstance(method, int) assert isinstance(request_timeout, int) assert isinstance(connect_timeout, int) - if not (method is HttpMethod.GET or method is HttpMethod.POST or method is HttpMethod.DELETE - or method is HttpMethod.PATCH): # noqa + + if not HttpMethod.string(method): raise AssertionError() self.params = None @@ -53,6 +53,9 @@ def is_post(self): def is_patch(self): return self._method is HttpMethod.PATCH + def is_put(self): + return self._method is HttpMethod.PUT + def query_list(self): """ All query keys and values should be already encoded inside a build_params() method""" s = [] diff --git a/tests/integrational/fixtures/native_sync/spaces/create_space.yaml b/tests/integrational/fixtures/native_sync/spaces/create_space.yaml new file mode 100644 index 00000000..b11a0c4d --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/create_space.yaml @@ -0,0 +1,83 @@ +interactions: +- request: + body: '{"name": "Trekkies Fan Space", "description": "Live Long and Prosper", + "custom": {"Leader": "Cpt. James ''Jim'' Tiberius Kirk"}, "status": "fanclub", + "type": "nerdy"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '164' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":{"Leader":"Cpt. James ''Jim'' Tiberius Kirk"},"description":"Live + Long and Prosper","externalId":"","id":"Trekkie","name":"Trekkies Fan Space","status":"fanclub","type":"nerdy"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '207' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:20:45 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:20:45 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/spaces/create_space_id_collision.yaml b/tests/integrational/fixtures/native_sync/spaces/create_space_id_collision.yaml new file mode 100644 index 00000000..1aacb67b --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/create_space_id_collision.yaml @@ -0,0 +1,122 @@ +interactions: +- request: + body: '{}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '2' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":null,"description":"","externalId":"","id":"Trekkie","name":"","status":"","type":""},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '117' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:22:04 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "Trekkies Fan Space", "description": "Live Long and Prosper", + "custom": {"Leader": "Cpt. James ''Jim'' Tiberius Kirk"}, "status": "fanclub", + "type": "nerdy"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '164' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"error":{"message":"Requested resource already exists.","source":"metadata"},"status":409}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '91' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:22:04 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 409 + message: Conflict +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:22:04 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/spaces/fetch_space_existing.yaml b/tests/integrational/fixtures/native_sync/spaces/fetch_space_existing.yaml new file mode 100644 index 00000000..b40aa8b4 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/fetch_space_existing.yaml @@ -0,0 +1,120 @@ +interactions: +- request: + body: '{"name": "Trekkies Fan Space", "description": "Live Long and Prosper", + "custom": {"Leader": "Cpt. James ''Jim'' Tiberius Kirk"}, "status": "fanclub", + "type": "nerdy"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '164' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":{"Leader":"Cpt. James ''Jim'' Tiberius Kirk"},"description":"Live + Long and Prosper","externalId":"","id":"Trekkie","name":"Trekkies Fan Space","status":"fanclub","type":"nerdy"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '207' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:28:14 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - PubNub-Python/6.5.1 + method: GET + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":{"Leader":"Cpt. James ''Jim'' Tiberius Kirk"},"description":"Live + Long and Prosper","externalId":"","id":"Trekkie","name":"Trekkies Fan Space","status":"fanclub","type":"nerdy"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '207' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:28:14 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:28:14 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/spaces/fetch_space_not_existing.yaml b/tests/integrational/fixtures/native_sync/spaces/fetch_space_not_existing.yaml new file mode 100644 index 00000000..8f006adb --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/fetch_space_not_existing.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - PubNub-Python/6.5.1 + method: GET + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"error":{"message":"Requested resource not found.","source":"metadata"},"status":404}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '86' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:28:15 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 404 + message: Not Found +version: 1 diff --git a/tests/integrational/fixtures/native_sync/spaces/fetch_spaces_existing.yaml b/tests/integrational/fixtures/native_sync/spaces/fetch_spaces_existing.yaml new file mode 100644 index 00000000..c632bd57 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/fetch_spaces_existing.yaml @@ -0,0 +1,120 @@ +interactions: +- request: + body: '{"name": "Trekkies Fan Space", "description": "Live Long and Prosper", + "custom": {"Leader": "Cpt. James ''Jim'' Tiberius Kirk"}, "status": "fanclub", + "type": "nerdy"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '164' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":{"Leader":"Cpt. James ''Jim'' Tiberius Kirk"},"description":"Live + Long and Prosper","externalId":"","id":"Trekkie","name":"Trekkies Fan Space","status":"fanclub","type":"nerdy"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '207' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:45:18 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - PubNub-Python/6.5.1 + method: GET + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces?uuid=uuid-mock + response: + body: + string: '{"data":[{"custom":{"Leader":"Cpt. James ''Jim'' Tiberius Kirk"},"description":"Live + Long and Prosper","externalId":"","id":"Trekkie","name":"Trekkies Fan Space","status":"fanclub","type":"nerdy"}],"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '209' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:45:19 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:45:19 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/spaces/fetch_spaces_multiple.yaml b/tests/integrational/fixtures/native_sync/spaces/fetch_spaces_multiple.yaml new file mode 100644 index 00000000..7257873a --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/fetch_spaces_multiple.yaml @@ -0,0 +1,272 @@ +interactions: +- request: + body: '{}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '2' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PUT + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/EuclideanSpace?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":null,"description":"","externalId":"","id":"EuclideanSpace","name":"","status":"","type":""},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '124' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:55:53 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '2' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PUT + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/BanachSpace?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":null,"description":"","externalId":"","id":"BanachSpace","name":"","status":"","type":""},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '121' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:55:53 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '2' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PUT + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/HausdorffSpace?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":null,"description":"","externalId":"","id":"HausdorffSpace","name":"","status":"","type":""},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '124' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:55:54 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - PubNub-Python/6.5.1 + method: GET + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces?uuid=uuid-mock + response: + body: + string: '{"data":[{"custom":null,"description":"","externalId":"","id":"BanachSpace","name":"","status":"","type":""},{"custom":null,"description":"","externalId":"","id":"EuclideanSpace","name":"","status":"","type":""},{"custom":null,"description":"","externalId":"","id":"HausdorffSpace","name":"","status":"","type":""}],"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '329' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:55:54 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/EuclideanSpace?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:55:54 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/BanachSpace?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:55:54 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/HausdorffSpace?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:55:54 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/spaces/fetch_spaces_not_existing.yaml b/tests/integrational/fixtures/native_sync/spaces/fetch_spaces_not_existing.yaml new file mode 100644 index 00000000..95e58527 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/fetch_spaces_not_existing.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - PubNub-Python/6.5.1 + method: GET + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces?uuid=uuid-mock + response: + body: + string: '{"error":{"message":"Requested resource not found.","source":"metadata"},"status":404}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '86' + Content-Type: + - application/json + Date: + - Tue, 20 Sep 2022 09:46:40 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 404 + message: Not Found +version: 1 diff --git a/tests/integrational/fixtures/native_sync/spaces/update_space.yaml b/tests/integrational/fixtures/native_sync/spaces/update_space.yaml new file mode 100644 index 00000000..909bd338 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/update_space.yaml @@ -0,0 +1,123 @@ +interactions: +- request: + body: '{}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '2' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":null,"description":"","externalId":"","id":"Trekkie","name":"","status":"","type":""},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '117' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:20:47 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "Trekkies Fan Space", "description": "Live Long and Prosper", + "custom": {"Leader": "Cpt. James ''Jim'' Tiberius Kirk"}, "status": "fanclub", + "type": "nerdy"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '164' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PATCH + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":{"Leader":"Cpt. James ''Jim'' Tiberius Kirk"},"description":"Live + Long and Prosper","externalId":"","id":"Trekkie","name":"Trekkies Fan Space","status":"fanclub","type":"nerdy"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '207' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:20:47 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:20:47 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/spaces/update_space_id_missing.yaml b/tests/integrational/fixtures/native_sync/spaces/update_space_id_missing.yaml new file mode 100644 index 00000000..26462e40 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/update_space_id_missing.yaml @@ -0,0 +1,82 @@ +interactions: +- request: + body: '{"name": "Trekkies Fan Space", "description": "Live Long and Prosper", + "custom": {"Leader": "Cpt. James ''Jim'' Tiberius Kirk"}, "status": "fanclub", + "type": "nerdy"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '164' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PATCH + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"error":{"message":"Requested resource does not exists.","source":"metadata"},"status":404}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '92' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:22:05 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 404 + message: Not Found +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:22:05 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/spaces/upsert_space.yaml b/tests/integrational/fixtures/native_sync/spaces/upsert_space.yaml new file mode 100644 index 00000000..07ddb70b --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/upsert_space.yaml @@ -0,0 +1,83 @@ +interactions: +- request: + body: '{"name": "Trekkies Fan Space", "description": "Live Long and Prosper", + "custom": {"Leader": "Cpt. James ''Jim'' Tiberius Kirk"}, "status": "fanclub", + "type": "nerdy"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '164' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PUT + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":{"Leader":"Cpt. James ''Jim'' Tiberius Kirk"},"description":"Live + Long and Prosper","externalId":"","id":"Trekkie","name":"Trekkies Fan Space","status":"fanclub","type":"nerdy"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '207' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:20:49 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:20:49 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/spaces/upsert_update_space.yaml b/tests/integrational/fixtures/native_sync/spaces/upsert_update_space.yaml new file mode 100644 index 00000000..c347410e --- /dev/null +++ b/tests/integrational/fixtures/native_sync/spaces/upsert_update_space.yaml @@ -0,0 +1,123 @@ +interactions: +- request: + body: '{}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '2' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":null,"description":"","externalId":"","id":"Trekkie","name":"","status":"","type":""},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '117' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:22:06 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "Trekkies Fan Space", "description": "Live Long and Prosper", + "custom": {"Leader": "Cpt. James ''Jim'' Tiberius Kirk"}, "status": "fanclub", + "type": "nerdy"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '164' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PUT + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"data":{"custom":{"Leader":"Cpt. James ''Jim'' Tiberius Kirk"},"description":"Live + Long and Prosper","externalId":"","id":"Trekkie","name":"Trekkies Fan Space","status":"fanclub","type":"nerdy"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '207' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:22:06 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/spaces/Trekkie?uuid=uuid-mock + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Fri, 16 Sep 2022 13:22:06 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/create_user.yaml b/tests/integrational/fixtures/native_sync/users/create_user.yaml new file mode 100644 index 00000000..138b5f87 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/create_user.yaml @@ -0,0 +1,83 @@ +interactions: +- request: + body: '{"name": "Ada Lovelace", "email": "ada.lovelace@user.id", "externalId": + "x1x2x3", "profileUrl": "https://eee.ee/eeee/e/ee.e", "custom": {"dob": "12/10/1815"}, + "status": "legend", "type": "programmer"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '200' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/users/AdaLovelace + response: + body: + string: '{"data":{"custom":{"dob":"12/10/1815"},"email":"ada.lovelace@user.id","externalId":"x1x2x3","id":"AdaLovelace","name":"Ada + Lovelace","profileUrl":"https://eee.ee/eeee/e/ee.e","status":"legend","type":"programmer"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '227' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:49:02 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/AdaLovelace + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:49:03 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/create_user_id_collision.yaml b/tests/integrational/fixtures/native_sync/users/create_user_id_collision.yaml new file mode 100644 index 00000000..a45eb4c2 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/create_user_id_collision.yaml @@ -0,0 +1,123 @@ +interactions: +- request: + body: '{"name": "None", "email": "None", "externalId": "None", "profileUrl": "None", + "custom": null, "status": "None", "type": "None"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '127' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/users/JosephMarieJacquard + response: + body: + string: '{"data":{"custom":null,"email":"None","externalId":"None","id":"JosephMarieJacquard","name":"None","profileUrl":"None","status":"None","type":"None"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '163' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 15:26:01 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "Joseph Marie Jacquard", "email": "jmjacquard@user.id", "externalId": + "None", "profileUrl": "None", "custom": {"dob": "1752-07-07"}, "status": "legend", + "type": "inventor"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '181' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/users/JosephMarieJacquard + response: + body: + string: '{"error":{"message":"Requested resource already exists.","source":"metadata"},"status":409}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '91' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 15:26:01 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 409 + message: Conflict +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/JosephMarieJacquard + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 15:26:02 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/fetch_user_existing.yaml b/tests/integrational/fixtures/native_sync/users/fetch_user_existing.yaml new file mode 100644 index 00000000..159f338e --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/fetch_user_existing.yaml @@ -0,0 +1,158 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/GraceBrewsterMurrayHopper + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 15:59:36 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "Grace Brewster Murray Hopper", "email": "admiral.grace@user.id", + "externalId": "None", "profileUrl": "None", "custom": {"dob": "1906-12-09"}, + "status": "legend", "type": "debugger"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '191' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/users/GraceBrewsterMurrayHopper + response: + body: + string: '{"data":{"custom":{"dob":"1906-12-09"},"email":"admiral.grace@user.id","externalId":"None","id":"GraceBrewsterMurrayHopper","name":"Grace + Brewster Murray Hopper","profileUrl":"None","status":"legend","type":"debugger"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '232' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 15:59:36 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - PubNub-Python/6.5.1 + method: GET + uri: https://test.ps.pn/v3/objects/sub-c-test/users/GraceBrewsterMurrayHopper + response: + body: + string: '{"data":{"custom":{"dob":"1906-12-09"},"email":"admiral.grace@user.id","externalId":"None","id":"GraceBrewsterMurrayHopper","name":"Grace + Brewster Murray Hopper","profileUrl":"None","status":"legend","type":"debugger"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '232' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 15:59:36 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/GraceBrewsterMurrayHopper + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 15:59:36 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/fetch_user_not_existing.yaml b/tests/integrational/fixtures/native_sync/users/fetch_user_not_existing.yaml new file mode 100644 index 00000000..ec168a48 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/fetch_user_not_existing.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - PubNub-Python/6.5.1 + method: GET + uri: https://test.ps.pn/v3/objects/sub-c-test/users/JamesTiberiusKirk%20 + response: + body: + string: '{"error":{"message":"Requested resource not found.","source":"metadata"},"status":404}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '86' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 15:59:37 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 404 + message: Not Found +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/fetch_users_existing.yaml b/tests/integrational/fixtures/native_sync/users/fetch_users_existing.yaml new file mode 100644 index 00000000..65170152 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/fetch_users_existing.yaml @@ -0,0 +1,158 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/GraceBrewsterMurrayHopper + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:12:14 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "Grace Brewster Murray Hopper", "email": "admiral.grace@user.id", + "externalId": "None", "profileUrl": "None", "custom": {"dob": "1906-12-09"}, + "status": "legend", "type": "debugger"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '191' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/users/GraceBrewsterMurrayHopper + response: + body: + string: '{"data":{"custom":{"dob":"1906-12-09"},"email":"admiral.grace@user.id","externalId":"None","id":"GraceBrewsterMurrayHopper","name":"Grace + Brewster Murray Hopper","profileUrl":"None","status":"legend","type":"debugger"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '232' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:12:14 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - PubNub-Python/6.5.1 + method: GET + uri: https://test.ps.pn/v3/objects/sub-c-test/users + response: + body: + string: '{"data":[{"custom":{"dob":"1906-12-09"},"email":"admiral.grace@user.id","externalId":"None","id":"GraceBrewsterMurrayHopper","name":"Grace + Brewster Murray Hopper","profileUrl":"None","status":"legend","type":"debugger"}],"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '234' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:12:14 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/GraceBrewsterMurrayHopper + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:12:14 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/fetch_users_multiple.yaml b/tests/integrational/fixtures/native_sync/users/fetch_users_multiple.yaml new file mode 100644 index 00000000..4af74b50 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/fetch_users_multiple.yaml @@ -0,0 +1,275 @@ +interactions: +- request: + body: '{"name": "None", "email": "None", "externalId": "None", "profileUrl": "None", + "custom": null, "status": "None", "type": "None"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '127' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PUT + uri: https://test.ps.pn/v3/objects/sub-c-test/users/GraceBrewsterMurrayHopper + response: + body: + string: '{"data":{"custom":null,"email":"None","externalId":"None","id":"GraceBrewsterMurrayHopper","name":"None","profileUrl":"None","status":"None","type":"None"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '169' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:51:14 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "None", "email": "None", "externalId": "None", "profileUrl": "None", + "custom": null, "status": "None", "type": "None"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '127' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PUT + uri: https://test.ps.pn/v3/objects/sub-c-test/users/MargaretHeafieldHamilton + response: + body: + string: '{"data":{"custom":null,"email":"None","externalId":"None","id":"MargaretHeafieldHamilton","name":"None","profileUrl":"None","status":"None","type":"None"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '168' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:51:15 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "None", "email": "None", "externalId": "None", "profileUrl": "None", + "custom": null, "status": "None", "type": "None"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '127' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PUT + uri: https://test.ps.pn/v3/objects/sub-c-test/users/FranBlanche + response: + body: + string: '{"data":{"custom":null,"email":"None","externalId":"None","id":"FranBlanche","name":"None","profileUrl":"None","status":"None","type":"None"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '155' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:51:15 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - PubNub-Python/6.5.1 + method: GET + uri: https://test.ps.pn/v3/objects/sub-c-test/users + response: + body: + string: '{"data":[{"custom":null,"email":"None","externalId":"None","id":"FranBlanche","name":"None","profileUrl":"None","status":"None","type":"None"},{"custom":null,"email":"None","externalId":"None","id":"GraceBrewsterMurrayHopper","name":"None","profileUrl":"None","status":"None","type":"None"},{"custom":null,"email":"None","externalId":"None","id":"MargaretHeafieldHamilton","name":"None","profileUrl":"None","status":"None","type":"None"}],"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '452' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:51:15 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/GraceBrewsterMurrayHopper + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:51:15 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/MargaretHeafieldHamilton + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:51:15 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/FranBlanche + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:51:16 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/fetch_users_not_existing.yaml b/tests/integrational/fixtures/native_sync/users/fetch_users_not_existing.yaml new file mode 100644 index 00000000..e2607fba --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/fetch_users_not_existing.yaml @@ -0,0 +1,38 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - PubNub-Python/6.5.1 + method: GET + uri: https://test.ps.pn/v3/objects/sub-c-test/users + response: + body: + string: '{"error":{"message":"Requested resource not found.","source":"metadata"},"status":404}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '86' + Content-Type: + - application/json + Date: + - Wed, 07 Sep 2022 19:13:26 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 404 + message: Not Found +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/update_user.yaml b/tests/integrational/fixtures/native_sync/users/update_user.yaml new file mode 100644 index 00000000..75b30549 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/update_user.yaml @@ -0,0 +1,124 @@ +interactions: +- request: + body: '{"name": "None", "email": "None", "externalId": "None", "profileUrl": "None", + "custom": null, "status": "None", "type": "None"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '127' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/users/AdaLovelace + response: + body: + string: '{"data":{"custom":null,"email":"None","externalId":"None","id":"AdaLovelace","name":"None","profileUrl":"None","status":"None","type":"None"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '155' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:49:03 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "Ada Lovelace", "email": "ada.lovelace@user.id", "externalId": + "None", "profileUrl": "None", "custom": {"dob": "1815-12-10"}, "status": "legend", + "type": "programmer"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '176' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PATCH + uri: https://test.ps.pn/v3/objects/sub-c-test/users/AdaLovelace + response: + body: + string: '{"data":{"custom":{"dob":"1815-12-10"},"email":"ada.lovelace@user.id","externalId":"None","id":"AdaLovelace","name":"Ada + Lovelace","profileUrl":"None","status":"legend","type":"programmer"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '203' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:49:04 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/AdaLovelace + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:49:04 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/update_user_id_missing.yaml b/tests/integrational/fixtures/native_sync/users/update_user_id_missing.yaml new file mode 100644 index 00000000..8d15b8bb --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/update_user_id_missing.yaml @@ -0,0 +1,120 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/StevenPaulJobs + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Thu, 08 Sep 2022 16:19:27 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "Steven Paul Jobs", "email": "steve-j@user.id", "externalId": + "None", "profileUrl": "None", "custom": {"dob": "1955-02-24"}, "status": "guru", + "type": "entrepreneur"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '175' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PATCH + uri: https://test.ps.pn/v3/objects/sub-c-test/users/StevenPaulJobs + response: + body: + string: '{"error":{"message":"Requested resource does not exists.","source":"metadata"},"status":404}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '92' + Content-Type: + - application/json + Date: + - Thu, 08 Sep 2022 16:19:27 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 404 + message: Not Found +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/StevenPaulJobs + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Thu, 08 Sep 2022 16:19:28 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/upsert_create_user.yaml b/tests/integrational/fixtures/native_sync/users/upsert_create_user.yaml new file mode 100644 index 00000000..b3815958 --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/upsert_create_user.yaml @@ -0,0 +1,121 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/CharlesBabbage + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:52:58 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "Charles Babbage", "email": "charlie.b@user.id", "externalId": + "None", "profileUrl": "None", "custom": {"dob": "1791-12-26"}, "status": "legend", + "type": "genius"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '172' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PUT + uri: https://test.ps.pn/v3/objects/sub-c-test/users/CharlesBabbage + response: + body: + string: '{"data":{"custom":{"dob":"1791-12-26"},"email":"charlie.b@user.id","externalId":"None","id":"CharlesBabbage","name":"Charles + Babbage","profileUrl":"None","status":"legend","type":"genius"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '202' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:52:58 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/CharlesBabbage + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:52:59 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/fixtures/native_sync/users/upsert_update_user.yaml b/tests/integrational/fixtures/native_sync/users/upsert_update_user.yaml new file mode 100644 index 00000000..ce02526d --- /dev/null +++ b/tests/integrational/fixtures/native_sync/users/upsert_update_user.yaml @@ -0,0 +1,124 @@ +interactions: +- request: + body: '{"name": "None", "email": "None", "externalId": "None", "profileUrl": "None", + "custom": null, "status": "None", "type": "None"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '127' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: POST + uri: https://test.ps.pn/v3/objects/sub-c-test/users/CharlesBabbage + response: + body: + string: '{"data":{"custom":null,"email":"None","externalId":"None","id":"CharlesBabbage","name":"None","profileUrl":"None","status":"None","type":"None"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '158' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:52:59 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: '{"name": "Charles Babbage", "email": "charlie.b@user.id", "externalId": + "None", "profileUrl": "None", "custom": {"dob": "1791-12-26"}, "status": "legend", + "type": "genius"}' + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '172' + Content-type: + - application/json + User-Agent: + - PubNub-Python/6.5.1 + method: PUT + uri: https://test.ps.pn/v3/objects/sub-c-test/users/CharlesBabbage + response: + body: + string: '{"data":{"custom":{"dob":"1791-12-26"},"email":"charlie.b@user.id","externalId":"None","id":"CharlesBabbage","name":"Charles + Babbage","profileUrl":"None","status":"legend","type":"genius"},"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '202' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:53:00 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + Content-Length: + - '0' + User-Agent: + - PubNub-Python/6.5.1 + method: DELETE + uri: https://test.ps.pn/v3/objects/sub-c-test/users/CharlesBabbage + response: + body: + string: '{"status":200}' + headers: + Access-Control-Allow-Credentials: + - 'true' + Connection: + - keep-alive + Content-Length: + - '14' + Content-Type: + - application/json + Date: + - Tue, 06 Sep 2022 14:53:00 GMT + access-control-allow-origin: + - '*' + vary: + - origin + - access-control-request-method + - access-control-request-headers + status: + code: 200 + message: OK +version: 1 diff --git a/tests/integrational/native_sync/test_spaces.py b/tests/integrational/native_sync/test_spaces.py new file mode 100644 index 00000000..9a815e33 --- /dev/null +++ b/tests/integrational/native_sync/test_spaces.py @@ -0,0 +1,240 @@ +import logging +import unittest + +import pubnub +from pubnub.models.consumer.entities.space import PNCreateSpaceResult, PNFetchSpaceResult, PNFetchSpacesResult, \ + PNUpdateSpaceResult, PNUpsertSpaceResult + +from pubnub.pubnub import PubNub +from pubnub.exceptions import PubNubException +from tests.helper import pnconf_pam_copy +from tests.integrational.vcr_helper import pn_vcr + + +pubnub.set_stream_logger('pubnub', logging.WARNING) + + +class TestPubNubUsers(unittest.TestCase): + def get_config(self): + config = pnconf_pam_copy() + config.origin = 'test.ps.pn' + config.subscribe_key = 'sub-c-test' + return config + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/create_space.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_create_space(self): + test_space_id = 'Trekkie' + pubnub = PubNub(self.get_config()) + + create = pubnub.create_space(test_space_id, + name='Trekkies Fan Space', + description='Live Long and Prosper', + space_type='nerdy', + space_status='fanclub', + custom={'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'}, + sync=True) + + assert isinstance(create.result, PNCreateSpaceResult) + assert 'custom' in create.result.data + assert {'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'} == create.result.data['custom'] + + pubnub.remove_space(test_space_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/update_space.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_update_space(self): + test_space_id = 'Trekkie' + pubnub = PubNub(self.get_config()) + + pubnub.create_space(test_space_id, sync=True) + + update = pubnub.update_space(test_space_id, + name='Trekkies Fan Space', + description='Live Long and Prosper', + space_type='nerdy', + space_status='fanclub', + custom={'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'}, + sync=True) + + assert isinstance(update.result, PNUpdateSpaceResult) + assert 'custom' in update.result.data + assert {'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'} == update.result.data['custom'] + + pubnub.remove_space(test_space_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/upsert_space.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_upsert_create_space(self): + test_space_id = 'Trekkie' + pubnub = PubNub(self.get_config()) + + upsert = pubnub.upsert_space(test_space_id, + name='Trekkies Fan Space', + description='Live Long and Prosper', + space_type='nerdy', + space_status='fanclub', + custom={'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'}, + sync=True) + + assert isinstance(upsert.result, PNUpsertSpaceResult) + assert 'custom' in upsert.result.data + assert {'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'} == upsert.result.data['custom'] + + pubnub.remove_space(test_space_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/upsert_update_space.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_upsert_update_space(self): + test_space_id = 'Trekkie' + pubnub = PubNub(self.get_config()) + + pubnub.create_space(test_space_id, sync=True) + + upsert = pubnub.upsert_space(test_space_id, + name='Trekkies Fan Space', + description='Live Long and Prosper', + space_type='nerdy', + space_status='fanclub', + custom={'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'}, + sync=True) + + assert isinstance(upsert.result, PNUpsertSpaceResult) + assert 'custom' in upsert.result.data + assert {'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'} == upsert.result.data['custom'] + + pubnub.remove_space(test_space_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/create_space_id_collision.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_create_space_id_collision(self): + test_space_id = 'Trekkie' + pubnub = PubNub(self.get_config()) + + pubnub.create_space(test_space_id, sync=True) + with self.assertRaises(PubNubException) as context: + pubnub.create_space(test_space_id, + name='Trekkies Fan Space', + description='Live Long and Prosper', + space_type='nerdy', + space_status='fanclub', + custom={'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'}, + sync=True) + + self.assertEqual( + '{"error":{"message":"Requested resource already exists.","source":"metadata"},"status":409}', + context.exception._errormsg + ) + self.assertEqual(409, context.exception._status_code) + + pubnub.remove_space(test_space_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/update_space_id_missing.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_update_space_id_missing(self): + test_space_id = 'Trekkie' + pubnub = PubNub(self.get_config()) + + with self.assertRaises(PubNubException) as context: + pubnub.update_space(test_space_id, + name='Trekkies Fan Space', + description='Live Long and Prosper', + space_type='nerdy', + space_status='fanclub', + custom={'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'}, + sync=True) + + self.assertEqual( + '{"error":{"message":"Requested resource does not exists.","source":"metadata"},"status":404}', + context.exception._errormsg + ) + self.assertEqual(404, context.exception._status_code) + + pubnub.remove_space(test_space_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/fetch_space_existing.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_fetch_space_existing(self): + test_space_id = 'Trekkie' + pubnub = PubNub(self.get_config()) + pubnub.create_space(test_space_id, + name='Trekkies Fan Space', + description='Live Long and Prosper', + space_type='nerdy', + space_status='fanclub', + custom={'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'}, + sync=True) + space = pubnub.fetch_space(test_space_id, sync=True) + + self.assertIs(type(space.result), PNFetchSpaceResult) + self.assertTrue("custom" in space.result.data.keys()) + self.assertEqual({'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'}, space.result.data["custom"]) + pubnub.remove_space(test_space_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/fetch_space_not_existing.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_fetch_space_not_existing(self): + test_space_id = 'Trekkie' + pubnub = PubNub(self.get_config()) + + with self.assertRaises(PubNubException) as context: + pubnub.fetch_space(test_space_id, sync=True) + + self.assertEqual( + '{"error":{"message":"Requested resource not found.","source":"metadata"},"status":404}', + context.exception._errormsg + ) + self.assertEqual(404, context.exception._status_code) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/fetch_spaces_existing.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_fetch_spaces_existing(self): + test_space_id = 'Trekkie' + pubnub = PubNub(self.get_config()) + + pubnub.create_space(test_space_id, + name='Trekkies Fan Space', + description='Live Long and Prosper', + space_type='nerdy', + space_status='fanclub', + custom={'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'}, + sync=True) + spaces = pubnub.fetch_spaces(sync=True) + + self.assertIs(type(spaces.result), PNFetchSpacesResult) + self.assertEqual(1, len(spaces.result.data)) + self.assertEqual(spaces.result.data[0]['id'], test_space_id) + self.assertTrue("custom" in spaces.result.data[0].keys()) + self.assertEqual({'Leader': 'Cpt. James \'Jim\' Tiberius Kirk'}, spaces.result.data[0]["custom"]) + pubnub.remove_space(test_space_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/fetch_spaces_not_existing.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_fetch_spaces_not_existing(self): + + pubnub = PubNub(self.get_config()) + + with self.assertRaises(PubNubException) as context: + pubnub.fetch_spaces(sync=True) + + self.assertEqual( + '{"error":{"message":"Requested resource not found.","source":"metadata"},"status":404}', + context.exception._errormsg + ) + self.assertEqual(404, context.exception._status_code) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/spaces/fetch_spaces_multiple.yaml', + filter_query_parameters=['pnsdk', 'signature', 'timestamp']) + def test_fetch_spaces_multiple(self): + pubnub = PubNub(self.get_config()) + test_spaces = ['EuclideanSpace', 'BanachSpace', 'HausdorffSpace'] + for space in test_spaces: + pubnub.upsert_space(space, sync=True) + + spaces = pubnub.fetch_spaces(sync=True) + + self.assertIs(type(spaces.result), PNFetchSpacesResult) + self.assertEqual(3, len(spaces.result.data)) + + for space in test_spaces: + pubnub.remove_space(space, sync=True) diff --git a/tests/integrational/native_sync/test_users.py b/tests/integrational/native_sync/test_users.py new file mode 100644 index 00000000..8fe83a11 --- /dev/null +++ b/tests/integrational/native_sync/test_users.py @@ -0,0 +1,275 @@ +import logging +import unittest + +import pubnub +from pubnub.models.consumer.entities.user import PNCreateUserResult, PNFetchUserResult, PNFetchUsersResult, \ + PNUpdateUserResult, PNUpsertUserResult +from pubnub.pubnub import PubNub +from pubnub.exceptions import PubNubException +from tests.helper import pnconf_pam_copy +from tests.integrational.vcr_helper import pn_vcr + + +pubnub.set_stream_logger('pubnub', logging.WARNING) + + +class TestPubNubUsers(unittest.TestCase): + def get_config(self): + config = pnconf_pam_copy() + config.origin = 'test.ps.pn' + config.subscribe_key = 'sub-c-test' + return config + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/create_user.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_create_user(self): + test_user_id = 'AdaLovelace' + pubnub = PubNub(self.get_config()) + + create = pubnub.create_user( + user_id=test_user_id, + name='Ada Lovelace', + email='ada.lovelace@user.id', + user_type='programmer', + user_status='legend', + profile_url='https://eee.ee/eeee/e/ee.e', + external_id='x1x2x3', + custom={ + 'dob': '12/10/1815' + }, + sync=True + ) + + assert isinstance(create.result, PNCreateUserResult) + assert 'custom' in create.result.data + assert {'dob': '12/10/1815'} == create.result.data['custom'] + + pubnub.remove_user(test_user_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/update_user.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_update_user(self): + test_user_id = 'AdaLovelace' + pubnub = PubNub(self.get_config()) + pubnub.create_user(test_user_id, sync=True) + + update = pubnub.update_user( + user_id=test_user_id, + name='Ada Lovelace', + email='ada.lovelace@user.id', + user_type='programmer', + user_status='legend', + custom={ + 'dob': '1815-12-10' + }, + sync=True + ) + + assert isinstance(update.result, PNUpdateUserResult) + assert 'custom' in update.result.data + assert {'dob': '1815-12-10'} == update.result.data['custom'] + + pubnub.remove_user(test_user_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/upsert_create_user.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_upsert_create_user(self): + pubnub = PubNub(self.get_config()) + test_user_id = 'CharlesBabbage' + + pubnub.remove_user(test_user_id, sync=True) + + update = pubnub.upsert_user( + user_id=test_user_id, + name='Charles Babbage', + email='charlie.b@user.id', + user_type='genius', + user_status='legend', + custom={ + 'dob': '1791-12-26' + }, + sync=True + ) + + assert isinstance(update.result, PNUpsertUserResult) + assert 'custom' in update.result.data + assert {'dob': '1791-12-26'} == update.result.data['custom'] + + pubnub.remove_user(test_user_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/upsert_update_user.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_upsert_update_user(self): + pubnub = PubNub(self.get_config()) + test_user_id = 'CharlesBabbage' + + pubnub.create_user(test_user_id, sync=True) + + update = pubnub.upsert_user( + user_id=test_user_id, + name='Charles Babbage', + email='charlie.b@user.id', + user_type='genius', + user_status='legend', + custom={ + 'dob': '1791-12-26' + }, + sync=True + ) + + assert isinstance(update.result, PNUpsertUserResult) + assert 'custom' in update.result.data + assert {'dob': '1791-12-26'} == update.result.data['custom'] + + pubnub.remove_user(test_user_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/create_user_id_collision.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_create_user_id_collision(self): + pubnub = PubNub(self.get_config()) + test_user_id = 'JosephMarieJacquard' + + pubnub.create_user(test_user_id, sync=True) + + with self.assertRaises(PubNubException) as context: + + pubnub.create_user( + user_id=test_user_id, + name='Joseph Marie Jacquard', + email='jmjacquard@user.id', + user_type='inventor', + user_status='legend', + custom={ + 'dob': '1752-07-07' + }, + sync=True + ) + + self.assertEqual( + '{"error":{"message":"Requested resource already exists.","source":"metadata"},"status":409}', + context.exception._errormsg + ) + self.assertEqual(409, context.exception._status_code) + + pubnub.remove_user(test_user_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/update_user_id_missing.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_update_user_id_missing(self): + pubnub = PubNub(self.get_config()) + test_user_id = 'StevenPaulJobs' + + pubnub.remove_user(test_user_id, sync=True) + + with self.assertRaises(PubNubException) as context: + pubnub.update_user( + user_id=test_user_id, + name='Steven Paul Jobs', + email='steve-j@user.id', + user_type='entrepreneur', + user_status='guru', + custom={ + 'dob': '1955-02-24' + }, + sync=True + ) + + self.assertEqual( + '{"error":{"message":"Requested resource does not exists.","source":"metadata"},"status":404}', + context.exception._errormsg + ) + self.assertEqual(404, context.exception._status_code) + + pubnub.remove_user(test_user_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/fetch_user_existing.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_fetch_user_existing(self): + pubnub = PubNub(self.get_config()) + test_user_id = 'GraceBrewsterMurrayHopper' + pubnub.remove_user(test_user_id, sync=True) + pubnub.create_user(user_id=test_user_id, name='Grace Brewster Murray Hopper', email='admiral.grace@user.id', + user_type='debugger', user_status='legend', custom={'dob': '1906-12-09'}, sync=True) + + user = pubnub.fetch_user(test_user_id, sync=True) + self.assertIs(type(user.result), PNFetchUserResult) + self.assertTrue("custom" in user.result.data.keys()) + self.assertEqual({'dob': '1906-12-09'}, user.result.data["custom"]) + + pubnub.remove_user(test_user_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/fetch_user_not_existing.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_fetch_user_not_existing(self): + pubnub = PubNub(self.get_config()) + test_user_id = 'JamesTiberiusKirk ' + + with self.assertRaises(PubNubException) as context: + pubnub.fetch_user(test_user_id, sync=True) + + self.assertEqual( + '{"error":{"message":"Requested resource not found.","source":"metadata"},"status":404}', + context.exception._errormsg + ) + self.assertEqual(404, context.exception._status_code) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/fetch_users_existing.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_fetch_users_existing(self): + pubnub = PubNub(self.get_config()) + test_user_id = 'GraceBrewsterMurrayHopper' + + pubnub.remove_user(test_user_id, sync=True) + pubnub.create_user(user_id=test_user_id, name='Grace Brewster Murray Hopper', email='admiral.grace@user.id', + user_type='debugger', user_status='legend', custom={'dob': '1906-12-09'}, sync=True) + + users = pubnub.fetch_users(sync=True) + self.assertTrue(isinstance(users.result, PNFetchUsersResult)) + self.assertEqual(1, len(users.result.data)) + self.assertEqual(users.result.data[0]['id'], test_user_id) + + pubnub.remove_user(test_user_id, sync=True) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/fetch_users_not_existing.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_fetch_users_not_existing(self): + pubnub = PubNub(self.get_config()) + + with self.assertRaises(PubNubException) as context: + pubnub.fetch_users(sync=True) + + self.assertEqual( + '{"error":{"message":"Requested resource not found.","source":"metadata"},"status":404}', + context.exception._errormsg + ) + self.assertEqual(404, context.exception._status_code) + + @pn_vcr.use_cassette('tests/integrational/fixtures/native_sync/users/fetch_users_multiple.yaml', + filter_query_parameters=['uuid', 'pnsdk', 'signature', 'timestamp']) + def test_fetch_users_multiple(self): + pubnub = PubNub(self.get_config()) + test_users = ['GraceBrewsterMurrayHopper', 'MargaretHeafieldHamilton', 'FranBlanche'] + for test_user_id in test_users: + pubnub.upsert_user(user_id=test_user_id, sync=True) + + users = pubnub.fetch_users(sync=True) + self.assertTrue(isinstance(users.result, PNFetchUsersResult)) + self.assertEqual(3, len(users.result.data)) + + for test_user_id in test_users: + pubnub.remove_user(test_user_id, sync=True) + + @unittest.skip('Not implemented on a server side') + def test_fetch_users_multiple_limit(self): + pubnub = PubNub(self.get_config()) + users = ['GraceBrewsterMurrayHopper', 'MargaretHeafieldHamilton', 'FranBlanche'] + for test_user_id in users: + pubnub.upsert_user(user_id=test_user_id, sync=True) + + users = pubnub.fetch_users(limit=2, sync=True) + self.assertTrue(isinstance(users.result, PNFetchUsersResult)) + self.assertEqual(2, len(users.result.data)) + self.assertIsNotNone(users.result.data.page) + + for test_user_id in users: + pubnub.remove_user(test_user_id, sync=True)