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

Frozen dataclasses #529

Merged
merged 7 commits into from
Jun 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ repos:
- id: docformatter
args: ["--in-place", "--pre-summary-newline"]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.902
rev: v0.910
hooks:
- id: mypy
additional_dependencies: [tokenize-rt, types-requests, types-Jinja2, types-click]
Expand Down
3 changes: 2 additions & 1 deletion docs/_static/config.sample.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
<Config xmlns="http://pypi.org/project/xsdata" version="21.6">
<Output maxLineLength="79">
<Package>generated</Package>
<Format relativeImports="false">dataclasses</Format>
<Format repr="true" eq="true" order="false" unsafeHash="false" frozen="false">dataclasses</Format>
<Structure>filenames</Structure>
<DocstringStyle>reStructuredText</DocstringStyle>
<RelativeImports>false</RelativeImports>
<CompoundFields>false</CompoundFields>
</Output>
<Conventions>
Expand Down
1 change: 1 addition & 0 deletions docs/api/codegen.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ like naming conventions and aliases.
GeneratorConfig
GeneratorOutput

OutputFormat
GeneratorConventions
GeneratorAliases
StructureStyle
Expand Down
6 changes: 4 additions & 2 deletions docs/codegen.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Generate Code

- :ref:`Compound fields <Type: Elements>`
- :ref:`Docstring styles`
- :ref:`Dataclasses Features`


.. code-block:: console
Expand Down Expand Up @@ -96,8 +97,9 @@ altogether.
.. warning::

Auto :ref:`locating types <Unknown xml target type>` during parsing might not work since
all classes are bundled together under the same module namespace.
Auto :ref:`locating types <Parse with unknown xml target type>` during parsing
might not work since all classes are bundled together under the same module
namespace.


Initialize Config
Expand Down
1 change: 1 addition & 0 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Code Generation
examples/xml-modeling
examples/json-modeling
examples/compound-fields
examples/dataclasses-features


Advance Topics
Expand Down
41 changes: 41 additions & 0 deletions docs/examples/dataclasses-features.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
====================
Dataclasses Features
====================

By default xsdata with generate
`dataclasses <https://docs.python.org/3/library/dataclasses.html>`_ with the default
features on but you can use a :ref:`generator config <Generator Config>` to toggle
almost all of them.


.. literalinclude:: /../tests/fixtures/stripe/.xsdata.xml
:language: xml
:lines: 2-6


.. tab:: Frozen Model

The code generator will use tuples instead of lists as well.

.. literalinclude:: /../tests/fixtures/stripe/models/balance.py
:language: python
:lines: 93-128

.. tab:: Frozen Bindings

.. testcode::

import pprint
from tests import fixtures_dir
from tests.fixtures.stripe.models import Balance
from xsdata.formats.dataclass.parsers import JsonParser

xml_path = fixtures_dir.joinpath("stripe/samples/balance.json")
parser = JsonParser()
root = parser.from_path(xml_path, Balance)
pprint.pprint(root.pending)

.. testoutput::

(Pending(amount=835408472, currency='usd', source_types=SourceTypes(bank_account=0, card=835408472)),
Pending(amount=-22251, currency='eur', source_types=SourceTypes(bank_account=0, card=-22251)))
6 changes: 3 additions & 3 deletions docs/examples/json-modeling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ duplicate classes and their fields and their field types.

.. code-block:: console
$ xsdata --package tests.fixtures.series tests/fixtures/series
$ xsdata --package tests.fixtures.series tests/fixtures/series/samples
.. tab:: Sample #1

.. literalinclude:: /../tests/fixtures/series/show1.json
.. literalinclude:: /../tests/fixtures/series/samples/show1.json
:language: json

.. tab:: Sample #2

.. literalinclude:: /../tests/fixtures/series/show2.json
.. literalinclude:: /../tests/fixtures/series/samples/show2.json
:language: json


