Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deploy release v0.35.0 #709

Merged
merged 10 commits into from
Sep 27, 2024
Merged
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.34.0
current_version = 0.35.0
commit = True
tag = False
message = chore: Bump version from {current_version} to {new_version}
Expand Down
42 changes: 42 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Configuration for Ignoring Revisions in Git Blame
#
# This file contains a list of revisions that are not helpful when assigning blame, such as source
# code reformatting, Python `import` sorting, etc., so that `git blame` is able to ignore those
# commits.
#
# > Ignore changes made by the revision when assigning blame, as if the change never happened.
# > Lines that were changed or added by an ignored commit will be blamed on the previous commit
# > that changed that line or nearby lines.
#
# Documentation:
# - https://git-scm.com/docs/git-blame#Documentation/git-blame.txt---ignore-revs-fileltfilegt
# - https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignore-commits-in-the-blame-view
#
# Using this file with Git Blame:
# - GitHub automatically uses this configuration file.
# - To use locally, run `git config blame.ignoreRevsFile .git-blame-ignore-revs`.

# Sort Python imports with Isort
33443511137a819050116358d46484a02e1b1157
2e839bce77b2a497789cd8db0603b59b34dc2a24
3e65ad14b0f2e35b6b817be668685682b15594a2

# Reformat source code using 'Black'
30c98966eb67bb7155085a0801590d4de5ee27d4
fdad3571586afb8dc94f280572d315434b52b11c
c3453173311d98eb8db9f35067a62bc8a6e296d1
b5d75137c6c3cffbbc12455f02306134871ca7e8
df26fa3d114fe063d3809b75931b78b9472adc98
e4a165f408c9d6a78bc929f379fd5adb5435f824
d9f7e31f8f9a13e739859d0282e36591cec10ec6
a98bf81dfef2ddd0a7d72a3b329aee214a020894
8429acfe04f0cb88ea528d5c580d397db269fab4
84c1be060c364c7316b1705ef41283b17f1061dc
c5040e9878dbf62cceb6262a1aa27df72d0c0752
da84feb45852860f549bb982d8f5371e3f5dffa3

# Reformat source code
605f6fe7c228401492177c93d5c661a9d2c03c8d

# Move files without changing them
347201cc5442962a0bd764df28bd4709e5b3fcd6
6 changes: 6 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# History

## 0.35.0 (2024-09-26)

