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 or nextbooking 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) or next (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
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.
desc

Format a "short" description of the object.

Returns
  • str: A string containing username, system_id and the booking times.