[blivet/master 1/4] Remove en_spec from Size and its related functions.

David Shea dshea at redhat.com
Wed Jan 15 22:34:50 UTC 2014


Untranslated size specifications are generally understood, but languages
that use non-Latin characters may want a transliterated version of size
specifications for display. Accept either English or localized sizes
when parsing size specs, which removes the need for en_spec.
---
 blivet/__init__.py          |   2 +-
 blivet/devicefactory.py     |   4 +-
 blivet/devicelibs/crypto.py |   2 +-
 blivet/devicelibs/lvm.py    |  34 +++++------
 blivet/devicelibs/mdraid.py |   8 +--
 blivet/devicelibs/swap.py   |   8 +--
 blivet/devices.py           |  14 ++---
 blivet/formats/biosboot.py  |   4 +-
 blivet/formats/fs.py        |  48 +++++++--------
 blivet/formats/prepboot.py  |   4 +-
 blivet/formats/swap.py      |   2 +-
 blivet/partitioning.py      |   4 +-
 blivet/platform.py          |  20 +++---
 blivet/size.py              | 146 +++++++++++++++++++++-----------------------
 blivet/udev.py              |  10 +--
 blivet/util.py              |   4 +-
 examples/factory.py         |   8 +--
 examples/lvm.py             |  12 ++--
 examples/partitioning.py    |  10 +--
 tests/size_test.py          |  10 +--
 20 files changed, 173 insertions(+), 181 deletions(-)

diff --git a/blivet/__init__.py b/blivet/__init__.py
index 3f676d0..9268255 100644
--- a/blivet/__init__.py
+++ b/blivet/__init__.py
@@ -1643,7 +1643,7 @@ class Blivet(object):
 
         if not swaps:
             installed = util.total_memory()
