Skip to content

Commit

Permalink
Allow overloading to_ and from_ keywords with datetime objects
Browse files Browse the repository at this point in the history
Fixes #82 and moved events tests to own file
  • Loading branch information
bensteUEM committed Nov 26, 2023
1 parent 69035da commit aaf33ab
Show file tree
Hide file tree
Showing 7 changed files with 374 additions and 293 deletions.
19 changes: 13 additions & 6 deletions churchtools_api/calendar.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import logging

from datetime import datetime
from churchtools_api.churchtools_api_abstract import ChurchToolsApiAbstract


Expand Down Expand Up @@ -48,8 +49,8 @@ def get_calendar_appointments(
kwargs: optional params to limit the results
Keyword Arguments:
from_ (str): with starting date in format YYYY-MM-DD - added _ to name as opposed to ct_api because of reserved keyword
to_ (str): end date in format YYYY-MM-DD ONLY allowed with from_ - added _ to name as opposed to ct_api because of reserved keyword
from_ (str|datetime): with starting date in format YYYY-MM-DD - added _ to name as opposed to ct_api because of reserved keyword
to_ (str|datetime): end date in format YYYY-MM-DD ONLY allowed with from_ - added _ to name as opposed to ct_api because of reserved keyword
appointment_id (int): limit to one appointment only - requires calendarId keyword!
Returns:
Expand All @@ -74,11 +75,17 @@ def get_calendar_appointments(
}

if 'from_' in kwargs.keys():
if len(kwargs['from_']) == 10:
params['from'] = kwargs['from_']
from_ = kwargs['from_']
if isinstance(from_, datetime):
from_ = from_.strftime("%Y-%m-%d")
if len(from_) == 10:
params['from'] = from_
if 'to_' in kwargs.keys() and 'from_' in kwargs.keys():
if len(kwargs['to_']) == 10:
params['to'] = kwargs['to_']
to_ = kwargs['to_']
if isinstance(to_, datetime):
to_ = to_.strftime("%Y-%m-%d")
if len(to_) == 10:
params['to'] = to_
elif 'to_' in kwargs.keys():
logging.warning(
'Use of to_ is only allowed together with from_')
Expand Down
42 changes: 27 additions & 15 deletions churchtools_api/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,25 @@ class ChurchToolsApiEvents(ChurchToolsApiAbstract):
def __init__(self):
super()

def get_events(self, **kwargs):
def get_events(self, **kwargs) -> list[dict]:
"""
Method to get all the events from given timespan or only the next event
:param kwargs: optional params to modify the search criteria
:key eventId: int: number of event for single event lookup
:key from_: str: with starting date in format YYYY-MM-DD - added _ to name as opposed to ct_api because of reserved keyword
:key to_: str: end date in format YYYY-MM-DD ONLY allowed with from_ - added _ to name as opposed to ct_api because of reserved keyword
:key canceled: bool: If true, include also canceled events
:key direction: str: direction of output 'forward' or 'backward' from the date defined by parameter 'from'
:key limit: int: limits the number of events - Default = 1, if all events shall be retrieved insert 'None', only applies if direction is specified
:key include: str: if Parameter is set to 'eventServices', the services of the event will be included
:return: list of events
:rtype: list[dict]
Arguments:
kwargs: optional params to modify the search criteria
Keyword Arguments:
eventId (int): number of event for single event lookup
from_ (str|datetime): with starting date in format YYYY-MM-DD - added _ to name as opposed to ct_api because of reserved keyword
to_ (str|datetime): end date in format YYYY-MM-DD ONLY allowed with from_ - added _ to name as opposed to ct_api because of reserved keyword
canceled (bool): If true, include also canceled events
direction (str): direction of output 'forward' or 'backward' from the date defined by parameter 'from'
limit (int): limits the number of events - Default = 1, if all events shall be retrieved insert 'None', only applies if direction is specified
include (str): if Parameter is set to 'eventServices', the services of the event will be included
Returns:
list of events
"""
url = self.domain + '/api/events'

Expand All @@ -43,11 +49,17 @@ def get_events(self, **kwargs):

else:
if 'from_' in kwargs.keys():
if len(kwargs['from_']) == 10:
params['from'] = kwargs['from_']
from_ = kwargs['from_']
if isinstance(from_, datetime):
from_ = from_.strftime("%Y-%m-%d")
if len(from_) == 10:
params['from'] = from_
if 'to_' in kwargs.keys() and 'from_' in kwargs.keys():
if len(kwargs['to_']) == 10:
params['to'] = kwargs['to_']
to_ = kwargs['to_']
if isinstance(to_, datetime):
to_ = to_.strftime("%Y-%m-%d")
if len(to_) == 10:
params['to'] = to_
elif 'to_' in kwargs.keys():
logging.warning(
'Use of to_ is only allowed together with from_')
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "churchtools-api"
version = "1.5.2"
version = "1.5.3"
description = "A python wrapper for use with ChurchToolsAPI"
authors = [
"bensteUEM",
Expand Down
270 changes: 0 additions & 270 deletions tests/test_churchtools_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,276 +456,6 @@ def test_get_songs_with_tag(self):
result = self.api.get_songs_by_tag(tagId)
self.assertEqual(songId, result[0]['id'])

def test_get_events(self):
"""
Tries to get a list of events and a single event from CT
Event ID may vary depending on the server used
On ELKW1610.KRZ.TOOLS event ID 484 is an existing Event with schedule (20th. Nov 2022)
:return:
"""

result = self.api.get_events()
self.assertIsNotNone(result)
self.assertIsInstance(result, list)

eventId = 484
result = self.api.get_events(eventId=eventId)
self.assertIsInstance(result, list)
self.assertEqual(1, len(result))
self.assertIsInstance(result[0], dict)

# load next event (limit)
result = self.api.get_events(limit=1, direction='forward')
self.assertIsInstance(result, list)
self.assertEqual(1, len(result))
self.assertIsInstance(result[0], dict)
result_date = datetime.strptime(
result[0]['startDate'],
'%Y-%m-%dT%H:%M:%S%z').astimezone().date()
today_date = datetime.today().date()
self.assertGreaterEqual(result_date, today_date)

# load last event (direction, limit)
result = self.api.get_events(limit=1, direction='backward')
result_date = datetime.strptime(
result[0]['startDate'],
'%Y-%m-%dT%H:%M:%S%z').astimezone().date()
self.assertLessEqual(result_date, today_date)

# Load events after 7 days (from)
next_week_date = today_date + timedelta(days=7)
next_week_formatted = next_week_date.strftime('%Y-%m-%d')
result = self.api.get_events(from_=next_week_formatted)
result_min_date = min([datetime.strptime(
item['startDate'], '%Y-%m-%dT%H:%M:%S%z').astimezone().date() for item in result])
result_max_date = max([datetime.strptime(
item['startDate'], '%Y-%m-%dT%H:%M:%S%z').astimezone().date() for item in result])
self.assertGreaterEqual(result_min_date, next_week_date)
self.assertGreaterEqual(result_max_date, next_week_date)

# load events for next 14 days (to)
next2_week_date = today_date + timedelta(days=14)
next2_week_formatted = next2_week_date.strftime('%Y-%m-%d')
today_date_formatted = today_date.strftime('%Y-%m-%d')

result = self.api.get_events(
from_=today_date_formatted,
to_=next2_week_formatted)
result_min = min([datetime.strptime(
item['startDate'], '%Y-%m-%dT%H:%M:%S%z').astimezone().date() for item in result])
result_max = max([datetime.strptime(
item['startDate'], '%Y-%m-%dT%H:%M:%S%z').astimezone().date() for item in result])
# only works if there is an event within 7 days on demo system
self.assertLessEqual(result_min, next_week_date)
self.assertLessEqual(result_max, next2_week_date)

# missing keyword pair warning
with self.assertLogs(level=logging.WARNING) as captured:
item = self.api.get_events(to_=next2_week_formatted)
self.assertEqual(len(captured.records), 1)
self.assertEqual(
['WARNING:root:Use of to_ is only allowed together with from_'],
captured.output)

# load more than 10 events (pagination #TODO #1 improve test case for
# pagination
result = self.api.get_events(direction='forward', limit=11)
self.assertIsInstance(result, list)
self.assertGreaterEqual(len(result), 11)

# TODO add test cases for uncommon parts #24 * canceled, include

def test_get_AllEventData_ajax(self):
"""
IMPORTANT - This test method and the parameters used depend on the target system!
Test function to check the get_AllEventData_ajax function for a specific ID
On ELKW1610.KRZ.TOOLS event ID 3396 is an existing Test Event with schedule (1. Jan 2024)
Please be aware that this function is limited to the timeframe configured for cache in CT (by default -90days)
:return:
"""
eventId = 3396
result = self.api.get_AllEventData_ajax(eventId)
self.assertIn('id', result.keys())
self.assertEqual(result['id'], str(eventId))

def test_get_set_event_services_counts(self):
"""
IMPORTANT - This test method and the parameters used depend on the target system!
Test function for get and set methods related to event services counts
tries to get the number of specicifc service in an id
tries to increase that number
tries to get the number again
tries to set it back to original
On ELKW1610.KRZ.TOOLS event ID 2626 is an existing test Event with schedule (1. Jan 2023)
On ELKW1610.KRZ.TOOLS serviceID 1 is Predigt (1. Jan 2023)
:return:
"""
eventId = 2626
serviceId = 1
original_count_comapre = 3

event = self.api.get_events(eventId=eventId)

original_count = self.api.get_event_services_counts_ajax(
eventId=eventId, serviceId=serviceId)
self.assertEqual(original_count, {serviceId: original_count_comapre})

result = self.api.set_event_services_counts_ajax(eventId, serviceId, 2)
self.assertTrue(result)

new_count = self.api.get_event_services_counts_ajax(
eventId=eventId, serviceId=serviceId)
self.assertEqual(new_count, {serviceId: 2})

result = self.api.set_event_services_counts_ajax(
eventId, serviceId, original_count[serviceId])
self.assertTrue(result)

def test_get_set_event_admins(self):
"""
IMPORTANT - This test method and the parameters used depend on the target system!
Test function to get list of event admins, change it and check again (and reset to original)
On ELKW1610.KRZ.TOOLS event ID 3396 is an existing Test Event with schedule (1. Jan 2024)
Please be aware that this function is limited to the timeframe configured for cache in CT (by default -90days)
:return:
"""
eventId = 3396
admin_ids_original_test = [9]

admin_ids_original = self.api.get_event_admins_ajax(eventId)
self.assertEqual(admin_ids_original, admin_ids_original_test)

admin_ids_change = [0, 1, 2]
result = self.api.set_event_admins_ajax(eventId, admin_ids_change)
self.assertTrue(result)

admin_ids_test = self.api.get_event_admins_ajax(eventId)
self.assertEqual(admin_ids_change, admin_ids_test)

self.assertTrue(
self.api.set_event_admins_ajax(
eventId, admin_ids_original_test))

def test_get_event_masterdata(self):
"""
IMPORTANT - This test method and the parameters used depend on the target system!
Tries to get a list of event masterdata and a type of masterdata from CT
The values depend on your system data! - Test case is valid against ELKW1610.KRZ.TOOLS
:return:
"""
result = self.api.get_event_masterdata()
self.assertEqual(len(result), 5)

result = self.api.get_event_masterdata(type='serviceGroups')
self.assertGreater(len(result), 1)
self.assertEqual(result[0]['name'], 'Programm')

result = self.api.get_event_masterdata(
type='serviceGroups', returnAsDict=True)
self.assertIsInstance(result, dict)
result = self.api.get_event_masterdata(
type='serviceGroups', returnAsDict=False)
self.assertIsInstance(result, list)

def test_get_event_agenda(self):
"""
IMPORTANT - This test method and the parameters used depend on the target system!
Tries to get an event agenda from a CT Event
Event ID may vary depending on the server used
On ELKW1610.KRZ.TOOLS event ID 484 is an existing Event with schedule (20th. Nov 2022)
:return:
"""
eventId = 484
result = self.api.get_event_agenda(eventId)
self.assertIsNotNone(result)

def test_export_event_agenda(self):
"""
IMPORTANT - This test method and the parameters used depend on the target system!
Test function to download an Event Agenda file package for e.g. Songbeamer
Event ID may vary depending on the server used
On ELKW1610.KRZ.TOOLS event ID 484 is an existing Event with schedule (20th. Nov 2022)
"""
eventId = 484
agendaId = self.api.get_event_agenda(eventId)['id']

with self.assertLogs(level=logging.WARNING) as captured:
download_result = self.api.export_event_agenda('SONG_BEAMER')
self.assertEqual(len(captured.records), 1)
self.assertFalse(download_result)

if os.path.exists('downloads'):
for file in os.listdir('downloads'):
os.remove('downloads/' + file)
self.assertEqual(len(os.listdir('downloads')), 0)

download_result = self.api.export_event_agenda(
'SONG_BEAMER', agendaId=agendaId)
self.assertTrue(download_result)

download_result = self.api.export_event_agenda(
'SONG_BEAMER', eventId=eventId)
self.assertTrue(download_result)

self.assertEqual(len(os.listdir('downloads')), 2)

def test_get_services(self):
"""
Tries to get all and a single services configuration from the server
serviceId varies depending on the server used id 1 = Predigt and more than one item exsits
On any KRZ.TOOLS serviceId 1 is named 'Predigt' and more than one service exists by default (13. Jan 2023)
:return:
"""
serviceId = 1
result1 = self.api.get_services()
self.assertIsInstance(result1, list)
self.assertIsInstance(result1[0], dict)
self.assertGreater(len(result1), 1)

result2 = self.api.get_services(serviceId=serviceId)
self.assertIsInstance(result2, dict)
self.assertEqual(result2['name'], 'Predigt')

result3 = self.api.get_services(returnAsDict=True)
self.assertIsInstance(result3, dict)

result4 = self.api.get_services(returnAsDict=False)
self.assertIsInstance(result4, list)

def test_get_tags(self):
"""
Test function for get_tags() with default type song
On ELKW1610.KRZ.TOOLS tag ID 49 has the name To Do
:return:
"""
result = self.api.get_tags()
self.assertGreater(len(result), 0)
test_tag = [item for item in result if item['id'] == 49][0]
self.assertEqual(test_tag['id'], 49)
self.assertEqual(test_tag['name'], 'ToDo')

def test_has_event_schedule(self):
"""
Tries to get boolean if event agenda exists for a CT Event
Event ID may vary depending on the server used
On ELKW1610.KRZ.TOOLS event ID 484 is an existing Event with schedule (20th. Nov 2022)
2376 does not have one
:return:
"""
eventId = 484
result = self.api.get_event_agenda(eventId)
self.assertIsNotNone(result)
eventId = 2376
result = self.api.get_event_agenda(eventId)
self.assertIsNone(result)

def test_file_download(self):
""" Test of file_download and file_download_from_url on https://elkw1610.krz.tools on any song
IDs vary depending on the server used
Expand Down
Loading

0 comments on commit aaf33ab

Please sign in to comment.