Skip to content

Commit 76e2ebf

Browse files
authored
Feat/upgrade tox and ci setup (#223)
* fix: update the tox settings * fix: one more attempt at failing builds * fix: one more attempt at coverage * fix: issues with tox ini * fix: one more try * fix: ci * fix: another try * fix: one more try * fix: update tox to emit junit format for coveralls * fix: try to get python 3.14 to work * fix: try to fix tox config * fix: issues with types * fix: update pre-commit config
1 parent bf6363d commit 76e2ebf

File tree

9 files changed

+282
-88
lines changed

9 files changed

+282
-88
lines changed

.coverage

52 KB
Binary file not shown.

.github/workflows/pythonpackage.yml

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,43 +13,56 @@ jobs:
1313
fail-fast: false
1414
matrix:
1515
python-version: [pypy-3.10, '3.10', '3.11' , '3.12', '3.13']
16+
tox-python-version: ['pypy3.10', 'py310', 'py311' , 'py312', 'py313']
1617
os: [
1718
ubuntu-latest,
1819
windows-latest,
1920
macos-latest,
2021
]
2122
include:
2223
# Add exact version 3.14.0-alpha.0 for ubuntu-latest only
23-
- python-version: '3.14.0-alpha.0'
24+
- python-version: '3.14.0-alpha.1'
25+
tox-python-version: py314-full
2426
os: ubuntu-latest
2527
exclude:
2628
# Exclude other OSes with Python 3.14.0-alpha.0
27-
- python-version: '3.14.0-alpha.0'
29+
- python-version: '3.14.0-alpha.1'
30+
tox-python-version: py314-full
2831
os: windows-latest
29-
- python-version: '3.14.0-alpha.0'
32+
- python-version: '3.14.0-alpha.1'
3033
os: macos-latest
34+
tox-python-version: py314-full
3135

3236
steps:
33-
- uses: actions/[email protected]
37+
- uses: actions/checkout@v4
38+
with:
39+
persist-credentials: false
40+
3441
- name: Set up Python ${{ matrix.python-version }}
3542
uses: actions/[email protected]
3643
with:
3744
python-version: ${{ matrix.python-version }}
3845
allow-prereleases: true
46+
- name: install uv
47+
uses: astral-sh/setup-uv@v3
48+
with:
49+
enable-cache: true
50+
cache-dependency-glob: requirements-dev.txt
51+
3952
- name: Install dependencies
40-
run: |
41-
python -m pip install --upgrade pip
42-
pip install --upgrade -r requirements-dev.txt
43-
pip install .
44-
- name: Test with pytest
45-
run: |
46-
pytest --cov --junitxml=junit.xml
53+
run: uv pip install --system tox tox-uv
54+
55+
- name: Run tox targets for ${{ matrix.python-version }}
56+
run: tox -e ${{matrix.tox-python-version}}
57+
4758
- name: Upload coverage to Codecov
4859
uses: codecov/codecov-action@v4
4960
with:
5061
token: ${{ secrets.CODECOV_TOKEN }}
62+
5163
- name: Upload test results to Codecov
5264
if: ${{ !cancelled() }}
5365
uses: codecov/test-results-action@v1
5466
with:
5567
token: ${{ secrets.CODECOV_TOKEN }}
68+

.gitignore

Lines changed: 131 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,131 @@
1-
.idea
2-
.tox
3-
*.pyc
4-
json2xml.egg-info
5-
build
6-
*.swp
7-
dist/*
8-
.mypy_cache
9-
.eggs
10-
.DS_Store
11-
venv
12-
.vscode
13-
tests/*.ipynb
14-
junit.xml
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# C extensions
7+
*.so
8+
9+
# Distribution / packaging
10+
.Python
11+
build/
12+
develop-eggs/
13+
dist/
14+
downloads/
15+
eggs/
16+
.eggs/
17+
lib/
18+
lib64/
19+
parts/
20+
sdist/
21+
var/
22+
wheels/
23+
pip-wheel-metadata/
24+
share/python-wheels/
25+
*.egg-info/
26+
.installed.cfg
27+
*.egg
28+
MANIFEST
29+
30+
# PyInstaller
31+
# Usually these files are written by a python script from a template
32+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
33+
*.manifest
34+
*.spec
35+
36+
# Installer logs
37+
pip-log.txt
38+
pip-delete-this-directory.txt
39+
40+
# Unit test / coverage reports
41+
htmlcov/
42+
.tox/
43+
.nox/
44+
.coverage
45+
.coverage.*
46+
.cache
47+
nosetests.xml
48+
coverage.xml
49+
*.cover
50+
*.py,cover
51+
.hypothesis/
52+
.pytest_cache/
53+
54+
# Translations
55+
*.mo
56+
*.pot
57+
58+
# Django stuff:
59+
*.log
60+
local_settings.py
61+
db.sqlite3
62+
db.sqlite3-journal
63+
64+
# Flask stuff:
65+
instance/
66+
.webassets-cache
67+
68+
# Scrapy stuff:
69+
.scrapy
70+
71+
# Sphinx documentation
72+
docs/_build/
73+
74+
# PyBuilder
75+
target/
76+
77+
# Jupyter Notebook
78+
.ipynb_checkpoints
79+
80+
# IPython
81+
profile_default/
82+
ipython_config.py
83+
84+
# pyenv
85+
.python-version
86+
87+
# pipenv
88+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
90+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
91+
# install all needed dependencies.
92+
#Pipfile.lock
93+
94+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
95+
__pypackages__/
96+
97+
# Celery stuff
98+
celerybeat-schedule
99+
celerybeat.pid
100+
101+
# SageMath parsed files
102+
*.sage.py
103+
104+
# Environments
105+
.env
106+
.venv
107+
env/
108+
venv/
109+
ENV/
110+
env.bak/
111+
venv.bak/
112+
113+
# Spyder project settings
114+
.spyderproject
115+
.spyproject
116+
117+
# Rope project settings
118+
.ropeproject
119+
120+
# mkdocs documentation
121+
/site
122+
123+
# mypy
124+
.mypy_cache/
125+
.dmypy.json
126+
dmypy.json
127+
128+
# Pyre type checker
129+
.pyre/
130+
131+
.idea/

.pre-commit-config.yaml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
ci:
2+
autofix_commit_msg: |
3+
ci: auto fixes from pre-commit hooks
4+
5+
for more information, see https://pre-commit.ci
6+
autofix_prs: true
7+
autoupdate_commit_msg: 'ci: pre-commit autoupdate'
8+
autoupdate_schedule: monthly
9+
10+
default_language_version:
11+
python: python3.12
12+
13+
repos:
14+
- repo: https://github.com/pre-commit/pre-commit-hooks
15+
rev: v5.0.0
16+
hooks:
17+
- id: check-added-large-files
18+
- id: check-case-conflict
19+
- id: check-json
20+
- id: check-merge-conflict
21+
- id: check-symlinks
22+
- id: check-toml
23+
- id: end-of-file-fixer
24+
- id: trailing-whitespace
25+
- repo: https://github.com/tox-dev/pyproject-fmt
26+
rev: v2.5.0
27+
hooks:
28+
- id: pyproject-fmt
29+
- repo: https://github.com/tox-dev/tox-ini-fmt
30+
rev: 1.4.1
31+
hooks:
32+
- id: tox-ini-fmt
33+
- repo: https://github.com/rstcheck/rstcheck
34+
rev: v6.2.4
35+
hooks:
36+
- id: rstcheck
37+
additional_dependencies:
38+
- tomli==2.0.1
39+
- repo: https://github.com/asottile/pyupgrade
40+
rev: v3.19.1
41+
hooks:
42+
- id: pyupgrade
43+
args: [--py38-plus]
44+
- repo: https://github.com/psf/black-pre-commit-mirror
45+
rev: 24.10.0
46+
hooks:
47+
- id: black
48+
- repo: https://github.com/adamchainz/blacken-docs
49+
rev: 1.19.1
50+
hooks:
51+
- id: blacken-docs
52+
additional_dependencies:
53+
- black==23.1.0
54+
- repo: https://github.com/pycqa/isort
55+
rev: 5.13.2
56+
hooks:
57+
- id: isort
58+
name: isort (python)
59+
- repo: https://github.com/pre-commit/mirrors-mypy
60+
rev: v1.13.0
61+
hooks:
62+
- id: mypy
63+
additional_dependencies:
64+
- django-stubs==5.0.4

json2xml/dicttoxml.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,10 +269,10 @@ def dict2xml_str(
269269
val_attr: dict[str, str] = item.pop("@attrs", attr) # update attr with custom @attr if exists
270270
rawitem = item["@val"] if "@val" in item else item
271271
if is_primitive_type(rawitem):
272+
if isinstance(rawitem, dict):
273+
subtree = escape_xml(str(rawitem))
272274
if isinstance(rawitem, str):
273275
subtree = escape_xml(rawitem)
274-
else:
275-
subtree = rawitem
276276
else:
277277
# we can not use convert_dict, because rawitem could be non-dict
278278
subtree = convert(

junit.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<?xml version="1.0" encoding="utf-8"?><testsuites><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="81" time="0.212" timestamp="2024-12-17T23:32:51.229976+05:30" hostname="Vinits-MacBook-Pro.local"><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_namespaces" time="0.001" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_xmlns_namespaces" time="0.001" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_xsi_location" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_xsi_xmlns" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_item_wrap_true" time="0.001" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_item_wrap_false" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_flat" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_omit_list" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_val_and_custom_attr" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_ampersand" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_ampsersand_and_attrs" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_list_items_with_attrs" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_make_id" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_get_unique_id" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_key_is_valid_xml" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_get_xml_type" time="0.001" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_is_primitive_type" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_escape_xml" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_wrap_cdata" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_list_parent_elements" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_str_list_header" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_list_headers" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_list_headers_nested" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_list_headers_root" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_no_root" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_root" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_custom_root" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_item_func" time="0.001" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_with_item_func_issue_151" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_issue_151" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dict2xml_attr_type" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_get_xml_type_number" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_convert_datetime" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_basic_conversion" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_with_type_attribute" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_with_custom_attributes" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_valid_key" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_convert_kv_with_cdata" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_convert_kv_with_attr_type" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_make_valid_xml_name_with_invalid_key" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_convert_bool_with_attr_type" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_convert_none_with_attr_type" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_make_valid_xml_name_with_numeric_key" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_escape_xml_with_special_chars" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_get_xml_type_with_sequence" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_get_xml_type_with_none" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_dicttoxml_with_xml_namespaces" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_datetime_conversion" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_list_to_xml_with_primitive_items" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_list_to_xml_with_dict_items" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_list_to_xml_with_mixed_items" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_list_to_xml_with_empty_list" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_list_to_xml_with_special_characters" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_datetime_conversion_with_isoformat" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_date_conversion_with_isoformat" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_datetime_conversion_with_attr_type" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_date_conversion_with_attr_type" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_datetime_conversion_with_custom_attributes" time="0.000" /><testcase classname="tests.test_dict2xml.TestDict2xml" name="test_date_conversion_with_custom_attributes" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_read_from_json" time="0.001" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_read_from_invalid_json" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_read_from_invalid_json2" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_read_from_jsonstring" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_read_from_invalid_string1" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_read_from_invalid_string2" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_read_from_invalid_jsonstring" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_json_to_xml_conversion" time="0.001" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_json_to_xml_empty_data_conversion" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_custom_wrapper_and_indent" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_no_wrapper" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_item_wrap" time="0.001" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_no_item_wrap" time="0.001" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_empty_array" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_attrs" time="0.001" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_dicttoxml_bug" time="0.001" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_bad_data" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_read_boolean_data_from_json" time="0.001" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_read_boolean_data_from_json2" time="0.001" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_dict_attr_crash" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_encoding_pretty_print" time="0.000" /><testcase classname="tests.test_json2xml.TestJson2xml" name="test_encoding_without_pretty_print" time="0.000" /></testsuite></testsuites>

pyproject.toml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,56 @@
1+
[build-system]
2+
requires = ["setuptools>=42", "wheel"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "json2xml"
7+
version = "5.0.5" # Replace with the dynamic version if needed
8+
description = "Simple Python Library to convert JSON to XML"
9+
readme = "README.rst"
10+
requires-python = ">=3.10"
11+
license = { text = "Apache Software License 2.0" }
12+
keywords = ["json2xml"]
13+
authors = [
14+
{ name = "Vinit Kumar", email = "[email protected]" }
15+
]
16+
classifiers = [
17+
"Development Status :: 6 - Mature",
18+
"Intended Audience :: Developers",
19+
"License :: OSI Approved :: Apache Software License",
20+
"Natural Language :: English",
21+
"Programming Language :: Python :: 3.10",
22+
"Programming Language :: Python :: 3.11",
23+
"Programming Language :: Python :: 3.12",
24+
"Programming Language :: Python :: 3.13",
25+
"Programming Language :: Python :: Implementation :: CPython",
26+
"Programming Language :: Python :: Implementation :: PyPy",
27+
"Topic :: Software Development :: Libraries :: Python Modules"
28+
]
29+
dependencies = [
30+
"defusedxml",
31+
"urllib3",
32+
"xmltodict>=0.12.0",
33+
"pytest",
34+
"pytest-cov",
35+
"coverage",
36+
"py",
37+
"setuptools",
38+
]
39+
40+
[project.urls]
41+
Homepage = "https://github.com/vinitkumar/json2xml"
42+
43+
[tool.setuptools.packages.find]
44+
include = ["json2xml"]
45+
46+
[project.optional-dependencies]
47+
test = [
48+
"pytest==7.0.1",
49+
"py==1.11.0"
50+
]
51+
52+
[tool.pytest.ini_options]
53+
testpaths = ["tests"]
154
[tool.ruff]
255
exclude = [
356
".env",

0 commit comments

Comments
 (0)