File: display.py

package info (click to toggle)
git-cola 4.18.2-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 7,036 kB
  • sloc: python: 40,107; sh: 298; makefile: 223; xml: 121; tcl: 62
file content (116 lines) | stat: -rw-r--r-- 3,706 bytes parent folder | download
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
"""Display models and utility functions"""
import collections
from datetime import datetime
from typing import Any, TYPE_CHECKING

try:
    import notify2
except ImportError:
    notify2 = None
try:
    import notifypy
except ImportError:
    notifypy = None

from . import resources
from .models import prefs

if TYPE_CHECKING:
    from .app import ApplicationContext

NOTIFICATIONS_AVAILABLE = bool(notify2 or notifypy)


def shorten_paths(source_paths) -> dict[Any, Any]:
    """Shorten a sequence of paths into unique strings for display"""
    result = {}
    # Start by assuming that all paths are in conflict.
    # On each iteration we will collect all the path suffixes, move the newly
    # unique entries to the result, and repeat until no conflicts remain.
    count = 0
    conflicts = list(source_paths)
    in_conflict = True
    while in_conflict:
        count += 1
        # Gather the suffixes for the current paths in conflict
        suffixes = collections.defaultdict(list)
        for path in conflicts:
            suffix = path_suffix(path, count)
            suffixes[suffix].append(path)

        # Loop over the suffixes to gather new conflicts and unique entries.
        conflicts = []
        in_conflict = False

        for suffix, paths in suffixes.items():
            # If only a single path exists for the suffix then no conflict
            # exists, and the suffix is valid.
            if len(paths) == 1:
                result[paths[0]] = suffix
            # If this loop runs too long then bail out by using the full path.
            elif count >= 128:
                for path in paths:
                    result[path] = path
            # If multiple paths map to the same suffix then the paths are
            # considered in conflict, and will be reprocessed.
            else:
                conflicts.extend(paths)
                in_conflict = True

    return result


def path_suffix(path: str, count: int) -> str:
    """Return `count` number of trailing path components"""
    path = normalize_path(path)
    components = path.split('/')[-count:]
    return '/'.join(components)


def normalize_path(path: str) -> str:
    """Normalize a path so that only "/" is used as a separator"""
    return path.replace('\\', '/')


def notify(context: 'ApplicationContext', title: str, message: str, icon) -> None:
    """Send a notification using notify2 xor notifypy"""
    app_name = context.app_name
    if notify2:
        notify2.init(app_name)
        notification = notify2.Notification(title, message, icon)
        notification.show()
    elif notifypy:
        notification = notifypy.Notify()
        notification.application_name = app_name
        notification.title = title
        notification.message = message
        notification.icon = icon
        notification.send()
    else:
        context.notifier.log.emit(f'{title}: {message}')


def push_notification(
    context: 'ApplicationContext',
    title: str,
    message: str,
    error: bool = False,
    allow_popups: bool = True,
) -> None:
    """Emit a push notification"""
    if prefs.enable_popups(context) and allow_popups:
        if error:
            context.notifier.critical.emit(title, dict(message=message))
        else:
            context.notifier.information.emit(title, dict(message=message))
    else:
        if error:
            icon = resources.icon_path('git-cola-error.svg')
        else:
            icon = resources.icon_path('git-cola-ok.svg')
        notify(context, title, message, icon)


def git_commit_date(datetime: datetime) -> str:
    """Return the datetime as a string for use by Git"""
    return datetime.strftime('%a %b %d %H:%M:%S %Y %z')