~m-buck/+junk/gtk-desktop-info

« back to all changes in this revision

Viewing changes to plugin_shell.py

  • Committer: Mark Buck (Kaivalagi)
  • Date: 2009-06-19 17:13:00 UTC
  • Revision ID: m_buck@hotmail.com-20090619171300-5cbhr90xwg62z27y
Added --backgroundblend and --backgroundcolour options for visual seperation of output from wallpaper if required, Fixed song length output in the rhythmbox plugin when songs are an hour long or more, Added copy option to right click, enabling the copying of html content to the clipboard for testing, Moved common functions into a plugin_common module

Show diffs side-by-side

added added

removed removed

Lines of Context:
6
6
#
7
7
#  Author: Kaivalagi
8
8
# Created: 23/11/2008
9
 
from htmlentitydefs import name2codepoint, codepoint2name
 
9
from plugin_common import getHTMLText, getTypedValue
10
10
from optparse import OptionParser
11
11
import traceback
12
12
import codecs
24
24
class ShellConfig:
25
25
    HEADERTEMPLATE = None
26
26
    TEMPLATE = None
27
 
    
 
27
 
28
28
class Output:
29
 
    
 
29
 
30
30
    output = u""
31
31
    error = u""
32
32
 
34
34
        self.options = options
35
35
        self.logger = logging.getLogger(app_name+"."+module_name)
36
36
        self.loadConfigData()
37
 
            
 
37
 
38
38
    def loadConfigData(self):
39
 
        try:         
 
39
        try:
40
40
 
41
41
            self.config = ShellConfig()
42
 
            
 
42
 
43
43
            if self.options.config != None:
44
44
                # load the config based on options passed in from the main app
45
45
                configfilepath = self.options.config
46
46
            else:
47
47
                # load plugin config from home directory of the user
48
48
                configfilepath = os.path.join(os.path.expanduser('~'), ".config/"+app_name+"/"+module_name+".config")
49
 
                            
 
49
 
50
50
            if os.path.exists(configfilepath):
51
 
                
 
51
 
52
52
                self.logger.info("Loading config settings from \"%s\""%configfilepath)
53
 
                
 
53
 
54
54
                for line in fileinput.input(os.path.expanduser(configfilepath)):
55
55
                    line = line.strip()
56
56
                    if len(line) > 0 and line[0:1] != "#": # ignore commented lines or empty ones
57
 
    
 
57
 
58
58
                        name = line.split("=")[0].strip().upper() # config setting name on the left of =
59
59
                        value = line.split("=")[1].split("#")[0].strip() # config value on the right of = (minus any trailing comments)
60
 
    
 
60
 
61
61
                        if len(value) > 0:
62
62
                            if name == "HEADERTEMPLATE":
63
 
                                self.config.HEADERTEMPLATE = self.getTypedValue(value, "string")                            
 
63
                                self.config.HEADERTEMPLATE = getTypedValue(value, "string")
64
64
                            elif name == "TEMPLATE":
65
 
                                self.config.TEMPLATE = self.getTypedValue(value, "string")                                                                                      
 
65
                                self.config.TEMPLATE = getTypedValue(value, "string")
66
66
                            else:
67
67
                                self.logger.error("Unknown option in config file: " + name)
68
68
            else:
69
69
                self.logger.info("Config data file %s not found, using defaults and setting up config file for next time" % configfilepath)
70
 
                
 
70
 
71
71
                userconfigpath = os.path.join(os.path.expanduser('~'), ".config/"+app_name+"/")
72
72
                configsource = os.path.join(app_path, "config/"+module_name+".config")
73
 
                
 
73
 
74
74
                if os.path.exists(userconfigpath) == False:
75
75
                    os.makedirs(userconfigpath)
76
76
 
77
77
                shutil.copy(configsource, configfilepath)
78
 
                
 
78
 
79
79
        except Exception, e:
80
80
            self.logger.error(e.__str__()+"\n"+traceback.format_exc())
81
81
 
82
 
    def getTypedValue(self, value, expectedtype):
83
 
        
84
 
        try:
85
 
            if len(value.strip(" ")) == 0:
86
 
                return None
87
 
            
88
 
            elif value.lower() == "true":
89
 
                if expectedtype == "boolean":
90
 
                    return True
91
 
                else:
92
 
                    self.logger.error("Expected type was '%s', but the value '%s' was given"%(expectedtype, value))
93
 
                    
94
 
            elif value.lower() == "false":
95
 
                if expectedtype == "boolean":
96
 
                    return False
97
 
                else:
98
 
                    self.logger.error("Expected type was '%s', but the value '%s' was given"%(expectedtype, value))
99
 
                    
100
 
            elif self.isNumeric(value) == True:
101
 
                if expectedtype == "integer":
102
 
                    return int(value)
103
 
                else:
104
 
                    self.logger.error("Expected type was '%s', but the value '%s' was given"%(expectedtype, value))
105
 
                    
106
 
            else:
107
 
                return value
108
 
 
109
 
        except (TypeError, ValueError):
110
 
            self.logger.error("Cannot convert '%s' to expected type of '%s'"%(value,expectedtype))
111
 
            return value
112
 
 
113
82
    def getShellCommandOutput(self, shell_command):
114
83
 
115
84
        self.logger.info("Running shell command '%s'"%shell_command)
116
 
        
 
85
 
117
86
        proc = subprocess.Popen(shell_command,
118
87
                           shell=True,
119
88
                           stdout=subprocess.PIPE,
120
89
                           )
121
90
        output = proc.communicate()[0].rstrip("\n")
122
 
        
123
 
        output = self.getHTMLText(output)
 
