Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding logger modules #268

Merged
merged 23 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 12 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
11 changes: 10 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,14 @@
"python.testing.pytestArgs": ["tests"],
"python.testing.pytestEnabled": true,
"python.testing.unittestEnabled": false,
"rust-analyzer.linkedProjects": ["./src/secrets/Cargo.toml"],
"rust-analyzer.linkedProjects": [
"./src/secrets/Cargo.toml"
],
"python.analysis.extraPaths": [
"./src/core",
"./src/zos_console",
"./src/zos_files",
"./src/zos_jobs",
"./src/zosmf"
t1m0thyj marked this conversation as resolved.
Show resolved Hide resolved
],
}
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

All notable changes to the Zowe Client Python SDK will be documented in this file.

## Recent Changes

### Enhancements

- Added logger class to core SDK [#185] https://github.com/zowe/zowe-client-python-sdk/issues/185
pem70 marked this conversation as resolved.
Show resolved Hide resolved

## `1.0.0-dev15`

### Bug Fixes
Expand Down
1 change: 1 addition & 0 deletions src/core/zowe/core_for_zowe_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
from .session import Session
from .session_constants import *
from .zosmf_profile import ZosmfProfile
from .logger import Log
39 changes: 21 additions & 18 deletions src/core/zowe/core_for_zowe_sdk/config_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import commentjson
import requests

import logging

from .credential_manager import CredentialManager
from .custom_warnings import ProfileNotFoundWarning, ProfileParsingWarning
from .exceptions import ProfileNotFound
Expand Down Expand Up @@ -71,6 +73,8 @@
jsonc: Optional[dict] = None
_missing_secure_props: list = field(default_factory=list)

__logger = logging.getLogger(__name__)

@property
def filename(self) -> str:
if self.type == TEAM_CONFIG:
Expand All @@ -92,20 +96,18 @@
def location(self) -> Optional[str]:
return self._location

@property
def schema_path(self) -> Optional[str]:
return self.schema_property

@location.setter
def location(self, dirname: str) -> None:
if os.path.isdir(dirname):
self._location = dirname
else:
self.__logger.error(f"given path {dirname} is not valid")
raise FileNotFoundError(f"given path {dirname} is not valid")

def init_from_file(
self,
validate_schema: Optional[bool] = True,
suppress_config_file_warnings: Optional[bool] = True,
) -> None:
"""
Initializes the class variable after
Expand All @@ -118,7 +120,9 @@
pass

if self.filepath is None or not os.path.isfile(self.filepath):
warnings.warn(f"Config file does not exist at {self.filepath}")
if not suppress_config_file_warnings:
t1m0thyj marked this conversation as resolved.
Show resolved Hide resolved
self.__logger.warning(f"Config file does not exist at {self.filepath}")
warnings.warn(f"Config file does not exist at {self.filepath}")

Check warning on line 125 in src/core/zowe/core_for_zowe_sdk/config_file.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/config_file.py#L124-L125

Added lines #L124 - L125 were not covered by tests
return

with open(self.filepath, encoding="UTF-8", mode="r") as fileobj:
Expand All @@ -129,7 +133,7 @@
self.defaults = profile_jsonc.get("defaults", {})
self.jsonc = profile_jsonc

if self.schema_property and validate_schema:
if validate_schema:
self.validate_schema()

CredentialManager.load_secure_props()
Expand All @@ -143,16 +147,11 @@
-------
file_path to the $schema property
"""

path_schema_json = None

path_schema_json = self.schema_path
if path_schema_json is None: # check if the $schema property is not defined
warnings.warn(f"$schema property could not found")

# validate the $schema property
if path_schema_json:
validate_config_json(self.jsonc, path_schema_json, cwd=self.location)
if self.schema_property is None: # check if the $schema property is not defined
self.__logger.warning(f"Could not find $schema property")
warnings.warn(f"Could not find $schema property")
else:
validate_config_json(self.jsonc, self.schema_property, cwd=self.location)

def schema_list(self, cwd=None) -> list:
"""
Expand Down Expand Up @@ -213,6 +212,7 @@
self.init_from_file(validate_schema)

if profile_name is None and profile_type is None:
self.__logger.error(f"Failed to load profile '{profile_name}' because Could not find profile as both profile_name and profile_type is not set")
pem70 marked this conversation as resolved.
Show resolved Hide resolved
raise ProfileNotFound(
profile_name=profile_name,
error_msg="Could not find profile as both profile_name and profile_type is not set.",
Expand Down Expand Up @@ -250,7 +250,6 @@
break

current_dir = os.path.dirname(current_dir)

raise FileNotFoundError(f"Could not find the file {self.filename}")

def get_profilename_from_profiletype(self, profile_type: str) -> str:
Expand All @@ -268,8 +267,9 @@
try:
profilename = self.defaults[profile_type]
except KeyError:
self.__logger.warn(f"Given profile type '{profile_type}' has no default profile name")
warnings.warn(
f"Given profile type '{profile_type}' has no default profilename",
f"Given profile type '{profile_type}' has no default profile name",
ProfileParsingWarning,
)
else:
Expand All @@ -282,12 +282,14 @@
if profile_type == temp_profile_type:
return key
except KeyError:
self.__logger.warning(f"Profile '{key}' has no type attribute")
warnings.warn(
f"Profile '{key}' has no type attribute",
ProfileParsingWarning,
)

# if no profile with matching type found, we raise an exception
self.__logger.error(f"No profile with matching profile_type '{profile_type}' found")
raise ProfileNotFound(
profile_name=profile_type,
error_msg=f"No profile with matching profile_type '{profile_type}' found",
Expand Down Expand Up @@ -334,6 +336,7 @@
props = {**profile.get("properties", {}), **props}
secure_fields.extend(profile.get("secure", []))
else:
self.__logger.warning(f"Profile {profile_name} not found")
warnings.warn(f"Profile {profile_name} not found", ProfileNotFoundWarning)
lst.pop()

Expand Down
5 changes: 5 additions & 0 deletions src/core/zowe/core_for_zowe_sdk/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
Copyright Contributors to the Zowe Project.
"""

from .exceptions import MissingConnectionArgs
import logging


class ApiConnection:
Expand All @@ -28,8 +30,11 @@ class ApiConnection:
"""

def __init__(self, host_url, user, password, ssl_verification=True):
logger = logging.getLogger(__name__)

"""Construct an ApiConnection object."""
if not host_url or not user or not password:
logger.error("Missing connection argument")
raise MissingConnectionArgs()

self.host_url = host_url
Expand Down
9 changes: 8 additions & 1 deletion src/core/zowe/core_for_zowe_sdk/credential_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@

Copyright Contributors to the Zowe Project.
"""

import base64
import sys
from typing import Optional

import commentjson

import logging

from .constants import constants
from .exceptions import SecureProfileLoadFailed

Expand All @@ -27,6 +30,7 @@

class CredentialManager:
secure_props = {}
__logger = logging.getLogger(__name__)

@staticmethod
def load_secure_props() -> None:
Expand All @@ -49,6 +53,7 @@ def load_secure_props() -> None:
return

except Exception as exc:
CredentialManager.__logger.error(f"Fail to load secure profile {constants['ZoweServiceName']}")
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
CredentialManager.__logger.error(f"Fail to load secure profile {constants['ZoweServiceName']}")
CredentialManager.__logger.error(f"Failed to load secure profile {constants['ZoweServiceName']}")

raise SecureProfileLoadFailed(constants["ZoweServiceName"], error_msg=str(exc)) from exc

secure_config: str
Expand All @@ -75,7 +80,9 @@ def save_secure_props() -> None:
if sys.platform == "win32":
# Delete the existing credential
CredentialManager._delete_credential(constants["ZoweServiceName"], constants["ZoweAccountName"])
CredentialManager._set_credential(constants["ZoweServiceName"], constants["ZoweAccountName"], encoded_credential)
CredentialManager._set_credential(
constants["ZoweServiceName"], constants["ZoweAccountName"], encoded_credential
)

@staticmethod
def _get_credential(service_name: str, account_name: str) -> Optional[str]:
Expand Down
21 changes: 21 additions & 0 deletions src/core/zowe/core_for_zowe_sdk/logger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import logging
import os

class Log:
"""root logger setup and a funtion to customize logger level"""
pem70 marked this conversation as resolved.
Show resolved Hide resolved

dirname = os.path.join(os.path.expanduser("~"), ".zowe/logs")
t1m0thyj marked this conversation as resolved.
Show resolved Hide resolved

if not os.path.isdir(dirname):
os.makedirs(dirname)
pem70 marked this conversation as resolved.
Show resolved Hide resolved

logging.basicConfig(
filename=os.path.join(dirname, "python_sdk_logs.log"),
level=logging.INFO,
format="[%(asctime)s] [%(levelname)s] [%(name)s] - %(message)s",
datefmt="%m/%d/%Y %I:%M:%S %p",
)
t1m0thyj marked this conversation as resolved.
Show resolved Hide resolved

@staticmethod
def setLoggerLevel(level: int):
logging.root.setLevel(level)
pem70 marked this conversation as resolved.
Show resolved Hide resolved
25 changes: 23 additions & 2 deletions src/core/zowe/core_for_zowe_sdk/profile_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import warnings
from copy import deepcopy
from typing import Optional
import logging

import jsonschema
from deepmerge import always_merger
Expand Down Expand Up @@ -57,10 +58,13 @@
self.project_config = ConfigFile(type=TEAM_CONFIG, name=appname)
self.project_user_config = ConfigFile(type=USER_CONFIG, name=appname)

self.__logger = logging.getLogger(__name__)

self.global_config = ConfigFile(type=TEAM_CONFIG, name=GLOBAL_CONFIG_NAME)
try:
self.global_config.location = GLOBAL_CONFIG_LOCATION
except Exception:
self.__logger.warning("Could not find Global Config Directory")
warnings.warn(
"Could not find Global Config Directory, please provide one.",
ConfigNotFoundWarning,
Expand All @@ -70,6 +74,7 @@
try:
self.global_user_config.location = GLOBAL_CONFIG_LOCATION
except Exception:
self.__logger.warning("Could not find Global User Config Directory")
warnings.warn(
"Could not find Global User Config Directory, please provide one.",
ConfigNotFoundWarning,
Expand Down Expand Up @@ -172,38 +177,48 @@
NamedTuple (data, name, secure_props_not_found)
"""

logger = logging.getLogger(__name__)

cfg_profile = Profile()
try:
cfg_profile = cfg.get_profile(
profile_name=profile_name, profile_type=profile_type, validate_schema=validate_schema
)
except jsonschema.exceptions.ValidationError as exc:
logger.error(f"Instance was invalid under the provided $schema property, {exc}")

Check warning on line 188 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L188

Added line #L188 was not covered by tests
raise jsonschema.exceptions.ValidationError(
f"Instance was invalid under the provided $schema property, {exc}"
)
except jsonschema.exceptions.SchemaError as exc:
logger.error(f"The provided schema is invalid, {exc}")

Check warning on line 193 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L193

Added line #L193 was not covered by tests
raise jsonschema.exceptions.SchemaError(f"The provided schema is invalid, {exc}")
except jsonschema.exceptions.UndefinedTypeCheck as exc:
logger.error(f"A type checker was asked to check a type it did not have registered, {exc}")

Check warning on line 196 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L196

Added line #L196 was not covered by tests
raise jsonschema.exceptions.UndefinedTypeCheck(
f"A type checker was asked to check a type it did not have registered, {exc}"
)
except jsonschema.exceptions.UnknownType as exc:
logger.error(f"Unknown type is found in schema_json, exc")

Check warning on line 201 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L201

Added line #L201 was not covered by tests
pem70 marked this conversation as resolved.
Show resolved Hide resolved
raise jsonschema.exceptions.UnknownType(f"Unknown type is found in schema_json, exc")
except jsonschema.exceptions.FormatError as exc:
logger.error(f"Validating a format config_json failed for schema_json, {exc}")

Check warning on line 204 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L204

Added line #L204 was not covered by tests
raise jsonschema.exceptions.FormatError(f"Validating a format config_json failed for schema_json, {exc}")
except ProfileNotFound:
if profile_name:
logger.warning(f"Profile '{profile_name}' not found in file '{cfg.filename}'")

Check warning on line 208 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L208

Added line #L208 was not covered by tests
warnings.warn(
f"Profile '{profile_name}' not found in file '{cfg.filename}', returning empty profile instead.",
ProfileNotFoundWarning,
)
else:
logger.warning(f"Profile of type '{profile_type}' not found in file '{cfg.filename}'")

Check warning on line 214 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L214

Added line #L214 was not covered by tests
warnings.warn(
f"Profile of type '{profile_type}' not found in file '{cfg.filename}', returning empty profile"
f" instead.",
ProfileNotFoundWarning,
)
except Exception as exc:
logger.warning(f"Could not load '{cfg.filename}' at '{cfg.filepath}'" f"because {type(exc).__name__}'{exc}'")

Check warning on line 221 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L221

Added line #L221 was not covered by tests
warnings.warn(
f"Could not load '{cfg.filename}' at '{cfg.filepath}'" f"because {type(exc).__name__}'{exc}'.",
ConfigNotFoundWarning,
Expand All @@ -218,6 +233,7 @@
check_missing_props: bool = True,
validate_schema: Optional[bool] = True,
override_with_env: Optional[bool] = False,
suppress_config_file_warnings: Optional[bool] = True,
) -> dict:
"""Load connection details from a team config profile.
Returns
Expand All @@ -236,7 +252,9 @@
If `profile_type` is not base, then we will load properties from both
`profile_type` and base profiles and merge them together.
"""

if profile_name is None and profile_type is None:
self.__logger.error(f"Failed to load profile as both profile_name and profile_type are not set")

Check warning on line 257 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L257

Added line #L257 was not covered by tests
raise ProfileNotFound(
profile_name=profile_name,
error_msg="Could not find profile as both profile_name and profile_type is not set.",
Expand All @@ -254,12 +272,13 @@
cfg_name = None
cfg_schema = None
cfg_schema_dir = None

for cfg_layer in (self.project_user_config, self.project_config, self.global_user_config, self.global_config):
if cfg_layer.profiles is None:
try:
cfg_layer.init_from_file(validate_schema)
cfg_layer.init_from_file(validate_schema, suppress_config_file_warnings)
except SecureProfileLoadFailed:
self.__logger.warning(f"Could not load secure properties for {cfg_layer.filepath}")
warnings.warn(
f"Could not load secure properties for {cfg_layer.filepath}",
SecurePropsNotFoundWarning,
Expand Down Expand Up @@ -314,6 +333,7 @@
missing_props.add(item)

if len(missing_props) > 0:
self.__logger.error(f"Failed to load secure values: {missing_props}")

Check warning on line 336 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L336

Added line #L336 was not covered by tests
raise SecureValuesNotFound(values=missing_props)

warnings.resetwarnings()
Expand Down Expand Up @@ -366,6 +386,7 @@
highest_layer = layer

if highest_layer is None:
self.__logger.error(f"Could not find a valid layer for {json_path}")

Check warning on line 389 in src/core/zowe/core_for_zowe_sdk/profile_manager.py

View check run for this annotation

Codecov / codecov/patch

src/core/zowe/core_for_zowe_sdk/profile_manager.py#L389

Added line #L389 was not covered by tests
raise FileNotFoundError(f"Could not find a valid layer for {json_path}")

return highest_layer
Expand Down
Loading
Loading