Passed
Push — main ( 4b9f06...da4e6c )
by Jochen
01:55
created

syslog2irc.router.Router.__init__()   A

Complexity

Conditions 1

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
nop 2
crap 1
1
"""
2
syslog2irc.router
3
~~~~~~~~~~~~~~~~~
4
5
Routing of syslog messages to IRC channels by the port they arrive on.
6
7
:Copyright: 2007-2021 Jochen Kupperschmidt
8
:License: MIT, see LICENSE for details.
9
"""
10
11 1
from collections import defaultdict
12 1
from dataclasses import dataclass
13 1
import logging
14 1
from typing import Any, Dict, Optional, Set
15
16
17 1
logger = logging.getLogger(__name__)
18
19
20 1
@dataclass(frozen=True)
21
class Route:
22
    """A route from a syslog message receiver port to an IRC channel."""
23
24 1
    port: int
25 1
    irc_channel_name: str
26
27
28 1
class Router:
29
    """Map syslog port numbers to IRC channel names."""
30
31 1
    def __init__(self, ports_to_channel_names: Dict[int, Set[str]]) -> None:
32 1
        self.ports_to_channel_names = ports_to_channel_names
33 1
        self.channel_names_to_ports = map_channel_names_to_ports(
34
            ports_to_channel_names
35
        )
36 1
        self.enabled_channels: Set[str] = set()
37
38 1
    def enable_channel(
39
        self, sender: Any, *, channel_name: Optional[str] = None
40
    ) -> None:
41 1
        ports = self.channel_names_to_ports.get(channel_name, set())
42 1
        if not ports:
43 1
            logger.warning(
44
                'No ports routed to channel %s, will not forward to it.',
45
                channel_name,
46
            )
47 1
            return
48
49 1
        self.enabled_channels.add(channel_name)
50 1
        logger.info(
51
            'Enabled forwarding to channel %s from port(s) %s.',
52
            channel_name,
53
            ', '.join(map(str, sorted(ports))),
54
        )
55
56 1
    def is_channel_enabled(self, channel: str) -> bool:
57 1
        return channel in self.enabled_channels
58
59 1
    def get_channel_names_for_port(self, port: int) -> Set[str]:
60
        return self.ports_to_channel_names[port]
61
62
63 1
def map_ports_to_channel_names(routes: Set[Route]) -> Dict[int, Set[str]]:
64
    ports_to_channel_names = defaultdict(set)
65
    for route in routes:
66
        ports_to_channel_names[route.port].add(route.irc_channel_name)
67
    return dict(ports_to_channel_names)
68
69
70 1
def map_channel_names_to_ports(
71
    ports_to_channel_names: Dict[int, Set[str]]
72
) -> Dict[str, Set[int]]:
73 1
    channel_names_to_ports = defaultdict(set)
74 1
    for port, channel_names in ports_to_channel_names.items():
75 1
        for channel_name in channel_names:
76 1
            channel_names_to_ports[channel_name].add(port)
77
    return dict(channel_names_to_ports)
78