File: utils.py

package info (click to toggle)
libm2k 0.9.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 95,580 kB
  • sloc: xml: 1,611,497; cpp: 16,278; python: 4,181; cs: 516; sh: 471; ansic: 403; makefile: 35
file content (156 lines) | stat: -rw-r--r-- 5,202 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#
# Copyright (c) 2024 Analog Devices Inc.
#
# This file is part of libm2k
# (see http://www.github.com/analogdevicesinc/libm2k).
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2.1 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

import os
import re
from ast import Set
from typing import Any, Iterable, List, Tuple

import iio


def validate_xml_extension(file_name):
    _, ext = os.path.splitext(file_name)
    if not ext:
        return file_name + ".xml"
    if ext == ".xml":
        return file_name
    raise ValueError("File must have a .xml extension")


class Color:
    """
    Class to hold ANSI color constants that can be used to colorize text in terminal.
    """

    WHITE = "\033[97m"  # Found with same name
    GREEN = "\033[92m"  # Exists only in target
    RED = "\033[91m"  # Found in
    BLUE = "\033[94m"


def get_conditional_color(value: Any, reference: Iterable, target: Iterable) -> Color:
    """
    Determines the color based on the presence of a value in the reference and target.

    Parameters:
    - value (Any): The value to check.
    - reference (Iterable): The reference set or list.
    - target (Iterable): The target set or list.

    Returns:
    Color: ANSI color code for text in terminal

    Color decision rules:
    - If the value is present in both the reference and target, returns WHITE.
    - If the value is new and coming from the target (i.e., it's in the target but not in the reference), returns GREEN.
    - If the value was in the reference but is missing from the target, returns RED.
    """
    if value in reference and value in target:
        return Color.WHITE
    if value in reference and value not in target:
        return Color.RED
    if value not in reference and value in target:
        return Color.GREEN


def extract_channel_index(input: str) -> int:
    """
    Extracts the channel index from a string.

    The function searches for patterns like 'voltage', 'temp', or 'altvoltage' followed by a number in the input string.
    It returns the number as an integer.

    Parameters:
    - input (str): The string to extract the channel index from.

    Returns:
    int: The extracted channel index.

    Raises:
    ValueError: If no valid number is found in the string.
    """
    match = re.search(r"(voltage|temp|altvoltage)(\d+)", input)
    if match:
        return int(match.group(2))
    else:
        raise ValueError("No valid number found in the string")


def get_channels(device1: iio.Device, device2: iio.Device) -> List[Tuple[str, bool]]:
    """
    Combines the channels of two devices into a set of tuples of channel id and output status that
    can be used to identify shared and unique channels to each device.

    Parameters:
    - device1 (iio.Device)
    - device2 (iio.Device)

    Returns:
    - List[Tuple[str, bool]]: A sorted list of tuples, where each tuple contains a channel id and a boolean indicating
      whether the channel is an output channel. The list is sorted by the channel index.
    """
    channels_1 = {(dev.id, dev.output) for dev in device1.channels}
    channels_2 = {(dev.id, dev.output) for dev in device2.channels}
    channels_all = channels_1 | channels_2
    return (
        channels_1,
        channels_2,
        sorted(channels_all, key=lambda x: extract_channel_index(x[0])),
    )


def get_union(input1: Any, input2: Any) -> Tuple[Set, Set, Set]:
    """
    Converts two inputs into sets and returns their individual sets and the union of both sets.

    This function takes two inputs, converts them into sets, and then returns a tuple containing the first set,
    the second set, and the union of both sets.

    Parameters:
    - input1 (Any): The first input to convert into a set.
    - input2 (Any): The second input to convert into a set.

    Returns:
    - Tuple[Set, Set, Set]: A tuple containing the first set, the second set, and the union of both sets.
    """
    s1 = set(input1)
    s2 = set(input2)
    return s1, s2, s1 | s2


def get_attrs(channel_reference, channel_target):
    if channel_reference and channel_target:
        attrs_reference = set(channel_reference.attrs)
        attrs_target = set(channel_target.attrs)
    if channel_reference and not channel_target:
        attrs_reference = set(channel_reference.attrs)
    if not channel_reference and channel_target:
        attrs_target = set(channel_target.attrs)
    attrs_union = attrs_reference | attrs_target
    return attrs_reference, attrs_target, attrs_union


def to_input_output(value):
    return "output" if value else "input"


def conditional_str(value):
    return f"{value}" if value else ""