Add and use valid_byte_count.
authorScott Gasch <[email protected]>
Sat, 4 Mar 2023 00:01:40 +0000 (16:01 -0800)
committerScott Gasch <[email protected]>
Sat, 4 Mar 2023 00:01:40 +0000 (16:01 -0800)
src/pyutils/argparse_utils.py
src/pyutils/logging_utils.py
src/pyutils/string_utils.py

index 6553e2c878355953c039cf88aa3bb021401c64b1..06b9a9c6c2142f940eb5450b420b7891f3a98e55 100644 (file)
@@ -459,6 +459,71 @@ def valid_duration(txt: str) -> datetime.timedelta:
         raise argparse.ArgumentTypeError(e) from e
 
 
+def valid_byte_count(txt: str) -> int:
+    """If the string is a valid number of bytes, return an integer
+    representing the requested byte count.  This method uses
+    :meth:`string_utils.suffix_string_to_number` to parse and and
+    accepts / understands:
+
+        - plain numbers (123456)
+        - numbers with ISO suffixes (Mb, Gb, Pb, etc...)
+
+    If the byte count is not parsable, raise an ArgumentTypeError.
+
+    Args:
+        txt: data passed to a commandline arg expecting a duration.
+
+    Returns:
+        An integer number of bytes or raises ArgumentTypeError on
+        error.
+
+    Sample usage::
+
+        cfg.add_argument(
+            '--max_file_size',
+            type=argparse_utils.valid_byte_count,
+            default=(1024 * 1024),
+            metavar='NUM_BYTES',
+            help='The largest file we may create',
+        )
+
+    >>> valid_byte_count('1Mb')
+    1048576
+
+    >>> valid_byte_count("1234567")
+    1234567
+
+    >>> valid_byte_count("1.2Gb")
+    1288490188
+
+    >>> valid_byte_count('1.2')      # <--- contains a decimal
+    Traceback (most recent call last):
+    ...
+    argparse.ArgumentTypeError: Invalid byte count: 1.2
+
+    >>> valid_byte_count(1234567)    # <--- not a string
+    Traceback (most recent call last):
+    ...
+    argparse.ArgumentTypeError: Invalid byte count: 1234567
+
+    >>> valid_byte_count('On a dark and stormy night')
+    Traceback (most recent call last):
+    ...
+    argparse.ArgumentTypeError: Invalid byte count: On a dark and stormy night
+
+    """
+    from pyutils.string_utils import suffix_string_to_number
+
+    try:
+        num_bytes = suffix_string_to_number(txt)
+        if num_bytes:
+            return num_bytes
+        raise argparse.ArgumentTypeError(f"Invalid byte count: {txt}")
+    except Exception as e:
+        logger.exception("Exception while parsing a supposed byte count: %s", txt)
+        raise argparse.ArgumentTypeError(e) from e
+
+
 if __name__ == "__main__":
     import doctest
 
index 669ba21499f2653f3e8c4be2cc86505e7169582a..8011604e7c3ee25fc5ed33ed4944e8d4b269f281 100644 (file)
@@ -107,7 +107,7 @@ cfg.add_argument(
 )
 cfg.add_argument(
     "--logging_filename_maxsize",
-    type=int,
+    type=argparse_utils.valid_byte_count,
     default=(1024 * 1024),
     metavar="#BYTES",
     help="The maximum size (in bytes) to write to the logging_filename.",
index a50347241845b4831deda165ceda7267f13642b7..0c18dcc62164a505fb93fe54c72867ca44821db2 100644 (file)
@@ -827,6 +827,11 @@ def suffix_string_to_number(in_str: str) -> Optional[int]:
     1048576
     >>> suffix_string_to_number('13.1Gb')
     14066017894
+    >>> suffix_string_to_number('12345')
+    12345
+    >>> x = suffix_string_to_number('a lot')
+    >>> x is None
+    True
     """
 
     def suffix_capitalize(s: str) -> str: