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

syslog2irc.router   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Test Coverage

Coverage 85.71%

Importance

Changes 0
Metric Value
eloc 46
dl 0
loc 78
rs 10
c 0
b 0
f 0
ccs 30
cts 35
cp 0.8571
wmc 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A Router.__init__() 0 6 1
A Router.enable_channel() 0 16 2
A Router.get_channel_names_for_port() 0 2 1
A Router.is_channel_enabled() 0 2 1

2 Functions

Rating   Name   Duplication   Size   Complexity  
A map_ports_to_channel_names() 0 5 2
A map_channel_names_to_ports() 0 8 3
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