2870
Comentário:
|
3892
|
Deleções são marcadas assim. | Adições são marcadas assim. |
Linha 8: | Linha 8: |
{{{ #!python #/usr/bin/env python # -*- coding:UTF-8 -*- def _gen(cpf): """Gera o próximo dígito do número de CPF """ res = [] for i in range(len(cpf)): a = cpf[i] b = (len(cpf) + 1 - i) res.append(b * a) res = sum(res) % 11 if res > 1: return (11 - res) return 0 def _translate(cpf): """Traduz o número como string na forma: 123.456.789-10 para a forma: 12345678910 """ i = xrange(256) t = [' '] * 256 e = ''.join([chr(x) for x in i if not chr(x).isdigit()]) for x in i: if chr(x).isdigit(): t[x] = chr(x) return cpf.translate(''.join(t), e) class CPF(object): def __init__(self, cpf): """O argumento cpf pode ser uma string nas formas: 12345678910 123.456.789-10 ou uma lista ou tuple [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0] (1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0) """ if isinstance(cpf, basestring): if not cpf.isdigit(): cpf = _translate(cpf) self.cpf = [int(x) for x in cpf] def __getitem__(self, index): """Retorna o dígito em index como string """ return self.cpf[index] def __repr__(self): """Retorna uma representação 'real', ou seja: eval(repr(cpf)) == cpf """ return "CPF('%s')" % ''.join([str(x) for x in self.cpf]) def __eq__(self, other): """Provê teste de igualdade para números de CPF """ if isinstance(other, CPF): return self.cpf == other.cpf return False def __str__(self): """Retorna uma representação do CPF na forma: 123.456.789-10 """ d = iter("..-") s = map(str, self.cpf) for i in xrange(3, 12, 4): s.insert(i, d.next()) r = ''.join(s) return r def verificar(self): """Valida o número de cpf """ s = self.cpf[:9] s.append(_gen(s)) s.append(_gen(s)) return bool(s == self.cpf[:]) }}} == Exemplo de uso == |
|
Linha 136: | Linha 15: |
from cpf import CPF | """ |
Linha 138: | Linha 17: |
# Estes números foram gerados aleatoriamente :) | Este módulo fornece uma classe wrapper para ser usada com números de CPF, que além de oferecer um método simples de verificação, também conta com métodos para comparação e conversão. |
Linha 140: | Linha 21: |
VALIDO = "113.451.253-80" INVALIDO = "31354110274" |
|
Linha 143: | Linha 22: |
# qualquer um dos dois formatos (com pontos ou não) pode ser usado | >>> a = CPF('56068332551') >>> b = CPF('560.683.325-51') >>> c = CPF((1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0)) >>> assert a.valido() >>> assert b.valido() >>> assert not c.valido() >>> assert a == b >>> assert not b == c >>> assert not a == c >>> assert eval(repr(a)) == a >>> assert eval(repr(b)) == b >>> assert eval(repr(c)) == c >>> assert str(a) == \"560.683.325-51\" >>> assert str(b) == str(a) >>> assert str(c) == \"123.456.789-00\" |
Linha 145: | Linha 38: |
valido = CPF(VALIDO) invalido = CPF(INVALIDO) |
""" |
Linha 148: | Linha 40: |
assert valido.verificar() assert not invalido.verificar() |
|
Linha 151: | Linha 41: |
class CPF(object): def __init__(self, cpf): """Classe representando um número de CPF >>> a = CPF('95524361503') >>> b = CPF('955.243.615-03') >>> c = CPF([9, 5, 5, 2, 4, 3, 6, 1, 5, 0, 3]) """ if isinstance(cpf, basestring): if not cpf.isdigit(): cpf = cpf.replace(".", "") cpf = cpf.replace("-", "") if not cpf.isdigit: raise ValueError("Valor não segue a forma xxx.xxx.xxx-xx") if len(cpf) < 11: raise ValueError("O número de CPF deve ter 11 digítos") self.cpf = map(int, cpf) def __getitem__(self, index): """Retorna o dígito em index como string >>> a = CPF('95524361503') >>> a[9] == '0' True >>> a[10] == '3' True >>> a[9] == 0 False >>> a[10] == 3 False """ return str(self.cpf[index]) def __repr__(self): """Retorna uma representação 'real', ou seja: eval(repr(cpf)) == cpf >>> a = CPF('95524361503') >>> print repr(a) CPF('95524361503') >>> eval(repr(a)) == a True """ return "CPF('%s')" % ''.join([str(x) for x in self.cpf]) def __eq__(self, other): """Provê teste de igualdade para números de CPF >>> a = CPF('95524361503') >>> b = CPF('955.243.615-03') >>> c = CPF('123.456.789-00') >>> a == b True >>> a != c True >>> b != c True """ if isinstance(other, CPF): return self.cpf == other.cpf return False def __str__(self): """Retorna uma string do CPF na forma com pontos e traço >>> a = CPF('95524361503') >>> str(a) '955.243.615-03' """ d = ((3, "."), (7, "."), (11, "-")) s = map(str, self.cpf) for i, v in d: s.insert(i, v) r = ''.join(s) return r def valido(self): """Valida o número de cpf >>> a = CPF('95524361503') >>> a.valido() True >>> b = CPF('12345678900') >>> b.valido() False """ cpf = self.cpf[:9] # pegamos apenas os 9 primeiros dígitos do cpf e geramos os # dois dígitos que faltam while len(cpf) < 11: r = sum(map(lambda(i,v):(len(cpf)+1-i)*v,enumerate(cpf))) % 11 if r > 1: f = 11 - r else: f = 0 cpf.append(f) # se o número com os digítos faltantes coincidir com o número # original, então ele é válido return bool(cpf == self.cpf) if __name__ == "__main__": import doctest, sys doctest.testmod(sys.modules[__name__]) |
Receita: Verificador de CPF
Esse módulo contém algumas funções e classes úteis para aplicações que envolvam cadastros e necessitem validar números de CPF antes de incluir no banco de dados..
Código
1 #/usr/bin/env python
2 # -*- coding:UTF-8 -*-
3
4
5 """
6
7 Este módulo fornece uma classe wrapper para ser usada com números de
8 CPF, que além de oferecer um método simples de verificação, também
9 conta com métodos para comparação e conversão.
10
11
12 >>> a = CPF('56068332551')
13 >>> b = CPF('560.683.325-51')
14 >>> c = CPF((1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0))
15 >>> assert a.valido()
16 >>> assert b.valido()
17 >>> assert not c.valido()
18 >>> assert a == b
19 >>> assert not b == c
20 >>> assert not a == c
21 >>> assert eval(repr(a)) == a
22 >>> assert eval(repr(b)) == b
23 >>> assert eval(repr(c)) == c
24 >>> assert str(a) == \"560.683.325-51\"
25 >>> assert str(b) == str(a)
26 >>> assert str(c) == \"123.456.789-00\"
27
28 """
29
30
31
32
33 class CPF(object):
34
35 def __init__(self, cpf):
36 """Classe representando um número de CPF
37
38 >>> a = CPF('95524361503')
39 >>> b = CPF('955.243.615-03')
40 >>> c = CPF([9, 5, 5, 2, 4, 3, 6, 1, 5, 0, 3])
41
42 """
43 if isinstance(cpf, basestring):
44 if not cpf.isdigit():
45 cpf = cpf.replace(".", "")
46 cpf = cpf.replace("-", "")
47
48 if not cpf.isdigit:
49 raise ValueError("Valor não segue a forma xxx.xxx.xxx-xx")
50
51 if len(cpf) < 11:
52 raise ValueError("O número de CPF deve ter 11 digítos")
53
54 self.cpf = map(int, cpf)
55
56
57 def __getitem__(self, index):
58 """Retorna o dígito em index como string
59
60 >>> a = CPF('95524361503')
61 >>> a[9] == '0'
62 True
63 >>> a[10] == '3'
64 True
65 >>> a[9] == 0
66 False
67 >>> a[10] == 3
68 False
69
70 """
71 return str(self.cpf[index])
72
73 def __repr__(self):
74 """Retorna uma representação 'real', ou seja:
75
76 eval(repr(cpf)) == cpf
77
78 >>> a = CPF('95524361503')
79 >>> print repr(a)
80 CPF('95524361503')
81 >>> eval(repr(a)) == a
82 True
83
84 """
85 return "CPF('%s')" % ''.join([str(x) for x in self.cpf])
86
87 def __eq__(self, other):
88 """Provê teste de igualdade para números de CPF
89
90 >>> a = CPF('95524361503')
91 >>> b = CPF('955.243.615-03')
92 >>> c = CPF('123.456.789-00')
93 >>> a == b
94 True
95 >>> a != c
96 True
97 >>> b != c
98 True
99
100 """
101 if isinstance(other, CPF):
102 return self.cpf == other.cpf
103 return False
104
105 def __str__(self):
106 """Retorna uma string do CPF na forma com pontos e traço
107
108 >>> a = CPF('95524361503')
109 >>> str(a)
110 '955.243.615-03'
111
112
113 """
114 d = ((3, "."), (7, "."), (11, "-"))
115 s = map(str, self.cpf)
116 for i, v in d:
117 s.insert(i, v)
118 r = ''.join(s)
119 return r
120
121 def valido(self):
122 """Valida o número de cpf
123
124 >>> a = CPF('95524361503')
125 >>> a.valido()
126 True
127 >>> b = CPF('12345678900')
128 >>> b.valido()
129 False
130
131 """
132 cpf = self.cpf[:9]
133 # pegamos apenas os 9 primeiros dígitos do cpf e geramos os
134 # dois dígitos que faltam
135 while len(cpf) < 11:
136
137 r = sum(map(lambda(i,v):(len(cpf)+1-i)*v,enumerate(cpf))) % 11
138
139 if r > 1:
140 f = 11 - r
141 else:
142 f = 0
143 cpf.append(f)
144
145 # se o número com os digítos faltantes coincidir com o número
146 # original, então ele é válido
147 return bool(cpf == self.cpf)
148
149
150
151 if __name__ == "__main__":
152
153 import doctest, sys
154 doctest.testmod(sys.modules[__name__])
Volta para CookBook.