-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Projections added to python client (#451)
* Projections added to python client * Fixed projections example * Identity unit tests, fixed changes requested on pr * Fixed print statements in doc example * Fix again print statements in python docs * Fixed requested changes * Python 2 test fix for HazelcastJsonValue
- Loading branch information
Showing
10 changed files
with
338 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
from hazelcast.serialization.api import IdentifiedDataSerializable | ||
|
||
_PROJECTIONS_FACTORY_ID = -30 | ||
|
||
|
||
class Projection(object): | ||
"""Marker base class for all projections. | ||
Projections allow the client to transform (strip down) each query result | ||
object in order to avoid redundant network traffic. | ||
""" | ||
|
||
pass | ||
|
||
|
||
class _AbstractProjection(Projection, IdentifiedDataSerializable): | ||
def write_data(self, object_data_output): | ||
raise NotImplementedError("write_data") | ||
|
||
def read_data(self, object_data_input): | ||
pass | ||
|
||
def get_factory_id(self): | ||
return _PROJECTIONS_FACTORY_ID | ||
|
||
def get_class_id(self): | ||
raise NotImplementedError("get_class_id") | ||
|
||
|
||
def _validate_attribute_path(attribute_path): | ||
if not attribute_path: | ||
raise ValueError("attribute_path must not be None or empty") | ||
|
||
if "[any]" in attribute_path: | ||
raise ValueError("attribute_path must not contain [any] operators") | ||
|
||
|
||
class _SingleAttributeProjection(_AbstractProjection): | ||
def __init__(self, attribute_path): | ||
_validate_attribute_path(attribute_path) | ||
self._attribute_path = attribute_path | ||
|
||
def write_data(self, object_data_output): | ||
object_data_output.write_string(self._attribute_path) | ||
|
||
def get_class_id(self): | ||
return 0 | ||
|
||
|
||
class _MultiAttributeProjection(_AbstractProjection): | ||
def __init__(self, *attribute_paths): | ||
if not attribute_paths: | ||
raise ValueError("Specify at least one attribute path") | ||
|
||
for attribute_path in attribute_paths: | ||
_validate_attribute_path(attribute_path) | ||
|
||
self.attribute_paths = attribute_paths | ||
|
||
def write_data(self, object_data_output): | ||
object_data_output.write_string_array(self.attribute_paths) | ||
|
||
def get_class_id(self): | ||
return 1 | ||
|
||
|
||
class _IdentityProjection(_AbstractProjection): | ||
def write_data(self, object_data_output): | ||
pass | ||
|
||
def get_class_id(self): | ||
return 2 | ||
|
||
|
||
def single_attribute(attribute_path): | ||
"""Creates a projection that extracts the value of | ||
the given attribute path. | ||
Args: | ||
attribute_path (str): Path to extract the attribute from. | ||
Returns: | ||
Projection[any]: A projection that extracts the value of the given | ||
attribute path. | ||
""" | ||
return _SingleAttributeProjection(attribute_path) | ||
|
||
|
||
def multi_attribute(*attribute_paths): | ||
"""Creates a projection that extracts the values of | ||
one or more attribute paths. | ||
Args: | ||
*attribute_paths (str): Paths to extract the attributes from. | ||
Returns: | ||
Projection[list]: A projection that extracts the values of the given | ||
attribute paths. | ||
""" | ||
return _MultiAttributeProjection(*attribute_paths) | ||
|
||
|
||
def identity(): | ||
"""Creates a projection that does no transformation. | ||
Returns: | ||
Projection[hazelcast.core.MapEntry]: A projection that does no | ||
transformation. | ||
""" | ||
return _IdentityProjection() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
from hazelcast.protocol.client_message import OutboundMessage, REQUEST_HEADER_SIZE, create_initial_buffer | ||
from hazelcast.protocol.builtin import StringCodec | ||
from hazelcast.protocol.builtin import DataCodec | ||
from hazelcast.protocol.builtin import ListMultiFrameCodec | ||
|
||
# hex: 0x013B00 | ||
_REQUEST_MESSAGE_TYPE = 80640 | ||
# hex: 0x013B01 | ||
_RESPONSE_MESSAGE_TYPE = 80641 | ||
|
||
_REQUEST_INITIAL_FRAME_SIZE = REQUEST_HEADER_SIZE | ||
|
||
|
||
def encode_request(name, projection): | ||
buf = create_initial_buffer(_REQUEST_INITIAL_FRAME_SIZE, _REQUEST_MESSAGE_TYPE) | ||
StringCodec.encode(buf, name) | ||
DataCodec.encode(buf, projection, True) | ||
return OutboundMessage(buf, True) | ||
|
||
|
||
def decode_response(msg): | ||
msg.next_frame() | ||
return ListMultiFrameCodec.decode_contains_nullable(msg, DataCodec.decode) |
24 changes: 24 additions & 0 deletions
24
hazelcast/protocol/codec/map_project_with_predicate_codec.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from hazelcast.protocol.client_message import OutboundMessage, REQUEST_HEADER_SIZE, create_initial_buffer | ||
from hazelcast.protocol.builtin import StringCodec | ||
from hazelcast.protocol.builtin import DataCodec | ||
from hazelcast.protocol.builtin import ListMultiFrameCodec | ||
|
||
# hex: 0x013C00 | ||
_REQUEST_MESSAGE_TYPE = 80896 | ||
# hex: 0x013C01 | ||
_RESPONSE_MESSAGE_TYPE = 80897 | ||
|
||
_REQUEST_INITIAL_FRAME_SIZE = REQUEST_HEADER_SIZE | ||
|
||
|
||
def encode_request(name, projection, predicate): | ||
buf = create_initial_buffer(_REQUEST_INITIAL_FRAME_SIZE, _REQUEST_MESSAGE_TYPE) | ||
StringCodec.encode(buf, name) | ||
DataCodec.encode(buf, projection) | ||
DataCodec.encode(buf, predicate, True) | ||
return OutboundMessage(buf, True) | ||
|
||
|
||
def decode_response(msg): | ||
msg.next_frame() | ||
return ListMultiFrameCodec.decode_contains_nullable(msg, DataCodec.decode) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.