Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Update REST API response type #322

Merged
merged 6 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/sdk-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ jobs:
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Lint with pydocstyle
run: pydocstyle --match-dir='^(?!build$).*' --match='^(?!(__init__\.py|setup\.py$)).*\.py$' src
run: pydocstyle --match-dir='^(?!(build|response)$).*' --match='^(?!(__init__\.py|setup\.py$)).*\.py$' src
- name: Lint with pydoclint
run: pydoclint --exclude='.*/build/.*' src
run: pydoclint --exclude='.*/(build|response)/.*' src
- name: Lint with pylint
run: |
# check for Python errors
pylint src --errors-only --disable=E0401,E0611 --ignore=build
# check for lint
pylint ./src --disable=all --enable=C0103,C0301 --ignore=build --max-line-length=127
pylint ./src --disable=all --enable=C0103,C0301 --ignore=build,response --max-line-length=127
- name: Check license headers
run: python scripts/license_header.py src
- name: Test with pytest
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"./src/zos_console",
"./src/zos_files",
"./src/zos_jobs",
"./src/zosmf"
"./src/zosmf",
"./src/zos_tso"
],
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

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

## Recent Changes

### Enhancements

- *Breaking*: Update method return types to use custom classes for REST API responses [#89] (https://github.com/zowe/zowe-client-python-sdk/issues/89)

### Bug Fixes


## `1.0.0-dev19`

### Enhancements
Expand Down
2 changes: 1 addition & 1 deletion scripts/license_header.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def main():
if "build" in root.split(os.path.sep):
continue
for file in files:
if file.endswith(".py"):
if file.endswith(".py") and file is not "_version.py":
file_path = os.path.join(root, file)
if not check_and_add_license_header(file_path, write_header):
print(f"License header missing in: {file_path}")
Expand Down
11 changes: 11 additions & 0 deletions src/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
"""Zowe Python Client SDK.
This program and the accompanying materials are made available under the terms of the
Eclipse Public License v2.0 which accompanies this distribution, and is available at
https://www.eclipse.org/legal/epl-v20.html
SPDX-License-Identifier: EPL-2.0
Copyright Contributors to the Zowe Project.
"""
__version__ = "1.0.0-dev19"
14 changes: 7 additions & 7 deletions src/core/zowe/core_for_zowe_sdk/request_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ def __handle_ssl_warnings(self):
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def perform_request(
self, method: str, request_arguments: dict, expected_code: dict = [200], stream: bool = False
) -> dict:
self, method: str, request_arguments: dict, expected_code: list = [200], stream: bool = False
) -> Union[str, bytes, dict, None]:
"""Execute an HTTP/HTTPS requests from given arguments and return validated response (JSON).

Parameters
Expand All @@ -54,14 +54,14 @@ def perform_request(
The request method that should be used
request_arguments: dict
The dictionary containing the required arguments for the execution of the request
expected_code: dict
expected_code: list
The list containing the acceptable response codes (default is [200])
stream: bool
The boolean value whether the request is stream

Returns
-------
dict
Union[str, bytes, dict, None]
normalized request response in json (dictionary)
"""
self.__method = method
Expand Down Expand Up @@ -136,13 +136,13 @@ def __validate_response(self):
)
raise RequestFailed(self.__response.status_code, output_str)

def __normalize_response(self) -> Union[str, bytes, dict]:
def __normalize_response(self) -> Union[str, bytes, dict, None]:
"""
Normalize the response object to a JSON format.

Returns
-------
Union[str, bytes, dict]
Union[str, bytes, dict, None]
Response object at the format based on Content-Type header:
- `bytes` when the response is binary data
- `str` when the response is plain text
Expand All @@ -152,6 +152,6 @@ def __normalize_response(self) -> Union[str, bytes, dict]:
if content_type == "application/octet-stream":
return self.__response.content
elif content_type and content_type.startswith("application/json"):
return "" if self.__response.text == "" else self.__response.json()
return None if self.__response.text == "" else self.__response.json()
else:
return self.__response.text
14 changes: 8 additions & 6 deletions src/zos_console/zowe/zos_console_for_zowe_sdk/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

from zowe.core_for_zowe_sdk import SdkApi

from .response import ConsoleResponse, IssueCommandResponse


class Console(SdkApi):
"""
Expand All @@ -28,7 +30,7 @@ class Console(SdkApi):
def __init__(self, connection: dict):
super().__init__(connection, "/zosmf/restconsoles/consoles/defcn", logger_name=__name__)

