def parse_transfers_from_messages(
        spine_messages: Iterable[Message],
        time_range: DateTimeRange) -> Iterator[Transfer]:
    conversations = group_into_conversations(spine_messages)
    parsed_conversations = _parse_conversations(conversations)
    conversations_started_in_range = filter_conversations_by_request_started_time(
        parsed_conversations, time_range)
    transfers = derive_transfers(conversations_started_in_range)
    return transfers
def test_group_into_conversations_sorts_messages_within_conversations():
    message_one = build_message(conversation_id="abc", time=datetime(year=2020, month=6, day=6))
    message_two = build_message(conversation_id="abc", time=datetime(year=2020, month=6, day=5))
    messages = [message_one, message_two]

    expected = [Conversation("abc", [message_two, message_one])]

    actual = group_into_conversations(messages)

    assert list(actual) == expected
def test_group_into_conversations_produces_correct_conversations():
    message_one = build_message(conversation_id="abc")
    message_two = build_message(conversation_id="xyz")
    messages = [message_one, message_two]

    expected = [Conversation("abc", [message_one]), Conversation("xyz", [message_two])]

    actual = group_into_conversations(messages)

    assert list(actual) == expected
        first_message.time)


def filter_for_full_conversations(conversations, date_range):
    return (c for c in conversations
            if conversation_is_started_in(c, date_range))


def message_code(message, requester):
    party = "R" if message.from_party_asid == requester else "S"
    interaction = abbreviations[message.interaction_id]
    error = str(message.error_code) if message.error_code is not None else ""
    return party + ":" + interaction + "[" + error + "]"


def extract_pattern(conversation):
    requester = conversation.messages[0].from_party_asid
    return "-".join(
        (message_code(m, requester) for m in conversation.messages))


spine_messages = read_spine_csv_gz_files(input_files)
gp2gp_conversations = group_into_conversations(spine_messages)
full_conversations = filter_for_full_conversations(gp2gp_conversations,
                                                   date_range)
counts = Counter((extract_pattern(c) for c in full_conversations))

with open("./gp2gp-patterns-jan-21.csv", 'w') as f:
    for pattern, count in counts.most_common():
        print(pattern, count)