Compare commits
1 Commits
main
...
feature/py
| Author | SHA1 | Date | |
|---|---|---|---|
| 93a3d18e32 |
20
Dockerfile
20
Dockerfile
@@ -7,34 +7,40 @@ RUN apt install software-properties-common -y \
|
|||||||
&& add-apt-repository ppa:deadsnakes/ppa
|
&& add-apt-repository ppa:deadsnakes/ppa
|
||||||
|
|
||||||
RUN apt-get install -y --no-install-recommends \
|
RUN apt-get install -y --no-install-recommends \
|
||||||
python3.9 python3.9-distutils python3.9-dev \
|
|
||||||
python3.10 python3.10-distutils python3.10-dev \
|
python3.10 python3.10-distutils python3.10-dev \
|
||||||
python3.11 python3.11-distutils python3.11-dev \
|
python3.11 python3.11-distutils python3.11-dev \
|
||||||
python3.12 python3-setuptools python3.12-dev \
|
python3.12 python3-setuptools python3.12-dev \
|
||||||
|
python3.13 python3-setuptools python3.13-dev \
|
||||||
wget \
|
wget \
|
||||||
ca-certificates
|
ca-certificates
|
||||||
|
|
||||||
RUN wget https://bootstrap.pypa.io/get-pip.py \
|
RUN wget https://bootstrap.pypa.io/get-pip.py \
|
||||||
&& python3.9 get-pip.py pip==23.2.1 --break-system-packages \
|
|
||||||
&& python3.10 get-pip.py pip==23.2.1 --break-system-packages \
|
&& python3.10 get-pip.py pip==23.2.1 --break-system-packages \
|
||||||
&& python3.11 get-pip.py pip==23.2.1 --break-system-packages \
|
&& python3.11 get-pip.py pip==23.2.1 --break-system-packages \
|
||||||
&& python3.12 get-pip.py pip==23.2.1 --break-system-packages \
|
&& python3.12 get-pip.py pip==23.2.1 --break-system-packages \
|
||||||
|
&& python3.13 get-pip.py pip==23.2.1 --break-system-packages \
|
||||||
&& rm get-pip.py
|
&& rm get-pip.py
|
||||||
|
|
||||||
RUN apt-get install -y --no-install-recommends \
|
RUN apt-get install -y --no-install-recommends \
|
||||||
libxml2-dev \
|
gcc \
|
||||||
libxmlsec1-dev \
|
build-essential \
|
||||||
build-essential \
|
pkg-config \
|
||||||
|
libxml2-dev \
|
||||||
|
libxmlsec1-dev \
|
||||||
|
xmlsec1 \
|
||||||
|
libxml2-dev \
|
||||||
|
libxslt-dev \
|
||||||
zip
|
zip
|
||||||
|
|
||||||
RUN python3.9 --version
|
|
||||||
RUN python3.10 --version
|
RUN python3.10 --version
|
||||||
RUN python3.11 --version
|
RUN python3.11 --version
|
||||||
RUN python3.12 --version
|
RUN python3.12 --version
|
||||||
|
RUN python3.13 --version
|
||||||
|
|
||||||
|
|
||||||
RUN pip3.9 install setuptools setuptools-rust
|
|
||||||
RUN pip3.10 install setuptools setuptools-rust
|
RUN pip3.10 install setuptools setuptools-rust
|
||||||
RUN pip3.11 install setuptools setuptools-rust --break-system-packages
|
RUN pip3.11 install setuptools setuptools-rust --break-system-packages
|
||||||
RUN pip3.12 install setuptools setuptools-rust --break-system-packages
|
RUN pip3.12 install setuptools setuptools-rust --break-system-packages
|
||||||
|
RUN pip3.13 install setuptools setuptools-rust --break-system-packages
|
||||||
|
|
||||||
RUN pip3 install tox pytest --break-system-packages
|
RUN pip3 install tox pytest --break-system-packages
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ dev-shell:
|
|||||||
docker run --rm -ti -v "$(PWD):/app" -w /app --name facho-cli facho bash
|
docker run --rm -ti -v "$(PWD):/app" -w /app --name facho-cli facho bash
|
||||||
|
|
||||||
test:
|
test:
|
||||||
docker run -t -v $(PWD):/app -w /app facho sh -c 'cd /app; python3.12 setup.py test'
|
docker run -t -v $(PWD):/app -w /app facho sh -c 'cd /app; python3.13 -m pytest'
|
||||||
|
|
||||||
tox:
|
tox:
|
||||||
docker run -it -v $(PWD)/:/app -w /app facho tox
|
docker run -it -v $(PWD)/:/app -w /app facho tox
|
||||||
|
|||||||
@@ -140,12 +140,12 @@ class LXMLBuilder:
|
|||||||
attrs['pretty_print'] = attrs.pop('pretty_print', False)
|
attrs['pretty_print'] = attrs.pop('pretty_print', False)
|
||||||
attrs['encoding'] = attrs.pop('encoding', 'UTF-8')
|
attrs['encoding'] = attrs.pop('encoding', 'UTF-8')
|
||||||
|
|
||||||
for el in elem.getiterator():
|
for el in elem.iter():
|
||||||
keys = filter(lambda key: key.startswith('facho_'), el.keys())
|
keys = filter(lambda key: key.startswith('facho_'), el.keys())
|
||||||
self.remove_attributes(el, keys, exclude=['facho_optional'])
|
self.remove_attributes(el, keys, exclude=['facho_optional'])
|
||||||
|
|
||||||
is_optional = el.get('facho_optional', 'False') == 'True'
|
is_optional = el.get('facho_optional', 'False') == 'True'
|
||||||
if is_optional and el.getchildren() == [] and el.keys() == [
|
if is_optional and list(el) == [] and el.keys() == [
|
||||||
'facho_optional']:
|
'facho_optional']:
|
||||||
el.getparent().remove(el)
|
el.getparent().remove(el)
|
||||||
|
|
||||||
@@ -291,7 +291,7 @@ class FachoXML:
|
|||||||
# se fuerza la adicion como un nuevo elemento
|
# se fuerza la adicion como un nuevo elemento
|
||||||
if append:
|
if append:
|
||||||
last_slibing = None
|
last_slibing = None
|
||||||
for child in parent.getchildren():
|
for child in list(parent):
|
||||||
if child.tag == node_tag:
|
if child.tag == node_tag:
|
||||||
last_slibing = child
|
last_slibing = child
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import xmlsec
|
|||||||
import urllib.request
|
import urllib.request
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from dataclasses import dataclass, asdict, field
|
from dataclasses import dataclass, asdict, field
|
||||||
from typing import List
|
|
||||||
import http.client
|
import http.client
|
||||||
import hashlib
|
import hashlib
|
||||||
import secrets
|
import secrets
|
||||||
@@ -47,7 +47,7 @@ class GetNumberingRangeResponse:
|
|||||||
ValidateDateTo: str
|
ValidateDateTo: str
|
||||||
TechnicalKey: str
|
TechnicalKey: str
|
||||||
|
|
||||||
NumberRangeResponse: List[NumberRangeResponse]
|
NumberRangeResponse: list[NumberRangeResponse]
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -91,7 +91,7 @@ class SendBillAsync(SOAPService):
|
|||||||
@dataclass
|
@dataclass
|
||||||
class SendTestSetAsyncResponse:
|
class SendTestSetAsyncResponse:
|
||||||
ZipKey: str
|
ZipKey: str
|
||||||
ErrorMessageList: List[str]
|
ErrorMessageList: list[str]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fromdict(cls, data):
|
def fromdict(cls, data):
|
||||||
@@ -134,7 +134,7 @@ class GetStatusResponse:
|
|||||||
IsValid: bool
|
IsValid: bool
|
||||||
StatusDescription: str
|
StatusDescription: str
|
||||||
StatusCode: int
|
StatusCode: int
|
||||||
ErrorMessage: List[str]
|
ErrorMessage: list[str]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fromdict(cls, data):
|
def fromdict(cls, data):
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ module.
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
import pytz
|
import pytz
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, timezone
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from lxml.etree import QName
|
from lxml.etree import QName
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ def sign_envelope(
|
|||||||
return _sign_envelope_with_key(envelope, key, signature_method, digest_method)
|
return _sign_envelope_with_key(envelope, key, signature_method, digest_method)
|
||||||
|
|
||||||
def get_timestamp(timestamp = None, delta=None):
|
def get_timestamp(timestamp = None, delta=None):
|
||||||
timestamp = timestamp or datetime.utcnow()
|
timestamp = timestamp or datetime.now(timezone.utc)
|
||||||
if delta:
|
if delta:
|
||||||
timestamp += delta
|
timestamp += delta
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ class CodeList:
|
|||||||
row = {}
|
row = {}
|
||||||
|
|
||||||
#construir registro...
|
#construir registro...
|
||||||
for value in xmlrow.getchildren():
|
for value in list(xmlrow):
|
||||||
row[value.attrib['ColumnRef']] = value.getchildren()[0].text
|
row[value.attrib['ColumnRef']] = list(value)[0].text
|
||||||
|
|
||||||
return row
|
return row
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import uuid
|
|||||||
import xmlsig
|
import xmlsig
|
||||||
import xades
|
import xades
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import OpenSSL
|
|
||||||
import zipfile
|
import zipfile
|
||||||
# import warnings
|
# import warnings
|
||||||
import hashlib
|
import hashlib
|
||||||
@@ -18,6 +17,21 @@ from dateutil import tz
|
|||||||
|
|
||||||
from cryptography.hazmat.primitives.serialization import pkcs12
|
from cryptography.hazmat.primitives.serialization import pkcs12
|
||||||
|
|
||||||
|
# Monkey-patch xades/xmlsig para compatibilidad con pyOpenSSL >= 24
|
||||||
|
# (PKCS12 fue eliminado de OpenSSL.crypto, pero ambas librerías lo referencian)
|
||||||
|
import OpenSSL
|
||||||
|
import xades.xades_context
|
||||||
|
|
||||||
|
if not hasattr(OpenSSL.crypto, 'PKCS12'):
|
||||||
|
def _patched_load_pkcs12(self, key):
|
||||||
|
if isinstance(key, tuple):
|
||||||
|
self.x509 = key[1]
|
||||||
|
self.public_key = key[1].public_key()
|
||||||
|
self.private_key = key[0]
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("unsupported key type")
|
||||||
|
xades.xades_context.XAdESContext.load_pkcs12 = _patched_load_pkcs12
|
||||||
|
|
||||||
AMBIENTE_PRUEBAS = codelist.TipoAmbiente.by_name('Pruebas')['code']
|
AMBIENTE_PRUEBAS = codelist.TipoAmbiente.by_name('Pruebas')['code']
|
||||||
AMBIENTE_PRODUCCION = codelist.TipoAmbiente.by_name('Producción')['code']
|
AMBIENTE_PRODUCCION = codelist.TipoAmbiente.by_name('Producción')['code']
|
||||||
|
|
||||||
@@ -444,9 +458,6 @@ class DianXMLExtensionSigner:
|
|||||||
self._pkcs12_data,
|
self._pkcs12_data,
|
||||||
self._passphrase))
|
self._passphrase))
|
||||||
|
|
||||||
# ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(
|
|
||||||
# self._pkcs12_data,
|
|
||||||
# self._passphrase))
|
|
||||||
if self._localpolicy:
|
if self._localpolicy:
|
||||||
with mock_xades_policy():
|
with mock_xades_policy():
|
||||||
ctx.sign(signature)
|
ctx.sign(signature)
|
||||||
@@ -590,8 +601,8 @@ class DianXMLExtensionSignerVerifier:
|
|||||||
if isinstance(self._pkcs12_path_or_bytes, str):
|
if isinstance(self._pkcs12_path_or_bytes, str):
|
||||||
pkcs12_data = open(self._pkcs12_path_or_bytes, 'rb').read()
|
pkcs12_data = open(self._pkcs12_path_or_bytes, 'rb').read()
|
||||||
ctx = xades.XAdESContext()
|
ctx = xades.XAdESContext()
|
||||||
ctx.load_pkcs12(OpenSSL.crypto.load_pkcs12(pkcs12_data,
|
ctx.load_pkcs12(pkcs12.load_key_and_certificates(
|
||||||
self._passphrase))
|
pkcs12_data, self._passphrase))
|
||||||
try:
|
try:
|
||||||
if self._localpolicy:
|
if self._localpolicy:
|
||||||
with mock_xades_policy():
|
with mock_xades_policy():
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ from datetime import datetime, date
|
|||||||
# from collections import defaultdict
|
# from collections import defaultdict
|
||||||
import decimal
|
import decimal
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
import typing
|
|
||||||
from ..data.dian import codelist
|
from ..data.dian import codelist
|
||||||
|
|
||||||
DECIMAL_PRECISION = 6
|
DECIMAL_PRECISION = 6
|
||||||
@@ -60,7 +59,7 @@ class AmountCollection(Collection):
|
|||||||
|
|
||||||
class Amount:
|
class Amount:
|
||||||
def __init__(
|
def __init__(
|
||||||
self, amount: typing.Union[int, float, str, "Amount"],
|
self, amount: int | float | str | "Amount",
|
||||||
currency: Currency = Currency('COP')):
|
currency: Currency = Currency('COP')):
|
||||||
|
|
||||||
# DIAN 1.7.-2020: 1.2.3.1
|
# DIAN 1.7.-2020: 1.2.3.1
|
||||||
@@ -294,7 +293,7 @@ class TaxScheme:
|
|||||||
class Party:
|
class Party:
|
||||||
name: str
|
name: str
|
||||||
ident: str
|
ident: str
|
||||||
responsability_code: typing.List[Responsability]
|
responsability_code: list[Responsability]
|
||||||
responsability_regime_code: str
|
responsability_regime_code: str
|
||||||
organization_code: str
|
organization_code: str
|
||||||
tax_scheme: TaxScheme = field(default_factory=lambda: TaxScheme('01'))
|
tax_scheme: TaxScheme = field(default_factory=lambda: TaxScheme('01'))
|
||||||
@@ -327,7 +326,7 @@ class TaxScheme:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class TaxSubTotal:
|
class TaxSubTotal:
|
||||||
percent: float
|
percent: float
|
||||||
scheme: typing.Optional[TaxScheme] = None
|
scheme: TaxScheme | None = None
|
||||||
tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
|
|
||||||
def calculate(self, invline):
|
def calculate(self, invline):
|
||||||
@@ -359,7 +358,7 @@ class TaxTotalOmit(TaxTotal):
|
|||||||
@dataclass
|
@dataclass
|
||||||
class WithholdingTaxSubTotal:
|
class WithholdingTaxSubTotal:
|
||||||
percent: float
|
percent: float
|
||||||
scheme: typing.Optional[TaxScheme] = None
|
scheme: TaxScheme | None = None
|
||||||
tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
tax_amount: Amount = field(default_factory=lambda: Amount(0.0))
|
||||||
|
|
||||||
def calculate(self, invline):
|
def calculate(self, invline):
|
||||||
@@ -491,7 +490,7 @@ class AllowanceCharge:
|
|||||||
reason: AllowanceChargeReason = None
|
reason: AllowanceChargeReason = None
|
||||||
|
|
||||||
# Valor Base para calcular el descuento o el cargo
|
# Valor Base para calcular el descuento o el cargo
|
||||||
base_amount: typing.Optional[Amount] = field(
|
base_amount: Amount | None = field(
|
||||||
default_factory=lambda: Amount(0.0))
|
default_factory=lambda: Amount(0.0))
|
||||||
|
|
||||||
# Porcentaje: Porcentaje que aplicar.
|
# Porcentaje: Porcentaje que aplicar.
|
||||||
@@ -536,9 +535,9 @@ class InvoiceLine:
|
|||||||
# ya que al reportar los totales es sobre
|
# ya que al reportar los totales es sobre
|
||||||
# la factura y el percent es unico por type_code
|
# la factura y el percent es unico por type_code
|
||||||
# de subtotal
|
# de subtotal
|
||||||
tax: typing.Optional[TaxTotal]
|
tax: TaxTotal | None
|
||||||
withholding: typing.Optional[WithholdingTaxTotal]
|
withholding: WithholdingTaxTotal | None
|
||||||
allowance_charge: typing.List[AllowanceCharge] = dataclasses.field(
|
allowance_charge: list[AllowanceCharge] = dataclasses.field(
|
||||||
default_factory=list)
|
default_factory=list)
|
||||||
|
|
||||||
def add_allowance_charge(self, charge):
|
def add_allowance_charge(self, charge):
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
import typing
|
|
||||||
|
|
||||||
from .. import fe
|
from .. import fe
|
||||||
from .. import form
|
from .. import form
|
||||||
@@ -86,13 +86,13 @@ class NumeroSecuencia:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Periodo:
|
class Periodo:
|
||||||
fecha_ingreso: typing.Union[str, Fecha]
|
fecha_ingreso: str | Fecha
|
||||||
fecha_liquidacion_inicio: typing.Union[str, Fecha]
|
fecha_liquidacion_inicio: str | Fecha
|
||||||
fecha_liquidacion_fin: typing.Union[str, Fecha]
|
fecha_liquidacion_fin: str | Fecha
|
||||||
fecha_generacion: typing.Union[str, Fecha]
|
fecha_generacion: str | Fecha
|
||||||
|
|
||||||
tiempo_laborado: int = 1
|
tiempo_laborado: int = 1
|
||||||
fecha_retiro: typing.Union[str, Fecha] = None
|
fecha_retiro: str | Fecha | None = None
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
self.fecha_ingreso = Fecha.cast(self.fecha_ingreso)
|
self.fecha_ingreso = Fecha.cast(self.fecha_ingreso)
|
||||||
@@ -259,7 +259,7 @@ class InformacionGeneral:
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
self.valor
|
self.valor
|
||||||
|
|
||||||
fecha_generacion: typing.Union[str, Fecha]
|
fecha_generacion: str | Fecha
|
||||||
hora_generacion: str
|
hora_generacion: str
|
||||||
periodo_nomina: PeriodoNomina
|
periodo_nomina: PeriodoNomina
|
||||||
tipo_moneda: TipoMoneda
|
tipo_moneda: TipoMoneda
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from ..amount import Amount
|
from ..amount import Amount
|
||||||
from .devengado import Devengado
|
from .devengado import Devengado
|
||||||
@@ -30,7 +30,7 @@ class DevengadoHoraExtra:
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DevengadoHorasExtrasDiarias(Devengado):
|
class DevengadoHorasExtrasDiarias(Devengado):
|
||||||
horas_extras: List[DevengadoHoraExtra]
|
horas_extras: list[DevengadoHoraExtra]
|
||||||
|
|
||||||
def apply(self, fragment):
|
def apply(self, fragment):
|
||||||
hora_extra_xml = fragment.fragment('./HEDs')
|
hora_extra_xml = fragment.fragment('./HEDs')
|
||||||
@@ -39,7 +39,7 @@ class DevengadoHorasExtrasDiarias(Devengado):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DevengadoHorasExtrasNocturnas(Devengado):
|
class DevengadoHorasExtrasNocturnas(Devengado):
|
||||||
horas_extras: List[DevengadoHoraExtra]
|
horas_extras: list[DevengadoHoraExtra]
|
||||||
|
|
||||||
def apply(self, fragment):
|
def apply(self, fragment):
|
||||||
hora_extra_xml = fragment.fragment('./HENs')
|
hora_extra_xml = fragment.fragment('./HENs')
|
||||||
@@ -49,7 +49,7 @@ class DevengadoHorasExtrasNocturnas(Devengado):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DevengadoHorasRecargoNocturno(Devengado):
|
class DevengadoHorasRecargoNocturno(Devengado):
|
||||||
horas_extras: List[DevengadoHoraExtra]
|
horas_extras: list[DevengadoHoraExtra]
|
||||||
|
|
||||||
def apply(self, fragment):
|
def apply(self, fragment):
|
||||||
hora_extra_xml = fragment.fragment('./HRNs')
|
hora_extra_xml = fragment.fragment('./HRNs')
|
||||||
@@ -58,7 +58,7 @@ class DevengadoHorasRecargoNocturno(Devengado):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DevengadoHorasExtrasDiariasDominicalesYFestivos(Devengado):
|
class DevengadoHorasExtrasDiariasDominicalesYFestivos(Devengado):
|
||||||
horas_extras: List[DevengadoHoraExtra]
|
horas_extras: list[DevengadoHoraExtra]
|
||||||
|
|
||||||
def apply(self, fragment):
|
def apply(self, fragment):
|
||||||
hora_extra_xml = fragment.fragment('./HEDDFs')
|
hora_extra_xml = fragment.fragment('./HEDDFs')
|
||||||
@@ -67,7 +67,7 @@ class DevengadoHorasExtrasDiariasDominicalesYFestivos(Devengado):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DevengadoHorasRecargoDiariasDominicalesYFestivos(Devengado):
|
class DevengadoHorasRecargoDiariasDominicalesYFestivos(Devengado):
|
||||||
horas_extras: List[DevengadoHoraExtra]
|
horas_extras: list[DevengadoHoraExtra]
|
||||||
|
|
||||||
def apply(self, fragment):
|
def apply(self, fragment):
|
||||||
hora_extra_xml = fragment.fragment('./HRDDFs')
|
hora_extra_xml = fragment.fragment('./HRDDFs')
|
||||||
@@ -76,7 +76,7 @@ class DevengadoHorasRecargoDiariasDominicalesYFestivos(Devengado):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DevengadoHorasExtrasNocturnasDominicalesYFestivos(Devengado):
|
class DevengadoHorasExtrasNocturnasDominicalesYFestivos(Devengado):
|
||||||
horas_extras: List[DevengadoHoraExtra]
|
horas_extras: list[DevengadoHoraExtra]
|
||||||
|
|
||||||
def apply(self, fragment):
|
def apply(self, fragment):
|
||||||
hora_extra_xml = fragment.fragment('./HENDFs')
|
hora_extra_xml = fragment.fragment('./HENDFs')
|
||||||
@@ -85,7 +85,7 @@ class DevengadoHorasExtrasNocturnasDominicalesYFestivos(Devengado):
|
|||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class DevengadoHorasRecargoNocturnoDominicalesYFestivos(Devengado):
|
class DevengadoHorasRecargoNocturnoDominicalesYFestivos(Devengado):
|
||||||
horas_extras: List[DevengadoHoraExtra]
|
horas_extras: list[DevengadoHoraExtra]
|
||||||
|
|
||||||
def apply(self, fragment):
|
def apply(self, fragment):
|
||||||
hora_extra_xml = fragment.fragment('./HRNDFs')
|
hora_extra_xml = fragment.fragment('./HRNDFs')
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
attrs==22.1.0
|
attrs==24.2.0
|
||||||
distlib==0.3.6
|
distlib==0.3.9
|
||||||
filelock==3.8.0
|
filelock==3.16.1
|
||||||
iniconfig==1.1.1
|
iniconfig==2.0.0
|
||||||
packaging==21.3
|
packaging==24.1
|
||||||
platformdirs==2.5.2
|
platformdirs==4.3.6
|
||||||
pluggy==1.0.0
|
pluggy==1.5.0
|
||||||
py==1.11.0
|
pyparsing==3.2.0
|
||||||
pyparsing==3.0.9
|
pytest==8.3.4
|
||||||
pytest==7.1.3
|
|
||||||
semantic-version==2.10.0
|
semantic-version==2.10.0
|
||||||
setuptools-rust==1.5.2
|
setuptools-rust==1.10.2
|
||||||
six==1.16.0
|
six==1.16.0
|
||||||
tomli==2.0.1
|
tomli==2.2.1
|
||||||
tox==3.26.0
|
tox==4.23.2
|
||||||
typing_extensions==4.4.0
|
virtualenv==20.28.0
|
||||||
virtualenv==20.16.5
|
|
||||||
|
|||||||
18
setup.py
18
setup.py
@@ -14,14 +14,14 @@ with open('HISTORY.rst') as history_file:
|
|||||||
history = history_file.read()
|
history = history_file.read()
|
||||||
|
|
||||||
requirements = ['Click>=8.1.7',
|
requirements = ['Click>=8.1.7',
|
||||||
'zeep==4.2.1',
|
'zeep>=4.2.1',
|
||||||
'lxml==5.2.2',
|
'lxml>=5.2.2',
|
||||||
'cryptography==3.3.2',
|
'cryptography>=41.0.0',
|
||||||
'pyOpenSSL==20.0.1',
|
'pyOpenSSL>=23.2.0',
|
||||||
'xmlsig==0.1.7',
|
'xmlsig>=0.1.9',
|
||||||
'xades==1.0.0',
|
'xades>=1.0.0',
|
||||||
'xmlsec==1.3.14',
|
'xmlsec>=1.3.12',
|
||||||
'python-dateutil==2.9.0.post0',
|
'python-dateutil>=2.9.0',
|
||||||
# usamos esta dependencia en runtime
|
# usamos esta dependencia en runtime
|
||||||
# para forzar uso de policy_id de archivo local
|
# para forzar uso de policy_id de archivo local
|
||||||
'mock>=5.1.0',
|
'mock>=5.1.0',
|
||||||
@@ -57,10 +57,10 @@ setup(
|
|||||||
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
|
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
|
||||||
'Natural Language :: English',
|
'Natural Language :: English',
|
||||||
'Programming Language :: Python :: 3',
|
'Programming Language :: Python :: 3',
|
||||||
'Programming Language :: Python :: 3.9',
|
|
||||||
'Programming Language :: Python :: 3.10',
|
'Programming Language :: Python :: 3.10',
|
||||||
'Programming Language :: Python :: 3.11',
|
'Programming Language :: Python :: 3.11',
|
||||||
'Programming Language :: Python :: 3.12',
|
'Programming Language :: Python :: 3.12',
|
||||||
|
'Programming Language :: Python :: 3.13',
|
||||||
],
|
],
|
||||||
description="Facturacion Electronica Colombia",
|
description="Facturacion Electronica Colombia",
|
||||||
entry_points={
|
entry_points={
|
||||||
|
|||||||
3
tox.ini
3
tox.ini
@@ -1,5 +1,5 @@
|
|||||||
[tox]
|
[tox]
|
||||||
envlist = py39, py310, py311, py312, flake8
|
envlist = py39, py310, py311, py312, py313, flake8
|
||||||
|
|
||||||
[travis]
|
[travis]
|
||||||
python =
|
python =
|
||||||
@@ -7,6 +7,7 @@ python =
|
|||||||
3.10: py310
|
3.10: py310
|
||||||
3.11: py311
|
3.11: py311
|
||||||
3.12: py312
|
3.12: py312
|
||||||
|
3.13: py313
|
||||||
|
|
||||||
[testenv:flake8]
|
[testenv:flake8]
|
||||||
basepython = python
|
basepython = python
|
||||||
|
|||||||
Reference in New Issue
Block a user