Repository: tefra/xsdata
Pull request #327 (2020-11-29 13:06:26)

#309 Update json bindings

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=VULNERABILITY)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=327&resolved=false&types=SECURITY_HOTSPOT) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=327&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=327&resolved=false&types=SECURITY_HOTSPOT)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=327) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/NoDuplicationInfo.png' alt='No Duplication information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=327&metric=duplicated_lines_density&view=list) No Duplication information


codecov[bot]: # [Codecov](https://codecov.io/gh/tefra/xsdata/pull/327?src=pr&el=h1) Report
> Merging [#327](https://codecov.io/gh/tefra/xsdata/pull/327?src=pr&el=desc) (0c88c13) into [master](https://codecov.io/gh/tefra/xsdata/commit/8ac0334e736fb8f815ef977ada231de260461cef?el=desc) (8ac0334) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/tefra/xsdata/pull/327/graphs/tree.svg?width=650&height=150&src=pr&token=YzDDLtywvl)](https://codecov.io/gh/tefra/xsdata/pull/327?src=pr&el=tree)

```diff
@@            Coverage Diff            @@
##            master      #327   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           70        70           
  Lines         5643      5641    -2     
  Branches       982       982           
=========================================
- Hits          5643      5641    -2     
```


| [Impacted Files](https://codecov.io/gh/tefra/xsdata/pull/327?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [xsdata/formats/dataclass/models/generics.py](https://codecov.io/gh/tefra/xsdata/pull/327/diff?src=pr&el=tree#diff-eHNkYXRhL2Zvcm1hdHMvZGF0YWNsYXNzL21vZGVscy9nZW5lcmljcy5weQ==) | `100.00% <ø> (ø)` | |
| [xsdata/formats/dataclass/parsers/nodes.py](https://codecov.io/gh/tefra/xsdata/pull/327/diff?src=pr&el=tree#diff-eHNkYXRhL2Zvcm1hdHMvZGF0YWNsYXNzL3BhcnNlcnMvbm9kZXMucHk=) | `100.00% <ø> (ø)` | |
| [xsdata/formats/dataclass/parsers/utils.py](https://codecov.io/gh/tefra/xsdata/pull/327/diff?src=pr&el=tree#diff-eHNkYXRhL2Zvcm1hdHMvZGF0YWNsYXNzL3BhcnNlcnMvdXRpbHMucHk=) | `100.00% <ø> (ø)` | |
| [xsdata/codegen/sanitizer.py](https://codecov.io/gh/tefra/xsdata/pull/327/diff?src=pr&el=tree#diff-eHNkYXRhL2NvZGVnZW4vc2FuaXRpemVyLnB5) | `100.00% <0.00%> (ø)` | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/tefra/xsdata/pull/327?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/tefra/xsdata/pull/327?src=pr&el=footer). Last update [8ac0334...0c88c13](https://codecov.io/gh/tefra/xsdata/pull/327?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=VULNERABILITY)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=327&resolved=false&types=SECURITY_HOTSPOT) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=327&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=327&resolved=false&types=SECURITY_HOTSPOT)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=327) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3.png' alt='0.0%' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=327&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=327&metric=new_duplicated_lines_density&view=list)


sonarcloud[bot]: Kudos, SonarCloud Quality Gate passed!

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug.png' alt='Bug' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=BUG) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=BUG) [0 Bugs](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=BUG)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability.png' alt='Vulnerability' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=VULNERABILITY) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=VULNERABILITY)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot.png' alt='Security Hotspot' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=327&resolved=false&types=SECURITY_HOTSPOT) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=327&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=tefra_xsdata&pullRequest=327&resolved=false&types=SECURITY_HOTSPOT)  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell.png' alt='Code Smell' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=CODE_SMELL) [<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A.png' alt='A' width='16' height='16' />](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=tefra_xsdata&pullRequest=327&resolved=false&types=CODE_SMELL)

[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/NoCoverageInfo.png' alt='No Coverage information' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=327) No Coverage information  
[<img src='https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3.png' alt='0.0%' width='16' height='16' />](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=327&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=tefra_xsdata&pullRequest=327&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/xsdata/formats/dataclass/models/generics.py b/xsdata/formats/dataclass/models/generics.py
index 1b60f465..c490df14 100644
--- a/xsdata/formats/dataclass/models/generics.py
+++ b/xsdata/formats/dataclass/models/generics.py
@@ -19,7 +19,6 @@ class AnyElement:
     :param qname: The namespace qualified name.
     :param text: Element text content.
     :param tail: Element tail content.
-    :param ns_map: The prefix-URI Namespace mapping
     :param children: A list of child elements.
     :param attributes: The element key-value attribute mapping.
     """
@@ -27,7 +26,6 @@ class AnyElement:
     qname: Optional[str] = field(default=None)
     text: Optional[str] = field(default=None)
     tail: Optional[str] = field(default=None)
-    ns_map: Dict = field(default_factory=dict)
     children: List[object] = field(
         default_factory=list, metadata={"type": XmlType.WILDCARD}
     )
diff --git a/xsdata/formats/dataclass/parsers/nodes.py b/xsdata/formats/dataclass/parsers/nodes.py
index b1691be3..cf059f23 100644
--- a/xsdata/formats/dataclass/parsers/nodes.py
+++ b/xsdata/formats/dataclass/parsers/nodes.py
@@ -226,7 +226,6 @@ class AnyTypeNode(XmlNode):
                 qname=qname,
                 text=ParserUtils.normalize_content(text),
                 tail=ParserUtils.normalize_content(tail),
-                ns_map=self.ns_map,
                 attributes=ParserUtils.parse_any_attributes(self.attrs, self.ns_map),
                 children=ParserUtils.fetch_any_children(self.position, objects),
             )
@@ -283,7 +282,6 @@ class WildcardNode(XmlNode):
             qname=qname,
             text=ParserUtils.normalize_content(text),
             tail=ParserUtils.normalize_content(tail),
-            ns_map=self.ns_map,
             attributes=ParserUtils.parse_any_attributes(self.attrs, self.ns_map),
             children=ParserUtils.fetch_any_children(self.position, objects),
         )
diff --git a/xsdata/formats/dataclass/parsers/utils.py b/xsdata/formats/dataclass/parsers/utils.py
index 6bf8b42b..d7858e34 100644
--- a/xsdata/formats/dataclass/parsers/utils.py
+++ b/xsdata/formats/dataclass/parsers/utils.py
@@ -187,7 +187,6 @@ class ParserUtils:
             generic = AnyElement(
                 text=txt,
                 tail=tail,
-                ns_map=ns_map,
                 attributes=cls.parse_any_attributes(attrs, ns_map),
             )
             if previous:
diff --git a/xsdata/formats/dataclass/serializers/json.py b/xsdata/formats/dataclass/serializers/json.py
index 4822e341..31c82a18 100644
--- a/xsdata/formats/dataclass/serializers/json.py
+++ b/xsdata/formats/dataclass/serializers/json.py
@@ -1,9 +1,7 @@
-import copy
 import json
+from dataclasses import asdict
 from dataclasses import dataclass
 from dataclasses import field
-from dataclasses import fields
-from dataclasses import is_dataclass
 from decimal import Decimal
 from enum import Enum
 from typing import Any
@@ -45,28 +43,6 @@ class JsonEncoder(json.JSONEncoder):
         return super().default(obj)
 
 
-def asdict(obj: Any, dict_factory: Callable = dict) -> Any:
-    """Clone dataclasses implementation to support pickling lxml.etree.QName
-    objects."""
-    if is_dataclass(obj):
-        return dict_factory(
-            [(f.name, asdict(getattr(obj, f.name), dict_factory)) for f in fields(obj)]
-        )
-
-    if isinstance(obj, (list, tuple)):
-        return type(obj)(asdict(v, dict_factory) for v in obj)
-
-    if isinstance(obj, dict):
-        return type(obj)(
-            (asdict(k, dict_factory), asdict(v, dict_factory)) for k, v in obj.items()
-        )
-
-    if isinstance(obj, QName):
-        return obj.text  # QNames are readonly anyway!
-
-    return copy.deepcopy(obj)
-
-
 @dataclass
 class JsonSerializer(AbstractSerializer):
     """


Test patch:
diff --git a/tests/fixtures/defxmlschema/chapter12.json b/tests/fixtures/defxmlschema/chapter12.json
index 0b977f9b..2794cceb 100644
--- a/tests/fixtures/defxmlschema/chapter12.json
+++ b/tests/fixtures/defxmlschema/chapter12.json
@@ -18,11 +18,6 @@
                             "qname": "{http://www.w3.org/1999/xhtml}b",
                             "text": "best-selling",
                             "tail": " shirt in\n      our catalog! ",
-                            "ns_map": {
-                                "xsi": "http://www.w3.org/2001/XMLSchema-instance",
-                                "xhtml": "http://www.w3.org/1999/xhtml",
-                                "oth": "http://example.org/oth"
-                            },
                             "children": [],
                             "attributes": {}
                         },
@@ -30,11 +25,6 @@
                             "qname": "{http://www.w3.org/1999/xhtml}br",
                             "text": null,
                             "tail": " Note: runs large.\n    ",
-                            "ns_map": {
-                                "xsi": "http://www.w3.org/2001/XMLSchema-instance",
-                                "xhtml": "http://www.w3.org/1999/xhtml",
-                                "oth": "http://example.org/oth"
-                            },
                             "children": [],
                             "attributes": {}
                         }
diff --git a/tests/fixtures/defxmlschema/chapter16.json b/tests/fixtures/defxmlschema/chapter16.json
index 204e1bc6..a897f569 100644
--- a/tests/fixtures/defxmlschema/chapter16.json
+++ b/tests/fixtures/defxmlschema/chapter16.json
@@ -5,15 +5,11 @@
                 "qname": null,
                 "text": null,
                 "tail": null,
-                "ns_map": {},
                 "children": [
                     {
                         "qname": "number",
                         "text": "443",
                         "tail": null,
-                        "ns_map": {
-                            "xsi": "http://www.w3.org/2001/XMLSchema-instance"
-                        },
                         "children": [],
                         "attributes": {}
                     },
@@ -21,9 +17,6 @@
                         "qname": "name",
                         "text": "Deluxe Golf Umbrella",
                         "tail": null,
-                        "ns_map": {
-                            "xsi": "http://www.w3.org/2001/XMLSchema-instance"
-                        },
                         "children": [],
                         "attributes": {}
                     }
diff --git a/tests/formats/dataclass/parsers/test_nodes.py b/tests/formats/dataclass/parsers/test_nodes.py
index ed5f8ba7..f72fe3ba 100644
--- a/tests/formats/dataclass/parsers/test_nodes.py
+++ b/tests/formats/dataclass/parsers/test_nodes.py
@@ -441,7 +441,6 @@ class AnyTypeNodeTests(TestCase):
             qname="a",
             text=None,
             tail="bar",
-            ns_map={},
             attributes={},
             children=[1, 2, 3],
         )
@@ -501,7 +500,6 @@ class WildcardNodeTests(TestCase):
             qname="foo",
             text=None,
             tail="bar",
-            ns_map=ns_map,
             attributes=attrs,
             children=[1, 2, 3],
         )
diff --git a/tests/formats/dataclass/parsers/test_utils.py b/tests/formats/dataclass/parsers/test_utils.py
index e9229219..eb77f912 100644
--- a/tests/formats/dataclass/parsers/test_utils.py
+++ b/tests/formats/dataclass/parsers/test_utils.py
@@ -321,11 +321,7 @@ class ParserUtilsTests(TestCase):
         ns_map = {"ns0": "a"}
         ParserUtils.bind_wild_content(params, var, "txt", "tail", attrs, ns_map)
         expected = AnyElement(
-            text="txt",
-            tail="tail",
-            children=[expected],
-            attributes=attrs,
-            ns_map=ns_map,
+            text="txt", tail="tail", children=[expected], attributes=attrs
         )
         self.assertEqual(dict(a=expected), params)
 
diff --git a/tests/formats/dataclass/serializers/test_json.py b/tests/formats/dataclass/serializers/test_json.py
index b5fcc456..f6e51a08 100644
--- a/tests/formats/dataclass/serializers/test_json.py
+++ b/tests/formats/dataclass/serializers/test_json.py
@@ -79,6 +79,3 @@ class JsonEncoderTests(TestCase):
     def test_default_raises_exceptions(self):
         with self.assertRaises(TypeError):
             json.dumps({"string": object()}, cls=JsonEncoder)
-
-    def test_asdict_qname_clone(self):
-        self.assertEqual("{a}b", asdict(QName("a", "b")))