Skip to content

Instantly share code, notes, and snippets.

@pimiento
Last active August 29, 2015 13:57
Show Gist options
  • Save pimiento/9649073 to your computer and use it in GitHub Desktop.
Save pimiento/9649073 to your computer and use it in GitHub Desktop.
Проверка на валидность логина, с тремя типами "проверялок" и тестами.
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
В системе авторизации есть ограничение:
* логин должен начинаться с латинской буквы,
* состоять из латинских букв, цифр, точки и минуса,
* но заканчиваться только латинской буквой или цифрой;
* минимальная длина логина — один символ, максимальная — 20.
"""
import re
import unittest
from string import ascii_letters, digits
max_len = 20
correct_end = ascii_letters + digits
correct_symbols = correct_end + "-."
def cchecker(login):
"""
Проверка корректности логина в цикле
"""
length_counter = max_len
for c in login:
if length_counter == max_len and c not in ascii_letters:
# начинается не с латинской буквы
return False
if length_counter == 0:
# превышена длина
return False
if c not in correct_symbols:
return False
length_counter -= 1
if length_counter < max_len and c in correct_end:
# был хоть один символ и последний цифра или латинская буква
return True
else:
return False
def occhecker(login):
"""
Проверка корректности логина посимвольным проходом в цикле.
Для оптимизации используются числовые коды символов, а не поиск вида:
if c not in string.ascii_letters
Но интересный момент: получается медленнее!
"""
length_counter = max_len
for c in login:
o = ord(c)
if length_counter == max_len: # начинается не с латинской буквы
if not (o > 96 and o < 123) and \
not (o > 64 and o < 91): return False
if length_counter == 0: return False # превышена длина
# not a digit
# not a uppercase letter
# not a downcase letter
# not a minus or dot
if not (o > 47 and o < 58) and \
not (o > 96 and o < 123) and \
not (o > 64 and o < 91) and \
o != 45 and o != 46: return False
length_counter -= 1
if length_counter < max_len:
o = ord(c)
# был хоть один символ и последний цифра или латинская буква
if not (o > 47 and o < 58) and \
not (o > 96 and o < 123) and \
not (o > 64 and o < 91): return False
else: return True
else: return False
def rchecker(login):
"""
Проверка корректности логина регулярным выражением
"""
return bool(re.match(r"^[a-zA-Z][a-zA-Z0-9.-]{0,18}[a-zA-Z0-9]$", login))
class LoginCheckTest(unittest.TestCase):
correct_login = "my.hard123-login2"
cases = dict(
uncorrect_symbol = "abcоdefg123-.me",
first_uncorrect_symbol = "сdef--12ghe.-hey",
last_uncorrect_symbol = "cdef--12ghe.-heу",
first_num = "1my.login",
first_dot = ".-login123-.abc",
last_dot = "my-123.login.",
first_minus = "-login123-.abc",
last_minus = "my-123.login-",
less_than_min = "",
more_than_max = "a.b-1234-cd.efg--hijklm.nop56-q-r-s----tu.v"
)
def test_cycle_checker(self):
self.assertTrue(cchecker(self.correct_login))
for name, login in self.cases.iteritems():
self.assertFalse(cchecker(login))
def test_regex_checker(self):
self.assertTrue(rchecker(self.correct_login))
for login in self.cases.values():
self.assertFalse(rchecker(login))
def test_regex_checker(self):
self.assertTrue(occhecker(self.correct_login))
for login in self.cases.values():
self.assertFalse(occhecker(login))
if __name__ == "__main__":
unittest.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment