json2xml 7.0.0__tar.gz → 7.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. {json2xml-7.0.0 → json2xml-7.0.1}/HISTORY.rst +6 -0
  2. {json2xml-7.0.0 → json2xml-7.0.1}/PKG-INFO +1 -1
  3. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml/__init__.py +1 -1
  4. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml/cli.py +9 -3
  5. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml.egg-info/PKG-INFO +1 -1
  6. {json2xml-7.0.0 → json2xml-7.0.1}/pyproject.toml +1 -1
  7. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_cli.py +54 -0
  8. {json2xml-7.0.0 → json2xml-7.0.1}/AUTHORS.rst +0 -0
  9. {json2xml-7.0.0 → json2xml-7.0.1}/CONTRIBUTING.rst +0 -0
  10. {json2xml-7.0.0 → json2xml-7.0.1}/LICENSE +0 -0
  11. {json2xml-7.0.0 → json2xml-7.0.1}/MANIFEST.in +0 -0
  12. {json2xml-7.0.0 → json2xml-7.0.1}/README.rst +0 -0
  13. {json2xml-7.0.0 → json2xml-7.0.1}/docs/Makefile +0 -0
  14. {json2xml-7.0.0 → json2xml-7.0.1}/docs/authors.rst +0 -0
  15. {json2xml-7.0.0 → json2xml-7.0.1}/docs/benchmarks.rst +0 -0
  16. {json2xml-7.0.0 → json2xml-7.0.1}/docs/conf.py +0 -0
  17. {json2xml-7.0.0 → json2xml-7.0.1}/docs/contributing.rst +0 -0
  18. {json2xml-7.0.0 → json2xml-7.0.1}/docs/history.rst +0 -0
  19. {json2xml-7.0.0 → json2xml-7.0.1}/docs/index.rst +0 -0
  20. {json2xml-7.0.0 → json2xml-7.0.1}/docs/installation.rst +0 -0
  21. {json2xml-7.0.0 → json2xml-7.0.1}/docs/json2xml.rst +0 -0
  22. {json2xml-7.0.0 → json2xml-7.0.1}/docs/make.bat +0 -0
  23. {json2xml-7.0.0 → json2xml-7.0.1}/docs/modules.rst +0 -0
  24. {json2xml-7.0.0 → json2xml-7.0.1}/docs/readme.rst +0 -0
  25. {json2xml-7.0.0 → json2xml-7.0.1}/docs/rust_memory_benchmark.rst +0 -0
  26. {json2xml-7.0.0 → json2xml-7.0.1}/docs/usage.rst +0 -0
  27. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml/backend_selector.py +0 -0
  28. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml/dicttoxml.py +0 -0
  29. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml/dicttoxml_fast.py +0 -0
  30. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml/json2xml.py +0 -0
  31. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml/types.py +0 -0
  32. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml/utils.py +0 -0
  33. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml.egg-info/SOURCES.txt +0 -0
  34. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml.egg-info/dependency_links.txt +0 -0
  35. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml.egg-info/entry_points.txt +0 -0
  36. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml.egg-info/requires.txt +0 -0
  37. {json2xml-7.0.0 → json2xml-7.0.1}/json2xml.egg-info/top_level.txt +0 -0
  38. {json2xml-7.0.0 → json2xml-7.0.1}/setup.cfg +0 -0
  39. {json2xml-7.0.0 → json2xml-7.0.1}/setup.py +0 -0
  40. {json2xml-7.0.0 → json2xml-7.0.1}/tests/__init__.py +0 -0
  41. {json2xml-7.0.0 → json2xml-7.0.1}/tests/conftest.py +0 -0
  42. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_backend_selector.py +0 -0
  43. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_benchmark_multi_python.py +0 -0
  44. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_benchmark_security_hardening.py +0 -0
  45. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_dict2xml.py +0 -0
  46. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_dicttoxml_fast_fallback.py +0 -0
  47. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_dicttoxml_unit.py +0 -0
  48. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_json2xml.py +0 -0
  49. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_missing_coverage.py +0 -0
  50. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_rust_dicttoxml.py +0 -0
  51. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_rust_python_parity.py +0 -0
  52. {json2xml-7.0.0 → json2xml-7.0.1}/tests/test_utils.py +0 -0
@@ -1,4 +1,10 @@
1
1
 
2
+ 7.0.1 / 2026-08-28
3
+ ==================
4
+
5
+ * fix: validate explicitly provided empty ``--string``, ``--url``, and file-path inputs instead of silently falling back to stdin
6
+
7
+
2
8
  7.0.0 / 2026-08-23
3
9
  ==================
4
10
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: json2xml
3
- Version: 7.0.0
3
+ Version: 7.0.1
4
4
  Summary: Simple Python Library to convert JSON to XML
5
5
  Author-email: Vinit Kumar <mail@vinitkumar.me>
6
6
  License: Apache Software License 2.0
@@ -2,4 +2,4 @@
2
2
 
3
3
  __author__ = """Vinit Kumar"""
4
4
  __email__ = "mail@vinitkumar.me"
5
- __version__ = "7.0.0"
5
+ __version__ = "7.0.1"
@@ -109,13 +109,14 @@ class CLIApplication:
109
109
  """Thin command adapter around input resolution, conversion, and output."""
110
110
 
111
111
  def read_input(self, options: CLIConversionOptions) -> JSONValue:
112
- if options.url:
112
+ # None means omitted; explicit empty values still require source validation.
113
+ if options.url is not None:
113
114
  try:
114
115
  return readfromurl(options.url)
115
116
  except URLReadError as error:
116
117
  exit_with_error(f"Error reading from URL: {error}")
117
118
 
118
- if options.string:
119
+ if options.string is not None:
119
120
  try:
120
121
  return readfromstring(options.string)
121
122
  except StringReadError as error:
@@ -125,9 +126,14 @@ class CLIApplication:
125
126
  f"({error})"
126
127
  )
127
128
 
128
- if options.input_file:
129
+ if options.input_file is not None:
129
130
  if options.input_file == "-":
130
131
  return read_from_stdin()
132
+ if not options.input_file:
133
+ exit_with_error(
134
+ "Error: Empty JSON file path. "
135
+ "Pass a JSON file, use - for stdin, or provide --string/--url."
136
+ )
131
137
  if not Path(options.input_file).is_file():
132
138
  exit_with_error(
133
139
  f"Error: JSON file not found: {options.input_file}. "
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: json2xml
3
- Version: 7.0.0
3
+ Version: 7.0.1
4
4
  Summary: Simple Python Library to convert JSON to XML
5
5
  Author-email: Vinit Kumar <mail@vinitkumar.me>
6
6
  License: Apache Software License 2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "json2xml"
7
- version = "7.0.0"
7
+ version = "7.0.1"
8
8
  description = "Simple Python Library to convert JSON to XML"
9
9
  readme = "README.rst"
10
10
  requires-python = ">=3.10"
@@ -218,6 +218,45 @@ class TestCLI:
218
218
  assert result.returncode == 1
219
219
  assert "Invalid JSON in --string input" in result.stderr
220
220
 
221
+ # @lat: [[tests#CLI input resolution#Explicit empty string rejects piped stdin]]
222
+ def test_empty_string_does_not_fall_back_to_stdin(self) -> None:
223
+ """Test an explicit empty string remains the selected input source."""
224
+ result = subprocess.run(
225
+ [sys.executable, "-m", "json2xml.cli", "-s", ""],
226
+ input='{"stdin": "unexpected"}',
227
+ capture_output=True,
228
+ text=True,
229
+ )
230
+ assert result.returncode == 1
231
+ assert "Invalid JSON in --string input" in result.stderr
232
+ assert result.stdout == ""
233
+
234
+ # @lat: [[tests#CLI input resolution#Explicit empty URL rejects piped stdin]]
235
+ def test_empty_url_does_not_fall_back_to_stdin(self) -> None:
236
+ """Test an explicit empty URL remains the selected input source."""
237
+ result = subprocess.run(
238
+ [sys.executable, "-m", "json2xml.cli", "-u", ""],
239
+ input='{"stdin": "unexpected"}',
240
+ capture_output=True,
241
+ text=True,
242
+ )
243
+ assert result.returncode == 1
244
+ assert "Error reading from URL" in result.stderr
245
+ assert result.stdout == ""
246
+
247
+ # @lat: [[tests#CLI input resolution#Explicit empty file path rejects piped stdin]]
248
+ def test_empty_file_path_does_not_fall_back_to_stdin(self) -> None:
249
+ """Test an explicit empty file path remains the selected input source."""
250
+ result = subprocess.run(
251
+ [sys.executable, "-m", "json2xml.cli", ""],
252
+ input='{"stdin": "unexpected"}',
253
+ capture_output=True,
254
+ text=True,
255
+ )
256
+ assert result.returncode == 1
257
+ assert "Empty JSON file path" in result.stderr
258
+ assert result.stdout == ""
259
+
221
260
  def test_no_input_error(self) -> None:
222
261
  """Test error when no input is provided."""
223
262
  # Force isatty to return True by using a pty-like environment
@@ -607,6 +646,21 @@ class TestCLIUnitTests:
607
646
  captured = capsys.readouterr()
608
647
  assert "Error reading from URL" in captured.err
609
648
 
649
+ # @lat: [[tests#CLI failure messages#Empty file path names the empty source]]
650
+ def test_read_input_empty_file_path(self, capsys: CaptureFixture[str]) -> None:
651
+ """Test read_input rejects an explicitly empty file path."""
652
+ args = MagicMock()
653
+ args.url = None
654
+ args.string = None
655
+ args.input_file = ""
656
+
657
+ with pytest.raises(SystemExit) as exc_info:
658
+ read_input(args)
659
+
660
+ assert exc_info.value.code == 1
661
+ captured = capsys.readouterr()
662
+ assert "Empty JSON file path" in captured.err
663
+
610
664
  def test_read_input_json_file_error(self, capsys: CaptureFixture[str]) -> None:
611
665
  """Test read_input handles JSON file read errors."""
612
666
  from json2xml.utils import JSONReadError
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes