1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 """
43 Provides general-purpose utilities.
44
45 @sort: AbsolutePathList, ObjectTypeList, RestrictedContentList, RegexMatchList,
46 RegexList, _Vertex, DirectedGraph, PathResolverSingleton,
47 sortDict, convertSize, getUidGid, changeOwnership, splitCommandLine,
48 resolveCommand, executeCommand, calculateFileAge, encodePath, nullDevice,
49 deriveDayOfWeek, isStartOfWeek, buildNormalizedPath,
50 ISO_SECTOR_SIZE, BYTES_PER_SECTOR,
51 BYTES_PER_KBYTE, BYTES_PER_MBYTE, BYTES_PER_GBYTE, KBYTES_PER_MBYTE, MBYTES_PER_GBYTE,
52 SECONDS_PER_MINUTE, MINUTES_PER_HOUR, HOURS_PER_DAY, SECONDS_PER_DAY,
53 UNIT_BYTES, UNIT_KBYTES, UNIT_MBYTES, UNIT_GBYTES, UNIT_SECTORS
54
55 @var ISO_SECTOR_SIZE: Size of an ISO image sector, in bytes.
56 @var BYTES_PER_SECTOR: Number of bytes (B) per ISO sector.
57 @var BYTES_PER_KBYTE: Number of bytes (B) per kilobyte (kB).
58 @var BYTES_PER_MBYTE: Number of bytes (B) per megabyte (MB).
59 @var BYTES_PER_GBYTE: Number of bytes (B) per megabyte (GB).
60 @var KBYTES_PER_MBYTE: Number of kilobytes (kB) per megabyte (MB).
61 @var MBYTES_PER_GBYTE: Number of megabytes (MB) per gigabyte (GB).
62 @var SECONDS_PER_MINUTE: Number of seconds per minute.
63 @var MINUTES_PER_HOUR: Number of minutes per hour.
64 @var HOURS_PER_DAY: Number of hours per day.
65 @var SECONDS_PER_DAY: Number of seconds per day.
66 @var UNIT_BYTES: Constant representing the byte (B) unit for conversion.
67 @var UNIT_KBYTES: Constant representing the kilobyte (kB) unit for conversion.
68 @var UNIT_MBYTES: Constant representing the megabyte (MB) unit for conversion.
69 @var UNIT_GBYTES: Constant representing the gigabyte (GB) unit for conversion.
70 @var UNIT_SECTORS: Constant representing the ISO sector unit for conversion.
71
72 @author: Kenneth J. Pronovici <pronovic@ieee.org>
73 """
74
75
76
77
78
79
80 import sys
81 import math
82 import os
83 import re
84 import time
85 import logging
86 import string
87 from subprocess import Popen, STDOUT, PIPE
88
89 from CedarBackup2.release import VERSION, DATE
90
91 try:
92 import pwd
93 import grp
94 _UID_GID_AVAILABLE = True
95 except ImportError:
96 _UID_GID_AVAILABLE = False
97
98
99
100
101
102
103 logger = logging.getLogger("CedarBackup2.log.util")
104 outputLogger = logging.getLogger("CedarBackup2.output")
105
106 ISO_SECTOR_SIZE = 2048.0
107 BYTES_PER_SECTOR = ISO_SECTOR_SIZE
108
109 BYTES_PER_KBYTE = 1024.0
110 KBYTES_PER_MBYTE = 1024.0
111 MBYTES_PER_GBYTE = 1024.0
112 BYTES_PER_MBYTE = BYTES_PER_KBYTE * KBYTES_PER_MBYTE
113 BYTES_PER_GBYTE = BYTES_PER_MBYTE * MBYTES_PER_GBYTE
114
115 SECONDS_PER_MINUTE = 60.0
116 MINUTES_PER_HOUR = 60.0
117 HOURS_PER_DAY = 24.0
118 SECONDS_PER_DAY = SECONDS_PER_MINUTE * MINUTES_PER_HOUR * HOURS_PER_DAY
119
120 UNIT_BYTES = 0
121 UNIT_KBYTES = 1
122 UNIT_MBYTES = 2
123 UNIT_GBYTES = 4
124 UNIT_SECTORS = 3
125
126 MTAB_FILE = "/etc/mtab"
127
128 MOUNT_COMMAND = [ "mount", ]
129 UMOUNT_COMMAND = [ "umount", ]
130
131 DEFAULT_LANGUAGE = "C"
132 LANG_VAR = "LANG"
133 LOCALE_VARS = [ "LC_ADDRESS", "LC_ALL", "LC_COLLATE",
134 "LC_CTYPE", "LC_IDENTIFICATION",
135 "LC_MEASUREMENT", "LC_MESSAGES",
136 "LC_MONETARY", "LC_NAME", "LC_NUMERIC",
137 "LC_PAPER", "LC_TELEPHONE", "LC_TIME", ]
145
146 """
147 Class representing an "unordered list".
148
149 An "unordered list" is a list in which only the contents matter, not the
150 order in which the contents appear in the list.
151
152 For instance, we might be keeping track of set of paths in a list, because
153 it's convenient to have them in that form. However, for comparison
154 purposes, we would only care that the lists contain exactly the same
155 contents, regardless of order.
156
157 I have come up with two reasonable ways of doing this, plus a couple more
158 that would work but would be a pain to implement. My first method is to
159 copy and sort each list, comparing the sorted versions. This will only work
160 if two lists with exactly the same members are guaranteed to sort in exactly
161 the same order. The second way would be to create two Sets and then compare
162 the sets. However, this would lose information about any duplicates in
163 either list. I've decided to go with option #1 for now. I'll modify this
164 code if I run into problems in the future.
165
166 We override the original C{__eq__}, C{__ne__}, C{__ge__}, C{__gt__},
167 C{__le__} and C{__lt__} list methods to change the definition of the various
168 comparison operators. In all cases, the comparison is changed to return the
169 result of the original operation I{but instead comparing sorted lists}.
170 This is going to be quite a bit slower than a normal list, so you probably
171 only want to use it on small lists.
172 """
173
175 """
176 Definition of C{==} operator for this class.
177 @param other: Other object to compare to.
178 @return: True/false depending on whether C{self == other}.
179 """
180 if other is None:
181 return False
182 selfSorted = self[:]
183 otherSorted = other[:]
184 selfSorted.sort()
185 otherSorted.sort()
186 return selfSorted.__eq__(otherSorted)
187
189 """
190 Definition of C{!=} operator for this class.
191 @param other: Other object to compare to.
192 @return: True/false depending on whether C{self != other}.
193 """
194 if other is None:
195 return True
196 selfSorted = self[:]
197 otherSorted = other[:]
198 selfSorted.sort()
199 otherSorted.sort()
200 return selfSorted.__ne__(otherSorted)
201
203 """
204 Definition of S{>=} operator for this class.
205 @param other: Other object to compare to.
206 @return: True/false depending on whether C{self >= other}.
207 """
208 if other is None:
209 return True
210 selfSorted = self[:]
211 otherSorted = other[:]
212 selfSorted.sort()
213 otherSorted.sort()
214 return selfSorted.__ge__(otherSorted)
215
217 """
218 Definition of C{>} operator for this class.
219 @param other: Other object to compare to.
220 @return: True/false depending on whether C{self > other}.
221 """
222 if other is None:
223 return True
224 selfSorted = self[:]
225 otherSorted = other[:]
226 selfSorted.sort()
227 otherSorted.sort()
228 return selfSorted.__gt__(otherSorted)
229
231 """
232 Definition of S{<=} operator for this class.
233 @param other: Other object to compare to.
234 @return: True/false depending on whether C{self <= other}.
235 """
236 if other is None:
237 return False
238 selfSorted = self[:]
239 otherSorted = other[:]
240 selfSorted.sort()
241 otherSorted.sort()
242 return selfSorted.__le__(otherSorted)
243
245 """
246 Definition of C{<} operator for this class.
247 @param other: Other object to compare to.
248 @return: True/false depending on whether C{self < other}.
249 """
250 if other is None:
251 return False
252 selfSorted = self[:]
253 otherSorted = other[:]
254 selfSorted.sort()
255 otherSorted.sort()
256 return selfSorted.__lt__(otherSorted)
257
264
265 """
266 Class representing a list of absolute paths.
267
268 This is an unordered list.
269
270 We override the C{append}, C{insert} and C{extend} methods to ensure that
271 any item added to the list is an absolute path.
272
273 Each item added to the list is encoded using L{encodePath}. If we don't do
274 this, we have problems trying certain operations between strings and unicode
275 objects, particularly for "odd" filenames that can't be encoded in standard
276 ASCII.
277 """
278
280 """
281 Overrides the standard C{append} method.
282 @raise ValueError: If item is not an absolute path.
283 """
284 if not os.path.isabs(item):
285 raise ValueError("Not an absolute path: [%s]" % item)
286 list.append(self, encodePath(item))
287
288 - def insert(self, index, item):
289 """
290 Overrides the standard C{insert} method.
291 @raise ValueError: If item is not an absolute path.
292 """
293 if not os.path.isabs(item):
294 raise ValueError("Not an absolute path: [%s]" % item)
295 list.insert(self, index, encodePath(item))
296
298 """
299 Overrides the standard C{insert} method.
300 @raise ValueError: If any item is not an absolute path.
301 """
302 for item in seq:
303 if not os.path.isabs(item):
304 raise ValueError("Not an absolute path: [%s]" % item)
305 for item in seq:
306 list.append(self, encodePath(item))
307
314
315 """
316 Class representing a list containing only objects with a certain type.
317
318 This is an unordered list.
319
320 We override the C{append}, C{insert} and C{extend} methods to ensure that
321 any item added to the list matches the type that is requested. The
322 comparison uses the built-in C{isinstance}, which should allow subclasses of
323 of the requested type to be added to the list as well.
324
325 The C{objectName} value will be used in exceptions, i.e. C{"Item must be a
326 CollectDir object."} if C{objectName} is C{"CollectDir"}.
327 """
328
329 - def __init__(self, objectType, objectName):
330 """
331 Initializes a typed list for a particular type.
332 @param objectType: Type that the list elements must match.
333 @param objectName: Short string containing the "name" of the type.
334 """
335 super(ObjectTypeList, self).__init__()
336 self.objectType = objectType
337 self.objectName = objectName
338
340 """
341 Overrides the standard C{append} method.
342 @raise ValueError: If item does not match requested type.
343 """
344 if not isinstance(item, self.objectType):
345 raise ValueError("Item must be a %s object." % self.objectName)
346 list.append(self, item)
347
348 - def insert(self, index, item):
349 """
350 Overrides the standard C{insert} method.
351 @raise ValueError: If item does not match requested type.
352 """
353 if not isinstance(item, self.objectType):
354 raise ValueError("Item must be a %s object." % self.objectName)
355 list.insert(self, index, item)
356
358 """
359 Overrides the standard C{insert} method.
360 @raise ValueError: If item does not match requested type.
361 """
362 for item in seq:
363 if not isinstance(item, self.objectType):
364 raise ValueError("All items must be %s objects." % self.objectName)
365 list.extend(self, seq)
366
367
368
369
370
371
372 -class RestrictedContentList(UnorderedList):
373
374 """
375 Class representing a list containing only object with certain values.
376
377 This is an unordered list.
378
379 We override the C{append}, C{insert} and C{extend} methods to ensure that
380 any item added to the list is among the valid values. We use a standard
381 comparison, so pretty much anything can be in the list of valid values.
382
383 The C{valuesDescr} value will be used in exceptions, i.e. C{"Item must be
384 one of values in VALID_ACTIONS"} if C{valuesDescr} is C{"VALID_ACTIONS"}.
385
386 @note: This class doesn't make any attempt to trap for nonsensical
387 arguments. All of the values in the values list should be of the same type
388 (i.e. strings). Then, all list operations also need to be of that type
389 (i.e. you should always insert or append just strings). If you mix types --
390 for instance lists and strings -- you will likely see AttributeError
391 exceptions or other problems.
392 """
393
394 - def __init__(self, valuesList, valuesDescr, prefix=None):
395 """
396 Initializes a list restricted to containing certain values.
397 @param valuesList: List of valid values.
398 @param valuesDescr: Short string describing list of values.
399 @param prefix: Prefix to use in error messages (None results in prefix "Item")
400 """
401 super(RestrictedContentList, self).__init__()
402 self.prefix = "Item"
403 if prefix is not None: self.prefix = prefix
404 self.valuesList = valuesList
405 self.valuesDescr = valuesDescr
406
407 - def append(self, item):
408 """
409 Overrides the standard C{append} method.
410 @raise ValueError: If item is not in the values list.
411 """
412 if item not in self.valuesList:
413 raise ValueError("%s must be one of the values in %s." % (self.prefix, self.valuesDescr))
414 list.append(self, item)
415
416 - def insert(self, index, item):
417 """
418 Overrides the standard C{insert} method.
419 @raise ValueError: If item is not in the values list.
420 """
421 if item not in self.valuesList:
422 raise ValueError("%s must be one of the values in %s." % (self.prefix, self.valuesDescr))
423 list.insert(self, index, item)
424
425 - def extend(self, seq):
426 """
427 Overrides the standard C{insert} method.
428 @raise ValueError: If item is not in the values list.
429 """
430 for item in seq:
431 if item not in self.valuesList:
432 raise ValueError("%s must be one of the values in %s." % (self.prefix, self.valuesDescr))
433 list.extend(self, seq)
434
441
442 """
443 Class representing a list containing only strings that match a regular expression.
444
445 If C{emptyAllowed} is passed in as C{False}, then empty strings are
446 explicitly disallowed, even if they happen to match the regular expression.
447 (C{None} values are always disallowed, since string operations are not
448 permitted on C{None}.)
449
450 This is an unordered list.
451
452 We override the C{append}, C{insert} and C{extend} methods to ensure that
453 any item added to the list matches the indicated regular expression.
454
455 @note: If you try to put values that are not strings into the list, you will
456 likely get either TypeError or AttributeError exceptions as a result.
457 """
458
459 - def __init__(self, valuesRegex, emptyAllowed=True, prefix=None):
460 """
461 Initializes a list restricted to containing certain values.
462 @param valuesRegex: Regular expression that must be matched, as a string
463 @param emptyAllowed: Indicates whether empty or None values are allowed.
464 @param prefix: Prefix to use in error messages (None results in prefix "Item")
465 """
466 super(RegexMatchList, self).__init__()
467 self.prefix = "Item"
468 if prefix is not None: self.prefix = prefix
469 self.valuesRegex = valuesRegex
470 self.emptyAllowed = emptyAllowed
471 self.pattern = re.compile(self.valuesRegex)
472
474 """
475 Overrides the standard C{append} method.
476 @raise ValueError: If item is None
477 @raise ValueError: If item is empty and empty values are not allowed
478 @raise ValueError: If item does not match the configured regular expression
479 """
480 if item is None or (not self.emptyAllowed and item == ""):
481 raise ValueError("%s cannot be empty." % self.prefix)
482 if not self.pattern.search(item):
483 raise ValueError("%s is not valid: [%s]" % (self.prefix, item))
484 list.append(self, item)
485
486 - def insert(self, index, item):
487 """
488 Overrides the standard C{insert} method.
489 @raise ValueError: If item is None
490 @raise ValueError: If item is empty and empty values are not allowed
491 @raise ValueError: If item does not match the configured regular expression
492 """
493 if item is None or (not self.emptyAllowed and item == ""):
494 raise ValueError("%s cannot be empty." % self.prefix)
495 if not self.pattern.search(item):
496 raise ValueError("%s is not valid [%s]" % (self.prefix, item))
497 list.insert(self, index, item)
498
500 """
501 Overrides the standard C{insert} method.
502 @raise ValueError: If any item is None
503 @raise ValueError: If any item is empty and empty values are not allowed
504 @raise ValueError: If any item does not match the configured regular expression
505 """
506 for item in seq:
507 if item is None or (not self.emptyAllowed and item == ""):
508 raise ValueError("%s cannot be empty.", self.prefix)
509 if not self.pattern.search(item):
510 raise ValueError("%s is not valid: [%s]" % (self.prefix, item))
511 list.extend(self, seq)
512
513
514
515
516
517
518 -class RegexList(UnorderedList):
519
520 """
521 Class representing a list of valid regular expression strings.
522
523 This is an unordered list.
524
525 We override the C{append}, C{insert} and C{extend} methods to ensure that
526 any item added to the list is a valid regular expression.
527 """
528
530 """
531 Overrides the standard C{append} method.
532 @raise ValueError: If item is not an absolute path.
533 """
534 try:
535 re.compile(item)
536 except re.error:
537 raise ValueError("Not a valid regular expression: [%s]" % item)
538 list.append(self, item)
539
540 - def insert(self, index, item):
541 """
542 Overrides the standard C{insert} method.
543 @raise ValueError: If item is not an absolute path.
544 """
545 try:
546 re.compile(item)
547 except re.error:
548 raise ValueError("Not a valid regular expression: [%s]" % item)
549 list.insert(self, index, item)
550
552 """
553 Overrides the standard C{insert} method.
554 @raise ValueError: If any item is not an absolute path.
555 """
556 for item in seq:
557 try:
558 re.compile(item)
559 except re.error:
560 raise ValueError("Not a valid regular expression: [%s]" % item)
561 for item in seq:
562 list.append(self, item)
563
564
565
566
567
568
569 -class _Vertex(object):
570
571 """
572 Represents a vertex (or node) in a directed graph.
573 """
574
576 """
577 Constructor.
578 @param name: Name of this graph vertex.
579 @type name: String value.
580 """
581 self.name = name
582 self.endpoints = []
583 self.state = None
584
586
587 """
588 Represents a directed graph.
589
590 A graph B{G=(V,E)} consists of a set of vertices B{V} together with a set
591 B{E} of vertex pairs or edges. In a directed graph, each edge also has an
592 associated direction (from vertext B{v1} to vertex B{v2}). A C{DirectedGraph}
593 object provides a way to construct a directed graph and execute a depth-
594 first search.
595
596 This data structure was designed based on the graphing chapter in
597 U{The Algorithm Design Manual<http://www2.toki.or.id/book/AlgDesignManual/>},
598 by Steven S. Skiena.
599
600 This class is intended to be used by Cedar Backup for dependency ordering.
601 Because of this, it's not quite general-purpose. Unlike a "general" graph,
602 every vertex in this graph has at least one edge pointing to it, from a
603 special "start" vertex. This is so no vertices get "lost" either because
604 they have no dependencies or because nothing depends on them.
605 """
606
607 _UNDISCOVERED = 0
608 _DISCOVERED = 1
609 _EXPLORED = 2
610
612 """
613 Directed graph constructor.
614
615 @param name: Name of this graph.
616 @type name: String value.
617 """
618 if name is None or name == "":
619 raise ValueError("Graph name must be non-empty.")
620 self._name = name
621 self._vertices = {}
622 self._startVertex = _Vertex(None)
623
625 """
626 Official string representation for class instance.
627 """
628 return "DirectedGraph(%s)" % self.name
629
631 """
632 Informal string representation for class instance.
633 """
634 return self.__repr__()
635
637 """
638 Definition of equals operator for this class.
639 @param other: Other object to compare to.
640 @return: -1/0/1 depending on whether self is C{<}, C{=} or C{>} other.
641 """
642
643 if other is None:
644 return 1
645 if self.name != other.name:
646 if self.name < other.name:
647 return -1
648 else:
649 return 1
650 if self._vertices != other._vertices:
651 if self._vertices < other._vertices:
652 return -1
653 else:
654 return 1
655 return 0
656
658 """
659 Property target used to get the graph name.
660 """
661 return self._name
662
663 name = property(_getName, None, None, "Name of the graph.")
664
666 """
667 Creates a named vertex.
668 @param name: vertex name
669 @raise ValueError: If the vertex name is C{None} or empty.
670 """
671 if name is None or name == "":
672 raise ValueError("Vertex name must be non-empty.")
673 vertex = _Vertex(name)
674 self._startVertex.endpoints.append(vertex)
675 self._vertices[name] = vertex
676
678 """
679 Adds an edge with an associated direction, from C{start} vertex to C{finish} vertex.
680 @param start: Name of start vertex.
681 @param finish: Name of finish vertex.
682 @raise ValueError: If one of the named vertices is unknown.
683 """
684 try:
685 startVertex = self._vertices[start]
686 finishVertex = self._vertices[finish]
687 startVertex.endpoints.append(finishVertex)
688 except KeyError, e:
689 raise ValueError("Vertex [%s] could not be found." % e)
690
692 """
693 Implements a topological sort of the graph.
694
695 This method also enforces that the graph is a directed acyclic graph,
696 which is a requirement of a topological sort.
697
698 A directed acyclic graph (or "DAG") is a directed graph with no directed
699 cycles. A topological sort of a DAG is an ordering on the vertices such
700 that all edges go from left to right. Only an acyclic graph can have a
701 topological sort, but any DAG has at least one topological sort.
702
703 Since a topological sort only makes sense for an acyclic graph, this
704 method throws an exception if a cycle is found.
705
706 A depth-first search only makes sense if the graph is acyclic. If the
707 graph contains any cycles, it is not possible to determine a consistent
708 ordering for the vertices.
709
710 @note: If a particular vertex has no edges, then its position in the
711 final list depends on the order in which the vertices were created in the
712 graph. If you're using this method to determine a dependency order, this
713 makes sense: a vertex with no dependencies can go anywhere (and will).
714
715 @return: Ordering on the vertices so that all edges go from left to right.
716
717 @raise ValueError: If a cycle is found in the graph.
718 """
719 ordering = []
720 for key in self._vertices:
721 vertex = self._vertices[key]
722 vertex.state = self._UNDISCOVERED
723 for key in self._vertices:
724 vertex = self._vertices[key]
725 if vertex.state == self._UNDISCOVERED:
726 self._topologicalSort(self._startVertex, ordering)
727 return ordering
728
730 """
731 Recursive depth first search function implementing topological sort.
732 @param vertex: Vertex to search
733 @param ordering: List of vertices in proper order
734 """
735 vertex.state = self._DISCOVERED
736 for endpoint in vertex.endpoints:
737 if endpoint.state == self._UNDISCOVERED:
738 self._topologicalSort(endpoint, ordering)
739 elif endpoint.state != self._EXPLORED:
740 raise ValueError("Cycle found in graph (found '%s' while searching '%s')." % (vertex.name, endpoint.name))
741 if vertex.name is not None:
742 ordering.insert(0, vertex.name)
743 vertex.state = self._EXPLORED
744
751
752 """
753 Singleton used for resolving executable paths.
754
755 Various functions throughout Cedar Backup (including extensions) need a way
756 to resolve the path of executables that they use. For instance, the image
757 functionality needs to find the C{mkisofs} executable, and the Subversion
758 extension needs to find the C{svnlook} executable. Cedar Backup's original
759 behavior was to assume that the simple name (C{"svnlook"} or whatever) was
760 available on the caller's C{$PATH}, and to fail otherwise. However, this
761 turns out to be less than ideal, since for instance the root user might not
762 always have executables like C{svnlook} in its path.
763
764 One solution is to specify a path (either via an absolute path or some sort
765 of path insertion or path appending mechanism) that would apply to the
766 C{executeCommand()} function. This is not difficult to implement, but it
767 seem like kind of a "big hammer" solution. Besides that, it might also
768 represent a security flaw (for instance, I prefer not to mess with root's
769 C{$PATH} on the application level if I don't have to).
770
771 The alternative is to set up some sort of configuration for the path to
772 certain executables, i.e. "find C{svnlook} in C{/usr/local/bin/svnlook}" or
773 whatever. This PathResolverSingleton aims to provide a good solution to the
774 mapping problem. Callers of all sorts (extensions or not) can get an
775 instance of the singleton. Then, they call the C{lookup} method to try and
776 resolve the executable they are looking for. Through the C{lookup} method,
777 the caller can also specify a default to use if a mapping is not found.
778 This way, with no real effort on the part of the caller, behavior can neatly
779 degrade to something equivalent to the current behavior if there is no
780 special mapping or if the singleton was never initialized in the first
781 place.
782
783 Even better, extensions automagically get access to the same resolver
784 functionality, and they don't even need to understand how the mapping
785 happens. All extension authors need to do is document what executables
786 their code requires, and the standard resolver configuration section will
787 meet their needs.
788
789 The class should be initialized once through the constructor somewhere in
790 the main routine. Then, the main routine should call the L{fill} method to
791 fill in the resolver's internal structures. Everyone else who needs to
792 resolve a path will get an instance of the class using L{getInstance} and
793 will then just call the L{lookup} method.
794
795 @cvar _instance: Holds a reference to the singleton
796 @ivar _mapping: Internal mapping from resource name to path.
797 """
798
799 _instance = None
800
802 """Helper class to provide a singleton factory method."""
811
812 getInstance = _Helper()
813
820
821 - def lookup(self, name, default=None):
822 """
823 Looks up name and returns the resolved path associated with the name.
824 @param name: Name of the path resource to resolve.
825 @param default: Default to return if resource cannot be resolved.
826 @return: Resolved path associated with name, or default if name can't be resolved.
827 """
828 value = default
829 if name in self._mapping.keys():
830 value = self._mapping[name]
831 logger.debug("Resolved command [%s] to [%s]." % (name, value))
832 return value
833
834 - def fill(self, mapping):
835 """
836 Fills in the singleton's internal mapping from name to resource.
837 @param mapping: Mapping from resource name to path.
838 @type mapping: Dictionary mapping name to path, both as strings.
839 """
840 self._mapping = { }
841 for key in mapping.keys():
842 self._mapping[key] = mapping[key]
843
844
845
846
847
848
849 -class Pipe(Popen):
850 """
851 Specialized pipe class for use by C{executeCommand}.
852
853 The L{executeCommand} function needs a specialized way of interacting
854 with a pipe. First, C{executeCommand} only reads from the pipe, and
855 never writes to it. Second, C{executeCommand} needs a way to discard all
856 output written to C{stderr}, as a means of simulating the shell
857 C{2>/dev/null} construct.
858 """
859 - def __init__(self, cmd, bufsize=-1, ignoreStderr=False):
860 stderr = STDOUT
861 if ignoreStderr:
862 devnull = nullDevice()
863 stderr = os.open(devnull, os.O_RDWR)
864 Popen.__init__(self, shell=False, args=cmd, bufsize=bufsize, stdin=None, stdout=PIPE, stderr=stderr)
865
872
873 """
874 Class holding runtime diagnostic information.
875
876 Diagnostic information is information that is useful to get from users for
877 debugging purposes. I'm consolidating it all here into one object.
878
879 @sort: __init__, __repr__, __str__
880 """
881
882
884 """
885 Constructor for the C{Diagnostics} class.
886 """
887
889 """
890 Official string representation for class instance.
891 """
892 return "Diagnostics()"
893
895 """
896 Informal string representation for class instance.
897 """
898 return self.__repr__()
899
901 """
902 Get a map containing all of the diagnostic values.
903 @return: Map from diagnostic name to diagnostic value.
904 """
905 values = {}
906 values['version'] = self.version
907 values['interpreter'] = self.interpreter
908 values['platform'] = self.platform
909 values['encoding'] = self.encoding
910 values['locale'] = self.locale
911 values['timestamp'] = self.timestamp
912 return values
913
915 """
916 Pretty-print diagnostic information to a file descriptor.
917 @param fd: File descriptor used to print information.
918 @param prefix: Prefix string (if any) to place onto printed lines
919 @note: The C{fd} is used rather than C{print} to facilitate unit testing.
920 """
921 lines = self._buildDiagnosticLines(prefix)
922 for line in lines:
923 fd.write("%s\n" % line)
924
926 """
927 Pretty-print diagnostic information using a logger method.
928 @param method: Logger method to use for logging (i.e. logger.info)
929 @param prefix: Prefix string (if any) to place onto printed lines
930 """
931 lines = self._buildDiagnosticLines(prefix)
932 for line in lines:
933 method("%s" % line)
934
936 """
937 Build a set of pretty-printed diagnostic lines.
938 @param prefix: Prefix string (if any) to place onto printed lines
939 @return: List of strings, not terminated by newlines.
940 """
941 values = self.getValues()
942 keys = values.keys()
943 keys.sort()
944 tmax = Diagnostics._getMaxLength(keys) + 3
945 lines = []
946 for key in keys:
947 title = key.title()
948 title += (tmax - len(title)) * '.'
949 value = values[key]
950 line = "%s%s: %s" % (prefix, title, value)
951 lines.append(line)
952 return lines
953
954 @staticmethod
956 """
957 Get the maximum length from among a list of strings.
958 """
959 tmax = 0
960 for value in values:
961 if len(value) > tmax:
962 tmax = len(value)
963 return tmax
964
966 """
967 Property target to get the Cedar Backup version.
968 """
969 return "Cedar Backup %s (%s)" % (VERSION, DATE)
970
972 """
973 Property target to get the Python interpreter version.
974 """
975 version = sys.version_info
976 return "Python %d.%d.%d (%s)" % (version[0], version[1], version[2], version[3])
977
979 """
980 Property target to get the filesystem encoding.
981 """
982 return sys.getfilesystemencoding() or sys.getdefaultencoding()
983
1004
1006 """
1007 Property target to get the default locale that is in effect.
1008 """
1009 try:
1010 import locale
1011 return locale.getdefaultlocale()[0]
1012 except:
1013 return "(unknown)"
1014
1016 """
1017 Property target to get a current date/time stamp.
1018 """
1019 try:
1020 import datetime
1021 return datetime.datetime.utcnow().ctime() + " UTC"
1022 except:
1023 return "(unknown)"
1024
1025 version = property(_getVersion, None, None, "Cedar Backup version.")
1026 interpreter = property(_getInterpreter, None, None, "Python interpreter version.")
1027 platform = property(_getPlatform, None, None, "Platform identifying information.")
1028 encoding = property(_getEncoding, None, None, "Filesystem encoding that is in effect.")
1029 locale = property(_getLocale, None, None, "Locale that is in effect.")
1030 timestamp = property(_getTimestamp, None, None, "Current timestamp.")
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041 -def sortDict(d):
1042 """
1043 Returns the keys of the dictionary sorted by value.
1044
1045 There are cuter ways to do this in Python 2.4, but we were originally
1046 attempting to stay compatible with Python 2.3.
1047
1048 @param d: Dictionary to operate on
1049 @return: List of dictionary keys sorted in order by dictionary value.
1050 """
1051 items = d.items()
1052 items.sort(lambda x, y: cmp(x[1], y[1]))
1053 return [key for key, value in items]
1054
1055
1056
1057
1058
1059
1060 -def removeKeys(d, keys):
1061 """
1062 Removes all of the keys from the dictionary.
1063 The dictionary is altered in-place.
1064 Each key must exist in the dictionary.
1065 @param d: Dictionary to operate on
1066 @param keys: List of keys to remove
1067 @raise KeyError: If one of the keys does not exist
1068 """
1069 for key in keys:
1070 del d[key]
1071
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES:
1114 byteSize = float(size) * BYTES_PER_GBYTE
1115 elif fromUnit == UNIT_SECTORS:
1116 byteSize = float(size) * BYTES_PER_SECTOR
1117 else:
1118 raise ValueError("Unknown 'from' unit %s." % fromUnit)
1119 if toUnit == UNIT_BYTES:
1120 return byteSize
1121 elif toUnit == UNIT_KBYTES:
1122 return byteSize / BYTES_PER_KBYTE
1123 elif toUnit == UNIT_MBYTES:
1124 return byteSize / BYTES_PER_MBYTE
1125 elif toUnit == UNIT_GBYTES:
1126 return byteSize / BYTES_PER_GBYTE
1127 elif toUnit == UNIT_SECTORS:
1128 return byteSize / BYTES_PER_SECTOR
1129 else:
1130 raise ValueError("Unknown 'to' unit %s." % toUnit)
1131
1132
1133
1134
1135
1136
1137 -def displayBytes(bytes, digits=2):
1138 """
1139 Format a byte quantity so it can be sensibly displayed.
1140
1141 It's rather difficult to look at a number like "72372224 bytes" and get any
1142 meaningful information out of it. It would be more useful to see something
1143 like "69.02 MB". That's what this function does. Any time you wan mea
1072
1073
1074
1075
1076
1077 -def convertSize(size, fromUnit, toUnit):
1078 """
1079 Converts a size in one unit to a size in another unit.
1080
1081 This is just a convenience function so that the functionality can be
1082 implemented in just one place. Internally, we convert values to bytes and
1083 then to the final unit.
1084
1085 The available units are:
1086
1087 - C{UNIT_BYTES} - Bytes
1088 - C{UNIT_KBYTES} - Kilobytes, where 1 kB = 1024 B
1089 - C{UNIT_MBYTES} - Megabytes, where 1 MB = 1024 kB
1090 - C{UNIT_GBYTES} - Gigabytes, where 1 GB = 1024 MB
1091 - C{UNIT_SECTORS} - Sectors, where 1 sector = 2048 B
1092
1093 @param size: Size to convert
1094 @type size: Integer or float value in units of C{fromUnit}
1095
1096 @param fromUnit: Unit to convert from
1097 @type fromUnit: One of the units listed above
1098
1099 @param toUnit: Unit to convert to
1100 @type toUnit: One of the units listed above
1101
1102 @return: Number converted to new unit, as a float.
1103 @raise ValueError: If one of the units is invalid.
1104 """
1105 if size is None:
1106 raise ValueError("Cannot convert size of None.")
1107 if fromUnit == UNIT_BYTES:
1108 byteSize = float(size)
1109 elif fromUnit == UNIT_KBYTES:
1110 byteSize = float(size) * BYTES_PER_KBYTE
1111 elif fromUnit == UNIT_MBYTES:
1112 byteSize = float(size) * BYTES_PER_MBYTE
1113 elif fromUnit == UNIT_GBYTES