# Path: botoflow/swf_exceptions.py
# @contextmanager
# def swf_exception_wrapper():
#     try:
#         yield
#     except ClientError as err:
#         err_type = err.response['Error'].get('Code', 'SWFResponseError')
#         err_msg = err.response['Error'].get(
#             'Message', 'No error message provided...')
# 
#         raise _swf_fault_exception.get(err_type, SWFResponseError)(err_msg)
# 
# Path: botoflow/data_converter/json_data_converter.py
# class JSONDataConverter(AbstractDataConverter):
#     """This is the **recomended** and default data converter. It
#     (de)serializes most Python types as JSON data, which
#     :py:mod:`json` cannot do, but allows you to have a more or less
#     human readable view of the data (if you for example were using the
#     AWS SWF console to check on the progress of your workflow
#     activities).
# 
#     It tries to serialize objects from new-style classes, moreover, it
#     tries to follow the pickle's __setstate__ and __getstate__ methods
#     for customizing serialization and deserialization.
# 
#     Because it is not pickle, it will **NOT** work in all the
#     situations that Pickle does and vice-versa. For example, bytes
#     have to be encoded manually in Python2 (as there's no easy way to
#     know what to do, and hence one of the big reasons for Python3).
# 
#     We try to support most of the base types for ease of use, but the
#     serialized data might be a bit 'chatty' and bump into SWF data
#     limitations.
# 
#     .. warning::
# 
#         This data converter does not support old-style classes.
#     """
# 
#     def __init__(self):
#         self._setup()
# 
#     def _setup(self):
#         self._encoder = _FlowObjEncoder(indent=None, separators=(',', ':'))
#         self._decoder = json.JSONDecoder(object_hook=_flow_obj_decoder)
# 
#     def dumps(self, obj):
#         """Serialize to object to JSON str format
# 
#         :param obj: Any serializable object (including classes)
#         :type obj: object
#         :returns: JSON string
#         :rtype: str
#         """
#         return self._encoder.encode(obj)
# 
#     def loads(self, data):
#         """Deserialize a JSON string into Python object(s)
# 
#         :param data: Input streang
#         :type data: str, unicode
#         :returns: deserialized object
#         :rtype: object
#         """
#         return self._decoder.decode(data)
# 
#     def __getstate__(self):
#         # make sure we handle (de)serialization of serializers well :)
#         newdct = copy.copy(self.__dict__)
#         del newdct['_encoder']
#         del newdct['_decoder']
#         return newdct
# 
#     def __setstate__(self, dct):
#         self.__dict__ = dct
#         self._setup()
# 
# Path: botoflow/core/exceptions.py
# class CancellationError(Exception):
#     """
#     Cancellation error exception
#     """
#     pass


from botoflow.swf_exceptions import swf_exception_wrapper
from botoflow.data_converter import JSONDataConverter
from botoflow.core.exceptions import CancellationError
class ManualActivityCompletionClient(object):
    def __init__(self, swf_client, data_converter=JSONDataConverter()):
        """Helper class to work with manual activities

        :param swf_client: botocore SWF client
        :type swf_client: botocore.clients.Client
        :param data_converter: DataConverter to use for marshaling data
        :type data_converter: botoflow.data_converter.BaseDataConverter
        """
        self._swf_client = swf_client
        self.data_converter = data_converter

    def complete(self, result, task_token):
        result = self.data_converter.dumps(result)
        with swf_exception_wrapper():
            self._swf_client.respond_activity_task_completed(result=result, taskToken=task_token)

    def fail(self, details, task_token, reason=''):
        details = self.data_converter.dumps(details)
        with swf_exception_wrapper():
            self._swf_client.respond_activity_task_failed(details=details, reason=reason, taskToken=task_token)

    def cancel(self, details, task_token):
        with swf_exception_wrapper():
            self._swf_client.respond_activity_task_cancelled(details=details, taskToken=task_token)

    def record_heartbeat(self, details, task_token):
        with swf_exception_wrapper():
            response_data = self._swf_client.record_activity_task_hearbeat(details=details, taskToken=task_token)
        if response_data['cancelRequested']:

# Path: botoflow/swf_exceptions.py
# @contextmanager
# def swf_exception_wrapper():
#     try:
#         yield
#     except ClientError as err:
#         err_type = err.response['Error'].get('Code', 'SWFResponseError')
#         err_msg = err.response['Error'].get(
#             'Message', 'No error message provided...')
# 
#         raise _swf_fault_exception.get(err_type, SWFResponseError)(err_msg)
# 
# Path: botoflow/data_converter/json_data_converter.py
# class JSONDataConverter(AbstractDataConverter):
#     """This is the **recomended** and default data converter. It
#     (de)serializes most Python types as JSON data, which
#     :py:mod:`json` cannot do, but allows you to have a more or less
#     human readable view of the data (if you for example were using the
#     AWS SWF console to check on the progress of your workflow
#     activities).
# 
#     It tries to serialize objects from new-style classes, moreover, it
#     tries to follow the pickle's __setstate__ and __getstate__ methods
#     for customizing serialization and deserialization.
# 
#     Because it is not pickle, it will **NOT** work in all the
#     situations that Pickle does and vice-versa. For example, bytes
#     have to be encoded manually in Python2 (as there's no easy way to
#     know what to do, and hence one of the big reasons for Python3).
# 
#     We try to support most of the base types for ease of use, but the
#     serialized data might be a bit 'chatty' and bump into SWF data
#     limitations.
# 
#     .. warning::
# 
#         This data converter does not support old-style classes.
#     """
# 
#     def __init__(self):
#         self._setup()
# 
#     def _setup(self):
#         self._encoder = _FlowObjEncoder(indent=None, separators=(',', ':'))
#         self._decoder = json.JSONDecoder(object_hook=_flow_obj_decoder)
# 
#     def dumps(self, obj):
#         """Serialize to object to JSON str format
# 
#         :param obj: Any serializable object (including classes)
#         :type obj: object
#         :returns: JSON string
#         :rtype: str
#         """
#         return self._encoder.encode(obj)
# 
#     def loads(self, data):
#         """Deserialize a JSON string into Python object(s)
# 
#         :param data: Input streang
#         :type data: str, unicode
#         :returns: deserialized object
#         :rtype: object
#         """
#         return self._decoder.decode(data)
# 
#     def __getstate__(self):
#         # make sure we handle (de)serialization of serializers well :)
#         newdct = copy.copy(self.__dict__)
#         del newdct['_encoder']
#         del newdct['_decoder']
#         return newdct
# 
#     def __setstate__(self, dct):
#         self.__dict__ = dct
#         self._setup()
# 
# Path: botoflow/core/exceptions.py
# class CancellationError(Exception):
#     """
#     Cancellation error exception
#     """
#     pass


# Path: botoflow/manual_activity_completion_client.py
from botoflow.swf_exceptions import swf_exception_wrapper
from botoflow.data_converter import JSONDataConverter
from botoflow.core.exceptions import CancellationError

class ManualActivityCompletionClient(object):
    def __init__(self, swf_client, data_converter=JSONDataConverter()):
        """Helper class to work with manual activities

        :param swf_client: botocore SWF client
        :type swf_client: botocore.clients.Client
        :param data_converter: DataConverter to use for marshaling data
        :type data_converter: botoflow.data_converter.BaseDataConverter
        """
        self._swf_client = swf_client
        self.data_converter = data_converter

    def complete(self, result, task_token):
        result = self.data_converter.dumps(result)
        with swf_exception_wrapper():
            self._swf_client.respond_activity_task_completed(result=result, taskToken=task_token)

    def fail(self, details, task_token, reason=''):
        details = self.data_converter.dumps(details)
        with swf_exception_wrapper():
            self._swf_client.respond_activity_task_failed(details=details, reason=reason, taskToken=task_token)

    def cancel(self, details, task_token):
        with swf_exception_wrapper():
            self._swf_client.respond_activity_task_cancelled(details=details, taskToken=task_token)

    def record_heartbeat(self, details, task_token):
        with swf_exception_wrapper():
            response_data = self._swf_client.record_activity_task_hearbeat(details=details, taskToken=task_token)
        if response_data['cancelRequested']:

            raise CancellationError()