Passed
Push — master ( c7c9ef...a777de )
by Alexander
05:19
created

things3.things3_app.Things3App.closing()   A

Complexity

Conditions 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nop 2
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
4
"""KanbanView (app) for Things 3."""
5
6
from __future__ import print_function
7
8
import sys
9
import signal
10
from os import system
11
from threading import Thread
12
import webview  # type: ignore
13
import objc  # type: ignore # pylint: disable=unused-import # noqa F401
0 ignored issues
show
introduced by
Unable to import 'objc'
Loading history...
14
import things3.things3_api as things3_api
15
16
17
class Things3App:
18
    """App wrapper for simple read-only API for Things 3."""
19
20
    database = None
21
    FILE = "kanban.html"
22
    api = None
23
    api_thread = None
24
25
    def open_api(self):
26
        """Delay opening the browser."""
27
        print(f"Using database 2: {self.database}")
28
        self.api.main()
29
30
    def __init__(self, database=None):
31
        self.database = database
32
        self.api = things3_api.Things3API(database=self.database)
33
34
    def sigterm_handler(self, _signo, _stack_frame):
35
        """Make sure the server shuts down."""
36
        print("Sigterm...")
37
        self.api.flask_context.shutdown()
38
39
    def main(self, appstore=False):
40
        """Run the app."""
41
        # kill possible zombie processes; can't use psutil in py2app context
42
        system("lsof -nti:" + str(things3_api.Things3API.port) + " | xargs kill -9")
43
44
        # Make sure the server shuts down
45
        signal.signal(signal.SIGTERM, self.sigterm_handler)
46
47
        print(f"Using database 1: {self.database}")
48
49
        self.window = webview.create_window(
0 ignored issues
show
Coding Style introduced by
The attribute window was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
50
            title="KanbanView",
51
            url=f"http://{things3_api.Things3API.host}:"
52
            + f"{things3_api.Things3API.port}/{self.FILE}",
53
            width=1280,
54
            height=650,
55
            min_size=(1280, 650),
56
            frameless=False,
57
        )
58
59
        if not appstore:
60
            self.window.closed += advertise
61
        self.window.closing += self.closing
62
        self.api_thread = Thread(target=self.open_api)
63
64
        try:
65
            self.api_thread.start()
66
            webview.start(self.closing, self.window)  # blocking
67
            self.api.flask_context.shutdown()
68
            self.api_thread.join()
69
        except KeyboardInterrupt:
70
            print("Shutting down...")
71
            self.api.flask_context.shutdown()
72
            self.api_thread.join()
73
            sys.exit(0)
74
75
    def closing(self, _window=None):
76
        """Close the app"""
77
        if not _window:
78
            self.window.destroy()
79
            # self.api.flask_context.shutdown()
80
            # self.api_thread.join()
81
        else:
82
            print(f"Registering close function for: {_window}")
83
84
85
def advertise():
86
    """Show a hint to buy the app"""
87
    text = (
88
        "Thank you for using KanbanView! "
89
        + "If you enjoy using it, please consider buying the app."
90
    )
91
    title = "KanbanView"
92
    url = "https://kanbanview.app"
93
    system(
94
        """osascript -e ' """
95
        + f"""set dialog to (display dialog "{text}" """
96
        + """buttons {"Buy", "Later"} default button 1 """
97
        + """giving up after 10 """
98
        + f"""with title "{title}" """
99
        + """with icon POSIX file "resources/icon.icns")' """
100
        + """-e 'if the button returned of the result is "Buy" then' """
101
        + f"""-e 'do shell script "open {url}"' -e 'end if'"""
102
    )
103
104
105
def main():
106
    """Main entry point for CLI installation"""
107
    Things3App().main()
108
109
110
if __name__ == "__main__":
111
    main()
112