Skip to content

Commit 8f19e8a

Browse files
committed
refactor(dicttoxml): improve typing and xml type detection; simplify get_unique_id API
- Accept optional ids list to avoid collisions deterministically in tests - Replace legacy type name checks with direct 'str'/'int' - Update tests to use monkeypatch for duplicate id simulation
1 parent 9e75ca4 commit 8f19e8a

File tree

2 files changed

+14
-45
lines changed

2 files changed

+14
-45
lines changed

json2xml/dicttoxml.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,19 @@ def make_id(element: str, start: int = 100000, end: int = 999999) -> str:
3131
return f"{element}_{safe_random.randint(start, end)}"
3232

3333

34-
def get_unique_id(element: str) -> str:
34+
def get_unique_id(element: str, ids: list[str] | None = None) -> str:
3535
"""
3636
Generate a unique ID for a given element.
3737
3838
Args:
3939
element (str): The element to generate an ID for.
40+
ids (list[str] | None, optional): A list of existing IDs to avoid duplicates. Defaults to None.
4041
4142
Returns:
4243
str: The unique ID.
4344
"""
44-
ids: list[str] = [] # initialize list of unique ids
45+
if ids is None:
46+
ids = []
4547
this_id = make_id(element)
4648
dup = True
4749
while dup:
@@ -78,9 +80,9 @@ def get_xml_type(val: ELEMENT) -> str:
7880
str: The XML type.
7981
"""
8082
if val is not None:
81-
if type(val).__name__ in ("str", "unicode"):
83+
if type(val).__name__ == "str":
8284
return "str"
83-
if type(val).__name__ in ("int", "long"):
85+
if type(val).__name__ == "int":
8486
return "int"
8587
if type(val).__name__ == "float":
8688
return "float"

tests/test_dict2xml.py

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import datetime
22
import numbers
33
from typing import TYPE_CHECKING, Any
4+
from unittest.mock import Mock
45

56
import pytest
67

@@ -774,50 +775,16 @@ def test_dicttoxml_with_cdata(self) -> None:
774775
result = dicttoxml.dicttoxml(data, cdata=True, attr_type=False, root=False)
775776
assert b"<key><![CDATA[value]]></key>" == result
776777

777-
def test_get_unique_id_with_duplicates(self) -> None:
778+
def test_get_unique_id_with_duplicates(self, monkeypatch: "MonkeyPatch") -> None:
778779
"""Test get_unique_id when duplicates are generated."""
779-
# We need to modify the original get_unique_id to simulate a pre-existing ID list
780-
import json2xml.dicttoxml as module
780+
ids = ["existing_id"]
781+
make_id_mock = Mock(side_effect=["existing_id", "new_id"])
782+
monkeypatch.setattr(dicttoxml, "make_id", make_id_mock)
781783

782-
# Save original function
783-
original_get_unique_id = module.get_unique_id
784-
785-
# Track make_id calls
786-
call_count = 0
787-
original_make_id = module.make_id
788-
789-
def mock_make_id(element: str, start: int = 100000, end: int = 999999) -> str:
790-
nonlocal call_count
791-
call_count += 1
792-
if call_count == 1:
793-
return "test_123456" # First call - will collide
794-
else:
795-
return "test_789012" # Second call - unique
796-
797-
# Patch get_unique_id to use a pre-populated ids list
798-
def patched_get_unique_id(element: str) -> str:
799-
# Start with a pre-existing ID to force collision
800-
ids = ["test_123456"]
801-
this_id = module.make_id(element)
802-
dup = True
803-
while dup:
804-
if this_id not in ids:
805-
dup = False
806-
ids.append(this_id)
807-
else:
808-
this_id = module.make_id(element) # This exercises line 52
809-
return ids[-1]
810-
811-
module.make_id = mock_make_id
812-
module.get_unique_id = patched_get_unique_id
784+
unique_id = dicttoxml.get_unique_id("some_element", ids=ids)
813785

814-
try:
815-
result = dicttoxml.get_unique_id("test")
816-
assert result == "test_789012"
817-
assert call_count == 2
818-
finally:
819-
module.make_id = original_make_id
820-
module.get_unique_id = original_get_unique_id
786+
assert unique_id == "new_id"
787+
assert make_id_mock.call_count == 2
821788

822789
def test_convert_with_bool_direct(self) -> None:
823790
"""Test convert function with boolean input directly."""

0 commit comments

Comments
 (0)