-            required = Size(en_spec="%s KiB" % isys.EARLY_SWAP_RAM)
+            required = Size(spec="%s KiB" % isys.EARLY_SWAP_RAM)
 
             if installed < required:
                 errors.append(_("You have not specified a swap partition.  "
diff --git a/blivet/devicefactory.py b/blivet/devicefactory.py
index d37af5b..7e20961 100644
--- a/blivet/devicefactory.py
+++ b/blivet/devicefactory.py
@@ -820,7 +820,7 @@ class PartitionFactory(DeviceFactory):
         if self.encrypted:
             min_format_size += getFormat("luks").minSize
 
-        return max(Size(en_spec="1MiB"), min_format_size)
+        return max(Size(spec="1MiB"), min_format_size)
 
     def _get_device_size(self):
         """ Return the factory device size including container limitations. """
@@ -958,7 +958,7 @@ class PartitionSetFactory(PartitionFactory):
             add_disks = self.disks
 
         # drop any new disks that don't have free space
-        min_free = min(Size(en_spec="500MiB"), self.parent_factory.size)
+        min_free = min(Size(spec="500MiB"), self.parent_factory.size)
         add_disks = [d for d in add_disks if d.partitioned and
                                              d.format.free >= min_free]
 
diff --git a/blivet/devicelibs/crypto.py b/blivet/devicelibs/crypto.py
index 28c03ae..4ddb996 100644
--- a/blivet/devicelibs/crypto.py
+++ b/blivet/devicelibs/crypto.py
@@ -26,7 +26,7 @@ from pycryptsetup import CryptSetup
 from ..errors import *
 from ..size import Size
 
-LUKS_METADATA_SIZE = Size(en_spec="2 MiB")
+LUKS_METADATA_SIZE = Size(spec="2 MiB")
 
 # Keep the character set size a power of two to make sure all characters are
 # equally likely
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
index 37cd13c..6f4bab2 100644
--- a/blivet/devicelibs/lvm.py
+++ b/blivet/devicelibs/lvm.py
@@ -37,14 +37,14 @@ from ..i18n import _
 MAX_LV_SLOTS = 256
 
 # some of lvm's defaults that we have no way to ask it for
-LVM_PE_START = Size(en_spec="1 MiB")
-LVM_PE_SIZE = Size(en_spec="4 MiB")
+LVM_PE_START = Size(spec="1 MiB")
+LVM_PE_SIZE = Size(spec="4 MiB")
 
 # thinp constants
-LVM_THINP_MIN_METADATA_SIZE = Size(en_spec="2 MiB")
-LVM_THINP_MAX_METADATA_SIZE = Size(en_spec="16 GiB")
-LVM_THINP_MIN_CHUNK_SIZE = Size(en_spec="64 KiB")
-LVM_THINP_MAX_CHUNK_SIZE = Size(en_spec="1 GiB")
+LVM_THINP_MIN_METADATA_SIZE = Size(spec="2 MiB")
+LVM_THINP_MAX_METADATA_SIZE = Size(spec="16 GiB")
+LVM_THINP_MIN_CHUNK_SIZE = Size(spec="64 KiB")
+LVM_THINP_MAX_CHUNK_SIZE = Size(spec="1 GiB")
 
 def has_lvm():
     if util.find_program_in_path("lvm"):
@@ -126,8 +126,8 @@ def getPossiblePhysicalExtents():
     """
 
     possiblePE = []
-    curpe = Size(en_spec="1 KiB")
-    while curpe <= Size(en_spec="16 GiB"):
+    curpe = Size(spec="1 KiB")
+    while curpe <= Size(spec="16 GiB"):
 	possiblePE.append(curpe)
 	curpe = curpe * 2
 
@@ -136,9 +136,9 @@ def getPossiblePhysicalExtents():
 def getMaxLVSize():
     """ Return the maximum size of a logical volume. """
     if arch.getArch() in ("x86_64", "ppc64", "alpha", "ia64", "s390"): #64bit architectures
-        return Size(en_spec="8 EiB")
+        return Size(spec="8 EiB")
     else:
-        return Size(en_spec="16 TiB")
+        return Size(spec="16 TiB")
 
 def clampSize(size, pesize, roundup=None):
     delta = size % pesize
@@ -229,7 +229,7 @@ def pvcreate(device):
 
 def pvresize(device, size):
     args = ["pvresize"] + \
-            ["--setphysicalvolumesize", ("%dm" % size.convertTo(en_spec="mib"))] + \
+            ["--setphysicalvolumesize", ("%dm" % size.convertTo(spec="mib"))] + \
             _getConfigArgs() + \
             [device]
 
@@ -294,7 +294,7 @@ def pvinfo(device):
 def vgcreate(vg_name, pv_list, pe_size):
     argv = ["vgcreate"]
     if pe_size:
-        argv.extend(["-s", "%dm" % pe_size.convertTo(en_spec="mib")])
+        argv.extend(["-s", "%dm" % pe_size.convertTo(spec="mib")])
     argv.extend(_getConfigArgs())
     argv.append(vg_name)
     argv.extend(pv_list)
@@ -408,7 +408,7 @@ def lvorigin(vg_name, lv_name):
 
 def lvcreate(vg_name, lv_name, size, pvs=[]):
     args = ["lvcreate"] + \
-            ["-L", "%dm" % size.convertTo(en_spec="mib")] + \
+            ["-L", "%dm" % size.convertTo(spec="mib")] + \
             ["-n", lv_name] + \
             _getConfigArgs() + \
             [vg_name] + pvs
@@ -430,7 +430,7 @@ def lvremove(vg_name, lv_name):
 
 def lvresize(vg_name, lv_name, size):
     args = ["lvresize"] + \
-            ["--force", "-L", "%dm" % size.convertTo(en_spec="mib")] + \
+            ["--force", "-L", "%dm" % size.convertTo(spec="mib")] + \
             _getConfigArgs() + \
             ["%s/%s" % (vg_name, lv_name)]
 
@@ -462,15 +462,15 @@ def lvdeactivate(vg_name, lv_name):
 
 def thinpoolcreate(vg_name, lv_name, size, metadatasize=None, chunksize=None):
     args = ["lvcreate", "--thinpool", "%s/%s" % (vg_name, lv_name),
-            "--size", "%dm" % size.convertTo(en_spec="mib")]
+            "--size", "%dm" % size.convertTo(spec="mib")]
 
     if metadatasize:
         # default unit is MiB
-        args += ["--poolmetadatasize", "%d" % metadatasize.convertTo(en_spec="mib")]
+        args += ["--poolmetadatasize", "%d" % metadatasize.convertTo(spec="mib")]
 
     if chunksize:
         # default unit is KiB
-        args += ["--chunksize", "%d" % chunksize.convertTo(en_spec="kib")]
+        args += ["--chunksize", "%d" % chunksize.convertTo(spec="kib")]
 
     args += _getConfigArgs()
 
diff --git a/blivet/devicelibs/mdraid.py b/blivet/devicelibs/mdraid.py
index 59e1b0e..b5bf688 100644
--- a/blivet/devicelibs/mdraid.py
+++ b/blivet/devicelibs/mdraid.py
@@ -31,8 +31,8 @@ import logging
 log = logging.getLogger("blivet")
 
 # these defaults were determined empirically
-MD_SUPERBLOCK_SIZE = Size(en_spec="2 MiB")
-MD_CHUNK_SIZE = Size(en_spec="512 KiB")
+MD_SUPERBLOCK_SIZE = Size(spec="2 MiB")
+MD_CHUNK_SIZE = Size(spec="512 KiB")
 
 class MDRaidLevels(raid.RAIDLevels):
     @classmethod
@@ -95,8 +95,8 @@ def get_raid_superblock_size(size, version=None):
         # MDADM: operations, but limit this to 128Meg (0.1% of 10Gig)
         # MDADM: which is plenty for efficient reshapes
         # NOTE: In the mdadm code this is in 512b sectors. Converted to use MiB
-        headroom = int(Size(en_spec="128 MiB"))
-        while headroom << 10 > size and headroom > Size(en_spec="1 MiB"):
+        headroom = int(Size(spec="128 MiB"))
+        while headroom << 10 > size and headroom > Size(spec="1 MiB"):
             headroom >>= 1
 
         headroom = Size(bytes=headroom)
diff --git a/blivet/devicelibs/swap.py b/blivet/devicelibs/swap.py
index 0e8b14a..c70e3e9 100644
--- a/blivet/devicelibs/swap.py
+++ b/blivet/devicelibs/swap.py
@@ -137,10 +137,10 @@ def swapSuggestion(quiet=False, hibernation=False, disk_space=None):
     if not quiet:
         log.info("Detected %s of memory", mem)
 
-    two_GiB = Size(en_spec="2GiB")
-    four_GiB = Size(en_spec="4GiB")
-    eight_GiB = Size(en_spec="8GiB")
-    sixtyfour_GiB = Size(en_spec="64 GiB")
+    two_GiB = Size(spec="2GiB")
+    four_GiB = Size(spec="4GiB")
+    eight_GiB = Size(spec="8GiB")
+    sixtyfour_GiB = Size(spec="64 GiB")
 
     #chart suggested in the discussion with other teams
     if mem < two_GiB:
diff --git a/blivet/devices.py b/blivet/devices.py
index 659644c..d223f72 100644
--- a/blivet/devices.py
+++ b/blivet/devices.py
@@ -1066,7 +1066,7 @@ class PartitionDevice(StorageDevice):
     """
     _type = "partition"
     _resizable = True
-    defaultSize = Size(en_spec="500MiB")
+    defaultSize = Size(spec="500MiB")
 
     def __init__(self, name, format=None,
                  size=None, grow=False, maxsize=None, start=None, end=None,
@@ -1491,7 +1491,7 @@ class PartitionDevice(StorageDevice):
         device = self.partedPartition.geometry.device.path
 
         # Erase 1MiB or to end of partition
-        count = Size(en_spec="1 MiB") / bs
+        count = Size(spec="1 MiB") / bs
         count = min(count, part_len)
 
         cmd = ["dd", "if=/dev/zero", "of=%s" % device, "bs=%s" % bs,
@@ -1753,7 +1753,7 @@ class PartitionDevice(StorageDevice):
             data.size = int(self.req_base_size)
             data.grow = self.req_grow
             if self.req_grow:
-                data.maxSizeMB = int(self.req_max_size.convertTo(en_spec="mib"))
+                data.maxSizeMB = int(self.req_max_size.convertTo(spec="mib"))
 
             ##data.disk = self.disk.name                      # by-id
             if self.req_disks and len(self.req_disks) == 1:
@@ -2472,7 +2472,7 @@ class LVMVolumeGroupDevice(DMDevice):
         data.physvols = ["pv.%d" % p.id for p in self.parents]
         data.preexist = self.exists
         if not self.exists:
-            data.pesize = self.peSize.convertTo(en_spec="KiB")
+            data.pesize = self.peSize.convertTo(spec="KiB")
 
         # reserved percent/space
 
@@ -2778,7 +2778,7 @@ class LVMLogicalVolumeDevice(DMDevice):
             data.grow = self.req_grow
             if self.req_grow:
                 data.size = int(self.req_size)
-                data.maxSizeMB = self.req_max_size.convertTo(en_spec="mib")
+                data.maxSizeMB = self.req_max_size.convertTo(spec="mib")
             else:
                 data.size = int(self.size)
 
@@ -3857,8 +3857,8 @@ class FileDevice(StorageDevice):
         fd = os.open(self.path, os.O_WRONLY|os.O_CREAT|os.O_TRUNC)
         # all this fuss is so we write the zeros 1MiB at a time
         zero = "\0"
-        MiB = Size(en_spec="1 MiB")
-        count = int(self.size.convertTo(en_spec="MiB"))
+        MiB = Size(spec="1 MiB")
+        count = int(self.size.convertTo(spec="MiB"))
         rem = self.size % MiB
         for n in range(count):
             os.write(fd, zero * MiB)
diff --git a/blivet/formats/biosboot.py b/blivet/formats/biosboot.py
index 3934178..77bf4c4 100644
--- a/blivet/formats/biosboot.py
+++ b/blivet/formats/biosboot.py
@@ -36,8 +36,8 @@ class BIOSBoot(DeviceFormat):
     partedFlag = PARTITION_BIOS_GRUB
     _formattable = True                 # can be formatted
     _linuxNative = True                 # for clearpart
-    _maxSize = Size(en_spec="2 MiB")
-    _minSize = Size(en_spec="512 KiB")
+    _maxSize = Size(spec="2 MiB")
+    _minSize = Size(spec="512 KiB")
 
     def __init__(self, *args, **kwargs):
         """
diff --git a/blivet/formats/fs.py b/blivet/formats/fs.py
index 4b96432..485f224 100644
--- a/blivet/formats/fs.py
+++ b/blivet/formats/fs.py
@@ -864,7 +864,7 @@ class Ext2FS(FS):
     _supported = True
     _resizable = True
     _linuxNative = True
-    _maxSize = Size(en_spec="8 TiB")
+    _maxSize = Size(spec="8 TiB")
     _minSize = Size(bytes=0)
     _defaultFormatOptions = []
     _defaultMountOptions = ["defaults"]
@@ -998,7 +998,7 @@ class Ext3FS(Ext2FS):
     # smaller than the default of 4096 bytes and therefore to make liars of us
     # with regard to this maximum filesystem size, but if they're doing such
     # things they should know the implications of their chosen block size.
-    _maxSize = Size(en_spec="16 TiB")
+    _maxSize = Size(spec="16 TiB")
 
     @property
     def needsFSCheck(self):
@@ -1029,7 +1029,7 @@ class FATFS(FS):
                    2: N_("Usage error.")}
     _supported = True
     _formattable = True
-    _maxSize = Size(en_spec="1 TiB")
+    _maxSize = Size(spec="1 TiB")
     _packages = [ "dosfstools" ]
     _defaultMountOptions = ["umask=0077", "shortname=winnt"]
     # FIXME this should be fat32 in some cases
@@ -1051,7 +1051,7 @@ class EFIFS(FATFS):
     _mountType = "vfat"
     _modules = ["vfat"]
     _name = N_("EFI System Partition")
-    _minSize = Size(en_spec="50 MiB")
+    _minSize = Size(spec="50 MiB")
 
     @property
     def supported(self):
@@ -1071,8 +1071,8 @@ class BTRFS(FS):
     _maxLabelChars = 256
     _supported = True
     _packages = ["btrfs-progs"]
-    _minSize = Size(en_spec="256 MiB")
-    _maxSize = Size(en_spec="16 TiB")
+    _minSize = Size(spec="256 MiB")
+    _maxSize = Size(spec="16 TiB")
     # FIXME parted needs to be taught about btrfs so that we can set the
     # partition table type correctly for btrfs partitions
     # partedSystem = fileSystemType["btrfs"]
@@ -1128,7 +1128,7 @@ class BTRFS(FS):
 
     @property
     def resizeArgs(self):
-        argv = ["-r", "%dm" % (self.targetSize.convertTo(en_spec="MiB"),), self.device]
+        argv = ["-r", "%dm" % (self.targetSize.convertTo(spec="MiB"),), self.device]
         return argv
 
 register_device_format(BTRFS)
@@ -1170,7 +1170,7 @@ class JFS(FS):
     _labelfs = fslabel.JFSTune()
     _defaultFormatOptions = ["-q"]
     _maxLabelChars = 16
-    _maxSize = Size(en_spec="8 TiB")
+    _maxSize = Size(spec="8 TiB")
     _formattable = True
     _linuxNative = True
     _supported = False
@@ -1202,7 +1202,7 @@ class ReiserFS(FS):
     _modules = ["reiserfs"]
     _defaultFormatOptions = ["-f", "-f"]
     _maxLabelChars = 16
-    _maxSize = Size(en_spec="16 TiB")
+    _maxSize = Size(spec="16 TiB")
     _formattable = True
     _linuxNative = True
     _supported = False
@@ -1225,7 +1225,7 @@ class ReiserFS(FS):
 
     @property
     def resizeArgs(self):
-        argv = ["-s", "%dM" % (self.targetSize.convertTo(en_spec="MiB"),), self.device]
+        argv = ["-s", "%dM" % (self.targetSize.convertTo(spec="MiB"),), self.device]
         return argv
 
 register_device_format(ReiserFS)
@@ -1239,7 +1239,7 @@ class XFS(FS):
     _labelfs = fslabel.XFSAdmin()
     _defaultFormatOptions = ["-f"]
     _maxLabelChars = 16
-    _maxSize = Size(en_spec="16 EiB")
+    _maxSize = Size(spec="16 EiB")
     _formattable = True
     _linuxNative = True
     _supported = True
@@ -1286,8 +1286,8 @@ class AppleBootstrapFS(HFS):
     _type = "appleboot"
     _mountType = "hfs"
     _name = N_("Apple Bootstrap")
-    _minSize = Size(en_spec="768 KiB")
-    _maxSize = Size(en_spec="1 MiB")
+    _minSize = Size(spec="768 KiB")
+    _maxSize = Size(spec="1 MiB")
 
     @property
     def supported(self):
@@ -1306,8 +1306,8 @@ class HFSPlus(FS):
     _packages = ["hfsplus-tools"]
     _formattable = True
     _mountType = "hfsplus"
-    _minSize = Size(en_spec="1 MiB")
-    _maxSize = Size(en_spec="2 TiB")
+    _minSize = Size(spec="1 MiB")
+    _maxSize = Size(spec="2 TiB")
     _check = True
     partedSystem = fileSystemType["hfs+"]
 
@@ -1334,8 +1334,8 @@ class NTFS(FS):
     _resizefs = "ntfsresize"
     _fsck = "ntfsresize"
     _resizable = True
-    _minSize = Size(en_spec="1 MiB")
-    _maxSize = Size(en_spec="16 TiB")
+    _minSize = Size(spec="1 MiB")
+    _maxSize = Size(spec="16 TiB")
     _defaultMountOptions = ["defaults", "ro"]
     _defaultCheckOptions = ["-c"]
     _packages = ["ntfsprogs"]
@@ -1370,7 +1370,7 @@ class NTFS(FS):
                     continue
                 try:
                     # ntfsresize uses SI unit prefixes
-                    minSize = Size(en_spec="%d mb" % l.split(":")[1].strip())
+                    minSize = Size(spec="%d mb" % l.split(":")[1].strip())
                 except (IndexError, ValueError) as e:
                     minSize = None
                     log.warning("Unable to parse output for minimum size on %s: %s" %(self.device, e))
@@ -1397,7 +1397,7 @@ class NTFS(FS):
         # You must supply at least two '-f' options to ntfsresize or
         # the proceed question will be presented to you.
         # ntfsresize uses SI unit prefixes
-        argv = ["-ff", "-s", "%dM" % self.targetSize.convertTo(en_spec="mb"),
+        argv = ["-ff", "-s", "%dM" % self.targetSize.convertTo(spec="mb"),
                 self.device]
         return argv
 
@@ -1535,9 +1535,9 @@ class TmpFS(NoDevFS):
         # and 16EB on 64 bit systems
         bits = arch.bits()
         if bits == 32:
-            self._maxSize = Size(en_spec="16TiB")
+            self._maxSize = Size(spec="16TiB")
         elif bits == 64:
-            self._maxSize = Size(en_spec="16EiB")
+            self._maxSize = Size(spec="16EiB")
         # if the architecture is other than 32 or 64 bit or unknown
         # just use the default maxsize, which is 0, this disables
         # resizing but other operations such as mounting should work fine
@@ -1553,7 +1553,7 @@ class TmpFS(NoDevFS):
             self._options = fsoptions
         if self._size:
             # absolute size for the tmpfs mount has been specified
-            self._size_option = "size=%dm" % self._size.convertTo(en_spec="MiB")
+            self._size_option = "size=%dm" % self._size.convertTo(spec="MiB")
         else:
             # if no size option is specified, the tmpfs mount size will be 50%
             # of system RAM by default
@@ -1641,7 +1641,7 @@ class TmpFS(NoDevFS):
         # the mount command
 
         # add the remount flag, size and any options
-        remount_options = 'remount,size=%dm' % self.targetSize.convertTo(en_spec="MiB")
+        remount_options = 'remount,size=%dm' % self.targetSize.convertTo(spec="MiB")
         # if any mount options are defined, append them
         if self._options:
             remount_options = "%s,%s" % (remount_options, self._options)
@@ -1661,7 +1661,7 @@ class TmpFS(NoDevFS):
             # update the size option string
             # -> please note that resizing always sets the
             # size of this tmpfs mount to an absolute value
-            self._size_option = "size=%dm" % self._size.convertTo(en_spec="MiB")
+            self._size_option = "size=%dm" % self._size.convertTo(spec="MiB")
 
 register_device_format(TmpFS)
 
diff --git a/blivet/formats/prepboot.py b/blivet/formats/prepboot.py
index c81f309..bb04ae1 100644
--- a/blivet/formats/prepboot.py
+++ b/blivet/formats/prepboot.py
@@ -38,8 +38,8 @@ class PPCPRePBoot(DeviceFormat):
     partedFlag = PARTITION_PREP
     _formattable = True                 # can be formatted
     _linuxNative = True                 # for clearpart
-    _maxSize = Size(en_spec="10 MiB")
-    _minSize = Size(en_spec="4 MiB")
+    _maxSize = Size(spec="10 MiB")
+    _minSize = Size(spec="4 MiB")
 
     def __init__(self, *args, **kwargs):
         """
diff --git a/blivet/formats/swap.py b/blivet/formats/swap.py
index cf3ac69..8ffe415 100644
--- a/blivet/formats/swap.py
+++ b/blivet/formats/swap.py
@@ -44,7 +44,7 @@ class SwapSpace(DeviceFormat):
     _linuxNative = True                # for clearpart
 
     #see rhbz#744129 for details
-    _maxSize = Size(en_spec="128 GiB")
+    _maxSize = Size(spec="128 GiB")
 
     def __init__(self, *args, **kwargs):
         """
diff --git a/blivet/partitioning.py b/blivet/partitioning.py
index e5da886..bf4ec11 100644
--- a/blivet/partitioning.py
+++ b/blivet/partitioning.py
@@ -584,7 +584,7 @@ def getBestFreeSpaceRegion(disk, part_type, req_size, start=None,
             continue
 
         if boot:
-            max_boot = Size(en_spec="2 TiB")
+            max_boot = Size(spec="2 TiB")
             free_start = Size(bytes=(free_geom.start * disk.device.sectorSize))
             req_end = free_start + req_size
             if req_end > max_boot:
@@ -1615,7 +1615,7 @@ class DiskChunk(Chunk):
 
         # 2TB limit on bootable partitions, regardless of disklabel
         if req.device.req_bootable:
-            max_boot = sizeToSectors(Size(en_spec="2 TiB"), self.sectorSize)
+            max_boot = sizeToSectors(Size(spec="2 TiB"), self.sectorSize)
             limits.append(max_boot - req_end)
 
         # request-specific maximum (see Request.__init__, above, for details)
diff --git a/blivet/platform.py b/blivet/platform.py
index 8791542..6c53d1d 100644
--- a/blivet/platform.py
+++ b/blivet/platform.py
@@ -135,7 +135,7 @@ class Platform(object):
 
     def setDefaultPartitioning(self):
         """Return the default platform-specific partitioning information."""
-        return [PartSpec(mountpoint="/boot", size=Size(en_spec="500MiB"),
+        return [PartSpec(mountpoint="/boot", size=Size(spec="500MiB"),
                          weight=self.weight(mountpoint="/boot"))]
 
     def weight(self, fstype=None, mountpoint=None):
@@ -166,7 +166,7 @@ class X86(Platform):
     def setDefaultPartitioning(self):
         """Return the default platform-specific partitioning information."""
         ret = Platform.setDefaultPartitioning(self)
-        ret.append(PartSpec(fstype="biosboot", size=Size(en_spec="1MiB"),
+        ret.append(PartSpec(fstype="biosboot", size=Size(spec="1MiB"),
                             weight=self.weight(fstype="biosboot")))
         return ret
 
@@ -195,7 +195,7 @@ class EFI(Platform):
     def setDefaultPartitioning(self):
         ret = Platform.setDefaultPartitioning(self)
         ret.append(PartSpec(mountpoint="/boot/efi", fstype="efi",
-                            size=Size(en_spec="20MiB"), maxSize=Size(en_spec="200MiB"),
+                            size=Size(spec="20MiB"), maxSize=Size(spec="200MiB"),
                             grow=True, weight=self.weight(fstype="efi")))
         return ret
 
@@ -217,7 +217,7 @@ class MacEFI(EFI):
     def setDefaultPartitioning(self):
         ret = Platform.setDefaultPartitioning(self)
         ret.append(PartSpec(mountpoint="/boot/efi", fstype="macefi",
-                            size=Size(en_spec="20MiB"), maxSize=Size(en_spec="200MiB"),
+                            size=Size(spec="20MiB"), maxSize=Size(spec="200MiB"),
                             grow=True, weight=self.weight(mountpoint="/boot/efi")))
         return ret
 
@@ -234,14 +234,14 @@ class PPC(Platform):
 
 class IPSeriesPPC(PPC):
     _boot_stage1_format_types = ["prepboot"]
-    _boot_stage1_max_end = Size(en_spec="4 GiB")
+    _boot_stage1_max_end = Size(spec="4 GiB")
     _boot_prep_description = N_("PReP Boot Partition")
     _boot_descriptions = {"partition": _boot_prep_description}
     _disklabel_types = ["msdos"]
 
     def setDefaultPartitioning(self):
         ret = PPC.setDefaultPartitioning(self)
-        ret.append(PartSpec(fstype="prepboot", size=Size(en_spec="4MiB"),
+        ret.append(PartSpec(fstype="prepboot", size=Size(spec="4MiB"),
                             weight=self.weight(fstype="prepboot")))
         return ret
 
@@ -263,7 +263,7 @@ class NewWorldPPC(PPC):
 
     def setDefaultPartitioning(self):
         ret = Platform.setDefaultPartitioning(self)
-        ret.append(PartSpec(fstype="appleboot", size=Size(en_spec="1MiB"),
+        ret.append(PartSpec(fstype="appleboot", size=Size(spec="1MiB"),
                             weight=self.weight(fstype="appleboot")))
         return ret
 
@@ -296,7 +296,7 @@ class S390(Platform):
 
     def setDefaultPartitioning(self):
         """Return the default platform-specific partitioning information."""
-        return [PartSpec(mountpoint="/boot", size=Size(en_spec="500MiB"),
+        return [PartSpec(mountpoint="/boot", size=Size(spec="500MiB"),
                          weight=self.weight(mountpoint="/boot"), lv=True,
                          singlePV=True)]
 
@@ -341,11 +341,11 @@ class omapARM(ARM):
     def setDefaultPartitioning(self):
         """Return the ARM-OMAP platform-specific partitioning information."""
         ret = [PartSpec(mountpoint="/boot/uboot", fstype="vfat",
-                        size=Size(en_spec="20MiB"), maxSize=Size(en_spec="200MiB"),
+                        size=Size(spec="20MiB"), maxSize=Size(spec="200MiB"),
                         grow=True,
                         weight=self.weight(fstype="vfat", mountpoint="/boot/uboot"))]
         ret.append(PartSpec(mountpoint="/", fstype="ext4",
-                            size=Size(en_spec="2GiB"), maxSize=Size(en_spec="3GiB"),
+                            size=Size(spec="2GiB"), maxSize=Size(spec="3GiB"),
                             weight=self.weight(mountpoint="/")))
         return ret
 
diff --git a/blivet/size.py b/blivet/size.py
index 0173ac6..fca0d03 100644
--- a/blivet/size.py
+++ b/blivet/size.py
@@ -20,6 +20,7 @@
 # Red Hat Author(s): David Cantrell <dcantrell at redhat.com>
 
 import re
+import string
 
 from decimal import Decimal
 from decimal import InvalidOperation
@@ -54,6 +55,11 @@ _binaryPrefix = [(1024, N_("kibi"), N_("Ki")),
 _bytes = [N_('B'), N_('b'), N_('byte'), N_('bytes')]
 _prefixes = _binaryPrefix + _decimalPrefix
 
+_ASCIIlower_table = string.maketrans(string.ascii_uppercase, string.ascii_lowercase)
+def _lowerASCII(s):
+    """Convert a string to lowercase using only ASCII character defintions."""
+    return string.translate(s, _ASCIIlower_table)
+
 def _makeSpecs(prefix, abbr, xlate):
     """ Internal method used to generate a list of specifiers. """
     specs = []
@@ -63,28 +69,28 @@ def _makeSpecs(prefix, abbr, xlate):
             specs.append(prefix.lower() + _("byte"))
             specs.append(prefix.lower() + _("bytes"))
         else:
-            specs.append(prefix.lower() + "byte")
-            specs.append(prefix.lower() + "bytes")
+            specs.append(_lowerASCII(prefix) + "byte")
+            specs.append(_lowerASCII(prefix) + "bytes")
 
     if abbr:
         if xlate:
             specs.append(abbr.lower() + _("b"))
+            specs.append(abbr.lower())
         else:
-            specs.append(abbr.lower() + "b")
-        specs.append(abbr.lower())
+            specs.append(_lowerASCII(abbr) + "b")
+            specs.append(_lowerASCII(abbr))
 
     return specs
 
-def _parseSpec(spec, xlate):
+def _parseSpec(spec):
     """ Parse string representation of size. """
     if not spec:
         raise ValueError("invalid size specification", spec)
 
-    # This regex isn't ideal, since \w matches both letters and digits,
-    # but python doesn't provide a means to match only Unicode letters.
-    # Probably the worst that will come of it is that bad specs will fail
-    # more confusingly.
-    m = re.match(r'(-?\s*[0-9.]+)\s*(\w*)$', spec.decode("utf-8").strip(), flags=re.UNICODE)
+    # Match the size specification using only digit/space/not-space, since the
+    # string might be non-English and python is profoundly awful at dealing
+    # with unicode data via regular expressions
+    m = re.match(r'(-?\s*[0-9.]+)\s*([^\s]*)$', spec.strip())
     if not m:
         raise ValueError("invalid size specification", spec)
 
@@ -93,20 +99,34 @@ def _parseSpec(spec, xlate):
     except InvalidOperation:
         raise ValueError("invalid size specification", spec)
 
+    # Only attempt to parse as English if all characters are ASCII
+    try:
+        specifier = _lowerASCII(str(m.groups()[1].decode('ascii')))
+    except UnicodeDecodeError:
+        pass
+    else:
+        if not specifier or specifier in _bytes:
+            return size
+
+        for factor, prefix, abbr in _prefixes:
+            check = _makeSpecs(prefix, abbr, False)
+
+            if specifier in check:
+                return size * factor
+
+    # No English match found, try localized size specs
+    xlated_bytes = [_(b) for b in _bytes]
     specifier = m.groups()[1].lower()
-    if xlate:
-        bytes = [_(b) for b in _bytes]
-    else:
-        bytes = _bytes
-    if not specifier or specifier in bytes:
+    if specifier in xlated_bytes:
         return size
 
-    if xlate:
-        prefixes = [_(p) for p in _prefixes]
-    else:
-        prefixes = _prefixes
-    for factor, prefix, abbr in prefixes:
-        check = _makeSpecs(prefix, abbr, xlate)
+    xlated_prefixes = [(p[0], _(p[1]), _(p[2])) for p in _prefixes]
+    for factor, prefix, abbr in xlated_prefixes:
+        if prefix:
+            prefix = prefix.decode("utf-8")
+        if abbr:
+            abbr = abbr.decode("utf-8")
+        check = _makeSpecs(prefix, abbr, True)
 
         if specifier in check:
             return size * factor
@@ -121,34 +141,29 @@ class Size(Decimal):
         decimal places.
     """
 
-    def __new__(cls, bytes=None, spec=None, en_spec=None):
-        """ Initialize a new Size object.  Must pass only one of bytes, spec,
-            or en_spec.  The bytes parameter is a numerical value for the size
-            this object represents, in bytes.  The spec and en_spec parameters
-            are string specifications of the size using any of the size
+    def __new__(cls, bytes=None, spec=None):
+        """ Initialize a new Size object.  Must pass either bytes or spec,
+            but not both.  The bytes parameter is a numerical value for
+            the size this object represents, in bytes.  The spec parameter
+            is a string specification of the size using any of the size
             specifiers in the _decimalPrefix or _binaryPrefix lists combined
-            with the abbreviation for "byte" in the current locale ('b' or 'B'
-            in English).  For example, to specify 640 kilobytes, you could pass
+            with a 'b' or 'B'.  For example, to specify 640 kilobytes, you could pass
             any of these parameter:
 
-                en_spec="640kb"
-                en_spec="640 kb"
-                en_spec="640KB"
-                en_spec="640 KB"
-                en_spec="640 kilobytes"
+                spec="640kb"
+                spec="640 kb"
+                spec="640KB"
+                spec="640 KB"
+                spec="640 kilobytes"
 
-            en_spec strings are in English, while spec strings are in the
-            language for the current locale. So Size objects initialized with
-            constant strings should use something like Size(en_spec="3000 MB"),
-            while Size objects created from user input should use 
-            Size(spec=input).
+            Size input can be in English or the current locale. English will
+            be attempted first.
 
-            If you want to use spec or en_spec to pass a bytes value, you can
-            use the localized version of the letter 'b' or 'B' or simply leave
-            the specifier off and bytes will be assumed.
+            If you want to use spec to pass a bytes value, you can use the
+            letter 'b' or 'B' or simply leave the specifier off and bytes
+            will be assumed.
         """
-        if (bytes and (spec or en_spec)) or (spec and (bytes or en_spec)) or \
-                (en_spec and (bytes or spec)):
+        if bytes and spec:
             raise SizeParamsError("only specify one parameter")
 
         if bytes is not None:
@@ -157,11 +172,9 @@ class Size(Decimal):
             else:
                 raise ValueError("invalid value for bytes param")
         elif spec:
-            value = _parseSpec(spec, True)
-        elif en_spec:
-            value = _parseSpec(en_spec, False)
+            value = _parseSpec(spec)
         else:
-            raise SizeParamsError("missing bytes=, spec=, or en_spec=")
+            raise SizeParamsError("missing bytes= or spec=")
 
         # drop any partial byte
         value = value.to_integral_value(rounding=ROUND_DOWN)
@@ -175,7 +188,7 @@ class Size(Decimal):
         return "Size('%s')" % self
 
     def __deepcopy__(self, memo):
-        return Size(bytes=self.convertTo(en_spec="b"))
+        return Size(bytes=self.convertTo(spec="b"))
 
     def __add__(self, other, context=None):
         return Size(bytes=Decimal.__add__(self, other, context=context))
@@ -206,43 +219,22 @@ class Size(Decimal):
 
         return val
 
-    def convertTo(self, spec=None, en_spec=None):
+    def convertTo(self, spec="b"):
         """ Return the size in the units indicated by the specifier.  The
             specifier can be prefixes from the _decimalPrefix and
-            _binaryPrefix lists combined with the localized version of 'b' or
-            'B' for abbreviations) or 'bytes' (for prefixes like kilo or mega).
-            The size is returned as a Decimal.
+            _binaryPrefix lists combined with 'b' or 'B' for abbreviations)
+            or 'bytes' (for prefixes like kilo or mega).  The size is
+            returned as a Decimal.
 
-            en_spec strings are treated as English, while spec strings are in
-            language for the current locale.
+            All spec strings must be in Engish.
         """
-        if spec and en_spec:
-            raise SizeParamsError("only specify one of spec= or en_spec=")
-
-        if not (spec or en_spec):
-            en_spec = "b"
-
-        if spec:
-            xlate = True
-        else:
-            spec = en_spec
-            xlate = False
-
         spec = spec.lower()
 
-        if xlate:
-            bytes = [_(b) for b in _bytes]
-        else:
-            bytes = _bytes
-        if spec in bytes:
+        if spec in _bytes:
             return self
 
-        if xlate:
-            prefixes = [_(p) for p in _prefixes]
-        else:
-            prefixes = _prefixes
         for factor, prefix, abbr in _prefixes:
-            check = _makeSpecs(prefix, abbr, xlate)
+            check = _makeSpecs(prefix, abbr, False)
 
             if spec in check:
                 return Decimal(self / Decimal(factor))
@@ -265,7 +257,7 @@ class Size(Decimal):
         if abs(Decimal(check)) < 1000:
             return "%s %s" % (check, _("B"))
 
-        prefixes_xlated = [_(p) for p in _prefixes]
+        prefixes_xlated = [(p[0], _(p[1]), _(p[2])) for p in _prefixes]
         for factor, prefix, abbr in prefixes_xlated:
             newcheck = super(Size, self).__div__(Decimal(factor))
 
diff --git a/blivet/udev.py b/blivet/udev.py
index 9d6107c..96d8f59 100644
--- a/blivet/udev.py
+++ b/blivet/udev.py
@@ -399,15 +399,15 @@ def udev_device_get_vg_uuid(info):
 def udev_device_get_vg_size(info):
     # lvm's decmial precision is not configurable, so we tell it to use
     # KB.
-    return Size(en_spec="%s KiB" % info['LVM2_VG_SIZE'])
+    return Size(spec="%s KiB" % info['LVM2_VG_SIZE'])
 
 def udev_device_get_vg_free(info):
     # lvm's decmial precision is not configurable, so we tell it to use
     # KB.
-    return Size(en_spec="%s KiB" % info['LVM2_VG_FREE'])
+    return Size(spec="%s KiB" % info['LVM2_VG_FREE'])
 
 def udev_device_get_vg_extent_size(info):
-    return Size(en_spec="%s KiB" % info['LVM2_VG_EXTENT_SIZE'])
+    return Size(spec="%s KiB" % info['LVM2_VG_EXTENT_SIZE'])
 
 def udev_device_get_vg_extent_count(info):
     return int(info['LVM2_VG_EXTENT_COUNT'])
@@ -419,7 +419,7 @@ def udev_device_get_vg_pv_count(info):
     return int(info['LVM2_PV_COUNT'])
 
 def udev_device_get_pv_pe_start(info):
-    return Size(en_spec="%s KiB" % info['LVM2_PE_START'])
+    return Size(spec="%s KiB" % info['LVM2_PE_START'])
 
 def udev_device_get_lv_names(info):
     names = info['LVM2_LV_NAME']
@@ -444,7 +444,7 @@ def udev_device_get_lv_sizes(info):
     elif not isinstance(sizes, list):
         sizes = [sizes]
 
-    return [Size(en_spec="%s KiB" % s) for s in sizes]
+    return [Size(spec="%s KiB" % s) for s in sizes]
 
 def udev_device_get_lv_attr(info):
     attr = info['LVM2_LV_ATTR']
diff --git a/blivet/util.py b/blivet/util.py
index 3c236a6..d275365 100644
--- a/blivet/util.py
+++ b/blivet/util.py
@@ -140,12 +140,12 @@ def total_memory():
     lines = open("/proc/meminfo").readlines()
     for line in lines:
         if line.startswith("MemTotal:"):
-            mem = Size(en_spec="%s KiB" % line.split()[1])
+            mem = Size(spec="%s KiB" % line.split()[1])
 
     # Because /proc/meminfo only gives us the MemTotal (total physical RAM
     # minus the kernel binary code), we need to round this up. Assuming
     # every machine has the total RAM MiB number divisible by 128. */
-    bs = Size(en_spec="128MiB")
+    bs = Size(spec="128MiB")
     mem = (mem / bs + 1) * bs
     return mem
 
diff --git a/examples/factory.py b/examples/factory.py
index 461920e..b434af4 100644
--- a/examples/factory.py
+++ b/examples/factory.py
@@ -19,9 +19,9 @@ from blivet.size import Size
 b = blivet.Blivet()   # create an instance of Blivet (don't add system devices)
 
 # create two disk image files on which to create new devices
-disk1_file = create_sparse_file(b, "disk1", Size(en_spec="100GiB"))
+disk1_file = create_sparse_file(b, "disk1", Size(spec="100GiB"))
 b.config.diskImages["disk1"] = disk1_file
-disk2_file = create_sparse_file(b, "disk2", Size(en_spec="100GiB"))
+disk2_file = create_sparse_file(b, "disk2", Size(spec="100GiB"))
 b.config.diskImages["disk2"] = disk2_file
 
 b.reset()
@@ -34,13 +34,13 @@ try:
 
     # create an lv named data in a vg named testvg
     device = b.factoryDevice(blivet.devicefactory.DEVICE_TYPE_LVM,
-                             Size(en_spec="50GiB"), disks=[disk1, disk2],
+                             Size(spec="50GiB"), disks=[disk1, disk2],
                              fstype="xfs", mountpoint="/data")
     print_devices(b)
 
     # change testvg to have an md RAID1 pv instead of partition pvs
     device = b.factoryDevice(blivet.devicefactory.DEVICE_TYPE_LVM,
-                             Size(en_spec="50GiB"), disks=[disk1, disk2],
+                             Size(spec="50GiB"), disks=[disk1, disk2],
                              fstype="xfs", mountpoint="/data",
                              container_raid_level="raid1",
                              device=device)
diff --git a/examples/lvm.py b/examples/lvm.py
index 9fdf10d..0c7d67f 100644
--- a/examples/lvm.py
+++ b/examples/lvm.py
@@ -19,7 +19,7 @@ from blivet.size import Size
 b = blivet.Blivet()   # create an instance of Blivet (don't add system devices)
 
 # create a disk image file on which to create new devices
-disk1_file = create_sparse_file(b, "disk1", Size(en_spec="100GiB"))
+disk1_file = create_sparse_file(b, "disk1", Size(spec="100GiB"))
 b.config.diskImages["disk1"] = disk1_file
 
 b.reset()
@@ -29,7 +29,7 @@ try:
 
     b.initializeDisk(disk1)
 
-    pv = b.newPartition(size=Size(en_spec="50GiB"), fmt_type="lvmpv")
+    pv = b.newPartition(size=Size(spec="50GiB"), fmt_type="lvmpv")
     b.createDevice(pv)
 
     # allocate the partitions (decide where and on which disks they'll reside)
@@ -39,17 +39,17 @@ try:
     b.createDevice(vg)
 
     # new lv with base size 5GiB and unbounded growth and an ext4 filesystem
-    dev = b.newLV(fmt_type="ext4", size=Size(en_spec="5GiB"), grow=True,
+    dev = b.newLV(fmt_type="ext4", size=Size(spec="5GiB"), grow=True,
                   parents=[vg], name="unbounded")
     b.createDevice(dev)
 
     # new lv with base size 5GiB and growth up to 15GiB and an ext4 filesystem
-    dev = b.newLV(fmt_type="ext4", size=Size(en_spec="5GiB"), grow=True,
-                  maxsize=Size(en_spec="15GiB"), parents=[vg], name="bounded")
+    dev = b.newLV(fmt_type="ext4", size=Size(spec="5GiB"), grow=True,
+                  maxsize=Size(spec="15GiB"), parents=[vg], name="bounded")
     b.createDevice(dev)
 
     # new lv with a fixed size of 2GiB formatted as swap space
-    dev = b.newLV(fmt_type="swap", size=Size(en_spec="2GiB"), parents=[vg])
+    dev = b.newLV(fmt_type="swap", size=Size(spec="2GiB"), parents=[vg])
     b.createDevice(dev)
 
     # allocate the growable lvs
diff --git a/examples/partitioning.py b/examples/partitioning.py
index b4d5155..1a1391f 100644
--- a/examples/partitioning.py
+++ b/examples/partitioning.py
@@ -19,9 +19,9 @@ from blivet.size import Size
 b = blivet.Blivet()   # create an instance of Blivet (don't add system devices)
 
 # create two disk image files on which to create new devices
-disk1_file = create_sparse_file(b, "disk1", Size(en_spec="100GiB"))
+disk1_file = create_sparse_file(b, "disk1", Size(spec="100GiB"))
 b.config.diskImages["disk1"] = disk1_file
-disk2_file = create_sparse_file(b, "disk2", Size(en_spec="100GiB"))
+disk2_file = create_sparse_file(b, "disk2", Size(spec="100GiB"))
 b.config.diskImages["disk2"] = disk2_file
 
 b.reset()
@@ -35,19 +35,19 @@ try:
 
     # new partition on either disk1 or disk2 with base size 10GiB and growth
     # up to a maximum size of 50GiB
-    dev = b.newPartition(size=Size(en_spec="10MiB"), maxsize=Size(en_spec="50GiB"),
+    dev = b.newPartition(size=Size(spec="10MiB"), maxsize=Size(spec="50GiB"),
                          grow=True, parents=[disk1, disk2])
     b.createDevice(dev)
 
     # new partition on disk1 with base size 5GiB and unbounded growth and an
     # ext4 filesystem
-    dev = b.newPartition(fmt_type="ext4", size=Size(en_spec="5GiB"), grow=True,
+    dev = b.newPartition(fmt_type="ext4", size=Size(spec="5GiB"), grow=True,
                          parents=[disk1])
     b.createDevice(dev)
 
     # new partition on any suitable disk with a fixed size of 2GiB formatted
     # as swap space
-    dev = b.newPartition(fmt_type="swap", size=Size(en_spec="2GiB"))
+    dev = b.newPartition(fmt_type="swap", size=Size(spec="2GiB"))
     b.createDevice(dev)
 
     # allocate the partitions (decide where and on which disks they'll reside)
diff --git a/tests/size_test.py b/tests/size_test.py
index c1c120f..30bc6eb 100644
--- a/tests/size_test.py
+++ b/tests/size_test.py
@@ -29,7 +29,7 @@ from blivet.size import Size, _prefixes
 class SizeTestCase(unittest.TestCase):
     def testExceptions(self):
         self.assertRaises(SizeParamsError, Size)
-        self.assertRaises(SizeParamsError, Size, bytes=500, en_spec="45GB")
+        self.assertRaises(SizeParamsError, Size, bytes=500, spec="45GB")
 
         zero = Size(bytes=0)
         self.assertEqual(zero, 0.0)
@@ -47,15 +47,15 @@ class SizeTestCase(unittest.TestCase):
 
         if prefix:
             u = "%sbytes" % prefix
-            s = Size(en_spec="%ld %s" % (bytes, u))
+            s = Size(spec="%ld %s" % (bytes, u))
             self.assertEquals(s, c)
-            self.assertEquals(s.convertTo(en_spec=u), bytes)
+            self.assertEquals(s.convertTo(spec=u), bytes)
 
         if abbr:
             u = "%sb" % abbr
-            s = Size(en_spec="%ld %s" % (bytes, u))
+            s = Size(spec="%ld %s" % (bytes, u))
             self.assertEquals(s, c)
-            self.assertEquals(s.convertTo(en_spec=u), bytes)
+            self.assertEquals(s.convertTo(spec=u), bytes)
 
         if not prefix and not abbr:
             s = Size(spec="%ld" % bytes)
-- 
1.8.4.2



More information about the anaconda-patches mailing list