Skip to content

Commit 0ce67a9

Browse files
authored
Merge pull request #420 from ExaWorks/parse_walltime_function
Move the walltime parsing routine in the serialiation module to
2 parents 3109e7c + 18fe874 commit 0ce67a9

File tree

2 files changed

+51
-36
lines changed

2 files changed

+51
-36
lines changed

src/psij/job_attributes.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
import re
12
from datetime import timedelta
23
from typing import Optional, Dict
34

45
from typeguard import check_argument_types
56

67

8+
_WALLTIME_FMT_ERROR = 'Unknown walltime format: %s. Accepted formats are hh:mm:ss, ' \
9+
'hh:mm, mm, or n\\s*[h|m|s].'
10+
11+
712
class JobAttributes(object):
813
"""A class containing ancillary job information that describes how a job is to be run."""
914

@@ -92,3 +97,48 @@ def __eq__(self, o: object) -> bool:
9297
return False
9398

9499
return True
100+
101+
@staticmethod
102+
def parse_walltime(walltime: str) -> timedelta:
103+
r"""
104+
Parses a walltime string into a :class:`~datetime.timedelta`.
105+
106+
The accepted walltime strings formats are:
107+
* hh:mm:ss
108+
* hh:mm
109+
* mm
110+
* n\s*[y|M|d|h|m\s]
111+
112+
Parameters
113+
----------
114+
walltime
115+
A string in one of the above formats representing a time duration
116+
117+
Returns
118+
-------
119+
A :class:`~datetime.timedelta` representing the same time duration as the ``walltime``
120+
parameter.
121+
"""
122+
if ':' in walltime:
123+
parts = walltime.split(':')
124+
seconds = 0
125+
if len(parts) == 3:
126+
seconds = int(parts[2])
127+
if len(parts) <= 3:
128+
return timedelta(hours=int(parts[0]), minutes=int(parts[1]), seconds=seconds)
129+
else:
130+
raise ValueError(_WALLTIME_FMT_ERROR % walltime)
131+
if walltime.isdigit():
132+
return timedelta(minutes=int(walltime))
133+
m = re.search(r'(\d+)\s*([hms])', walltime)
134+
if m:
135+
digits = m.group(1)
136+
unit = m.group(2)
137+
val = int(digits)
138+
if unit == 'h':
139+
return timedelta(hours=val)
140+
elif unit == 'm':
141+
return timedelta(minutes=val)
142+
elif unit == 's':
143+
return timedelta(seconds=val)
144+
raise ValueError(_WALLTIME_FMT_ERROR % walltime)

src/psij/serialize.py

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import inspect
22
import json
3-
import re
43
import typing
54
from abc import ABC, abstractmethod
65
from datetime import timedelta
@@ -245,7 +244,7 @@ def _to_object(self, s: object, t: object) -> object:
245244
return s
246245
if issubclass(t, timedelta):
247246
assert isinstance(s, str)
248-
return self._to_timedelta(s)
247+
return JobAttributes.parse_walltime(s)
249248
else:
250249
if t == Union[str, Path] or t == Optional[Union[str, Path]]:
251250
assert isinstance(s, str)
@@ -273,40 +272,6 @@ def _to_dict(self, d: Dict[str, object]) -> Dict[str, object]:
273272
def _to_list(self, lst: List[object]) -> List[object]:
274273
return [self._to_object(v, type(v)) for v in lst]
275274

276-
_TIMEDELTA_FMT_ERROR = 'Unknown time interval format: %s. Accepted formats are hh:mm:ss, ' \
277-
'hh:mm, mm, or n\\s*[h|m|s].'
278-
279-
def _to_timedelta(self, s: str) -> timedelta:
280-
# we accept multiple formats here:
281-
# hh:mm:ss
282-
# hh:mm
283-
# mm
284-
# n\s*[y|M|d|h|m\s]
285-
286-
if ':' in s:
287-
parts = s.split(':')
288-
seconds = 0
289-
if len(parts) == 3:
290-
seconds = int(parts[2])
291-
if len(parts) <= 3:
292-
return timedelta(hours=int(parts[0]), minutes=int(parts[1]), seconds=seconds)
293-
else:
294-
raise ValueError(Serializer._TIMEDELTA_FMT_ERROR % s)
295-
if s.isdigit():
296-
return timedelta(minutes=int(s))
297-
m = re.search(r'(\d+)\s*([hms])', s)
298-
if m:
299-
digits = m.group(1)
300-
unit = m.group(2)
301-
val = int(digits)
302-
if unit == 'h':
303-
return timedelta(hours=val)
304-
elif unit == 'm':
305-
return timedelta(minutes=val)
306-
elif unit == 's':
307-
return timedelta(seconds=val)
308-
raise ValueError(Serializer._TIMEDELTA_FMT_ERROR % s)
309-
310275

311276
class JSONSerializer(Serializer):
312277
"""A JSON serializer."""

0 commit comments

Comments
 (0)