def test_get_fl_username_variations(self): """ Are all of hte first and last name variations generated, including initials? :return: """ generated_usernames = get_fl_name_variations( self.first_name, self.last_name, True ) generated_usernames.sort() expected_usernames = [ ('James', 'Bond'), ('J', 'Bond'), ('James', 'B'), ('J', 'B') ] expected_usernames.sort() self.assertListEqual(generated_usernames, expected_usernames)
def _enumerate_probable_usernames(self): """ Build a simple list of user names based on a person's full name. Limit our formatting to only the special symbols in ``._`` and alphanumeric characters in ``a-zA-Z0-9``. Usernames of services such as Gmail, Yahoo, Outlook.com, LinkedIn, AngelList, and Twitter are restricted to these characters despite RFCs allowing more characters ( including unicode in some cases). Email: :rfc:`3696` .. todo:: * Expand our variations to include numbers once we obtain age, birthday, etc * Translate non-latin characters to their latin equivalent :return: None """ fml_pattern = '{f}{s1}{m}{s2}{l}' common_special_characters = ['.', '_', ''] # '' To represent *no special character* name_variations = [] generated_usernames = set() # Normalize characters in each name to their decomposed equivalents first_name = ''.join([ c for c in unicodedata.normalize('NFKD', self.person.first_name) if not unicodedata.combining(c) ]) middle_name = ''.join([ c for c in unicodedata.normalize('NFKD', self.person.middle_name) if not unicodedata.combining(c) ]) if self.person.has_middle_name() else None last_name = ''.join([ c for c in unicodedata.normalize('NFKD', self.person.last_name) if not unicodedata.combining(c) ]) # Build a list of name variations. E.g. (James, Bond), (J, Bond), or (J, H, Bond) if middle_name: name_variations.extend(get_fml_name_variations(first_name, middle_name, last_name, True)) name_variations.extend(get_fml_name_variations(last_name, first_name, middle_name, True)) name_variations.extend(get_fml_name_variations(middle_name, last_name, first_name, True)) name_variations.extend(get_fl_name_variations(first_name, last_name, True)) name_variations.extend(get_fl_name_variations(last_name, first_name, True)) # Generate names by concatenating them together with combinations of the special symbols for name in name_variations: # Each part of the name can be separated by a special character for symbol in common_special_characters: if len(name) == 2: # First and Last generated_usernames.add(symbol.join(name)) elif len(name) == 3: # First, Middle, and Last first, middle, last = name # We can have combinations of two symbols separating the names for symbol2 in common_special_characters: generated_usernames.add( fml_pattern.format(f=first, m=middle, l=last, s1=symbol, s2=symbol2) ) self.probable_usernames = generated_usernames