Skip to content

Commit

Permalink
Merge pull request #68 from dapper91/doc-fix
Browse files Browse the repository at this point in the history
- None type encoding paragraph added.
  • Loading branch information
dapper91 committed Jun 23, 2023
2 parents 2dc6ff1 + c11b1ea commit b442b17
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 17 deletions.
19 changes: 10 additions & 9 deletions docs/source/pages/data-binding/elements.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@ A model supports several element search strategies (modes). Each strategy has it
Strict (default)
................

An element to which a field will be bound is searched sequentially one by one (without skipping unknown elements).
The element to which a field will be bound is searched sequentially one by one (without skipping unknown elements).
If the tag of a next element doesn't match the field tag that field is considered unbound.
This mode is used when strong document validation is required. If you parse a very large document it is the best
This mode is used when strong document validation is required. If you parse a large document it is the best
choice because it works in predictable time since it doesn't require any look-ahead operations.

.. grid:: 2
Expand Down Expand Up @@ -237,9 +237,9 @@ choice because it works in predictable time since it doesn't require any look-ah
Ordered
.......

An element to which a field will be bound is searched sequentially skipping unknown elements.
The element to which a field will be bound is searched sequentially skipping unknown elements.
If the tag of a next element doesn't match the field tag that element is skipped and the search continues.
This mode is used when element order matters but unexpected (or irrelevant) elements could appear in a document.
This mode is used when the elements order matters but unexpected (or irrelevant) elements could appear in a document.

.. grid:: 2
:gutter: 2
Expand Down Expand Up @@ -276,7 +276,7 @@ This mode is used when element order matters but unexpected (or irrelevant) elem

.. code-block:: python
class Model(BaseXmlModel):
class Model(BaseXmlModel, search_mode='ordered'):
field1: Optional[str] = element(tag='element1')
field2: str = element(tag='element2')
field3: str = element(tag='element1')
Expand All @@ -297,10 +297,11 @@ This mode is used when element order matters but unexpected (or irrelevant) elem
Unordered
.........

An element to which a field will be bound is searched in random order.
This mode is used when element order doesn't matter.
The time complexity of this strategy is worst case is
``O(F*E)`` where ``F`` - is the number of fields, ``E`` - the number of sub-elements.
The element to which a field will be bound is searched among all sub-elements in any order.
This mode is used when the elements order doesn't matter.
The time complexity of this strategy in worst case is
``O(F*E)`` where ``F`` - is the number of fields, ``E`` - the number of sub-elements so that it is not suitable
for large documents.

.. grid:: 2
:gutter: 2
Expand Down
53 changes: 51 additions & 2 deletions docs/source/pages/misc.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
.. _misc:


Encoding
~~~~~~~~


Custom type encoding
~~~~~~~~~~~~~~~~~~~~
____________________

``pydantic-xml`` uses ``pydantic`` default encoder to encode fields data during xml serialization. To alter the default
behaviour ``pydantic`` provides a mechanism to `customize <https://docs.pydantic.dev/usage/exporting_models/#json_encoders>`_
Expand All @@ -11,7 +15,7 @@ The api is similar to the json one:

.. code-block:: python
class Model:
class Model(BaseXmlModel):
class Config:
xml_encoders = {
bytes: base64.b64encode,
Expand Down Expand Up @@ -40,6 +44,51 @@ The following example illustrate how to encode :py:class:`bytes` typed fields as
:language: xml


None type encoding
__________________

Since xml format doesn't support ``null`` type natively it is not obvious how to encode ``None`` fields
(ignore it, encode it as an empty string or mark it as ``xsi:nil``) the library doesn't implement
``None`` type encoding by default.

You can define your own encoding format for the model:

.. code-block:: python
from typing import Optional
from pydantic_xml import BaseXmlModel, element
class Company(BaseXmlModel):
class Config:
xml_encoders = {
type(None): lambda o: '', # encodes None field as an empty string
}
title: Optional[str] = element()
company = Company()
assert company.to_xml() == b'<Company><title /></Company>'
or drop ``None`` fields at all:

.. code-block:: python
from typing import Optional
from pydantic_xml import BaseXmlModel, element
class Company(BaseXmlModel):
title: Optional[str] = element()
company = Company()
assert company.to_xml(skip_empty=True) == b'<Company />'
Default namespace
~~~~~~~~~~~~~~~~~

Expand Down
6 changes: 5 additions & 1 deletion examples/snippets/model_mode_ordered.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@


# [model-start]
class Company(BaseXmlModel, tag='Company', search_mode='ordered'):
class Company(
BaseXmlModel,
tag='Company',
search_mode='ordered',
):
founded: str = element(tag='Founded')
website: str = element(tag='WebSite')
# [model-end]
Expand Down
6 changes: 5 additions & 1 deletion examples/snippets/model_mode_strict.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@


# [model-start]
class Company(BaseXmlModel, tag='Company', search_mode='strict'):
class Company(
BaseXmlModel,
tag='Company',
search_mode='strict',
):
founded: str = element(tag='Founded')
website: str = element(tag='WebSite')
# [model-end]
Expand Down
6 changes: 5 additions & 1 deletion examples/snippets/model_mode_unordered.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@


# [model-start]
class Company(BaseXmlModel, tag='Company', search_mode='unordered'):
class Company(
BaseXmlModel,
tag='Company',
search_mode='unordered',
):
founded: str = element(tag='Founded')
website: str = element(tag='WebSite')
# [model-end]
Expand Down
10 changes: 7 additions & 3 deletions pydantic_xml/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ def nsmap(self) -> Optional[NsMap]:
def attr(**kwargs: Any) -> Any:
"""
Marks a pydantic field as an xml attribute.
Method parameters are identical to :py:class:`pydantic_xml.XmlAttributeInfo`.
:param kwargs: see :py:class:`pydantic_xml.XmlAttributeInfo`
"""

return XmlAttributeInfo(**kwargs)
Expand All @@ -153,7 +154,8 @@ def attr(**kwargs: Any) -> Any:
def element(**kwargs: Any) -> Any:
"""
Marks a pydantic field as an xml element.
Method parameters are identical to :py:class:`pydantic_xml.XmlElementInfo`.
:param kwargs: see :py:class:`pydantic_xml.XmlElementInfo`
"""

return XmlElementInfo(**kwargs)
Expand All @@ -162,7 +164,9 @@ def element(**kwargs: Any) -> Any:
def wrapped(*args: Any, **kwargs: Any) -> Any:
"""
Marks a pydantic field as a wrapped xml entity.
Method parameters are identical to :py:class:`pydantic_xml.XmlWrapperInfo`.
:param args: see :py:class:`pydantic_xml.XmlWrapperInfo`
:param kwargs: see :py:class:`pydantic_xml.XmlWrapperInfo`
"""

return XmlWrapperInfo(*args, **kwargs)
Expand Down

0 comments on commit b442b17

Please sign in to comment.