def issue_command(self, command: str, console: Optional[str] = None) -> dict:
def issue_command(self, command: str, console: Optional[str] = None) -> IssueCommandResponse:
"""Issues a command on z/OS Console.

Parameters
Expand All @@ -40,17 +42,17 @@ def issue_command(self, command: str, console: Optional[str] = None) -> dict:

Returns
-------
dict
IssueCommandResponse
A JSON containing the response from the console command
"""
custom_args = self._create_custom_request_arguments()
custom_args["url"] = self._request_endpoint.replace("defcn", console or "defcn")
request_body = {"cmd": command}
custom_args["json"] = request_body
response_json = self.request_handler.perform_request("PUT", custom_args)
return response_json
return IssueCommandResponse(response_json)

def get_response(self, response_key: str, console: Optional[str] = None) -> dict:
def get_response(self, response_key: str, console: Optional[str] = None) -> ConsoleResponse:
"""
Collect outstanding synchronous z/OS Console response messages.

Expand All @@ -63,11 +65,11 @@ def get_response(self, response_key: str, console: Optional[str] = None) -> dict

Returns
-------
dict
ConsoleResponse
A JSON containing the response to the command
"""
custom_args = self._create_custom_request_arguments()
request_url = "{}/solmsgs/{}".format(console or "defcn", response_key)
custom_args["url"] = self._request_endpoint.replace("defcn", request_url)
response_json = self.request_handler.perform_request("GET", custom_args)
return response_json
return ConsoleResponse(response_json)
13 changes: 13 additions & 0 deletions src/zos_console/zowe/zos_console_for_zowe_sdk/response/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"""Zowe Python Client SDK.

This program and the accompanying materials are made available under the terms of the
Eclipse Public License v2.0 which accompanies this distribution, and is available at

https://www.eclipse.org/legal/epl-v20.html

SPDX-License-Identifier: EPL-2.0

Copyright Contributors to the Zowe Project.
"""

from .console import ConsoleResponse, IssueCommandResponse
50 changes: 50 additions & 0 deletions src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Zowe Python Client SDK.

This program and the accompanying materials are made available under the terms of the
Eclipse Public License v2.0 which accompanies this distribution, and is available at

https://www.eclipse.org/legal/epl-v20.html

SPDX-License-Identifier: EPL-2.0

Copyright Contributors to the Zowe Project.
"""

from dataclasses import dataclass
from typing import Any, Optional


@dataclass
class IssueCommandResponse:
cmd_response_key: Optional[str] = None
cmd_response_url: Optional[str] = None
cmd_response_uri: Optional[str] = None
cmd_response: Optional[str] = None

def __init__(self, response: dict) -> None:
for k, value in response.items():
key = k.replace("-", "_")
super().__setattr__(key, value)

Check warning on line 27 in src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py

View check run for this annotation

Codecov / codecov/patch

src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py#L26-L27

Added lines #L26 - L27 were not covered by tests

def __getitem__(self, key: str) -> str:
return self.__dict__[key.replace("-", "_")]

Check warning on line 30 in src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py

View check run for this annotation

Codecov / codecov/patch

src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py#L30

Added line #L30 was not covered by tests

def __setitem__(self, key: str, value: str) -> None:
self.__dict__[key.replace("-", "_")] = value

Check warning on line 33 in src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py

View check run for this annotation

Codecov / codecov/patch

src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py#L33

Added line #L33 was not covered by tests
t1m0thyj marked this conversation as resolved.
Show resolved Hide resolved


@dataclass
class ConsoleResponse:
cmd_response: Optional[str] = None
sol_key_detected: Optional[bool] = None

def __init__(self, response: dict) -> None:
for k, value in response.items():
key = k.replace("-", "_")
super().__setattr__(key, value)

Check warning on line 44 in src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py

View check run for this annotation

Codecov / codecov/patch

src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py#L43-L44

Added lines #L43 - L44 were not covered by tests

def __getitem__(self, key: str) -> Any:
return self.__dict__[key.replace("-", "_")]

Check warning on line 47 in src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py

View check run for this annotation

Codecov / codecov/patch

src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py#L47

Added line #L47 was not covered by tests

def __setitem__(self, key: str, value: Any) -> None:
self.__dict__[key.replace("-", "_")] = value

Check warning on line 50 in src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py

View check run for this annotation

Codecov / codecov/patch

src/zos_console/zowe/zos_console_for_zowe_sdk/response/console.py#L50

Added line #L50 was not covered by tests
13 changes: 7 additions & 6 deletions src/zos_files/zowe/zos_files_for_zowe_sdk/datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from zowe.core_for_zowe_sdk import SdkApi
from zowe.core_for_zowe_sdk.exceptions import FileNotFound
from zowe.zos_files_for_zowe_sdk.constants import FileType, zos_file_constants
from zowe.zos_files_for_zowe_sdk.response import DatasetListResponse, MemberListResponse

_ZOWE_FILES_DEFAULT_ENCODING = zos_file_constants["ZoweFilesDefaultEncoding"]

Expand Down Expand Up @@ -306,7 +307,7 @@ def __init__(self, connection: dict):
super().__init__(connection, "/zosmf/restfiles/", logger_name=__name__)
self._default_headers["Accept-Encoding"] = "gzip"

def list(self, name_pattern: str, return_attributes: bool = False) -> List[Dict]:
def list(self, name_pattern: str, return_attributes: bool = False) -> DatasetListResponse:
"""
Retrieve a list of datasets based on a given pattern.

