Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All notable changes to the Zowe Client Python SDK will be documented in this fil
### Enhancements

- Added z/OSMF Workflows functionality. [#372](https://github.com/zowe/zowe-client-python-sdk/pull/372)
- Replaced the `commentjson` package with the `json5` package to support block comments. [#374](https://github.com/zowe/zowe-client-python-sdk/pull/374)

### Bug Fixes

Expand All @@ -16,12 +17,12 @@ All notable changes to the Zowe Client Python SDK will be documented in this fil

### Enhancements

- Fixed missing and incorrect type annotations. [#321](https://github.com/zowe/zowe-client-python-sdk/issues/321)
- Removed the `suppress_config_file_warnings` parameter from individual functions. [#365](https://github.com/zowe/zowe-client-python-sdk/issues/365)
- Introduced the class-wide property `suppress_config_file_warnings` to control configuration file warnings. [#365](https://github.com/zowe/zowe-client-python-sdk/issues/365)

### Bug Fixes

- Fixed missing and incorrect type annotations. [#321](https://github.com/zowe/zowe-client-python-sdk/issues/321)
- Updated the `pyo3` dependency of the Secrets SDK for technical currency. [#355](https://github.com/zowe/zowe-client-python-sdk/pull/355)
- Updated the `urllib3` dependency of the Core SDK for technical currency. [#370](https://github.com/zowe/zowe-client-python-sdk/pull/370)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ For more information on the available sub-packages click [HERE](https://zowe-cli
The Zowe core package has dependencies on the packages listed below:

```
commentjson
json5
deepmerge
jsonschema
pyyaml
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
commentjson==0.9.0
json5==0.12.1
deepmerge==1.1.0
jsonschema==4.17.3
PyYAML==6.0.1
Expand Down
2 changes: 1 addition & 1 deletion src/core/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)",
],
install_requires=[
"commentjson~=0.9.0",
"json5~=0.12.1",
"deepmerge~=1.1.0",
"jsonschema~=4.17.3",
"pyyaml~=6.0.1",
Expand Down
6 changes: 3 additions & 3 deletions src/core/zowe/core_for_zowe_sdk/config_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from dataclasses import dataclass, field
from typing import NamedTuple, Optional, Any, Union

import commentjson
import json5
import requests

from .credential_manager import CredentialManager
Expand Down Expand Up @@ -136,7 +136,7 @@ def init_from_file(
return

with open(self.filepath, encoding="UTF-8", mode="r") as fileobj:
profile_jsonc = commentjson.load(fileobj)
profile_jsonc = json5.load(fileobj)

self.profiles = profile_jsonc.get("profiles", {}) if profile_jsonc.get("profiles", {}) is not None else []
self.schema_property = profile_jsonc.get("$schema", None)
Expand Down Expand Up @@ -629,7 +629,7 @@ def save(self, update_secure_props: Optional[bool] = True) -> None:
CredentialManager.secure_props[self.filepath] = secure_props
with open(self.filepath, "w") as file:
self.jsonc["profiles"] = profiles_temp
commentjson.dump(self.jsonc, file, indent=4)
json5.dump(self.jsonc, file, indent=4)
if update_secure_props:
CredentialManager.save_secure_props()

Expand Down
6 changes: 3 additions & 3 deletions src/core/zowe/core_for_zowe_sdk/credential_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import sys
from typing import Optional, Any

import commentjson
import json5

from .constants import constants
from .exceptions import SecureProfileLoadFailed
Expand Down Expand Up @@ -63,7 +63,7 @@ def load_secure_props() -> None:

secure_config: bytes
secure_config = secret_value.encode()
secure_config_json = commentjson.loads(base64.b64decode(secure_config).decode())
secure_config_json = json5.loads(base64.b64decode(secure_config).decode())
# update the secure props
CredentialManager.secure_props = secure_config_json

Expand All @@ -76,7 +76,7 @@ def save_secure_props() -> None:
credential = CredentialManager.secure_props
# Check if credential is a non-empty string
if credential:
encoded_credential = base64.b64encode(commentjson.dumps(credential).encode()).decode()
encoded_credential = base64.b64encode(json5.dumps(credential).encode()).decode()
if sys.platform == "win32":
# Delete the existing credential
CredentialManager._delete_credential(
Expand Down
9 changes: 4 additions & 5 deletions src/core/zowe/core_for_zowe_sdk/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import os
from typing import Union, Any

import commentjson
import json5
import requests
from jsonschema import validate

Expand All @@ -38,21 +38,20 @@ def validate_config_json(path_config_json: Union[str, dict[str, Any]], path_sche
# checks if the path_schema_json is a file
elif os.path.isfile(path_schema_json) or path_schema_json.startswith("file://"):
with open(path_schema_json.replace("file://", "")) as file:
schema_json = commentjson.load(file)

schema_json = json5.load(file)
# checks if the path_schema_json is absolute
elif not os.path.isabs(path_schema_json):
path_schema_json = os.path.join(cwd, path_schema_json)
with open(path_schema_json) as file:
schema_json = commentjson.load(file)
schema_json = json5.load(file)

# if there is no path_schema_json it will return None
else:
return None

if isinstance(path_config_json, str):
with open(path_config_json) as file:
config_json = commentjson.load(file)
config_json = json5.load(file)
else:
config_json = path_config_json

Expand Down
87 changes: 78 additions & 9 deletions tests/unit/core/test_config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import importlib.util
import os

import commentjson
import json5
from jsonschema import ValidationError, validate
from pyfakefs.fake_filesystem_unittest import TestCase
from zowe.core_for_zowe_sdk.validators import validate_config_json
Expand Down Expand Up @@ -36,8 +36,8 @@ def setUp(self):

def test_validate_config_json_valid(self):
"""Test validate_config_json with valid config.json matching schema.json"""
config_json = commentjson.load(open(self.original_file_path))
schema_json = commentjson.load(open(self.original_schema_file_path))
config_json = json5.load(open(self.original_file_path))
schema_json = json5.load(open(self.original_schema_file_path))

expected = validate(config_json, schema_json)
result = validate_config_json(self.original_file_path, self.original_schema_file_path, cwd=FIXTURES_PATH)
Expand All @@ -51,17 +51,17 @@ def test_validate_config_json_invalid(self):
path_to_invalid_schema = os.path.join(custom_dir, "invalid.zowe.schema.json")

with open(self.original_file_path, "r") as f:
original_config = commentjson.load(f)
original_config = json5.load(f)
original_config["$schema"] = "invalid.zowe.schema.json"
original_config["profiles"]["zosmf"]["properties"]["port"] = "10443"
with open(path_to_invalid_config, "w") as f:
commentjson.dump(original_config, f)
json5.dump(original_config, f)
with open(self.original_schema_file_path, "r") as f:
original_schema = commentjson.load(f)
original_schema = json5.load(f)
with open(path_to_invalid_schema, "w") as f:
commentjson.dump(original_schema, f)
invalid_config_json = commentjson.load(open(path_to_invalid_config))
invalid_schema_json = commentjson.load(open(path_to_invalid_schema))
json5.dump(original_schema, f)
invalid_config_json = json5.load(open(path_to_invalid_config))
invalid_schema_json = json5.load(open(path_to_invalid_schema))

with self.assertRaises(ValidationError) as expected_info:
validate(invalid_config_json, invalid_schema_json)
Expand All @@ -70,3 +70,72 @@ def test_validate_config_json_invalid(self):
validate_config_json(path_to_invalid_config, path_to_invalid_schema, cwd=FIXTURES_PATH)

self.assertEqual(str(actual_info.exception), str(expected_info.exception))

def test_validate_config_json_with_block_comments(self):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, sorry for taking so much time 😓, I have added the unit test to load and validate config json with block comments

"""Config with /* block comments */ should load and validate."""
custom_dir = os.path.dirname(FIXTURES_PATH)
commented_config_path = os.path.join(custom_dir, "commented.zowe.config.json")
commented_schema_path = os.path.join(custom_dir, "commented.zowe.schema.json")

schema_text = """
{
/* Top-level block comment in schema */
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"$schema": { "type": "string" },
"profiles": {
"type": "object",
"properties": {
"zosmf": {
"type": "object",
"properties": {
"properties": {
"type": "object",
"properties": {
"host": { "type": "string" },
"port": { "type": "integer" }
},
"required": ["host", "port"]
}
},
"required": ["properties"]
}
},
"required": ["zosmf"]
}
},
"required": ["$schema", "profiles"]
}
"""

config_text = """
{
/* Block comment before schema reference */
"$schema": "commented.zowe.schema.json",
"profiles": {
/* Block comment inside profiles */
"zosmf": {
"properties": {
"host": "localhost",
/* Inline block comment between fields */
"port": 10443, /* trailing comma tolerated by JSON5 */
},
},
}
}
"""

# Write files to the fake FS
with open(commented_schema_path, "w", encoding="utf-8") as f:
f.write(schema_text)
with open(commented_config_path, "w", encoding="utf-8") as f:
f.write(config_text)

loaded_config = json5.load(open(commented_config_path, encoding="utf-8"))
loaded_schema = json5.load(open(commented_schema_path, encoding="utf-8"))

expected = validate(loaded_config, loaded_schema)
result = validate_config_json(commented_config_path, commented_schema_path, cwd=os.path.dirname(commented_config_path))

self.assertEqual(result, expected)
26 changes: 13 additions & 13 deletions tests/unit/core/test_profile_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import shutil
from unittest import mock

import commentjson
import json5
from jsonschema import SchemaError, ValidationError
from pyfakefs.fake_filesystem_unittest import TestCase
from zowe.core_for_zowe_sdk import (
Expand Down Expand Up @@ -348,7 +348,7 @@ def test_load_secure_props(self, retrieve_cred_func):
cwd_up_file_path: {"profiles.base.properties.user": "user", "profiles.base.properties.password": "password"}
}
self.setUpCreds(cwd_up_file_path, credential)
encoded_credential = base64.b64encode(commentjson.dumps(credential).encode()).decode()
encoded_credential = base64.b64encode(json5.dumps(credential).encode()).decode()
retrieve_cred_func.return_value = encoded_credential

# call the load_secure_props method
Expand Down Expand Up @@ -446,7 +446,7 @@ def test_save_secure_props_normal_credential(self, delete_pass_func, retrieve_cr
}
}
self.setUpCreds(cwd_up_file_path, credential)
encoded_credential = base64.b64encode(commentjson.dumps(credential).encode()).decode()
encoded_credential = base64.b64encode(json5.dumps(credential).encode()).decode()
retrieve_cred_func.return_value = None

CredentialManager.secure_props = credential
Expand Down Expand Up @@ -474,7 +474,7 @@ def test_save_secure_props_exceed_limit(self, delete_pass_func, set_pass_func, r
}
}
self.setUpCreds(cwd_up_file_path, credential)
encoded_credential = base64.b64encode(commentjson.dumps(credential).encode()).decode()
encoded_credential = base64.b64encode(json5.dumps(credential).encode()).decode()
encoded_credential += "\0"
retrieve_cred_func.return_value = encoded_credential

Expand Down Expand Up @@ -524,15 +524,15 @@ def test_profile_loading_with_invalid_schema(self, get_pass_func):
with self.assertRaises(ValidationError):
custom_file_path = os.path.join(self.custom_dir, "zowe.config.json")
with open(self.original_file_path, "r") as f:
original_config = commentjson.load(f)
original_config = json5.load(f)
original_config["$schema"] = "invalid.zowe.schema.json"
original_config["profiles"]["zosmf"]["properties"]["port"] = "10443"
with open(os.path.join(self.custom_dir, "invalid.zowe.config.json"), "w") as f:
commentjson.dump(original_config, f)
json5.dump(original_config, f)
with open(self.original_schema_file_path, "r") as f:
original_schema = commentjson.load(f)
original_schema = json5.load(f)
with open(os.path.join(self.custom_dir, "invalid.zowe.schema.json"), "w") as f:
commentjson.dump(original_schema, f)
json5.dump(original_schema, f)
self.setUpCreds(
custom_file_path,
{
Expand All @@ -555,15 +555,15 @@ def test_profile_loading_with_invalid_schema_internet_URI(self, get_pass_func):
with self.assertRaises(SchemaError):
custom_file_path = os.path.join(self.custom_dir, "zowe.config.json")
with open(self.original_file_path, "r") as f:
original_config = commentjson.load(f)
original_config = json5.load(f)
original_config["$schema"] = "invalidUri.zowe.schema.json"
with open(os.path.join(self.custom_dir, "invalidUri.zowe.config.json"), "w") as f:
commentjson.dump(original_config, f)
json5.dump(original_config, f)
with open(self.original_schema_file_path, "r") as f:
original_schema = commentjson.load(f)
original_schema = json5.load(f)
original_schema["type"] = "invalid"
with open(os.path.join(self.custom_dir, "invalidUri.zowe.schema.json"), "w") as f:
commentjson.dump(original_schema, f)
json5.dump(original_schema, f)

self.setUpCreds(
custom_file_path,
Expand Down Expand Up @@ -840,4 +840,4 @@ def test_find_profile_with_non_dict_value():

valid_result = config_file.find_profile("valid_profile", profiles)
assert valid_result is not None
assert valid_result["type"] == "zosmf"
assert valid_result["type"] == "zosmf"