~ubuntu-branches/ubuntu/saucy/hplip/saucy-proposed

« back to all changes in this revision

Viewing changes to .pc/make-commafy-correctly-work-with-python-2.dpatch/base/utils.py

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2012-05-26 11:20:39 UTC
  • mfrom: (1.5.6) (31.1.3 precise)
  • Revision ID: package-import@ubuntu.com-20120526112039-bevxczegxnbyr5m7
Tags: 3.12.4-1
* New upstream release
* Switch to source/format 3.0 (quilt) - drop dpatch
* Refreshed debian/patches
* dh_autoreconf debian/autogen.sh & set local-options single-debian-patch
* Update to debian/compat -> 9
* Fix "hardened build flags" patch from Moritz - thanks (Closes: #667828)
* Fix "duplex descriptor uninitialized" patch from Matej (Closes: #583273)
* Fix "please migrate to kde-runtime" patch from Pino (Closes: #666544)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- coding: utf-8 -*-
 
2
#
 
3
# (c) Copyright 2001-2009 Hewlett-Packard Development Company, L.P.
 
4
#
 
5
# This program is free software; you can redistribute it and/or modify
 
6
# it under the terms of the GNU General Public License as published by
 
7
# the Free Software Foundation; either version 2 of the License, or
 
8
# (at your option) any later version.
 
9
#
 
10
# This program is distributed in the hope that it will be useful,
 
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
# GNU General Public License for more details.
 
14
#
 
15
# You should have received a copy of the GNU General Public License
 
16
# along with this program; if not, write to the Free Software
 
17
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
18
#
 
19
# Author: Don Welch, Naga Samrat Chowdary Narla, Goutam Kodu, Amarnath Chitumalla
 
20
#
 
21
# Thanks to Henrique M. Holschuh <hmh@debian.org> for various security patches
 
22
#
 
23
 
 
24
from __future__ import generators
 
25
 
 
26
# Std Lib
 
27
import sys
 
28
import os
 
29
from subprocess import Popen, PIPE
 
30
import grp
 
31
import fnmatch
 
32
import tempfile
 
33
import socket
 
34
import struct
 
35
import select
 
36
import time
 
37
import fcntl
 
38
import errno
 
39
import stat
 
40
import string
 
41
import commands # TODO: Replace with subprocess (commands is deprecated in Python 3.0)
 
42
import cStringIO
 
43
import re
 
44
import xml.parsers.expat as expat
 
45
import getpass
 
46
import locale
 
47
import htmlentitydefs
 
48
import urllib
 
49
 
 
50
try:
 
51
    import platform
 
52
    platform_avail = True
 
53
except ImportError:
 
54
    platform_avail = False
 
55
 
 
56
# Local
 
57
from g import *
 
58
from codes import *
 
59
import pexpect
 
60
 
 
61
BIG_ENDIAN = 0
 
62
LITTLE_ENDIAN = 1
 
63
 
 
64
def addgroup():
 
65
    lis = []
 
66
    try:
 
67
        fp=open('/etc/cups/cupsd.conf')
 
68
    except IOError:
 
69
        try:
 
70
            if "root" != grp.getgrgid(os.stat('/etc/cups/cupsd.conf').st_gid).gr_name:
 
71
                return [grp.getgrgid(os.stat('/etc/cups/cupsd.conf').st_gid).gr_name]
 
72
        except OSError:
 
73
            return lis
 
74
 
 
75
    try:
 
76
        lis = ((re.findall('SystemGroup [\w* ]*',fp.read()))[0].replace('SystemGroup ','')).split(' ')
 
77
    except IndexError:
 
78
        return lis
 
79
 
 
80
    if 'root' in lis:
 
81
        lis.remove('root')
 
82
    fp.close()
 
83
    return lis
 
84
 
 
85
def list_to_string(lis):
 
86
    if len(lis) == 0:
 
87
        return ""
 
88
    if len(lis) == 1:
 
89
        return str("\""+lis[0]+"\"")
 
90
    if len(lis) >= 1:
 
91
        return "\""+"\", \"".join(lis)+"\" and \""+str(lis.pop())+"\""
 
92
        
 
93
def lock(f):
 
94
    log.debug("Locking: %s" % f.name)
 
95
    try:
 
96
        fcntl.flock(f.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
 
97
        return True
 
98
    except (IOError, OSError):
 
99
        log.debug("Failed to unlock %s." % f.name)
 
100
        return False
 
101
 
 
102
 
 
103
def unlock(f):
 
104
    if f is not None:
 
105
        log.debug("Unlocking: %s" % f.name)
 
106
        try:
 
107
            fcntl.flock(f.fileno(), fcntl.LOCK_UN)
 
108
            os.remove(f.name)
 
109
        except (IOError, OSError):
 
110
            pass
 
111
 
 
112
 
 
113
def lock_app(application, suppress_error=False):
 
114
    dir = prop.user_dir
 
115
    if os.geteuid() == 0:
 
116
        dir = '/var'
 
117
 
 
118
    elif not os.path.exists(dir):
 
119
        os.makedirs(dir)
 
120
 
 
121
    lock_file = os.path.join(dir, '.'.join([application, 'lock']))
 
122
    try:
 
123
        lock_file_f = open(lock_file, "w")
 
124
    except IOError:
 
125
        if not suppress_error:
 
126
            log.error("Unable to open %s lock file." % lock_file)
 
127
        return False, None
 
128
 
 
129
    #log.debug("Locking file: %s" % lock_file)
 
130
 
 
131
    if not lock(lock_file_f):
 
132
        if not suppress_error:
 
133
            log.error("Unable to lock %s. Is %s already running?" % (lock_file, application))
 
134
        return False, None
 
135
 
 
136
    return True, lock_file_f
 
137
 
 
138
 
 
139
#xml_basename_pat = re.compile(r"""HPLIP-(\d*)_(\d*)_(\d*).xml""", re.IGNORECASE)
 
140
 
 
141
 
 
142
def Translator(frm='', to='', delete='', keep=None):
 
143
    allchars = string.maketrans('','')
 
144
 
 
145
    if len(to) == 1:
 
146
        to = to * len(frm)
 
147
    trans = string.maketrans(frm, to)
 
148
 
 
149
    if keep is not None:
 
150
        delete = allchars.translate(allchars, keep.translate(allchars, delete))
 
151
 
 
152
    def callable(s):
 
153
        return s.translate(trans, delete)
 
154
 
 
155
    return callable
 
156
 
 
157
 
 
158
def to_bool_str(s, default='0'):
 
159
    """ Convert an arbitrary 0/1/T/F/Y/N string to a normalized string 0/1."""
 
160
    if isinstance(s, str) and s:
 
161
        if s[0].lower() in ['1', 't', 'y']:
 
162
            return u'1'
 
163
        elif s[0].lower() in ['0', 'f', 'n']:
 
164
            return u'0'
 
165
 
 
166
    return default
 
167
 
 
168
def to_bool(s, default=False):
 
169
    """ Convert an arbitrary 0/1/T/F/Y/N string to a boolean True/False value."""
 
170
    if isinstance(s, str) and s:
 
171
        if s[0].lower() in ['1', 't', 'y']:
 
172
            return True
 
173
        elif s[0].lower() in ['0', 'f', 'n']:
 
174
            return False
 
175
    elif isinstance(s, bool):
 
176
        return s
 
177
 
 
178
    return default
 
179
 
 
180
 
 
181
def walkFiles(root, recurse=True, abs_paths=False, return_folders=False, pattern='*', path=None):
 
182
    if path is None:
 
183
        path = root
 
184
 
 
185
    try:
 
186
        names = os.listdir(root)
 
187
    except os.error:
 
188
        raise StopIteration
 
189
 
 
190
    pattern = pattern or '*'
 
191
    pat_list = pattern.split(';')
 
192
 
 
193
    for name in names:
 
194
        fullname = os.path.normpath(os.path.join(root, name))
 
195
 
 
196
        for pat in pat_list:
 
197
            if fnmatch.fnmatch(name, pat):
 
198
                if return_folders or not os.path.isdir(fullname):
 
199
                    if abs_paths:
 
200
                        yield fullname
 
201
                    else:
 
202
                        try:
 
203
                            yield os.path.basename(fullname)
 
204
                        except ValueError:
 
205
                            yield fullname
 
206
 
 
207
        #if os.path.islink(fullname):
 
208
        #    fullname = os.path.realpath(os.readlink(fullname))
 
209
 
 
210
        if recurse and os.path.isdir(fullname): # or os.path.islink(fullname):
 
211
            for f in walkFiles(fullname, recurse, abs_paths, return_folders, pattern, path):
 
212
                yield f
 
213
 
 
214
 
 
215
def is_path_writable(path):
 
216
    if os.path.exists(path):
 
217
        s = os.stat(path)
 
218
        mode = s[stat.ST_MODE] & 0777
 
219
 
 
220
        if mode & 02:
 
221
            return True
 
222
        elif s[stat.ST_GID] == os.getgid() and mode & 020:
 
223
            return True
 
224
        elif s[stat.ST_UID] == os.getuid() and mode & 0200:
 
225
            return True
 
226
 
 
227
    return False
 
228
 
 
229
 
 
230
# Provides the TextFormatter class for formatting text into columns.
 
231
# Original Author: Hamish B Lawson, 1999
 
232
# Modified by: Don Welch, 2003
 
233
class TextFormatter:
 
234
 
 
235
    LEFT  = 0
 
236
    CENTER = 1
 
237
    RIGHT  = 2
 
238
 
 
239
    def __init__(self, colspeclist):
 
240
        self.columns = []
 
241
        for colspec in colspeclist:
 
242
            self.columns.append(Column(**colspec))
 
243
 
 
244
    def compose(self, textlist, add_newline=False):
 
245
        numlines = 0
 
246
        textlist = list(textlist)
 
247
        if len(textlist) != len(self.columns):
 
248
            log.error("Formatter: Number of text items does not match columns")
 
249
            return
 
250
        for text, column in map(None, textlist, self.columns):
 
251
            column.wrap(text)
 
252
            numlines = max(numlines, len(column.lines))
 
253
        complines = [''] * numlines
 
254
        for ln in range(numlines):
 
255
            for column in self.columns:
 
256
                complines[ln] = complines[ln] + column.getline(ln)
 
257
        if add_newline:
 
258
            return '\n'.join(complines) + '\n'
 
259
        else:
 
260
            return '\n'.join(complines)
 
261
 
 
262
class Column:
 
263
 
 
264
    def __init__(self, width=78, alignment=TextFormatter.LEFT, margin=0):
 
265
        self.width = width
 
266
        self.alignment = alignment
 
267
        self.margin = margin
 
268
        self.lines = []
 
269
 
 
270
    def align(self, line):
 
271
        if self.alignment == TextFormatter.CENTER:
 
272
            return line.center(self.width)
 
273
        elif self.alignment == TextFormatter.RIGHT:
 
274
            return line.rjust(self.width)
 
275
        else:
 
276
            return line.ljust(self.width)
 
277
 
 
278
    def wrap(self, text):
 
279
        self.lines = []
 
280
        words = []
 
281
        for word in text.split():
 
282
            if word <= self.width:
 
283
                words.append(word)
 
284
            else:
 
285
                for i in range(0, len(word), self.width):
 
286
                    words.append(word[i:i+self.width])
 
287
        if not len(words): return
 
288
        current = words.pop(0)
 
289
        for word in words:
 
290
            increment = 1 + len(word)
 
291
            if len(current) + increment > self.width:
 
292
                self.lines.append(self.align(current))
 
293
                current = word
 
294
            else:
 
295
                current = current + ' ' + word
 
296
        self.lines.append(self.align(current))
 
297
 
 
298
    def getline(self, index):
 
299
        if index < len(self.lines):
 
300
            return ' '*self.margin + self.lines[index]
 
301
        else:
 
302
            return ' ' * (self.margin + self.width)
 
303
 
 
304
 
 
305
 
 
306
class Stack:
 
307
    def __init__(self):
 
308
        self.stack = []
 
309
 
 
310
    def pop(self):
 
311
        return self.stack.pop()
 
312
 
 
313
    def push(self, value):
 
314
        self.stack.append(value)
 
315
 
 
316
    def as_list(self):
 
317
        return self.stack
 
318
 
 
319
    def clear(self):
 
320
        self.stack = []
 
321
 
 
322
    def __len__(self):
 
323
        return len(self.stack)
 
324
 
 
325
 
 
326
 
 
327
class Queue(Stack):
 
328
    def __init__(self):
 
329
        Stack.__init__(self)
 
330
 
 
331
    def get(self):
 
332
        return self.stack.pop(0)
 
333
 
 
334
    def put(self, value):
 
335
        Stack.push(self, value)
 
336
 
 
337
 
 
338
 
 
339
# RingBuffer class
 
340
# Source: Python Cookbook 1st Ed., sec. 5.18, pg. 201
 
341
# Credit: Sebastien Keim
 
342
# License: Modified BSD
 
343
class RingBuffer:
 
344
    def __init__(self, size_max=50):
 
345
        self.max = size_max
 
346
        self.data = []
 
347
 
 
348
    def append(self,x):
 
349
        """append an element at the end of the buffer"""
 
350
        self.data.append(x)
 
351
 
 
352
        if len(self.data) == self.max:
 
353
            self.cur = 0
 
354
            self.__class__ = RingBufferFull
 
355
 
 
356
    def replace(self, x):
 
357
        """replace the last element instead off appending"""
 
358
        self.data[-1] = x
 
359
 
 
360
    def get(self):
 
361
        """ return a list of elements from the oldest to the newest"""
 
362
        return self.data
 
363
 
 
364
 
 
365
class RingBufferFull:
 
366
    def __init__(self, n):
 
367
        #raise "you should use RingBuffer"
 
368
        pass
 
369
 
 
370
    def append(self, x):
 
371
        self.data[self.cur] = x
 
372
        self.cur = (self.cur+1) % self.max
 
373
 
 
374
    def replace(self, x):
 
375
        # back up 1 position to previous location
 
376
        self.cur = (self.cur-1) % self.max
 
377
        self.data[self.cur] = x
 
378
        # setup for next item
 
379
        self.cur = (self.cur+1) % self.max
 
380
 
 
381
    def get(self):
 
382
        return self.data[self.cur:] + self.data[:self.cur]
 
383
 
 
384
 
 
385
 
 
386
def sort_dict_by_value(d):
 
387
    """ Returns the keys of dictionary d sorted by their values """
 
388
    items=d.items()
 
389
    backitems=[[v[1],v[0]] for v in items]
 
390
    backitems.sort()
 
391
    return [backitems[i][1] for i in range(0, len(backitems))]
 
392
 
 
393
 
 
394
def commafy(val):
 
395
    return unicode(locale.format("%d", val, grouping=True))
 
396
 
 
397
 
 
398
def format_bytes(s, show_bytes=False):
 
399
    if s < 1024:
 
400
        return ''.join([commafy(s), ' B'])
 
401
    elif 1024 < s < 1048576:
 
402
        if show_bytes:
 
403
            return ''.join([unicode(round(s/1024.0, 1)) , u' KB (',  commafy(s), ')'])
 
404
        else:
 
405
            return ''.join([unicode(round(s/1024.0, 1)) , u' KB'])
 
406
    elif 1048576 < s < 1073741824:
 
407
        if show_bytes:
 
408
            return ''.join([unicode(round(s/1048576.0, 1)), u' MB (',  commafy(s), ')'])
 
409
        else:
 
410
            return ''.join([unicode(round(s/1048576.0, 1)), u' MB'])
 
411
    else:
 
412
        if show_bytes:
 
413
            return ''.join([unicode(round(s/1073741824.0, 1)), u' GB (',  commafy(s), ')'])
 
414
        else:
 
415
            return ''.join([unicode(round(s/1073741824.0, 1)), u' GB'])
 
416
 
 
417
 
 
418
 
 
419
try:
 
420
    make_temp_file = tempfile.mkstemp # 2.3+
 
421
except AttributeError:
 
422
    def make_temp_file(suffix='', prefix='', dir='', text=False): # pre-2.3
 
423
        path = tempfile.mktemp(suffix)
 
424
        fd = os.open(path, os.O_RDWR|os.O_CREAT|os.O_EXCL, 0700)
 
425
        return ( os.fdopen( fd, 'w+b' ), path )
 
426
 
 
427
 
 
428
 
 
429
def which(command, return_full_path=False):
 
430
    path = os.getenv('PATH').split(':')
 
431
 
 
432
    # Add these paths for Fedora
 
433
    path.append('/sbin')
 
434
    path.append('/usr/sbin')
 
435
    path.append('/usr/local/sbin')
 
436
 
 
437
    found_path = ''
 
438
    for p in path:
 
439
        try:
 
440
            files = os.listdir(p)
 
441
        except OSError:
 
442
            continue
 
443
        else:
 
444
            if command in files:
 
445
                found_path = p
 
446
                break
 
447
 
 
448
    if return_full_path:
 
449
        if found_path:
 
450
            return os.path.join(found_path, command)
 
451
        else:
 
452
            return ''
 
453
    else:
 
454
        return found_path
 
455
 
 
456
 
 
457
class UserSettings(object): # Note: Deprecated after 2.8.8 in Qt4 (see ui4/ui_utils.py)
 
458
    def __init__(self):
 
459
        self.load()
 
460
 
 
461
    def loadDefaults(self):
 
462
        # Print
 
463
        self.cmd_print = ''
 
464
        path = which('hp-print')
 
465
 
 
466
        if len(path) > 0:
 
467
            self.cmd_print = 'hp-print -p%PRINTER%'
 
468
        else:
 
469
            path = which('kprinter')
 
470
            if len(path) > 0:
 
471
                self.cmd_print = 'kprinter -P%PRINTER% --system cups'
 
472
            else:
 
473
                path = which('gtklp')
 
474
                if len(path) > 0:
 
475
                    self.cmd_print = 'gtklp -P%PRINTER%'
 
476
                else:
 
477
                    path = which('xpp')
 
478
                    if len(path) > 0:
 
479
                        self.cmd_print = 'xpp -P%PRINTER%'
 
480
 
 
481
        # Scan
 
482
        self.cmd_scan = ''
 
483
        path = which('simple-scan')
 
484
        if len(path) > 0:
 
485
            self.cmd_scan = 'simple-scan %SANE_URI%'
 
486
        else:
 
487
            path = which('xsane')
 
488
            if len(path) > 0:
 
489
                self.cmd_scan = 'xsane -V %SANE_URI%'
 
490
            else:
 
491
                path = which('kooka')
 
492
                if len(path) > 0:
 
493
                    self.cmd_scan = 'kooka'
 
494
                else:
 
495
                    path = which('xscanimage')
 
496
                    if len(path) > 0:
 
497
                        self.cmd_scan = 'xscanimage'
 
498
 
 
499
        # Photo Card
 
500
        path = which('hp-unload')
 
501
 
 
502
        if len(path):
 
503
            self.cmd_pcard = 'hp-unload -d %DEVICE_URI%'
 
504
        else:
 
505
            self.cmd_pcard = 'python %HOME%/unload.py -d %DEVICE_URI%'
 
506
 
 
507
        # Copy
 
508
        path = which('hp-makecopies')
 
509
 
 
510
        if len(path):
 
511
            self.cmd_copy = 'hp-makecopies -d %DEVICE_URI%'
 
512
        else:
 
513
            self.cmd_copy = 'python %HOME%/makecopies.py -d %DEVICE_URI%'
 
514
 
 
515
        # Fax
 
516
        path = which('hp-sendfax')
 
517
 
 
518
        if len(path):
 
519
            self.cmd_fax = 'hp-sendfax -d %FAX_URI%'
 
520
        else:
 
521
            self.cmd_fax = 'python %HOME%/sendfax.py -d %FAX_URI%'
 
522
 
 
523
        # Fax Address Book
 
524
        path = which('hp-fab')
 
525
 
 
526
        if len(path):
 
527
            self.cmd_fab = 'hp-fab'
 
528
        else:
 
529
            self.cmd_fab = 'python %HOME%/fab.py'
 
530
 
 
531
    def load(self):
 
532
        self.loadDefaults()
 
533
        log.debug("Loading user settings...")
 
534
        self.auto_refresh = to_bool(user_conf.get('refresh', 'enable', '0'))
 
535
 
 
536
        try:
 
537
            self.auto_refresh_rate = int(user_conf.get('refresh', 'rate', '30'))
 
538
        except ValueError:
 
539
            self.auto_refresh_rate = 30 # (secs)
 
540
 
 
541
        try:
 
542
            self.auto_refresh_type = int(user_conf.get('refresh', 'type', '0'))
 
543
        except ValueError:
 
544
            self.auto_refresh_type = 0 # refresh 1 (1=refresh all)
 
545
 
 
546
        self.cmd_print = user_conf.get('commands', 'prnt', self.cmd_print)
 
547
        self.cmd_scan = user_conf.get('commands', 'scan', self.cmd_scan)
 
548
        self.cmd_pcard = user_conf.get('commands', 'pcard', self.cmd_pcard)
 
549
        self.cmd_copy = user_conf.get('commands', 'cpy', self.cmd_copy)
 
550
        self.cmd_fax = user_conf.get('commands', 'fax', self.cmd_fax)
 
551
        self.cmd_fab = user_conf.get('commands', 'fab', self.cmd_fab)
 
552
 
 
553
        self.upgrade_notify= to_bool(user_conf.get('upgrade', 'notify_upgrade', '0'))
 
554
        self.upgrade_last_update_time = int(user_conf.get('upgrade','last_upgraded_time', '0'))
 
555
        self.upgrade_pending_update_time =int(user_conf.get('upgrade', 'pending_upgrade_time', '0'))
 
556
        self.latest_available_version=str(user_conf.get('upgrade', 'latest_available_version',''))
 
557
        self.debug()
 
558
 
 
559
    def debug(self):
 
560
        log.debug("Print command: %s" % self.cmd_print)
 
561
        log.debug("PCard command: %s" % self.cmd_pcard)
 
562
        log.debug("Fax command: %s" % self.cmd_fax)
 
563
        log.debug("FAB command: %s" % self.cmd_fab)
 
564
        log.debug("Copy command: %s " % self.cmd_copy)
 
565
        log.debug("Scan command: %s" % self.cmd_scan)
 
566
        log.debug("Auto refresh: %s" % self.auto_refresh)
 
567
        log.debug("Auto refresh rate: %s" % self.auto_refresh_rate)
 
568
        log.debug("Auto refresh type: %s" % self.auto_refresh_type)
 
569
        log.debug("Upgrade notification:%d"  %self.upgrade_notify)
 
570
        log.debug("Last Installed time:%d" %self.upgrade_last_update_time)
 
571
        log.debug("Next scheduled installation time:%d" % self.upgrade_pending_update_time)
 
572
 
 
573
 
 
574
    def save(self):
 
575
        log.debug("Saving user settings...")
 
576
        user_conf.set('commands', 'prnt', self.cmd_print)
 
577
        user_conf.set('commands', 'pcard', self.cmd_pcard)
 
578
        user_conf.set('commands', 'fax', self.cmd_fax)
 
579
        user_conf.set('commands', 'scan', self.cmd_scan)
 
580
        user_conf.set('commands', 'cpy', self.cmd_copy)
 
581
        user_conf.set('refresh', 'enable',self.auto_refresh)
 
582
        user_conf.set('refresh', 'rate', self.auto_refresh_rate)
 
583
        user_conf.set('refresh', 'type', self.auto_refresh_type)
 
584
        user_conf.set('upgrade', 'notify_upgrade', self.upgrade_notify)
 
585
        user_conf.set('upgrade','last_upgraded_time', self.upgrade_last_update_time)
 
586
        user_conf.set('upgrade', 'pending_upgrade_time', self.upgrade_pending_update_time)
 
587
        user_conf.set('upgrade', 'latest_available_version', self.latest_available_version)
 
588
 
 
589
        self.debug()
 
590
 
 
591
 
 
592
 
 
593
def no_qt_message_gtk():
 
594
    try:
 
595
        import gtk
 
596
        w = gtk.Window()
 
597
        dialog = gtk.MessageDialog(w, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
 
598
                                   gtk.MESSAGE_WARNING, gtk.BUTTONS_OK,
 
599
                                   "PyQt not installed. GUI not available. Please check that the PyQt package is installed. Exiting.")
 
600
        dialog.run()
 
601
        dialog.destroy()
 
602
 
 
603
    except ImportError:
 
604
        log.error("PyQt not installed. GUI not available. Please check that the PyQt package is installed. Exiting.")
 
605
 
 
606
 
 
607
def canEnterGUIMode(): # qt3
 
608
    if not prop.gui_build:
 
609
        log.warn("GUI mode disabled in build.")
 
610
        return False
 
611
 
 
612
    elif not os.getenv('DISPLAY'):
 
613
        log.warn("No display found.")
 
614
        return False
 
615
 
 
616
    elif not checkPyQtImport():
 
617
        log.warn("Qt/PyQt 3 initialization failed.")
 
618
        return False
 
619
 
 
620
    return True
 
621
 
 
622
 
 
623
def canEnterGUIMode4(): # qt4
 
624
    if not prop.gui_build:
 
625
        log.warn("GUI mode disabled in build.")
 
626
        return False
 
627
 
 
628
    elif not os.getenv('DISPLAY'):
 
629
        log.warn("No display found.")
 
630
        return False
 
631
 
 
632
    elif not checkPyQtImport4():
 
633
        log.warn("Qt/PyQt 4 initialization failed.")
 
634
        return False
 
635
 
 
636
    return True
 
637
 
 
638
 
 
639
def checkPyQtImport(): # qt3
 
640
    # PyQt
 
641
    try:
 
642
        import qt
 
643
    except ImportError:
 
644
        if os.getenv('DISPLAY') and os.getenv('STARTED_FROM_MENU'):
 
645
            no_qt_message_gtk()
 
646
 
 
647
        log.error("PyQt not installed. GUI not available. Exiting.")
 
648
        return False
 
649
 
 
650
    # check version of Qt
 
651
    qtMajor = int(qt.qVersion().split('.')[0])
 
652
 
 
653
    if qtMajor < MINIMUM_QT_MAJOR_VER:
 
654
 
 
655
        log.error("Incorrect version of Qt installed. Ver. 3.0.0 or greater required.")
 
656
        return False
 
657
 
 
658
    #check version of PyQt
 
659
    try:
 
660
        pyqtVersion = qt.PYQT_VERSION_STR
 
661
    except AttributeError:
 
662
        pyqtVersion = qt.PYQT_VERSION
 
663
 
 
664
    while pyqtVersion.count('.') < 2:
 
665
        pyqtVersion += '.0'
 
666
 
 
667
    (maj_ver, min_ver, pat_ver) = pyqtVersion.split('.')
 
668
 
 
669
    if pyqtVersion.find('snapshot') >= 0:
 
670
        log.warning("A non-stable snapshot version of PyQt is installed.")
 
671
    else:
 
672
        try:
 
673
            maj_ver = int(maj_ver)
 
674
            min_ver = int(min_ver)
 
675
            pat_ver = int(pat_ver)
 
676
        except ValueError:
 
677
            maj_ver, min_ver, pat_ver = 0, 0, 0
 
678
 
 
679
        if maj_ver < MINIMUM_PYQT_MAJOR_VER or \
 
680
            (maj_ver == MINIMUM_PYQT_MAJOR_VER and min_ver < MINIMUM_PYQT_MINOR_VER):
 
681
            log.error("This program may not function properly with the version of PyQt that is installed (%d.%d.%d)." % (maj_ver, min_ver, pat_ver))
 
682
            log.error("Incorrect version of pyQt installed. Ver. %d.%d or greater required." % (MINIMUM_PYQT_MAJOR_VER, MINIMUM_PYQT_MINOR_VER))
 
683
            log.error("This program will continue, but you may experience errors, crashes or other problems.")
 
684
            return True
 
685
 
 
686
    return True
 
687
 
 
688
 
 
689
def checkPyQtImport4():
 
690
    try:
 
691
        import PyQt4
 
692
    except ImportError:
 
693
        return False
 
694
    else:
 
695
        return True
 
696
 
 
697
 
 
698
try:
 
699
    from string import Template # will fail in Python <= 2.3
 
700
except ImportError:
 
701
    # Code from Python 2.4 string.py
 
702
    #import re as _re
 
703
 
 
704
    class _multimap:
 
705
        """Helper class for combining multiple mappings.
 
706
 
 
707
        Used by .{safe_,}substitute() to combine the mapping and keyword
 
708
        arguments.
 
709
        """
 
710
        def __init__(self, primary, secondary):
 
711
            self._primary = primary
 
712
            self._secondary = secondary
 
713
 
 
714
        def __getitem__(self, key):
 
715
            try:
 
716
                return self._primary[key]
 
717
            except KeyError:
 
718
                return self._secondary[key]
 
719
 
 
720
 
 
721
    class _TemplateMetaclass(type):
 
722
        pattern = r"""
 
723
        %(delim)s(?:
 
724
          (?P<escaped>%(delim)s) |   # Escape sequence of two delimiters
 
725
          (?P<named>%(id)s)      |   # delimiter and a Python identifier
 
726
          {(?P<braced>%(id)s)}   |   # delimiter and a braced identifier
 
727
          (?P<invalid>)              # Other ill-formed delimiter exprs
 
728
        )
 
729
        """
 
730
 
 
731
        def __init__(cls, name, bases, dct):
 
732
            super(_TemplateMetaclass, cls).__init__(name, bases, dct)
 
733
            if 'pattern' in dct:
 
734
                pattern = cls.pattern
 
735
            else:
 
736
                pattern = _TemplateMetaclass.pattern % {
 
737
                    'delim' : re.escape(cls.delimiter),
 
738
                    'id'    : cls.idpattern,
 
739
                    }
 
740
            cls.pattern = re.compile(pattern, re.IGNORECASE | re.VERBOSE)
 
741
 
 
742
 
 
743
    class Template:
 
744
        """A string class for supporting $-substitutions."""
 
745
        __metaclass__ = _TemplateMetaclass
 
746
 
 
747
        delimiter = '$'
 
748
        idpattern = r'[_a-z][_a-z0-9]*'
 
749
 
 
750
        def __init__(self, template):
 
751
            self.template = template
 
752
 
 
753
        # Search for $$, $identifier, ${identifier}, and any bare $'s
 
754
        def _invalid(self, mo):
 
755
            i = mo.start('invalid')
 
756
            lines = self.template[:i].splitlines(True)
 
757
            if not lines:
 
758
                colno = 1
 
759
                lineno = 1
 
760
            else:
 
761
                colno = i - len(''.join(lines[:-1]))
 
762
                lineno = len(lines)
 
763
            raise ValueError('Invalid placeholder in string: line %d, col %d' %
 
764
                             (lineno, colno))
 
765
 
 
766
        def substitute(self, *args, **kws):
 
767
            if len(args) > 1:
 
768
                raise TypeError('Too many positional arguments')
 
769
            if not args:
 
770
                mapping = kws
 
771
            elif kws:
 
772
                mapping = _multimap(kws, args[0])
 
773
            else:
 
774
                mapping = args[0]
 
775
            # Helper function for .sub()
 
776
            def convert(mo):
 
777
                # Check the most common path first.
 
778
                named = mo.group('named') or mo.group('braced')
 
779
                if named is not None:
 
780
                    val = mapping[named]
 
781
                    # We use this idiom instead of str() because the latter will
 
782
                    # fail if val is a Unicode containing non-ASCII characters.
 
783
                    return '%s' % val
 
784
                if mo.group('escaped') is not None:
 
785
                    return self.delimiter
 
786
                if mo.group('invalid') is not None:
 
787
                    self._invalid(mo)
 
788
                raise ValueError('Unrecognized named group in pattern',
 
789
                                 self.pattern)
 
790
            return self.pattern.sub(convert, self.template)
 
791
 
 
792
 
 
793
        def safe_substitute(self, *args, **kws):
 
794
            if len(args) > 1:
 
795
                raise TypeError('Too many positional arguments')
 
796
            if not args:
 
797
                mapping = kws
 
798
            elif kws:
 
799
                mapping = _multimap(kws, args[0])
 
800
            else:
 
801
                mapping = args[0]
 
802
            # Helper function for .sub()
 
803
            def convert(mo):
 
804
                named = mo.group('named')
 
805
                if named is not None:
 
806
                    try:
 
807
                        # We use this idiom instead of str() because the latter
 
808
                        # will fail if val is a Unicode containing non-ASCII
 
809
                        return '%s' % mapping[named]
 
810
                    except KeyError:
 
811
                        return self.delimiter + named
 
812
                braced = mo.group('braced')
 
813
                if braced is not None:
 
814
                    try:
 
815
                        return '%s' % mapping[braced]
 
816
                    except KeyError:
 
817
                        return self.delimiter + '{' + braced + '}'
 
818
                if mo.group('escaped') is not None:
 
819
                    return self.delimiter
 
820
                if mo.group('invalid') is not None:
 
821
                    return self.delimiter
 
822
                raise ValueError('Unrecognized named group in pattern',
 
823
                                 self.pattern)
 
824
            return self.pattern.sub(convert, self.template)
 
825
 
 
826
 
 
827
 
 
828
#cat = lambda _ : Template(_).substitute(sys._getframe(1).f_globals, **sys._getframe(1).f_locals)
 
829
 
 
830
def cat(s):
 
831
    globals = sys._getframe(1).f_globals.copy()
 
832
    if 'self' in globals:
 
833
        del globals['self']
 
834
 
 
835
    locals = sys._getframe(1).f_locals.copy()
 
836
    if 'self' in locals:
 
837
        del locals['self']
 
838
 
 
839
    return Template(s).substitute(sys._getframe(1).f_globals, **locals)
 
840
 
 
841
 
 
842
identity = string.maketrans('','')
 
843
unprintable = identity.translate(identity, string.printable)
 
844
 
 
845
 
 
846
def printable(s):
 
847
    return s.translate(identity, unprintable)
 
848
 
 
849
 
 
850
def any(S,f=lambda x:x):
 
851
    for x in S:
 
852
        if f(x): return True
 
853
    return False
 
854
 
 
855
 
 
856
def all(S,f=lambda x:x):
 
857
    for x in S:
 
858
        if not f(x): return False
 
859
    return True
 
860
 
 
861
 
 
862
BROWSERS = ['firefox', 'mozilla', 'konqueror', 'galeon', 'skipstone'] # in preferred order
 
863
BROWSER_OPTS = {'firefox': '-new-window', 'mozilla' : '', 'konqueror': '', 'galeon': '-w', 'skipstone': ''}
 
864
 
 
865
 
 
866
def find_browser():
 
867
    if platform_avail and platform.system() == 'Darwin':
 
868
        return "open"
 
869
    else:
 
870
        for b in BROWSERS:
 
871
            if which(b):
 
872
                return b
 
873
        else:
 
874
            return None
 
875
 
 
876
 
 
877
def openURL(url, use_browser_opts=True):
 
878
    if platform_avail and platform.system() == 'Darwin':
 
879
        cmd = 'open "%s"' % url
 
880
        log.debug(cmd)
 
881
        os.system(cmd)
 
882
    else:
 
883
        for b in BROWSERS:
 
884
            bb = which(b)
 
885
            if bb:
 
886
                bb = os.path.join(bb, b)
 
887
                if use_browser_opts:
 
888
                    cmd = """%s %s "%s" &""" % (bb, BROWSER_OPTS[b], url)
 
889
                else:
 
890
                    cmd = """%s "%s" &""" % (bb, url)
 
891
                log.debug(cmd)
 
892
                os.system(cmd)
 
893
                break
 
894
        else:
 
895
            log.warn("Unable to open URL: %s" % url)
 
896
 
 
897
 
 
898
def uniqueList(input):
 
899
    temp = []
 
900
    [temp.append(i) for i in input if not temp.count(i)]
 
901
    return temp
 
902
 
 
903
 
 
904
def list_move_up(l, m, cmp=None):
 
905
    if cmp is None:
 
906
        f = lambda x: l[x] == m
 
907
    else:
 
908
        f = lambda x: cmp(l[x], m)
 
909
 
 
910
    for i in range(1, len(l)):
 
911
        if f(i):
 
912
            l[i-1], l[i] = l[i], l[i-1]
 
913
 
 
914
 
 
915
def list_move_down(l, m, cmp=None):
 
916
    if cmp is None:
 
917
        f = lambda x: l[x] == m
 
918
    else:
 
919
        f = lambda x: cmp(l[x], m)
 
920
 
 
921
    for i in range(len(l)-2, -1, -1):
 
922
        if f(i):
 
923
            l[i], l[i+1] = l[i+1], l[i]
 
924
 
 
925
 
 
926
 
 
927
class XMLToDictParser:
 
928
    def __init__(self):
 
929
        self.stack = []
 
930
        self.data = {}
 
931
        self.last_start = ''
 
932
 
 
933
    def startElement(self, name, attrs):
 
934
        #print "START:", name, attrs
 
935
        self.stack.append(unicode(name).lower())
 
936
        self.last_start = unicode(name).lower()
 
937
 
 
938
        if len(attrs):
 
939
            for a in attrs:
 
940
                self.stack.append(unicode(a).lower())
 
941
                self.addData(attrs[a])
 
942
                self.stack.pop()
 
943
 
 
944
    def endElement(self, name):
 
945
        if name.lower() == self.last_start:
 
946
            self.addData('')
 
947
 
 
948
        #print "END:", name
 
949
        self.stack.pop()
 
950
 
 
951
    def charData(self, data):
 
952
        data = unicode(data).strip()
 
953
 
 
954
        if data and self.stack:
 
955
            self.addData(data)
 
956
 
 
957
    def addData(self, data):
 
958
        #print "DATA:", data
 
959
        self.last_start = ''
 
960
        try:
 
961
            data = int(data)
 
962
        except ValueError:
 
963
            data = unicode(data)
 
964
 
 
965
        stack_str = '-'.join(self.stack)
 
966
        stack_str_0 = '-'.join([stack_str, '0'])
 
967
 
 
968
        try:
 
969
            self.data[stack_str]
 
970
        except KeyError:
 
971
            try:
 
972
                self.data[stack_str_0]
 
973
            except KeyError:
 
974
                self.data[stack_str] = data
 
975
            else:
 
976
                j = 2
 
977
                while True:
 
978
                    try:
 
979
                        self.data['-'.join([stack_str, unicode(j)])]
 
980
                    except KeyError:
 
981
                        self.data['-'.join([stack_str, unicode(j)])] = data
 
982
                        break
 
983
                    j += 1
 
984
 
 
985
        else:
 
986
            self.data[stack_str_0] = self.data[stack_str]
 
987
            self.data['-'.join([stack_str, '1'])] = data
 
988
            del self.data[stack_str]
 
989
 
 
990
 
 
991
    def parseXML(self, text):
 
992
        parser = expat.ParserCreate()
 
993
        parser.StartElementHandler = self.startElement
 
994
        parser.EndElementHandler = self.endElement
 
995
        parser.CharacterDataHandler = self.charData
 
996
        parser.Parse(text.encode('utf-8'), True)
 
997
        return self.data
 
998
 
 
999
 
 
1000
def dquote(s):
 
1001
    return ''.join(['"', s, '"'])
 
1002
 
 
1003
 
 
1004
# Python 2.2.x compatibility functions (strip() family with char argument added in Python 2.2.3)
 
1005
if sys.hexversion < 0x020203f0:
 
1006
    def xlstrip(s, chars=' '):
 
1007
        i = 0
 
1008
        for c, i in zip(s, range(len(s))):
 
1009
            if c not in chars:
 
1010
                break
 
1011
 
 
1012
        return s[i:]
 
1013
 
 
1014
    def xrstrip(s, chars=' '):
 
1015
        return xreverse(xlstrip(xreverse(s), chars))
 
1016
 
 
1017
    def xreverse(s):
 
1018
        l = list(s)
 
1019
        l.reverse()
 
1020
        return ''.join(l)
 
1021
 
 
1022
    def xstrip(s, chars=' '):
 
1023
        return xreverse(xlstrip(xreverse(xlstrip(s, chars)), chars))
 
1024
 
 
1025
else:
 
1026
    xlstrip = string.lstrip
 
1027
    xrstrip = string.rstrip
 
1028
    xstrip = string.strip
 
1029
 
 
1030
 
 
1031
def getBitness():
 
1032
    if platform_avail:
 
1033
        return int(platform.architecture()[0][:-3])
 
1034
    else:
 
1035
        return struct.calcsize("P") << 3
 
1036
 
 
1037
 
 
1038
def getProcessor():
 
1039
    if platform_avail:
 
1040
        return platform.machine().replace(' ', '_').lower() # i386, i686, power_macintosh, etc.
 
1041
    else:
 
1042
        return "i686" # TODO: Need a fix here
 
1043
 
 
1044
 
 
1045
def getEndian():
 
1046
    if sys.byteorder == 'big':
 
1047
        return BIG_ENDIAN
 
1048
    else:
 
1049
        return LITTLE_ENDIAN
 
1050
 
 
1051
 
 
1052
def get_password():
 
1053
    return getpass.getpass("Enter password: ")
 
1054
 
 
1055
def get_password_ui(pswd_msg=''):
 
1056
    fp = open("/etc/hp/hplip.conf", "r")
 
1057
    qt = "qt3"
 
1058
    for line in fp:
 
1059
        if string.find(line, "qt4") is not -1 and string.find(line, "yes") is not -1:
 
1060
            qt = "qt4"
 
1061
    fp.close()
 
1062
    if qt is "qt4":
 
1063
        from ui4.setupdialog import showPasswordUI
 
1064
        if pswd_msg == '':
 
1065
            username, password = showPasswordUI("Your HP Device requires to install HP proprietary plugin\nPlease enter root/superuser password to continue", "root", False)
 
1066
        else:
 
1067
            username, password = showPasswordUI(pswd_msg, "root", False)
 
1068
    if qt is "qt3":
 
1069
        from ui.setupform import showPasswordUI
 
1070
        if pswd_msg == '':
 
1071
            username, password = showPasswordUI("Your HP Device requires to install HP proprietary plugin\nPlease enter root/superuser password to continue", "root", False)
 
1072
        else:
 
1073
            username, password = showPasswordUI(pswd_msg, "root", False)
 
1074
    return  password
 
1075
 
 
1076
def run(cmd, log_output=True, password_func=get_password, timeout=1, spinner=True, pswd_msg=''):
 
1077
    output = cStringIO.StringIO()
 
1078
 
 
1079
    try:
 
1080
        child = pexpect.spawn(cmd, timeout=timeout)
 
1081
    except pexpect.ExceptionPexpect:
 
1082
        return -1, ''
 
1083
 
 
1084
    try:
 
1085
        while True:
 
1086
            if spinner:
 
1087
                update_spinner()
 
1088
 
 
1089
            i = child.expect(["[pP]assword:", pexpect.EOF, pexpect.TIMEOUT])
 
1090
 
 
1091
            if child.before:
 
1092
                output.write(child.before)
 
1093
                if log_output:
 
1094
                    log.debug(child.before)
 
1095
 
 
1096
            if i == 0: # Password:
 
1097
                if password_func is not None:
 
1098
                    if password_func == "get_password_ui":
 
1099
                        child.sendline(get_password_ui(pswd_msg))
 
1100
                    else:
 
1101
                        child.sendline(password_func())
 
1102
                else:
 
1103
                    child.sendline(get_password())
 
1104
                
 
1105
 
 
1106
            elif i == 1: # EOF
 
1107
                break
 
1108
 
 
1109
            elif i == 2: # TIMEOUT
 
1110
                continue
 
1111
 
 
1112
 
 
1113
    except Exception, e:
 
1114
        log.error("Exception: %s" % e)
 
1115
    if spinner:
 
1116
        cleanup_spinner()
 
1117
    child.close()
 
1118
 
 
1119
    return child.exitstatus, output.getvalue()
 
1120
 
 
1121
 
 
1122
def expand_range(ns): # ns -> string repr. of numeric range, e.g. "1-4, 7, 9-12"
 
1123
    """Credit: Jean Brouwers, comp.lang.python 16-7-2004
 
1124
       Convert a string representation of a set of ranges into a
 
1125
       list of ints, e.g.
 
1126
       u"1-4, 7, 9-12" --> [1,2,3,4,7,9,10,11,12]
 
1127
    """
 
1128
    fs = []
 
1129
    for n in ns.split(u','):
 
1130
        n = n.strip()
 
1131
        r = n.split('-')
 
1132
        if len(r) == 2:  # expand name with range
 
1133
            h = r[0].rstrip(u'0123456789')  # header
 
1134
            r[0] = r[0][len(h):]
 
1135
             # range can't be empty
 
1136
            if not (r[0] and r[1]):
 
1137
                raise ValueError, 'empty range: ' + n
 
1138
             # handle leading zeros
 
1139
            if r[0] == u'0' or r[0][0] != u'0':
 
1140
                h += '%d'
 
1141
            else:
 
1142
                w = [len(i) for i in r]
 
1143
                if w[1] > w[0]:
 
1144
                   raise ValueError, 'wide range: ' + n
 
1145
                h += u'%%0%dd' % max(w)
 
1146
             # check range
 
1147
            r = [int(i, 10) for i in r]
 
1148
            if r[0] > r[1]:
 
1149
               raise ValueError, 'bad range: ' + n
 
1150
            for i in range(r[0], r[1]+1):
 
1151
                fs.append(h % i)
 
1152
        else:  # simple name
 
1153
            fs.append(n)
 
1154
 
 
1155
     # remove duplicates
 
1156
    fs = dict([(n, i) for i, n in enumerate(fs)]).keys()
 
1157
     # convert to ints and sort
 
1158
    fs = [int(x) for x in fs if x]
 
1159
    fs.sort()
 
1160
 
 
1161
    return fs
 
1162
 
 
1163
 
 
1164
def collapse_range(x): # x --> sorted list of ints
 
1165
    """ Convert a list of integers into a string
 
1166
        range representation:
 
1167
        [1,2,3,4,7,9,10,11,12] --> u"1-4,7,9-12"
 
1168
    """
 
1169
    if not x:
 
1170
        return ''
 
1171
 
 
1172
    s, c, r = [str(x[0])], x[0], False
 
1173
 
 
1174
    for i in x[1:]:
 
1175
        if i == (c+1):
 
1176
            r = True
 
1177
        else:
 
1178
            if r:
 
1179
                s.append(u'-%s,%s' % (c,i))
 
1180
                r = False
 
1181
            else:
 
1182
                s.append(u',%s' % i)
 
1183
 
 
1184
        c = i
 
1185
 
 
1186
    if r:
 
1187
        s.append(u'-%s' % i)
 
1188
 
 
1189
    return ''.join(s)
 
1190
 
 
1191
 
 
1192
def createSequencedFilename(basename, ext, dir=None, digits=3):
 
1193
    if dir is None:
 
1194
        dir = os.getcwd()
 
1195
 
 
1196
    m = 0
 
1197
    for f in walkFiles(dir, recurse=False, abs_paths=False, return_folders=False, pattern='*', path=None):
 
1198
        r, e = os.path.splitext(f)
 
1199
 
 
1200
        if r.startswith(basename) and ext == e:
 
1201
            try:
 
1202
                i = int(r[len(basename):])
 
1203
            except ValueError:
 
1204
                continue
 
1205
            else:
 
1206
                m = max(m, i)
 
1207
 
 
1208
    return os.path.join(dir, "%s%0*d%s" % (basename, digits, m+1, ext))
 
1209
 
 
1210
 
 
1211
def validate_language(lang, default='en_US'):
 
1212
    if lang is None:
 
1213
        loc, encoder = locale.getdefaultlocale()
 
1214
    else:
 
1215
        lang = lang.lower().strip()
 
1216
        for loc, ll in supported_locales.items():
 
1217
            if lang in ll:
 
1218
                break
 
1219
        else:
 
1220
            loc = 'en_US'
 
1221
            log.warn("Unknown lang/locale. Using default of %s." % loc)
 
1222
 
 
1223
    return loc
 
1224
 
 
1225
 
 
1226
def gen_random_uuid():
 
1227
    try:
 
1228
        import uuid # requires Python 2.5+
 
1229
        return str(uuid.uuid4())
 
1230
 
 
1231
    except ImportError:
 
1232
        uuidgen = which("uuidgen")
 
1233
        if uuidgen:
 
1234
            uuidgen = os.path.join(uuidgen, "uuidgen")
 
1235
            return commands.getoutput(uuidgen) # TODO: Replace with subprocess (commands is deprecated in Python 3.0)
 
1236
        else:
 
1237
            return ''
 
1238
 
 
1239
 
 
1240
class RestTableFormatter(object):
 
1241
    def __init__(self, header=None):
 
1242
        self.header = header # tuple of strings
 
1243
        self.rows = [] # list of tuples
 
1244
 
 
1245
    def add(self, row_data): # tuple of strings
 
1246
        self.rows.append(row_data)
 
1247
 
 
1248
    def output(self, w):
 
1249
        if self.rows:
 
1250
            num_cols = len(self.rows[0])
 
1251
            for r in self.rows:
 
1252
                if len(r) != num_cols:
 
1253
                    log.error("Invalid number of items in row: %s" % r)
 
1254
                    return
 
1255
 
 
1256
            if len(self.header) != num_cols:
 
1257
                log.error("Invalid number of items in header.")
 
1258
 
 
1259
            col_widths = []
 
1260
            for x, c in enumerate(self.header):
 
1261
                max_width = len(c)
 
1262
                for r in self.rows:
 
1263
                    max_width = max(max_width, len(r[x]))
 
1264
 
 
1265
                col_widths.append(max_width+2)
 
1266
 
 
1267
            x = '+'
 
1268
            for c in col_widths:
 
1269
                x = ''.join([x, '-' * (c+2), '+'])
 
1270
 
 
1271
            x = ''.join([x, '\n'])
 
1272
            w.write(x)
 
1273
 
 
1274
            # header
 
1275
            if self.header:
 
1276
                x = '|'
 
1277
                for i, c in enumerate(col_widths):
 
1278
                    x = ''.join([x, ' ', self.header[i], ' ' * (c+1-len(self.header[i])), '|'])
 
1279
 
 
1280
                x = ''.join([x, '\n'])
 
1281
                w.write(x)
 
1282
 
 
1283
                x = '+'
 
1284
                for c in col_widths:
 
1285
                    x = ''.join([x, '=' * (c+2), '+'])
 
1286
 
 
1287
                x = ''.join([x, '\n'])
 
1288
                w.write(x)
 
1289
 
 
1290
            # data rows
 
1291
            for j, r in enumerate(self.rows):
 
1292
                x = '|'
 
1293
                for i, c in enumerate(col_widths):
 
1294
                    x = ''.join([x, ' ', self.rows[j][i], ' ' * (c+1-len(self.rows[j][i])), '|'])
 
1295
 
 
1296
                x = ''.join([x, '\n'])
 
1297
                w.write(x)
 
1298
 
 
1299
                x = '+'
 
1300
                for c in col_widths:
 
1301
                    x = ''.join([x, '-' * (c+2), '+'])
 
1302
 
 
1303
                x = ''.join([x, '\n'])
 
1304
                w.write(x)
 
1305
 
 
1306
        else:
 
1307
            log.error("No data rows")
 
1308
 
 
1309
 
 
1310
def mixin(cls):
 
1311
    import inspect
 
1312
 
 
1313
    locals = inspect.stack()[1][0].f_locals
 
1314
    if "__module__" not in locals:
 
1315
        raise TypeError("Must call mixin() from within class def.")
 
1316
 
 
1317
    dict = cls.__dict__.copy()
 
1318
    dict.pop("__doc__", None)
 
1319
    dict.pop("__module__", None)
 
1320
 
 
1321
    locals.update(dict)
 
1322
 
 
1323
 
 
1324
 
 
1325
# TODO: Move usage stuff to to base/module/Module class
 
1326
 
 
1327
 
 
1328
 # ------------------------- Usage Help
 
1329
USAGE_OPTIONS = ("[OPTIONS]", "", "heading", False)
 
1330
USAGE_LOGGING1 = ("Set the logging level:", "-l<level> or --logging=<level>", 'option', False)
 
1331
USAGE_LOGGING2 = ("", "<level>: none, info\*, error, warn, debug (\*default)", "option", False)
 
1332
USAGE_LOGGING3 = ("Run in debug mode:", "-g (same as option: -ldebug)", "option", False)
 
1333
USAGE_LOGGING_PLAIN = ("Output plain text only:", "-t", "option", False)
 
1334
USAGE_ARGS = ("[PRINTER|DEVICE-URI]", "", "heading", False)
 
1335
USAGE_ARGS2 = ("[PRINTER]", "", "heading", False)
 
1336
USAGE_DEVICE = ("To specify a device-URI:", "-d<device-uri> or --device=<device-uri>", "option", False)
 
1337
USAGE_PRINTER = ("To specify a CUPS printer:", "-p<printer> or --printer=<printer>", "option", False)
 
1338
USAGE_BUS1 = ("Bus to probe (if device not specified):", "-b<bus> or --bus=<bus>", "option", False)
 
1339
USAGE_BUS2 = ("", "<bus>: cups\*, usb\*, net, bt, fw, par\* (\*defaults) (Note: bt and fw not supported in this release.)", 'option', False)
 
1340
USAGE_HELP = ("This help information:", "-h or --help", "option", True)
 
1341
USAGE_SPACE = ("", "", "space", False)
 
1342
USAGE_EXAMPLES = ("Examples:", "", "heading", False)
 
1343
USAGE_NOTES = ("Notes:", "", "heading", False)
 
1344
USAGE_STD_NOTES1 = ("If device or printer is not specified, the local device bus is probed and the program enters interactive mode.", "", "note", False)
 
1345
USAGE_STD_NOTES2 = ("If -p\* is specified, the default CUPS printer will be used.", "", "note", False)
 
1346
USAGE_SEEALSO = ("See Also:", "", "heading", False)
 
1347
USAGE_LANGUAGE = ("Set the language:", "-q <lang> or --lang=<lang>. Use -q? or --lang=? to see a list of available language codes.", "option", False)
 
1348
USAGE_LANGUAGE2 = ("Set the language:", "--lang=<lang>. Use --lang=? to see a list of available language codes.", "option", False)
 
1349
USAGE_MODE = ("[MODE]", "", "header", False)
 
1350
USAGE_NON_INTERACTIVE_MODE = ("Run in non-interactive mode:", "-n or --non-interactive", "option", False)
 
1351
USAGE_GUI_MODE = ("Run in graphical UI mode:", "-u or --gui (Default)", "option", False)
 
1352
USAGE_INTERACTIVE_MODE = ("Run in interactive mode:", "-i or --interactive", "option", False)
 
1353
 
 
1354
if sys_conf.get('configure', 'ui-toolkit', 'qt3') == 'qt3':
 
1355
    USAGE_USE_QT3 = ("Use Qt3:",  "--qt3 (Default)",  "option",  False)
 
1356
    USAGE_USE_QT4 = ("Use Qt4:",  "--qt4",  "option",  False)
 
1357
else:
 
1358
    USAGE_USE_QT3 = ("Use Qt3:",  "--qt3",  "option",  False)
 
1359
    USAGE_USE_QT4 = ("Use Qt4:",  "--qt4 (Default)",  "option",  False)
 
1360
 
 
1361
 
 
1362
 
 
1363
 
 
1364
def ttysize(): # TODO: Move to base/tui
 
1365
    ln1 = commands.getoutput('stty -a').splitlines()[0]
 
1366
    vals = {'rows':None, 'columns':None}
 
1367
    for ph in ln1.split(';'):
 
1368
        x = ph.split()
 
1369
        if len(x) == 2:
 
1370
            vals[x[0]] = x[1]
 
1371
            vals[x[1]] = x[0]
 
1372
    try:
 
1373
        rows, cols = int(vals['rows']), int(vals['columns'])
 
1374
    except TypeError:
 
1375
        rows, cols = 25, 80
 
1376
 
 
1377
    return rows, cols
 
1378
 
 
1379
 
 
1380
def usage_formatter(override=0): # TODO: Move to base/module/Module class
 
1381
    rows, cols = ttysize()
 
1382
 
 
1383
    if override:
 
1384
        col1 = override
 
1385
        col2 = cols - col1 - 8
 
1386
    else:
 
1387
        col1 = int(cols / 3) - 8
 
1388
        col2 = cols - col1 - 8
 
1389
 
 
1390
    return TextFormatter(({'width': col1, 'margin' : 2},
 
1391
                            {'width': col2, 'margin' : 2},))
 
1392
 
 
1393
 
 
1394
def format_text(text_list, typ='text', title='', crumb='', version=''): # TODO: Move to base/module/Module class
 
1395
    """
 
1396
    Format usage text in multiple formats:
 
1397
        text: for --help in the console
 
1398
        rest: for conversion with rst2web for the website
 
1399
        man: for manpages
 
1400
    """
 
1401
    if typ == 'text':
 
1402
        formatter = usage_formatter()
 
1403
 
 
1404
        for line in text_list:
 
1405
            text1, text2, format, trailing_space = line
 
1406
 
 
1407
            # remove any reST/man escapes
 
1408
            text1 = text1.replace("\\", "")
 
1409
            text2 = text2.replace("\\", "")
 
1410
 
 
1411
            if format == 'summary':
 
1412
                log.info(log.bold(text1))
 
1413
                log.info("")
 
1414
 
 
1415
            elif format in ('para', 'name', 'seealso'):
 
1416
                log.info(text1)
 
1417
 
 
1418
                if trailing_space:
 
1419
                    log.info("")
 
1420
 
 
1421
            elif format in ('heading', 'header'):
 
1422
                log.info(log.bold(text1))
 
1423
 
 
1424
            elif format in ('option', 'example'):
 
1425
                log.info(formatter.compose((text1, text2), trailing_space))
 
1426
 
 
1427
            elif format == 'note':
 
1428
                if text1.startswith(' '):
 
1429
                    log.info('\t' + text1.lstrip())
 
1430
                else:
 
1431
                    log.info(text1)
 
1432
 
 
1433
            elif format == 'space':
 
1434
                log.info("")
 
1435
 
 
1436
        log.info("")
 
1437
 
 
1438
 
 
1439
    elif typ == 'rest':
 
1440
        opt_colwidth1, opt_colwidth2 = 0, 0
 
1441
        exmpl_colwidth1, exmpl_colwidth2 = 0, 0
 
1442
        note_colwidth1, note_colwidth2 = 0, 0
 
1443
 
 
1444
        for line in text_list:
 
1445
            text1, text2, format, trailing_space = line
 
1446
 
 
1447
            if format  == 'option':
 
1448
                opt_colwidth1 = max(len(text1), opt_colwidth1)
 
1449
                opt_colwidth2 = max(len(text2), opt_colwidth2)
 
1450
 
 
1451
            elif format == 'example':
 
1452
                exmpl_colwidth1 = max(len(text1), exmpl_colwidth1)
 
1453
                exmpl_colwidth2 = max(len(text2), exmpl_colwidth2)
 
1454
 
 
1455
            elif format == 'note':
 
1456
                note_colwidth1 = max(len(text1), note_colwidth1)
 
1457
                note_colwidth2 = max(len(text2), note_colwidth2)
 
1458
 
 
1459
        opt_colwidth1 += 4
 
1460
        opt_colwidth2 += 4
 
1461
        exmpl_colwidth1 += 4
 
1462
        exmpl_colwidth2 += 4
 
1463
        note_colwidth1 += 4
 
1464
        note_colwidth2 += 4
 
1465
        opt_tablewidth = opt_colwidth1 + opt_colwidth2
 
1466
        exmpl_tablewidth = exmpl_colwidth1 + exmpl_colwidth2
 
1467
        note_tablewidth = note_colwidth1 + note_colwidth2
 
1468
 
 
1469
        # write the rst2web header
 
1470
        log.info("""restindex
 
1471
page-title: %s
 
1472
crumb: %s
 
1473
format: rest
 
1474
file-extension: html
 
1475
encoding: utf8
 
1476
/restindex\n""" % (title, crumb))
 
1477
 
 
1478
        t = "%s: %s (ver. %s)" % (crumb, title, version)
 
1479
        log.info(t)
 
1480
        log.info("="*len(t))
 
1481
        log.info("")
 
1482
 
 
1483
        links = []
 
1484
        needs_header = False
 
1485
        for line in text_list:
 
1486
            text1, text2, format, trailing_space = line
 
1487
 
 
1488
            if format == 'seealso':
 
1489
                links.append(text1)
 
1490
                text1 = "`%s`_" % text1
 
1491
 
 
1492
            len1, len2 = len(text1), len(text2)
 
1493
 
 
1494
            if format == 'summary':
 
1495
                log.info(''.join(["**", text1, "**"]))
 
1496
                log.info("")
 
1497
 
 
1498
            elif format in ('para', 'name'):
 
1499
                log.info("")
 
1500
                log.info(text1)
 
1501
                log.info("")
 
1502
 
 
1503
            elif format in ('heading', 'header'):
 
1504
 
 
1505
                log.info("")
 
1506
                log.info("**" + text1 + "**")
 
1507
                log.info("")
 
1508
                needs_header = True
 
1509
 
 
1510
            elif format == 'option':
 
1511
                if needs_header:
 
1512
                    log.info(".. class:: borderless")
 
1513
                    log.info("")
 
1514
                    log.info(''.join(["+", "-"*opt_colwidth1, "+", "-"*opt_colwidth2, "+"]))
 
1515
                    needs_header = False
 
1516
 
 
1517
                if text1 and '`_' not in text1:
 
1518
                    log.info(''.join(["| *", text1, '*', " "*(opt_colwidth1-len1-3), "|", text2, " "*(opt_colwidth2-len2), "|"]))
 
1519
                elif text1:
 
1520
                    log.info(''.join(["|", text1, " "*(opt_colwidth1-len1), "|", text2, " "*(opt_colwidth2-len2), "|"]))
 
1521
                else:
 
1522
                    log.info(''.join(["|", " "*(opt_colwidth1), "|", text2, " "*(opt_colwidth2-len2), "|"]))
 
1523
 
 
1524
                log.info(''.join(["+", "-"*opt_colwidth1, "+", "-"*opt_colwidth2, "+"]))
 
1525
 
 
1526
            elif format == 'example':
 
1527
                if needs_header:
 
1528
                    log.info(".. class:: borderless")
 
1529
                    log.info("")
 
1530
                    log.info(''.join(["+", "-"*exmpl_colwidth1, "+", "-"*exmpl_colwidth2, "+"]))
 
1531
                    needs_header = False
 
1532
 
 
1533
                if text1 and '`_' not in text1:
 
1534
                    log.info(''.join(["| *", text1, '*', " "*(exmpl_colwidth1-len1-3), "|", text2, " "*(exmpl_colwidth2-len2), "|"]))
 
1535
                elif text1:
 
1536
                    log.info(''.join(["|", text1, " "*(exmpl_colwidth1-len1), "|", text2, " "*(exmpl_colwidth2-len2), "|"]))
 
1537
                else:
 
1538
                    log.info(''.join(["|", " "*(exmpl_colwidth1), "|", text2, " "*(exmpl_colwidth2-len2), "|"]))
 
1539
 
 
1540
                log.info(''.join(["+", "-"*exmpl_colwidth1, "+", "-"*exmpl_colwidth2, "+"]))
 
1541
 
 
1542
            elif format == 'seealso':
 
1543
                if text1 and '`_' not in text1:
 
1544
                    log.info(text1)
 
1545
 
 
1546
 
 
1547
            elif format == 'note':
 
1548
                if needs_header:
 
1549
                    log.info(".. class:: borderless")
 
1550
                    log.info("")
 
1551
                    log.info(''.join(["+", "-"*note_colwidth1, "+", "-"*note_colwidth2, "+"]))
 
1552
                    needs_header = False
 
1553
 
 
1554
                if text1.startswith(' '):
 
1555
                    log.info(''.join(["|", " "*(note_tablewidth+1), "|"]))
 
1556
 
 
1557
                log.info(''.join(["|", text1, " "*(note_tablewidth-len1+1), "|"]))
 
1558
                log.info(''.join(["+", "-"*note_colwidth1, "+", "-"*note_colwidth2, "+"]))
 
1559
 
 
1560
            elif format == 'space':
 
1561
                log.info("")
 
1562
 
 
1563
        for l in links:
 
1564
            log.info("\n.. _`%s`: %s.html\n" % (l, l.replace('hp-', '')))
 
1565
 
 
1566
        log.info("")
 
1567
 
 
1568
    elif typ == 'man':
 
1569
        log.info('.TH "%s" 1 "%s" Linux "User Manuals"' % (crumb, version))
 
1570
        log.info(".SH NAME\n%s \- %s" % (crumb, title))
 
1571
 
 
1572
        for line in text_list:
 
1573
            text1, text2, format, trailing_space = line
 
1574
 
 
1575
            text1 = text1.replace("\\*", "*")
 
1576
            text2 = text2.replace("\\*", "*")
 
1577
 
 
1578
            len1, len2 = len(text1), len(text2)
 
1579
 
 
1580
            if format == 'summary':
 
1581
                log.info(".SH SYNOPSIS")
 
1582
                log.info(".B %s" % text1.replace('Usage:', ''))
 
1583
 
 
1584
            elif format == 'name':
 
1585
                log.info(".SH DESCRIPTION\n%s" % text1)
 
1586
 
 
1587
            elif format in ('option', 'example', 'note'):
 
1588
                if text1:
 
1589
                    log.info('.IP "%s"\n%s' % (text1, text2))
 
1590
                else:
 
1591
                    log.info(text2)
 
1592
 
 
1593
            elif format in ('header', 'heading'):
 
1594
                log.info(".SH %s" % text1.upper().replace(':', '').replace('[', '').replace(']', ''))
 
1595
 
 
1596
            elif format in ('seealso, para'):
 
1597
                log.info(text1)
 
1598
 
 
1599
        log.info(".SH AUTHOR")
 
1600
        log.info("HPLIP (Hewlett-Packard Linux Imaging and Printing) is an")
 
1601
        log.info("HP developed solution for printing, scanning, and faxing with")
 
1602
        log.info("HP inkjet and laser based printers in Linux.")
 
1603
 
 
1604
        log.info(".SH REPORTING BUGS")
 
1605
        log.info("The HPLIP Launchpad.net site")
 
1606
        log.info(".B https://launchpad.net/hplip")
 
1607
        log.info("is available to get help, report")
 
1608
        log.info("bugs, make suggestions, discuss the HPLIP project or otherwise")
 
1609
        log.info("contact the HPLIP Team.")
 
1610
 
 
1611
        log.info(".SH COPYRIGHT")
 
1612
        log.info("Copyright (c) 2001-14 Hewlett-Packard Development Company, L.P.")
 
1613
        log.info(".LP")
 
1614
        log.info("This software comes with ABSOLUTELY NO WARRANTY.")
 
1615
        log.info("This is free software, and you are welcome to distribute it")
 
1616
        log.info("under certain conditions. See COPYING file for more details.")
 
1617
 
 
1618
        log.info("")
 
1619
 
 
1620
 
 
1621
def log_title(program_name, version, show_ver=True): # TODO: Move to base/module/Module class
 
1622
    log.info("")
 
1623
 
 
1624
    if show_ver:
 
1625
        log.info(log.bold("HP Linux Imaging and Printing System (ver. %s)" % prop.version))
 
1626
    else:
 
1627
        log.info(log.bold("HP Linux Imaging and Printing System"))
 
1628
 
 
1629
    log.info(log.bold("%s ver. %s" % (program_name, version)))
 
1630
    log.info("")
 
1631
    log.info("Copyright (c) 2001-14 Hewlett-Packard Development Company, LP")
 
1632
    log.info("This software comes with ABSOLUTELY NO WARRANTY.")
 
1633
    log.info("This is free software, and you are welcome to distribute it")
 
1634
    log.info("under certain conditions. See COPYING file for more details.")
 
1635
    log.info("")
 
1636
 
 
1637
 
 
1638
def ireplace(old, search, replace):
 
1639
    regex = '(?i)' + re.escape(search)
 
1640
    return re.sub(regex, replace, old)
 
1641
 
 
1642
 
 
1643
def su_sudo():
 
1644
    su_sudo_str = None
 
1645
 
 
1646
    if which('kdesu'):
 
1647
        su_sudo_str = 'kdesu -- %s'
 
1648
 
 
1649
    elif utils.which('/usr/lib/kde4/libexec/kdesu'):
 
1650
        su_sudo_str = '/usr/lib/kde4/libexec/kdesu -- %s'
 
1651
 
 
1652
    elif utils.which('kdesudo'):
 
1653
        su_sudo_str = 'kdesudo -- %s'
 
1654
 
 
1655
    elif which('gnomesu'):
 
1656
        su_sudo_str = 'gnomesu -c "%s"'
 
1657
 
 
1658
    elif which('gksu'):
 
1659
        su_sudo_str = 'gksu "%s"'
 
1660
    
 
1661
    elif which('su'):
 
1662
        su_sudo_str = 'su'
 
1663
 
 
1664
    return su_sudo_str
 
1665
 
 
1666
# This function returns the distro name and distro version. 
 
1667
#This is provided to check on Fedora 14 in pkit.py file for Plugin-installation. 
 
1668
#is_su variable is used to provide a check on Fedora 8 
 
1669
def os_release():
 
1670
    os_name = None;
 
1671
    os_version = None;
 
1672
    is_su = None;
 
1673
    if which('lsb_release'):
 
1674
       name = os.popen('lsb_release -i | cut -f 2')
 
1675
       os_name = name.read().strip()
 
1676
       name.close()
 
1677
       version = os.popen('lsb_release -r | cut -f 2')
 
1678
       os_version=version.read().strip()
 
1679
       version.close()
 
1680
       is_su = True
 
1681
    else:
 
1682
       name = os.popen('cat /etc/issue | cut -c 1-6 | head -n 1')
 
1683
       os_name = name.read().strip()
 
1684
       name.close()
 
1685
       version1=os.popen('cat /etc/issue | cut -c 16 | head -n 1')
 
1686
       version2=version1.read().strip()
 
1687
       version1.close()
 
1688
       if (version2 == '1'):
 
1689
           version=os.popen('cat /etc/issue | cut -c 16-17 | head -n 1')
 
1690
           is_su = True
 
1691
       else: 
 
1692
           version=os.popen('cat /etc/issue | cut -c 16 | head -n 1')
 
1693
           is_su = False
 
1694
       os_version=version.read().strip()
 
1695
       version.close()
 
1696
 
 
1697
    return os_name,os_version,is_su 
 
1698
    
 
1699
 
 
1700
#
 
1701
# Removes HTML or XML character references and entities from a text string.
 
1702
#
 
1703
 
 
1704
def unescape(text):
 
1705
    def fixup(m):
 
1706
        text = m.group(0)
 
1707
        if text[:2] == "&#":
 
1708
            # character reference
 
1709
            try:
 
1710
                if text[:3] == "&#x":
 
1711
                    #return unichr(int(text[3:-1], 16))
 
1712
                    return chr(int(text[3:-1], 16))
 
1713
                else:
 
1714
                    #return unichr(int(text[2:-1]))
 
1715
                    return chr(int(text[2:-1]))
 
1716
            except ValueError:
 
1717
                pass
 
1718
        else:
 
1719
            # named entity
 
1720
            try:
 
1721
                #text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
 
1722
                text = chr(htmlentitydefs.name2codepoint[text[1:-1]])
 
1723
            except KeyError:
 
1724
                pass
 
1725
        return text # leave as is
 
1726
    return re.sub("&#?\w+;", fixup, text)
 
1727
 
 
1728
 
 
1729
# Adds HTML or XML character references and entities from a text string
 
1730
 
 
1731
def escape(s):
 
1732
    if not isinstance(s, unicode):
 
1733
        s = unicode(s) # hmmm...
 
1734
 
 
1735
    s = s.replace(u"&", u"&amp;")
 
1736
 
 
1737
    for c in htmlentitydefs.codepoint2name:
 
1738
        if c != 0x26: # exclude &
 
1739
            s = s.replace(unichr(c), u"&%s;" % htmlentitydefs.codepoint2name[c])
 
1740
 
 
1741
    for c in range(0x20) + range(0x7f, 0xa0):
 
1742
        s = s.replace(unichr(c), u"&#%d;" % c)
 
1743
 
 
1744
    return s
 
1745
 
 
1746
# checks if given process is running.
 
1747
#return value:
 
1748
#    True or False
 
1749
#    None - if process is not running
 
1750
#    grep output - if process is running
 
1751
 
 
1752
def Is_Process_Running(process_name):
 
1753
    try:
 
1754
        p1 = Popen(["ps", "aux"], stdout=PIPE)
 
1755
        p2 = Popen(["grep", process_name], stdin=p1.stdout, stdout=PIPE)
 
1756
        p3 = Popen(["grep", "-v", "grep"], stdin=p2.stdout, stdout=PIPE)
 
1757
        output = p3.communicate()[0]
 
1758
        log.debug("Is_Process_Running outpu = %s " %output)
 
1759
 
 
1760
        if process_name in output:
 
1761
            return True, output
 
1762
        else:
 
1763
            return False, None
 
1764
 
 
1765
    except Exception, e:
 
1766
        log.error("Execution failed: process Name[%s]" %process_name)
 
1767
        print >>sys.stderr, "Execution failed:", e
 
1768
        return False, None
 
1769
 
 
1770
#return tye: strings
 
1771
#Return values.
 
1772
#   None --> on error.
 
1773
#  "terminal name"-->success
 
1774
def get_terminal():
 
1775
    terminal_list=['gnome-terminal', 'konsole','x-terminal-emulator', 'xterm', 'gtkterm']
 
1776
    cnt = 0
 
1777
    terminal_cmd = None
 
1778
    while cnt < len(terminal_list):
 
1779
        if which(terminal_list[cnt]):
 
1780
            terminal_cmd = terminal_list[cnt]+" -e "
 
1781
            log.debug("Available Terminal = %s " %terminal_cmd)
 
1782
            break
 
1783
            
 
1784
    return terminal_cmd
 
1785
 
 
1786
#Return Type: bool
 
1787
# Return values:
 
1788
#      True --> if it is older version
 
1789
#      False  --> if it is same or later version.
 
1790
 
 
1791
def Is_HPLIP_older_version(installed_version, available_version):
 
1792
    
 
1793
    if available_version == "" or available_version == None or installed_version == "" or installed_version == None:
 
1794
        log.debug("available_version is ''")
 
1795
        return False
 
1796
 
 
1797
    installed_array=installed_version.split('.')
 
1798
    available_array=available_version.split('.')
 
1799
 
 
1800
    log.debug("HPLIP Installed_version=%s  Available_version=%s"%(installed_version,available_version))
 
1801
    cnt = 0
 
1802
    Is_older = False
 
1803
    while cnt <len(installed_array) and cnt <len(available_array):
 
1804
        if(int(installed_array[cnt]) < int(available_array[cnt])):
 
1805
            Is_older = True
 
1806
            break
 
1807
        elif(int(installed_array[cnt]) > int(available_array[cnt])):
 
1808
            log.debug("Already new verison is installed")
 
1809
            return False
 
1810
        cnt += 1
 
1811
 
 
1812
    # To check internal version is installed.
 
1813
    if Is_older is False and len(installed_array) >len(available_array):
 
1814
        Is_older = True
 
1815
 
 
1816
    return Is_older
 
1817
 
 
1818
 
 
1819
def downLoad_status(count, blockSize, totalSize):
 
1820
    percent = int(count*blockSize*100/totalSize)
 
1821
    if count != 0:
 
1822
        sys.stdout.write("\b\b\b")
 
1823
    sys.stdout.write("%s" %(log.color("%2d%%"%percent, 'bold')))
 
1824
    sys.stdout.flush()
 
1825
 
 
1826
 
 
1827
def download_from_network(weburl, outputFile = None, useURLLIB=False):
 
1828
    result =False
 
1829
 
 
1830
    if weburl is "" or weburl is None:
 
1831
        log.error("URL is empty")
 
1832
        return result, ""
 
1833
 
 
1834
    if outputFile is None:
 
1835
        fp, outputFile = make_temp_file()
 
1836
 
 
1837
    try:
 
1838
        if useURLLIB is False:
 
1839
            wget = which("wget")
 
1840
            if wget:
 
1841
                wget = os.path.join(wget, "wget")
 
1842
                status, output = run("%s --cache=off --timeout=60 --output-document=%s %s" %(wget, outputFile, weburl))
 
1843
                if status:
 
1844
                    log.error("Failed to connect to HPLIP site. Error code = %d" %status)
 
1845
                    return False, ""
 
1846
            else:
 
1847
                useURLLIB = True
 
1848
 
 
1849
        if useURLLIB:
 
1850
            sys.stdout.write("Download in progress...")
 
1851
            urllib.urlretrieve(weburl, outputFile, downLoad_status)
 
1852
 
 
1853
    except IOError, e:
 
1854
        log.error("I/O Error: %s" % e.strerror)
 
1855
        return False, ""
 
1856
 
 
1857
    if not os.path.exists(outputFile):
 
1858
        log.error("Failed to get hplip version/ %s file not found."%hplip_version_file)
 
1859
        return False, ""
 
1860
 
 
1861
    return True, outputFile
 
1862
 
 
1863
 
 
1864
 
 
1865
 
 
1866
    
 
1867
class Sync_Lock:
 
1868
    def __init__(self, filename):
 
1869
        self.Lock_filename = filename
 
1870
        self.handler = open(self.Lock_filename, 'w')
 
1871
 
 
1872
# Wait for another process to release resource and acquires the resource.
 
1873
    def acquire(self):
 
1874
        fcntl.flock(self.handler, fcntl.LOCK_EX)
 
1875
 
 
1876
    def release(self):
 
1877
        fcntl.flock(self.handler, fcntl.LOCK_UN)
 
1878
 
 
1879
    def __del__(self):
 
1880
        self.handler.close()