diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index edeb1307..6ac66f87 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -67,4 +67,4 @@ This project follows the [PEP 8](https://www.python.org/dev/peps/pep-0008/) styl This project also uses `flake8` for code linting. Make sure to run `flake8` on your code before submitting a pull request. -We recommend using `black` as a code formatter. Please format your code using `black` before creating a pull request. +We recommend using `black` and `isort` as code formatters. Please format your code using these tools before creating a pull request. diff --git a/docs/source/_ext/zowe_autodoc.py b/docs/source/_ext/zowe_autodoc.py index 5f9e9d9a..8472d91a 100644 --- a/docs/source/_ext/zowe_autodoc.py +++ b/docs/source/_ext/zowe_autodoc.py @@ -52,16 +52,15 @@ def main(): py_name = os.path.basename(py_file) if py_name == "__init__.py": continue - with open(py_file, 'r', encoding="utf-8") as f: + with open(py_file, "r", encoding="utf-8") as f: py_contents = f.read() class_names = re.findall(r"^class (\w+)\b", py_contents, re.MULTILINE) if len(class_names) == 1: rst_name = f"{py_name[:-3]}.rst" - rst_contents = render_template(CLASS_TEMPLATE, { - "fullname": f"{sdk_name}.{pkg_name}.{class_names[0]}", - "header": class_names[0] - }) - with open(f"docs/source/classes/{sdk_name}/{rst_name}", 'w', encoding="utf-8") as f: + rst_contents = render_template( + CLASS_TEMPLATE, {"fullname": f"{sdk_name}.{pkg_name}.{class_names[0]}", "header": class_names[0]} + ) + with open(f"docs/source/classes/{sdk_name}/{rst_name}", "w", encoding="utf-8") as f: f.write(rst_contents) rst_names.append(rst_name) elif len(class_names) > 1: @@ -70,39 +69,44 @@ def main(): child_rst_names = [] for class_name in sorted(class_names): rst_name = f"{class_name.lower()}.rst" - rst_contents = render_template(CLASS_TEMPLATE, { - "fullname": f"{sdk_name}.{pkg_name}.{module_name}.{class_name}", - "header": class_name - }) - with open(f"docs/source/classes/{sdk_name}/{module_name}/{rst_name}", 'w', encoding="utf-8") as f: + rst_contents = render_template( + CLASS_TEMPLATE, + {"fullname": f"{sdk_name}.{pkg_name}.{module_name}.{class_name}", "header": class_name}, + ) + with open(f"docs/source/classes/{sdk_name}/{module_name}/{rst_name}", "w", encoding="utf-8") as f: f.write(rst_contents) child_rst_names.append(rst_name) rst_name = f"{module_name}/index.rst" - rst_contents = render_template(INDEX_TEMPLATE, { - "filelist": "\n ".join(name[:-4] for name in child_rst_names), - "header": f"{module_name.replace('_', ' ').title()} classes", - "maxdepth": 2 - }) - with open(f"docs/source/classes/{sdk_name}/{rst_name}", 'w', encoding="utf-8") as f: + rst_contents = render_template( + INDEX_TEMPLATE, + { + "filelist": "\n ".join(name[:-4] for name in child_rst_names), + "header": f"{module_name.replace('_', ' ').title()} classes", + "maxdepth": 2, + }, + ) + with open(f"docs/source/classes/{sdk_name}/{rst_name}", "w", encoding="utf-8") as f: f.write(rst_contents) parent_rst_names.append(rst_name) - rst_contents = render_template(INDEX_TEMPLATE, { - "filelist": "\n ".join(name[:-4] for name in rst_names + parent_rst_names), - "header": pkg_name, - "maxdepth": 2 - }) - with open(f"docs/source/classes/{sdk_name}/index.rst", 'w', encoding="utf-8") as f: + rst_contents = render_template( + INDEX_TEMPLATE, + { + "filelist": "\n ".join(name[:-4] for name in rst_names + parent_rst_names), + "header": pkg_name, + "maxdepth": 2, + }, + ) + with open(f"docs/source/classes/{sdk_name}/index.rst", "w", encoding="utf-8") as f: f.write(rst_contents) sdk_names.append(sdk_name) print("done") - rst_contents = render_template(INDEX_TEMPLATE, { - "filelist": "\n ".join(f"{name}/index" for name in sdk_names), - "header": "Classes", - "maxdepth": 3 - }) - with open(f"docs/source/classes/index.rst", 'w', encoding="utf-8") as f: + rst_contents = render_template( + INDEX_TEMPLATE, + {"filelist": "\n ".join(f"{name}/index" for name in sdk_names), "header": "Classes", "maxdepth": 3}, + ) + with open(f"docs/source/classes/index.rst", "w", encoding="utf-8") as f: f.write(rst_contents) diff --git a/docs/source/conf.py b/docs/source/conf.py index 2781f3ef..58d5df40 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -13,16 +13,16 @@ import os import sys from datetime import date -sys.path.insert(0, os.path.abspath('../../src')) -sys.path.append(os.path.abspath('./_ext')) -from _version import __version__ +sys.path.insert(0, os.path.abspath("../../src")) +sys.path.append(os.path.abspath("./_ext")) +from _version import __version__ # -- Project information ----------------------------------------------------- -project = 'Zowe Client Python SDK' -copyright = f'{date.today().year}, Contributors to the Zowe Project' -author = 'Contributors to the Zowe Project' +project = "Zowe Client Python SDK" +copyright = f"{date.today().year}, Contributors to the Zowe Project" +author = "Contributors to the Zowe Project" # The full version, including alpha/beta/rc tags release = __version__ @@ -33,12 +33,14 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.coverage', - 'sphinx.ext.napoleon', - 'sphinx_rtd_theme', - 'sphinxcontrib.spelling', - 'zowe_autodoc'] +extensions = [ + "sphinx.ext.autodoc", + "sphinx.ext.coverage", + "sphinx.ext.napoleon", + "sphinx_rtd_theme", + "sphinxcontrib.spelling", + "zowe_autodoc", +] # Napoleon options napoleon_google_docstring = False @@ -56,7 +58,7 @@ # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -69,11 +71,11 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] -html_logo = '_static/zowe-white.png' +html_logo = "_static/zowe-white.png" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..85c3b073 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,5 @@ +[tool.black] +line-length = 120 + +[tool.isort] +profile = "black" diff --git a/requirements.txt b/requirements.txt index 47cf70ee..12437b1a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +black certifi==2023.7.22 chardet==4.0.0 colorama==0.4.4 @@ -7,6 +8,7 @@ deepmerge==1.1.0 flake8==3.8.4 idna==2.10 importlib-metadata==3.6.0 +isort jsonschema==4.17.3 keyring lxml==4.9.3 @@ -28,7 +30,6 @@ Unidecode==1.2.0 urllib3==1.26.5 wheel zipp==3.4.0 -black -e ./src/core -e ./src/zos_console -e ./src/zos_files diff --git a/samples/SampleConsole.py b/samples/SampleConsole.py index cecf9279..55581152 100644 --- a/samples/SampleConsole.py +++ b/samples/SampleConsole.py @@ -2,16 +2,11 @@ # Change below to the name of your zosmf profile -connection = { - "plugin_profile": "xxxx" -} +connection = {"plugin_profile": "xxxx"} my_console = Console(connection) -command = 'D IPLINFO' +command = "D IPLINFO" command_result = my_console.issue_command(command) -command_output = command_result['cmd-response'].replace('\r','\n') +command_output = command_result["cmd-response"].replace("\r", "\n") print(f"Command: {command} \n Output: \n\n{command_output}") - - - \ No newline at end of file diff --git a/samples/SampleFiles.py b/samples/SampleFiles.py index d76d5583..7da6912c 100644 --- a/samples/SampleFiles.py +++ b/samples/SampleFiles.py @@ -2,24 +2,22 @@ # Change below to the name of your zosmf profile -connection = { - "plugin_profile": "xxxx" -} +connection = {"plugin_profile": "xxxx"} # ----------------------------------------------------- # print list of zos datasets -# ----------------------------------------------------- +# ----------------------------------------------------- print("...SYS1 datasets\n") my_files = Files(connection) my_dsn_list = my_files.list_dsn("SYS1.**.*") -datasets = my_dsn_list['items'] +datasets = my_dsn_list["items"] for ds in datasets: - print(ds['dsname']) + print(ds["dsname"]) # ----------------------------------------------------- # Now try the uss side... Not in the SDK in GitHub yet -# ----------------------------------------------------- +# ----------------------------------------------------- print("...files in /etc\n") my_file_list = my_files.list_files("/etc") files = my_file_list["items"] @@ -28,8 +26,7 @@ # ----------------------------------------------------- # Get the content of one of the files. -# ----------------------------------------------------- +# ----------------------------------------------------- print("...content of a file\n") my_file_content = my_files.get_file_content("/z/tm891807/file.txt") print(my_file_content["response"]) - diff --git a/samples/SampleJobs.py b/samples/SampleJobs.py index c2d2a2b5..95960fa9 100644 --- a/samples/SampleJobs.py +++ b/samples/SampleJobs.py @@ -1,48 +1,46 @@ -from zowe.zos_jobs_for_zowe_sdk import Jobs -import time import os +import time +from zowe.zos_jobs_for_zowe_sdk import Jobs # ----------------------------------------------------- # Test drive the jobs SDK with jcl from a file -# ----------------------------------------------------- +# ----------------------------------------------------- # Change below to the name of your zosmf profile -connection = { - "plugin_profile": "xxxx" -} +connection = {"plugin_profile": "xxxx"} print("...Submit a sleeper job\n") my_jobs = Jobs(connection) job = my_jobs.submit_from_local_file("jcl\sleep.jcl") -job_name = job['jobname'] -job_id = job['jobid'] +job_name = job["jobname"] +job_id = job["jobid"] print(f"Job {job_name} ID {job_id} submitted") # ----------------------------------------------------- # Wait until the job completes -# ----------------------------------------------------- +# ----------------------------------------------------- boolJobNotDone = True while boolJobNotDone: - status = my_jobs.get_job_status(job_name,job_id) - job_status = status['status'] - if job_status != 'OUTPUT': + status = my_jobs.get_job_status(job_name, job_id) + job_status = status["status"] + if job_status != "OUTPUT": print(f"Status {job_status}") time.sleep(5) else: boolJobNotDone = False # ----------------------------------------------------- -# Get the return code -# ----------------------------------------------------- -job_retcode = status['retcode'] -job_correlator = status['job-correlator'] +# Get the return code +# ----------------------------------------------------- +job_retcode = status["retcode"] +job_correlator = status["job-correlator"] print(f"Job {job_name} ID {job_id} ended with {job_retcode}") # ----------------------------------------------------- # Get all the spool files and dump them in -# ----------------------------------------------------- -output_dir = './output' -my_jobs.get_job_output_as_files(status,output_dir) +# ----------------------------------------------------- +output_dir = "./output" +my_jobs.get_job_output_as_files(status, output_dir) diff --git a/src/core/setup.py b/src/core/setup.py index 81a0a0d9..aed4a73a 100644 --- a/src/core/setup.py +++ b/src/core/setup.py @@ -1,5 +1,7 @@ import sys -from setuptools import setup, find_namespace_packages + +from setuptools import find_namespace_packages, setup + sys.path.append("..") from _version import __version__ diff --git a/src/core/zowe/core_for_zowe_sdk/__init__.py b/src/core/zowe/core_for_zowe_sdk/__init__.py index fb740b4e..615b966f 100644 --- a/src/core/zowe/core_for_zowe_sdk/__init__.py +++ b/src/core/zowe/core_for_zowe_sdk/__init__.py @@ -2,14 +2,14 @@ Zowe Python SDK - Core package """ +from .config_file import ConfigFile from .connection import ApiConnection from .constants import constants +from .credential_manager import CredentialManager from .exceptions import * from .profile_manager import ProfileManager from .request_handler import RequestHandler from .sdk_api import SdkApi -from .session_constants import * from .session import Session +from .session_constants import * from .zosmf_profile import ZosmfProfile -from .config_file import ConfigFile -from .credential_manager import CredentialManager diff --git a/src/core/zowe/core_for_zowe_sdk/config_file.py b/src/core/zowe/core_for_zowe_sdk/config_file.py index f5127d48..d1ef4a25 100644 --- a/src/core/zowe/core_for_zowe_sdk/config_file.py +++ b/src/core/zowe/core_for_zowe_sdk/config_file.py @@ -10,37 +10,27 @@ Copyright Contributors to the Zowe Project. """ +import json import os.path import re -import json -import requests import warnings from copy import deepcopy from dataclasses import dataclass, field -from typing import Optional, NamedTuple +from typing import NamedTuple, Optional import commentjson +import requests from .constants import constants -from .validators import validate_config_json from .credential_manager import CredentialManager -from .custom_warnings import ( - ProfileNotFoundWarning, - ProfileParsingWarning, -) +from .custom_warnings import ProfileNotFoundWarning, ProfileParsingWarning from .exceptions import ProfileNotFound -from .profile_constants import ( - GLOBAL_CONFIG_NAME, - TEAM_CONFIG, - USER_CONFIG, -) - +from .profile_constants import GLOBAL_CONFIG_NAME, TEAM_CONFIG, USER_CONFIG +from .validators import validate_config_json HOME = os.path.expanduser("~") GLOBAL_CONFIG_LOCATION = os.path.join(HOME, ".zowe") -GLOBAL_CONFIG_PATH = os.path.join( - GLOBAL_CONFIG_LOCATION, f"{GLOBAL_CONFIG_NAME}.config.json" -) +GLOBAL_CONFIG_PATH = os.path.join(GLOBAL_CONFIG_LOCATION, f"{GLOBAL_CONFIG_NAME}.config.json") CURRENT_DIR = os.getcwd() # Profile datatype is used by ConfigFile to return Profile Data along with @@ -146,9 +136,7 @@ def init_from_file( CredentialManager.load_secure_props() self.__load_secure_properties() - def validate_schema( - self - ) -> None: + def validate_schema(self) -> None: """ Get the $schema_property from the config and load the schema @@ -160,14 +148,12 @@ def validate_schema( 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" - ) + 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) + validate_config_json(self.jsonc, path_schema_json, cwd=self.location) def schema_list( self, @@ -201,10 +187,10 @@ def schema_list( else: return [] - profile_props:dict = {} + profile_props: dict = {} schema_json = dict(schema_json) - for props in schema_json['properties']['profiles']['patternProperties']["^\\S*$"]["allOf"]: + for props in schema_json["properties"]["profiles"]["patternProperties"]["^\\S*$"]["allOf"]: props = props["then"] while "properties" in props: @@ -236,9 +222,7 @@ def get_profile( ) if profile_name is None: - profile_name = self.get_profilename_from_profiletype( - profile_type=profile_type - ) + profile_name = self.get_profilename_from_profiletype(profile_type=profile_type) props: dict = self.load_profile_properties(profile_name=profile_name) return Profile(props, profile_name, self._missing_secure_props) @@ -295,7 +279,7 @@ def get_profilename_from_profiletype(self, profile_type: str) -> str: return profilename # iterate through the profiles and check if profile is found - for (key, value) in self.profiles.items(): + for key, value in self.profiles.items(): try: temp_profile_type = value["type"] if profile_type == temp_profile_type: @@ -353,10 +337,7 @@ def load_profile_properties(self, profile_name: str) -> dict: props = {**profile.get("properties", {}), **props} secure_fields.extend(profile.get("secure", [])) else: - warnings.warn( - f"Profile {profile_name} not found", - ProfileNotFoundWarning - ) + warnings.warn(f"Profile {profile_name} not found", ProfileNotFoundWarning) lst.pop() return props @@ -387,7 +368,9 @@ def __extract_secure_properties(self, profiles_obj, json_path="profiles"): for key, value in profiles_obj.items(): for property_name in value.get("secure", []): if property_name in value.get("properties", {}): - secure_props[f"{json_path}.{key}.properties.{property_name}"] = value["properties"].pop(property_name) + secure_props[f"{json_path}.{key}.properties.{property_name}"] = value["properties"].pop( + property_name + ) if value.get("profiles"): secure_props.update(self.__extract_secure_properties(value["profiles"], f"{json_path}.{key}.profiles")) return secure_props @@ -467,7 +450,7 @@ def set_profile(self, profile_path: str, profile_data: dict) -> None: if "secure" in profile_data: # Checking if the profile has a 'secure' field with values secure_fields = profile_data["secure"] - current_profile = self.find_profile(profile_name,self.profiles) or {} + current_profile = self.find_profile(profile_name, self.profiles) or {} existing_secure_fields = current_profile.get("secure", []) new_secure_fields = [field for field in secure_fields if field not in existing_secure_fields] @@ -480,7 +463,6 @@ def set_profile(self, profile_path: str, profile_data: dict) -> None: } self.__set_or_create_nested_profile(profile_name, profile_data) - def save(self, update_secure_props=True): """ Save the config file to disk. and secure props to vault @@ -496,13 +478,12 @@ def save(self, update_secure_props=True): profiles_temp = deepcopy(self.profiles) secure_props = self.__extract_secure_properties(profiles_temp) CredentialManager.secure_props[self.filepath] = secure_props - with open(self.filepath, 'w') as file: + with open(self.filepath, "w") as file: self.jsonc["profiles"] = profiles_temp commentjson.dump(self.jsonc, file, indent=4) if update_secure_props: CredentialManager.save_secure_props() - def get_profile_name_from_path(self, path: str) -> str: """ Get the name of the profile from the given path. @@ -515,4 +496,4 @@ def get_profile_path_from_name(self, short_path: str) -> str: """ Get the path of the profile from the given name. """ - return re.sub(r'(^|\.)', r'\1profiles.', short_path) + return re.sub(r"(^|\.)", r"\1profiles.", short_path) diff --git a/src/core/zowe/core_for_zowe_sdk/connection.py b/src/core/zowe/core_for_zowe_sdk/connection.py index 756d9138..fa97609c 100644 --- a/src/core/zowe/core_for_zowe_sdk/connection.py +++ b/src/core/zowe/core_for_zowe_sdk/connection.py @@ -27,11 +27,7 @@ class ApiConnection: ssl_verification: bool """ - def __init__(self, - host_url, - user, - password, - ssl_verification=True): + def __init__(self, host_url, user, password, ssl_verification=True): """Construct an ApiConnection object.""" if not host_url or not user or not password: raise MissingConnectionArgs() diff --git a/src/core/zowe/core_for_zowe_sdk/constants.py b/src/core/zowe/core_for_zowe_sdk/constants.py index b56b3da8..89767a59 100644 --- a/src/core/zowe/core_for_zowe_sdk/constants.py +++ b/src/core/zowe/core_for_zowe_sdk/constants.py @@ -16,5 +16,5 @@ "ZoweCredentialKey": "Zowe-Plugin", "ZoweServiceName": "Zowe", "ZoweAccountName": "secure_config_props", - "WIN32_CRED_MAX_STRING_LENGTH" : 2560 + "WIN32_CRED_MAX_STRING_LENGTH": 2560, } diff --git a/src/core/zowe/core_for_zowe_sdk/credential_manager.py b/src/core/zowe/core_for_zowe_sdk/credential_manager.py index de9de637..4969015b 100644 --- a/src/core/zowe/core_for_zowe_sdk/credential_manager.py +++ b/src/core/zowe/core_for_zowe_sdk/credential_manager.py @@ -9,16 +9,15 @@ Copyright Contributors to the Zowe Project. """ -import sys -import warnings import base64 import logging +import sys +import warnings from typing import Optional + import commentjson from zowe.core_for_zowe_sdk import constants -from zowe.core_for_zowe_sdk.exceptions import ( - SecureProfileLoadFailed - ) +from zowe.core_for_zowe_sdk.exceptions import SecureProfileLoadFailed HAS_KEYRING = True try: @@ -27,11 +26,10 @@ except ImportError: HAS_KEYRING = False + class CredentialManager: secure_props = {} - - @staticmethod def load_secure_props() -> None: """ @@ -54,9 +52,7 @@ def load_secure_props() -> None: return except Exception as exc: - raise SecureProfileLoadFailed( - constants["ZoweServiceName"], error_msg=str(exc) - ) from exc + raise SecureProfileLoadFailed(constants["ZoweServiceName"], error_msg=str(exc)) from exc secure_config: str secure_config = secret_value.encode() @@ -64,7 +60,6 @@ def load_secure_props() -> None: # update the secure props CredentialManager.secure_props = secure_config_json - @staticmethod def _retrieve_credential(service_name: str) -> Optional[str]: """ @@ -99,7 +94,7 @@ def _retrieve_credential(service_name: str) -> Optional[str]: if is_win32: try: - encoded_credential = encoded_credential.encode('utf-16le').decode() + encoded_credential = encoded_credential.encode("utf-16le").decode() except (UnicodeDecodeError, AttributeError): # The credential is not encoded in UTF-16 pass @@ -109,7 +104,6 @@ def _retrieve_credential(service_name: str) -> Optional[str]: return encoded_credential - @staticmethod def delete_credential(service_name: str, account_name: str) -> None: """ @@ -143,9 +137,8 @@ def delete_credential(service_name: str, account_name: str) -> None: break index += 1 - @staticmethod - def save_secure_props()-> None: + def save_secure_props() -> None: """ Set secure_props for the given config file Returns @@ -156,7 +149,7 @@ def save_secure_props()-> None: return service_name = constants["ZoweServiceName"] - credential = CredentialManager.secure_props + credential = CredentialManager.secure_props # Check if credential is a non-empty string if credential: is_win32 = sys.platform == "win32" @@ -165,21 +158,19 @@ def save_secure_props()-> None: if is_win32: service_name += "/" + constants["ZoweAccountName"] # Delete the existing credential - CredentialManager.delete_credential(service_name , constants["ZoweAccountName"]) + CredentialManager.delete_credential(service_name, constants["ZoweAccountName"]) # Check if the encoded credential exceeds the maximum length for win32 if is_win32 and len(encoded_credential) > constants["WIN32_CRED_MAX_STRING_LENGTH"]: # Split the encoded credential string into chunks of maximum length chunk_size = constants["WIN32_CRED_MAX_STRING_LENGTH"] - encoded_credential+='\0' - chunks = [encoded_credential[i: i + chunk_size] for i in range(0, len(encoded_credential), chunk_size)] + encoded_credential += "\0" + chunks = [encoded_credential[i : i + chunk_size] for i in range(0, len(encoded_credential), chunk_size)] # Set the individual chunks as separate keyring entries for index, chunk in enumerate(chunks, start=1): - password=(chunk + '\0' *(len(chunk)%2)).encode().decode('utf-16le') + password = (chunk + "\0" * (len(chunk) % 2)).encode().decode("utf-16le") field_name = f"{constants['ZoweAccountName']}-{index}" keyring.set_password(f"{service_name}-{index}", field_name, password) else: # Credential length is within the maximum limit or not on win32, set it as a single keyring entry - keyring.set_password( - service_name, constants["ZoweAccountName"], - encoded_credential) \ No newline at end of file + keyring.set_password(service_name, constants["ZoweAccountName"], encoded_credential) diff --git a/src/core/zowe/core_for_zowe_sdk/exceptions.py b/src/core/zowe/core_for_zowe_sdk/exceptions.py index e3d4b849..fdca6e94 100644 --- a/src/core/zowe/core_for_zowe_sdk/exceptions.py +++ b/src/core/zowe/core_for_zowe_sdk/exceptions.py @@ -39,9 +39,7 @@ def __init__(self, expected, received, request_output): The output from the request """ super().__init__( - "The status code from z/OSMF was {} it was expected {}. \n {}".format( - received, expected, request_output - ) + "The status code from z/OSMF was {} it was expected {}. \n {}".format(received, expected, request_output) ) @@ -57,11 +55,7 @@ def __init__(self, status_code, request_output): request_output The output from the request """ - super().__init__( - "HTTP Request has failed with status code {}. \n {}".format( - status_code, request_output - ) - ) + super().__init__("HTTP Request has failed with status code {}. \n {}".format(status_code, request_output)) class FileNotFound(Exception): @@ -100,11 +94,7 @@ def __init__(self, profile_name: str = "unknown", error_msg: str = "error"): error_msg The error message received while trying to load the profile """ - super().__init__( - "Failed to load secure profile '{}' because '{}'".format( - profile_name, error_msg - ) - ) + super().__init__("Failed to load secure profile '{}' because '{}'".format(profile_name, error_msg)) class ProfileNotFound(Exception): @@ -120,9 +110,7 @@ def __init__(self, profile_name: str = "unknown", error_msg: str = "error"): The error message received while trying to load the profile """ - super().__init__( - "Failed to load profile '{}' because '{}'".format(profile_name, error_msg) - ) + super().__init__("Failed to load profile '{}' because '{}'".format(profile_name, error_msg)) class SecureValuesNotFound(Exception): diff --git a/src/core/zowe/core_for_zowe_sdk/profile_manager.py b/src/core/zowe/core_for_zowe_sdk/profile_manager.py index d3da6882..841ade35 100644 --- a/src/core/zowe/core_for_zowe_sdk/profile_manager.py +++ b/src/core/zowe/core_for_zowe_sdk/profile_manager.py @@ -10,13 +10,14 @@ Copyright Contributors to the Zowe Project. """ -import os.path import os +import os.path import warnings -import jsonschema +from copy import deepcopy from typing import Optional + +import jsonschema from deepmerge import always_merger -from copy import deepcopy from .config_file import ConfigFile, Profile from .credential_manager import CredentialManager @@ -38,9 +39,7 @@ HOME = os.path.expanduser("~") GLOBAl_CONFIG_LOCATION = os.path.join(HOME, ".zowe") -GLOBAL_CONFIG_PATH = os.path.join( - GLOBAl_CONFIG_LOCATION, f"{GLOBAL_CONFIG_NAME}.config.json" -) +GLOBAL_CONFIG_PATH = os.path.join(GLOBAl_CONFIG_LOCATION, f"{GLOBAL_CONFIG_NAME}.config.json") CURRENT_DIR = os.getcwd() @@ -58,8 +57,7 @@ def __init__(self, appname: str = "zowe", show_warnings: bool = True): self.project_config = ConfigFile(type=TEAM_CONFIG, name=appname) self.project_user_config = ConfigFile(type=USER_CONFIG, name=appname) - self.global_config = ConfigFile( - type=TEAM_CONFIG, name=GLOBAL_CONFIG_NAME) + self.global_config = ConfigFile(type=TEAM_CONFIG, name=GLOBAL_CONFIG_NAME) try: self.global_config.location = GLOBAl_CONFIG_LOCATION except Exception: @@ -68,8 +66,7 @@ def __init__(self, appname: str = "zowe", show_warnings: bool = True): ConfigNotFoundWarning, ) - self.global_user_config = ConfigFile( - type=USER_CONFIG, name=GLOBAL_CONFIG_NAME) + self.global_user_config = ConfigFile(type=USER_CONFIG, name=GLOBAL_CONFIG_NAME) try: self.global_user_config.location = GLOBAl_CONFIG_LOCATION except Exception: @@ -138,24 +135,24 @@ def get_env( for var in list(os.environ.keys()): if var.startswith("ZOWE_OPT"): - env[var[len("ZOWE_OPT_"):].lower()] = os.environ.get(var) + env[var[len("ZOWE_OPT_") :].lower()] = os.environ.get(var) for k, v in env.items(): word = k.split("_") if len(word) > 1: - k = word[0]+word[1].capitalize() + k = word[0] + word[1].capitalize() else: k = word[0] if k in list(props.keys()): - if props[k]['type'] == "number": + if props[k]["type"] == "number": env_var[k] = int(v) - elif props[k]['type'] == "string": + elif props[k]["type"] == "string": env_var[k] = str(v) - elif props[k]['type'] == "boolean": + elif props[k]["type"] == "boolean": env_var[k] = bool(v) return env_var @@ -187,21 +184,15 @@ def get_profile( f"Instance was invalid under the provided $schema property, {exc}" ) except jsonschema.exceptions.SchemaError as exc: - raise jsonschema.exceptions.SchemaError( - f"The provided schema is invalid, {exc}" - ) + raise jsonschema.exceptions.SchemaError(f"The provided schema is invalid, {exc}") except jsonschema.exceptions.UndefinedTypeCheck as exc: 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: - raise jsonschema.exceptions.UnknownType( - f"Unknown type is found in schema_json, exc" - ) + raise jsonschema.exceptions.UnknownType(f"Unknown type is found in schema_json, exc") except jsonschema.exceptions.FormatError as exc: - raise jsonschema.exceptions.FormatError( - f"Validating a format config_json failed for schema_json, {exc}" - ) + raise jsonschema.exceptions.FormatError(f"Validating a format config_json failed for schema_json, {exc}") except ProfileNotFound: if profile_name: warnings.warn( @@ -216,8 +207,7 @@ def get_profile( ) except Exception as exc: warnings.warn( - f"Could not load '{cfg.filename}' at '{cfg.filepath}'" - f"because {type(exc).__name__}'{exc}'.", + f"Could not load '{cfg.filename}' at '{cfg.filepath}'" f"because {type(exc).__name__}'{exc}'.", ConfigNotFoundWarning, ) @@ -296,7 +286,13 @@ def load( if name not in profiles_merged: profiles_merged[name] = value - cfg = ConfigFile(type="Merged Config", name=cfg_name, profiles=profiles_merged, defaults=defaults_merged, schema_property=cfg_schema) + cfg = ConfigFile( + type="Merged Config", + name=cfg_name, + profiles=profiles_merged, + defaults=defaults_merged, + schema_property=cfg_schema, + ) profile_loaded = self.get_profile(cfg, profile_name, profile_type, validate_schema) if profile_loaded: profile_props = profile_loaded.data @@ -341,12 +337,7 @@ def get_highest_priority_layer(self, json_path: str) -> Optional[ConfigFile]: """ highest_layer = None longest_match = "" - layers = [ - self.project_user_config, - self.project_config, - self.global_user_config, - self.global_config - ] + layers = [self.project_user_config, self.project_config, self.global_user_config, self.global_config] original_name = layers[0].get_profile_name_from_path(json_path) @@ -379,7 +370,6 @@ def get_highest_priority_layer(self, json_path: str) -> Optional[ConfigFile]: return highest_layer - def set_property(self, json_path, value, secure=None) -> None: """ Set a property in the profile, storing it securely if necessary. @@ -413,10 +403,7 @@ def save(self) -> None: """ Save the layers (configuration files) to disk. """ - layers = [self.project_user_config, - self.project_config, - self.global_user_config, - self.global_config] + layers = [self.project_user_config, self.project_config, self.global_user_config, self.global_config] for layer in layers: layer.save(False) diff --git a/src/core/zowe/core_for_zowe_sdk/request_handler.py b/src/core/zowe/core_for_zowe_sdk/request_handler.py index 29c05ab2..adb271e0 100644 --- a/src/core/zowe/core_for_zowe_sdk/request_handler.py +++ b/src/core/zowe/core_for_zowe_sdk/request_handler.py @@ -10,12 +10,11 @@ Copyright Contributors to the Zowe Project. """ -from .exceptions import UnexpectedStatus -from .exceptions import RequestFailed -from .exceptions import InvalidRequestMethod import requests import urllib3 +from .exceptions import InvalidRequestMethod, RequestFailed, UnexpectedStatus + class RequestHandler: """ @@ -44,7 +43,7 @@ def __init__(self, session_arguments): def __handle_ssl_warnings(self): """Turn off warnings if the SSL verification argument if off.""" - if not self.session_arguments['verify']: + if not self.session_arguments["verify"]: urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) def perform_request(self, method, request_arguments, expected_code=[200]): @@ -142,8 +141,8 @@ def __normalize_response(self): ------- A bytes object if the response content type is application/octet-stream, a normalized JSON for the request response otherwise - """ - if self.response.headers.get('Content-Type') == 'application/octet-stream': + """ + if self.response.headers.get("Content-Type") == "application/octet-stream": return self.response.content else: try: diff --git a/src/core/zowe/core_for_zowe_sdk/sdk_api.py b/src/core/zowe/core_for_zowe_sdk/sdk_api.py index 486c2e68..146f29aa 100644 --- a/src/core/zowe/core_for_zowe_sdk/sdk_api.py +++ b/src/core/zowe/core_for_zowe_sdk/sdk_api.py @@ -11,10 +11,11 @@ """ import urllib + +from . import session_constants from .exceptions import UnsupportedAuthType from .request_handler import RequestHandler -from .session import Session, ISession -from . import session_constants +from .session import ISession, Session class SdkApi: @@ -22,7 +23,7 @@ class SdkApi: Abstract class used to represent the base SDK API. """ - def __init__(self, profile, default_url): + def __init__(self, profile, default_url): self.profile = profile session = Session(profile) self.session: ISession = session.load() diff --git a/src/core/zowe/core_for_zowe_sdk/session.py b/src/core/zowe/core_for_zowe_sdk/session.py index 5b85f652..54647f38 100644 --- a/src/core/zowe/core_for_zowe_sdk/session.py +++ b/src/core/zowe/core_for_zowe_sdk/session.py @@ -67,9 +67,7 @@ def __init__(self, props: dict) -> None: self.session.basePath = props.get("basePath") self.session.port = props.get("port", self.session.port) self.session.protocol = props.get("protocol", self.session.protocol) - self.session.rejectUnauthorized = props.get( - "rejectUnauthorized", self.session.rejectUnauthorized - ) + self.session.rejectUnauthorized = props.get("rejectUnauthorized", self.session.rejectUnauthorized) def load(self) -> ISession: return self.session diff --git a/src/core/zowe/core_for_zowe_sdk/validators.py b/src/core/zowe/core_for_zowe_sdk/validators.py index 7d0a1551..cd6b2332 100644 --- a/src/core/zowe/core_for_zowe_sdk/validators.py +++ b/src/core/zowe/core_for_zowe_sdk/validators.py @@ -10,11 +10,12 @@ Copyright Contributors to the Zowe Project. """ -import commentjson -from jsonschema import validate import os -from typing import Union, Optional +from typing import Optional, Union + +import commentjson import requests +from jsonschema import validate def validate_config_json(path_config_json: Union[str, dict], path_schema_json: str, cwd: str): @@ -50,7 +51,7 @@ def validate_config_json(path_config_json: Union[str, dict], path_schema_json: s schema_json = commentjson.load(file) # if there is no path_schema_json it will return None - else: + else: return None if isinstance(path_config_json, str): diff --git a/src/core/zowe/core_for_zowe_sdk/zosmf_profile.py b/src/core/zowe/core_for_zowe_sdk/zosmf_profile.py index 827b6ad8..5bfea1b8 100644 --- a/src/core/zowe/core_for_zowe_sdk/zosmf_profile.py +++ b/src/core/zowe/core_for_zowe_sdk/zosmf_profile.py @@ -13,11 +13,12 @@ import base64 import os.path import sys + import yaml +from .connection import ApiConnection from .constants import constants from .exceptions import SecureProfileLoadFailed -from .connection import ApiConnection HAS_KEYRING = True try: @@ -32,8 +33,8 @@ class ZosmfProfile: Description ----------- - This class is only used when there is already a Zowe z/OSMF profile created - and the user opted to use the profile instead of passing the credentials directly + This class is only used when there is already a Zowe z/OSMF profile created + and the user opted to use the profile instead of passing the credentials directly in the object constructor. Attributes @@ -67,9 +68,7 @@ def load(self): zosmf_connection z/OSMF connection object """ - profile_file = os.path.join( - self.profiles_dir, "{}.yaml".format(self.profile_name) - ) + profile_file = os.path.join(self.profiles_dir, "{}.yaml".format(self.profile_name)) with open(profile_file, "r") as fileobj: profile_yaml = yaml.safe_load(fileobj) @@ -80,18 +79,16 @@ def load(self): zosmf_user = profile_yaml["user"] zosmf_password = profile_yaml["password"] - if zosmf_user.startswith( + if zosmf_user.startswith(constants["SecureValuePrefix"]) and zosmf_password.startswith( constants["SecureValuePrefix"] - ) and zosmf_password.startswith(constants["SecureValuePrefix"]): + ): zosmf_user, zosmf_password = self.__load_secure_credentials() zosmf_ssl_verification = True if "rejectUnauthorized" in profile_yaml: zosmf_ssl_verification = profile_yaml["rejectUnauthorized"] - return ApiConnection( - zosmf_host, zosmf_user, zosmf_password, zosmf_ssl_verification - ) + return ApiConnection(zosmf_host, zosmf_user, zosmf_password, zosmf_ssl_verification) def __get_secure_value(self, name): service_name = constants["ZoweCredentialKey"] @@ -101,7 +98,7 @@ def __get_secure_value(self, name): service_name += "/" + account_name secret_value = keyring.get_password(service_name, account_name) - + # Handle the case when secret_value is None if secret_value is None: secret_value = "" @@ -116,9 +113,7 @@ def __get_secure_value(self, name): def __load_secure_credentials(self): """Load secure credentials for a z/OSMF profile.""" if not HAS_KEYRING: - raise SecureProfileLoadFailed( - self.profile_name, "Keyring module not installed" - ) + raise SecureProfileLoadFailed(self.profile_name, "Keyring module not installed") try: zosmf_user = self.__get_secure_value("user") @@ -131,6 +126,7 @@ def __load_secure_credentials(self): if HAS_KEYRING and sys.platform.startswith("linux"): from contextlib import closing + from keyring.backends import SecretService class KeyringBackend(SecretService.Keyring): @@ -160,4 +156,4 @@ def get_password(self, service, username): else: return self.__get_password(service, username, collection) - keyring.set_keyring(KeyringBackend()) \ No newline at end of file + keyring.set_keyring(KeyringBackend()) diff --git a/src/setup.py b/src/setup.py index b69b595b..af3527a1 100644 --- a/src/setup.py +++ b/src/setup.py @@ -1,11 +1,14 @@ import os.path import uuid + from setuptools import setup + from _version import __version__ src_dir = os.path.realpath(os.path.dirname(__file__)) uuid4 = uuid.uuid4() + def resolve_sdk_dep(sdk_name, version_spec): # if os.path.exists(os.path.join(src_dir, sdk_name, "zowe")): # # Handle building from a Git checkout @@ -15,11 +18,12 @@ def resolve_sdk_dep(sdk_name, version_spec): # else: return f"zowe.{sdk_name}_for_zowe_sdk{version_spec}" + if __name__ == "__main__": setup( - name='zowe', + name="zowe", version=__version__, - description='Zowe Python SDK', + description="Zowe Python SDK", url="https://github.com/zowe/zowe-client-python-sdk", author="Guilherme Cartier", author_email="gcartier94@gmail.com", @@ -27,11 +31,14 @@ def resolve_sdk_dep(sdk_name, version_spec): classifiers=[ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", - "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)"], - install_requires=[resolve_sdk_dep('zos_console', '==' + __version__), - resolve_sdk_dep('zos_files', '==' + __version__), - resolve_sdk_dep('zos_tso', '==' + __version__), - resolve_sdk_dep('zos_jobs', '==' + __version__), - resolve_sdk_dep('zosmf', '==' + __version__)], - py_modules=[] + "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)", + ], + install_requires=[ + resolve_sdk_dep("zos_console", "==" + __version__), + resolve_sdk_dep("zos_files", "==" + __version__), + resolve_sdk_dep("zos_tso", "==" + __version__), + resolve_sdk_dep("zos_jobs", "==" + __version__), + resolve_sdk_dep("zosmf", "==" + __version__), + ], + py_modules=[], ) diff --git a/src/zos_console/setup.py b/src/zos_console/setup.py index 224cbe36..659f9212 100644 --- a/src/zos_console/setup.py +++ b/src/zos_console/setup.py @@ -1,13 +1,15 @@ import sys -from setuptools import setup, find_namespace_packages + +from setuptools import find_namespace_packages, setup + sys.path.insert(0, "..") from _version import __version__ from setup import resolve_sdk_dep setup( - name='zowe_zos_console_for_zowe_sdk', + name="zowe_zos_console_for_zowe_sdk", version=__version__, - description='Zowe Python SDK - z/OS Console package', + description="Zowe Python SDK - z/OS Console package", url="https://github.com/zowe/zowe-client-python-sdk", author="Guilherme Cartier", author_email="gcartier94@gmail.com", @@ -15,7 +17,8 @@ classifiers=[ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", - "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)"], - install_requires=[resolve_sdk_dep('core', '~=' + __version__)], - packages=find_namespace_packages(include=['zowe.*']) + "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)", + ], + install_requires=[resolve_sdk_dep("core", "~=" + __version__)], + packages=find_namespace_packages(include=["zowe.*"]), ) diff --git a/src/zos_console/zowe/zos_console_for_zowe_sdk/console.py b/src/zos_console/zowe/zos_console_for_zowe_sdk/console.py index 39723694..67365eb4 100644 --- a/src/zos_console/zowe/zos_console_for_zowe_sdk/console.py +++ b/src/zos_console/zowe/zos_console_for_zowe_sdk/console.py @@ -1,5 +1,6 @@ from zowe.core_for_zowe_sdk import SdkApi + class Console(SdkApi): """ Class used to represent the base z/OSMF Console API. @@ -47,7 +48,7 @@ def issue_command(self, command, console=None): def get_response(self, response_key, console=None): """ Collect outstanding synchronous z/OS Console response messages. - + Parameters ---------- response_key diff --git a/src/zos_files/setup.py b/src/zos_files/setup.py index 3cc4d750..f6adc7c2 100644 --- a/src/zos_files/setup.py +++ b/src/zos_files/setup.py @@ -1,13 +1,15 @@ import sys -from setuptools import setup, find_namespace_packages + +from setuptools import find_namespace_packages, setup + sys.path.insert(0, "..") from _version import __version__ from setup import resolve_sdk_dep setup( - name='zowe_zos_files_for_zowe_sdk', + name="zowe_zos_files_for_zowe_sdk", version=__version__, - description='Zowe Python SDK - z/OS Files package', + description="Zowe Python SDK - z/OS Files package", url="https://github.com/zowe/zowe-client-python-sdk", author="Guilherme Cartier", author_email="gcartier94@gmail.com", @@ -15,7 +17,8 @@ classifiers=[ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", - "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)"], - install_requires=[resolve_sdk_dep('core', '~=' + __version__)], - packages=find_namespace_packages(include=['zowe.*']) + "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)", + ], + install_requires=[resolve_sdk_dep("core", "~=" + __version__)], + packages=find_namespace_packages(include=["zowe.*"]), ) diff --git a/src/zos_files/zowe/zos_files_for_zowe_sdk/__init__.py b/src/zos_files/zowe/zos_files_for_zowe_sdk/__init__.py index 7537a03d..a772ba07 100644 --- a/src/zos_files/zowe/zos_files_for_zowe_sdk/__init__.py +++ b/src/zos_files/zowe/zos_files_for_zowe_sdk/__init__.py @@ -2,5 +2,5 @@ Zowe Python SDK - z/OS Files package """ +from . import constants, exceptions from .files import Files -from . import exceptions, constants diff --git a/src/zos_files/zowe/zos_files_for_zowe_sdk/constants.py b/src/zos_files/zowe/zos_files_for_zowe_sdk/constants.py index 6335c406..4e7e7942 100644 --- a/src/zos_files/zowe/zos_files_for_zowe_sdk/constants.py +++ b/src/zos_files/zowe/zos_files_for_zowe_sdk/constants.py @@ -14,8 +14,9 @@ "MaxAllocationQuantity": 16777215, } from enum import Enum + + class FileType(Enum): BINARY = "binary" EXECUTABLE = "executable" TEXT = "text" - \ No newline at end of file diff --git a/src/zos_files/zowe/zos_files_for_zowe_sdk/exceptions.py b/src/zos_files/zowe/zos_files_for_zowe_sdk/exceptions.py index 06809f74..f079c0f5 100644 --- a/src/zos_files/zowe/zos_files_for_zowe_sdk/exceptions.py +++ b/src/zos_files/zowe/zos_files_for_zowe_sdk/exceptions.py @@ -30,4 +30,6 @@ class MaxAllocationQuantityExceeded(Exception): """Class used to represent an invalid allocation quantity.""" def __init__(self): - super().__init__("Maximum allocation quantity of {} exceeded".format(zos_file_constants['MaxAllocationQuantity'])) + super().__init__( + "Maximum allocation quantity of {} exceeded".format(zos_file_constants["MaxAllocationQuantity"]) + ) diff --git a/src/zos_files/zowe/zos_files_for_zowe_sdk/files.py b/src/zos_files/zowe/zos_files_for_zowe_sdk/files.py index 9a5c3e54..f338854a 100644 --- a/src/zos_files/zowe/zos_files_for_zowe_sdk/files.py +++ b/src/zos_files/zowe/zos_files_for_zowe_sdk/files.py @@ -11,14 +11,16 @@ """ -from zowe.core_for_zowe_sdk import SdkApi -from zowe.core_for_zowe_sdk.exceptions import FileNotFound -from zowe.zos_files_for_zowe_sdk import exceptions, constants import os import shutil -from zowe.zos_files_for_zowe_sdk.constants import zos_file_constants, FileType -_ZOWE_FILES_DEFAULT_ENCODING='utf-8' +from zowe.core_for_zowe_sdk import SdkApi +from zowe.core_for_zowe_sdk.exceptions import FileNotFound +from zowe.zos_files_for_zowe_sdk import constants, exceptions +from zowe.zos_files_for_zowe_sdk.constants import FileType, zos_file_constants + +_ZOWE_FILES_DEFAULT_ENCODING = "utf-8" + class Files(SdkApi): """ @@ -46,7 +48,6 @@ def __init__(self, connection): super().__init__(connection, "/zosmf/restfiles/") self.default_headers["Accept-Encoding"] = "gzip" - def list_files(self, path): """Retrieve a list of USS files based on a given pattern. @@ -70,11 +71,11 @@ def get_file_content(self, filepath_name): A JSON with the contents of the specified USS file """ custom_args = self._create_custom_request_arguments() - #custom_args["params"] = {"filepath-name": filepath_name} - custom_args["url"] = "{}fs{}".format(self.request_endpoint,filepath_name) + # custom_args["params"] = {"filepath-name": filepath_name} + custom_args["url"] = "{}fs{}".format(self.request_endpoint, filepath_name) response_json = self.request_handler.perform_request("GET", custom_args) return response_json - + def delete_uss(self, filepath_name, recursive=False): """ Delete a file or directory @@ -99,8 +100,7 @@ def delete_uss(self, filepath_name, recursive=False): response_json = self.request_handler.perform_request("DELETE", custom_args, expected_code=[204]) return response_json - - def list_dsn(self, name_pattern, return_attributes= False): + def list_dsn(self, name_pattern, return_attributes=False): """Retrieve a list of datasets based on a given pattern. Parameters @@ -113,24 +113,20 @@ def list_dsn(self, name_pattern, return_attributes= False): Returns ------- list of dict - + A JSON with a list of dataset names (and attributes if specified) matching the given pattern. """ custom_args = self._create_custom_request_arguments() custom_args["params"] = {"dslevel": self._encode_uri_component(name_pattern)} custom_args["url"] = "{}ds".format(self.request_endpoint) - - + if return_attributes: - custom_args["headers"]["X-IBM-Attributes"] = "base" - + custom_args["headers"]["X-IBM-Attributes"] = "base" + response_json = self.request_handler.perform_request("GET", custom_args) return response_json - - - def list_dsn_members(self, dataset_name, member_pattern=None, - member_start=None, limit=1000, attributes='member'): + def list_dsn_members(self, dataset_name, member_pattern=None, member_start=None, limit=1000, attributes="member"): """Retrieve the list of members on a given PDS/PDSE. Returns @@ -141,21 +137,23 @@ def list_dsn_members(self, dataset_name, member_pattern=None, custom_args = self._create_custom_request_arguments() additional_parms = {} if member_start is not None: - additional_parms['start'] = member_start + additional_parms["start"] = member_start if member_pattern is not None: - additional_parms['pattern'] = member_pattern + additional_parms["pattern"] = member_pattern url = "{}ds/{}/member".format(self.request_endpoint, dataset_name) - separator = '?' - for k,v in additional_parms.items(): - url = "{}{}{}={}".format(url,separator,k,v) - separator = '&' - custom_args['url'] = self._encode_uri_component(url) - custom_args["headers"]["X-IBM-Max-Items"] = "{}".format(limit) + separator = "?" + for k, v in additional_parms.items(): + url = "{}{}{}={}".format(url, separator, k, v) + separator = "&" + custom_args["url"] = self._encode_uri_component(url) + custom_args["headers"]["X-IBM-Max-Items"] = "{}".format(limit) custom_args["headers"]["X-IBM-Attributes"] = attributes response_json = self.request_handler.perform_request("GET", custom_args) - return response_json['items'] # type: ignore - - def copy_uss_to_dataset(self, from_filename, to_dataset_name, to_member_name=None, type=FileType.TEXT,replace=False): + return response_json["items"] # type: ignore + + def copy_uss_to_dataset( + self, from_filename, to_dataset_name, to_member_name=None, type=FileType.TEXT, replace=False + ): """ Copy a USS file to dataset. @@ -177,25 +175,31 @@ def copy_uss_to_dataset(self, from_filename, to_dataset_name, to_member_name=Non json A JSON containing the result of the operation. """ - - data={ - "request":"copy", - "from-file":{ - "filename":from_filename.strip(), - "type":type.value - }, - "replace":replace + + data = { + "request": "copy", + "from-file": {"filename": from_filename.strip(), "type": type.value}, + "replace": replace, } - + path_to_member = f"{to_dataset_name}({to_member_name})" if to_member_name else to_dataset_name custom_args = self._create_custom_request_arguments() - custom_args['json'] = data + custom_args["json"] = data custom_args["url"] = "{}ds/{}".format(self.request_endpoint, self._encode_uri_component(path_to_member)) response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[200]) return response_json - - def copy_dataset_or_member(self,from_dataset_name,to_dataset_name,from_member_name=None,volser=None,alias=None, - to_member_name=None,enq=None,replace=False): + + def copy_dataset_or_member( + self, + from_dataset_name, + to_dataset_name, + from_member_name=None, + volser=None, + alias=None, + to_member_name=None, + enq=None, + replace=False, + ): """ Copy a dataset or member to another dataset or member. Parameters @@ -208,7 +212,7 @@ def copy_dataset_or_member(self,from_dataset_name,to_dataset_name,from_member_na Name of the member to copy from volser: str Volume serial number of the dataset to copy from - alias: bool + alias: bool Alias of the dataset to copy from to_member_name: str Name of the member to copy to @@ -216,39 +220,35 @@ def copy_dataset_or_member(self,from_dataset_name,to_dataset_name,from_member_na Enqueue type for the dataset to copy from replace: bool If true, members in the target data set are replaced. - Returns + Returns ------- json A JSON containing the result of the operation """ - - data={ - "request":"copy", - "from-dataset":{ - "dsn":from_dataset_name.strip(), - "member":from_member_name - }, - "replace":replace + + data = { + "request": "copy", + "from-dataset": {"dsn": from_dataset_name.strip(), "member": from_member_name}, + "replace": replace, } - - + path_to_member = f"{to_dataset_name}({to_member_name})" if to_member_name else to_dataset_name if enq: - if enq in ("SHR","SHRW","EXCLU"): + if enq in ("SHR", "SHRW", "EXCLU"): data["enq"] = enq else: raise ValueError("Invalid value for enq.") if volser: - data["from-dataset"]["volser"]=volser - if alias is not None: #because it can be false so - data["from-dataset"]["alias"]=alias - + data["from-dataset"]["volser"] = volser + if alias is not None: # because it can be false so + data["from-dataset"]["alias"] = alias + custom_args = self._create_custom_request_arguments() - custom_args['json'] = data + custom_args["json"] = data custom_args["url"] = "{}ds/{}".format(self.request_endpoint, self._encode_uri_component(path_to_member)) response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[200]) return response_json - + def get_dsn_content(self, dataset_name): """Retrieve the contents of a given dataset. @@ -262,8 +262,7 @@ def get_dsn_content(self, dataset_name): response_json = self.request_handler.perform_request("GET", custom_args) return response_json - def create_data_set(self, dataset_name, options = {}): - + def create_data_set(self, dataset_name, options={}): """ Create a sequential or partitioned dataset. Parameters @@ -278,11 +277,24 @@ def create_data_set(self, dataset_name, options = {}): if options.get("primary") is None or options.get("lrecl") is None: raise ValueError("If 'like' is not specified, you must specify 'primary' or 'lrecl'.") - for opt in ("volser", "unit", "dsorg", "alcunit", - "primary", "secondary", "dirblk", "avgblk", "recfm", - "blksize", "lrecl", "storclass", "mgntclass", "dataclass", - "dsntype", "like"): - + for opt in ( + "volser", + "unit", + "dsorg", + "alcunit", + "primary", + "secondary", + "dirblk", + "avgblk", + "recfm", + "blksize", + "lrecl", + "storclass", + "mgntclass", + "dataclass", + "dsntype", + "like", + ): if opt == "dsorg": if options.get(opt) is not None and options[opt] not in ("PO", "PS"): raise KeyError @@ -329,7 +341,7 @@ def create_data_set(self, dataset_name, options = {}): custom_args = self._create_custom_request_arguments() custom_args["url"] = "{}ds/{}".format(self.request_endpoint, self._encode_uri_component(dataset_name)) custom_args["json"] = options - response_json = self.request_handler.perform_request("POST", custom_args, expected_code = [201]) + response_json = self.request_handler.perform_request("POST", custom_args, expected_code=[201]) return response_json def create_default_data_set(self, dataset_name: str, default_type: str): @@ -361,7 +373,7 @@ def create_default_data_set(self, dataset_name: str, default_type: str): "dirblk": 5, "recfm": "FB", "blksize": 6160, - "lrecl": 80 + "lrecl": 80, } elif default_type == "sequential": custom_args["json"] = { @@ -370,7 +382,7 @@ def create_default_data_set(self, dataset_name: str, default_type: str): "primary": 1, "recfm": "FB", "blksize": 6160, - "lrecl": 80 + "lrecl": 80, } elif default_type == "classic": custom_args["json"] = { @@ -380,7 +392,7 @@ def create_default_data_set(self, dataset_name: str, default_type: str): "recfm": "FB", "blksize": 6160, "lrecl": 80, - "dirblk": 25 + "dirblk": 25, } elif default_type == "c": custom_args["json"] = { @@ -390,7 +402,7 @@ def create_default_data_set(self, dataset_name: str, default_type: str): "recfm": "VB", "blksize": 32760, "lrecl": 260, - "dirblk": 25 + "dirblk": 25, } elif default_type == "binary": custom_args["json"] = { @@ -400,14 +412,14 @@ def create_default_data_set(self, dataset_name: str, default_type: str): "recfm": "U", "blksize": 27998, "lrecl": 27998, - "dirblk": 25 + "dirblk": 25, } custom_args["url"] = "{}ds/{}".format(self.request_endpoint, self._encode_uri_component(dataset_name)) response_json = self.request_handler.perform_request("POST", custom_args, expected_code=[201]) return response_json - def create_uss(self, file_path, type, mode = None): + def create_uss(self, file_path, type, mode=None): """ Add a file or directory Parameters @@ -418,15 +430,12 @@ def create_uss(self, file_path, type, mode = None): """ - data = { - "type": type, - "mode": mode - } - + data = {"type": type, "mode": mode} + custom_args = self._create_custom_request_arguments() custom_args["json"] = data custom_args["url"] = "{}fs/{}".format(self.request_endpoint, file_path.lstrip("/")) - response_json = self.request_handler.perform_request("POST", custom_args, expected_code = [201]) + response_json = self.request_handler.perform_request("POST", custom_args, expected_code=[201]) return response_json def get_dsn_content_streamed(self, dataset_name): @@ -460,9 +469,9 @@ def get_dsn_binary_content(self, dataset_name, with_prefixes=False): custom_args["url"] = "{}ds/{}".format(self.request_endpoint, self._encode_uri_component(dataset_name)) custom_args["headers"]["Accept"] = "application/octet-stream" if with_prefixes: - custom_args["headers"]["X-IBM-Data-Type"] = 'record' + custom_args["headers"]["X-IBM-Data-Type"] = "record" else: - custom_args["headers"]["X-IBM-Data-Type"] = 'binary' + custom_args["headers"]["X-IBM-Data-Type"] = "binary" content = self.request_handler.perform_request("GET", custom_args) return content @@ -474,7 +483,7 @@ def get_dsn_binary_content_streamed(self, dataset_name, with_prefixes=False): ---------- dataset_name: str - Name of the dataset to retrieve with_prefixes: boolean - if True include a 4 byte big endian record len prefix - default: False + default: False Returns ------- raw @@ -484,9 +493,9 @@ def get_dsn_binary_content_streamed(self, dataset_name, with_prefixes=False): custom_args["url"] = "{}ds/{}".format(self.request_endpoint, self._encode_uri_component(dataset_name)) custom_args["headers"]["Accept"] = "application/octet-stream" if with_prefixes: - custom_args["headers"]["X-IBM-Data-Type"] = 'record' + custom_args["headers"]["X-IBM-Data-Type"] = "record" else: - custom_args["headers"]["X-IBM-Data-Type"] = 'binary' + custom_args["headers"]["X-IBM-Data-Type"] = "binary" content = self.request_handler.perform_streamed_request("GET", custom_args) return content @@ -501,16 +510,14 @@ def write_to_dsn(self, dataset_name, data, encoding=_ZOWE_FILES_DEFAULT_ENCODING custom_args = self._create_custom_request_arguments() custom_args["url"] = "{}ds/{}".format(self.request_endpoint, self._encode_uri_component(dataset_name)) custom_args["data"] = data - custom_args['headers']['Content-Type'] = 'text/plain; charset={}'.format(encoding) - response_json = self.request_handler.perform_request( - "PUT", custom_args, expected_code=[204, 201] - ) + custom_args["headers"]["Content-Type"] = "text/plain; charset={}".format(encoding) + response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[204, 201]) return response_json def download_dsn(self, dataset_name, output_file): """Retrieve the contents of a dataset and saves it to a given file.""" raw_response = self.get_dsn_content_streamed(dataset_name) - with open(output_file, 'w') as f: + with open(output_file, "w") as f: shutil.copyfileobj(raw_response, f) def download_binary_dsn(self, dataset_name, output_file, with_prefixes=False): @@ -529,13 +536,13 @@ def download_binary_dsn(self, dataset_name, output_file, with_prefixes=False): Binary content of the dataset. """ content = self.get_dsn_binary_content_streamed(dataset_name, with_prefixes=with_prefixes) - with open(output_file, 'wb') as f: + with open(output_file, "wb") as f: shutil.copyfileobj(content, f) def upload_file_to_dsn(self, input_file, dataset_name, encoding=_ZOWE_FILES_DEFAULT_ENCODING): """Upload contents of a given file and uploads it to a dataset.""" if os.path.isfile(input_file): - with open(input_file, 'rb') as in_file: + with open(input_file, "rb") as in_file: response_json = self.write_to_dsn(dataset_name, in_file) else: raise FileNotFound(input_file) @@ -550,16 +557,14 @@ def write_to_uss(self, filepath_name, data, encoding=_ZOWE_FILES_DEFAULT_ENCODIN custom_args = self._create_custom_request_arguments() custom_args["url"] = "{}fs/{}".format(self.request_endpoint, filepath_name.lstrip("/")) custom_args["data"] = data - custom_args['headers']['Content-Type'] = 'text/plain; charset={}'.format(encoding) - response_json = self.request_handler.perform_request( - "PUT", custom_args, expected_code=[204, 201] - ) + custom_args["headers"]["Content-Type"] = "text/plain; charset={}".format(encoding) + response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[204, 201]) return response_json def upload_file_to_uss(self, input_file, filepath_name, encoding=_ZOWE_FILES_DEFAULT_ENCODING): """Upload contents of a given file and uploads it to UNIX file""" if os.path.isfile(input_file): - in_file = open(input_file, 'r') + in_file = open(input_file, "r") file_contents = in_file.read() response_json = self.write_to_uss(filepath_name, file_contents) else: @@ -569,40 +574,39 @@ def delete_data_set(self, dataset_name, volume=None, member_name=None): """Deletes a sequential or partitioned data.""" custom_args = self._create_custom_request_arguments() if member_name is not None: - dataset_name = f'{dataset_name}({member_name})' + dataset_name = f"{dataset_name}({member_name})" url = "{}ds/{}".format(self.request_endpoint, dataset_name) if volume is not None: url = "{}ds/-{}/{}".format(self.request_endpoint, volume, dataset_name) custom_args["url"] = self._encode_uri_component(url) - response_json = self.request_handler.perform_request( - "DELETE", custom_args, expected_code=[200, 202, 204]) + response_json = self.request_handler.perform_request("DELETE", custom_args, expected_code=[200, 202, 204]) return response_json def create_zFS_file_system(self, file_system_name, options={}): """ Create a z/OS UNIX zFS Filesystem. - + Parameter --------- file_system_name: str - the name for the file system - + Returns ------- json - A JSON containing the result of the operation """ for key, value in options.items(): - if key == 'perms': + if key == "perms": if value < 0 or value > 777: raise exceptions.InvalidPermsOption(value) - + if key == "cylsPri" or key == "cylsSec": - if value > constants.zos_file_constants['MaxAllocationQuantity']: + if value > constants.zos_file_constants["MaxAllocationQuantity"]: raise exceptions.MaxAllocationQuantityExceeded custom_args = self._create_custom_request_arguments() custom_args["url"] = "{}mfs/zfs/{}".format(self.request_endpoint, file_system_name) custom_args["json"] = options - response_json = self.request_handler.perform_request("POST", custom_args, expected_code = [201]) + response_json = self.request_handler.perform_request("POST", custom_args, expected_code=[201]) return response_json def delete_zFS_file_system(self, file_system_name): @@ -613,7 +617,7 @@ def delete_zFS_file_system(self, file_system_name): custom_args["url"] = "{}mfs/zfs/{}".format(self.request_endpoint, file_system_name) response_json = self.request_handler.perform_request("DELETE", custom_args, expected_code=[204]) return response_json - + def mount_file_system(self, file_system_name, mount_point, options={}, encoding=_ZOWE_FILES_DEFAULT_ENCODING): """Mounts a z/OS UNIX file system on a specified directory. Parameter @@ -631,7 +635,7 @@ def mount_file_system(self, file_system_name, mount_point, options={}, encoding= custom_args = self._create_custom_request_arguments() custom_args["url"] = "{}mfs/{}".format(self.request_endpoint, file_system_name) custom_args["json"] = options - custom_args['headers']['Content-Type'] = 'text/plain; charset={}'.format(encoding) + custom_args["headers"]["Content-Type"] = "text/plain; charset={}".format(encoding) response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[204]) return response_json @@ -642,7 +646,7 @@ def unmount_file_system(self, file_system_name, options={}, encoding=_ZOWE_FILES --------- file_system_name: str - the name for the file system options: dict - A JSON of request body options - + Returns ------- json - A JSON containing the result of the operation @@ -651,7 +655,7 @@ def unmount_file_system(self, file_system_name, options={}, encoding=_ZOWE_FILES custom_args = self._create_custom_request_arguments() custom_args["url"] = "{}mfs/{}".format(self.request_endpoint, file_system_name) custom_args["json"] = options - custom_args['headers']['Content-Type'] = 'text/plain; charset={}'.format(encoding) + custom_args["headers"]["Content-Type"] = "text/plain; charset={}".format(encoding) response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[204]) return response_json @@ -664,14 +668,14 @@ def list_unix_file_systems(self, file_path_name=None, file_system_name=None): --------- file_path: str - the UNIX directory that contains the files and directories to be listed. file_system_name: str - the name for the file system to be listed - + Returns ------- json - A JSON containing the result of the operation """ custom_args = self._create_custom_request_arguments() - custom_args["params"] = {"path":file_path_name, "fsname": file_system_name} + custom_args["params"] = {"path": file_path_name, "fsname": file_system_name} custom_args["url"] = "{}mfs".format(self.request_endpoint) response_json = self.request_handler.perform_request("GET", custom_args, expected_code=[200]) return response_json @@ -693,10 +697,7 @@ def recall_migrated_dataset(self, dataset_name: str, wait=False): json - A JSON containing the result of the operation """ - data = { - "request": "hrecall", - "wait": wait - } + data = {"request": "hrecall", "wait": wait} custom_args = self._create_custom_request_arguments() custom_args["json"] = data @@ -713,10 +714,10 @@ def delete_migrated_data_set(self, dataset_name: str, purge=False, wait=False): ---------- dataset_name: str Name of the data set - + purge: bool If true, the function uses the PURGE=YES on ARCHDEL request, otherwise it uses the PURGE=NO. - + wait: bool If true, the function waits for completion of the request, otherwise the request is queued. @@ -755,10 +756,7 @@ def migrate_data_set(self, dataset_name: str, wait=False): json - A JSON containing the result of the operation """ - data = { - "request": "hmigrate", - "wait": wait - } + data = {"request": "hmigrate", "wait": wait} custom_args = self._create_custom_request_arguments() custom_args["json"] = data @@ -783,17 +781,14 @@ def rename_dataset(self, before_dataset_name: str, after_dataset_name: str): ------- json - A JSON containing the result of the operation """ - - data = { - "request": "rename", - "from-dataset": { - "dsn": before_dataset_name.strip() - } - } + + data = {"request": "rename", "from-dataset": {"dsn": before_dataset_name.strip()}} custom_args = self._create_custom_request_arguments() custom_args["json"] = data - custom_args["url"] = "{}ds/{}".format(self.request_endpoint, self._encode_uri_component(after_dataset_name).strip()) + custom_args["url"] = "{}ds/{}".format( + self.request_endpoint, self._encode_uri_component(after_dataset_name).strip() + ) response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[200]) return response_json @@ -826,7 +821,7 @@ def rename_dataset_member(self, dataset_name: str, before_member_name: str, afte "from-dataset": { "dsn": dataset_name.strip(), "member": before_member_name.strip(), - } + }, } path_to_member = dataset_name.strip() + "(" + after_member_name.strip() + ")" @@ -838,7 +833,7 @@ def rename_dataset_member(self, dataset_name: str, before_member_name: str, afte raise ValueError("Invalid value for enq.") custom_args = self._create_custom_request_arguments() - custom_args['json'] = data + custom_args["json"] = data custom_args["url"] = "{}ds/{}".format(self.request_endpoint, self._encode_uri_component(path_to_member)) response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[200]) diff --git a/src/zos_jobs/setup.py b/src/zos_jobs/setup.py index 88a506e3..8109eaf1 100644 --- a/src/zos_jobs/setup.py +++ b/src/zos_jobs/setup.py @@ -1,13 +1,15 @@ import sys -from setuptools import setup, find_namespace_packages + +from setuptools import find_namespace_packages, setup + sys.path.insert(0, "..") from _version import __version__ from setup import resolve_sdk_dep setup( - name='zowe_zos_jobs_for_zowe_sdk', + name="zowe_zos_jobs_for_zowe_sdk", version=__version__, - description='Zowe Python SDK - z/OS Jobs package', + description="Zowe Python SDK - z/OS Jobs package", url="https://github.com/zowe/zowe-client-python-sdk", author="Guilherme Cartier", author_email="gcartier94@gmail.com", @@ -15,7 +17,8 @@ classifiers=[ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", - "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)"], - install_requires=[resolve_sdk_dep('core', '~=' + __version__)], - packages=find_namespace_packages(include=['zowe.*']) + "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)", + ], + install_requires=[resolve_sdk_dep("core", "~=" + __version__)], + packages=find_namespace_packages(include=["zowe.*"]), ) diff --git a/src/zos_jobs/zowe/zos_jobs_for_zowe_sdk/jobs.py b/src/zos_jobs/zowe/zos_jobs_for_zowe_sdk/jobs.py index 0d508569..c5a2d5dc 100644 --- a/src/zos_jobs/zowe/zos_jobs_for_zowe_sdk/jobs.py +++ b/src/zos_jobs/zowe/zos_jobs_for_zowe_sdk/jobs.py @@ -9,9 +9,10 @@ Copyright Contributors to the Zowe Project. """ -from zowe.core_for_zowe_sdk import SdkApi import os +from zowe.core_for_zowe_sdk import SdkApi + class Jobs(SdkApi): """ @@ -80,10 +81,7 @@ def cancel_job(self, jobname: str, jobid: str, modify_version="2.0"): job_url = "{}/{}".format(jobname, jobid) request_url = "{}{}".format(self.request_endpoint, self._encode_uri_component(job_url)) custom_args["url"] = request_url - custom_args["json"] = { - "request": "cancel", - "version": modify_version - } + custom_args["json"] = {"request": "cancel", "version": modify_version} response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[202, 200]) return response_json @@ -118,21 +116,17 @@ def delete_job(self, jobname, jobid, modify_version="2.0"): return response_json def _issue_job_request(self, req: dict, jobname: str, jobid: str, modify_version): - custom_args = self._create_custom_request_arguments() job_url = "{}/{}".format(jobname, jobid) request_url = "{}{}".format(self.request_endpoint, self._encode_uri_component(job_url)) custom_args["url"] = request_url - custom_args["json"] = { - **req, - "version": modify_version - } + custom_args["json"] = {**req, "version": modify_version} custom_args["headers"]["X-IBM-Job-Modify-Version"] = modify_version - + response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[202, 200]) return response_json - + def change_job_class(self, jobname: str, jobid: str, class_name: str, modify_version="2.0"): """Changes the job class @@ -158,7 +152,7 @@ def change_job_class(self, jobname: str, jobid: str, class_name: str, modify_ver def hold_job(self, jobname: str, jobid: str, modify_version="2.0"): """Hold the given job on JES - + Parameters ---------- jobname: str @@ -175,13 +169,13 @@ def hold_job(self, jobname: str, jobid: str, modify_version="2.0"): """ if modify_version not in ("1.0", "2.0"): raise ValueError('Accepted values for modify_version: "1.0" or "2.0"') - + response_json = self._issue_job_request({"request": "hold"}, jobname, jobid, modify_version) return response_json def release_job(self, jobname: str, jobid: str, modify_version="2.0"): """Release the given job on JES - + Parameters ---------- jobname: str @@ -198,11 +192,11 @@ def release_job(self, jobname: str, jobid: str, modify_version="2.0"): """ if modify_version not in ("1.0", "2.0"): raise ValueError('Accepted values for modify_version: "1.0" or "2.0"') - + response_json = self._issue_job_request({"request": "release"}, jobname, jobid, modify_version) return response_json - def list_jobs(self, owner=None, prefix="*", max_jobs=1000, user_correlator=None): + def list_jobs(self, owner=None, prefix="*", max_jobs=1000, user_correlator=None): """Retrieve list of jobs on JES based on the provided arguments. Parameters @@ -244,11 +238,9 @@ def submit_from_mainframe(self, jcl_path): A JSON containing the result of the request execution """ custom_args = self._create_custom_request_arguments() - request_body = {"file": "//\'%s\'" % jcl_path} + request_body = {"file": "//'%s'" % jcl_path} custom_args["json"] = request_body - response_json = self.request_handler.perform_request( - "PUT", custom_args, expected_code=[201] - ) + response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[201]) return response_json def submit_from_local_file(self, jcl_path): @@ -297,9 +289,7 @@ def submit_plaintext(self, jcl): custom_args = self._create_custom_request_arguments() custom_args["data"] = str(jcl) custom_args["headers"] = {"Content-Type": "text/plain", "X-CSRF-ZOSMF-HEADER": ""} - response_json = self.request_handler.perform_request( - "PUT", custom_args, expected_code=[201] - ) + response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[201]) return response_json def get_spool_files(self, correlator): @@ -321,7 +311,7 @@ def get_spool_files(self, correlator): custom_args["url"] = request_url response_json = self.request_handler.perform_request("GET", custom_args) return response_json - + def get_jcl_text(self, correlator): """Retrieve the input JCL text for job with specified correlator Parameters @@ -339,7 +329,7 @@ def get_jcl_text(self, correlator): request_url = "{}{}".format(self.request_endpoint, self._encode_uri_component(job_url)) custom_args["url"] = request_url response_json = self.request_handler.perform_request("GET", custom_args) - return response_json + return response_json def get_spool_file_contents(self, correlator, id): """Retrieve the contents of a single spool file from a job @@ -380,7 +370,7 @@ def get_job_output_as_files(self, status, output_dir): dir: stepname | file: spool file - ... + ... Parameters @@ -397,31 +387,31 @@ def get_job_output_as_files(self, status, output_dir): A JSON containing the result of the request execution """ - _job_name = status['jobname'] - _job_id = status['jobid'] - _job_correlator = status['job-correlator'] + _job_name = status["jobname"] + _job_id = status["jobid"] + _job_correlator = status["job-correlator"] _output_dir = os.path.join(output_dir, _job_name, _job_id) os.makedirs(_output_dir, exist_ok=True) - _output_file = os.path.join(output_dir, _job_name, _job_id, 'jcl.txt') + _output_file = os.path.join(output_dir, _job_name, _job_id, "jcl.txt") _data_spool_file = self.get_jcl_text(_job_correlator) - _dataset_content = _data_spool_file['response'] - _out_file = open(_output_file, 'w') + _dataset_content = _data_spool_file["response"] + _out_file = open(_output_file, "w") _out_file.write(_dataset_content) _out_file.close() _spool = self.get_spool_files(_job_correlator) for _spool_file in _spool: - _stepname = _spool_file['stepname'] - _ddname = _spool_file['ddname'] - _spoolfile_id = _spool_file['id'] + _stepname = _spool_file["stepname"] + _ddname = _spool_file["ddname"] + _spoolfile_id = _spool_file["id"] _output_dir = os.path.join(output_dir, _job_name, _job_id, _stepname) os.makedirs(_output_dir, exist_ok=True) - + _output_file = os.path.join(output_dir, _job_name, _job_id, _stepname, _ddname) _data_spool_file = self.get_spool_file_contents(_job_correlator, _spoolfile_id) - _dataset_content = _data_spool_file['response'] - _out_file = open(_output_file, 'w') + _dataset_content = _data_spool_file["response"] + _out_file = open(_output_file, "w") _out_file.write(_dataset_content) _out_file.close() diff --git a/src/zos_tso/setup.py b/src/zos_tso/setup.py index 1f54857d..593f7a41 100644 --- a/src/zos_tso/setup.py +++ b/src/zos_tso/setup.py @@ -1,13 +1,15 @@ import sys -from setuptools import setup, find_namespace_packages + +from setuptools import find_namespace_packages, setup + sys.path.insert(0, "..") from _version import __version__ from setup import resolve_sdk_dep setup( - name='zowe_zos_tso_for_zowe_sdk', + name="zowe_zos_tso_for_zowe_sdk", version=__version__, - description='Zowe Python SDK - z/OS TSO package', + description="Zowe Python SDK - z/OS TSO package", url="https://github.com/zowe/zowe-client-python-sdk", author="Guilherme Cartier", author_email="gcartier94@gmail.com", @@ -15,7 +17,8 @@ classifiers=[ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", - "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)"], - install_requires=[resolve_sdk_dep('core', '~=' + __version__)], - packages=find_namespace_packages(include=['zowe.*']) + "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)", + ], + install_requires=[resolve_sdk_dep("core", "~=" + __version__)], + packages=find_namespace_packages(include=["zowe.*"]), ) diff --git a/src/zos_tso/zowe/zos_tso_for_zowe_sdk/tso.py b/src/zos_tso/zowe/zos_tso_for_zowe_sdk/tso.py index 6854cdcf..07972314 100644 --- a/src/zos_tso/zowe/zos_tso_for_zowe_sdk/tso.py +++ b/src/zos_tso/zowe/zos_tso_for_zowe_sdk/tso.py @@ -125,7 +125,7 @@ def send_tso_message(self, session_key, message): """ custom_args = self._create_custom_request_arguments() custom_args["url"] = "{}/{}".format(self.request_endpoint, str(session_key)) - custom_args["json"] = {"TSO RESPONSE":{"VERSION":"0100","DATA":str(message)}} + custom_args["json"] = {"TSO RESPONSE": {"VERSION": "0100", "DATA": str(message)}} response_json = self.request_handler.perform_request("PUT", custom_args) return response_json["tsoData"] @@ -144,16 +144,10 @@ def ping_tso_session(self, session_key): Where the options are: 'Ping successful' or 'Ping failed' """ custom_args = self._create_custom_request_arguments() - custom_args["url"] = "{}/{}/{}".format( - self.request_endpoint, "ping", str(session_key) - ) + custom_args["url"] = "{}/{}/{}".format(self.request_endpoint, "ping", str(session_key)) response_json = self.request_handler.perform_request("PUT", custom_args) message_id_list = self.parse_message_ids(response_json) - return ( - "Ping successful" - if self.session_not_found not in message_id_list - else "Ping failed" - ) + return "Ping successful" if self.session_not_found not in message_id_list else "Ping failed" def end_tso_session(self, session_key): """Terminates an existing TSO session. @@ -172,11 +166,7 @@ def end_tso_session(self, session_key): custom_args["url"] = "{}/{}".format(self.request_endpoint, session_key) response_json = self.request_handler.perform_request("DELETE", custom_args) message_id_list = self.parse_message_ids(response_json) - return ( - "Session ended" - if self.session_not_found not in message_id_list - else "Session already ended" - ) + return "Session ended" if self.session_not_found not in message_id_list else "Session already ended" def parse_message_ids(self, response_json): """Parse TSO response and retrieve only the message ids. @@ -191,11 +181,7 @@ def parse_message_ids(self, response_json): list A list containing the TSO response message ids """ - return ( - [message["messageId"] for message in response_json["msgData"]] - if "msgData" in response_json - else [] - ) + return [message["messageId"] for message in response_json["msgData"]] if "msgData" in response_json else [] def retrieve_tso_messages(self, response_json): """Parse the TSO response and retrieve all messages. @@ -210,8 +196,4 @@ def retrieve_tso_messages(self, response_json): list A list containing the TSO response messages """ - return [ - message["TSO MESSAGE"]["DATA"] - for message in response_json - if "TSO MESSAGE" in message - ] + return [message["TSO MESSAGE"]["DATA"] for message in response_json if "TSO MESSAGE" in message] diff --git a/src/zosmf/setup.py b/src/zosmf/setup.py index d971de17..ba830f9a 100644 --- a/src/zosmf/setup.py +++ b/src/zosmf/setup.py @@ -1,13 +1,15 @@ import sys -from setuptools import setup, find_namespace_packages + +from setuptools import find_namespace_packages, setup + sys.path.insert(0, "..") from _version import __version__ from setup import resolve_sdk_dep setup( - name='zowe_zosmf_for_zowe_sdk', + name="zowe_zosmf_for_zowe_sdk", version=__version__, - description='Zowe Python SDK - z/OSMF package', + description="Zowe Python SDK - z/OSMF package", url="https://github.com/zowe/zowe-client-python-sdk", author="Guilherme Cartier", author_email="gcartier94@gmail.com", @@ -15,7 +17,8 @@ classifiers=[ "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.7", - "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)"], - install_requires=[resolve_sdk_dep('core', '~=' + __version__)], - packages=find_namespace_packages(include=['zowe.*']) + "License :: OSI Approved :: Eclipse Public License 2.0 (EPL-2.0)", + ], + install_requires=[resolve_sdk_dep("core", "~=" + __version__)], + packages=find_namespace_packages(include=["zowe.*"]), ) diff --git a/src/zosmf/zowe/zosmf_for_zowe_sdk/zosmf.py b/src/zosmf/zowe/zosmf_for_zowe_sdk/zosmf.py index f611a6ad..22e4fa65 100644 --- a/src/zosmf/zowe/zosmf_for_zowe_sdk/zosmf.py +++ b/src/zosmf/zowe/zosmf_for_zowe_sdk/zosmf.py @@ -41,9 +41,7 @@ def get_info(self): json A JSON containing the z/OSMF Info REST API data """ - response_json = self.request_handler.perform_request( - "GET", self.request_arguments - ) + response_json = self.request_handler.perform_request("GET", self.request_arguments) return response_json def list_systems(self): @@ -56,5 +54,5 @@ def list_systems(self): custom_args = self._create_custom_request_arguments() custom_args["url"] = "{}/systems".format(self.request_endpoint) - response_json = self.request_handler.perform_request("GET", custom_args, expected_code = [200]) - return response_json \ No newline at end of file + response_json = self.request_handler.perform_request("GET", custom_args, expected_code=[200]) + return response_json diff --git a/tests/integration/test_zos_console.py b/tests/integration/test_zos_console.py index dba76fb2..4423982b 100644 --- a/tests/integration/test_zos_console.py +++ b/tests/integration/test_zos_console.py @@ -1,7 +1,8 @@ """Integration tests for the Zowe Python SDK z/OS Console package.""" import unittest -from zowe.zos_console_for_zowe_sdk import Console + from zowe.core_for_zowe_sdk import ProfileManager +from zowe.zos_console_for_zowe_sdk import Console class TestConsoleIntegration(unittest.TestCase): @@ -11,15 +12,14 @@ def setUp(self): """Setup fixtures for Console class.""" test_profile = ProfileManager().load(profile_type="zosmf") self.console = Console(test_profile) - + def test_console_command_time_should_return_time(self): """Test the execution of the time command should return the current time""" command_output = self.console.issue_command("D T") - self.assertTrue(command_output['cmd-response'].strip().startswith("IEE136I")) + self.assertTrue(command_output["cmd-response"].strip().startswith("IEE136I")) def test_get_response_should_return_messages(self): """Test that response message can be received from the console""" command_output = self.console.issue_command("D T") response = self.console.get_response(command_output["cmd-response-key"]) self.assertTrue("cmd-response" in response) - diff --git a/tests/integration/test_zos_files.py b/tests/integration/test_zos_files.py index f77a2f91..bba80195 100644 --- a/tests/integration/test_zos_files.py +++ b/tests/integration/test_zos_files.py @@ -1,13 +1,14 @@ """Integration tests for the Zowe Python SDK z/OS Files package.""" -import unittest import json import os -from zowe.zos_files_for_zowe_sdk import Files +import unittest + import urllib3 from zowe.core_for_zowe_sdk import ProfileManager +from zowe.zos_files_for_zowe_sdk import Files -FIXTURES_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),'fixtures') -FILES_FIXTURES_PATH = os.path.join(FIXTURES_PATH, 'files.json') +FIXTURES_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures") +FILES_FIXTURES_PATH = os.path.join(FIXTURES_PATH, "files.json") class TestFilesIntegration(unittest.TestCase): @@ -17,44 +18,43 @@ def setUp(self): """Setup fixtures for Files class.""" test_profile = ProfileManager().load(profile_type="zosmf") self.user_name = test_profile["user"] - with open(FILES_FIXTURES_PATH, 'r') as fixtures_json: + with open(FILES_FIXTURES_PATH, "r") as fixtures_json: self.files_fixtures = json.load(fixtures_json) self.files = Files(test_profile) self.test_member_jcl = f'{self.files_fixtures["TEST_PDS"]}({self.files_fixtures["TEST_MEMBER"]})' self.test_member_generic = f'{self.files_fixtures["TEST_PDS"]}(TEST)' self.test1_zfs_file_system = f'{self.user_name}.{self.files_fixtures["TEST1_ZFS"]}' self.test2_zfs_file_system = f'{self.user_name}.{self.files_fixtures["TEST2_ZFS"]}' - self.create_zfs_options = {"perms": 755,"cylsPri": 10,"cylsSec": 2,"timeout": 20, "volumes": ["VPMVSC"]} + self.create_zfs_options = {"perms": 755, "cylsPri": 10, "cylsSec": 2, "timeout": 20, "volumes": ["VPMVSC"]} self.mount_zfs_file_system_options = {"fs-type": "ZFS", "mode": "rdonly"} def test_list_dsn_should_return_a_list_of_datasets(self): """Executing list_dsn method should return a list of found datasets.""" - + scenarios = [ {"attributes": False, "expected_attributes": ["dsname"]}, - {"attributes": True, "expected_attributes": ["dsname", "migr","vol"]} + {"attributes": True, "expected_attributes": ["dsname", "migr", "vol"]}, ] - - for scenario in scenarios: + for scenario in scenarios: # Get the command output command_output = self.files.list_dsn(self.files_fixtures["TEST_HLQ"], scenario["attributes"]) - + # Assert that command_output['items'] is a list - self.assertIsInstance(command_output['items'], list) - + self.assertIsInstance(command_output["items"], list) + # Assert that command_output['items'] contains at least one item - self.assertGreater(len(command_output['items']), 0) - + self.assertGreater(len(command_output["items"]), 0) + # Assert that the first item in the list has 'dsname' defined - first_item = command_output['items'][0] - self.assertIn('dsname', first_item) - + first_item = command_output["items"][0] + self.assertIn("dsname", first_item) + # Assert that the first item in the list has the expected attributes defined attributes = first_item.keys() for expected_attr in scenario["expected_attributes"]: self.assertIn(expected_attr, attributes) - + def test_list_members_should_return_a_list_of_members(self): """Executing list_dsn_members should return a list of members.""" command_output = self.files.list_dsn_members(self.files_fixtures["TEST_PDS"]) @@ -63,7 +63,7 @@ def test_list_members_should_return_a_list_of_members(self): def test_get_dsn_content_should_return_content_from_dataset(self): """Executing get_dsn_content should return content from dataset.""" command_output = self.files.get_dsn_content(self.test_member_jcl) - self.assertIsInstance(command_output['response'], str) + self.assertIsInstance(command_output["response"], str) def test_get_dsn_content_streamed_should_return_a_raw_response_content(self): """Executing get_dsn_content_streamed should return raw socket response from the server.""" @@ -78,49 +78,51 @@ def test_get_dsn_binary_content_streamed_should_return_a_raw_response_content(se def test_write_to_dsn_should_be_possible(self): """Executing write_to_dsn should be possible.""" command_output = self.files.write_to_dsn(self.test_member_generic, "HELLO WORLD") - self.assertTrue(command_output['response'] == '') - - + self.assertTrue(command_output["response"] == "") + def test_copy_uss_to_dataset_should_be_possible(self): """Executing copy_uss_to_dataset should be possible.""" - command_output = self.files.copy_uss_to_dataset(self.files_fixtures["TEST_USS"],"ZOWE.TESTS.JCL(TEST2)",replace=True) - self.assertTrue(command_output['response']=="") + command_output = self.files.copy_uss_to_dataset( + self.files_fixtures["TEST_USS"], "ZOWE.TESTS.JCL(TEST2)", replace=True + ) + self.assertTrue(command_output["response"] == "") def test_copy_dataset_or_member_should_be_possible(self): """Executing copy_dataset_or_member should be possible.""" test_case = { - "from_dataset_name": self.files_fixtures["TEST_PDS"], - "to_dataset_name": self.files_fixtures["TEST_PDS"], - "from_member_name": self.files_fixtures["TEST_MEMBER"], - "to_member_name": "TEST", - "replace": True + "from_dataset_name": self.files_fixtures["TEST_PDS"], + "to_dataset_name": self.files_fixtures["TEST_PDS"], + "from_member_name": self.files_fixtures["TEST_MEMBER"], + "to_member_name": "TEST", + "replace": True, } command_output = self.files.copy_dataset_or_member(**test_case) - self.assertTrue(command_output['response'] =="") + self.assertTrue(command_output["response"] == "") def test_mount_unmount_zfs_file_system(self): """Mounting a zfs filesystem should be possible""" username = self.user_name.lower() - mount_point = f"/u/{username}/mount" # Assuming a dir called mount exist in zOS USS + mount_point = f"/u/{username}/mount" # Assuming a dir called mount exist in zOS USS # Create a zfs file system zfs_file_system = self.files.create_zFS_file_system(self.test2_zfs_file_system, self.create_zfs_options) - # Mount file system - command_output = self.files.mount_file_system(self.test2_zfs_file_system, mount_point, self.mount_zfs_file_system_options) - self.assertTrue(command_output['response'] == '') + command_output = self.files.mount_file_system( + self.test2_zfs_file_system, mount_point, self.mount_zfs_file_system_options + ) + self.assertTrue(command_output["response"] == "") # List a zfs file system command_output = self.files.list_unix_file_systems(file_system_name=self.test2_zfs_file_system) - self.assertTrue(len(command_output['items']) > 0) + self.assertTrue(len(command_output["items"]) > 0) # Unmount file system command_output = self.files.unmount_file_system(self.test2_zfs_file_system) - self.assertTrue(command_output['response'] == '') + self.assertTrue(command_output["response"] == "") # Delete file system command_output = self.files.delete_zFS_file_system(self.test2_zfs_file_system) - self.assertTrue(command_output['response'] == '') + self.assertTrue(command_output["response"] == "") - #TODO implement tests for download/upload datasets + # TODO implement tests for download/upload datasets diff --git a/tests/integration/test_zos_jobs.py b/tests/integration/test_zos_jobs.py index 224d7b15..e27c5863 100644 --- a/tests/integration/test_zos_jobs.py +++ b/tests/integration/test_zos_jobs.py @@ -1,13 +1,14 @@ """Integration tests for the Zowe Python SDK z/OS Jobs package.""" -import unittest import json import os -from zowe.zos_jobs_for_zowe_sdk import Jobs +import unittest + from zowe.core_for_zowe_sdk import ProfileManager +from zowe.zos_jobs_for_zowe_sdk import Jobs -FIXTURES_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)),'fixtures') -JOBS_FIXTURES_JSON_JSON_PATH = os.path.join(FIXTURES_PATH, 'jobs.json') -SAMPLE_JCL_FIXTURE_PATH = os.path.join(FIXTURES_PATH, 'sample.jcl') +FIXTURES_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures") +JOBS_FIXTURES_JSON_JSON_PATH = os.path.join(FIXTURES_PATH, "jobs.json") +SAMPLE_JCL_FIXTURE_PATH = os.path.join(FIXTURES_PATH, "sample.jcl") class TestJobsIntegration(unittest.TestCase): @@ -16,57 +17,57 @@ class TestJobsIntegration(unittest.TestCase): def setUp(self): """Setup fixtures for Jobs class.""" test_profile = ProfileManager().load(profile_type="zosmf") - with open(JOBS_FIXTURES_JSON_JSON_PATH, 'r') as fixtures_json: + with open(JOBS_FIXTURES_JSON_JSON_PATH, "r") as fixtures_json: self.jobs_fixtures_json = json.load(fixtures_json) self.jobs = Jobs(test_profile) def test_get_job_status_should_return_the_status_of_a_job(self): """Executing the get_job_status method should return the status of a given job""" - execution_output = self.jobs.submit_from_mainframe(self.jobs_fixtures_json['TEST_JCL_MEMBER']) - jobname = execution_output['jobname'] - jobid = execution_output['jobid'] + execution_output = self.jobs.submit_from_mainframe(self.jobs_fixtures_json["TEST_JCL_MEMBER"]) + jobname = execution_output["jobname"] + jobid = execution_output["jobid"] command_output = self.jobs.get_job_status(jobname, jobid) - self.assertIsNotNone(command_output['status']) + self.assertIsNotNone(command_output["status"]) def test_list_jobs_should_return_valid_spool_information(self): """Executing the list_jobs method should return a list of found jobs in JES spool.""" - command_output = self.jobs.list_jobs(owner=self.jobs_fixtures_json['TEST_JCL_OWNER']) + command_output = self.jobs.list_jobs(owner=self.jobs_fixtures_json["TEST_JCL_OWNER"]) self.assertIsInstance(command_output, list) - + def test_change_job_class(self): """Execute the change_jobs_class should execute successfully.""" - execution_output = self.jobs.submit_from_mainframe(self.jobs_fixtures_json['TEST_JCL_MEMBER']) - jobname = execution_output['jobname'] - jobid = execution_output['jobid'] - classname = self.jobs_fixtures_json['TEST_JCL_CLASS'] + execution_output = self.jobs.submit_from_mainframe(self.jobs_fixtures_json["TEST_JCL_MEMBER"]) + jobname = execution_output["jobname"] + jobid = execution_output["jobid"] + classname = self.jobs_fixtures_json["TEST_JCL_CLASS"] command_output = self.jobs.change_job_class(jobname, jobid, classname) expected_class = self.jobs.get_job_status(jobname, jobid) - self.assertEqual(expected_class['class'], classname) + self.assertEqual(expected_class["class"], classname) def test_submit_hold_and_release_job_should_execute_properly(self): """Execute the hold_job should execute successfully.""" - execution_output = self.jobs.submit_from_mainframe(self.jobs_fixtures_json['TEST_JCL_MEMBER']) - jobname = execution_output['jobname'] - jobid = execution_output['jobid'] - command_output = self.jobs.submit_from_mainframe(self.jobs_fixtures_json['TEST_JCL_MEMBER']) + execution_output = self.jobs.submit_from_mainframe(self.jobs_fixtures_json["TEST_JCL_MEMBER"]) + jobname = execution_output["jobname"] + jobid = execution_output["jobid"] + command_output = self.jobs.submit_from_mainframe(self.jobs_fixtures_json["TEST_JCL_MEMBER"]) command_output = self.jobs.hold_job(jobname, jobid) command_output = self.jobs.release_job(jobname, jobid) - self.assertIsNotNone(command_output['jobid']) + self.assertIsNotNone(command_output["jobid"]) def test_submit_from_mainframe_should_execute_properly(self): """Executing the submit_from_mainframe method should execute successfully.""" - command_output = self.jobs.submit_from_mainframe(self.jobs_fixtures_json['TEST_JCL_MEMBER']) - jobid = command_output['jobid'] + command_output = self.jobs.submit_from_mainframe(self.jobs_fixtures_json["TEST_JCL_MEMBER"]) + jobid = command_output["jobid"] self.assertIsNotNone(jobid) def test_submit_from_local_file_should_execute_properly(self): """Executing the submit_from_local_file method should execute successfully.""" command_output = self.jobs.submit_from_local_file(SAMPLE_JCL_FIXTURE_PATH) - jobid = command_output['jobid'] + jobid = command_output["jobid"] self.assertIsNotNone(jobid) def test_submit_plaintext_should_execute_properly(self): """Executing the submit_plaintext method should execute successfully.""" - command_output = self.jobs.submit_plaintext('\n'.join(self.jobs_fixtures_json['TEST_JCL_CODE'])) - jobid = command_output['jobid'] + command_output = self.jobs.submit_plaintext("\n".join(self.jobs_fixtures_json["TEST_JCL_CODE"])) + jobid = command_output["jobid"] self.assertIsNotNone(jobid) diff --git a/tests/integration/test_zos_tso.py b/tests/integration/test_zos_tso.py index 90c87208..6df85a5c 100644 --- a/tests/integration/test_zos_tso.py +++ b/tests/integration/test_zos_tso.py @@ -1,7 +1,8 @@ """Integration tests for the Zowe Python SDK z/OS Tso package.""" import unittest -from zowe.zos_tso_for_zowe_sdk import Tso + from zowe.core_for_zowe_sdk import ProfileManager +from zowe.zos_tso_for_zowe_sdk import Tso class TestTsoIntegration(unittest.TestCase): @@ -35,4 +36,3 @@ def test_ping_tso_session_should_return_failure_for_invalid_session(self): """Executing the ping_tso_session method should return a failure message for invalid TSO session.""" command_output = self.tso.ping_tso_session("INVALID") self.assertEqual(command_output, "Ping failed") - diff --git a/tests/integration/test_zosmf.py b/tests/integration/test_zosmf.py index 10ca2e14..3d8a87ab 100644 --- a/tests/integration/test_zosmf.py +++ b/tests/integration/test_zosmf.py @@ -1,7 +1,8 @@ """Integration tests for the Zowe Python SDK z/OSMF package.""" import unittest -from zowe.zosmf_for_zowe_sdk import Zosmf + from zowe.core_for_zowe_sdk import ProfileManager +from zowe.zosmf_for_zowe_sdk import Zosmf class TestZosmfIntegration(unittest.TestCase): @@ -20,4 +21,4 @@ def test_get_info_should_return_valid_response(self): def test_list_systems_should_return_valid_response(self): """Executing the list_systems method should return a valid response.""" command_output = self.zosmf.list_systems() - self.assertIsInstance(command_output, dict) \ No newline at end of file + self.assertIsInstance(command_output, dict) diff --git a/tests/unit/test_zos_console.py b/tests/unit/test_zos_console.py index 3a7c494d..d6e1d320 100644 --- a/tests/unit/test_zos_console.py +++ b/tests/unit/test_zos_console.py @@ -1,28 +1,30 @@ """Unit tests for the Zowe Python SDK z/OS Console package.""" import unittest -from zowe.zos_console_for_zowe_sdk import Console from unittest import mock +from zowe.zos_console_for_zowe_sdk import Console + class TestConsoleClass(unittest.TestCase): """Console class unit tests.""" def setUp(self): """Setup fixtures for Console class.""" - self.session_details = {"host": "mock-url.com", - "user": "Username", - "password": "Password", - "port": 443, - "rejectUnauthorized": True - } + self.session_details = { + "host": "mock-url.com", + "user": "Username", + "password": "Password", + "port": 443, + "rejectUnauthorized": True, + } def test_object_should_be_instance_of_class(self): """Created object should be instance of Console class.""" console = Console(self.session_details) self.assertIsInstance(console, Console) - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_get_response_should_return_messages(self, mock_send_request): """Getting z/OS Console response messages on sending a response key""" mock_send_request.return_value = mock.Mock(headers={"Content-type": "application/json"}, status_code=200) diff --git a/tests/unit/test_zos_files.py b/tests/unit/test_zos_files.py index 85d4027d..927e80d5 100644 --- a/tests/unit/test_zos_files.py +++ b/tests/unit/test_zos_files.py @@ -1,6 +1,7 @@ """Unit tests for the Zowe Python SDK z/OS Files package.""" import re from unittest import TestCase, mock + from zowe.zos_files_for_zowe_sdk import Files, exceptions @@ -9,19 +10,20 @@ class TestFilesClass(TestCase): def setUp(self): """Setup fixtures for File class.""" - self.test_profile = {"host": "mock-url.com", - "user": "Username", - "password": "Password", - "port": 443, - "rejectUnauthorized": True - } + self.test_profile = { + "host": "mock-url.com", + "user": "Username", + "password": "Password", + "port": 443, + "rejectUnauthorized": True, + } def test_object_should_be_instance_of_class(self): """Created object should be instance of Files class.""" files = Files(self.test_profile) self.assertIsInstance(files, Files) - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_delete_uss(self, mock_send_request): """Test deleting a directory recursively sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=204) @@ -29,35 +31,41 @@ def test_delete_uss(self, mock_send_request): Files(self.test_profile).delete_uss("filepath_name", recursive=True) mock_send_request.assert_called_once() - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_create_zFS_file_system(self, mock_send_request): """Test creating a zfs sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=201) - Files(self.test_profile).create_zFS_file_system("file_system_name", {"perms":100, "cylsPri": 16777213, "cylsSec": 16777215}) + Files(self.test_profile).create_zFS_file_system( + "file_system_name", {"perms": 100, "cylsPri": 16777213, "cylsSec": 16777215} + ) mock_send_request.assert_called_once() - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_delete_zFS_file_system(self, mock_send_request): """Test deleting a zfs sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=204) Files(self.test_profile).delete_zFS_file_system("file_system_name") mock_send_request.assert_called_once() - + def test_invalid_permission(self): """Test that the correct exception is raised when an invalid permission option is provided""" with self.assertRaises(exceptions.InvalidPermsOption) as e_info: - Files(self.test_profile).create_zFS_file_system("file_system_name", {"perms": -1, "cylsPri": 16777213, "cylsSec": 16777215}) + Files(self.test_profile).create_zFS_file_system( + "file_system_name", {"perms": -1, "cylsPri": 16777213, "cylsSec": 16777215} + ) self.assertEqual(str(e_info.exception), "Invalid zos-files create command 'perms' option: -1") def test_invalid_memory_allocation(self): """Test that the correct exception is raised when an invalid memory allocation option is provided""" with self.assertRaises(exceptions.MaxAllocationQuantityExceeded) as e_info: - Files(self.test_profile).create_zFS_file_system("file_system_name", {"perms": 775, "cylsPri": 1677755513, "cylsSec": 16777215}) + Files(self.test_profile).create_zFS_file_system( + "file_system_name", {"perms": 775, "cylsPri": 1677755513, "cylsSec": 16777215} + ) self.assertEqual(str(e_info.exception), "Maximum allocation quantity of 16777215 exceeded") - - @mock.patch('requests.Session.send') + + @mock.patch("requests.Session.send") def test_mount_zFS_file_system(self, mock_send_request): """Test mounting a zfs sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=204) @@ -65,7 +73,7 @@ def test_mount_zFS_file_system(self, mock_send_request): Files(self.test_profile).mount_file_system("file_system_name", "mount_point") mock_send_request.assert_called_once() - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_unmount_zFS_file_system(self, mock_send_request): """Test unmounting a zfs sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=204) @@ -73,22 +81,17 @@ def test_unmount_zFS_file_system(self, mock_send_request): Files(self.test_profile).unmount_file_system("file_system_name") mock_send_request.assert_called_once() - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_list_dsn(self, mock_send_request): """Test list DSN sends request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) - test_values = [ - ('MY.DSN',False), - ('MY.DSN',True) - ] + test_values = [("MY.DSN", False), ("MY.DSN", True)] for test_case in test_values: Files(self.test_profile).list_dsn(*test_case) mock_send_request.assert_called() - - - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_list_zFS_file_system(self, mock_send_request): """Test unmounting a zfs sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) @@ -96,71 +99,70 @@ def test_list_zFS_file_system(self, mock_send_request): Files(self.test_profile).list_unix_file_systems("file_system_name") mock_send_request.assert_called_once() - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_recall_migrated_dataset(self, mock_send_request): """Test recalling migrated data set sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) Files(self.test_profile).recall_migrated_dataset("dataset_name") mock_send_request.assert_called_once() - - @mock.patch('requests.Session.send') + + @mock.patch("requests.Session.send") def test_copy_uss_to_dataset(self, mock_send_request): """Test copy_uss_to_dataset sends a request""" - + mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) - Files(self.test_profile).copy_uss_to_dataset("from_filename","to_dataset_name","to_member_name",replace=True) - - + Files(self.test_profile).copy_uss_to_dataset("from_filename", "to_dataset_name", "to_member_name", replace=True) + mock_send_request.assert_called_once() - + def test_copy_dataset_or_member_raises_exception(self): """Test copying a data set or member raises error when assigning invalid values to enq parameter""" test_case = { - "from_dataset_name": "MY.OLD.DSN", - "to_dataset_name": "MY.NEW.DSN", - "from_member_name": "MYMEM1", - "to_member_name": "MYMEM2", - "enq": "RANDOM", - "replace": True + "from_dataset_name": "MY.OLD.DSN", + "to_dataset_name": "MY.NEW.DSN", + "from_member_name": "MYMEM1", + "to_member_name": "MYMEM2", + "enq": "RANDOM", + "replace": True, } with self.assertRaises(ValueError) as e_info: Files(self.test_profile).copy_dataset_or_member(**test_case) self.assertEqual(str(e_info.exception), "Invalid value for enq.") - - @mock.patch('requests.Session.send') + + @mock.patch("requests.Session.send") def test_copy_dataset_or_member(self, mock_send_request): """Test copying a data set or member sends a request""" - + mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) test_values = [ - { - "from_dataset_name": "MY.OLD.DSN", - "to_dataset_name": "MY.NEW.DSN", - "from_member_name": "MYMEM1", - "to_member_name": "MYMEM2", - "volser":'ABC', - "alias":False, - "enq": "SHRW", - "replace": False - }, - { - "from_dataset_name": "MY.OLD.DSN", - "to_dataset_name": "MY.NEW.DSN", - "from_member_name": "MYMEM1", - "to_member_name": "MYMEM2", - "volser":'ABC', - "alias":True, - "enq": "SHRW", - "replace": True - } + { + "from_dataset_name": "MY.OLD.DSN", + "to_dataset_name": "MY.NEW.DSN", + "from_member_name": "MYMEM1", + "to_member_name": "MYMEM2", + "volser": "ABC", + "alias": False, + "enq": "SHRW", + "replace": False, + }, + { + "from_dataset_name": "MY.OLD.DSN", + "to_dataset_name": "MY.NEW.DSN", + "from_member_name": "MYMEM1", + "to_member_name": "MYMEM2", + "volser": "ABC", + "alias": True, + "enq": "SHRW", + "replace": True, + }, ] for test_case in test_values: Files(self.test_profile).copy_dataset_or_member(**test_case) mock_send_request.assert_called() - + def test_recall_migrated_dataset_parameterized(self): """Testing recall migrated_dataset with different values""" @@ -176,18 +178,17 @@ def test_recall_migrated_dataset_parameterized(self): for test_case in test_values: files_test_profile.request_handler.perform_request = mock.Mock() - data = { - "request": "hrecall", - "wait": test_case[1] - } + data = {"request": "hrecall", "wait": test_case[1]} files_test_profile.recall_migrated_dataset(test_case[0], test_case[1]) custom_args = files_test_profile._create_custom_request_arguments() custom_args["json"] = data custom_args["url"] = "https://mock-url.com:443/zosmf/restfiles/ds/{}".format(test_case[0]) - files_test_profile.request_handler.perform_request.assert_called_once_with("PUT", custom_args, expected_code=[200]) + files_test_profile.request_handler.perform_request.assert_called_once_with( + "PUT", custom_args, expected_code=[200] + ) - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_delete_migrated_data_set(self, mock_send_request): """Test deleting a migrated data set sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) @@ -216,16 +217,17 @@ def test_delete_migrated_data_set_parameterized(self): "request": "hdelete", "purge": test_case[1], "wait": test_case[2], - } files_test_profile.delete_migrated_data_set(test_case[0], test_case[1], test_case[2]) custom_args = files_test_profile._create_custom_request_arguments() custom_args["json"] = data custom_args["url"] = "https://mock-url.com:443/zosmf/restfiles/ds/{}".format(test_case[0]) - files_test_profile.request_handler.perform_request.assert_called_once_with("PUT", custom_args, expected_code=[200]) + files_test_profile.request_handler.perform_request.assert_called_once_with( + "PUT", custom_args, expected_code=[200] + ) - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_migrate_data_set(self, mock_send_request): """Test migrating a data set sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) @@ -258,9 +260,11 @@ def test_migrate_data_set_parameterized(self): custom_args = files_test_profile._create_custom_request_arguments() custom_args["json"] = data custom_args["url"] = "https://mock-url.com:443/zosmf/restfiles/ds/{}".format(test_case[0]) - files_test_profile.request_handler.perform_request.assert_called_once_with("PUT", custom_args, expected_code=[200]) + files_test_profile.request_handler.perform_request.assert_called_once_with( + "PUT", custom_args, expected_code=[200] + ) - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_rename_dataset(self, mock_send_request): """Test renaming dataset sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) @@ -271,9 +275,9 @@ def test_rename_dataset(self, mock_send_request): def test_rename_dataset_parametrized(self): """Test renaming a dataset with different values""" test_values = [ - (('DSN.OLD', "DSN.NEW"), True), - (('DS.NAME.CURRENT', "DS.NAME.NEW"), True), - (('MY.OLD.DSN', "MY.NEW.DSN"), True), + (("DSN.OLD", "DSN.NEW"), True), + (("DS.NAME.CURRENT", "DS.NAME.NEW"), True), + (("MY.OLD.DSN", "MY.NEW.DSN"), True), ] files_test_profile = Files(self.test_profile) @@ -285,7 +289,7 @@ def test_rename_dataset_parametrized(self): "request": "rename", "from-dataset": { "dsn": test_case[0][0].strip(), - } + }, } files_test_profile.rename_dataset(test_case[0][0], test_case[0][1]) @@ -293,9 +297,11 @@ def test_rename_dataset_parametrized(self): custom_args = files_test_profile._create_custom_request_arguments() custom_args["json"] = data custom_args["url"] = "https://mock-url.com:443/zosmf/restfiles/ds/{}".format(test_case[0][1]) - files_test_profile.request_handler.perform_request.assert_called_once_with("PUT", custom_args, expected_code=[200]) + files_test_profile.request_handler.perform_request.assert_called_once_with( + "PUT", custom_args, expected_code=[200] + ) - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_rename_dataset_member(self, mock_send_request): """Test renaming dataset member sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) @@ -312,11 +318,11 @@ def test_rename_dataset_member_raises_exception(self): def test_rename_dataset_member_parametrized(self): """Test renaming a dataset member with different values""" test_values = [ - (('DSN', "MBROLD$", "MBRNEW$", "EXCLU"), True), - (('DSN', "MBROLD#", "MBRNE#", "SHRW"), True), - (('DSN', "MBROLD", "MBRNEW", "INVALID"), False), - (('DATA.SET.@NAME', 'MEMBEROLD', 'MEMBERNEW'), True), - (('DS.NAME', "MONAME", "MNNAME"), True), + (("DSN", "MBROLD$", "MBRNEW$", "EXCLU"), True), + (("DSN", "MBROLD#", "MBRNE#", "SHRW"), True), + (("DSN", "MBROLD", "MBRNEW", "INVALID"), False), + (("DATA.SET.@NAME", "MEMBEROLD", "MEMBERNEW"), True), + (("DS.NAME", "MONAME", "MNNAME"), True), ] files_test_profile = Files(self.test_profile) @@ -329,7 +335,7 @@ def test_rename_dataset_member_parametrized(self): "from-dataset": { "dsn": test_case[0][0].strip(), "member": test_case[0][1].strip(), - } + }, } if len(test_case[0]) > 3: @@ -340,11 +346,12 @@ def test_rename_dataset_member_parametrized(self): custom_args["json"] = data ds_path = "{}({})".format(test_case[0][0], test_case[0][2]) ds_path_adjusted = files_test_profile._encode_uri_component(ds_path) - self.assertNotRegex(ds_path_adjusted, r'[\$\@\#]') - self.assertRegex(ds_path_adjusted, r'[\(' + re.escape(test_case[0][2]) + r'\)]') + self.assertNotRegex(ds_path_adjusted, r"[\$\@\#]") + self.assertRegex(ds_path_adjusted, r"[\(" + re.escape(test_case[0][2]) + r"\)]") custom_args["url"] = "https://mock-url.com:443/zosmf/restfiles/ds/{}".format(ds_path_adjusted) - files_test_profile.request_handler.perform_request.assert_called_once_with("PUT", custom_args, - expected_code=[200]) + files_test_profile.request_handler.perform_request.assert_called_once_with( + "PUT", custom_args, expected_code=[200] + ) else: with self.assertRaises(ValueError) as e_info: files_test_profile.rename_dataset_member(*test_case[0]) @@ -353,13 +360,9 @@ def test_rename_dataset_member_parametrized(self): def test_create_data_set_raises_error_without_required_arguments(self): """Test not providing required arguments raises an error""" with self.assertRaises(ValueError) as e_info: - obj = Files(self.test_profile).create_data_set("DSNAME123", options={ - "alcunit": "CYL", - "dsorg": "PO", - "recfm": "FB", - "blksize": 6160, - "dirblk": 25 - }) + obj = Files(self.test_profile).create_data_set( + "DSNAME123", options={"alcunit": "CYL", "dsorg": "PO", "recfm": "FB", "blksize": 6160, "dirblk": 25} + ) self.assertEqual(str(e_info.exception), "If 'like' is not specified, you must specify 'primary' or 'lrecl'.") def test_create_data_set_raises_error_with_invalid_arguments_parameterized(self): @@ -372,7 +375,7 @@ def test_create_data_set_raises_error_with_invalid_arguments_parameterized(self) "dirblk": 5, "recfm": "FB", "blksize": 6160, - "lrecl": 80 + "lrecl": 80, }, { "dsorg": "PO", @@ -381,7 +384,7 @@ def test_create_data_set_raises_error_with_invalid_arguments_parameterized(self) "recfm": "invalid", "blksize": 32760, "lrecl": 260, - "dirblk": 25 + "dirblk": 25, }, { "alcunit": "CYL", @@ -390,7 +393,7 @@ def test_create_data_set_raises_error_with_invalid_arguments_parameterized(self) "dirblk": 5, "recfm": "FB", "blksize": 6160, - "lrecl": 80 + "lrecl": 80, }, { "dsorg": "PO", @@ -399,7 +402,7 @@ def test_create_data_set_raises_error_with_invalid_arguments_parameterized(self) "recfm": "U", "blksize": 27998, "lrecl": 27998, - "dirblk": 0 + "dirblk": 0, }, { "alcunit": "CYL", @@ -408,8 +411,8 @@ def test_create_data_set_raises_error_with_invalid_arguments_parameterized(self) "dirblk": 5, "recfm": "FB", "blksize": 6160, - "lrecl": 80 - } + "lrecl": 80, + }, ] for test_case in test_values: @@ -419,47 +422,67 @@ def test_create_data_set_raises_error_with_invalid_arguments_parameterized(self) def test_create_dataset_parameterized(self): """Test create dataset with different values""" test_values = [ - (("DSN", { - "alcunit": "CYL", - "dsorg": "PO", - "primary": 1, - "dirblk": 5, - "recfm": "FB", - "blksize": 6160, - "lrecl": 80 - }), True), - (("DSN", { - "alcunit": "CYL", - "dsorg": "PO", - "primary": 1, - "recfm": "FB", - "blksize": 6160, - "lrecl": 80, - "dirblk": 25 - }), True), - (("DSN", { - "dsorg": "PO", - "alcunit": "CYL", - "primary": 1, - "recfm": "VB", - "blksize": 32760, - "lrecl": 260, - "dirblk": 25 - }), True), - (("DSN", { - "alcunit": "CYL", - "dsorg": "PS", - "primary": 1, - "recfm": "FB", - "blksize": 6160, - "lrecl": 80 - }), True), - (("DSN", { - "alcunit": "CYL", - "dsorg": "PS", - "recfm": "FB", - "blksize": 6160, - }), False), + ( + ( + "DSN", + { + "alcunit": "CYL", + "dsorg": "PO", + "primary": 1, + "dirblk": 5, + "recfm": "FB", + "blksize": 6160, + "lrecl": 80, + }, + ), + True, + ), + ( + ( + "DSN", + { + "alcunit": "CYL", + "dsorg": "PO", + "primary": 1, + "recfm": "FB", + "blksize": 6160, + "lrecl": 80, + "dirblk": 25, + }, + ), + True, + ), + ( + ( + "DSN", + { + "dsorg": "PO", + "alcunit": "CYL", + "primary": 1, + "recfm": "VB", + "blksize": 32760, + "lrecl": 260, + "dirblk": 25, + }, + ), + True, + ), + ( + ("DSN", {"alcunit": "CYL", "dsorg": "PS", "primary": 1, "recfm": "FB", "blksize": 6160, "lrecl": 80}), + True, + ), + ( + ( + "DSN", + { + "alcunit": "CYL", + "dsorg": "PS", + "recfm": "FB", + "blksize": 6160, + }, + ), + False, + ), ] files_test_profile = Files(self.test_profile) @@ -472,13 +495,17 @@ def test_create_dataset_parameterized(self): custom_args = files_test_profile._create_custom_request_arguments() custom_args["json"] = test_case[0][1] custom_args["url"] = "https://mock-url.com:443/zosmf/restfiles/ds/{}".format(test_case[0][0]) - files_test_profile.request_handler.perform_request.assert_called_once_with("POST", custom_args, expected_code=[201]) + files_test_profile.request_handler.perform_request.assert_called_once_with( + "POST", custom_args, expected_code=[201] + ) else: with self.assertRaises(ValueError) as e_info: files_test_profile.create_data_set(*test_case[0]) - self.assertEqual(str(e_info.exception), "If 'like' is not specified, you must specify 'primary' or 'lrecl'.") + self.assertEqual( + str(e_info.exception), "If 'like' is not specified, you must specify 'primary' or 'lrecl'." + ) - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_create_default_dataset(self, mock_send_request): """Test creating a default data set sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=201) @@ -510,7 +537,7 @@ def test_create_default_dataset_parameterized(self): "dirblk": 5, "recfm": "FB", "blksize": 6160, - "lrecl": 80 + "lrecl": 80, }, "sequential": { "alcunit": "CYL", @@ -518,7 +545,7 @@ def test_create_default_dataset_parameterized(self): "primary": 1, "recfm": "FB", "blksize": 6160, - "lrecl": 80 + "lrecl": 80, }, "classic": { "alcunit": "CYL", @@ -527,7 +554,7 @@ def test_create_default_dataset_parameterized(self): "recfm": "FB", "blksize": 6160, "lrecl": 80, - "dirblk": 25 + "dirblk": 25, }, "c": { "dsorg": "PO", @@ -536,7 +563,7 @@ def test_create_default_dataset_parameterized(self): "recfm": "VB", "blksize": 32760, "lrecl": 260, - "dirblk": 25 + "dirblk": 25, }, "binary": { "dsorg": "PO", @@ -545,8 +572,8 @@ def test_create_default_dataset_parameterized(self): "recfm": "U", "blksize": 27998, "lrecl": 27998, - "dirblk": 25 - } + "dirblk": 25, + }, } if test_case[1]: @@ -554,7 +581,9 @@ def test_create_default_dataset_parameterized(self): custom_args = files_test_profile._create_custom_request_arguments() custom_args["json"] = options.get(test_case[0][1]) custom_args["url"] = "https://mock-url.com:443/zosmf/restfiles/ds/{}".format(test_case[0][0]) - files_test_profile.request_handler.perform_request.assert_called_once_with("POST", custom_args, expected_code=[201]) + files_test_profile.request_handler.perform_request.assert_called_once_with( + "POST", custom_args, expected_code=[201] + ) else: with self.assertRaises(ValueError) as e_info: files_test_profile.create_default_data_set(*test_case[0]) diff --git a/tests/unit/test_zos_jobs.py b/tests/unit/test_zos_jobs.py index 3b683d36..5bb93528 100644 --- a/tests/unit/test_zos_jobs.py +++ b/tests/unit/test_zos_jobs.py @@ -1,6 +1,7 @@ """Unit tests for the Zowe Python SDK z/OS Jobs package.""" from unittest import TestCase, mock + from zowe.zos_jobs_for_zowe_sdk import Jobs @@ -14,69 +15,69 @@ def setUp(self): "user": "Username", "password": "Password", "port": 443, - "rejectUnauthorized": True + "rejectUnauthorized": True, } def test_object_should_be_instance_of_class(self): """Created object should be instance of Jobs class.""" jobs = Jobs(self.test_profile) self.assertIsInstance(jobs, Jobs) - - @mock.patch('requests.Session.send') + + @mock.patch("requests.Session.send") def test_cancel_job(self, mock_send_request): """Test cancelling a job sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) - Jobs(self.test_profile).cancel_job("TESTJOB2","JOB00084") + Jobs(self.test_profile).cancel_job("TESTJOB2", "JOB00084") mock_send_request.assert_called_once() - - @mock.patch('requests.Session.send') + + @mock.patch("requests.Session.send") def test_hold_job(self, mock_send_request): """Test holding a job sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) - Jobs(self.test_profile).hold_job("TESTJOB2","JOB00084") + Jobs(self.test_profile).hold_job("TESTJOB2", "JOB00084") mock_send_request.assert_called_once() - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_modified_version_hold_job(self, mock_send_request): """Test holding a job sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) with self.assertRaises(ValueError): - Jobs(self.test_profile).hold_job("TESTJOB2","JOB00084",modify_version="3.0") - - @mock.patch('requests.Session.send') + Jobs(self.test_profile).hold_job("TESTJOB2", "JOB00084", modify_version="3.0") + + @mock.patch("requests.Session.send") def test_modified_version_release_job(self, mock_send_request): """Test holding a job sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) with self.assertRaises(ValueError): - Jobs(self.test_profile).release_job("TESTJOB2","JOB00084",modify_version="3.0") - - @mock.patch('requests.Session.send') + Jobs(self.test_profile).release_job("TESTJOB2", "JOB00084", modify_version="3.0") + + @mock.patch("requests.Session.send") def test_release_job(self, mock_send_request): """Test releasing a job sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) - Jobs(self.test_profile).release_job("TESTJOB2","JOB00084") + Jobs(self.test_profile).release_job("TESTJOB2", "JOB00084") mock_send_request.assert_called_once() - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_change_job_class(self, mock_send_request): """Test changing the job class sends a request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) - Jobs(self.test_profile).change_job_class("TESTJOB2","JOB00084","A") + Jobs(self.test_profile).change_job_class("TESTJOB2", "JOB00084", "A") mock_send_request.assert_called_once() - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_modified_version_error(self, mock_send_request): """Test modified version should raise value error""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) with self.assertRaises(ValueError): - Jobs(self.test_profile).change_job_class("TESTJOB2","JOB00084","A",modify_version="3.0") + Jobs(self.test_profile).change_job_class("TESTJOB2", "JOB00084", "A", modify_version="3.0") def test_cancel_job_modify_version_parameterized(self): """Test cancelling a job with different values sends the expected request""" @@ -102,9 +103,11 @@ def test_cancel_job_modify_version_parameterized(self): } job_url = "{}/{}".format(test_case[0][0], test_case[0][1]) job_url_adjusted = jobs_test_object._encode_uri_component(job_url) - self.assertNotRegex(job_url_adjusted, r'\$') + self.assertNotRegex(job_url_adjusted, r"\$") custom_args["url"] = "https://mock-url.com:443/zosmf/restjobs/jobs/{}".format(job_url_adjusted) - jobs_test_object.request_handler.perform_request.assert_called_once_with("PUT", custom_args, expected_code=[202, 200]) + jobs_test_object.request_handler.perform_request.assert_called_once_with( + "PUT", custom_args, expected_code=[202, 200] + ) else: with self.assertRaises(ValueError) as e_info: jobs_test_object.cancel_job(*test_case[0]) diff --git a/tests/unit/test_zos_tso.py b/tests/unit/test_zos_tso.py index fea0594a..adb4ece2 100644 --- a/tests/unit/test_zos_tso.py +++ b/tests/unit/test_zos_tso.py @@ -1,6 +1,7 @@ """Unit tests for the Zowe Python SDK z/OS TSO package.""" import unittest + from zowe.zos_tso_for_zowe_sdk import Tso @@ -9,14 +10,15 @@ class TestTsoClass(unittest.TestCase): def setUp(self): """Setup fixtures for Tso class.""" - self.connection_dict = {"host": "mock-url.com", - "user": "Username", - "password": "Password", - "port": 443, - "rejectUnauthorized": True - } + self.connection_dict = { + "host": "mock-url.com", + "user": "Username", + "password": "Password", + "port": 443, + "rejectUnauthorized": True, + } def test_object_should_be_instance_of_class(self): """Created object should be instance of Tso class.""" tso = Tso(self.connection_dict) - self.assertIsInstance(tso, Tso) \ No newline at end of file + self.assertIsInstance(tso, Tso) diff --git a/tests/unit/test_zosmf.py b/tests/unit/test_zosmf.py index 00e38a52..91a81e10 100644 --- a/tests/unit/test_zosmf.py +++ b/tests/unit/test_zosmf.py @@ -2,6 +2,7 @@ import unittest from unittest import mock + from zowe.zosmf_for_zowe_sdk import Zosmf @@ -10,21 +11,22 @@ class TestZosmfClass(unittest.TestCase): def setUp(self): """Setup fixtures for Zosmf class.""" - self.connection_dict = {"host": "mock-url.com", - "user": "Username", - "password": "Password", - "port": 443, - "rejectUnauthorized": True - } + self.connection_dict = { + "host": "mock-url.com", + "user": "Username", + "password": "Password", + "port": 443, + "rejectUnauthorized": True, + } def test_object_should_be_instance_of_class(self): """Created object should be instance of Zosmf class.""" zosmf = Zosmf(self.connection_dict) self.assertIsInstance(zosmf, Zosmf) - @mock.patch('requests.Session.send') + @mock.patch("requests.Session.send") def test_list_systems(self, mock_send_request): """Listing z/OSMF systems should send a REST request""" mock_send_request.return_value = mock.Mock(headers={"Content-Type": "application/json"}, status_code=200) Zosmf(self.connection_dict).list_systems() - mock_send_request.assert_called_once() \ No newline at end of file + mock_send_request.assert_called_once() diff --git a/tests/unit/test_zowe_core.py b/tests/unit/test_zowe_core.py index 54a91739..5763cf51 100644 --- a/tests/unit/test_zowe_core.py +++ b/tests/unit/test_zowe_core.py @@ -2,32 +2,31 @@ # Including necessary paths import base64 -import commentjson import importlib.util import json -import keyring import os import shutil import unittest - -from jsonschema import validate, ValidationError, SchemaError -from pyfakefs.fake_filesystem_unittest import TestCase from unittest import mock -from zowe.core_for_zowe_sdk.validators import validate_config_json +import commentjson +import keyring +from jsonschema import SchemaError, ValidationError, validate +from pyfakefs.fake_filesystem_unittest import TestCase from zowe.core_for_zowe_sdk import ( ApiConnection, ConfigFile, - ProfileManager, CredentialManager, + ProfileManager, RequestHandler, SdkApi, ZosmfProfile, + constants, + custom_warnings, exceptions, session_constants, - custom_warnings, - constants, ) +from zowe.core_for_zowe_sdk.validators import validate_config_json FIXTURES_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "fixtures") CWD = os.getcwd() @@ -79,12 +78,7 @@ class TestSdkApiClass(TestCase): def setUp(self): """Setup fixtures for SdkApi class.""" - common_props = { - "host": "mock-url.com", - "port": 443, - "protocol": "https", - "rejectUnauthorized": True - } + common_props = {"host": "mock-url.com", "port": 443, "protocol": "https", "rejectUnauthorized": True} self.basic_props = {**common_props, "user": "Username", "password": "Password"} self.bearer_props = {**common_props, "tokenValue": "BearerToken"} self.token_props = { @@ -131,12 +125,12 @@ def test_encode_uri_component(self): sdk_api = SdkApi(self.basic_props, self.default_url) - actual_not_empty = sdk_api._encode_uri_component('MY.STRING@.TEST#.$HERE(MBR#NAME)') - expected_not_empty = 'MY.STRING%40.TEST%23.%24HERE(MBR%23NAME)' + actual_not_empty = sdk_api._encode_uri_component("MY.STRING@.TEST#.$HERE(MBR#NAME)") + expected_not_empty = "MY.STRING%40.TEST%23.%24HERE(MBR%23NAME)" self.assertEqual(actual_not_empty, expected_not_empty) - actual_wildcard = sdk_api._encode_uri_component('GET.#DS.*') - expected_wildcard = 'GET.%23DS.*' + actual_wildcard = sdk_api._encode_uri_component("GET.#DS.*") + expected_wildcard = "GET.%23DS.*" self.assertEqual(actual_wildcard, expected_wildcard) actual_none = sdk_api._encode_uri_component(None) @@ -178,6 +172,7 @@ def test_object_should_be_instance_of_class(self): zosmf_profile = ZosmfProfile(self.profile_name) self.assertIsInstance(zosmf_profile, ZosmfProfile) + class TestZosmfProfileManager(TestCase): """ProfileManager class unit tests.""" @@ -187,29 +182,15 @@ def setUp(self): self.session_arguments = {"verify": False} self.setUpPyfakefs() self.original_file_path = os.path.join(FIXTURES_PATH, "zowe.config.json") - self.original_user_file_path = os.path.join( - FIXTURES_PATH, "zowe.config.user.json" - ) - self.original_invalid_file_path = os.path.join( - FIXTURES_PATH, "invalid.zowe.config.json" - ) - self.original_nested_file_path = os.path.join( - FIXTURES_PATH, "nested.zowe.config.json" - ) - self.original_schema_file_path = os.path.join( - FIXTURES_PATH, "zowe.schema.json" - ) - self.original_invalid_schema_file_path = os.path.join( - FIXTURES_PATH, "invalid.zowe.schema.json" - ) - self.original_invalidUri_file_path = os.path.join( - FIXTURES_PATH, "invalidUri.zowe.config.json" - ) - self.original_invalidUri_schema_file_path = os.path.join( - FIXTURES_PATH, "invalidUri.zowe.schema.json" - ) - - loader = importlib.util.find_spec('jsonschema') + self.original_user_file_path = os.path.join(FIXTURES_PATH, "zowe.config.user.json") + self.original_invalid_file_path = os.path.join(FIXTURES_PATH, "invalid.zowe.config.json") + self.original_nested_file_path = os.path.join(FIXTURES_PATH, "nested.zowe.config.json") + self.original_schema_file_path = os.path.join(FIXTURES_PATH, "zowe.schema.json") + self.original_invalid_schema_file_path = os.path.join(FIXTURES_PATH, "invalid.zowe.schema.json") + self.original_invalidUri_file_path = os.path.join(FIXTURES_PATH, "invalidUri.zowe.config.json") + self.original_invalidUri_schema_file_path = os.path.join(FIXTURES_PATH, "invalidUri.zowe.schema.json") + + loader = importlib.util.find_spec("jsonschema") module_path = loader.origin self.fs.add_real_directory(os.path.dirname(module_path)) @@ -255,10 +236,13 @@ def test_autodiscovery_and_base_profile_loading(self, get_pass_func): os.chdir(CWD) shutil.copy(self.original_file_path, cwd_up_file_path) - self.setUpCreds(cwd_up_file_path, { - "profiles.base.properties.user": "user", - "profiles.base.properties.password": "password", - }) + self.setUpCreds( + cwd_up_file_path, + { + "profiles.base.properties.user": "user", + "profiles.base.properties.password": "password", + }, + ) # Test prof_manager = ProfileManager() @@ -284,10 +268,13 @@ def test_custom_file_and_custom_profile_loading(self, get_pass_func): custom_file_path = os.path.join(self.custom_dir, self.custom_filename) shutil.copy(self.original_file_path, custom_file_path) - self.setUpCreds(custom_file_path, { - "profiles.zosmf.properties.user": "user", - "profiles.zosmf.properties.password": "password", - }) + self.setUpCreds( + custom_file_path, + { + "profiles.zosmf.properties.user": "user", + "profiles.zosmf.properties.password": "password", + }, + ) # Test prof_manager = ProfileManager(appname=self.custom_appname) @@ -315,10 +302,13 @@ def test_custom_file_and_custom_profile_loading_with_nested_profile(self, get_pa custom_file_path = os.path.join(self.custom_dir, self.custom_filename) shutil.copy(self.original_nested_file_path, custom_file_path) - self.setUpCreds(custom_file_path, { - "profiles.zosmf.properties.user": "user", - "profiles.zosmf.properties.password": "password", - }) + self.setUpCreds( + custom_file_path, + { + "profiles.zosmf.properties.user": "user", + "profiles.zosmf.properties.password": "password", + }, + ) # Test prof_manager = ProfileManager(appname=self.custom_appname) @@ -326,11 +316,7 @@ def test_custom_file_and_custom_profile_loading_with_nested_profile(self, get_pa props: dict = prof_manager.load(profile_name="lpar1.zosmf", validate_schema=False) self.assertEqual(prof_manager.config_filepath, custom_file_path) - expected_props = { - "host": "example1.com", - "rejectUnauthorized": True, - "port": 443 - } + expected_props = {"host": "example1.com", "rejectUnauthorized": True, "port": 443} self.assertEqual(props, expected_props) @mock.patch("keyring.get_password", side_effect=keyring_get_password) @@ -347,10 +333,13 @@ def test_profile_loading_with_user_overridden_properties(self, get_pass_func): shutil.copy(self.original_file_path, cwd_up_file_path) shutil.copy(self.original_user_file_path, cwd_up_dir_path) - self.setUpCreds(cwd_up_file_path, { - "profiles.zosmf.properties.user": "user", - "profiles.zosmf.properties.password": "password", - }) + self.setUpCreds( + cwd_up_file_path, + { + "profiles.zosmf.properties.user": "user", + "profiles.zosmf.properties.password": "password", + }, + ) # Test prof_manager = ProfileManager() @@ -377,9 +366,7 @@ def test_profile_loading_exception(self, get_pass_func): with self.assertWarns(custom_warnings.ProfileNotFoundWarning): # Setup cwd_up_dir_path = os.path.dirname(CWD) - cwd_up_file_path = os.path.join( - cwd_up_dir_path, f"{self.custom_appname}.config.json" - ) + cwd_up_file_path = os.path.join(cwd_up_dir_path, f"{self.custom_appname}.config.json") os.chdir(CWD) shutil.copy(self.original_file_path, cwd_up_file_path) @@ -436,15 +423,11 @@ def test_load_secure_props(self, retrieve_cred_func): os.chdir(CWD) shutil.copy(self.original_file_path, cwd_up_file_path) credential = { - cwd_up_file_path: - { - "profiles.base.properties.user": "user", - "profiles.base.properties.password": "password" - } + cwd_up_file_path: {"profiles.base.properties.user": "user", "profiles.base.properties.password": "password"} } self.setUpCreds(cwd_up_file_path, credential) base64_encoded_credential = base64.b64encode(commentjson.dumps(credential).encode()).decode() - encoded_credential = base64_encoded_credential.encode('utf-16le').decode() + encoded_credential = base64_encoded_credential.encode("utf-16le").decode() retrieve_cred_func.return_value = encoded_credential # call the load_secure_props method @@ -461,19 +444,21 @@ def test_delete_credential(self, delete_pass_func): """ Test the delete_credential method for deleting credentials from keyring. """ + def side_effect(*args, **kwargs): if side_effect.counter < 2: side_effect.counter += 1 raise keyring.errors.PasswordDeleteError else: return None + side_effect.counter = 0 # custom side effect function for the mock delete_pass_func.side_effect = side_effect credential_manager = CredentialManager() - service_name = constants['ZoweServiceName'] - account_name = constants['ZoweAccountName'] + service_name = constants["ZoweServiceName"] + account_name = constants["ZoweAccountName"] # Delete the credential credential_manager.delete_credential(service_name, account_name) expected_calls = [ @@ -492,15 +477,15 @@ def test_retrieve_credential(self, get_pass_func): service_name = f"{constants['ZoweServiceName']}/{constants['ZoweAccountName']}" # Scenario 1: Retrieve password directly - expected_password1 = "password".encode('utf-16le').decode() + expected_password1 = "password".encode("utf-16le").decode() expected_password1 = expected_password1[:-1] - retrieve_credential1 = credential_manager._retrieve_credential(constants['ZoweServiceName']) + retrieve_credential1 = credential_manager._retrieve_credential(constants["ZoweServiceName"]) self.assertEqual(retrieve_credential1, expected_password1) get_pass_func.assert_called_with(service_name, constants["ZoweAccountName"]) # Scenario 2: Retrieve password in parts - expected_password2 = "part1part2".encode('utf-16le').decode() - retrieve_credential2 = credential_manager._retrieve_credential(constants['ZoweServiceName']) + expected_password2 = "part1part2".encode("utf-16le").decode() + retrieve_credential2 = credential_manager._retrieve_credential(constants["ZoweServiceName"]) retrieve_credential2 = retrieve_credential2[:-1] self.assertEqual(retrieve_credential2, expected_password2) get_pass_func.assert_any_call(service_name, constants["ZoweAccountName"]) @@ -508,17 +493,16 @@ def test_retrieve_credential(self, get_pass_func): get_pass_func.assert_any_call(f"{service_name}-2", f"{constants['ZoweAccountName']}-2") @mock.patch("sys.platform", "win32") - @mock.patch("keyring.get_password", side_effect=[None,None]) + @mock.patch("keyring.get_password", side_effect=[None, None]) def test_retrieve_credential_encoding_errors(self, get_pass_func): """ Test the _retrieve_credential method for handling encoding errors and None values. """ service_name = f"{constants['ZoweServiceName']}/{constants['ZoweAccountName']}" - result=CredentialManager._retrieve_credential(constants['ZoweServiceName']) + result = CredentialManager._retrieve_credential(constants["ZoweServiceName"]) self.assertIsNone(result) get_pass_func.assert_called_with(f"{service_name}-1", f"{constants['ZoweAccountName']}-1") - @mock.patch("sys.platform", "win32") @mock.patch("keyring.set_password") @mock.patch("zowe.core_for_zowe_sdk.CredentialManager._retrieve_credential") @@ -536,33 +520,27 @@ def test_save_secure_props_normal_credential(self, delete_pass_func, retrieve_cr os.chdir(CWD) shutil.copy(self.original_file_path, cwd_up_file_path) credential = { - cwd_up_file_path: - { - "profiles.base.properties.user": "samadpls", - "profiles.base.properties.password": "password" + cwd_up_file_path: { + "profiles.base.properties.user": "samadpls", + "profiles.base.properties.password": "password", } } - self.setUpCreds(cwd_up_file_path,credential) + self.setUpCreds(cwd_up_file_path, credential) encoded_credential = base64.b64encode(commentjson.dumps(credential).encode()).decode() retrieve_cred_func.return_value = None - CredentialManager.secure_props = credential + CredentialManager.secure_props = credential CredentialManager.save_secure_props() # delete the existing credential delete_pass_func.return_value = None # Verify the keyring function call - set_pass_func.assert_called_once_with( - service_name, - constants['ZoweAccountName'], - encoded_credential - ) + set_pass_func.assert_called_once_with(service_name, constants["ZoweAccountName"], encoded_credential) @mock.patch("sys.platform", "win32") @mock.patch("zowe.core_for_zowe_sdk.CredentialManager._retrieve_credential") @mock.patch("keyring.set_password") @mock.patch("zowe.core_for_zowe_sdk.CredentialManager.delete_credential") def test_save_secure_props_exceed_limit(self, delete_pass_func, set_pass_func, retrieve_cred_func): - # Set up mock values and expected results service_name = constants["ZoweServiceName"] + "/" + constants["ZoweAccountName"] # Setup - copy profile to fake filesystem created by pyfakefs @@ -571,19 +549,18 @@ def test_save_secure_props_exceed_limit(self, delete_pass_func, set_pass_func, r os.chdir(CWD) shutil.copy(self.original_file_path, cwd_up_file_path) credential = { - cwd_up_file_path: - { - "profiles.base.properties.user": "user", - "profiles.base.properties.password": "a" * (constants["WIN32_CRED_MAX_STRING_LENGTH"] + 1) + cwd_up_file_path: { + "profiles.base.properties.user": "user", + "profiles.base.properties.password": "a" * (constants["WIN32_CRED_MAX_STRING_LENGTH"] + 1), } } self.setUpCreds(cwd_up_file_path, credential) base64_encoded_credential = base64.b64encode(commentjson.dumps(credential).encode()).decode() - base64_encoded_credential+='\0' - encoded_credential = base64_encoded_credential.encode('utf-16le').decode() + base64_encoded_credential += "\0" + encoded_credential = base64_encoded_credential.encode("utf-16le").decode() retrieve_cred_func.return_value = encoded_credential - CredentialManager.secure_props = credential + CredentialManager.secure_props = credential CredentialManager.save_secure_props() # delete the existing credential @@ -591,16 +568,14 @@ def test_save_secure_props_exceed_limit(self, delete_pass_func, set_pass_func, r expected_calls = [] chunk_size = constants["WIN32_CRED_MAX_STRING_LENGTH"] - chunks = [base64_encoded_credential[i: i + chunk_size] for i in range(0, len(base64_encoded_credential), chunk_size)] + chunks = [ + base64_encoded_credential[i : i + chunk_size] for i in range(0, len(base64_encoded_credential), chunk_size) + ] for index, chunk in enumerate(chunks, start=1): field_name = f"{constants['ZoweAccountName']}-{index}" service_names = f"{service_name}-{index}" - password=(chunk + '\0' *(len(chunk)%2)).encode().decode('utf-16le') - expected_calls.append(mock.call( - service_names, - field_name, - password - )) + password = (chunk + "\0" * (len(chunk) % 2)).encode().decode("utf-16le") + expected_calls.append(mock.call(service_names, field_name, password)) set_pass_func.assert_has_calls(expected_calls) @mock.patch("keyring.get_password", side_effect=keyring_get_password) @@ -614,10 +589,13 @@ def test_profile_loading_with_valid_schema(self, get_pass_func): shutil.copy(self.original_schema_file_path, self.custom_dir) os.chdir(self.custom_dir) - self.setUpCreds(custom_file_path, { - "profiles.zosmf.properties.user": "user", - "profiles.zosmf.properties.password": "password", - }) + self.setUpCreds( + custom_file_path, + { + "profiles.zosmf.properties.user": "user", + "profiles.zosmf.properties.password": "password", + }, + ) # Test prof_manager = ProfileManager(appname="zowe") @@ -636,10 +614,13 @@ def test_profile_loading_with_invalid_schema(self, get_pass_func): shutil.copy(self.original_invalid_schema_file_path, self.custom_dir) os.chdir(self.custom_dir) - self.setUpCreds(custom_file_path, { - "profiles.zosmf.properties.user": "user", - "profiles.zosmf.properties.password": "password", - }) + self.setUpCreds( + custom_file_path, + { + "profiles.zosmf.properties.user": "user", + "profiles.zosmf.properties.password": "password", + }, + ) # Test prof_manager = ProfileManager(appname="invalid.zowe") @@ -658,10 +639,13 @@ def test_profile_loading_with_invalid_schema_internet_URI(self, get_pass_func): shutil.copy(self.original_invalidUri_schema_file_path, self.custom_dir) os.chdir(self.custom_dir) - self.setUpCreds(custom_file_path, { - "profiles.zosmf.properties.user": "user", - "profiles.zosmf.properties.password": "password", - }) + self.setUpCreds( + custom_file_path, + { + "profiles.zosmf.properties.user": "user", + "profiles.zosmf.properties.password": "password", + }, + ) # Test prof_manager = ProfileManager(appname="invalidUri.zowe") @@ -682,10 +666,13 @@ def test_profile_loading_with_env_variables(self, get_pass_func): shutil.copy(self.original_schema_file_path, self.custom_dir) os.chdir(self.custom_dir) - self.setUpCreds(custom_file_path, { - "profiles.zosmf.properties.user": "user", - "profiles.zosmf.properties.password": "password", - }) + self.setUpCreds( + custom_file_path, + { + "profiles.zosmf.properties.user": "user", + "profiles.zosmf.properties.password": "password", + }, + ) # Test prof_manager = ProfileManager(appname="zowe") @@ -742,7 +729,6 @@ def test_profile_manager_set_property(self, get_highest_priority_layer_mock): # Assert the method calls highest_priority_layer_mock.set_property.assert_called_with(json_path, value, secure=secure) - @mock.patch("zowe.core_for_zowe_sdk.ConfigFile.save") @mock.patch("zowe.core_for_zowe_sdk.CredentialManager.save_secure_props") def test_profile_manager_save(self, mock_save_secure_props, mock_save): @@ -761,12 +747,7 @@ def test_profile_manager_set_profile(self, get_highest_priority_layer_mock): Test that set_profile calls the set_profile method of the highest priority layer. """ profile_path = "profiles.zosmf" - profile_data = { - "properties": { - "user": "admin", - "password": "password1" - } - } + profile_data = {"properties": {"user": "admin", "password": "password1"}} highest_priority_layer_mock = mock.MagicMock(spec=ConfigFile) get_highest_priority_layer_mock.return_value = highest_priority_layer_mock @@ -783,22 +764,10 @@ def test_set_or_create_nested_profile(self, mock_get_profile_path): Test that __set_or_create_nested_profile calls the get_profile_path_from_name method and sets the profile data. """ mock_get_profile_path.return_value = "profiles.zosmf" - config_file = ConfigFile( name="zowe_abcd", type="User Config", profiles={}) - profile_data = { - "properties": { - "user": "samadpls", - "password": "password1" - } - } + config_file = ConfigFile(name="zowe_abcd", type="User Config", profiles={}) + profile_data = {"properties": {"user": "samadpls", "password": "password1"}} config_file._ConfigFile__set_or_create_nested_profile("zosmf", profile_data) - expected_profiles = { - "zosmf": { - "properties": { - "user": "samadpls", - "password": "password1" - } - } - } + expected_profiles = {"zosmf": {"properties": {"user": "samadpls", "password": "password1"}}} self.assertEqual(config_file.profiles, expected_profiles) @mock.patch("zowe.core_for_zowe_sdk.ConfigFile.find_profile") @@ -807,10 +776,7 @@ def test_is_secure(self, mock_find_profile): Test that __is_secure returns True if the property is secure and False otherwise. """ config_file = ConfigFile(name="zowe_abcd", type="User Config", profiles={}) - mock_find_profile.return_value = { - "properties": {"user":"samadpls"}, - "secure": ["password"] - } + mock_find_profile.return_value = {"properties": {"user": "samadpls"}, "secure": ["password"]} is_secure_secure = config_file._ConfigFile__is_secure("zosmf", "password") is_secure_non_secure = config_file._ConfigFile__is_secure("zosmf", "user") @@ -829,10 +795,8 @@ def test_config_file_set_property(self, get_pass_func, mock_is_secure, mock_find cwd_up_file_path = os.path.join(cwd_up_dir_path, "zowe.config.json") os.chdir(CWD) shutil.copy(self.original_file_path, cwd_up_file_path) - self.setUpCreds(cwd_up_file_path, { - "profiles.zosmf.properties.user": "admin" - }) - config_file = ConfigFile(name="zowe_abcd", type="User Config", profiles= {}) + self.setUpCreds(cwd_up_file_path, {"profiles.zosmf.properties.user": "admin"}) + config_file = ConfigFile(name="zowe_abcd", type="User Config", profiles={}) mock_is_secure.return_value = False mock_find_profile.return_value = {"properties": {"port": 1443}, "secure": []} mock_get_profile_name.return_value = "zosmf" @@ -842,12 +806,9 @@ def test_config_file_set_property(self, get_pass_func, mock_is_secure, mock_find mock_is_secure.assert_called_with("zosmf", "user") mock_find_profile.assert_called_with("zosmf", config_file.profiles) mock_get_profile_name.assert_called_with("profiles.zosmf.properties.user") - self.assertEqual(config_file.profiles, { - "zosmf": { - "properties": {"port": 1443, "user": "admin"}, - "secure": ["user"] - } - }) + self.assertEqual( + config_file.profiles, {"zosmf": {"properties": {"port": 1443, "user": "admin"}, "secure": ["user"]}} + ) def test_get_profile_name_from_path(self): """ @@ -874,49 +835,30 @@ def test_config_file_set_profile_and_save(self, get_pass_func): cwd_up_file_path = os.path.join(cwd_up_dir_path, "zowe.config.json") os.chdir(CWD) shutil.copy(self.original_file_path, cwd_up_file_path) - self.setUpCreds(cwd_up_file_path, { - "profiles.zosmf.properties.user": "abc", - "profiles.zosmf.properties.password": "def" - }) - initial_profiles = { - "zosmf": { - "properties": { - "port": 1443 - }, - "secure": [] - } - } - config_file = ConfigFile("User Config", "zowe.config.json", cwd_up_dir_path , profiles=initial_profiles) + self.setUpCreds( + cwd_up_file_path, {"profiles.zosmf.properties.user": "abc", "profiles.zosmf.properties.password": "def"} + ) + initial_profiles = {"zosmf": {"properties": {"port": 1443}, "secure": []}} + config_file = ConfigFile("User Config", "zowe.config.json", cwd_up_dir_path, profiles=initial_profiles) profile_data = { "type": "zosmf", - "properties": { - "port": 443, - "user": "abc", - "password": "def" - }, - "secure": ["user", "password"] + "properties": {"port": 443, "user": "abc", "password": "def"}, + "secure": ["user", "password"], } with mock.patch("zowe.core_for_zowe_sdk.ConfigFile.get_profile_name_from_path", return_value="zosmf"): with mock.patch("zowe.core_for_zowe_sdk.ConfigFile.find_profile", return_value=initial_profiles["zosmf"]): config_file.set_profile("profiles.zosmf", profile_data) - expected_profiles = { - "zosmf": profile_data - } + expected_profiles = {"zosmf": profile_data} self.assertEqual(config_file.profiles, expected_profiles) - config_file.jsonc = { - "profiles": expected_profiles - } + config_file.jsonc = {"profiles": expected_profiles} with mock.patch("builtins.open", mock.mock_open()): config_file.save(False) expected_secure_props = { - cwd_up_file_path: { - "profiles.zosmf.properties.user": "abc", - "profiles.zosmf.properties.password": "def" - } + cwd_up_file_path: {"profiles.zosmf.properties.user": "abc", "profiles.zosmf.properties.password": "def"} } expected_profiles = { "zosmf": { @@ -924,7 +866,7 @@ def test_config_file_set_profile_and_save(self, get_pass_func): "properties": { "port": 443, }, - "secure": ["user", "password"] + "secure": ["user", "password"], } } self.assertEqual(CredentialManager.secure_props, expected_secure_props) @@ -941,20 +883,9 @@ def test_config_file_save(self, mock_save_secure_props): shutil.copy(self.original_file_path, cwd_up_file_path) profile_data = { "lpar1": { - "profiles": { - "zosmf": { - "properties": { - "port": 1443, - "password": "secret" - }, - "secure": ["password"] - } - }, - "properties": { - "host": "example.com", - "user": "admin" - }, - "secure": ["user"] + "profiles": {"zosmf": {"properties": {"port": 1443, "password": "secret"}, "secure": ["password"]}}, + "properties": {"host": "example.com", "user": "admin"}, + "secure": ["user"], } } with mock.patch("builtins.open", mock.mock_open()) as mock_file: @@ -963,11 +894,13 @@ def test_config_file_save(self, mock_save_secure_props): config_file.save() mock_save_secure_props.assert_called_once() - mock_file.assert_called_once_with(cwd_up_file_path, 'w') + mock_file.assert_called_once_with(cwd_up_file_path, "w") mock_file.return_value.write.assert_called() self.assertIn("user", profile_data["lpar1"]["properties"]) self.assertNotIn("user", config_file.jsonc["profiles"]["lpar1"]["properties"]) - self.assertEqual(["port"], list(config_file.jsonc["profiles"]["lpar1"]["profiles"]["zosmf"]["properties"].keys())) + self.assertEqual( + ["port"], list(config_file.jsonc["profiles"]["lpar1"]["profiles"]["zosmf"]["properties"].keys()) + ) class TestValidateConfigJsonClass(unittest.TestCase): @@ -982,7 +915,7 @@ def test_validate_config_json_valid(self): schema_json = commentjson.load(open(path_to_schema)) expected = validate(config_json, schema_json) - result = validate_config_json(path_to_config, path_to_schema, cwd = FIXTURES_PATH) + result = validate_config_json(path_to_config, path_to_schema, cwd=FIXTURES_PATH) self.assertEqual(result, expected) @@ -998,7 +931,6 @@ def test_validate_config_json_invalid(self): validate(invalid_config_json, invalid_schema_json) with self.assertRaises(ValidationError) as actual_info: - validate_config_json(path_to_invalid_config, path_to_invalid_schema, cwd = FIXTURES_PATH) + validate_config_json(path_to_invalid_config, path_to_invalid_schema, cwd=FIXTURES_PATH) self.assertEqual(str(actual_info.exception), str(expected_info.exception)) -