1# This file is part of Gajim.
2#
3# Gajim is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published
5# by the Free Software Foundation; version 3 only.
6#
7# Gajim is distributed in the hope that it will be useful,
8# but WITHOUT ANY WARRANTY; without even the implied warranty of
9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10# GNU General Public License for more details.
11#
12# You should have received a copy of the GNU General Public License
13# along with Gajim.  If not, see <http://www.gnu.org/licenses/>.
14
15'''
16Helper code related to plug-ins management system.
17
18:author: Mateusz Biliński <mateusz@bilinski.it>
19:since: 30th May 2008
20:copyright: Copyright (2008) Mateusz Biliński <mateusz@bilinski.it>
21:license: GPL
22'''
23
24__all__ = ['log', 'log_calls']
25
26from typing import List
27
28import logging
29import functools
30
31from gajim.common import configpaths
32from gajim.plugins import plugins_i18n
33from gajim.gui.util import Builder
34
35log = logging.getLogger('gajim.plugin_system')
36'''
37Logger for code related to plug-in system.
38
39:type: logging.Logger
40'''
41
42class GajimPluginActivateException(Exception):
43    '''
44    Raised when activation failed
45    '''
46
47class log_calls:
48    '''
49    Decorator class for functions to easily log when they are entered and left.
50    '''
51
52    filter_out_classes = ['GajimPluginConfig', 'PluginManager',
53                          'GajimPluginConfigDialog', 'PluginsWindow']
54    '''
55    List of classes from which no logs should be emitted when methods are
56    called, even though `log_calls` decorator is used.
57    '''
58
59    def __init__(self, classname=''):
60        '''
61        :Keywords:
62          classname : str
63            Name of class to prefix function name (if function is a method).
64          log : logging.Logger
65            Logger to use when outputting debug information on when function has
66            been entered and when left. By default: `plugins.helpers.log`
67            is used.
68        '''
69
70        self.full_func_name = ''
71        '''
72        Full name of function, with class name (as prefix) if given
73        to decorator.
74
75        Otherwise, it's only function name retrieved from function object
76        for which decorator was called.
77
78        :type: str
79        '''
80        self.log_this_class = True
81        '''
82        Determines whether wrapper of given function should log calls of this
83        function or not.
84
85        :type: bool
86        '''
87
88        if classname:
89            self.full_func_name = classname+'.'
90
91        if classname in self.filter_out_classes:
92            self.log_this_class = False
93
94    def __call__(self, f):
95        '''
96        :param f: function to be wrapped with logging statements
97
98        :return: given function wrapped by *log.debug* statements
99        :rtype: function
100        '''
101
102        self.full_func_name += f.__name__
103        if self.log_this_class:
104            @functools.wraps(f)
105            def wrapper(*args, **kwargs):
106
107                log.debug('%s() <entered>', self.full_func_name)
108                result = f(*args, **kwargs)
109                log.debug('%s() <left>', self.full_func_name)
110                return result
111        else:
112            @functools.wraps(f)
113            def wrapper(*args, **kwargs):
114                result = f(*args, **kwargs)
115                return result
116
117        return wrapper
118
119
120def get_builder(file_name: str, widgets: List[str] = None) -> Builder:
121    return Builder(file_name,
122                   widgets,
123                   domain=plugins_i18n.DOMAIN,
124                   gettext_=plugins_i18n._)
125
126
127def is_shipped_plugin(path):
128    base = configpaths.get('PLUGINS_BASE')
129    if not base.exists():
130        return False
131    plugin_parent = path.parent
132    return base.samefile(plugin_parent)
133