diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 54fb421..a13cb25 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,7 +13,7 @@ jobs: strategy: fail-fast: false matrix: - python: [ "3.8", "3.9", "3.10", "3.11", "3.12-dev" ] + python: [ "3.8", "3.9", "3.10", "3.11", "3.12" ] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} @@ -43,16 +43,18 @@ jobs: - { name: "Amadeus", id: "amadeus" } - { name: "Autosar", id: "autosar" } - { name: "BPMN", id: "bpmn" } - - { name: "Common Types", id: "common_types" } + - { name: "Common Types", id: "common-types" } - { name: "Crossref Metadata", id: "crossref" } - { name: "DateX II", id: "datexii" } - { name: "EWP", id: "ewp" } - - { name: "Generali", id: "generali" } + - { name: "Generali", id: "generali", skip_mypy: true } - { name: "NeTEx", id: "netex" } - { name: "NPO API", id: "npo" } - { name: "ReqIF", id: "reqif" } - { name: "Sabre", id: "sabre" } + - { name: "Sdmx-ml", id: "sdmx-ml", skip_mypy: true } - { name: "SpaceX", id: "spacex" } + - { name: "TPDB", id: "tpdb" } - { name: "Travelport", id: "travelport" } - { name: "UBL", id: "ubl" } - { name: "Voko", id: "voko" } @@ -71,18 +73,18 @@ jobs: python-version: ${{ matrix.python }} - name: Install dependencies run: | - pip install --upgrade pip mypy types-attrs types-dataclasses typed_dataclass dataclasses-jsonschema + pip install --upgrade pip invoke mypy types-attrs types-dataclasses typed_dataclass dataclasses-jsonschema pip install .[cli,test] - name: Generate Code working-directory: ./xsdata-samples - run: ./run.py build ${{ matrix.collection.id }} --output-format=attrs + run: invoke ${{ matrix.collection.id }}.build --output-format=attrs - name: Run Tests working-directory: ./xsdata-samples - run: ./run.py test ${{ matrix.collection.id }} --output-format=attrs + run: invoke ${{ matrix.collection.id }}.test --output-format=attrs - name: Run mypy + if: matrix.collection.skip_mypy != true working-directory: ./xsdata-samples - if: matrix.collection.id != 'generali' - run: ./run.py mypy ${{ matrix.collection.id }} --output-format=attrs + run: invoke ${{ matrix.collection.id }}.mypy pre-commit: name: Pre-commit Hooks runs-on: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3d879e6..9f1d98e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,32 +2,35 @@ exclude: tests/fixtures repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: debug-statements - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.2 + rev: v0.4.3 hooks: - id: ruff - args: [ --fix, --show-fixes ] + args: [ --fix, --show-fixes] - id: ruff-format - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.9.0 + rev: v1.10.0 hooks: - id: mypy - files: ^(xsdata_attrs/) + files: ^(xsdata/) additional_dependencies: - tokenize-rt - - types-attrs - - repo: https://github.com/PyCQA/doc8 - rev: v1.1.1 - hooks: - - id: doc8 + - types-requests + - types-Jinja2 + - types-click + - types-docutils + - types-toposort + args: [ "--check-untyped-defs", "--ignore-missing-imports" ] - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.1.0 + rev: v4.0.0-alpha.8 hooks: - id: prettier + additional_dependencies: + - prettier@3.2.5 types_or: [markdown] args: [--prose-wrap=always, --print-width=88] diff --git a/CHANGES.md b/CHANGES.md index 001d976..3ef71e7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,7 @@ +## 24.5 (2024-05-08) + +- Bump xsdata minimum version v24.5 + ## 24.3 (2024-03-10) - Add missing parser/serializer shortcuts diff --git a/README.md b/README.md index c8c0c9e..b994911 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,6 @@ class Rss: ``` -## Changelog: 24.3 (2024-03-10) +## Changelog: 24.5 (2024-05-08) -- Add missing parser/serializer shortcuts -- General project maintenance +- Bump xsdata minimum version v24.5 diff --git a/pyproject.toml b/pyproject.toml index 7be3e44..a4c43a6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ keywords = ["xsd", "wsdl", "schema", "dtd", "binding", "xml", "json", "dataclass requires-python = ">=3.8" dependencies = [ "attrs>=19.2.0", - "xsdata>=24.3", + "xsdata>=24.5", ] dynamic = ["version"] diff --git a/tests/test_bindings.py b/tests/test_bindings.py index dfef5b4..a7179c2 100644 --- a/tests/test_bindings.py +++ b/tests/test_bindings.py @@ -1,11 +1,8 @@ from datetime import datetime from unittest import TestCase -from xsdata.formats.dataclass.serializers.config import SerializerConfig from tests.fixtures.common import TypeC -from xsdata_attrs.bindings import JsonParser -from xsdata_attrs.bindings import JsonSerializer from xsdata_attrs.bindings import XmlParser from xsdata_attrs.bindings import XmlSerializer from xsdata_attrs.compat import AnyElement @@ -55,46 +52,3 @@ def test_xml_bindings(self): ) self.assertEqual(expected, serializer.render(self.obj, ns_map)) self.assertEqual(self.obj, parser.from_string(expected)) - - def test_serialize_json(self): - serializer = JsonSerializer(config=SerializerConfig(indent=" ")) - parser = JsonParser() - - expected = ( - "{\n" - ' "one": "first",\n' - ' "two": 1.1,\n' - ' "three": true,\n' - ' "four": [\n' - ' "01 January 2002 12:01",\n' - ' "05 February 2003 13:05"\n' - " ],\n" - ' "any": {\n' - ' "qname": null,\n' - ' "text": null,\n' - ' "tail": null,\n' - ' "children": [\n' - " {\n" - ' "qname": "foo",\n' - ' "text": "bar",\n' - ' "tail": null,\n' - ' "children": [],\n' - ' "attributes": {}\n' - " },\n" - " {\n" - ' "qname": "bar",\n' - ' "value": "1",\n' - ' "type": null\n' - " },\n" - " {\n" - ' "qname": "bar",\n' - ' "value": 2,\n' - ' "type": null\n' - " }\n" - " ],\n" - ' "attributes": {}\n' - " }\n" - "}" - ) - self.assertEqual(expected, serializer.render(self.obj)) - self.assertEqual(self.obj, parser.from_string(expected, TypeC)) diff --git a/tests/test_generator.py b/tests/test_generator.py index a999656..695f069 100644 --- a/tests/test_generator.py +++ b/tests/test_generator.py @@ -4,7 +4,6 @@ from click.testing import CliRunner from xsdata.cli import cli from xsdata.models.config import GeneratorConfig -from xsdata.utils.testing import ClassFactory from xsdata.utils.testing import FactoryTestCase from xsdata_attrs.generator import AttrsGenerator @@ -16,91 +15,7 @@ def setUp(self): config = GeneratorConfig() self.generator = AttrsGenerator(config) - def test_render(self): - classes = [ - ClassFactory.elements(2, package="foo"), - ClassFactory.elements(3, package="foo"), - ] - - classes[0].attrs[0].restrictions.max_occurs = 3 - - iterator = self.generator.render(classes) - - actual = [(out.path, out.title, out.source) for out in iterator] - expected = ( - "from typing import List, Optional\n" - "\n" - "import attr\n" - "\n" - '__NAMESPACE__ = "xsdata"\n' - "\n" - "\n" - "@attr.s\n" - "class ClassB:\n" - " class Meta:\n" - ' name = "class_B"\n' - "\n" - " attr_b: List[str] = attr.ib(\n" - " factory=list,\n" - " metadata={\n" - ' "name": "attr_B",\n' - ' "type": "Element",\n' - ' "max_occurs": 3,\n' - " },\n" - " )\n" - " attr_c: Optional[str] = attr.ib(\n" - " default=None,\n" - " metadata={\n" - ' "name": "attr_C",\n' - ' "type": "Element",\n' - " },\n" - " )\n" - "\n" - "\n" - "@attr.s\n" - "class ClassC:\n" - " class Meta:\n" - ' name = "class_C"\n' - "\n" - " attr_d: Optional[str] = attr.ib(\n" - " default=None,\n" - " metadata={\n" - ' "name": "attr_D",\n' - ' "type": "Element",\n' - " },\n" - " )\n" - " attr_e: Optional[str] = attr.ib(\n" - " default=None,\n" - " metadata={\n" - ' "name": "attr_E",\n' - ' "type": "Element",\n' - " },\n" - " )\n" - " attr_f: Optional[str] = attr.ib(\n" - " default=None,\n" - " metadata={\n" - ' "name": "attr_F",\n' - ' "type": "Element",\n' - " },\n" - " )\n" - ) - - self.assertEqual(2, len(actual)) - self.assertEqual(3, len(actual[1])) - - self.assertEqual("foo.tests", actual[1][1]) - self.assertEqual(expected, actual[1][2]) - - def test_with_unsafe_hash(self): - config = GeneratorConfig() - config.output.format.unsafe_hash = True - self.generator = AttrsGenerator(config) - - iterator = self.generator.render(ClassFactory.list(1)) - actual = [(out.path, out.title, out.source) for out in iterator] - self.assertTrue("@attr.s(hash=True)" in actual[1][2]) - - def test_complete(self): + def test_generator(self): runner = CliRunner() schema = Path(__file__).parent.joinpath("fixtures/schemas/po.xsd") os.chdir(Path(__file__).parent.parent) diff --git a/xsdata_attrs/__init__.py b/xsdata_attrs/__init__.py index 2926ea9..edeca10 100644 --- a/xsdata_attrs/__init__.py +++ b/xsdata_attrs/__init__.py @@ -1 +1 @@ -__version__ = "24.3" +__version__ = "24.5" diff --git a/xsdata_attrs/generator.py b/xsdata_attrs/generator.py index e8d7d3e..84b6df9 100644 --- a/xsdata_attrs/generator.py +++ b/xsdata_attrs/generator.py @@ -1,8 +1,7 @@ from typing import Dict -from typing import List from typing import Optional -from xsdata.codegen.models import Attr +from xsdata.codegen.models import Attr, Class from xsdata.formats.dataclass.filters import Filters from xsdata.formats.dataclass.generator import DataclassGenerator from xsdata.models.config import GeneratorConfig @@ -40,13 +39,12 @@ def build_class_annotation(cls, format: OutputFormat) -> str: def field_definition( self, + obj: Class, attr: Attr, - ns_map: Dict, parent_namespace: Optional[str], - parents: List[str], ) -> str: """Return the field definition with any extra metadata.""" - result = super().field_definition(attr, ns_map, parent_namespace, parents) + result = super().field_definition(obj, attr, parent_namespace) return result.replace("field(", "attr.ib(") @classmethod