~ubuntu-branches/ubuntu/karmic/calibre/karmic

« back to all changes in this revision

Viewing changes to src/calibre/devices/prs500/cli/main.py

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-07-30 12:49:41 UTC
  • mfrom: (1.3.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090730124941-qjdsmri25zt8zocn
Tags: 0.6.3+dfsg-0ubuntu1
* New upstream release. Please see http://calibre.kovidgoyal.net/new_in_6/
  for the list of new features and changes.
* remove_postinstall.patch: Update for new version.
* build_debug.patch: Does not apply any more, disable for now. Might not be
  necessary any more.
* debian/copyright: Fix reference to versionless GPL.
* debian/rules: Drop obsolete dh_desktop call.
* debian/rules: Add workaround for weird Python 2.6 setuptools behaviour of
  putting compiled .so files into src/calibre/plugins/calibre/plugins
  instead of src/calibre/plugins.
* debian/rules: Drop hal fdi moving, new upstream version does not use hal
  any more. Drop hal dependency, too.
* debian/rules: Install udev rules into /lib/udev/rules.d.
* Add debian/calibre.preinst: Remove unmodified
  /etc/udev/rules.d/95-calibre.rules on upgrade.
* debian/control: Bump Python dependencies to 2.6, since upstream needs
  it now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
"""
4
4
Provides a command-line and optional graphical interface to the SONY Reader PRS-500.
5
5
 
6
 
For usage information run the script. 
 
6
For usage information run the script.
7
7
"""
8
8
 
9
9
import StringIO, sys, time, os
10
10
from optparse import OptionParser
11
11
 
12
12
from calibre import __version__, iswindows, __appname__
13
 
from calibre.devices.errors import PathError 
 
13
from calibre.devices.errors import PathError
14
14
from calibre.utils.terminfo import TerminalController
15
15
from calibre.devices.errors import ArgumentError, DeviceError, DeviceLocked
16
 
from calibre.devices import devices
 
16
from calibre.customize.ui import device_plugins
17
17
from calibre.devices.scanner import DeviceScanner
18
18
 
19
19
MINIMUM_COL_WIDTH = 12 #: Minimum width of columns in ls output
29
29
    return size + suffix
30
30
 
31
31
class FileFormatter(object):
32
 
    def __init__(self, file, term):    
 
32
    def __init__(self, file, term):
33
33
        self.term = term
34
34
        self.is_dir      = file.is_dir
35
35
        self.is_readonly = file.is_readonly
38
38
        self.wtime       = file.wtime
39
39
        self.name        = file.name
40
40
        self.path        = file.path
41
 
    
42
 
    @apply
43
 
    def mode_string():
 
41
 
 
42
    @dynamic_property
 
43
    def mode_string(self):
44
44
        doc=""" The mode string for this file. There are only two modes read-only and read-write """
45
45
        def fget(self):
46
 
            mode, x = "-", "-"      
 
46
            mode, x = "-", "-"
47
47
            if self.is_dir: mode, x = "d", "x"
48
48
            if self.is_readonly: mode += "r-"+x+"r-"+x+"r-"+x
49
49
            else: mode += "rw"+x+"rw"+x+"rw"+x
50
50
            return mode
51
51
        return property(doc=doc, fget=fget)
52
 
    
53
 
    @apply
54
 
    def isdir_name():
 
52
 
 
53
    @dynamic_property
 
54
    def isdir_name(self):
55
55
        doc='''Return self.name + '/' if self is a directory'''
56
56
        def fget(self):
57
57
            name = self.name
59
59
                name += '/'
60
60
            return name
61
61
        return property(doc=doc, fget=fget)
62
 
            
63
 
    
64
 
    @apply
65
 
    def name_in_color():
 
62
 
 
63
 
 
64
    @dynamic_property
 
65
    def name_in_color(self):
66
66
        doc=""" The name in ANSI text. Directories are blue, ebooks are green """
67
67
        def fget(self):
68
68
            cname = self.name
71
71
            if self.is_dir: cname = blue + self.name + normal
72
72
            else:
73
73
                ext = self.name[self.name.rfind("."):]
74
 
                if ext in (".pdf", ".rtf", ".lrf", ".lrx", ".txt"): cname = green + self.name + normal        
 
74
                if ext in (".pdf", ".rtf", ".lrf", ".lrx", ".txt"): cname = green + self.name + normal
75
75
            return cname
76
76
        return property(doc=doc, fget=fget)
77
 
    
78
 
    @apply
79
 
    def human_readable_size():
 
77
 
 
78
    @dynamic_property
 
79
    def human_readable_size(self):
80
80
        doc=""" File size in human readable form """
81
81
        def fget(self):
82
82
            return human_readable(self.size)
83
83
        return property(doc=doc, fget=fget)
84
 
    
85
 
    @apply
86
 
    def modification_time():
 
84
 
 
85
    @dynamic_property
 
86
    def modification_time(self):
87
87
        doc=""" Last modified time in the Linux ls -l format """
88
88
        def fget(self):
89
89
            return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.wtime))
90
90
        return property(doc=doc, fget=fget)
