def get_replacement(self, placeholder): replacement = self.values.get(placeholder.name) if replacement is None: return None if isinstance(replacement, list): vals = (strip_and_remove_obscure_whitespace(str(val)) for val in replacement if val is not None) vals = list(filter(None, vals)) if not vals: return '' return self.sanitizer(self.get_replacement_as_list(vals)) return self.sanitizer(str(replacement))
def get_rows(self): column_headers = self._raw_column_headers # this is for caching length_of_column_headers = len(column_headers) rows_as_lists_of_columns = self._rows next(rows_as_lists_of_columns, None) # skip the header row for index, row in enumerate(rows_as_lists_of_columns): output_dict = OrderedDict() for column_name, column_value in zip(column_headers, row): column_value = strip_and_remove_obscure_whitespace( column_value) if Columns.make_key( column_name ) in self.recipient_column_headers_as_column_keys: output_dict[column_name] = column_value or None else: insert_or_append_to_dict(output_dict, column_name, column_value or None) length_of_row = len(row) if length_of_column_headers < length_of_row: output_dict[None] = row[length_of_column_headers:] elif length_of_column_headers > length_of_row: for key in column_headers[length_of_row:]: insert_or_append_to_dict(output_dict, key, None) if index < self.max_rows: yield Row( output_dict, index=index, error_fn=self._get_error_for_field, recipient_column_headers=self.recipient_column_headers, placeholders=self.placeholders_as_column_keys, template=self.template, allow_international_letters=self. allow_international_letters, ) else: yield None
def validate_email_address(email_address, column=None): # noqa (C901 too complex) # almost exactly the same as by https://github.com/wtforms/wtforms/blob/master/wtforms/validators.py, # with minor tweaks for SES compatibility - to avoid complications we are a lot stricter with the local part # than neccessary - we don't allow any double quotes or semicolons to prevent SES Technical Failures email_address = strip_and_remove_obscure_whitespace(email_address) match = re.match(EMAIL_REGEX_PATTERN, email_address) # not an email if not match: raise InvalidEmailError if len(email_address) > 320: raise InvalidEmailError # don't allow consecutive periods in either part if '..' in email_address: raise InvalidEmailError hostname = match.group(1) # idna = "Internationalized domain name" - this encode/decode cycle converts unicode into its accurate ascii # representation as the web uses. '例え.テスト'.encode('idna') == b'xn--r8jz45g.xn--zckzah' try: hostname = hostname.encode('idna').decode('ascii') except UnicodeError: raise InvalidEmailError parts = hostname.split('.') if len(hostname) > 253 or len(parts) < 2: raise InvalidEmailError for part in parts: if not part or len(part) > 63 or not hostname_part.match(part): raise InvalidEmailError # if the part after the last . is not a valid TLD then bail out if not tld_part.match(parts[-1]): raise InvalidEmailError return email_address
def format_email_address(email_address): return strip_and_remove_obscure_whitespace(email_address.lower())
def test_strip_and_remove_obscure_whitespace_only_removes_normal_whitespace_from_ends(): sentence = ' words \n over multiple lines with \ttabs\t ' assert strip_and_remove_obscure_whitespace(sentence) == 'words \n over multiple lines with \ttabs'
def test_strip_and_remove_obscure_whitespace(value): assert strip_and_remove_obscure_whitespace(value) == 'notifications-email'