Skip to content

Commit

Permalink
Merge pull request #323 from danimaribeiro/feature/publish-github
Browse files Browse the repository at this point in the history
Create python-publish.yml
  • Loading branch information
danimaribeiro authored May 11, 2023
2 parents 5a105bb + fccafec commit 2801635
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 139 deletions.
39 changes: 39 additions & 0 deletions .github/workflows/python-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

name: Upload Python Package

on:
release:
types: [published]

permissions:
contents: read

jobs:
deploy:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: '3.7'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Publish package
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
41 changes: 41 additions & 0 deletions .github/workflows/python-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Python application

on:
push:
branches: [ "master3" ]
pull_request:
branches: [ "master3" ]

permissions:
contents: read

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.7"
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -qq libxml2-dev libxmlsec1-dev libxmlsec1-openssl
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest --cov=pytrustnfe
2 changes: 1 addition & 1 deletion pytrustnfe/certificado.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def save_pfx(self):


def extract_cert_and_key_from_pfx(pfx, password):
pfx = crypto.load_pkcs12(pfx, password)
pfx = crypto.load_pkcs12(pfx, password.encode())
# PEM formatted private key
key = crypto.dump_privatekey(crypto.FILETYPE_PEM, pfx.get_privatekey())
# PEM formatted certificate
Expand Down
110 changes: 0 additions & 110 deletions pytrustnfe/nfe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,116 +68,6 @@ def _render(certificado, method, sign, **kwargs):
return xml_send


def gerar_qrcode(id_csc: int, csc: str, xml_send: str, cert = False) -> str:
xml = etree.fromstring(xml_send)
signature = xml.find(
".//{http://www.w3.org/2000/09/xmldsig#}Signature")
id = xml.find(
".//{http://www.portalfiscal.inf.br/nfe}infNFe").get('Id')
if id is None:
raise Exception("XML Invalido - Sem o ID")

chave = id.replace('NFe', '')
emit_uf = chave[:2]

tp_amb = xml.find(".//{http://www.portalfiscal.inf.br/nfe}tpAmb")
if tp_amb is None:
raise Exception("XML Invalido - Sem o tipo de ambiente")

dh_emi = xml.find(".//{http://www.portalfiscal.inf.br/nfe}dhEmi")
if dh_emi is None:
raise Exception("XML Invalido - Sem data de Emissao")
dh_emi = dh_emi.text.split("-")[2].split("T")[0]

tp_emis = xml.find(".//{http://www.portalfiscal.inf.br/nfe}tpEmis")
if tp_emis is None:
raise Exception("XML Invalido - Sem tipo de emissao")

v_nf = xml.find(".//{http://www.portalfiscal.inf.br/nfe}vNF")
if v_nf is None:
raise Exception("XML Invalido - Sem o valor da NFe")

url_qrcode_str = url_qrcode(
estado=emit_uf,
ambiente=tp_amb.text)
url_qrcode_exibicao_str = url_qrcode_exibicao(
estado=emit_uf,
ambiente=tp_amb.text)

if tp_emis != 1:
if signature is None:
if cert is not False:
signer = Assinatura(certificado.pfx, certificado.password)
xml_send = signer.assina_xml(xmlElem_send, id)
else:
raise Exception("XML Invalido - Sem assinatura e não "
"foi enviado o certificado nos parametros")
digest_value = xml.find(
".//{http://www.w3.org/2000/09/xmldsig#}DigestValue")
c_hash_qr_code = \
"{ch_acesso}|{versao}|{tp_amb}|{dh_emi}|" \
"{v_nf}|{dig_val}|{id_csc}|{csc}".format(
ch_acesso=chave,
versao=2,
tp_amb=tp_amb.text,
dh_emi=dh_emi,
v_nf=float(v_nf.text),
dig_val=digest_value.text,
id_csc=int(id_csc),
csc=csc
)
c_hash_qr_code = hashlib.sha1(c_hash_qr_code.encode()). \
hexdigest()
qr_code_url = 'p={ch_acesso}|{versao}|{tp_amb}|{dh_emi}|" \
"{v_nf}|{dig_val}|{id_csc}|{hash}'.format(
ch_acesso=chave,
versao=2,
tp_amb=tp_amb.text,
dh_emi=dh_emi,
v_nf=float(v_nf.text),
dig_val=digest_value.text,
id_csc=int(id_csc),
hash=c_hash_qr_code
)
qrcode = url_qrcode_str + qr_code_url
url_consulta = url_qrcode_exibicao_str

qrCode = xml.find(
'.//{http://www.portalfiscal.inf.br/nfe}qrCode').text = \
qrcode
urlChave = xml.find(
'.//{http://www.portalfiscal.inf.br/nfe}urlChave').text = \
url_consulta
else:
c_hash_qr_code = \
"{ch_acesso}|{versao}|{tp_amb}|{id_csc}|{csc}".format(
ch_acesso=chave,
versao=2,
tp_amb=tp_amb.text,
id_csc=int(id_csc),
csc=csc
)
c_hash_qr_code = hashlib.sha1(c_hash_qr_code.encode()).hexdigest()

qr_code_url = "p={ch_acesso}|{versao}|{tp_amb}|{id_csc}|" \
"{hash}".\
format(
ch_acesso=chave,
versao=2,
tp_amb=tp_amb.text,
id_csc=int(id_csc),
hash=c_hash_qr_code
)
qrcode = url_qrcode_str + qr_code_url
url_consulta = url_qrcode_exibicao_str
qrCode = xml.find(
'.//{http://www.portalfiscal.inf.br/nfe}qrCode').text = \
qrcode
urlChave = xml.find(
'.//{http://www.portalfiscal.inf.br/nfe}urlChave').text = \
url_consulta
return etree.tostring(xml)

def _get_session(certificado):
cert, key = extract_cert_and_key_from_pfx(certificado.pfx, certificado.password)
cert, key = save_cert_key(cert, key)
Expand Down
8 changes: 7 additions & 1 deletion pytrustnfe/nfe/assinatura.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
from signxml import XMLSigner


class XMLSignerWithSHA1(XMLSigner):
def check_deprecated_methods(self):
pass


class Assinatura(object):
def __init__(self, arquivo, senha):
self.arquivo = arquivo
Expand All @@ -20,7 +25,7 @@ def assina_xml(self, xml_element, reference, getchildren=False):
if element.text is not None and not element.text.strip():
element.text = None

signer = XMLSigner(
signer = XMLSignerWithSHA1(
method=signxml.methods.enveloped,
signature_algorithm="rsa-sha1",
digest_algorithm="sha1",
Expand All @@ -30,6 +35,7 @@ def assina_xml(self, xml_element, reference, getchildren=False):
ns = {}
ns[None] = signer.namespaces["ds"]
signer.namespaces = ns
signer.excise_empty_xmlns_declarations = True

ref_uri = ("#%s" % reference) if reference else None
signed_root = signer.sign(
Expand Down
6 changes: 3 additions & 3 deletions pytrustnfe/nfse/paulistana/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@


def sign_tag(certificado, **kwargs):
pkcs12 = crypto.load_pkcs12(certificado.pfx, certificado.password)
pkcs12 = crypto.load_pkcs12(certificado.pfx, certificado.password.encode())
key = pkcs12.get_privatekey()
if "nfse" in kwargs:
for item in kwargs["nfse"]["lista_rps"]:
signed = crypto.sign(key, item["assinatura"], "SHA1")
signed = crypto.sign(key, item["assinatura"].encode(), "SHA1")
item["assinatura"] = b64encode(signed).decode()
if "cancelamento" in kwargs:
signed = crypto.sign(key, kwargs["cancelamento"]["assinatura"], "SHA1")
signed = crypto.sign(key, kwargs["cancelamento"]["assinatura"].encode(), "SHA1")
kwargs["cancelamento"]["assinatura"] = b64encode(signed).decode()


Expand Down
3 changes: 1 addition & 2 deletions pytrustnfe/xml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ def recursively_empty(e):

def render_xml(path, template_name, remove_empty, **nfe):
nfe = recursively_normalize(nfe)
env = Environment(loader=FileSystemLoader(
path), extensions=["jinja2.ext.with_"])
env = Environment(loader=FileSystemLoader(path))
env.filters["normalize"] = filters.strip_line_feed
env.filters["normalize_str"] = filters.normalize_str
env.filters["format_percent"] = filters.format_percent
Expand Down
32 changes: 19 additions & 13 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
lxml >= 4.2.1, < 5
coveralls
Jinja2
# Sign xml dependencies
signxml==2.9.0 ; python_version < '3.7'
signxml ; python_version >= '3.7'
urllib3 >= 1.22
lxml >= 4.2.1
cryptography >= 3.4.8
pyOpenSSL >= 22.1.0
certifi >= 2018.1.18

# XmlSec
xmlsec >= 1.3.13

# pytrustnfe dependencies
Jinja2
pytz
zeep
reportlab
urllib3
suds-community
suds-requests4
defusedxml >= 0.7.1, < 1
eight >= 0.3.0, < 1
cryptography >= 2.1.4
pyOpenSSL == 22.1.0
certifi >= 2015.11.20.1
xmlsec >= 1.3.3
reportlab

# Test dependencies
coveralls
pytest>=4.1.1
pytest-cov
pytz
zeep

17 changes: 9 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from setuptools import setup, find_packages


VERSION = "1.0.62"
VERSION = "2.0.0"


setup(
Expand Down Expand Up @@ -50,13 +50,14 @@
long_description=open("README.md", "r").read(),
long_description_content_type="text/markdown",
install_requires=[
'urllib3 >= 1.22',
'xmlsec >= 1.3.3', # apt update;apt install libxmlsec1-dev pkg-config -y
'Jinja2 >= 2.8, <= 3.0.3',
'lxml >= 4.2.1, < 5',
'cryptography >= 2.1.4',
'pyOpenSSL == 22.1.0',
'suds',
'xmlsec >= 1.3.13', # apt update;apt install libxmlsec1-dev pkg-config -y
'lxml >= 4.2.1',
'cryptography >= 3.4.8',
'pyOpenSSL >= 17.5.0',
'certifi >= 2018.1.18',
'urllib3',
'Jinja2',
'suds-community',
'suds-requests4',
'reportlab',
'pytz',
Expand Down
2 changes: 1 addition & 1 deletion tests/test_nfse_paulistana.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# coding=utf-8

import mock
from unittest import mock
import os.path
import unittest
from pytrustnfe.certificado import Certificado
Expand Down

0 comments on commit 2801635

Please sign in to comment.