1# Copyright (C) 2020 Red Hat Inc.
2#
3# Authors:
4#  Eduardo Habkost <ehabkost@redhat.com>
5#
6# This work is licensed under the terms of the GNU GPL, version 2.  See
7# the COPYING file in the top-level directory.
8from typing import *
9
10import logging
11logger = logging.getLogger(__name__)
12DBG = logger.debug
13INFO = logger.info
14WARN = logger.warning
15
16T = TypeVar('T')
17def opt_compare(a: T, b: T) -> bool:
18    """Compare two values, ignoring mismatches if one of them is None"""
19    return (a is None) or (b is None) or (a == b)
20
21def merge(a: T, b: T) -> T:
22    """Merge two values if they matched using opt_compare()"""
23    assert opt_compare(a, b)
24    if a is None:
25        return b
26    else:
27        return a
28
29def test_comp_merge():
30    assert opt_compare(None, 1) == True
31    assert opt_compare(2, None) == True
32    assert opt_compare(1, 1) == True
33    assert opt_compare(1, 2) == False
34
35    assert merge(None, None) is None
36    assert merge(None, 10) == 10
37    assert merge(10, None) == 10
38    assert merge(10, 10) == 10
39
40
41LineNumber = NewType('LineNumber', int)
42ColumnNumber = NewType('ColumnNumber', int)
43class LineAndColumn(NamedTuple):
44    line: int
45    col: int
46
47    def __str__(self):
48        return '%d:%d' % (self.line, self.col)
49
50def line_col(s, position: int) -> LineAndColumn:
51    """Return line and column for a char position in string
52
53    Character position starts in 0, but lines and columns start in 1.
54    """
55    before = s[:position]
56    lines = before.split('\n')
57    line = len(lines)
58    col = len(lines[-1]) + 1
59    return LineAndColumn(line, col)
60
61def test_line_col():
62    assert line_col('abc\ndefg\nhijkl', 0) == (1, 1)
63    assert line_col('abc\ndefg\nhijkl', 2) == (1, 3)
64    assert line_col('abc\ndefg\nhijkl', 3) == (1, 4)
65    assert line_col('abc\ndefg\nhijkl', 4) == (2, 1)
66    assert line_col('abc\ndefg\nhijkl', 10) == (3, 2)
67
68def not_optional(arg: Optional[T]) -> T:
69    assert arg is not None
70    return arg
71
72__all__ = ['not_optional', 'opt_compare', 'merge', 'line_col', 'LineAndColumn']