Skip to content

Commit

Permalink
add indent arg to JSONHandler and RUAMLHandler constructors (#3910)
Browse files Browse the repository at this point in the history
* add indent arg to JSONHandler and RUAMLHandler constructors

* commit
  • Loading branch information
israelpoli authored Jan 1, 2024
1 parent 5b8b969 commit 870373e
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 17 deletions.
15 changes: 8 additions & 7 deletions demisto_sdk/commands/common/handlers/json/json5_handler.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import IO, Any, AnyStr
from typing import IO, Any, AnyStr, Optional

import json5 # noqa: TID251 - this is the handler

Expand All @@ -14,8 +14,9 @@ class JSON5_Handler(XSOAR_Handler):
Use only this wrapper for json handling.
"""

def __init__(self):
def __init__(self, indent=0) -> None:
self.json = json5
self.indent = indent

def loads(self, s: AnyStr):
try:
Expand All @@ -33,7 +34,7 @@ def dump(
self,
data: Any,
fp: IO[str],
indent: int = 0,
indent: Optional[int] = None,
sort_keys: bool = False,
quote_keys: bool = True,
**kwargs,
Expand All @@ -42,7 +43,7 @@ def dump(
self.json.dump(
data,
fp,
indent=indent,
indent=indent if indent is not None else self.indent,
sort_keys=sort_keys,
quote_keys=quote_keys,
ensure_ascii=kwargs.get("ensure_ascii", False),
Expand All @@ -53,15 +54,15 @@ def dump(
def dumps(
self,
obj: Any,
indent: int = 0,
indent: Optional[int] = None,
sort_keys: bool = False,
quote_keys: bool = True,
**kwargs,
):
try:
return self.dumps(
return self.json.dumps(
obj,
indent=indent,
indent=indent if indent is not None else self.indent,
sort_keys=sort_keys,
quote_keys=quote_keys,
ensure_ascii=kwargs.get("ensure_ascii", False),
Expand Down
11 changes: 6 additions & 5 deletions demisto_sdk/commands/common/handlers/json/ujson_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ class UJSON_Handler(XSOAR_Handler):

JSONDecodeError = JSONDecodeError

def __init__(self):
def __init__(self, indent=0) -> None:
self.json = ujson
self.indent = indent

def loads(self, s: AnyStr):
try:
Expand All @@ -31,12 +32,12 @@ def load(self, fp: IO[str]):
except ValueError as e:
raise JSONDecodeError(e)

def dump(self, data: Any, fp: IO[str], indent=0, sort_keys=False, **kwargs):
def dump(self, data: Any, fp: IO[str], indent=None, sort_keys=False, **kwargs):
try:
self.json.dump(
data,
fp,
indent=indent,
indent=indent if indent is not None else self.indent,
sort_keys=sort_keys,
escape_forward_slashes=kwargs.get("escape_forward_slashes", False),
encode_html_chars=kwargs.get("encode_html_chars", False),
Expand All @@ -45,11 +46,11 @@ def dump(self, data: Any, fp: IO[str], indent=0, sort_keys=False, **kwargs):
except ValueError as e:
raise JSONDecodeError(e) from e

def dumps(self, obj: Any, indent=0, sort_keys=False, **kwargs):
def dumps(self, obj: Any, indent=None, sort_keys=False, **kwargs):
try:
return self.json.dumps(
obj,
indent=indent,
indent=indent if indent is not None else self.indent,
sort_keys=sort_keys,
escape_forward_slashes=kwargs.get("escape_forward_slashes", False),
ensure_ascii=kwargs.get("ensure_ascii", False),
Expand Down
65 changes: 65 additions & 0 deletions demisto_sdk/commands/common/handlers/tests/json_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from io import StringIO

import json5 # noqa: TID251
import pytest
import ujson # noqa: TID251

from demisto_sdk.commands.common.handlers import JSON_Handler
from demisto_sdk.commands.common.handlers.json.json5_handler import JSON5_Handler


class TestJSONHandler:
Expand All @@ -22,3 +27,63 @@ def test_no_escape_chars_dump(self, tmpdir, slash_count: int):
url = f"https:{slashes}xsoar.com"
JSON_Handler().dump({"url": url}, file_.open("w+"))
assert url in file_.open().read()


@pytest.mark.parametrize(
"xsoar_handler, handler",
[
(
JSON_Handler,
ujson,
),
(
JSON5_Handler,
json5,
),
],
)
def test_json_handler_with_indent(mocker, xsoar_handler, handler):
"""
Given:
- A JSON_Handler / JSON5_Handler class with indent
When:
- run dumps / dump method
Then:
- Ensure that the method is called with the expected `indent`
"""
dumps_mock = mocker.patch.object(handler, "dumps")
dump_mock = mocker.patch.object(handler, "dump")
xsoar_handler(indent=4).dumps({"url": "https://xsoar.com"})
xsoar_handler(indent=4).dump({"url": "https://xsoar.com"}, StringIO())
assert dumps_mock.call_args[1]["indent"] == 4
assert dump_mock.call_args[1]["indent"] == 4


@pytest.mark.parametrize(
"xsoar_handler, handler",
[
(
JSON_Handler,
ujson,
),
(
JSON5_Handler,
json5,
),
],
)
def test_json_handler_without_indent(mocker, xsoar_handler, handler):
"""
Given:
- A JSON_Handler / JSON5_Handler class without indent
When:
- run dumps / dump method
Then:
- Ensure that the method is called with indent=0
"""
dumps_mock = mocker.patch.object(handler, "dumps")
dump_mock = mocker.patch.object(handler, "dump")
xsoar_handler().dumps({"url": "https://xsoar.com"})
xsoar_handler().dump({"url": "https://xsoar.com"}, StringIO())
assert dumps_mock.call_args[1]["indent"] == 0
assert dump_mock.call_args[1]["indent"] == 0
40 changes: 40 additions & 0 deletions demisto_sdk/commands/common/handlers/tests/yml_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from io import StringIO

from ruamel.yaml import YAML # noqa: TID251

from demisto_sdk.commands.common.handlers.yaml.ruamel_handler import RUAMEL_Handler


class TestYAMLHandler:
def test_yaml_handler_without_indent(self, mocker):
"""
Given:
- A RUAMEL_Handler object without indent
When:
- Running dump method
Then:
- Ensure indent is not called
"""
mocker.patch.object(YAML, "dump")
mocker.patch.object(YAML, "indent")
yaml = RUAMEL_Handler()
yaml.dump({}, StringIO())
assert yaml.yaml.indent.call_count == 0

def test_yaml_handler_with_indent(self, mocker):
"""
Given:
- A RUAMEL_Handler object with indent
When:
- Running dump method
Then:
- Ensure indent is called
- Ensure indent is called with the correct value
"""
mocker.patch.object(YAML, "dump")
mocker.patch.object(YAML, "indent")
yaml_dump = RUAMEL_Handler(indent=4)
yaml_dump.dump({}, StringIO())

assert yaml_dump.yaml.indent.call_count == 1
yaml_dump.yaml.indent.assert_called_with(sequence=4)
4 changes: 2 additions & 2 deletions demisto_sdk/commands/common/handlers/xsoar_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ def load(self, stream: IO[str]) -> Any:
pass

@abstractmethod
def dump(self, data: Any, fp: IO[str], indent=0, sort_keys=False, **kwargs):
def dump(self, data: Any, fp: IO[str], indent=None, sort_keys=False, **kwargs):
pass

@abstractmethod
def dumps(self, obj: Any, indent=0, sort_keys=False, **kwargs) -> str:
def dumps(self, obj: Any, indent=None, sort_keys=False, **kwargs) -> str:
pass
14 changes: 11 additions & 3 deletions demisto_sdk/commands/common/handlers/yaml/ruamel_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ def __init__(
allow_duplicate_keys=False,
width=5000,
ensure_ascii=False,
indent=0,
):
"""
typ: 'rt'/None -> RoundTripLoader/RoundTripDumper, (default, preserves order, comments and formatting. slower then the rest))
Expand All @@ -32,6 +33,7 @@ def __init__(
self._allow_duplicate_keys = allow_duplicate_keys
self._width = width
self._allow_unicode = not ensure_ascii
self.indent = indent

@property
def yaml(self) -> YAML:
Expand All @@ -46,15 +48,16 @@ def yaml(self) -> YAML:
def load(self, stream):
return self.yaml.load(stream)

def dump(self, data, stream, indent=0, sort_keys=False, **kwargs):
def dump(self, data, stream, indent=None, sort_keys=False, **kwargs):
if sort_keys:
data = order_dict(data)
yaml = self.yaml
indent = indent if indent is not None else self.indent
if indent:
yaml.indent(sequence=indent)
yaml.dump(data, stream)

def dumps(self, data, indent=0, sort_keys=False, **kwargs):
def dumps(self, data, indent=None, sort_keys=False, **kwargs):
"""
This function is not recommended and not efficient!
Expand All @@ -64,7 +67,12 @@ def dumps(self, data, indent=0, sort_keys=False, **kwargs):
to print a YAML, it is better to use `yaml.dump(data, sys.stdout)`
"""
string_stream = StringIO()
self.dump(data, string_stream, sort_keys=sort_keys, indent=indent)
self.dump(
data,
string_stream,
sort_keys=sort_keys,
indent=indent if indent is not None else self.indent,
)
output_str = string_stream.getvalue()
string_stream.close()
return output_str

0 comments on commit 870373e

Please sign in to comment.