Expand All @@ -319,7 +320,7 @@ def list(self, name_pattern: str, return_attributes: bool = False) -> List[Dict]

Returns
-------
List[Dict]
DatasetListResponse
A JSON with a list of dataset names (and attributes if specified) matching the given pattern.
"""
custom_args = self._create_custom_request_arguments()
Expand All @@ -330,7 +331,7 @@ def list(self, name_pattern: str, return_attributes: bool = False) -> List[Dict]
custom_args["headers"]["X-IBM-Attributes"] = "base"

response_json = self.request_handler.perform_request("GET", custom_args)
return response_json
return DatasetListResponse(response_json, return_attributes)

def list_members(
self,
Expand All @@ -339,7 +340,7 @@ def list_members(
member_start: Optional[str] = None,
limit: int = 1000,
attributes: str = "member",
) -> dict:
) -> MemberListResponse:
"""
Retrieve the list of members on a given PDS/PDSE.

Expand All @@ -358,7 +359,7 @@ def list_members(

Returns
-------
dict
MemberListResponse
A JSON with a list of members from a given PDS/PDSE
"""
custom_args = self._create_custom_request_arguments()
Expand All @@ -372,7 +373,7 @@ def list_members(
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
return MemberListResponse(response_json, (attributes == "base"))

def copy_data_set_or_member(
self,
Expand Down
10 changes: 7 additions & 3 deletions src/zos_files/zowe/zos_files_for_zowe_sdk/file_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
from zowe.core_for_zowe_sdk import SdkApi
from zowe.zos_files_for_zowe_sdk import constants, exceptions

from .response import FileSystemListResponse

_ZOWE_FILES_DEFAULT_ENCODING = constants.zos_file_constants["ZoweFilesDefaultEncoding"]


Expand Down Expand Up @@ -150,7 +152,9 @@ def unmount(self, file_system_name: str, options: dict = {}, encoding: str = _ZO
response_json = self.request_handler.perform_request("PUT", custom_args, expected_code=[204])
return response_json

def list(self, file_path_name: Optional[str] = None, file_system_name: Optional[str] = None) -> dict:
def list(
self, file_path_name: Optional[str] = None, file_system_name: Optional[str] = None
) -> FileSystemListResponse:
"""
List all mounted filesystems.
Expand All @@ -166,12 +170,12 @@ def list(self, file_path_name: Optional[str] = None, file_system_name: Optional[
Returns
-------
dict
FileSystemListResponse
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["url"] = "{}mfs".format(self._request_endpoint)
response_json = self.request_handler.perform_request("GET", custom_args, expected_code=[200])
return response_json
return FileSystemListResponse(response_json)
14 changes: 14 additions & 0 deletions src/zos_files/zowe/zos_files_for_zowe_sdk/response/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Zowe Python Client SDK.

This program and the accompanying materials are made available under the terms of the
Eclipse Public License v2.0 which accompanies this distribution, and is available at

https://www.eclipse.org/legal/epl-v20.html

SPDX-License-Identifier: EPL-2.0

Copyright Contributors to the Zowe Project.
"""
from .datasets import DatasetListResponse, MemberListResponse
from .file_system import FileSystemListResponse
from .uss import USSListResponse
Loading
Loading