Skip to content

Commit

Permalink
Merge pull request #7 from tolstislon/dev
Browse files Browse the repository at this point in the history
version 1.3.0
  • Loading branch information
tolstislon authored Sep 11, 2019
2 parents 297a4b0 + 8856116 commit 36652e3
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 27 deletions.
10 changes: 5 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
name='testrail_api',
version=testrail_api.__version__,
packages=['testrail_api'],
url='https://github.com/tolstislon/testrail-api',
license='MIT License',
author='tolstislon',
author_email='tolstislon@gmail.com',
description='Python wrapper of the TestRail API',
url=testrail_api.__url__,
license=testrail_api.__license__,
author=testrail_api.__author__,
author_email=testrail_api.__author_email__,
description=testrail_api.__description__,
long_description=parse_from_file('README.md'),
install_requires=[
'requests>=2.20.1'
Expand Down
36 changes: 33 additions & 3 deletions testrail_api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
from ._testrail_api import TestRailAPI
# -*- coding: utf-8 -*-

"""
Python wrapper of the TestRail API
------------------
from testrail_api import TestRailAPI
api = TestRailAPI('https://example.testrail.com/', 'example@mail.com', 'password')
my_case = api.cases.get_case(22)
api.cases.add_case(1, 'New Case', milestone_id=1)
------------------
__version__ = '1.2.0'
"""

from .__version__ import (
__version__,
__author__,
__author_email__,
__description__,
__license__,
__url__
)

from ._testrail_api import TestRailAPI

__all__ = ['TestRailAPI']
__all__ = [
'TestRailAPI',
'__version__',
'__author__',
'__author_email__',
'__description__',
'__license__',
'__url__'
]
6 changes: 6 additions & 0 deletions testrail_api/__version__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
__version__ = '1.3.0'
__url__ = 'https://github.com/tolstislon/testrail-api'
__description__ = 'Python wrapper of the TestRail API'
__author__ = 'tolstislon'
__author_email__ = 'tolstislon@gmail.com'
__license__ = 'MIT License'
12 changes: 6 additions & 6 deletions testrail_api/_category.py
Original file line number Diff line number Diff line change
Expand Up @@ -973,8 +973,7 @@ def add_attachment_to_result(self, result_id: int, path: Union[str, Path]) -> di
:param path: The path to the file
:return: response
"""
file = path if isinstance(path, Path) else Path(path)
return self._session.attachment_request(METHODS.POST, f'add_attachment_to_result/{result_id}', file)
return self._session.attachment_request(METHODS.POST, f'add_attachment_to_result/{result_id}', path)

def add_attachment_to_result_for_case(self, result_id: int, case_id: int, path: Union[str, Path]) -> dict:
"""
Expand All @@ -987,10 +986,10 @@ def add_attachment_to_result_for_case(self, result_id: int, case_id: int, path:
:param path: The path to the file
:return: response
"""
file = path if isinstance(path, Path) else Path(path)
return self._session.attachment_request(
METHODS.POST,
f'add_attachment_to_result_for_case/{result_id}/{case_id}', file
f'add_attachment_to_result_for_case/{result_id}/{case_id}',
path
)

def get_attachments_for_case(self, case_id: int) -> List[dict]:
Expand All @@ -1015,16 +1014,17 @@ def get_attachments_for_test(self, test_id: int) -> List[dict]:
"""
return self._session.request(METHODS.GET, f'get_attachments_for_test/{test_id}')

def get_attachment(self, attachment_id: int):
def get_attachment(self, attachment_id: int, path: Union[str, Path]):
"""
http://docs.gurock.com/testrail-api2/reference-attachments#get_attachment
Returns the requested attachment identified by attachment_id.
:param attachment_id:
:param path:
:return: response
"""
return self._session.request(METHODS.GET, f'get_attachment/{attachment_id}')
return self._session.get_attachment(METHODS.GET, f'get_attachment/{attachment_id}', path)

def delete_attachment(self, attachment_id: int) -> None:
"""
Expand Down
84 changes: 72 additions & 12 deletions testrail_api/_session.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
import logging
from json.decoder import JSONDecodeError
from pathlib import Path
from typing import Union
from .__version__ import __version__

import requests

from ._enums import METHODS

log = logging.getLogger(__name__)


class TestRailAPIError(Exception):
pass


class StatusCodeError(TestRailAPIError):
pass


class Session:
_user_agent = 'Python TestRail API v: 1.2'
_user_agent = f'Python TestRail API v: {__version__}'

def __init__(self, base_url: str, user: str, password: str, **kwargs):
def __init__(self, base_url: str, user: str, password: str, exc: bool = False, **kwargs):
"""
:param base_url: TestRail address
:param user: Email for the account on the TestRail
:param password: Password for the account on the TestRail
:param exc: Catching exceptions
:param kwargs:
:key timeout int
:key verify bool
Expand All @@ -21,21 +39,63 @@ def __init__(self, base_url: str, user: str, password: str, **kwargs):
self.__timeout = kwargs.get('timeout', 30)
self.__session = requests.Session()
self.__session.headers['User-Agent'] = self._user_agent
self.__session.headers['Content-Type'] = 'application/json'
self.__session.headers.update(kwargs.get('headers', {}))
self.__session.verify = kwargs.get('verify', True)
self.__session.auth = (user, password)
self.__exc = exc
log.info(
'Create Session{url: %s, user: %s, timeout: %s, headers: %s, verify: %s, exception: %s}',
base_url, user, self.__timeout, self.__session.headers, self.__session.verify, self.__exc
)

def request(self, method: METHODS, src: str, **kwargs):
"""Base request method"""
url = f'{self.__base_url}{src}'
response = self.__session.request(method=method.value, url=url, timeout=self.__timeout, **kwargs)
if 'json' in response.headers.get('Content-Type', ''):
def __del__(self):
self.__session.close()

def __response(self, response: requests.Response):
if not response.ok:
log.error('Code: %s, reason: %s url: %s, content: %s',
response.status_code, response.reason, response.url, response.content)
if not self.__exc:
raise StatusCodeError(response.status_code, response.reason, response.url, response.content)

log.debug('Response body: %s', response.text)
try:
return response.json()
else:
except (JSONDecodeError, ValueError):
return response.text or None

def attachment_request(self, method: METHODS, src: str, file: Path, **kwargs):
def request(self, method: METHODS, src: str, raw: bool = False, **kwargs):
"""Base request method"""
url = f'{self.__base_url}{src}'
if not src.startswith('add_attachment'):
headers = kwargs.setdefault('headers', {})
headers.update({'Content-Type': 'application/json'})

try:
response = self.__session.request(method=method.value, url=url, timeout=self.__timeout, **kwargs)
except Exception as err:
log.error('%s', err, exc_info=True)
raise

log.debug('Response header: %s', response.headers)
return response if raw else self.__response(response)

@staticmethod
def _path(path: Union[Path, str]) -> Path:
return path if isinstance(path, Path) else Path(path)

def attachment_request(self, method: METHODS, src: str, file: Union[Path, str], **kwargs):
""""""
file = self._path(file)
with file.open('rb') as attachment:
return self.request(method, src, files={'attachment': attachment}, **kwargs)

def get_attachment(self, method: METHODS, srs: str, file: Union[Path, str], **kwargs) -> Path:
""""""
return self.request(method, src, files={'file': file.open('rb')},
headers={'Content-Type': 'multipart/form-data'}, **kwargs)
file = self._path(file)
response = self.request(method, srs, raw=True, **kwargs)
if response.ok:
with file.open('wb') as attachment:
attachment.write(response.content)
return file
return self.__response(response)
2 changes: 1 addition & 1 deletion testrail_api/_testrail_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Description
TestRail API Categories
"""

from . import _category
Expand Down

0 comments on commit 36652e3

Please sign in to comment.