summaryrefslogtreecommitdiffstats
path: root/server/src/shared_vim_server.py
blob: a7f52011993c2fb05941752cfe19de319651967f (plain) (blame)
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
#! /usr/bin/env python3

"""Main thread."""

import signal
import sys
import threading
import log

from cmd_ui import CmdUI
from tcp_server import TCPServer
from users_text_manager import UsersTextManager


class _ArgsError(Exception):
    """Exception raised by _Args."""
    pass

class _Args(object):
    """Arguments of this program.

    Attributes:
        port: Port number.
        user_list_filename: Default user list.
        save_filename: Name of the file to save the text.
    """
    DOCUMENT = '[usage] <port_number> <user_list_filename> <save_filename>\n'
    def __init__(self):
        if len(sys.argv) != 4:
            raise _ArgsError('Wrong length of arguments.')
        try:
            self.port = int(sys.argv[1])
        except ValueError as e:
            raise _ArgsError(e)
        self.user_list_filename = sys.argv[2]
        self.saved_filename = sys.argv[3]


class _SharedVimServerError(Exception):
    """Error raised by SharedVimServer."""
    pass

class SharedVimServer(threading.Thread):
    """Main class.

    Attributes:
        _users_text_manager: Instance of UsersTextManager.
        _tcp_server: Instance of TCPServer.
        _cmd_ui: Instance of CmdUI.
    """
    def __init__(self):
        """Constructor."""
        super(SharedVimServer, self).__init__()
        try:
            self._args = _Args()
        except _ArgsError as e:
            raise _SharedVimServerError(str(e) + '\n' + _Args.DOCUMENT)
        self._users_text_manager = UsersTextManager(self._args.saved_filename)
        self._tcp_server = TCPServer(self._args.port, self._users_text_manager)
        self._cmd_ui = CmdUI(self._users_text_manager, self._tcp_server, self)
        log.info.interface = self._cmd_ui
        log.error.interface = self._cmd_ui

    def run(self):
        """Starts the program."""
        self._tcp_server.start()
        self._cmd_ui.start(['load %s' % self._args.user_list_filename])
        self._cmd_ui.join()
        self._tcp_server.join()

    def stop(self):
        """Exits the program."""
        self._cmd_ui.stop()
        self._tcp_server.stop()


class _SignalHandler(object):
    """Single handler.

    It will handle below the signals:
        SIGTERM, SIGINT - Exit the program.

    Attributes:
        _shared_vim_server: Instance of SharedVimServer.
    """
    def __init__(self, shared_vim_server):
        """Constructor.

        Args:
            shared_vim_server: Instance of SharedVimServer.
        """
        self._shared_vim_server = shared_vim_server
        signal.signal(signal.SIGTERM, self._handler)
        signal.signal(signal.SIGINT, self._handler)

    def _handler(self, number, unused_frame):
        """Signal handler function.

        Args:
            number: The signal number to be handle.
        """
        if number in (signal.SIGTERM, signal.SIGINT):
            self._shared_vim_server.stop()


def main():
    """Program entry point."""
    try:
        shared_vim_server = SharedVimServer()
        _SignalHandler(shared_vim_server)
        shared_vim_server.start()
        shared_vim_server.join()
    except _SharedVimServerError as e:
        print(e)
        sys.exit(1)


if __name__ == '__main__':
    main()