diff options
-rw-r--r-- | openstack/common/fileutils.py | 12 | ||||
-rw-r--r-- | openstack/common/strutils.py | 39 | ||||
-rw-r--r-- | tests/unit/test_fileutils.py | 13 | ||||
-rw-r--r-- | tests/unit/test_strutils.py | 32 |
4 files changed, 96 insertions, 0 deletions
diff --git a/openstack/common/fileutils.py b/openstack/common/fileutils.py index 0c967da..9f8807f 100644 --- a/openstack/common/fileutils.py +++ b/openstack/common/fileutils.py @@ -96,3 +96,15 @@ def remove_path_on_error(path): except Exception: with excutils.save_and_reraise_exception(): delete_if_exists(path) + + +def file_open(*args, **kwargs): + """Open file + + see built-in file() documentation for more details + + Note: The reason this is kept in a separate module is to easily + be able to provide a stub module that doesn't alter system + state at all (for unit tests) + """ + return file(*args, **kwargs) diff --git a/openstack/common/strutils.py b/openstack/common/strutils.py index 6d227c6..8a5367b 100644 --- a/openstack/common/strutils.py +++ b/openstack/common/strutils.py @@ -24,6 +24,17 @@ import sys from openstack.common.gettextutils import _ +# Used for looking up extensions of text +# to their 'multiplied' byte amount +BYTE_MULTIPLIERS = { + '': 1, + 't': 1024 ** 4, + 'g': 1024 ** 3, + 'm': 1024 ** 2, + 'k': 1024, +} + + TRUE_STRINGS = ('1', 't', 'true', 'on', 'y', 'yes') FALSE_STRINGS = ('0', 'f', 'false', 'off', 'n', 'no') @@ -148,3 +159,31 @@ def safe_encode(text, incoming=None, return text.encode(encoding, errors) return text + + +def to_bytes(text, default=0): + """Try to turn a string into a number of bytes. Looks at the last + characters of the text to determine what conversion is needed to + turn the input text into a byte number. + + Supports: B/b, K/k, M/m, G/g, T/t (or the same with b/B on the end) + + """ + # Take off everything not number 'like' (which should leave + # only the byte 'identifier' left) + mult_key_org = text.lstrip('-1234567890') + mult_key = mult_key_org.lower() + mult_key_len = len(mult_key) + if mult_key.endswith("b"): + mult_key = mult_key[0:-1] + try: + multiplier = BYTE_MULTIPLIERS[mult_key] + if mult_key_len: + # Empty cases shouldn't cause text[0:-0] + text = text[0:-mult_key_len] + return int(text) * multiplier + except KeyError: + msg = _('Unknown byte multiplier: %s') % mult_key_org + raise TypeError(msg) + except ValueError: + return default diff --git a/tests/unit/test_fileutils.py b/tests/unit/test_fileutils.py index 030f5f0..4214e83 100644 --- a/tests/unit/test_fileutils.py +++ b/tests/unit/test_fileutils.py @@ -132,3 +132,16 @@ class RemovePathOnError(utils.BaseTestCase): pass self.assertTrue(os.path.exists(tmpfile)) os.unlink(tmpfile) + + +class UtilsTestCase(utils.BaseTestCase): + def test_file_open(self): + dst_fd, dst_path = tempfile.mkstemp() + try: + os.close(dst_fd) + with open(dst_path, 'w') as f: + f.write('hello') + with fileutils.file_open(dst_path, 'r') as fp: + self.assertEquals(fp.read(), 'hello') + finally: + os.unlink(dst_path) diff --git a/tests/unit/test_strutils.py b/tests/unit/test_strutils.py index bad50c8..42160a6 100644 --- a/tests/unit/test_strutils.py +++ b/tests/unit/test_strutils.py @@ -166,3 +166,35 @@ class StrUtilsTest(utils.BaseTestCase): # Forcing incoming to ascii so it falls back to utf-8 self.assertEqual('ni\xc3\xb1o', safe_encode('ni\xc3\xb1o', incoming='ascii')) + + def test_string_conversions(self): + working_examples = { + '1024KB': 1048576, + '1024TB': 1125899906842624, + '1024K': 1048576, + '1024T': 1125899906842624, + '1TB': 1099511627776, + '1T': 1099511627776, + '1KB': 1024, + '1K': 1024, + '1B': 1, + '1': 1, + '1MB': 1048576, + '7MB': 7340032, + '0MB': 0, + '0KB': 0, + '0TB': 0, + '': 0, + } + for (in_value, expected_value) in working_examples.items(): + b_value = strutils.to_bytes(in_value) + self.assertEquals(expected_value, b_value) + if in_value: + in_value = "-" + in_value + b_value = strutils.to_bytes(in_value) + self.assertEquals(expected_value * -1, b_value) + breaking_examples = [ + 'junk1KB', '1023BBBB', + ] + for v in breaking_examples: + self.assertRaises(TypeError, strutils.to_bytes, v) |