-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmain.py
155 lines (108 loc) · 4.19 KB
/
main.py
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import json
import os
import logging
import symenu
import subprocess
from wox import Wox,WoxAPI
class Main(Wox):
'''Initializes the plug-in.
This plug-in is requiring a 'config.json' file, must be alongside the
plug-in root directory.
The required configuration parameters are:
SyMenuRoot - Path to the SyMenu program root on the system.
SoftwareRoot - Path to the actual portable software managed by SyMenu.
It's required to resolve relative path definitions made by SyMenu in it's
configuration.
The escaped backslashes in path definitions are required due to JSON compatibility.
Example:
{
"SyMenuRoot": "p:\\software\\SyMenu",
"SoftwareRoot": "p:\\software"
}
'''
_config = dict()
def __init__(self, config_file):
'''Grabs the configuration file.
Additionally some Wox API behavior must be initialized as well by
calling the parent __init__() method. If not the plug-in won't work
correctly.
Args:
config_file (str): Path to the configuration file.
'''
config = self._read_config(config_file)
try:
if self._check_config(config):
Main._config = config
except ConfigError as e:
logging.error(e)
super().__init__()
def query(self, query):
'''Delegates a query on the SyMenu item file and is called by Wox.
This method is inherited from Wox() and needs to be overridden with
custom query code.
Args:
query (str): The query string.
Returns:
list: A list of directories compatible with the Wox API.
Every match of the query is represented by a dictionary.
The following keys are used:
Title - The program name.
SubTitle - The full path to the executable.
IcoPath - The full path to a icon file. Generated by SyMenu.
JsonRPCAction - Another dictionary with these keys:
method - 'open_process' the method to call when item is selected.
parameters - path to application.
The list can be empty also.
'''
config = self._get_config()
symenu_loader = symenu.SyMenu(config['SyMenuRoot'], config['SoftwareRoot'])
result = symenu_loader.find_items(query)
return result
@classmethod
def _get_config(self):
# TODO: ValueError?
if not Main._config:
raise ValueError
return Main._config
# TODO: Really a class method?
# TODO: Check different place?
@classmethod
def _check_config(cls, config):
try:
if not config['SyMenuRoot']:
raise ConfigError('Path is missing')
except KeyError as e:
raise ConfigError ('Config element is missing', e)
try:
if not config['SoftwareRoot']:
raise ConfigError('Path is missing')
except KeyError as e:
raise ConfigError ('Config element is missing', e)
return True
# TODO: Really a class method?
@classmethod
def _read_config(cls, config_file):
config = dict()
# TODO: Exception handling
try:
with open(config_file, 'r') as config_file:
config = json.loads(config_file.read())
except OSError as e:
raise ConfigError('Cannot read config', e)
return config
def open_process(self, path):
'''Opens a new process, the application selected in the Wox dialog.
This method is called from the Wox API regarding the result dictionary
queried by query().
Args:
path (str): The path to an executable .
'''
# TODO: Correct handling of subprocess or path exceptions
subprocess.Popen(os.path.normpath(path), shell=False)
class ConfigError(Exception):
def __init__(self, message, exception=None):
super().__init__('{0}: {1}'.format(message, exception if exception is not None else ''))
self.original_exception = exception
if __name__ == '__main__':
plugin = Main(os.path.join(os.path.dirname(__file__),'config.json'))
# plugin = Main()