Skip to content

Commit 264746a

Browse files
authored
Merge pull request #3 from nassauwinter/session_attrs
Modify signature of the ZephyrSession constructor to be able to pass any session attributes
2 parents 98979a8 + 0135322 commit 264746a

File tree

3 files changed

+117
-5
lines changed

3 files changed

+117
-5
lines changed

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = zephyr-python-api
3-
version = 0.0.1
3+
version = 0.0.2
44
author = Petr Sharapenko
55
author_email = nassauwinter@gmail.com
66
description = Zephyr (TM4J) Python REST API wrapper

tests/unit/test_zephyr_session.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import pytest
2+
from requests import Session
3+
4+
from zephyr.scale.scale import DEFAULT_BASE_URL, ZephyrSession
5+
from zephyr.scale.zephyr_session import INIT_SESSION_MSG, InvalidAuthData
6+
7+
REQUESTS_SESSION_PATH = "requests.sessions.Session"
8+
GETLOGGER_PATH = "logging.getLogger"
9+
LOGGER_DEBUG_PATH = "logging.Logger.debug"
10+
11+
12+
@pytest.mark.unit
13+
class TestZephyrSession:
14+
def test_creation(self, mocker):
15+
"""Tests basic creation logic"""
16+
logger_mock = mocker.patch(GETLOGGER_PATH)
17+
18+
zsession = ZephyrSession(DEFAULT_BASE_URL, token="token_test")
19+
20+
assert zsession.base_url == DEFAULT_BASE_URL, (f"Attribute base_url expected to be {DEFAULT_BASE_URL}, "
21+
f"not {zsession.base_url}")
22+
assert isinstance(zsession._session, Session)
23+
logger_mock.assert_called_with("zephyr.scale.zephyr_session")
24+
25+
def test_token_auth(self, mocker):
26+
"""Test token auth"""
27+
token = "test_token"
28+
logger_mock = mocker.patch(LOGGER_DEBUG_PATH)
29+
30+
zsession = ZephyrSession(DEFAULT_BASE_URL, token=token)
31+
32+
logger_mock.assert_called_with(INIT_SESSION_MSG.format("token"))
33+
assert f"Bearer {token}" == zsession._session.headers.get("Authorization")
34+
35+
def test_credentials_auth(self, mocker):
36+
"""Test auth with username and password"""
37+
username = "usertest"
38+
password = "pwdtest"
39+
logger_mock = mocker.patch(LOGGER_DEBUG_PATH)
40+
41+
zsession = ZephyrSession(DEFAULT_BASE_URL, username=username, password=password)
42+
43+
logger_mock.assert_called_with(INIT_SESSION_MSG.format("username and password"))
44+
assert (username, password) == zsession._session.auth
45+
46+
def test_cookie_auth(self, mocker):
47+
"""Test auth with cookie dict"""
48+
test_cookie = {"cookies": {"cookie.token": "cookie_test"}}
49+
logger_mock = mocker.patch(LOGGER_DEBUG_PATH)
50+
51+
zsession = ZephyrSession(DEFAULT_BASE_URL, cookies=test_cookie)
52+
53+
logger_mock.assert_called_with(INIT_SESSION_MSG.format("cookies"))
54+
assert test_cookie['cookies'] in zsession._session.cookies.values()
55+
56+
@pytest.mark.parametrize("auth_data, exception", [(dict(), InvalidAuthData),
57+
({"username": "user"}, InvalidAuthData),
58+
({"password": "pwd"}, InvalidAuthData)])
59+
def test_auth_exception(self, auth_data, exception):
60+
"""Test exceptions on auth"""
61+
with pytest.raises(exception):
62+
ZephyrSession(DEFAULT_BASE_URL, **auth_data)
63+
64+
@pytest.mark.parametrize("creation_kwargs",
65+
[{"token": "token_test",
66+
"session_attrs": {'verify': False, "max_redirects": 333}}])
67+
def test_requests_session_attrs(self, creation_kwargs, mocker):
68+
"""The test checks ZephyrScale (not) provided with "session_attrs"."""
69+
logger_mock = mocker.patch(LOGGER_DEBUG_PATH)
70+
session_attrs = creation_kwargs.get('session_attrs')
71+
72+
zsession = ZephyrSession(DEFAULT_BASE_URL, **creation_kwargs)
73+
74+
logger_mock.assert_called_with(
75+
f"Modify requests session object with {session_attrs}")
76+
77+
for attrib, value in session_attrs.items():
78+
actual = getattr(zsession._session, attrib)
79+
assert actual == session_attrs[attrib], (f"Request session attr {attrib} is {actual}, "
80+
f"but expected{session_attrs[attrib]}")
81+
82+
@pytest.mark.skip
83+
def test_crud_request(self):
84+
"""Test GET, POST, PUT, DELETE requests"""
85+
pass
86+
87+
@pytest.mark.skip
88+
def test_get_paginated(self):
89+
"""Test paginated request"""
90+
pass
91+
92+
@pytest.mark.skip
93+
def test_post_file(self):
94+
"""Test Post file wrapper"""
95+
pass

