Welcome, guest | Sign In | My Account | Store | Cart
def isacn(obj):
    """isacn(string or int) -> True|False

    Validate an ACN (Australian Company Number).
    http://www.asic.gov.au/asic/asic.nsf/byheadline/Australian+Company+Number+(ACN)+Check+Digit

    Accepts an int, or a string of digits including any leading zeroes.
    Digits may be optionally separated with spaces. Any other input raises
    TypeError or ValueError.

    Return True if the argument is a valid ACN, otherwise False.

    >>> isacn('004 085 616')
    True
    >>> isacn('005 085 616')
    False

    """
    if isinstance(obj, int):
        if not 0 <= obj < 10**9:
            raise ValueError('int out of range for an ACN')
        obj = '%09d' % obj
        assert len(obj) == 9
    if not isinstance(obj, str):
        raise TypeError('expected a str or int but got %s' % type(obj))
    obj = obj.replace(' ', '')
    if len(obj) != 9:
        raise ValueError('ACN must have exactly 9 digits')
    if not obj.isdigit():
        raise ValueError('non-digit found in ACN')
    digits = [int(c) for c in obj]
    weights = [8, 7, 6, 5, 4, 3, 2, 1]
    assert len(digits) == 9 and len(weights) == 8
    chksum = 10 - sum(d*w for d,w in zip(digits, weights)) % 10
    if chksum == 10:
        chksum = 0
    return chksum == digits[-1]


if __name__ == '__main__':
    # Check the list of valid ACNs from the ASIC website.
    ACNs = '''
        000 000 019  *  000 250 000  *  000 500 005  *  000 750 005
        001 000 004  *  001 250 004  *  001 500 009  *  001 749 999
        001 999 999  *  002 249 998  *  002 499 998  *  002 749 993
        002 999 993  *  003 249 992  *  003 499 992  *  003 749 988
        003 999 988  *  004 249 987  *  004 499 987  *  004 749 982
        004 999 982  *  005 249 981  *  005 499 981  *  005 749 986
        005 999 977  *  006 249 976  *  006 499 976  *  006 749 980
        006 999 980  *  007 249 989  *  007 499 989  *  007 749 975
        007 999 975  *  008 249 974  *  008 499 974  *  008 749 979
        008 999 979  *  009 249 969  *  009 499 969  *  009 749 964
        009 999 964  *  010 249 966  *  010 499 966  *  010 749 961
        '''.replace('*', '\n').split('\n')
    ACNs = [s for s in ACNs if s and not s.isspace()]
    for s in ACNs:
        n = int(s.replace(' ', ''))
        if not (isacn(s) and isacn(n) and not isacn(n+1)):
            print('test failed for ACN:  %s' % s.strip())
            break
    else:
        print('all ACNs tested okay')

History