Receita: Verificador simplificado de CPF e CNPJ
O título "simplificado" é porque esse módulo não possui tantos recursos quanto as receitas originais em que foi baseado (VerificadorDeCpf e VerificadorDeCnpj); apenas retornam o CPF/CNPJ como uma string ("56068332551") se o CPF for válido ou False se for inválido.
A idéia foi unificar as duas receitas, tirar os testes repetidos e deixar o código menor e mais fácil de entender.
Código
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 import re
5
6 __all__ = ['validar_cpf', 'validar_cnpj']
7
8 def validar_cpf(cpf):
9 """
10 Valida CPFs, retornando apenas a string de números válida.
11
12 # CPFs errados
13 >>> validar_cpf('abcdefghijk')
14 False
15 >>> validar_cpf('123')
16 False
17 >>> validar_cpf('')
18 False
19 >>> validar_cpf(None)
20 False
21 >>> validar_cpf('12345678900')
22 False
23
24 # CPFs corretos
25 >>> validar_cpf('95524361503')
26 '95524361503'
27 >>> validar_cpf('955.243.615-03')
28 '95524361503'
29 >>> validar_cpf(' 955 243 615 03 ')
30 '95524361503'
31 """
32 cpf = ''.join(re.findall('\d', str(cpf)))
33
34 if (not cpf) or (len(cpf) < 11):
35 return False
36
37 # Pega apenas os 9 primeiros dígitos do CPF e gera os 2 dígitos que faltam
38 inteiros = map(int, cpf)
39 novo = inteiros[:9]
40
41 while len(novo) < 11:
42 r = sum([(len(novo)+1-i)*v for i,v in enumerate(novo)]) % 11
43
44 if r > 1:
45 f = 11 - r
46 else:
47 f = 0
48 novo.append(f)
49
50 # Se o número gerado coincidir com o número original, é válido
51 if novo == inteiros:
52 return cpf
53 return False
54
55 def validar_cnpj(cnpj):
56 """
57 Valida CNPJs, retornando apenas a string de números válida.
58
59 # CNPJs errados
60 >>> validar_cnpj('abcdefghijklmn')
61 False
62 >>> validar_cnpj('123')
63 False
64 >>> validar_cnpj('')
65 False
66 >>> validar_cnpj(None)
67 False
68 >>> validar_cnpj('12345678901234')
69 False
70 >>> validar_cnpj('11222333000100')
71 False
72
73 # CNPJs corretos
74 >>> validar_cnpj('11222333000181')
75 '11222333000181'
76 >>> validar_cnpj('11.222.333/0001-81')
77 '11222333000181'
78 >>> validar_cnpj(' 11 222 333 0001 81 ')
79 '11222333000181'
80 """
81 cnpj = ''.join(re.findall('\d', str(cnpj)))
82
83 if (not cnpj) or (len(cnpj) < 14):
84 return False
85
86 # Pega apenas os 12 primeiros dígitos do CNPJ e gera os 2 dígitos que faltam
87 inteiros = map(int, cnpj)
88 novo = inteiros[:12]
89
90 prod = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
91 while len(novo) < 14:
92 r = sum([x*y for (x, y) in zip(novo, prod)]) % 11
93 if r > 1:
94 f = 11 - r
95 else:
96 f = 0
97 novo.append(f)
98 prod.insert(0, 6)
99
100 # Se o número gerado coincidir com o número original, é válido
101 if novo == inteiros:
102 return cnpj
103 return False
104
105 if __name__ == "__main__":
106 import doctest, sys
107 result = doctest.testmod() #verbose=True)
108 if result[0] == 0:
109 print "OK!"
110 else:
111 print result
Volta para CookBook.