pyppms.booking
Module representing bookings / reservations in PPMS.
1"""Module representing bookings / reservations in PPMS.""" 2 3from datetime import datetime, timedelta 4 5from loguru import logger as log 6 7from .common import time_rel_to_abs, fmt_time 8 9 10class PpmsBooking: 11 12 """Object representing a booking (reservation) in PPMS. 13 14 Attributes 15 ---------- 16 username : str 17 The user's account / login name the booking is linked to. 18 system_id : int 19 The PPMS system ID to which this booking refers to. 20 starttime : datetime.date 21 The booking's starting time. 22 endtime : datetime.date or NoneType 23 The booking's ending time, can be 'None'. 24 session : str 25 A string referring to a session ID in PPMS, can be empty. 26 """ 27 28 def __init__(self, text, booking_type, system_id): 29 r"""Initialize the booking object. 30 31 Parameters 32 ---------- 33 text : str 34 The response text of a PUMAPI `getbooking` or `nextbooking` request, 35 should consist of three lines: username, time_delta, session. 36 Example: ``pyppms\n42\n12345\n`` 37 booking_type : str 38 Either ``get`` (for a currently running booking) or ``next`` (for 39 the next upcoming booking). 40 system_id : int or int-like 41 The ID of the system the booking refers to. 42 """ 43 valid = ["get", "next"] 44 if booking_type not in valid: 45 raise ValueError( 46 f"Value for 'booking_type' ({booking_type}) not in {valid}!" 47 ) 48 49 try: 50 lines = text.splitlines() 51 starttime = time_rel_to_abs(lines[1]) 52 endtime = None 53 54 if booking_type == "get": 55 endtime = starttime 56 starttime = datetime.now().replace(second=0, microsecond=0) 57 58 self.username = lines[0] 59 self.system_id = int(system_id) 60 self.starttime = starttime 61 self.endtime = endtime 62 self.session = lines[2] 63 except Exception as err: 64 log.error("Parsing booking response failed ({}), text was:\n{}", err, text) 65 raise 66 67 log.trace(str(self)) 68 69 # FIXME: date is of type datetime.datetime, NOT datetime.date !!! 70 @classmethod 71 def from_runningsheet(cls, entry, system_id, username, date): 72 """Alternative constructor using a (parsed) getrunningsheet response. 73 74 Parameters 75 ---------- 76 entry : dict 77 One item of a 'getrunningsheet' response processed by the 78 parse_multiline_response function. 79 system_id : int or int-like 80 The system ID to which this booking refers to. 81 username : str 82 The user's account / login name for PPMS. 83 date : datetime.date 84 The date object of the *DAY* this booking is linked to. Note that 85 the exact start- and end-time of the booking will be taken from the 86 ``entry`` dict above. 87 88 Returns 89 ------- 90 pyppms.booking.PpmsBooking 91 The object constructed with the parsed response. 92 """ 93 try: 94 response = f"{username}\n0\n\n" 95 booking = cls(response, "get", system_id) 96 booking.starttime_fromstr(entry["Start time"], date) 97 booking.endtime_fromstr(entry["End time"], date) 98 except Exception as err: 99 log.error( 100 "Parsing runningsheet entry failed ({}), text was:\n{}", err, entry 101 ) 102 raise 103 104 log.trace(f"Created booking from runningsheet: {booking}") 105 return booking 106 107 def starttime_fromstr(self, time_str, date=None): 108 """Change the starting time and / or day of a booking. 109 110 Parameters 111 ---------- 112 time_str : str 113 The new starting time in format ``%H:%M:%S`` (e.g. ``13:45:00``). 114 date : datetime.date, optional 115 The new starting day, by default ``None`` which will result in the 116 current date to be used. 117 """ 118 if date is None: 119 date = datetime.now() 120 start = date.replace( 121 hour=int(time_str.split(":")[0]), 122 minute=int(time_str.split(":")[1]), 123 second=0, 124 microsecond=0, 125 ) 126 self.starttime = start 127 log.trace("New starttime: {}", self) 128 129 def endtime_fromstr(self, time_str, date=None): 130 """Change the ending time and / or day of a booking. 131 132 Parameters 133 ---------- 134 time_str : str 135 The new ending time in format ``%H:%M:%S`` (e.g. ``13:45:00``). 136 date : datetime.date, optional 137 The new ending day, by default ``None`` which will result in the 138 current date to be used. 139 """ 140 if date is None: 141 date = datetime.now() 142 end = date.replace( 143 hour=int(time_str.split(":")[0]), 144 minute=int(time_str.split(":")[1]), 145 second=0, 146 microsecond=0, 147 ) 148 if end.hour == 0 and end.minute == 0: 149 end = end + timedelta(days=1) 150 log.debug(f"Booking end is midnight, adjust date to {end}") 151 self.endtime = end 152 log.trace("New endtime: {}", self) 153 154 def __str__(self): 155 msg = ( 156 f"PpmsBooking(username=[{self.username}], " 157 f"system_id=[{self.system_id}], " 158 f"starttime=[{fmt_time(self.starttime)}], " 159 f"endtime=[{fmt_time(self.endtime)}]" 160 ) 161 if self.session: 162 msg += f", session=[{self.session}]" 163 msg += ")" 164 165 return msg 166 167 @property 168 def desc(self): 169 """Format a "short" description of the object. 170 171 Returns 172 ------- 173 str 174 A string containing `username`, `system_id` and the booking times. 175 """ 176 return ( 177 f"{self.username}@{self.system_id} " 178 f"[{fmt_time(self.starttime)} -- {fmt_time(self.endtime)}]" 179 )
class
PpmsBooking:
11class PpmsBooking: 12 13 """Object representing a booking (reservation) in PPMS. 14 15 Attributes 16 ---------- 17 username : str 18 The user's account / login name the booking is linked to. 19 system_id : int 20 The PPMS system ID to which this booking refers to. 21 starttime : datetime.date 22 The booking's starting time. 23 endtime : datetime.date or NoneType 24 The booking's ending time, can be 'None'. 25 session : str 26 A string referring to a session ID in PPMS, can be empty. 27 """ 28 29 def __init__(self, text, booking_type, system_id): 30 r"""Initialize the booking object. 31 32 Parameters 33 ---------- 34 text : str 35 The response text of a PUMAPI `getbooking` or `nextbooking` request, 36 should consist of three lines: username, time_delta, session. 37 Example: ``pyppms\n42\n12345\n`` 38 booking_type : str 39 Either ``get`` (for a currently running booking) or ``next`` (for 40 the next upcoming booking). 41 system_id : int or int-like 42 The ID of the system the booking refers to. 43 """ 44 valid = ["get", "next"] 45 if booking_type not in valid: 46 raise ValueError( 47 f"Value for 'booking_type' ({booking_type}) not in {valid}!" 48 ) 49 50 try: 51 lines = text.splitlines() 52 starttime = time_rel_to_abs(lines[1]) 53 endtime = None 54 55 if booking_type == "get": 56 endtime = starttime 57 starttime = datetime.now().replace(second=0, microsecond=0) 58 59 self.username = lines[0] 60 self.system_id = int(system_id) 61 self.starttime = starttime 62 self.endtime = endtime 63 self.session = lines[2] 64 except Exception as err: 65 log.error("Parsing booking response failed ({}), text was:\n{}", err, text) 66 raise 67 68 log.trace(str(self)) 69 70 # FIXME: date is of type datetime.datetime, NOT datetime.date !!! 71 @classmethod 72 def from_runningsheet(cls, entry, system_id, username, date): 73 """Alternative constructor using a (parsed) getrunningsheet response. 74 75 Parameters 76 ---------- 77 entry : dict 78 One item of a 'getrunningsheet' response processed by the 79 parse_multiline_response function. 80 system_id : int or int-like 81 The system ID to which this booking refers to. 82 username : str 83 The user's account / login name for PPMS. 84 date : datetime.date 85 The date object of the *DAY* this booking is linked to. Note that 86 the exact start- and end-time of the booking will be taken from the 87 ``entry`` dict above. 88 89 Returns 90 ------- 91 pyppms.booking.PpmsBooking 92 The object constructed with the parsed response. 93 """ 94 try: 95 response = f"{username}\n0\n\n" 96 booking = cls(response, "get", system_id) 97 booking.starttime_fromstr(entry["Start time"], date) 98 booking.endtime_fromstr(entry["End time"], date) 99 except Exception as err: 100 log.error( 101 "Parsing runningsheet entry failed ({}), text was:\n{}", err, entry 102 ) 103 raise 104 105 log.trace(f"Created booking from runningsheet: {booking}") 106 return booking 107 108 def starttime_fromstr(self, time_str, date=None): 109 """Change the starting time and / or day of a booking. 110 111 Parameters 112 ---------- 113 time_str : str 114 The new starting time in format ``%H:%M:%S`` (e.g. ``13:45:00``). 115 date : datetime.date, optional 116 The new starting day, by default ``None`` which will result in the 117 current date to be used. 118 """ 119 if date is None: 120 date = datetime.now() 121 start = date.replace( 122 hour=int(time_str.split(":")[0]), 123 minute=int(time_str.split(":")[1]), 124 second=0, 125 microsecond=0, 126 ) 127 self.starttime = start 128 log.trace("New starttime: {}", self) 129 130 def endtime_fromstr(self, time_str, date=None): 131 """Change the ending time and / or day of a booking. 132 133 Parameters 134 ---------- 135 time_str : str 136 The new ending time in format ``%H:%M:%S`` (e.g. ``13:45:00``). 137 date : datetime.date, optional 138 The new ending day, by default ``None`` which will result in the 139 current date to be used. 140 """ 141 if date is None: 142 date = datetime.now() 143 end = date.replace( 144 hour=int(time_str.split(":")[0]), 145 minute=int(time_str.split(":")[1]), 146 second=0, 147 microsecond=0, 148 ) 149 if end.hour == 0 and end.minute == 0: 150 end = end + timedelta(days=1) 151 log.debug(f"Booking end is midnight, adjust date to {end}") 152 self.endtime = end 153 log.trace("New endtime: {}", self) 154 155 def __str__(self): 156 msg = ( 157 f"PpmsBooking(username=[{self.username}], " 158 f"system_id=[{self.system_id}], " 159 f"starttime=[{fmt_time(self.starttime)}], " 160 f"endtime=[{fmt_time(self.endtime)}]" 161 ) 162 if self.session: 163 msg += f", session=[{self.session}]" 164 msg += ")" 165 166 return msg 167 168 @property 169 def desc(self): 170 """Format a "short" description of the object. 171 172 Returns 173 ------- 174 str 175 A string containing `username`, `system_id` and the booking times. 176 """ 177 return ( 178 f"{self.username}@{self.system_id} " 179 f"[{fmt_time(self.starttime)} -- {fmt_time(self.endtime)}]" 180 )
Object representing a booking (reservation) in PPMS.
Attributes
- username (str): The user's account / login name the booking is linked to.
- system_id (int): The PPMS system ID to which this booking refers to.
- starttime (datetime.date): The booking's starting time.
- endtime (datetime.date or NoneType): The booking's ending time, can be 'None'.
- session (str): A string referring to a session ID in PPMS, can be empty.
PpmsBooking(text, booking_type, system_id)
29 def __init__(self, text, booking_type, system_id): 30 r"""Initialize the booking object. 31 32 Parameters 33 ---------- 34 text : str 35 The response text of a PUMAPI `getbooking` or `nextbooking` request, 36 should consist of three lines: username, time_delta, session. 37 Example: ``pyppms\n42\n12345\n`` 38 booking_type : str 39 Either ``get`` (for a currently running booking) or ``next`` (for 40 the next upcoming booking). 41 system_id : int or int-like 42 The ID of the system the booking refers to. 43 """ 44 valid = ["get", "next"] 45 if booking_type not in valid: 46 raise ValueError( 47 f"Value for 'booking_type' ({booking_type}) not in {valid}!" 48 ) 49 50 try: 51 lines = text.splitlines() 52 starttime = time_rel_to_abs(lines[1]) 53 endtime = None 54 55 if booking_type == "get": 56 endtime = starttime 57 starttime = datetime.now().replace(second=0, microsecond=0) 58 59 self.username = lines[0] 60 self.system_id = int(system_id) 61 self.starttime = starttime 62 self.endtime = endtime 63 self.session = lines[2] 64 except Exception as err: 65 log.error("Parsing booking response failed ({}), text was:\n{}", err, text) 66 raise 67 68 log.trace(str(self))
Initialize the booking object.
Parameters
- text (str):
The response text of a PUMAPI
getbooking
ornextbooking
request, should consist of three lines: username, time_delta, session. Example:pyppms\n42\n12345\n
- booking_type (str):
Either
get
(for a currently running booking) ornext
(for the next upcoming booking). - system_id (int or int-like): The ID of the system the booking refers to.
@classmethod
def
from_runningsheet(cls, entry, system_id, username, date):
71 @classmethod 72 def from_runningsheet(cls, entry, system_id, username, date): 73 """Alternative constructor using a (parsed) getrunningsheet response. 74 75 Parameters 76 ---------- 77 entry : dict 78 One item of a 'getrunningsheet' response processed by the 79 parse_multiline_response function. 80 system_id : int or int-like 81 The system ID to which this booking refers to. 82 username : str 83 The user's account / login name for PPMS. 84 date : datetime.date 85 The date object of the *DAY* this booking is linked to. Note that 86 the exact start- and end-time of the booking will be taken from the 87 ``entry`` dict above. 88 89 Returns 90 ------- 91 pyppms.booking.PpmsBooking 92 The object constructed with the parsed response. 93 """ 94 try: 95 response = f"{username}\n0\n\n" 96 booking = cls(response, "get", system_id) 97 booking.starttime_fromstr(entry["Start time"], date) 98 booking.endtime_fromstr(entry["End time"], date) 99 except Exception as err: 100 log.error( 101 "Parsing runningsheet entry failed ({}), text was:\n{}", err, entry 102 ) 103 raise 104 105 log.trace(f"Created booking from runningsheet: {booking}") 106 return booking
Alternative constructor using a (parsed) getrunningsheet response.
Parameters
- entry (dict): One item of a 'getrunningsheet' response processed by the parse_multiline_response function.
- system_id (int or int-like): The system ID to which this booking refers to.
- username (str): The user's account / login name for PPMS.
- date (datetime.date):
The date object of the DAY this booking is linked to. Note that
the exact start- and end-time of the booking will be taken from the
entry
dict above.
Returns
- pyppms.booking.PpmsBooking: The object constructed with the parsed response.
def
starttime_fromstr(self, time_str, date=None):
108 def starttime_fromstr(self, time_str, date=None): 109 """Change the starting time and / or day of a booking. 110 111 Parameters 112 ---------- 113 time_str : str 114 The new starting time in format ``%H:%M:%S`` (e.g. ``13:45:00``). 115 date : datetime.date, optional 116 The new starting day, by default ``None`` which will result in the 117 current date to be used. 118 """ 119 if date is None: 120 date = datetime.now() 121 start = date.replace( 122 hour=int(time_str.split(":")[0]), 123 minute=int(time_str.split(":")[1]), 124 second=0, 125 microsecond=0, 126 ) 127 self.starttime = start 128 log.trace("New starttime: {}", self)
Change the starting time and / or day of a booking.
Parameters
- time_str (str):
The new starting time in format
%H:%M:%S
(e.g.13:45:00
). - date (datetime.date, optional):
The new starting day, by default
None
which will result in the current date to be used.
def
endtime_fromstr(self, time_str, date=None):
130 def endtime_fromstr(self, time_str, date=None): 131 """Change the ending time and / or day of a booking. 132 133 Parameters 134 ---------- 135 time_str : str 136 The new ending time in format ``%H:%M:%S`` (e.g. ``13:45:00``). 137 date : datetime.date, optional 138 The new ending day, by default ``None`` which will result in the 139 current date to be used. 140 """ 141 if date is None: 142 date = datetime.now() 143 end = date.replace( 144 hour=int(time_str.split(":")[0]), 145 minute=int(time_str.split(":")[1]), 146 second=0, 147 microsecond=0, 148 ) 149 if end.hour == 0 and end.minute == 0: 150 end = end + timedelta(days=1) 151 log.debug(f"Booking end is midnight, adjust date to {end}") 152 self.endtime = end 153 log.trace("New endtime: {}", self)
Change the ending time and / or day of a booking.
Parameters
- time_str (str):
The new ending time in format
%H:%M:%S
(e.g.13:45:00
). - date (datetime.date, optional):
The new ending day, by default
None
which will result in the current date to be used.