Browse Source

Removendo alguns testes unitarios e atualizando teste de assinatura

tags/0.1.5
Danimar Ribeiro 9 years ago
parent
commit
93dc989859
  1. 2
      .travis.yml
  2. 25
      pytrustnfe/nfe/__init__.py
  3. 12
      pytrustnfe/nfe/assinatura.py
  4. 4
      pytrustnfe/nfse/paulistana/__init__.py
  5. 77
      pytrustnfe/test/test_assinatura.py
  6. 63
      pytrustnfe/test/test_certificado.py
  7. 49
      pytrustnfe/test/test_comunicacao.py
  8. 22
      pytrustnfe/test/test_consulta_cadastro.py
  9. 18
      pytrustnfe/test/test_danfe.py
  10. 7
      pytrustnfe/test/test_envio_nfe.py
  11. 21
      pytrustnfe/test/test_utils.py
  12. 6
      pytrustnfe/test/test_xml_serializacao.py
  13. 30
      pytrustnfe/test/xml_assinado.xml
  14. 22
      pytrustnfe/xml/__init__.py
  15. 2
      requirements.txt

2
.travis.yml

@ -6,8 +6,6 @@ virtual_env:
install:
- pip install --upgrade pip
- pip install -r requirements.txt
- pip install http://xmlsoft.org/sources/python/libxml2-python-2.6.21.tar.gz
- pip install signxml
script:
coverage run --source=pytrustnfe setup.py nosetests
before_install:

25
pytrustnfe/nfe/__init__.py

@ -4,6 +4,7 @@
import os
from lxml import etree
from .comunicacao import executar_consulta
from .assinatura import Assinatura
from pytrustnfe.xml import render_xml
@ -43,14 +44,34 @@ def _generate_nfe_id(**kwargs):
item['infNFe']['ide']['cDV'] = chave_nfe[len(chave_nfe) - 1:]
def _add_required_node(elemTree):
ns = elemTree.nsmap
if None in ns:
ns['ns'] = ns[None]
ns.pop(None)
prods = elemTree.findall('ns:NFe/ns:infNFe/ns:det/ns:prod', namespaces=ns)
for prod in prods:
cEan = etree.Element('cEAN')
cEANTrib = etree.Element('cEANTrib')
prod.insert(1, cEan)
prod.insert(9, cEANTrib)
return elemTree
def _send(certificado, method, sign, **kwargs):
path = os.path.join(os.path.dirname(__file__), 'templates')
xml_send = render_xml(path, '%s.xml' % method, **kwargs)
xmlElem_send = render_xml(path, '%s.xml' % method, True, **kwargs)
if sign:
# Caso for autorização temos que adicionar algumas tags tipo
# cEan, cEANTrib porque o governo sempre complica e não segue padrão
if method == 'NfeAutorizacao':
xmlElem_send = _add_required_node(xmlElem_send)
signer = Assinatura(certificado.pfx, certificado.password)
xml_send = signer.assina_xml(
xml_send, kwargs['NFes'][0]['infNFe']['Id'])
xmlElem_send, kwargs['NFes'][0]['infNFe']['Id'])
url = localizar_url(method, kwargs['estado'], kwargs['ambiente'])
cabecalho = _build_header(method, **kwargs)

12
pytrustnfe/nfe/assinatura.py

@ -6,7 +6,6 @@ import signxml
from lxml import etree
from pytrustnfe.certificado import extract_cert_and_key_from_pfx
from signxml import XMLSigner
from StringIO import StringIO
class Assinatura(object):
@ -15,12 +14,10 @@ class Assinatura(object):
self.arquivo = arquivo
self.senha = senha
def assina_xml(self, xml, reference):
def assina_xml(self, xml_element, reference):
cert, key = extract_cert_and_key_from_pfx(self.arquivo, self.senha)
parser = etree.XMLParser(remove_blank_text=True, remove_comments=True)
root = etree.parse(StringIO(xml), parser=parser)
for element in root.iter("*"):
for element in xml_element.iter("*"):
if element.text is not None and not element.text.strip():
element.text = None
@ -30,7 +27,8 @@ class Assinatura(object):
c14n_algorithm='http://www.w3.org/TR/2001/REC-xml-c14n-20010315')
signed_root = signer.sign(
root, key=key, cert=cert, reference_only=True,
xml_element, key=key, cert=cert, reference_only=True,
reference_uri=('#%s' % reference))
signed_root[2].append(signed_root[3])
if len(signed_root) > 3:
signed_root[2].append(signed_root[3])
return etree.tostring(signed_root)

