You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
4.4 KiB
171 lines
4.4 KiB
# *-* encoding: utf-8 *-*
|
|
|
|
import os
|
|
import codecs
|
|
import unicodedata
|
|
|
|
try:
|
|
from lxml import etree
|
|
except ImportError:
|
|
try:
|
|
# Python 2.5 - cElementTree
|
|
import xml.etree.cElementTree as etree
|
|
except ImportError:
|
|
try:
|
|
# Python 2.5 - ElementTree
|
|
import xml.etree.ElementTree as etree
|
|
except ImportError:
|
|
try:
|
|
# Instalacao normal do cElementTree
|
|
import cElementTree as etree
|
|
except ImportError:
|
|
try:
|
|
# Instalacao normal do ElementTree
|
|
import elementtree.ElementTree as etree
|
|
except ImportError:
|
|
raise Exception('Falhou ao importar lxml/ElementTree')
|
|
|
|
try:
|
|
from cStringIO import StringIO
|
|
except ImportError:
|
|
from StringIO import StringIO
|
|
|
|
import flags
|
|
|
|
# from geraldo.utils import memoize
|
|
|
|
|
|
# @memoize
|
|
def so_numeros(texto):
|
|
"""Retorna o texto informado mas somente os numeros"""
|
|
return ''.join(filter(lambda c: ord(c) in range(48, 58), texto))
|
|
|
|
|
|
# @memoize
|
|
def obter_pais_por_codigo(codigo):
|
|
# TODO
|
|
if codigo == '1058':
|
|
return 'Brasil'
|
|
|
|
CAMINHO_DATA = os.path.join(os.path.dirname(
|
|
os.path.abspath(__file__)), '..', 'data')
|
|
CAMINHO_MUNICIPIOS = os.path.join(CAMINHO_DATA, 'MunIBGE')
|
|
CARACTERS_ACENTUADOS = {
|
|
ord(u'á'): u'a',
|
|
ord(u'â'): u'a',
|
|
ord(u'à'): u'a',
|
|
ord(u'ã'): u'a',
|
|
ord(u'é'): u'e',
|
|
ord(u'ê'): u'e',
|
|
ord(u'í'): u'i',
|
|
ord(u'ó'): u'o',
|
|
ord(u'õ'): u'o',
|
|
ord(u'ô'): u'o',
|
|
ord(u'ú'): u'u',
|
|
ord(u'ç'): u'c',
|
|
}
|
|
|
|
|
|
# @memoize
|
|
def normalizar_municipio(municipio):
|
|
if not isinstance(municipio, unicode):
|
|
municipio = municipio.decode('utf-8')
|
|
|
|
return municipio.lower().translate(CARACTERS_ACENTUADOS).upper()
|
|
|
|
|
|
# @memoize
|
|
def carregar_arquivo_municipios(uf, reverso=False):
|
|
if isinstance(uf, basestring):
|
|
try:
|
|
uf = int(uf)
|
|
except ValueError:
|
|
uf = flags.CODIGOS_ESTADOS[uf.upper()]
|
|
|
|
caminho_arquivo = os.path.join(CAMINHO_MUNICIPIOS, 'MunIBGE-UF%s.txt' % uf)
|
|
|
|
# Carrega o conteudo do arquivo
|
|
fp = codecs.open(caminho_arquivo, "r", "utf-8-sig")
|
|
linhas = list(fp.readlines())
|
|
fp.close()
|
|
|
|
municipios_dict = {}
|
|
|
|
for linha in linhas:
|
|
codigo, municipio = linha.split('\t')
|
|
codigo = codigo.strip()
|
|
municipio = municipio.strip()
|
|
|
|
if not reverso:
|
|
municipios_dict[codigo] = municipio
|
|
else:
|
|
municipios_dict[normalizar_municipio(municipio)] = codigo
|
|
|
|
return municipios_dict
|
|
|
|
|
|
# @memoize
|
|
def obter_codigo_por_municipio(municipio, uf):
|
|
# TODO: fazer UF ser opcional
|
|
municipios = carregar_arquivo_municipios(uf, True)
|
|
return municipios[normalizar_municipio(municipio)]
|
|
|
|
|
|
# @memoize
|
|
def obter_municipio_por_codigo(codigo, uf, normalizado=False):
|
|
# TODO: fazer UF ser opcional
|
|
municipios = carregar_arquivo_municipios(uf)
|
|
municipio = municipios.get(unicode(codigo))
|
|
if municipio is None:
|
|
raise ValueError
|
|
if normalizado:
|
|
return normalizar_municipio(municipio)
|
|
return municipio
|
|
|
|
|
|
# @memoize
|
|
def obter_municipio_e_codigo(dados, uf):
|
|
'''Retorna código e município
|
|
municipio_ou_codigo - espera receber um dicionário no formato:
|
|
{codigo: 121212, municipio: u'municipio'}
|
|
'''
|
|
|
|
cod = dados.get('codigo', '')
|
|
mun = normalizar_municipio(dados.get('municipio', ''))
|
|
try:
|
|
cod = int(cod)
|
|
except ValueError:
|
|
cod = obter_codigo_por_municipio(mun, uf)
|
|
# TODO: se ainda com este teste apresentar erros de nessa seção
|
|
# desenvolver um retorno que informe ao cliente quais nfes estão com erro
|
|
# e não explodir esse a geração das outras nfes
|
|
municipio = obter_municipio_por_codigo(cod, uf, normalizado=True)
|
|
return cod, municipio
|
|
|
|
# @memoize
|
|
def extrair_tag(root):
|
|
return root.tag.split('}')[-1]
|
|
|
|
|
|
def formatar_decimal(dec):
|
|
if dec * 100 - int(dec * 100):
|
|
return str(dec)
|
|
else:
|
|
return "%.2f" % dec
|
|
|
|
|
|
def safe_str(str_):
|
|
if not isinstance(str_, unicode):
|
|
if isinstance(str_, str):
|
|
str_ = str_.decode('utf8')
|
|
else:
|
|
str_ = unicode(str_)
|
|
return unicodedata.normalize('NFKD', str_).encode('ascii', 'ignore')
|
|
|
|
|
|
def obter_uf_por_codigo(codigo_uf):
|
|
if isinstance(codigo_uf, basestring) and codigo_uf.isalpha():
|
|
return codigo_uf
|
|
|
|
estados = {v: k for k, v in flags.CODIGOS_ESTADOS.items()}
|
|
return estados[unicode(codigo_uf)]
|