91
 
    
92
 
    @apply
93
 
    def creation_time():
 
91
 
 
92
    @dynamic_property
 
93
    def creation_time(self):
94
94
        doc=""" Last modified time in the Linux ls -l format """
95
95
        def fget(self):
96
96
            return time.strftime("%Y-%m-%d %H:%M", time.localtime(self.ctime))
104
104
    print "Mime type:       ", info[3]
105
105
 
106
106
def ls(dev, path, term, recurse=False, color=False, human_readable_size=False, ll=False, cols=0):
107
 
    def col_split(l, cols): # split list l into columns 
 
107
    def col_split(l, cols): # split list l into columns
108
108
        rows = len(l) / cols
109
109
        if len(l) % cols:
110
110
            rows += 1
112
112
        for i in range(rows):
113
113
            m.append(l[i::rows])
114
114
        return m
115
 
    
116
 
    def row_widths(table): # Calculate widths for each column in the row-wise table      
 
115
 
 
116
    def row_widths(table): # Calculate widths for each column in the row-wise table
117
117
        tcols = len(table[0])
118
118
        rowwidths = [ 0 for i in range(tcols) ]
119
119
        for row in table:
122
122
                rowwidths[c] = len(item) if len(item) > rowwidths[c] else rowwidths[c]
123
123
                c += 1
124
124
        return rowwidths
125
 
    
126
 
    output = StringIO.StringIO()    
 
125
 
 
126
    output = StringIO.StringIO()
127
127
    if path.endswith("/") and len(path) > 1: path = path[:-1]
128
128
    dirs = dev.list(path, recurse)
129
129
    for dir in dirs:
130
 
        if recurse: print >>output, dir[0] + ":" 
 
130
        if recurse: print >>output, dir[0] + ":"
131
131
        lsoutput, lscoloutput = [], []
132
132
        files = dir[1]
133
133
        maxlen = 0
134
134
        if ll: # Calculate column width for size column
135
135
            for file in files:
136
136
                size = len(str(file.size))
137
 
                if human_readable_size: 
 
137
                if human_readable_size:
138
138
                    file = FileFormatter(file, term)
139
139
                    size = len(file.human_readable_size)
140
140
                if size > maxlen: maxlen = size
148
148
                size = str(file.size)
149
149
                if human_readable_size: size = file.human_readable_size
150
150
                print >>output, file.mode_string, ("%"+str(maxlen)+"s")%size, file.modification_time, name
151
 
        if not ll and len(lsoutput) > 0:          
 
151
        if not ll and len(lsoutput) > 0:
152
152
            trytable = []
153
153
            for colwidth in range(MINIMUM_COL_WIDTH, cols):
154
154
                trycols = int(cols/colwidth)
155
 
                trytable = col_split(lsoutput, trycols)    
 
155
                trytable = col_split(lsoutput, trycols)
156
156
                works = True
157
157
                for row in trytable:
158
158
                    row_break = False
159
159
                    for item in row:
160
 
                        if len(item) > colwidth - 1: 
 
160
                        if len(item) > colwidth - 1:
161
161
                            works, row_break = False, True
162
162
                            break
163
163
                    if row_break: break
164
164
                if works: break
165
165
            rowwidths = row_widths(trytable)
166
166
            trytablecol = col_split(lscoloutput, len(trytable[0]))
167
 
            for r in range(len(trytable)):          
 
167
            for r in range(len(trytable)):
168
168
                for c in range(len(trytable[r])):
169
169
                    padding = rowwidths[c] - len(trytable[r][c])
170
170
                    print >>output, trytablecol[r][c], "".ljust(padding),
171
 
                print >>output    
 
171
                print >>output
172
172
        print >>output
173
 
    listing = output.getvalue().rstrip()+ "\n"    
 
173
    listing = output.getvalue().rstrip()+ "\n"
174
174
    output.close()
175
175
    return listing
176
176
 
179
179
    cols = term.COLS
180
180
    if not cols: # On windows terminal width is unknown
181
181
        cols = 80
182
 
    
183
 
    parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand is one of: info, books, df, ls, cp, mkdir, touch, cat, rm\n\n"+
 
182
 
 
183
    parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand "+
 
184
            "is one of: info, books, df, ls, cp, mkdir, touch, cat, rm, eject\n\n"+
184
185
    "For help on a particular command: %prog command", version=__appname__+" version: " + __version__)
185
186
    parser.add_option("--log-packets", help="print out packet stream to stdout. "+\
186
 
                    "The numbers in the left column are byte offsets that allow the packet size to be read off easily.", 
 
187
                    "The numbers in the left column are byte offsets that allow the packet size to be read off easily.",
187
188
    dest="log_packets", action="store_true", default=False)
188
189
    parser.remove_option("-h")
189
190
    parser.disable_interspersed_args() # Allow unrecognized options
190
191
    options, args = parser.parse_args()
191
 
    
 
192
 
192
193
    if len(args) < 1:
193
194
        parser.print_help()
194
195
        return 1
195
 
    
 
196
 
196
197
    command = args[0]
197
198
    args = args[1:]
198
199
    dev = None
203
204
        _wmi = wmi.WMI()
204
205
    scanner = DeviceScanner(_wmi)
205
206
    scanner.scan()
206
 
    for d in devices():
 
207
    for d in device_plugins():
207
208
        if scanner.is_device_connected(d):
208
 
            dev = d(log_packets=options.log_packets)
209
 
    
 
209
            dev = d
 
210
            dev.reset(log_packets=options.log_packets)
 
211
 
210
212
    if dev is None:
211
213
        print >>sys.stderr, 'Unable to find a connected ebook reader.'
212
214
        return 1
213
 
        
 
215
 
214
216
    try:
215
217
        dev.open()
216
218
        if command == "df":
217
219
            total = dev.total_space(end_session=False)
218
220
            free = dev.free_space()
219
 
            where = ("Memory", "Stick", "Card")
220
 
            print "Filesystem\tSize \tUsed \tAvail \tUse%"      
 
221
            where = ("Memory", "Card A", "Card B")
 
222
            print "Filesystem\tSize \tUsed \tAvail \tUse%"
221
223
            for i in range(3):
222
224
                print "%-10s\t%s\t%s\t%s\t%s"%(where[i], human_readable(total[i]), human_readable(total[i]-free[i]), human_readable(free[i]),\
223
225
                                                                            str(0 if total[i]==0 else int(100*(total[i]-free[i])/(total[i]*1.)))+"%")
 
226
        elif command == 'eject':
 
227
            dev.eject()
224
228
        elif command == "books":
225
229
            print "Books in main memory:"
226
 
            for book in dev.books(): 
 
230
            for book in dev.books():
227
231
                print book
228
232
            print "\nBooks on storage card:"
229
 
            for book in dev.books(oncard=True): print book      
 
233
            for book in dev.books(oncard=True): print book
230
234
        elif command == "mkdir":
231
235
            parser = OptionParser(usage="usage: %prog mkdir [options] path\nCreate a directory on the device\n\npath must begin with / or card:/")
232
236
            if len(args) != 1:
244
248
            if len(args) != 1:
245
249
                parser.print_help()
246
250
                return 1
247
 
            print ls(dev, args[0], term, color=options.color, recurse=options.recurse, ll=options.ll, human_readable_size=options.hrs, cols=cols),      
 
251
            print ls(dev, args[0], term, color=options.color, recurse=options.recurse, ll=options.ll, human_readable_size=options.hrs, cols=cols),
248
252
        elif command == "info":
249
253
            info(dev)
250
254
        elif command == "cp":
258
262
            parser.add_option('-f', '--force', dest='force', action='store_true', default=False,
259
263
                              help='Overwrite the destination file if it exists already.')
260
264
            options, args = parser.parse_args(args)
261
 
            if len(args) != 2: 
 
265
            if len(args) != 2:
262
266
                parser.print_help()
263
267
                return 1
264
268
            if args[0].startswith("prs500:"):
265
269
                outfile = args[1]
266
270
                path = args[0][7:]
267
 
                if path.endswith("/"): path = path[:-1]      
 
271
                if path.endswith("/"): path = path[:-1]
268
272
                if os.path.isdir(outfile):
269
 
                    outfile = os.path.join(outfile, path[path.rfind("/")+1:]) 
 
273
                    outfile = os.path.join(outfile, path[path.rfind("/")+1:])
270
274
                try:
271
275
                    outfile = open(outfile, "wb")
272
276
                except IOError, e:
273
277
                    print >> sys.stderr, e
274
278
                    parser.print_help()
275
279
                    return 1
276
 
                dev.get_file(path, outfile)        
 
280
                dev.get_file(path, outfile)
277
281
                outfile.close()
278
282
            elif args[1].startswith("prs500:"):
279
283
                try:
298
302
            outfile = sys.stdout
299
303
            parser = OptionParser(usage="usage: %prog cat path\nShow file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/")
300
304
            options, args = parser.parse_args(args)
301
 
            if len(args) != 1: 
 
305
            if len(args) != 1:
302
306
                parser.print_help()
303
307
                return 1
304
308
            if args[0].endswith("/"): path = args[0][:-1]
310
314
                                  "and must begin with / or card:/\n\n"+\
311
315
                                  "rm will DELETE the file. Be very CAREFUL")
312
316
            options, args = parser.parse_args(args)
313
 
            if len(args) != 1: 
 
317
            if len(args) != 1:
314
318
                parser.print_help()
315
319
                return 1
316
 
            dev.rm(args[0])      
 
320
            dev.rm(args[0])
317
321
        elif command == "touch":
318
322
            parser = OptionParser(usage="usage: %prog touch path\nCreate an empty file on the device\n\npath should point to a file on the device and must begin with /,a:/ or b:/\n\n"+
319
323
            "Unfortunately, I cant figure out how to update file times on the device, so if path already exists, touch does nothing" )
320
324
            options, args = parser.parse_args(args)
321
 
            if len(args) != 1: 
 
325
            if len(args) != 1:
322
326
                parser.print_help()
323
327
                return 1
324
328
            dev.touch(args[0])