Skip to content

Commit

Permalink
Merge pull request #268 from zowe/logger
Browse files Browse the repository at this point in the history
Adding logger modules
  • Loading branch information
traeok authored May 31, 2024
2 parents d582a88 + 5ecbeab commit 5816aab
Show file tree
Hide file tree
Showing 19 changed files with 311 additions and 73 deletions.
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"
],
}
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)

## `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
40 changes: 22 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,11 +21,14 @@
import commentjson
import requests

import logging

from .credential_manager import CredentialManager
from .custom_warnings import ProfileNotFoundWarning, ProfileParsingWarning
from .exceptions import ProfileNotFound
from .profile_constants import GLOBAL_CONFIG_NAME, TEAM_CONFIG, USER_CONFIG
from .validators import validate_config_json
from .logger import Log

HOME = os.path.expanduser("~")
GLOBAL_CONFIG_LOCATION = os.path.join(HOME, ".zowe")
Expand Down Expand Up @@ -71,6 +74,8 @@ class ConfigFile:
jsonc: Optional[dict] = None
_missing_secure_props: list = field(default_factory=list)

__logger = Log.registerLogger(__name__)

@property
def filename(self) -> str:
if self.type == TEAM_CONFIG:
Expand All @@ -92,20 +97,18 @@ def filepath(self) -> Optional[str]:
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 +121,9 @@ def init_from_file(
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:
self.__logger.warning(f"Config file does not exist at {self.filepath}")
warnings.warn(f"Config file does not exist at {self.filepath}")
return

with open(self.filepath, encoding="UTF-8", mode="r") as fileobj:
Expand All @@ -129,7 +134,7 @@ def init_from_file(
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 +148,11 @@ def validate_schema(self) -> None:
-------
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 +213,7 @@ def get_profile(
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 and profile_type were not provided.")
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 +251,6 @@ def autodiscover_config_dir(self) -> None:
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 +268,9 @@ def get_profilename_from_profiletype(self, profile_type: str) -> str:
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 +283,14 @@ def get_profilename_from_profiletype(self, profile_type: str) -> str:
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 +337,7 @@ def load_profile_properties(self, profile_name: str) -> dict:
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
6 changes: 6 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,10 @@
Copyright Contributors to the Zowe Project.
"""

from .exceptions import MissingConnectionArgs
from .logger import Log
import logging


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

def __init__(self, host_url, user, password, ssl_verification=True):
logger = Log.registerLogger(__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
10 changes: 9 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,14 +9,18 @@
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
from .logger import Log

HAS_KEYRING = True
try:
Expand All @@ -27,6 +31,7 @@

class CredentialManager:
secure_props = {}
__logger = Log.registerLogger(__name__)

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

except Exception as exc:
CredentialManager.__logger.error(f"Fail to load secure profile {constants['ZoweServiceName']}")
raise SecureProfileLoadFailed(constants["ZoweServiceName"], error_msg=str(exc)) from exc

secure_config: str
Expand All @@ -75,7 +81,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
29 changes: 29 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,29 @@
import logging
import os

class Log:
"""root logger setup and a function to customize logger level"""

dirname = os.path.join(os.path.expanduser("~"), ".zowe/logs")

os.makedirs(dirname, exist_ok=True)

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",
)

loggers = []
@staticmethod
def registerLogger(name: str):
"""A function to get Logger and registered for level setting"""
logger = logging.getLogger(name)
Log.loggers.append(logger)
return logger

@staticmethod
def setLoggerLevel(level: int):
for logger in Log.loggers:
logger.setLevel(level)
Loading

0 comments on commit 5816aab

Please sign in to comment.