diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..68bc17f --- /dev/null +++ b/.gitignore @@ -0,0 +1,160 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..18c9147 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..e415cf4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# Contributing to Transcriptase +We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: + +- Reporting a bug +- Discussing the current state of the code +- Submitting a fix +- Proposing new features +- Becoming a maintainer + +## We Develop with GitHub +We use GitHub to host code, to track issues and feature requests, as well as accept pull requests. + +## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests +Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your pull requests: + +1. Fork the repo and create your branch from `master`. +2. If you've added code that should be tested, add tests. +3. Always update the documentation. +4. Ensure the test suite passes. +5. Make sure your code lints: pylint, mypy and black code formatter. +6. Issue that pull request! + +## Any contributions you make will be under the MIT Software License +In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern. + +## Report bugs using Github's [issues](https://github.com/wwakabobik/testrail_api_reporter/issues) +We use GitHub issues to track public bugs. Report a bug by [opening a new issue](); it's that easy! + +## Write bug reports with detail, background, and sample code +[This is an example](http://stackoverflow.com/q/12488905/180626) of a bug report I wrote, and I think it's not a bad model. Here's [another example from Craig Hockenberry](http://www.openradar.me/11905408), an app developer whom I greatly respect. + +**Great Bug Reports** tend to have: + +- A quick summary and/or background +- Steps to reproduce + - Be specific! + - Give sample code if you can. [My stackoverflow question](http://stackoverflow.com/q/12488905/180626) includes sample code that *anyone* with a base R setup can run to reproduce what I was seeing +- What you expected would happen +- What actually happens +- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) + +People *love* thorough bug reports. I'm not even kidding. + +## Use a Consistent Coding Style +Always use [PEP8](https://peps.python.org/pep-0008/). Always check your code using mypy and pylint, and use black code formatter. If possible, use and apply flake8 extended rules of snowflake plugin. + +## License +By contributing, you agree that your contributions will be licensed under its MIT License. + +## References +This document was adapted from the open-source contribution guidelines for [Hitchhiker's Guide to Python](https://docs.python-guide.org/writing/style/) diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..ca31eb8 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,17 @@ +# Security Policy + +## Supported Versions + +Use this section to tell people about which versions of your project are +currently being supported with security updates. + +| Version | Supported | +| ------- | ------------------ | +| 0.0.1 | :white_check_mark: | + + +## Reporting a Vulnerability + +In case of issues, please report to: https://github.com/wwakabobik/testrail_api_reporter/issues + +Some ignored/declined issues will be described bellow, please check them prior to create new issues. diff --git a/__init__.py b/__init__.py index 90b7e87..f8013df 100644 --- a/__init__.py +++ b/__init__.py @@ -1,3 +1,4 @@ +""" This module is used to import all the classes and functions from the package """ # Engines from .testrail_api_reporter.engines.at_coverage_reporter import ATCoverageReporter from .testrail_api_reporter.engines.results_reporter import TestRailResultsReporter diff --git a/__main__.py b/__main__.py index b38aefd..a9f9707 100644 --- a/__main__.py +++ b/__main__.py @@ -1,3 +1,4 @@ +""" TestRail API Reporter """ # Engines from testrail_api_reporter.engines.at_coverage_reporter import ATCoverageReporter from testrail_api_reporter.engines.results_reporter import TestRailResultsReporter diff --git a/pull_request_template.md b/pull_request_template.md new file mode 100644 index 0000000..b91d916 --- /dev/null +++ b/pull_request_template.md @@ -0,0 +1,11 @@ +### Code linters/formatters +- [ ] PyCharm inspection passed on changed files (or any local IDE) +- [ ] pylint inspection executed and passed on changed files +- [ ] mypy inspection executed and passed on changed files +- [ ] Black code formatter executed and passed on changed files + +### Documentation +- [ ] Documentation / README.md has been updated + +### Other code changes +- [ ] The soul is pure diff --git a/requirements.txt b/requirements.txt index 9275034..74f43f1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,12 +1,12 @@ requests==2.31.0 xmltodict==0.13.0 -testrail-api==1.12.0 -plotly==5.16.1 +testrail-api==1.12.1 +plotly==5.17.0 psutil==5.9.5 atlassian-python-api==3.41.2 kaleido==0.2.1 httplib2==0.22.0 google-auth-httplib2==0.1.1 google-auth-oauthlib==1.1.0 -google-api-python-client==2.99.0 +google-api-python-client==2.100.0 oauth2client==4.1.3 diff --git a/testrail_api_reporter/__init__.py b/testrail_api_reporter/__init__.py index c005845..674904d 100644 --- a/testrail_api_reporter/__init__.py +++ b/testrail_api_reporter/__init__.py @@ -1,3 +1,4 @@ +""" testrail_api_reporter package """ # Engines from .engines.at_coverage_reporter import ATCoverageReporter from .engines.plotly_reporter import PlotlyReporter diff --git a/testrail_api_reporter/engines/__init__.py b/testrail_api_reporter/engines/__init__.py index 8c2f6d0..1253d5b 100644 --- a/testrail_api_reporter/engines/__init__.py +++ b/testrail_api_reporter/engines/__init__.py @@ -1,4 +1,4 @@ -# Engines +""" Engines package """ from .at_coverage_reporter import ATCoverageReporter from .results_reporter import TestRailResultsReporter from .plotly_reporter import PlotlyReporter diff --git a/testrail_api_reporter/engines/at_coverage_reporter.py b/testrail_api_reporter/engines/at_coverage_reporter.py index f6125af..692514c 100644 --- a/testrail_api_reporter/engines/at_coverage_reporter.py +++ b/testrail_api_reporter/engines/at_coverage_reporter.py @@ -13,16 +13,16 @@ class ATCoverageReporter: """ def __init__( - self, - url: str, - email: str, - password: str, - priority=None, - project=None, - type_platforms=None, - automation_platforms=None, - suite_id=None, - debug=None, + self, + url: str, + email: str, + password: str, + priority=None, + project=None, + type_platforms=None, + automation_platforms=None, + suite_id=None, + debug=None, ): """ General init @@ -114,13 +114,13 @@ def __get_all_sections(self, project_id=None, suite_id=None, debug=None): return sections def __get_all_cases( - self, - project_id=None, - suite_id=None, - section_id=None, - priority_id=None, - debug=None, - retries=3, + self, + project_id=None, + suite_id=None, + section_id=None, + priority_id=None, + debug=None, + retries=3, ): """ Wrapper to get all test cases for selected project, suite, section and priority @@ -205,13 +205,13 @@ def __get_all_cases( return cases_list def automation_state_report( - self, - priority=None, - project=None, - automation_platforms=None, - filename_pattern="current_automation", - suite=None, - debug=None, + self, + priority=None, + project=None, + automation_platforms=None, + filename_pattern="current_automation", + suite=None, + debug=None, ): """ Generates data of automation coverage for stacked bar chart or staked line chart @@ -299,12 +299,12 @@ def test_case_by_priority(self, project=None, suite=None, debug=None): return results def test_case_by_type( - self, - project=None, - type_platforms=None, - filename_pattern="current_area_distribution", - suite=None, - debug=None, + self, + project=None, + type_platforms=None, + filename_pattern="current_area_distribution", + suite=None, + debug=None, ): """ Generates data for pie/line chart with distribution by type of platforms (guided by top section). diff --git a/testrail_api_reporter/engines/case_backup.py b/testrail_api_reporter/engines/case_backup.py index d3ca90e..4478990 100644 --- a/testrail_api_reporter/engines/case_backup.py +++ b/testrail_api_reporter/engines/case_backup.py @@ -1,3 +1,4 @@ +""" TestRails backup module """ import os from datetime import datetime @@ -5,6 +6,8 @@ class TCBackup: + """ TestRails backup class """ + def __init__(self, test_rails_url, test_rails_username, test_rails_password, test_rails_suite, cleanup_needed=True, backup_filename='backup.xml', cookie_name='cookie.txt', debug=True): """ diff --git a/testrail_api_reporter/engines/plotly_reporter.py b/testrail_api_reporter/engines/plotly_reporter.py index 1421c43..0374e6a 100644 --- a/testrail_api_reporter/engines/plotly_reporter.py +++ b/testrail_api_reporter/engines/plotly_reporter.py @@ -1,3 +1,4 @@ +""" Confluence sender module """ import plotly from ..utils.csv_parser import CSVParser @@ -7,9 +8,7 @@ class PlotlyReporter: - """ - Class contains wrapper for generate reports (images) via plot charts - """ + """ Class contains wrapper for generate reports (images) via plot charts """ def __init__(self, pr_colors=None, pr_labels=None, ar_colors=None, lines=None, type_platforms=None, debug=True): """ diff --git a/testrail_api_reporter/engines/results_reporter.py b/testrail_api_reporter/engines/results_reporter.py index a1efdcb..40cf180 100644 --- a/testrail_api_reporter/engines/results_reporter.py +++ b/testrail_api_reporter/engines/results_reporter.py @@ -13,14 +13,14 @@ class TestRailResultsReporter: """Reporter to TestRails from xml report results, obtained by pytest""" def __init__( - self, - url: str, - email: str, - password: str, - project_id: int, - xml_report="junit-report.xml", - suite_id=None, - debug=True, + self, + url: str, + email: str, + password: str, + project_id: int, + xml_report="junit-report.xml", + suite_id=None, + debug=True, ): """ Default init @@ -289,15 +289,15 @@ def __prepare_title(self, environment=None, timestamp=None): return title def send_results( - self, - run_id=None, - environment=None, - title=None, - timestamp=None, - close_run=True, - run_name=None, - delete_old_run=False, - debug=None, + self, + run_id=None, + environment=None, + title=None, + timestamp=None, + close_run=True, + run_name=None, + delete_old_run=False, + debug=None, ): """ Send results to TestRail @@ -316,9 +316,9 @@ def send_results( if debug: print("\n") if ( - not self.__project_id - or not self.__at_section - or not self.__check_report_exists(xml_report=self.__xml_report) + not self.__project_id + or not self.__at_section + or not self.__check_report_exists(xml_report=self.__xml_report) ): print("Error! Please specify all required params!") self.__self_check() @@ -497,6 +497,7 @@ def __search_for_run_by_name(self, title=None): def __delete_run(self, run_id=None): """ Delete run + :param run_id: run id, integer :return: True if deleted, False in case of error """ @@ -538,6 +539,7 @@ def __add_run(self, title, cases_list=None, include_all=False, debug=None): def __add_results(self, run_id=None, results=None): """ Add results for test cases to TestRail + :param run_id: run id :param results: payload (list of dicts) :return: run id or False in case of error @@ -580,6 +582,7 @@ def __prepare_runs(self, cases=None, title=None, run_id=None, run_name=None, del def __close_run(self, title=None, run_id=None, debug=None): """ Closes run + :param title: title of test run :param run_id: run id, integer :param debug: debug output is enabled, may be True or False, optional diff --git a/testrail_api_reporter/publishers/__init__.py b/testrail_api_reporter/publishers/__init__.py index 32b98e9..3e5ca54 100644 --- a/testrail_api_reporter/publishers/__init__.py +++ b/testrail_api_reporter/publishers/__init__.py @@ -1,4 +1,4 @@ -# Publishers +""" Publishers package. """ from .confluence_sender import ConfluenceSender from .email_sender import EmailSender from .gdrive_uploader import GoogleDriveUploader diff --git a/testrail_api_reporter/publishers/confluence_sender.py b/testrail_api_reporter/publishers/confluence_sender.py index 05aecbe..8c27c74 100644 --- a/testrail_api_reporter/publishers/confluence_sender.py +++ b/testrail_api_reporter/publishers/confluence_sender.py @@ -1,3 +1,4 @@ +""" Confluence sender module """ from atlassian import Confluence from ..engines.plotly_reporter import PlotlyReporter @@ -143,6 +144,24 @@ def history_type_chart(self, confluence_page=None, type_platforms=None, def generate_report(self, confluence_page=None, reports=None, cases=None, values=None, type_platforms=None, automation_platforms=None, debug=None): + """ + Generates and sends (attach) an image file (png) to confluence page with state distribution (staked line chart) + + :param confluence_page: confluence page short URL, string - only last part of it (it's id or str), optional + :param reports: report with stacked distribution, usually it's output of + ATCoverageReporter().automation_state_report() + :param cases: list of values to draw report with priority distribution, usually it's output from + ATCoverageReporter().test_case_by_type() + :param values: list of values to draw report with priority distribution, usually it's output from + ATCoverageReporter().test_case_by_priority() + :param type_platforms: list of dicts, with sections ids, where dict = {'name': 'UI', + 'sections': [16276]}, optional + :param automation_platforms: list of dicts of automation platforms, dict = {'name': 'Desktop Chrome', + 'internal_name': 'type_id', + 'sections': [16276]}, optional + :param debug: debug output is enabled, may be True or False, optional + :return: none + """ confluence_page = confluence_page if confluence_page else self.__confluence_page if not confluence_page: raise ValueError("No confluence page is provided, report aborted!") diff --git a/testrail_api_reporter/publishers/email_sender.py b/testrail_api_reporter/publishers/email_sender.py index 3eaddd2..42fc4a0 100644 --- a/testrail_api_reporter/publishers/email_sender.py +++ b/testrail_api_reporter/publishers/email_sender.py @@ -1,3 +1,4 @@ +""" Email sender module """ import base64 import os import smtplib diff --git a/testrail_api_reporter/publishers/gdrive_uploader.py b/testrail_api_reporter/publishers/gdrive_uploader.py index 944dde2..35ef1e5 100644 --- a/testrail_api_reporter/publishers/gdrive_uploader.py +++ b/testrail_api_reporter/publishers/gdrive_uploader.py @@ -1,3 +1,4 @@ +""" Google Drive uploader module """ import json import os @@ -5,6 +6,7 @@ class GoogleDriveUploader: + """ Google Drive uploader class """ # Google token needs to be configured firstly, to do it, you have to visit: # https://console.developers.google.com/apis/credentials?pli=1 # Create Credentials => OAuth client ID => TV and limited Input Devices and get client_id and a client_secret diff --git a/testrail_api_reporter/publishers/slack_sender.py b/testrail_api_reporter/publishers/slack_sender.py index c80bfe6..43a963c 100644 --- a/testrail_api_reporter/publishers/slack_sender.py +++ b/testrail_api_reporter/publishers/slack_sender.py @@ -1,3 +1,4 @@ +""" Slack sender module """ import json import requests @@ -6,7 +7,7 @@ class SlackSender: - """ See for details https://api.slack.com/messaging/webhooks """ + """ Slack sender class, see for details https://api.slack.com/messaging/webhooks """ def __init__(self, hook_url=None, timeout=5, verify=True, debug=True): """ @@ -47,6 +48,12 @@ def __prepare_attachments(files, captions): @staticmethod def __prepare_blocks(title): + """ + Prepares blocks + + :param title: header title of message + :return: list of dict with blocks info + """ return [{'type': 'header', 'text': {'type': 'plain_text', 'text': title, 'emoji': True}}] def __prepare_payload(self, title, files, captions): diff --git a/testrail_api_reporter/utils/__init__.py b/testrail_api_reporter/utils/__init__.py index 07faa24..0007adf 100644 --- a/testrail_api_reporter/utils/__init__.py +++ b/testrail_api_reporter/utils/__init__.py @@ -1 +1,2 @@ +""" Utils for testrail_api_reporter """ from .reporter_utils import upload_image diff --git a/testrail_api_reporter/utils/case_stat.py b/testrail_api_reporter/utils/case_stat.py index 00d776b..0db6d8c 100644 --- a/testrail_api_reporter/utils/case_stat.py +++ b/testrail_api_reporter/utils/case_stat.py @@ -1,3 +1,6 @@ +""" CaseStat class """ + + class CaseStat: """ Placeholder class for automation statistics diff --git a/testrail_api_reporter/utils/csv_parser.py b/testrail_api_reporter/utils/csv_parser.py index 38af639..8ea721b 100644 --- a/testrail_api_reporter/utils/csv_parser.py +++ b/testrail_api_reporter/utils/csv_parser.py @@ -1,3 +1,4 @@ +""" CSV parser for TestRail API Reporter """ import csv from datetime import datetime from os.path import exists diff --git a/testrail_api_reporter/utils/reporter_utils.py b/testrail_api_reporter/utils/reporter_utils.py index 07233a9..de2a4e3 100644 --- a/testrail_api_reporter/utils/reporter_utils.py +++ b/testrail_api_reporter/utils/reporter_utils.py @@ -1,3 +1,4 @@ +""" This module contains service functions for reporter """ import os import requests @@ -38,12 +39,26 @@ def upload_image(filename, api_token): def delete_file(filename, debug=True): + """ + Service function to delete file from filesystem + + :param filename: filename or path to file, which should be deleted + :param debug: debug output is enabled, may be True or False, optional, by default is True + """ os.popen(f'rm {filename}').read() if debug: print(f'Removed {filename}') def zip_file(filename, suffix=None, debug=True): + """ + Service function to ZIP file + + :param filename: filename or path to file, which should be zipped + :param suffix: suffix for zipped file, optional + :param debug: debug output is enabled, may be True or False, optional, by default is True + :return: zipped filename + """ if suffix is None: suffix = '' zipped_file = f'{filename.split(".")[0]}{suffix}.zip'