Skip to content
Snippets Groups Projects
Commit 60eaa295 authored by Robert Habermann's avatar Robert Habermann
Browse files

wip

parent aabd6608
No related branches found
No related tags found
No related merge requests found
""" __init__.py """ """ __init__.py """
from .pyotrs import PyOTRS from .client import *
...@@ -111,30 +111,31 @@ class Client(object): ...@@ -111,30 +111,31 @@ class Client(object):
self.webservicename = webservicename self.webservicename = webservicename
if not session_id_file: if not session_id_file:
self.session_id_file = ".session_id.tmp" self.session_id_file = "/tmp/.session_id.tmp"
else:
self.session_id_file = session_id_file
if not session_timeout: if not session_timeout:
self.session_timeout = 28800 # 8 hours is OTRS default self.session_timeout = 28800 # 8 hours is OTRS default
self.https_verify = https_verify
# dummy initialization
self.data = None
self.data_type = None
self.data_json = None
# if session_id is passed in with a value other than None # if session_id is passed in with a value other than None
# ignore username and password and use session_id # ignore username and password and use session_id
# if session_id is None then restore or create a Session! # if session_id is None then restore or create a Session!
self.username = username self.username = username
self.password = password self.password = password
self.session_id_file = session_id_file
if not session_id: if not session_id:
self.restore_or_set_up_session() self.restore_or_set_up_session()
else: else:
self.session_id = session_id self.session_id = session_id
self.https_verify = https_verify
# dummy initialization
self.data = None
self.data_type = None
self.data_json = None
""" """
GenericInterface::Operation::Session::SessionCreate GenericInterface::Operation::Session::SessionCreate
Client public methods: Client public methods:
...@@ -180,9 +181,9 @@ class Client(object): ...@@ -180,9 +181,9 @@ class Client(object):
""" """
if not session_id: if not session_id:
client = TicketGet(self.baseurl, self.webservicename, session_id=self.session_id) client = Client(self.baseurl, self.webservicename, session_id=self.session_id)
else: else:
client = TicketGet(self.baseurl, self.webservicename, session_id=session_id) client = Client(self.baseurl, self.webservicename, session_id=session_id)
return client.ticket_get_by_id(1, dynamic_fields=0, all_articles=0) return client.ticket_get_by_id(1, dynamic_fields=0, all_articles=0)
...@@ -192,12 +193,21 @@ class Client(object): ...@@ -192,12 +193,21 @@ class Client(object):
""" """
if os.path.isfile(self.session_id_file): if os.path.isfile(self.session_id_file):
with open(self.session_id_file, "r") as f: with open(self.session_id_file, "r") as f:
data = json.loads(f.read()) content = f.read()
created = data['created'] try:
data = json.loads(content)
created = datetime.datetime.utcfromtimestamp(int(data['created']))
expires = created + datetime.timedelta(minutes=self.session_timeout) expires = created + datetime.timedelta(minutes=self.session_timeout)
if expires > datetime.datetime.utcnow(): if expires > datetime.datetime.utcnow():
self.session_id = data['session_id'] # still valid self.session_id = data['session_id'] # still valid
return True return True
except ValueError as err:
logger.error("JSON Parse Exception: {}".format(err))
pass # pass this exception as
except Exception as err:
logger.error("Some Exception: {}".format(err))
raise Exception("Some Exception: {}".format(err))
return False return False
...@@ -210,7 +220,7 @@ class Client(object): ...@@ -210,7 +220,7 @@ class Client(object):
""" """
with open(self.session_id_file, "w") as f: with open(self.session_id_file, "w") as f:
f.write(json.dumps({'created': datetime.datetime.utcnow(), f.write(json.dumps({'created': str(int(time.time())),
'session_id': self.session_id})) 'session_id': self.session_id}))
return True return True
...@@ -224,7 +234,7 @@ class Client(object): ...@@ -224,7 +234,7 @@ class Client(object):
payload = { payload = {
"UserLogin": self.username, "UserLogin": self.username,
"Password": self.password "Password": self.password
} }
try: try:
...@@ -246,20 +256,18 @@ class Client(object): ...@@ -246,20 +256,18 @@ class Client(object):
return True return True
class TicketCreate(Client):
""" """
GenericInterface::Operation::Ticket::TicketCreate GenericInterface::Operation::Ticket::TicketCreate
TicketCreate public methods: public methods:
* ticket_create
""" """
pass def ticket_create(self):
pass
class TicketGet(Client):
""" """
GenericInterface::Operation::Ticket::TicketGet GenericInterface::Operation::Ticket::TicketGet
TicketGet public methods: public methods:
* ticket_get_by_id * ticket_get_by_id
""" """
...@@ -343,8 +351,8 @@ class TicketGet(Client): ...@@ -343,8 +351,8 @@ class TicketGet(Client):
"{0.webservicename}/Ticket/{1}".format(self, ticket_id) "{0.webservicename}/Ticket/{1}".format(self, ticket_id)
payload = { payload = {
"SessionID": self.session_id, "SessionID": self.session_id,
"AllArticles": all_articles, "AllArticles": all_articles,
"DynamicFields": dynamic_fields "DynamicFields": dynamic_fields
} }
...@@ -354,11 +362,9 @@ class TicketGet(Client): ...@@ -354,11 +362,9 @@ class TicketGet(Client):
logger.error("Exception: {0}".format(err)) logger.error("Exception: {0}".format(err))
return False return False
class TicketSearch(Client):
""" """
GenericInterface::Operation::Ticket::TicketSearch GenericInterface::Operation::Ticket::TicketSearch
TicketSearch public methods: public methods:
* ticket_search * ticket_search
* ticket_search_by_past_days * ticket_search_by_past_days
""" """
...@@ -488,7 +494,7 @@ class TicketSearch(Client): ...@@ -488,7 +494,7 @@ class TicketSearch(Client):
older = newer - 1440 * days older = newer - 1440 * days
payload = { payload = {
"SessionID": self.session_id, "SessionID": self.session_id,
"TicketLastChangeTimeNewerMinutes": newer, "TicketLastChangeTimeNewerMinutes": newer,
"TicketLastChangeTimeOlderMinutes": older "TicketLastChangeTimeOlderMinutes": older
} }
...@@ -501,17 +507,13 @@ class TicketSearch(Client): ...@@ -501,17 +507,13 @@ class TicketSearch(Client):
logger.error("Exception: {0}".format(err)) logger.error("Exception: {0}".format(err))
return False return False
# GenericInterface :: Operation::Ticket :: TicketUpdate
class TicketUpdate(Client): # public methods
""" # * ticket_update_add_article
GenericInterface::Operation::Ticket::TicketUpdate # * ticket_update_set_dynamic_field_value
TicketUpdate public methods: # * ticket_update_set_state
* ticket_update_add_article # * ticket_update_set_state_pending
* ticket_update_set_dynamic_field_value # * ticket_update_set_title
* ticket_update_set_state
* ticket_update_set_state_pending
* ticket_update_set_title
"""
def _update_by_ticket_id(self, url, payload): def _update_by_ticket_id(self, url, payload):
""" update_by_ticket_id """ update_by_ticket_id
...@@ -589,9 +591,9 @@ class TicketUpdate(Client): ...@@ -589,9 +591,9 @@ class TicketUpdate(Client):
payload = { payload = {
"SessionID": self.session_id, "SessionID": self.session_id,
"Article": { "Article": {
"Subject": article_subject, "Subject": article_subject,
"Body": article_body, "Body": article_body,
"TimeUnit": 0, "TimeUnit": 0,
"ContentType": "text/plain; charset=ISO-8859-15" "ContentType": "text/plain; charset=ISO-8859-15"
} }
} }
...@@ -629,7 +631,7 @@ class TicketUpdate(Client): ...@@ -629,7 +631,7 @@ class TicketUpdate(Client):
"{0.webservicename}/Ticket/{1}".format(self, ticket_id) "{0.webservicename}/Ticket/{1}".format(self, ticket_id)
payload = { payload = {
"SessionID": self.session_id, "SessionID": self.session_id,
"DynamicField": {"Name": dynamic_field_name, "Value": dynamic_field_value} "DynamicField": {"Name": dynamic_field_name, "Value": dynamic_field_value}
} }
...@@ -658,7 +660,7 @@ class TicketUpdate(Client): ...@@ -658,7 +660,7 @@ class TicketUpdate(Client):
payload = { payload = {
"SessionID": self.session_id, "SessionID": self.session_id,
"Ticket": {"State": new_state} "Ticket": {"State": new_state}
} }
logger.debug("Updating {0} with: ".format(ticket_id)) logger.debug("Updating {0} with: ".format(ticket_id))
...@@ -693,16 +695,16 @@ class TicketUpdate(Client): ...@@ -693,16 +695,16 @@ class TicketUpdate(Client):
pending_time = time.gmtime( pending_time = time.gmtime(
time.time() + (pending_hours * 3600) + (pending_days * 3600 * 24)) time.time() + (pending_hours * 3600) + (pending_days * 3600 * 24))
pending_time_str = { pending_time_str = {
"Year": pending_time.tm_year, "Year": pending_time.tm_year,
"Month": pending_time.tm_mon, "Month": pending_time.tm_mon,
"Day": pending_time.tm_mday, "Day": pending_time.tm_mday,
"Hour": pending_time.tm_hour, "Hour": pending_time.tm_hour,
"Minute": pending_time.tm_min "Minute": pending_time.tm_min
} }
payload = { payload = {
"SessionID": self.session_id, "SessionID": self.session_id,
"Ticket": {"State": new_state, "PendingTime": pending_time_str} "Ticket": {"State": new_state, "PendingTime": pending_time_str}
} }
logger.debug("Updating {0} with: ".format(ticket_id)) logger.debug("Updating {0} with: ".format(ticket_id))
...@@ -742,54 +744,4 @@ class TicketUpdate(Client): ...@@ -742,54 +744,4 @@ class TicketUpdate(Client):
logger.error("Exception: {0}".format(err)) logger.error("Exception: {0}".format(err))
return False return False
def _get_numeric_logger_level_from_string(level):
"""Parse string and return appropriate numeric logger level
Args:
level (str): the string representation of a logging level.
Level is one of these: [NOTSET|TRACE|DEBUG|INFO|WARNING|ERROR|CRITICAL]
Returns:
int: value of the log level - see doctests below for mapping
if for some reason the level is not known return DEBUG (10)
Examples:
>>> print(_get_numeric_logger_level_from_string("NOTSET"))
0
>>> print(_get_numeric_logger_level_from_string("TRACE"))
5
>>> print(_get_numeric_logger_level_from_string("DEBUG"))
10
>>> print(_get_numeric_logger_level_from_string("INFO"))
20
>>> print(_get_numeric_logger_level_from_string("WARNING"))
30
>>> print(_get_numeric_logger_level_from_string("ERROR"))
40
>>> print(_get_numeric_logger_level_from_string("CRITICAL"))
50
>>> print(_get_numeric_logger_level_from_string("FOO_BAR"))
10
"""
if level == "NOTSET":
return 0
elif level == "TRACE":
return 5
elif level == "DEBUG":
return 10
elif level == "INFO":
return 20
elif level == "WARNING":
return 30
elif level == "ERROR":
return 40
elif level == "CRITICAL":
return 50
else:
return 10
# EOF # EOF
This diff is collapsed.
from doctest import DocTestSuite from doctest import DocTestSuite
from unittest import TestSuite from unittest import TestSuite
def load_tests(loader, tests, pattern): def load_tests(loader, tests, pattern):
suite = TestSuite() suite = TestSuite()
suite.addTests(DocTestSuite('pyotrs.pyotrs')) suite.addTests(DocTestSuite('pyotrs.client'))
return suite return suite
...@@ -21,7 +21,8 @@ import responses ...@@ -21,7 +21,8 @@ import responses
from mock import MagicMock, patch from mock import MagicMock, patch
from pyotrs import Client from pyotrs import Client
from pyotrs import TicketCreate, TicketGet, TicketSearch, TicketUpdate from pyotrs import NoBaseURL, NoWebServiceName, NoCredentials
from pyotrs import SessionCreateError, SessionIDFileError, OTRSAPIError, OTRSHTTPError
class PyOTRSTests(unittest.TestCase): class PyOTRSTests(unittest.TestCase):
...@@ -89,9 +90,9 @@ class PyOTRSTests(unittest.TestCase): ...@@ -89,9 +90,9 @@ class PyOTRSTests(unittest.TestCase):
'DynamicFields': 1 'DynamicFields': 1
} }
obj = TicketGet(self.base_url, self.webservice_name, username, password) obj = Client(self.base_url, self.webservice_name, username, password)
self.assertRaisesRegexp(Exception, 'get api', obj._get_json_ticket_data, url=url, self.assertRaisesRegexp(OTRSAPIError, 'get api', obj._get_json_ticket_data, url=url,
payload=payload) payload=payload)
""" Test Responses: when calling: get_json_ticket_data_by_ticket_id - Test 200 OK; Body Error """ Test Responses: when calling: get_json_ticket_data_by_ticket_id - Test 200 OK; Body Error
...@@ -117,13 +118,13 @@ class PyOTRSTests(unittest.TestCase): ...@@ -117,13 +118,13 @@ class PyOTRSTests(unittest.TestCase):
username = "wrong_username" username = "wrong_username"
password = "wrong_password" password = "wrong_password"
obj = TicketGet(self.base_url, self.webservice_name, username, password) obj = Client(self.base_url, self.webservice_name, username, password)
obj.ticket_get_by_id(1) obj.ticket_get_by_id(1)
# self.logger.debug(obj.data) # self.logger.debug(obj.data)
self.assertEqual({"Error": {"ErrorMessage": "TicketGet: Authorization failing!", self.assertEqual({"Error": {"ErrorMessage": "TicketGet: Authorization failing!",
"ErrorCode" : "TicketGet.AuthFail"}}, obj.data.json()) "ErrorCode": "TicketGet.AuthFail"}}, obj.data.json())
self.assertEqual(200, obj.data.status_code) self.assertEqual(200, obj.data.status_code)
""" Test Responses: update title on valid ticket """ """ Test Responses: update title on valid ticket """
...@@ -148,7 +149,7 @@ class PyOTRSTests(unittest.TestCase): ...@@ -148,7 +149,7 @@ class PyOTRSTests(unittest.TestCase):
username = "fake_username" username = "fake_username"
password = "fake_password" password = "fake_password"
obj = TicketUpdate(self.base_url, self.webservice_name, username, password) obj = Client(self.base_url, self.webservice_name, username, password)
obj.ticket_update_set_title(10, "Full New Title") obj.ticket_update_set_title(10, "Full New Title")
self.assertEqual({"TicketNumber": "1970010100000010", "TicketID": "10"}, obj.data.json()) self.assertEqual({"TicketNumber": "1970010100000010", "TicketID": "10"}, obj.data.json())
...@@ -176,10 +177,10 @@ class PyOTRSTests(unittest.TestCase): ...@@ -176,10 +177,10 @@ class PyOTRSTests(unittest.TestCase):
username = "fake_username" username = "fake_username"
password = "fake_password" password = "fake_password"
obj = TicketUpdate(self.base_url, self.webservice_name, username, password) obj = Client(self.base_url, self.webservice_name, username, password)
obj.ticket_update_set_title(20, "Full New Title") obj.ticket_update_set_title(20, "Full New Title")
self.assertEqual({"Error": {"ErrorCode" : "TicketUpdate.AccessDenied", self.assertEqual({"Error": {"ErrorCode": "TicketUpdate.AccessDenied",
"ErrorMessage": "TicketUpdate: User does not have access to the ticket!"}}, "ErrorMessage": "TicketUpdate: User does not have access to the ticket!"}},
obj.data.json()) obj.data.json())
self.assertEqual(200, obj.data.status_code) self.assertEqual(200, obj.data.status_code)
...@@ -209,7 +210,7 @@ class PyOTRSTests(unittest.TestCase): ...@@ -209,7 +210,7 @@ class PyOTRSTests(unittest.TestCase):
} }
### create object ### create object
obj = TicketGet(self.base_url, self.webservice_name, username, password) obj = Client(self.base_url, self.webservice_name, username, password)
### enable Mock ### enable Mock
obj._get_json_ticket_data = MagicMock() obj._get_json_ticket_data = MagicMock()
...@@ -241,7 +242,7 @@ class PyOTRSTests(unittest.TestCase): ...@@ -241,7 +242,7 @@ class PyOTRSTests(unittest.TestCase):
mock_username = "wrong_username" mock_username = "wrong_username"
mock_password = "wrong_password" mock_password = "wrong_password"
obj = TicketGet(self.base_url, self.webservice_name, mock_username, mock_password) obj = Client(self.base_url, self.webservice_name, mock_username, mock_password)
with patch('requests.get') as patched_get: with patch('requests.get') as patched_get:
obj.ticket_get_by_id(1) obj.ticket_get_by_id(1)
......
...@@ -53,8 +53,8 @@ basepython = python2.7 ...@@ -53,8 +53,8 @@ basepython = python2.7
commands = flake8 \ commands = flake8 \
--max-complexity=15 \ --max-complexity=15 \
--exclude=./build,.venv,.tox,dist,doc \ --exclude=./build,.venv,.tox,dist,doc,test_pyotrs.py \
--ignore=F403 \ --ignore=F403,Q000 \
--max-line-length=99 \ --max-line-length=99 \
[] []
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment