0001"""
0002Number Helpers
0003
0004Provides methods for converting numbers into formatted strings. Functions are provided for
0005phone numbers, currencies, percentages, precision, positional notation, and file size.
0006
0007"""
0008# Last synced with Rails copy at Revision 6045 on Feb 7th, 2007.
0009import re
0010import warnings
0011
0012def number_to_phone(number, area_code=False, delimiter="-", extension="", country_code=""):
0013    """
0014    Formats a ``number`` into a US phone number string.
0015
0016    ``area_code``
0017        When enabled, adds parentheses around the area code. Defaults to False
0018    ``delimiter``
0019        The delimiter to use, defaults to "-"
0020    ``extension``
0021        Specifies an extension to add to the end of the generated number
0022    ``country_code``
0023        Sets the country code for the phone number
0024    
0025    Examples::
0026    
0027        >>> number_to_phone(1235551234)
0028        '123-555-1234'
0029        >>> number_to_phone(1235551234, area_code=True)
0030        '(123) 555-1234'
0031        >>> number_to_phone(1235551234, delimiter=" ")
0032        '123 555 1234'
0033        >>> number_to_phone(1235551234, area_code=True, extension=555)
0034        '(123) 555-1234 x 555'
0035        >>> number_to_phone(1235551234, country_code=1)
0036        '1-123-555-1234'
0037    """
0038    number = str(number).strip()
0039    if area_code:
0040        number = re.sub(r'([0-9]{1,3})([0-9]{3})([0-9]{4})', r'(\1) \2%s\3' % delimiter,
0041                        number)
0042    else:
0043        number = re.sub(r'([0-9]{1,3})([0-9]{3})([0-9]{4})', r'\1%s\2%s\3' %                           (delimiter, delimiter), number)
0045    if extension and str(extension).strip():
0046        number += " x %s" % extension
0047    if country_code:
0048        number = '%s%s%s' % (country_code, delimiter, number)
0049    return number
0050
0051def number_to_currency(number, unit="$", precision=2, separator=".", delimiter=","):
0052    """
0053    Formats a ``number`` into a currency string. 
0054    
0055    ``precision``
0056        Indicates the level of precision. Defaults to 2
0057    ``unit``
0058        Sets the currency type, defaults to "$"
0059    ``separator``
0060        Used to set what the unit separation should be. Defaults to "."
0061    ``delimiter``
0062        The delimiter character to use, defaults to ","
0063    
0064    Examples::
0065    
0066        >>> number_to_currency(1234567890.50)
0067        '$1,234,567,890.50'
0068        >>> number_to_currency(1234567890.506)
0069        '$1,234,567,890.51'
0070        >>> number_to_currency(1234567890.50, unit="£", separator=",", delimiter="")
0071        '£1234567890,50'
0072    """
0073    if precision < 1:
0074        separator = ""
0075    parts = number_with_precision(number, precision).split('.')
0076    num = unit + number_with_delimiter(parts[0], delimiter)
0077    if len(parts) > 1:
0078        num += separator + parts[1]
0079    return num
0080
0081def number_to_percentage(number, precision=3, separator="."):
0082    """
0083    Formats a ``number`` as into a percentage string. 
0084    
0085    ``precision``
0086        The level of precision, defaults to 3
0087    ``separator``
0088        The unit separator to be used. Defaults to "."
0089    
0090    Examples::
0091    
0092        >>> number_to_percentage(100)
0093        '100.000%'
0094        >>> number_to_percentage(100, precision=0)
0095        '100%'
0096        >>> number_to_percentage(302.0574, precision=2)
0097        '302.06%'
0098    """
0099    number = number_with_precision(number, precision)
0100    parts = number.split('.')
0101    if len(parts) < 2:
0102        return parts[0] + "%"
0103    else:
0104        return parts[0] + separator + parts[1] + "%"
0105
0106def number_to_human_size(size, precision=1):
0107    """
0108    Returns a formatted-for-humans file size.
0109
0110    ``precision``
0111        The level of precision, defaults to 1
0112    
0113    Examples::
0114    
0115        >>> number_to_human_size(123)
0116        '123 Bytes'
0117        >>> number_to_human_size(1234)
0118        '1.2 KB'
0119        >>> number_to_human_size(12345)
0120        '12.1 KB'
0121        >>> number_to_human_size(1234567)
0122        '1.2 MB'
0123        >>> number_to_human_size(1234567890)
0124        '1.1 GB'
0125        >>> number_to_human_size(1234567890123)
0126        '1.1 TB'
0127        >>> number_to_human_size(1234567, 2)
0128        '1.18 MB'
0129    """
0130    if size == 1:
0131        return "1 Byte"
0132    elif size < 1024:
0133        return "%d Bytes" % size
0134    elif size < (1024**2):
0135        return ("%%.%if KB" % precision) % (size / 1024.00)
0136    elif size < (1024**3):
0137        return ("%%.%if MB" % precision) % (size / 1024.00**2)
0138    elif size < (1024**4):
0139        return ("%%.%if GB" % precision) % (size / 1024.00**3)
0140    elif size < (1024**5):
0141        return ("%%.%if TB" % precision) % (size / 1024.00**4)
0142    else:
0143        return ""
0144
0145def human_size(*args, **kwargs):
0146    """Deprecated: Use number_to_human_size instead."""
0147    warnings.warn('The human_size function has been deprecated, please use '
0148                  'number_to_human_size instead.', DeprecationWarning, 2)
0149    return number_to_human_size(*args, **kwargs)
0150
0151def number_with_delimiter(number, delimiter=",", separator="."):
0152    """
0153    Formats a ``number`` with grouped thousands using ``delimiter``.
0154    
0155    ``delimiter``
0156        The delimiter character to use, defaults to ","
0157    ``separator``
0158        Used to set what the unit separation should be. Defaults to "."
0159
0160    Example::
0161    
0162        >>> number_with_delimiter(12345678)
0163        '12,345,678'
0164        >>> number_with_delimiter(12345678.05)
0165        '12,345,678.05'
0166        >>> number_with_delimiter(12345678, delimiter=".")
0167        '12.345.678'
0168    """
0169    parts = str(number).split('.')
0170    parts[0] = re.sub(r'(\d)(?=(\d\d\d)+(?!\d))', r'\1%s' % delimiter, str(parts[0]))
0171    return separator.join(parts)
0172
0173def number_with_precision(number, precision=3):
0174    """
0175    Formats a ``number`` with a level of ``precision``.
0176    
0177    ``precision``
0178        The level of precision, defaults to 3
0179
0180    Example::
0181    
0182        >>> number_with_precision(111.2345)
0183        '111.234'
0184        >>> number_with_precision(111.2345, 2)
0185        '111.23'
0186    """
0187    formstr = '%01.' + str(precision) + 'f'
0188    return formstr % number
0189
0190__all__ = ['number_to_phone', 'number_to_currency', 'number_to_percentage',
0191           'number_with_delimiter', 'number_with_precision', 'number_to_human_size',
0192           'human_size']