summaryrefslogtreecommitdiff
path: root/src/buildstream/_pluginproxy.py
blob: c6f28eea30c8f83f33032f6ff102e256e6cbcca3 (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
#
#  Copyright (C) 2020 Codethink Limited
#
#  This program is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2 of the License, or (at your option) any later version.
#
#  This library 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
#  Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public
#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
#
#  Authors:
#        Tristan Van Berkom <tristan.vanberkom@codethink.co.uk>

from .plugin import Plugin


# PluginProxyError()
#
# The PluginProxyError is raised by PluginProxy objects when an illegal
# method call is called by a Plugin.
#
# This exception does not derive from BstError because it is not a user
# facing error but a Plugin author facing error; the result of a
# PluginProxyError being raised is that BuildStream treats it as an
# unhandled exception, and issues a BUG message with a helpful stacktrace
# which can be helpful for the Plugin author to fix their bugs.
#
class PluginProxyError(Exception):
    pass


# PluginProxy()
#
# Base class for proxies to Plugin instances.
#
# Proxies are handed off to Plugin implementations whenever they observe the data
# model, like when the Element observes it's dependencies, this allows the core to
# do some police work and raise errors when plugins attempt to perform illegal method
# calls.
#
# Refer to the Plugin class for the documentation for these APIs.
#
# In this file we simply raise a PluginProxyError() in the case that a Plugin tries to
# call an illegal API, or we forward the method call along to the underlying Plugin
# instance if the given method call is considered legal.
#
# Args:
#    owner (Plugin): The owning plugin, i.e. the plugin which this proxy was given to
#    plugin (Plugin): The proxied plugin, i.e. the plugin this proxy is attached to
#
class PluginProxy:
    def __init__(self, owner: Plugin, plugin: Plugin):

        # These members are considered internal, they are accessed by subclasses
        # which extend the PluginProxy, but hidden from the client Plugin implementations
        # which the proxy objects are handed off to.
        #
        self._owner = owner  # The Plugin this proxy was given to / created for
        self._plugin = plugin  # The Plugin this proxy was created as a proxy for

    # We use the fallback __getattr__ method to trigger plugin author facing
    # errors for any methods we have not explicitly redirected to the underlying
    # plugin object.
    #
    def __getattr__(self, name):
        if hasattr(self._plugin, name):
            raise PluginProxyError(
                "{}: Illegal attempt to access attribute '{}' on plugin: {}".format(self._owner, name, self._plugin)
            )
        raise AttributeError("{}: Has no attribute '{}'".format(self._plugin, name))

    ##############################################################
    #                   Exposed proxied APIs                     #
    ##############################################################
    @property
    def name(self):
        return self._plugin.name

    def get_kind(self) -> str:
        return self._plugin.get_kind()

    @property
    def _unique_id(self):
        return self._plugin._unique_id