- (PR #706, 2024-09-26) Improvements and fixes related to validation of trusted inputs
- (PR #582, 2024-09-26) Add configuration for ignoring revisions in Git Blame
- (PR #707, 2024-09-26) Make file `setup.py` executable again

## 0.34.0 (2024-09-26)

- (PR #690, 2024-09-25) chore(deps): Bump lxml from 5.2.2 to 5.3.0
Expand Down
Empty file modified setup.py
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion src/cl_sii/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@

"""

__version__ = '0.34.0'
__version__ = '0.35.0'
3 changes: 3 additions & 0 deletions src/cl_sii/dte/data_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -918,3 +918,6 @@ def validate_referencias_codigo_ref_is_consistent_with_tipo_dte(self) -> DteXmlD
)

return self


DTE_XML_DATA_PYDANTIC_TYPE_ADAPTER = pydantic.TypeAdapter(DteXmlData)
51 changes: 33 additions & 18 deletions src/cl_sii/dte/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,24 @@ def validate_dte_xml(xml_doc: XmlElement) -> None:
xml_utils.validate_xml_doc(DTE_XML_SCHEMA_OBJ, xml_doc)


def parse_dte_xml(xml_doc: XmlElement) -> data_models.DteXmlData:
def parse_dte_xml(xml_doc: XmlElement, trust_input: bool = False) -> data_models.DteXmlData:
"""
Parse data from a DTE XML doc.

.. warning::
It is assumed that ``xml_doc`` is an
``{http://www.sii.cl/SiiDte}/DTE`` XML element.

:param xml_doc:
DTE XML document.
:param trust_input:
If ``True``, the input data is trusted to be valid and
some validation errors are replaced by warnings.

.. warning::
Use this option *only* if the DTE XML document was obtained directly
from the SII *and* you need to work around some validation errors
that the SII should have caught, but let through.
:raises ValueError:
:raises TypeError:
:raises NotImplementedError:
Expand Down Expand Up @@ -511,23 +521,28 @@ def parse_dte_xml(xml_doc: XmlElement) -> data_models.DteXmlData:
_text_strip_or_raise(signature_key_info_x509_cert_em)
)

return data_models.DteXmlData(
emisor_rut=emisor_rut_value,
tipo_dte=tipo_dte_value,
folio=folio_value,
fecha_emision_date=fecha_emision_value,
receptor_rut=receptor_rut_value,
monto_total=monto_total_value,
emisor_razon_social=emisor_razon_social_value,
receptor_razon_social=receptor_razon_social_value,
fecha_vencimiento_date=fecha_vencimiento_value,
firma_documento_dt=tmst_firma_value,
signature_value=signature_signature_value,
signature_x509_cert_der=signature_key_info_x509_cert_der,
emisor_giro=emisor_giro_value,
emisor_email=emisor_email_value,
receptor_email=receptor_email_value,
referencias=referencia_xml_list,
return data_models.DTE_XML_DATA_PYDANTIC_TYPE_ADAPTER.validate_python(
dict(
emisor_rut=emisor_rut_value,
tipo_dte=tipo_dte_value,
folio=folio_value,
fecha_emision_date=fecha_emision_value,
receptor_rut=receptor_rut_value,
monto_total=monto_total_value,
emisor_razon_social=emisor_razon_social_value,
receptor_razon_social=receptor_razon_social_value,
fecha_vencimiento_date=fecha_vencimiento_value,
firma_documento_dt=tmst_firma_value,
signature_value=signature_signature_value,
signature_x509_cert_der=signature_key_info_x509_cert_der,
emisor_giro=emisor_giro_value,
emisor_email=emisor_email_value,
receptor_email=receptor_email_value,
referencias=referencia_xml_list,
),
context={
data_models.VALIDATION_CONTEXT_TRUST_INPUT: trust_input,
},
)


Expand Down
3 changes: 3 additions & 0 deletions src/cl_sii/rtc/data_models_aec.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,3 +798,6 @@ def validate_signature_value_and_signature_x509_cert_der_may_only_be_none_togeth
)

return self


AEC_XML_PYDANTIC_TYPE_ADAPTER = pydantic.TypeAdapter(AecXml)
38 changes: 22 additions & 16 deletions src/cl_sii/rtc/parse_aec.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import cl_sii.dte.data_models
import cl_sii.dte.parse
from cl_sii.dte.constants import TipoDte
from cl_sii.dte.data_models import DteXmlData
from cl_sii.dte.data_models import DteXmlData, is_input_trusted_according_to_validation_context
from cl_sii.dte.parse import DTE_XMLNS_MAP
from cl_sii.libs import encoding_utils, tz_utils, xml_utils
from cl_sii.libs.xml_utils import XmlElement
Expand Down Expand Up @@ -88,7 +88,7 @@ def parse_aec_xml(xml_doc: XmlElement, trust_input: bool = False) -> data_models
that the SII should have caught, but let through.
"""
aec_struct = _Aec.parse_xml(xml_doc, trust_input=trust_input)
return aec_struct.as_aec_xml()
return aec_struct.as_aec_xml(trust_input=trust_input)


###############################################################################
Expand Down Expand Up @@ -656,10 +656,11 @@ def parse_xml_to_dict(xml_em: XmlElement) -> Mapping[str, object]:

@pydantic.field_validator('dte', mode='before')
@classmethod
def validate_dte(cls, v: object) -> object:
def validate_dte(cls, v: object, info: pydantic.ValidationInfo) -> object:
if isinstance(v, XmlElement):
cl_sii.dte.parse.validate_dte_xml(v)
v = cl_sii.dte.parse.parse_dte_xml(v)
trust_dte = is_input_trusted_according_to_validation_context(info.context)
v = cl_sii.dte.parse.parse_dte_xml(v, trust_input=trust_dte)
return v

# @pydantic.validator('tmst_firma')
Expand Down Expand Up @@ -909,7 +910,7 @@ def parse_xml(cls, xml_doc: XmlElement, trust_input: bool = False) -> _Aec:
},
)

def as_aec_xml(self) -> data_models_aec.AecXml:
def as_aec_xml(self, trust_input: bool = False) -> data_models_aec.AecXml:
doc_aec_struct = self.documento_aec
signature_over_doc_aec_struct = self.signature

Expand All @@ -922,17 +923,22 @@ def as_aec_xml(self) -> data_models_aec.AecXml:
cesion_struct.as_cesion_aec_xml() for cesion_struct in cesion_struct_list
]

return data_models_aec.AecXml(
dte=dte,
cedente_rut=caratula_struct.rut_cedente,
cesionario_rut=caratula_struct.rut_cesionario,
fecha_firma_dt=caratula_struct.tmst_firmaenvio,
signature_value=signature_over_doc_aec_struct.signature_value,
signature_x509_cert_der=signature_over_doc_aec_struct.key_info_x509_data_x509_cert,
cesiones=aec_xml_cesion_list,
contacto_nombre=caratula_struct.nmb_contacto,
contacto_telefono=caratula_struct.fono_contacto,
contacto_email=caratula_struct.mail_contacto,
return data_models_aec.AEC_XML_PYDANTIC_TYPE_ADAPTER.validate_python(
dict(
dte=dte,
cedente_rut=caratula_struct.rut_cedente,
cesionario_rut=caratula_struct.rut_cesionario,
fecha_firma_dt=caratula_struct.tmst_firmaenvio,
signature_value=signature_over_doc_aec_struct.signature_value,
signature_x509_cert_der=signature_over_doc_aec_struct.key_info_x509_data_x509_cert,
cesiones=aec_xml_cesion_list,
contacto_nombre=caratula_struct.nmb_contacto,
contacto_telefono=caratula_struct.fono_contacto,
contacto_email=caratula_struct.mail_contacto,
),
context={
cl_sii.dte.data_models.VALIDATION_CONTEXT_TRUST_INPUT: trust_input,
},
)

@staticmethod
Expand Down
11 changes: 5 additions & 6 deletions src/tests/test_dte_data_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
TipoDte,
)
from cl_sii.dte.data_models import ( # noqa: F401
DTE_XML_DATA_PYDANTIC_TYPE_ADAPTER,
VALIDATION_CONTEXT_TRUST_INPUT,
DteDataL0,
DteDataL1,
Expand Down Expand Up @@ -1062,8 +1063,6 @@ def setUpClass(cls) -> None:
'test_data/sii-crypto/DTE--96670340-7--61--110616-cert.der'
)

cls.dte_xml_data_pydantic_type_adapter = pydantic.TypeAdapter(DteXmlData)

def setUp(self) -> None:
super().setUp()

Expand Down Expand Up @@ -1788,7 +1787,7 @@ def test_validate_referencias_rut_otro_is_consistent_with_tipo_dte_for_trusted_i
)

invalid_but_trusted_obj: Mapping[str, object] = {
**self.dte_xml_data_pydantic_type_adapter.dump_python(obj),
**DTE_XML_DATA_PYDANTIC_TYPE_ADAPTER.dump_python(obj),
**dict(
referencias=[obj_referencia],
),
Expand All @@ -1797,7 +1796,7 @@ def test_validate_referencias_rut_otro_is_consistent_with_tipo_dte_for_trusted_i

try:
with self.assertLogs('cl_sii.dte.data_models', level='WARNING') as assert_logs_cm:
self.dte_xml_data_pydantic_type_adapter.validate_python(
DTE_XML_DATA_PYDANTIC_TYPE_ADAPTER.validate_python(
invalid_but_trusted_obj, context=validation_context
)
except pydantic.ValidationError as exc:
Expand Down Expand Up @@ -1876,7 +1875,7 @@ def test_validate_referencias_rut_otro_is_consistent_with_emisor_rut_for_trusted
)

invalid_but_trusted_obj: Mapping[str, object] = {
**self.dte_xml_data_pydantic_type_adapter.dump_python(obj),
**DTE_XML_DATA_PYDANTIC_TYPE_ADAPTER.dump_python(obj),
**dict(
referencias=[obj_referencia],
),
Expand All @@ -1885,7 +1884,7 @@ def test_validate_referencias_rut_otro_is_consistent_with_emisor_rut_for_trusted

try:
with self.assertLogs('cl_sii.dte.data_models', level='WARNING') as assert_logs_cm:
self.dte_xml_data_pydantic_type_adapter.validate_python(
DTE_XML_DATA_PYDANTIC_TYPE_ADAPTER.validate_python(
invalid_but_trusted_obj, context=validation_context
)
except pydantic.ValidationError as exc:
Expand Down