91
 
 
92
        output = getHTMLText(output)
124
93
        return output
125
94
 
126
95
 
128
97
        output = u""
129
98
        end = False
130
99
        a = 0
131
 
        
 
100
 
132
101
        # a and b are indexes in the template string
133
102
        # moving from left to right the string is processed
134
103
        # b is index of the opening bracket and a of the closing bracket
135
104
        # everything between b and a is a template that needs to be parsed
136
105
        while not end:
137
106
            b = template.find('[', a)
138
 
            
 
107
 
139
108
            if b == -1:
140
109
                b = len(template)
141
110
                end = True
142
 
            
 
111
 
143
112
            # if there is something between a and b, append it straight to output
144
113
            if b > a:
145
114
                output += template[a : b]
150
119
                    # skip the bracket in the input string and continue from the beginning
151
120
                    a = b + 1
152
121
                    continue
153
 
                    
 
122
 
154
123
            if end:
155
124
                break
156
 
            
 
125
 
157
126
            a = template.find(']', b)
158
 
            
 
127
 
159
128
            if a == -1:
160
129
                self.logger.error("Missing terminal bracket (]) for a template item")
161
130
                return u""
162
 
            
 
131
 
163
132
            # if there is some template text...
164
133
            if a > b + 1:
165
134
                output += self.getShellCommandOutput(template[b + 1 : a])
166
 
            
 
135
 
167
136
            a = a + 1
168
137
 
169
138
        return output
170
 
    
 
139
 
171
140
    def getOutput(self):
172
141
 
173
142
        if self.options.noheader == True:
183
152
            headertemplatefilepath = app_path+"/templates/nullheader.template"
184
153
            self.logger.info("Using default header template")
185
154
 
186
 
         # load the file
 
155
        # load the file
187
156
        try:
188
157
            inputfile = codecs.open(os.path.expanduser(headertemplatefilepath), encoding='utf-8')
189
158
        except Exception, e:
192
161
            headertemplate = inputfile.read()
193
162
        finally:
194
163
            inputfile.close()
195
 
            
 
164
 
196
165
        if self.options.template != None:
197
166
            templatefilepath = self.options.template
198
167
            self.logger.info("Using custom template file '%s'"%templatefilepath)
202
171
        else:
203
172
            templatefilepath = app_path+"/templates/shell.template"
204
173
            self.logger.info("Using default template")
205
 
             
 
174
 
206
175
        # load the file
207
176
        try:
208
177
            inputfile = codecs.open(os.path.expanduser(templatefilepath), encoding='utf-8')
218
187
 
219
188
        return output.encode("utf-8")
220
189
 
221
 
    def getHTMLText(self,text):
222
 
        try:
223
 
            htmlentities = []               
224
 
            for char in text: #html:
225
 
                if ord(char) < 128:
226
 
                    htmlentities.append(char)
227
 
                else:
228
 
                    htmlentities.append('&%s;' % codepoint2name[ord(char)])
229
 
            html = "".join(htmlentities)
230
 
            
231
 
            html = html.replace("\n","<br>\n") # switch out new line for html breaks
232
 
            return html            
233
 
        except:
234
 
            return text
235
 
 
236
 
    def getCleanText(self,html):
237
 
        try:
238
 
            text = str(html)
239
 
            text = text.replace("\n","") # remove new lines from html
240
 
            text = text.replace("&apos;","'") # workaround for shitty xml codes not compliant with html
241
 
            text = text.replace("<br>","\n") # switch out html breaks for new line
242
 
            text = re.sub('<(.|\n)+?>','',text) # remove any html tags
243
 
            text =  re.sub('&(%s);' % '|'.join(name2codepoint), lambda m: chr(name2codepoint[m.group(1)]), text)
244
 
            return text            
245
 
        except:
246
 
            return html
247
 
    
248
 
    def isNumeric(self,value):
249
 
        try:
250
 
            temp = int(value)
251
 
            return True
252
 
        except:
253
 
            return False
254
 
 
255
190
def getHTML(options):
256
191
    output = Output(options)
257
192
    html = output.getOutput()
260
195
 
261
196
# to enable testing in isolation
262
197
if __name__ == "__main__":
263
 
    
 
198
 
264
199
    parser = OptionParser()
265
 
    parser.add_option("--noheader", dest="noheader", default=False, action="store_true", help=u"Turn off header output. This will override any header template setting to be nothing")        
 
200
    parser.add_option("--noheader", dest="noheader", default=False, action="store_true", help=u"Turn off header output. This will override any header template setting to be nothing")
266
201
    parser.add_option("--headertemplate", dest="headertemplate", type="string", metavar="FILE", help=u"Override the header template for the plugin, default or config based template ignored.")
267
202
    parser.add_option("--template", dest="template", type="string", metavar="FILE", help=u"Override the template for the plugin, default or config based template ignored.")
268
203
    parser.add_option("--verbose", dest="verbose", default=False, action="store_true", help=u"Outputs verbose info to the terminal")
269
204
    parser.add_option("--version", dest="version", default=False, action="store_true", help=u"Displays the version of the script.")
270
 
    parser.add_option("--logfile", dest="logfile", type="string", metavar="FILE", help=u"If a filepath is set, the script logs to the filepath.")                
271
 
    
 
205
    parser.add_option("--logfile", dest="logfile", type="string", metavar="FILE", help=u"If a filepath is set, the script logs to the filepath.")
 
206
 
272
207
    (options, args) = parser.parse_args()
273
 
        
 
208
 
274
209
    output = Output(options)
275
210
    html = output.getOutput()
276
211
    del output