zephyr/scale/zephyr_session.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import logging
22
from urllib.parse import urlparse, parse_qs
33

4-
from requests import Session
4+
from requests import HTTPError, Session
55

66

77
INIT_SESSION_MSG = "Initialize session by {}"
88

99

10+
class InvalidAuthData(Exception):
11+
"""Invalid authentication data provided"""
12+
13+
1014
class ZephyrSession:
1115
"""
1216
Zephyr Scale basic session object.
@@ -16,11 +20,15 @@ class ZephyrSession:
1620
:param username: username
1721
:param password: password
1822
:param cookies: cookie dict
23+
24+
:keyword session_attrs: a dict with session attrs to be set as keys and their values
1925
"""
20-
def __init__(self, base_url, token=None, username=None, password=None, cookies=None):
26+
def __init__(self, base_url, token=None, username=None, password=None, cookies=None, **kwargs):
2127
self.base_url = base_url
2228
self._session = Session()
29+
2330
self.logger = logging.getLogger(__name__)
31+
2432
if token:
2533
self.logger.debug(INIT_SESSION_MSG.format("token"))
2634
self._session.headers.update({"Authorization": f"Bearer {token}"})
@@ -31,12 +39,21 @@ def __init__(self, base_url, token=None, username=None, password=None, cookies=N
3139
self.logger.debug(INIT_SESSION_MSG.format("cookies"))
3240
self._session.cookies.update(cookies)
3341
else:
34-
raise Exception("Insufficient auth data")
42+
raise InvalidAuthData("Insufficient auth data")
43+
44+
if kwargs.get("session_attrs"):
45+
self._modify_session(**kwargs.get("session_attrs"))
3546

3647
def _create_url(self, *args):
3748
"""Helper for URL creation"""
3849
return self.base_url + "/".join(args)
3950

51+
def _modify_session(self, **kwargs):
52+
"""Modify requests session with extra arguments"""
53+
self.logger.debug(f"Modify requests session object with {kwargs}")
54+
for session_attr, value in kwargs.items():
55+
setattr(self._session, session_attr, value)
56+
4057
def _request(self, method: str, endpoint: str, return_raw: bool = False, **kwargs):
4158
"""General request wrapper with logging and handling response"""
4259
self.logger.debug(f"{method.capitalize()} data: endpoint={endpoint} and {kwargs}")
@@ -48,7 +65,7 @@ def _request(self, method: str, endpoint: str, return_raw: bool = False, **kwarg
4865
if response.text:
4966
return response.json()
5067
return ""
51-
raise Exception(f"Error {response.status_code}. Response: {response.content}")
68+
raise HTTPError(f"Error {response.status_code}. Response: {response.content}")
5269

5370
def get(self, endpoint: str, params: dict = None, **kwargs):
5471
"""Get request wrapper"""

0 commit comments

Comments
 (0)