Expand Down
2 changes: 1 addition & 1 deletion docs/models.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Simply follow the Python lib

.. warning::

Currently only List, Dict and Union annotations are supported.
Currently only List, Tuple, Dict and Union annotations are supported.
Everything else will raise an exception as unsupported.


Expand Down
1 change: 0 additions & 1 deletion tests/fixtures/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ def deserialize(self, value: Any, **kwargs: Any) -> Any:

raise ConverterError()


def serialize(self, value: Telephone, **kwargs: Any) -> str:
return "-".join(map(str, value))

Expand Down
20 changes: 20 additions & 0 deletions tests/fixtures/stripe/.xsdata.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<Config xmlns="http://pypi.org/project/xsdata" version="21.6">
<Output maxLineLength="79">
<Package>tests.fixtures.stripe.models.balance</Package>
<Format repr="true" eq="true" order="true" unsafeHash="false" frozen="true">dataclasses</Format>
<Structure>single-package</Structure>
<DocstringStyle>reStructuredText</DocstringStyle>
<RelativeImports>true</RelativeImports>
<CompoundFields>false</CompoundFields>
</Output>
<Conventions>
<ClassName case="pascalCase" safePrefix="type"/>
<FieldName case="snakeCase" safePrefix="value"/>
<ConstantName case="screamingSnakeCase" safePrefix="value"/>
<ModuleName case="snakeCase" safePrefix="mod"/>
<PackageName case="snakeCase" safePrefix="pkg"/>
</Conventions>
<Aliases>
</Aliases>
</Config>
Empty file.
15 changes: 15 additions & 0 deletions tests/fixtures/stripe/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from .balance import (
Available,
Balance,
ConnectReserved,
Pending,
SourceTypes,
)

__all__ = [
"Available",
"Balance",
"ConnectReserved",
"Pending",
"SourceTypes",
]
128 changes: 128 additions & 0 deletions tests/fixtures/stripe/models/balance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
from dataclasses import dataclass, field
from typing import Optional, Tuple


@dataclass(order=True, frozen=True)
class ConnectReserved:
class Meta:
name = "connect_reserved"

amount: Optional[int] = field(
default=None,
metadata={
"type": "Element",
}
)
currency: Optional[str] = field(
default=None,
metadata={
"type": "Element",
}
)


@dataclass(order=True, frozen=True)
class SourceTypes:
class Meta:
name = "source_types"

bank_account: Optional[int] = field(
default=None,
metadata={
"type": "Element",
}
)
card: Optional[int] = field(
default=None,
metadata={
"type": "Element",
}
)


@dataclass(order=True, frozen=True)
class Available:
class Meta:
name = "available"

amount: Optional[int] = field(
default=None,
metadata={
"type": "Element",
}
)
currency: Optional[str] = field(
default=None,
metadata={
"type": "Element",
}
)
source_types: Optional[SourceTypes] = field(
default=None,
metadata={
"type": "Element",
}
)


@dataclass(order=True, frozen=True)
class Pending:
class Meta:
name = "pending"

amount: Optional[int] = field(
default=None,
metadata={
"type": "Element",
}
)
currency: Optional[str] = field(
default=None,
metadata={
"type": "Element",
}
)
source_types: Optional[SourceTypes] = field(
default=None,
metadata={
"type": "Element",
}
)


@dataclass(order=True, frozen=True)
class Balance:
class Meta:
name = "balance"

object_value: Optional[str] = field(
default=None,
metadata={
"name": "object",
"type": "Element",
}
)
available: Tuple[Available, ...] = field(
default_factory=tuple,
metadata={
"type": "Element",
}
)
connect_reserved: Tuple[ConnectReserved, ...] = field(
default_factory=tuple,
metadata={
"type": "Element",
}
)
livemode: Optional[bool] = field(
default=None,
metadata={
"type": "Element",
}
)
pending: Tuple[Pending, ...] = field(
default_factory=tuple,
metadata={
"type": "Element",
}
)
Loading