summaryrefslogtreecommitdiff
path: root/.emacs.d.back/.python-environments/default/lib/python3.7/site-packages/epc/core.py
blob: 5157f77dee918c6d9953edd292ceb871594266e8 (plain)
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
# Copyright (C) 2012-  Takafumi Arakaki

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 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 General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import logging
from .py3compat import SimpleXMLRPCServer


def _get_logger():
    """
    Generate a logger with a stream handler.
    """
    logger = logging.getLogger('epc')
    hndlr = logging.StreamHandler()
    hndlr.setLevel(logging.INFO)
    hndlr.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
    logger.addHandler(hndlr)
    return logger
_logger = _get_logger()


class EPCDispatcher:

    # This class will be mixed with `SocketServer.TCPServer`,
    # which is an old style class.

    # see also: SimpleXMLRPCServer.SimpleXMLRPCDispatcher

    def __init__(self):
        self.funcs = {}
        self.instance = None

    def register_instance(self, instance, allow_dotted_names=False):
        """
        Register an instance to respond to EPC requests.

        :type instance: object
        :arg  instance:
            An object with methods to provide to peer.  If this
            instance has `_get_method` method, EPC method name
            resolution can be done by this method.

        :type allow_dotted_names: bool
        :arg  allow_dotted_names:
            If it is true, method names containing dots are supported.
            They are resolved using `getattr` for each part of the
            name as long as it does not start with '_'.

        Unlike :meth:`register_function`, only one instance can
        be registered.

        """
        self.instance = instance
        self.allow_dotted_names = allow_dotted_names

    def register_function(self, function, name=None):
        """
        Register function to be called from EPC client.

        :type  function: callable
        :arg   function: Function to publish.
        :type      name: str
        :arg       name: Name by which function is published.

        This method returns the given `function` as-is, so that you
        can use it as a decorator.

        """
        if name is None:
            name = function.__name__
        self.funcs[name] = function
        return function

    def get_method(self, name):
        """
        Get registered method callend `name`.
        """
        try:
            return self.funcs[name]
        except KeyError:
            try:
                return self.instance._get_method(name)
            except AttributeError:
                return SimpleXMLRPCServer.resolve_dotted_attribute(
                    self.instance, name, self.allow_dotted_names)


class EPCCore(EPCDispatcher):

    """
    Core methods shared by `EPCServer` and `EPCClient`.
    """

    logger = _logger

    def __init__(self, debugger, log_traceback):
        EPCDispatcher.__init__(self)
        self.set_debugger(debugger)
        self.log_traceback = log_traceback

    def set_debugger(self, debugger):
        """
        Set debugger to run when an error occurs in published method.

        You can also set debugger by passing `debugger` argument to
        the class constructor.

        :type debugger: {'pdb', 'ipdb', None}
        :arg  debugger: type of debugger.

        """
        if debugger == 'pdb':
            import pdb
            self.debugger = pdb
        elif debugger == 'ipdb':
            import ipdb
            self.debugger = ipdb
        else:
            self.debugger = debugger