# Path: clearly/utils/data.py
# def _accept(pattern: Pattern, negate: bool, values: Tuple[str, ...]) -> bool:
#     return any(v and pattern.search(v) for v in values) != negate
# 
# def accept_task(pattern: Pattern, negate: bool, message: TaskMessage) -> bool:
#     """Find if the message values match the given pattern and negate.
#     This centralizes the search criteria, to both real time streaming
#     and past events.
# 
#     """
#     return _accept(pattern, negate, TASK_OP(message))
# 
# def accept_worker(pattern: Pattern, negate: bool, message: WorkerMessage) -> bool:
#     """Find if the message values match the given pattern and negate.
#     This centralizes the search criteria, to both real time streaming
#     and past events.
# 
#     """
#     return _accept(pattern, negate, WORKER_OP(message))
# 
# def obj_to_message(obj: Union[Task, Worker], to_type: Union[TaskMessage, WorkerMessage],
#                    **updates) -> Union[TaskMessage, WorkerMessage]:
#     """Convert celery Task/Worker objects to proto buffer messages, updating
#     some fields as needed.
# 
#     Args:
#         obj: the celery object to be converted
#         to_type: desired message type
#             Note: even having only one compatible type, the caller already has this info,
#             and this avoids ifs here and so improve performance in this heavy usage method.
# 
#     Returns:
#         key and proto buffer message
# 
#     """
#     keys = to_type.DESCRIPTOR.fields_by_name.keys()
#     data = {k: getattr(obj, k) for k in keys}
#     data.update(updates)
#     return to_type(**data)


import re
import pytest
from unittest import mock
from celery.events.state import Task, Worker
from clearly.protos.clearly_pb2 import TaskMessage, WorkerMessage
from clearly.utils.data import _accept, accept_task, accept_worker, obj_to_message

TASK = dict(name='name', routing_key='routing_key', uuid='uuid', retries=5, args='args',
            kwargs='kwargs', result='result', traceback='traceback', result_meta='meta')

WORKER = dict(hostname='hostname', pid=12000, sw_sys='sw_sys', sw_ident='sw_ident',
              sw_ver='sw_ver', loadavg=[1., 2., 3.], processed=789789, freq=5, heartbeats=[1])


@pytest.mark.parametrize('obj, to_type, data', [
    (Task(**TASK), TaskMessage, TASK),
    (Worker(**WORKER), WorkerMessage, WORKER),
])
def test_server_obj_to_message_valid(obj, to_type, data):
    obj.timestamp, obj.state = 123.1, 'state'
    message = obj_to_message(obj, to_type)
    assert all(getattr(message, k) == v for k, v in data.items())


@pytest.mark.parametrize('obj, to_type', [
    (1, TaskMessage),
    (1, WorkerMessage),
    ('wrong', TaskMessage),
    ('wrong', WorkerMessage),
    ({'wrong': True}, TaskMessage),
    ({'wrong': True}, WorkerMessage),
    (Task(**TASK), WorkerMessage),
    (Worker(**WORKER), TaskMessage),
])
def test_server_obj_to_message_invalid(obj, to_type):
    with pytest.raises(AttributeError):

# Path: clearly/utils/data.py
# def _accept(pattern: Pattern, negate: bool, values: Tuple[str, ...]) -> bool:
#     return any(v and pattern.search(v) for v in values) != negate
# 
# def accept_task(pattern: Pattern, negate: bool, message: TaskMessage) -> bool:
#     """Find if the message values match the given pattern and negate.
#     This centralizes the search criteria, to both real time streaming
#     and past events.
# 
#     """
#     return _accept(pattern, negate, TASK_OP(message))
# 
# def accept_worker(pattern: Pattern, negate: bool, message: WorkerMessage) -> bool:
#     """Find if the message values match the given pattern and negate.
#     This centralizes the search criteria, to both real time streaming
#     and past events.
# 
#     """
#     return _accept(pattern, negate, WORKER_OP(message))
# 
# def obj_to_message(obj: Union[Task, Worker], to_type: Union[TaskMessage, WorkerMessage],
#                    **updates) -> Union[TaskMessage, WorkerMessage]:
#     """Convert celery Task/Worker objects to proto buffer messages, updating
#     some fields as needed.
# 
#     Args:
#         obj: the celery object to be converted
#         to_type: desired message type
#             Note: even having only one compatible type, the caller already has this info,
#             and this avoids ifs here and so improve performance in this heavy usage method.
# 
#     Returns:
#         key and proto buffer message
# 
#     """
#     keys = to_type.DESCRIPTOR.fields_by_name.keys()
#     data = {k: getattr(obj, k) for k in keys}
#     data.update(updates)
#     return to_type(**data)


# Path: tests/unit/utils/test_data.py
import re
import pytest
from unittest import mock
from celery.events.state import Task, Worker
from clearly.protos.clearly_pb2 import TaskMessage, WorkerMessage
from clearly.utils.data import _accept, accept_task, accept_worker, obj_to_message


TASK = dict(name='name', routing_key='routing_key', uuid='uuid', retries=5, args='args',
            kwargs='kwargs', result='result', traceback='traceback', result_meta='meta')

WORKER = dict(hostname='hostname', pid=12000, sw_sys='sw_sys', sw_ident='sw_ident',
              sw_ver='sw_ver', loadavg=[1., 2., 3.], processed=789789, freq=5, heartbeats=[1])


@pytest.mark.parametrize('obj, to_type, data', [
    (Task(**TASK), TaskMessage, TASK),
    (Worker(**WORKER), WorkerMessage, WORKER),
])
def test_server_obj_to_message_valid(obj, to_type, data):
    obj.timestamp, obj.state = 123.1, 'state'
    message = obj_to_message(obj, to_type)
    assert all(getattr(message, k) == v for k, v in data.items())


@pytest.mark.parametrize('obj, to_type', [
    (1, TaskMessage),
    (1, WorkerMessage),
    ('wrong', TaskMessage),
    ('wrong', WorkerMessage),
    ({'wrong': True}, TaskMessage),
    ({'wrong': True}, WorkerMessage),
    (Task(**TASK), WorkerMessage),
    (Worker(**WORKER), TaskMessage),
])
def test_server_obj_to_message_invalid(obj, to_type):
    with pytest.raises(AttributeError):

        obj_to_message(obj, to_type)