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

Added python 3.8 support #191

Merged
merged 2 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import trcli.cli
from shutil import copyfile
from trcli.cli import cli
from trcli.backports import removeprefix
from trcli.constants import FAULT_MAPPING
from tests.helpers.cli_helpers import CLIParametersHelper

Expand Down Expand Up @@ -241,7 +242,7 @@ def test_default_config_does_not_override_environments(self, mocker, cli_resourc

for arg_name, arg_value in ENVIRONMENT_VARIABLES.items():
setattr_mock.assert_any_call(
mocker.ANY, arg_name.removeprefix("TR_CLI_").lower(), arg_value
mocker.ANY, removeprefix(arg_name, "TR_CLI_").lower(), arg_value
)

@pytest.mark.cli
Expand Down
4 changes: 2 additions & 2 deletions trcli/api/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pathlib import Path

import requests
from typing import Union, Callable
from typing import Union, Callable, Dict, List
from time import sleep

import urllib3
Expand All @@ -22,7 +22,7 @@ class APIClientResult:
error_message - custom error message when -1 was returned in status_code"""

status_code: int
response_text: Union[dict, str, list]
response_text: Union[Dict, str, List]
error_message: str


Expand Down
20 changes: 10 additions & 10 deletions trcli/api/api_request_handler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import html
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import List, Union, Tuple
from typing import List, Union, Tuple, Dict

from trcli.api.api_client import APIClient, APIClientResult
from trcli.api.api_response_verify import ApiResponseVerify
Expand Down Expand Up @@ -46,7 +46,7 @@ def check_automation_id_field(self, project_id: int) -> Union[str, None]:
"""
response = self.client.send_get("get_case_fields")
if not response.error_message:
fields: list = response.response_text
fields: List = response.response_text
automation_id_field = next(
filter(lambda x: x["system_name"] == "custom_automation_id", fields),
None
Expand Down Expand Up @@ -181,7 +181,7 @@ def get_suite_ids(self, project_id: int) -> Tuple[List[int], str]:
) > 0 else "Update skipped"
return available_suites, error_message

def add_suites(self, project_id: int) -> Tuple[List[dict], str]:
def add_suites(self, project_id: int) -> Tuple[List[Dict], str]:
"""
Adds suites that doesn't have ID's in DataProvider.
Runs update_data in data_provider for successfully created resources.
Expand Down Expand Up @@ -244,7 +244,7 @@ def check_missing_section_ids(self, project_id: int) -> Tuple[bool, str]:
else:
return False, error_message

def add_sections(self, project_id: int) -> Tuple[List[dict], str]:
def add_sections(self, project_id: int) -> Tuple[List[Dict], str]:
"""
Add sections that doesn't have ID in DataProvider.
Runs update_data in data_provider for successfully created resources.
Expand Down Expand Up @@ -373,7 +373,7 @@ def add_run(
run_name: str,
milestone_id: int = None,
plan_id: int = None,
config_ids: list[int] = None
config_ids: List[int] = None
) -> Tuple[int, str]:
"""
Creates a new test run.
Expand Down Expand Up @@ -435,7 +435,7 @@ def update_run(self, run_id: int, run_name: str, milestone_id: int = None) -> Tu
run_response = self.client.send_get(f"get_run/{run_id}")
return run_response.response_text, update_response.error_message

def upload_attachments(self, report_results: [dict], results: list[dict], run_id: int):
def upload_attachments(self, report_results: [Dict], results: List[Dict], run_id: int):
""" Getting test result id and upload attachments for it. """
tests_in_run, error = self.__get_all_tests_in_run(run_id)
if not error:
Expand All @@ -452,7 +452,7 @@ def upload_attachments(self, report_results: [dict], results: list[dict], run_id
else:
self.environment.elog(f"Unable to upload attachments due to API request error: {error}")

def add_results(self, run_id: int) -> Tuple[list, str, int]:
def add_results(self, run_id: int) -> Tuple[List, str, int]:
"""
Adds one or more new test results.
:run_id: run id
Expand Down Expand Up @@ -564,7 +564,7 @@ def delete_suite(self, suite_id: int) -> Tuple[dict, str]:
response = self.client.send_post(f"delete_suite/{suite_id}", payload={})
return response.response_text, response.error_message

def delete_sections(self, added_sections: List[dict]) -> Tuple[list, str]:
def delete_sections(self, added_sections: List[Dict]) -> Tuple[List, str]:
"""
Delete section given add_sections response
:suite_id: section id
Expand All @@ -583,7 +583,7 @@ def delete_sections(self, added_sections: List[dict]) -> Tuple[list, str]:
break
return responses, error_message

def delete_cases(self, suite_id: int, added_cases: List[dict]) -> Tuple[dict, str]:
def delete_cases(self, suite_id: int, added_cases: List[Dict]) -> Tuple[Dict, str]:
"""
Delete cases given add_cases response
:suite_id: section id
Expand Down Expand Up @@ -654,7 +654,7 @@ def __get_all_projects(self) -> Tuple[List[dict], str]:
"""
return self.__get_all_entities('projects', f"get_projects")

def __get_all_entities(self, entity: str, link=None, entities=[]) -> Tuple[List[dict], str]:
def __get_all_entities(self, entity: str, link=None, entities=[]) -> Tuple[List[Dict], str]:
"""
Get all entities from all pages if number of entities is too big to return in single response.
Function using next page field in API response.
Expand Down
2 changes: 1 addition & 1 deletion trcli/api/results_uploader.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ def check_suite_id(self, project_id: int) -> int:
self.environment.elog(error_message)
return result_code

def add_missing_sections(self, project_id: int) -> Tuple[list, int]:
def add_missing_sections(self, project_id: int) -> Tuple[List, int]:
"""
Checks for missing sections in specified project. Add missing sections if user agrees to
do so. Returns list of added section IDs if succeeds or empty list with result_code set to
Expand Down
6 changes: 6 additions & 0 deletions trcli/backports.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
def removeprefix(text, prefix):
"""Backport of python 3.9 str.removeprefix"""

if text.startswith(prefix):
return text[len(prefix):]
return text
4 changes: 2 additions & 2 deletions trcli/data_classes/data_parsers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import re
from typing import Union
from typing import Union, List, Dict


class MatchersParser:
Expand Down Expand Up @@ -49,7 +49,7 @@ def parse_name_with_id(case_name: str) -> (int, str):
class FieldsParser:

@staticmethod
def resolve_fields(fields: Union[list[str], dict]) -> (dict, str):
def resolve_fields(fields: Union[List[str], Dict]) -> (Dict, str):
error = None
fields_dictionary = {}
try:
Expand Down
10 changes: 5 additions & 5 deletions trcli/data_classes/dataclass_testrail.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ class TestRailResult:
assignedto_id: int = field(default=None, skip_if_default=True)
attachments: Optional[List[str]] = field(default_factory=list, skip_if_default=True)
result_fields: Optional[dict] = field(default_factory=dict, skip=True)
junit_result_unparsed: list = field(default=None, metadata={"serde_skip": True})
custom_step_results: list[TestRailSeparatedStep] = field(default_factory=list, skip_if_default=True)
junit_result_unparsed: List = field(default=None, metadata={"serde_skip": True})
custom_step_results: List[TestRailSeparatedStep] = field(default_factory=list, skip_if_default=True)

def __post_init__(self):
if self.junit_result_unparsed is not None:
Expand All @@ -51,7 +51,7 @@ def __post_init__(self):
self.elapsed = self.proper_format_for_elapsed(self.elapsed)

@staticmethod
def calculate_status_id_from_junit_element(junit_result: list) -> int:
def calculate_status_id_from_junit_element(junit_result: List) -> int:
"""
Calculate id for first result. In junit no result mean pass
1 - Passed
Expand All @@ -68,7 +68,7 @@ def calculate_status_id_from_junit_element(junit_result: list) -> int:
return 5

@staticmethod
def get_comment_from_junit_element(junit_result: list) -> str:
def get_comment_from_junit_element(junit_result: List) -> str:
if len(junit_result) == 0:
return ""
elif not any(
Expand Down Expand Up @@ -136,7 +136,7 @@ class TestRailCase:
result: TestRailResult = field(default=None, metadata={"serde_skip": True})
custom_automation_id: str = field(default=None, skip_if_default=True)
# Uncomment if we want to support separated steps in cases in the future
# custom_steps_separated: list[TestRailSeparatedStep] = field(default_factory=list, skip_if_default=True)
# custom_steps_separated: List[TestRailSeparatedStep] = field(default_factory=list, skip_if_default=True)

def __int__(self):
return int(self.case_id) if self.case_id is not None else -1
Expand Down
14 changes: 7 additions & 7 deletions trcli/data_providers/api_data_provider.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import List
from typing import List, Dict

from serde.json import to_dict

Expand Down Expand Up @@ -109,9 +109,9 @@ def add_results_for_cases(self, bulk_size):

def update_data(
self,
suite_data: List[dict] = None,
section_data: List[dict] = None,
case_data: List[dict] = None,
suite_data: List[Dict] = None,
section_data: List[Dict] = None,
case_data: List[Dict] = None,
):
"""Here you can provide responses from service after creating resources.
This way TestRailSuite data will be updated by ID's of new created resources.
Expand All @@ -123,7 +123,7 @@ def update_data(
if case_data is not None:
self.__update_case_data(case_data)

def __update_suite_data(self, suite_data: List[dict]):
def __update_suite_data(self, suite_data: List[Dict]):
"""suite_data comes from add_suite API response
example:
{
Expand All @@ -146,7 +146,7 @@ def check_section_names_duplicates(self):
else:
return True

def __update_section_data(self, section_data: List[dict]):
def __update_section_data(self, section_data: List[Dict]):
"""section_data comes from add_section API response
example:
{
Expand All @@ -173,7 +173,7 @@ def __update_parent_section(self, parent_section_id: int):
for section in self.suites_input.testsections:
section.parent_id = parent_section_id

def __update_case_data(self, case_data: List[dict]):
def __update_case_data(self, case_data: List[Dict]):
"""case_data comes from add_case API response
example:
{
Expand Down
4 changes: 2 additions & 2 deletions trcli/readers/file_parser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from pathlib import Path
from abc import abstractmethod
from typing import Union
from typing import Union, List

from trcli.cli import Environment
from trcli.data_classes.dataclass_testrail import TestRailSuite
Expand All @@ -24,5 +24,5 @@ def check_file(filepath: Union[str, Path]) -> Path:
return filepath

@abstractmethod
def parse_file(self) -> list[TestRailSuite]:
def parse_file(self) -> List[TestRailSuite]:
raise NotImplementedError
6 changes: 3 additions & 3 deletions trcli/readers/junit_xml.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import glob
from pathlib import Path
from typing import Union
from typing import Union, List
from unittest import TestCase, TestSuite
from xml.etree import ElementTree as etree

Expand Down Expand Up @@ -75,7 +75,7 @@ def check_file(filepath: Union[str, Path]) -> Path:
suite.write(merged_report_path)
return merged_report_path

def parse_file(self) -> list[TestRailSuite]:
def parse_file(self) -> List[TestRailSuite]:
self.env.log(f"Parsing JUnit report.")
suite = JUnitXml.fromfile(
self.filepath, parse_func=self._add_root_element_to_tree
Expand Down Expand Up @@ -188,7 +188,7 @@ def parse_file(self) -> list[TestRailSuite]:

return testrail_suites

def split_sauce_report(self, suite) -> list[JUnitXml]:
def split_sauce_report(self, suite) -> List[JUnitXml]:
self.env.log(f"Processing SauceLabs report.")
subsuites = {}
for section in suite:
Expand Down
3 changes: 2 additions & 1 deletion trcli/readers/openapi_yml.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
from pathlib import Path
from typing import List

import yaml

Expand Down Expand Up @@ -133,7 +134,7 @@ def _format_text(title, details):

class OpenApiParser(FileParser):

def parse_file(self) -> list[TestRailSuite]:
def parse_file(self) -> List[TestRailSuite]:
self.env.log(f"Parsing OpenAPI specification.")
spec = self.resolve_openapi_spec()
sections = {
Expand Down
8 changes: 5 additions & 3 deletions trcli/readers/robot_xml.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from datetime import datetime
from typing import List
from xml.etree import ElementTree

from trcli.backports import removeprefix
from trcli.cli import Environment
from trcli.data_classes.data_parsers import MatchersParser, FieldsParser
from trcli.data_classes.dataclass_testrail import (
Expand All @@ -18,7 +20,7 @@ def __init__(self, environment: Environment):
super().__init__(environment)
self.case_matcher = environment.case_matcher

def parse_file(self) -> list[TestRailSuite]:
def parse_file(self) -> List[TestRailSuite]:
self.env.log(f"Parsing Robot Framework report.")
tree = ElementTree.parse(self.filepath)
root = tree.getroot()
Expand All @@ -38,7 +40,7 @@ def parse_file(self) -> list[TestRailSuite]:

return testrail_suites

def _find_suites(self, suite_element, sections_list: list, namespace=""):
def _find_suites(self, suite_element, sections_list: List, namespace=""):
name = suite_element.get("name")
namespace += f".{name}" if namespace else name
tests = suite_element.findall("test")
Expand Down Expand Up @@ -124,4 +126,4 @@ def _parse_rf_time(time_str: str) -> datetime:

@staticmethod
def _remove_tr_prefix(text: str, tr_prefix: str) -> str:
return text.strip().removeprefix(tr_prefix).strip()
return removeprefix(text, tr_prefix).strip()