Failed Conditions
Pull Request — master (#1093)
by Lasse
01:45
created

coalib.output.dbus.DbusServer.dispose_document()   A

Complexity

Conditions 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 3
dl 0
loc 14
rs 9.4286
1
import os
2
import dbus.service
3
4
from coalib.output.dbus.DbusApp import DbusApp
5
6
7
class DbusServer(dbus.service.Object):
8
    interface = "org.coala_analyzer.v1"
9
10
    def __init__(self, bus, path, on_disconnected=None):
11
        """
12
        Creates a new DbusServer class which handles the dynamic creation and
13
        disposal of dbus object-paths for documents and also handles
14
        information about DbusApplication.
15
16
        :param bus:             The dbus bus to which to connect this object
17
                                path to.
18
        :param path:            The path in the dbus bus using which apps can
19
                                communicate.
20
        :param on_disconnected: This function will be called when the
21
                                DbusServer has no more applications connected
22
                                to it.
23
        """
24
        dbus.service.Object.__init__(self, bus, path)
25
26
        self.apps = {}
27
        self.__next_app_id = 0
28
        self.on_disconnected = on_disconnected
29
30
        bus.add_signal_receiver(self._on_name_lost,
31
                                signal_name='NameOwnerChanged',
32
                                dbus_interface=None,
33
                                path=None)
34
35
    @dbus.service.method(interface,
36
                         in_signature="s",
37
                         out_signature="o",
38
                         sender_keyword="sender")
39
    def CreateDocument(self, path, sender=None):
40
        """
41
        Creates a DbusDocument if it doesn't exist.
42
43
        :param path:   The path to the document.
44
        :param sender: The client who created the dbus request - this is used
45
                       as the DbusApp's name.
46
        :return:       a DbusDocument object.
47
        """
48
        app = self.get_or_create_app(sender)
49
        doc = self.get_or_create_document(app, path)
50
        return doc._object_path
51
52
    @dbus.service.method(interface,
53
                         in_signature="s",
54
                         out_signature="",
55
                         sender_keyword="sender")
56
    def DisposeDocument(self, path, sender=None):
57
        """
58
        Disposes a DbusDocument if it exists. Fails silently if it does not
59
        exist.
60
61
        :param path:   The path to the document.
62
        :param sender: The client who created the dbus request - this is used
63
                       as the DbusApp's name to search for the document in.
64
        """
65
        path = os.path.normpath(path)
66
67
        try:
68
            app = self.apps[sender]
69
        except KeyError:
70
            return
71
72
        self.dispose_document(app, path)
73
74
    def _on_name_lost(self, name, oldowner, newowner):
75
        if newowner != '':
76
            return
77
78
        self.dispose_app(oldowner)
79
80
    def _next_app_id(self):
81
        self.__next_app_id += 1
82
        return self.__next_app_id
83
84
    def create_app(self, appname):
85
        """
86
        Create a new dbus app with the given appname.
87
88
        :param appname: The name of the app to be created.
89
        :return:        a DbusApp object.
90
        """
91
        self.apps[appname] = DbusApp(self._next_app_id(), appname)
92
        return self.apps[appname]
93
94
    def get_or_create_app(self, appname):
95
        """
96
        Get the dbus app with the given appname. If there does not exist any
97
        app with the given name, a new app is created and returned.
98
99
        :param appname: The name of the app to be created.
100
        :return:        A DbusApp object.
101
        """
102
        try:
103
            return self.apps[appname]
104
        except KeyError:
105
            return self.create_app(appname)
106
107
    def dispose_app(self, appname):
108
        """
109
        Dispose of the app with the given name. It fails silently if the app
110
        does not exist. If there are no more apps connected to the server, it
111
        calls the on_disconnected callback.
112
113
        :param appname: The name of the app to dispose of.
114
        """
115
        try:
116
            self.apps.pop(appname)
117
            if len(self.apps) == 0 and self.on_disconnected:
118
                self.on_disconnected()
119
        except KeyError:
120
            pass
121
122
    def create_document(self, app, path):
123
        """
124
        Create a new dbus document.
125
126
        :param app:  The DbusApp the document is related to.
127
        :param path: The path to the document to be created.
128
        :return:     a DbusDocument object.
129
        """
130
        doc = app.create_document(path)
131
        objpath = (self._object_path + "/" + str(app.app_id) +
132
                   "/documents/" + str(doc.doc_id))
133
        doc.add_to_connection(self._connection, objpath)
134
135
        return doc
136
137
    def get_or_create_document(self, app, path):
138
        """
139
        Get the dbus document with the given path. If there does not exist any
140
        document under the DbusApp with the given path, a new document is
141
        created and returned.
142
143
        :param app:  The DbusApp the document is under.
144
        :param path: The path to the document to be created.
145
        :return:     A DbusApp object.
146
        """
147
        path = os.path.abspath(os.path.expanduser(path))
148
        try:
149
            doc = app.docs[path]
150
        except KeyError:
151
            doc = self.create_document(app, path)
152
153
        return doc
154
155
    def dispose_document(self, app, path):
156
        """
157
        Dispose of the document with the given path. It fails silently if the
158
        document does not exist. If there are no more documents in the app,
159
        the app is disposed.
160
161
        :param app:  The DbusApp the document is under.
162
        :param path: The path to the document.
163
        """
164
        doc = app.dispose_document(path)
165
        if doc != None:
166
            doc.remove_from_connection()
167
            if len(app.docs) == 0:
168
                self.dispose_app(app.name)
169