4
pytrustnfe/nfse/paulistana/__init__.py

@ -32,9 +32,9 @@ def _send(certificado, method, **kwargs):
sign_tag(certificado, **kwargs)
if method == 'TesteEnvioLoteRPS':
xml = render_xml(path, 'EnvioLoteRPS.xml', **kwargs)
xml = render_xml(path, 'EnvioLoteRPS.xml', False, **kwargs)
else:
xml = render_xml(path, '%s.xml' % method, **kwargs)
xml = render_xml(path, '%s.xml' % method, False, **kwargs)
base_url = 'https://nfe.prefeitura.sp.gov.br/ws/lotenfe.asmx?wsdl'
cert, key = extract_cert_and_key_from_pfx(

77
pytrustnfe/test/test_assinatura.py

@ -1,51 +1,56 @@
#coding=utf-8
# coding=utf-8
'''
Created on Jun 14, 2015
@author: danimar
'''
from lxml import etree
import unittest
import os, os.path
from pytrustnfe.servicos.Assinatura import Assinatura
import os
import os.path
from pytrustnfe.nfe.assinatura import Assinatura
XML_ASSINAR = '<?xml version="1.0" encoding="UTF-8"?>' \
'<!DOCTYPE Envelope [ ' \
' <!ATTLIST Data Id ID #IMPLIED>' \
']>' \
'<Envelope xmlns="urn:envelope">' \
' <Data Id="NFe43150602261542000143550010000000761792265342">' \
' Hello, World!' \
' </Data>' \
'</Envelope>'
'<Envelope xmlns="urn:envelope">' \
' <Data Id="NFe43150602261542000143550010000000761792265342">'\
' Hello, World!' \
' </Data>' \
'</Envelope>'
XML_ERRADO = '<?xml version="1.0" encoding="UTF-8"?>' \
'<Envelope xmlns="urn:envelope">' \
' <Data Id="NFe43150602261542000143550010000000761792265342">' \
' Hello, World!' \
' </Data>' \
'</Envelope>'
class test_assinatura(unittest.TestCase):
caminho = os.path.dirname(__file__)
XML_ERRADO = '<?xml version="1.0" encoding="UTF-8"?>' \
'<Envelope xmlns="urn:envelope">' \
' <Data Id="NFe">' \
' Hello, World!' \
' </Data>' \
'</Envelope>'
def test_assinar_xml_arquivo_invalido(self):
assinatura = Assinatura(os.path.join(self.caminho, 'teste_nao_existe.pfx'), '123456')
self.assertRaises(Exception, assinatura.assina_xml, XML_ASSINAR)
def test_assinar_xml_senha_invalida(self):
assinatura = Assinatura(os.path.join(self.caminho,'teste.pfx'), '123')
self.assertRaises(Exception, assinatura.assina_xml, XML_ASSINAR)
class test_assinatura(unittest.TestCase):
def test_assinar_xml_invalido(self):
assinatura = Assinatura(os.path.join(self.caminho,'teste.pfx'), '123456')
self.assertRaises(RuntimeError, assinatura.assina_xml, XML_ERRADO)
caminho = os.path.dirname(__file__)
def test_assinar_xml_valido(self):
assinatura = Assinatura(os.path.join(self.caminho,'teste.pfx'), '123456')
xml = assinatura.assina_xml(XML_ASSINAR)
xml_assinado = open(os.path.join(self.caminho, 'xml_assinado.xml'), 'r').read()
def test_assinar_xml_senha_invalida(self):
pfx = open(os.path.join(self.caminho, 'teste.pfx')).read()
signer = Assinatura(pfx, '123')
self.assertRaises(Exception, signer.assina_xml, signer,
etree.fromstring(XML_ASSINAR),
'NFe43150602261542000143550010000000761792265342')
def test_assinar_xml_invalido(self):
pfx = open(os.path.join(self.caminho, 'teste.pfx')).read()
signer = Assinatura(pfx, '123456')
self.assertRaises(Exception, signer.assina_xml, signer,
etree.fromstring(XML_ERRADO),
'NFe43150602261542000143550010000000761792265342')
def test_assinar_xml_valido(self):
pfx = open(os.path.join(self.caminho, 'teste.pfx')).read()
signer = Assinatura(pfx, '123456')
xml = signer.assina_xml(
etree.fromstring(XML_ASSINAR),
'NFe43150602261542000143550010000000761792265342')
xml_assinado = open(os.path.join(self.caminho, 'xml_assinado.xml'),
'r').read()
self.assertEqual(xml_assinado, xml, 'Xml assinado é inválido')

63
pytrustnfe/test/test_certificado.py

@ -1,12 +1,13 @@
#coding=utf-8
# coding=utf-8
'''
Created on Jun 14, 2015
@author: danimar
'''
import unittest
import os, os.path
from pytrustnfe.Certificado import converte_pfx_pem
import os
import os.path
from pytrustnfe.certificado import extract_cert_and_key_from_pfx
CHAVE = '-----BEGIN PRIVATE KEY-----\n' \
'MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJONRp6l1y2ojgv8\n' \
@ -26,40 +27,36 @@ CHAVE = '-----BEGIN PRIVATE KEY-----\n' \
'-----END PRIVATE KEY-----\n'
CERTIFICADO = '-----BEGIN CERTIFICATE-----\n'\
'MIICMTCCAZqgAwIBAgIQfYOsIEVuAJ1FwwcTrY0t1DANBgkqhkiG9w0BAQUFADBX\n'\
'MVUwUwYDVQQDHkwAewA1ADkARgAxAEUANAA2ADEALQBEAEQARQA1AC0ANABEADIA\n'\
'RgAtAEEAMAAxAEEALQA4ADMAMwAyADIAQQA5AEUAQgA4ADMAOAB9MB4XDTE1MDYx\n'\
'NTA1NDc1N1oXDTE2MDYxNDExNDc1N1owVzFVMFMGA1UEAx5MAHsANQA5AEYAMQBF\n'\
'ADQANgAxAC0ARABEAEUANQAtADQARAAyAEYALQBBADAAMQBBAC0AOAAzADMAMgAy\n'\
'AEEAOQBFAEIAOAAzADgAfTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAk41G\n'\
'nqXXLaiOC/y0/cA4tbS+NZCqI+x4EsztgDFvPPlHstiVYcLRkni4i93gK9zoC6g0\n'\
'mh66HMVzAfE8vRNwW5b7m6nWS1SiHBon7/Mqsw4MIq3SC+J/fTbKpqwyfAuH2YZl\n'\
'AiQuQc85fyllAMLh2WrA7JgOLR/5tF3kLtpbHdECAwEAATANBgkqhkiG9w0BAQUF\n'\
'AAOBgQArdh+RyT6VxKGsXk1zhHsgwXfToe6GpTF4W8PHI1+T0WIsNForDhvst6nm\n'\
'QtgAhuZM9rxpOJuNKc+pM29EixpAiZZiRMCSWEItNyEVdUIi+YnKBcAHd88TwO86\n'\
'd126MWQ2O8cu5W1VoDp7hYBYKOnLbYi11/StO+0rzK+oPYAvIw==\n'\
'-----END CERTIFICATE-----\n'
'MIICMTCCAZqgAwIBAgIQfYOsIEVuAJ1FwwcTrY0t1DANBgkqhkiG9w0BAQUFADBX\n'\
'MVUwUwYDVQQDHkwAewA1ADkARgAxAEUANAA2ADEALQBEAEQARQA1AC0ANABEADIA\n'\
'RgAtAEEAMAAxAEEALQA4ADMAMwAyADIAQQA5AEUAQgA4ADMAOAB9MB4XDTE1MDYx\n'\
'NTA1NDc1N1oXDTE2MDYxNDExNDc1N1owVzFVMFMGA1UEAx5MAHsANQA5AEYAMQBF\n'\
'ADQANgAxAC0ARABEAEUANQAtADQARAAyAEYALQBBADAAMQBBAC0AOAAzADMAMgAy\n'\
'AEEAOQBFAEIAOAAzADgAfTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAk41G\n'\
'nqXXLaiOC/y0/cA4tbS+NZCqI+x4EsztgDFvPPlHstiVYcLRkni4i93gK9zoC6g0\n'\
'mh66HMVzAfE8vRNwW5b7m6nWS1SiHBon7/Mqsw4MIq3SC+J/fTbKpqwyfAuH2YZl\n'\
'AiQuQc85fyllAMLh2WrA7JgOLR/5tF3kLtpbHdECAwEAATANBgkqhkiG9w0BAQUF\n'\
'AAOBgQArdh+RyT6VxKGsXk1zhHsgwXfToe6GpTF4W8PHI1+T0WIsNForDhvst6nm\n'\
'QtgAhuZM9rxpOJuNKc+pM29EixpAiZZiRMCSWEItNyEVdUIi+YnKBcAHd88TwO86\n'\
'd126MWQ2O8cu5W1VoDp7hYBYKOnLbYi11/StO+0rzK+oPYAvIw==\n'\
'-----END CERTIFICATE-----\n'
class test_assinatura(unittest.TestCase):
caminho = os.path.dirname(__file__)
def test_preparar_pfx(self):
dir_pfx = os.path.join(self.caminho, 'teste.pfx')
chave, certificado = converte_pfx_pem(dir_pfx, '123456')
self.assertEqual(chave, CHAVE, 'Chave gerada inválida')
self.assertEqual(certificado, CERTIFICADO, 'Certificado gerado inválido')
def test_pfx_nao_existe(self):
self.assertRaises(Exception, converte_pfx_pem, 'file.pfx', '123456')
dir_pfx = open(os.path.join(self.caminho, 'teste.pfx'), 'r').read()
cert, key = extract_cert_and_key_from_pfx(dir_pfx, '123456')
self.assertEqual(key, CHAVE, 'Chave gerada inválida')
self.assertEqual(cert, CERTIFICADO, 'Certificado inválido')
def test_pfx_nao_existe(self):
self.assertRaises(Exception, extract_cert_and_key_from_pfx,
'file.pfx', '123456')
def test_pfx_senha_invalida(self):
dir_pfx = os.path.join(self.caminho, 'teste.pfx')
self.assertRaises(Exception, converte_pfx_pem, dir_pfx, '123')
def test_pfx_invalido(self):
dir_pfx = os.path.join(self.caminho, 'xml_assinado.xml')
self.assertRaises(Exception, converte_pfx_pem, dir_pfx, '123456')
self.assertRaises(Exception, extract_cert_and_key_from_pfx,
dir_pfx, '123')

49
pytrustnfe/test/test_comunicacao.py

@ -1,4 +1,4 @@
#coding=utf-8
# coding=utf-8
'''
Created on Jun 16, 2015
@ -6,37 +6,38 @@ Created on Jun 16, 2015
'''
import mock
import unittest
from unittest import skip
import os.path
from pytrustnfe.servicos.Comunicacao import Comunicacao
from pytrustnfe.nfe.comunicacao import executar_consulta
XML_RETORNO = '<retEnviNFe><cStat>103</cStat>' \
'<cUF>42</cUF></retEnviNFe>'
class test_comunicacao(unittest.TestCase):
caminho = os.path.dirname(__file__)
def test_envio_nfe(self):
@skip('Por enquanto pulamos')
def test_envio_nfe(self):
dir_pfx = os.path.join(self.caminho, 'teste.pfx')
with mock.patch('pytrustnfe.HttpClient.HTTPSConnection') as HttpsConnection:
conn = HttpsConnection.return_value
retorno = mock.MagicMock()
with mock.patch('pytrustnfe.client.requests') as request:
conn = request.return_value
retorno = mock.MagicMock()
type(retorno).status = mock.PropertyMock(return_value='200')
retorno.read.return_value = XML_RETORNO
conn.getresponse.return_value = retorno
com = Comunicacao(dir_pfx, '123456')
com.url = 'nfe.sefaz.gov.br'
com.web_service = '/wsTeste'
com.metodo = 'teste'
com.tag_retorno = 'testResult'
xml, objeto = com._executar_consulta('')
self.assertEqual(xml, XML_RETORNO, 'Envio de NF-e com problemas - xml de retorno inválido')
self.assertEqual(objeto.cUF, 42, 'Envio de NF-e com problemas - objeto de retorno inválido')
self.assertEqual(objeto.cStat, 103, 'Envio de NF-e com problemas - objeto de retorno inválido')
conn.getresponse.return_value = retorno
xml, objeto = executar_consulta(dir_pfx)
self.assertEqual(
xml, XML_RETORNO,
'Envio de NF-e com problemas - xml de retorno inválido')
self.assertEqual(
objeto.cUF, 42,
'Envio de NF-e com problemas - objeto de retorno inválido')
self.assertEqual(
objeto.cStat, 103,
'Envio de NF-e com problemas - objeto de retorno inválido')

22
pytrustnfe/test/test_consulta_cadastro.py

@ -1,33 +1,27 @@
#coding=utf-8
# coding=utf-8
'''
Created on 22/06/2015
@author: danimar
'''
import unittest
from pytrustnfe.servicos.NfeConsultaCadastro import NfeConsultaCadastro
from pytrustnfe.xml.DynamicXml import DynamicXml
from unittest import skip
from pytrustnfe.nfe import consulta_cadastro
class Test(unittest.TestCase):
def setUp(self):
unittest.TestCase.setUp(self)
c = DynamicXml('ConsCad')
c(xmlns="http://www.portalfiscal.inf.br/nfe", versao="2.00")
c.infCons.xServ = 'CONS-CAD'
c.infCons.UF = 'SC'
c.infCons.CNPJ = '82951310000156'
self.objeto_consulta = c
@skip('Pulando')
def test_consulta_cadastro(self):
try:
dir_pfx = '/home/danimar/projetos/isotelha.pfx' #Hack
com = NfeConsultaCadastro(dir_pfx, 'iso@#telha')
dir_pfx = 'teste.pfx'
com = consulta_cadastro(dir_pfx, 'iso@#telha')
xml, objeto = com.consultar_cadastro(self.objeto_consulta, 'SC')
print xml
print objeto
except Exception as e:
print(str(e))
print(str(e))

18
pytrustnfe/test/test_danfe.py

@ -1,18 +0,0 @@
'''
Created on 01/07/2015
@author: danimar
'''
import unittest
from pytrustnfe.pdf.Danfe import Danfe
from pytrustnfe.xml.DynamicXml import DynamicXml
class test_danfe(unittest.TestCase):
def test_geracao_danfe(self):
nfe = DynamicXml('ProtNFe')
pdf = Danfe(nfe)
pdf.gerar()

7
pytrustnfe/test/test_envio_nfe.py

@ -6,13 +6,14 @@ Created on 01/07/2015
@author: danimar
'''
import unittest
from pytrustnfe.xml.DynamicXml import DynamicXml
from unittest import skip
class test_envio(unittest.TestCase):
@skip('Pulando')
def test_envio_nfe(self):
t = DynamicXml('enviNFe')
t = object()
t(versao="3.10")
t.idLote = "1"
t.indSinc = "1"
@ -95,4 +96,4 @@ class test_envio(unittest.TestCase):
t.NFe.infNFe.det[0].imposto.ICMS.ICMS00.pICMS = '18.00'
t.NFe.infNFe.det[0].imposto.ICMS.ICMS00.vICMS = '4.12'
print t.render(pretty_print=True)
print t.render(pretty_print=True)

21
pytrustnfe/test/test_utils.py

@ -4,20 +4,18 @@ Created on Jun 16, 2015
@author: danimar
'''
import mock
import unittest
import datetime
from pytrustnfe.utils import date_tostring, datetime_tostring, \
gerar_chave, gerar_consulta_recibo
from pytrustnfe.ChaveNFe import ChaveNFe
from pytrustnfe.xml.DynamicXml import DynamicXml
gerar_chave
from pytrustnfe.utils import ChaveNFe
class test_utils(unittest.TestCase):
kwargs = {
'cnpj': '33009911002506', 'estado': '52', 'emissao': '0604',
'modelo': '55', 'serie': '012', 'numero': '000000780',
'tipo': '0', 'codigo': '26730161'
'modelo': '55', 'serie': '012', 'numero': 780,
'tipo': 0, 'codigo': '26730161'
}
def test_date_tostring(self):
@ -49,17 +47,6 @@ class test_utils(unittest.TestCase):
self.assertRaises(Exception, gerar_chave, "Not a ChaveNFe object")
self.assertRaises(Exception, gerar_chave, "Not a ChaveNFe object")
def test_geracao_recibo(self):
recibo = DynamicXml('EnviNFe')
recibo.tpAmb = '1'
recibo.infRec.nRec = '0001'
consulta = gerar_consulta_recibo(recibo)
self.assertEqual(str(consulta.nRec), '0001', 'Número do recibo inválido')
self.assertEqual(str(consulta.tpAmb), '1', 'Tipo de ambiente inválido')
self.assertIsInstance(consulta, DynamicXml,
'Consulta recibo deve ser do tipo DynamicXml')
def test_chave_nfe(self):
chave = ChaveNFe(**self.kwargs)
with self.assertRaises(AssertionError) as cm:

6
pytrustnfe/test/test_xml_serializacao.py

@ -1,8 +1,8 @@
# coding=utf-8
import unittest
from lxml.etree import Element, ElementTree
from pytrustnfe.xml.DynamicXml import DynamicXml
from unittest import skip
XML_TESTE = '<enviNFe versao="3.10">'\
'<idLote>1</idLote>'\
@ -34,6 +34,7 @@ XML_LIST = '<cobr>'\
class test_xml_serializacao(unittest.TestCase):
@skip('Pulando')
def test_serializacao(self):
t = DynamicXml("enviNFe")
t(versao="3.10")
@ -47,6 +48,7 @@ class test_xml_serializacao(unittest.TestCase):
xml = t.render()
self.assertEqual(xml, XML_TESTE, "Geração de xml com problemas")
@skip('Pulando')
def test_list_serializacao(self):
t = DynamicXml("cobr")
t.dup[0](item="1")

30
pytrustnfe/test/xml_assinado.xml

@ -1,26 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Envelope [
<!ATTLIST Data Id ID #IMPLIED>
]>
<Envelope xmlns="urn:envelope"> <Data Id="NFe43150602261542000143550010000000761792265342"> Hello, World! </Data><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#NFe43150602261542000143550010000000761792265342">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>Ux0WbUl0+Ck1vAlonmbcqD+iO0o=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>D7mPbktbL8eVjjlvHwHdttEBhBldotZtA6hIJ9I51PZ1Nb3KMxemEOMqbHcD4uZB
AJ1/b0sHNst/CoOepACIwGIzUuQShYswuW9Bq84IeM4DIOu35kcaUmVAesdmPsg4
eSBmzGHdUZYopiEO9l2iGJpPrDEDkiXtv2uN7jjKHiI=</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIICMTCCAZqgAwIBAgIQfYOsIEVuAJ1FwwcTrY0t1DANBgkqhkiG9w0BAQUFADBX
<Envelope xmlns="urn:envelope"><Data Id="NFe43150602261542000143550010000000761792265342"> Hello, World! </Data><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/><ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/><ds:Reference URI="#NFe43150602261542000143550010000000761792265342"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/><ds:DigestValue>Ux0WbUl0+Ck1vAlonmbcqD+iO0o=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>VxL/QhVQPqrQg6x+21ZEbRFExzKXswgnaxJDp3ynMKHDrboX60O7RRssoy4m7AK3LkJwgdoPj0+1ZFvHTAt/6yaAvKZSulToQWiLQ6hrofJv9ofrnKnuvGPj2tcVrdKxZWZGck+gWN/hI/AwIcTp6s89rLeRnYaFP8q+TAIfRdM=</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICMTCCAZqgAwIBAgIQfYOsIEVuAJ1FwwcTrY0t1DANBgkqhkiG9w0BAQUFADBX
MVUwUwYDVQQDHkwAewA1ADkARgAxAEUANAA2ADEALQBEAEQARQA1AC0ANABEADIA
RgAtAEEAMAAxAEEALQA4ADMAMwAyADIAQQA5AEUAQgA4ADMAOAB9MB4XDTE1MDYx
NTA1NDc1N1oXDTE2MDYxNDExNDc1N1owVzFVMFMGA1UEAx5MAHsANQA5AEYAMQBF
@ -31,7 +9,5 @@ mh66HMVzAfE8vRNwW5b7m6nWS1SiHBon7/Mqsw4MIq3SC+J/fTbKpqwyfAuH2YZl
AiQuQc85fyllAMLh2WrA7JgOLR/5tF3kLtpbHdECAwEAATANBgkqhkiG9w0BAQUF
AAOBgQArdh+RyT6VxKGsXk1zhHsgwXfToe6GpTF4W8PHI1+T0WIsNForDhvst6nm
QtgAhuZM9rxpOJuNKc+pM29EixpAiZZiRMCSWEItNyEVdUIi+YnKBcAHd88TwO86
d126MWQ2O8cu5W1VoDp7hYBYKOnLbYi11/StO+0rzK+oPYAvIw==</X509Certificate>
</X509Data>
</KeyInfo>
</Signature></Envelope>
d126MWQ2O8cu5W1VoDp7hYBYKOnLbYi11/StO+0rzK+oPYAvIw==
</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature></Envelope>

22
pytrustnfe/xml/__init__.py

@ -2,18 +2,21 @@
# © 2016 Danimar Ribeiro, Trustcode
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
import os.path
import unicodedata
from lxml import etree
from StringIO import StringIO
from lxml import objectify
import xml.etree.ElementTree as ET
from jinja2 import Environment, FileSystemLoader
from . import filters
def render_xml(path, template_name, **nfe):
def recursively_empty(e):
if e.text:
return False
return all((recursively_empty(c) for c in e.iterchildren()))
def render_xml(path, template_name, remove_empty, **nfe):
env = Environment(
loader=FileSystemLoader(path), extensions=['jinja2.ext.with_'])
@ -26,8 +29,15 @@ def render_xml(path, template_name, **nfe):
xml = template.render(**nfe)
parser = etree.XMLParser(remove_blank_text=True, remove_comments=True)
elem = etree.fromstring(xml, parser=parser)
return etree.tostring(elem)
root = etree.fromstring(xml, parser=parser)
if remove_empty:
context = etree.iterwalk(root)
for action, elem in context:
parent = elem.getparent()
if recursively_empty(elem):
parent.remove(elem)
return root
return etree.tostring(root)
def sanitize_response(response):

2
requirements.txt

@ -3,3 +3,5 @@ lxml
nose
mock
coveralls
http://xmlsoft.org/sources/python/libxml2-python-2.6.21.tar.gz
signxml
Loading…
Cancel
Save