use the `isodate` package to mange iso8601 durations
5 files changed, 10 insertions(+), 29 deletions(-)

M rework/api.py
M rework/helper.py
M rework/monitor.py
M setup.py
M tests/test_monitor.py
M rework/api.py +2 -2
@@ 9,9 9,9 @@ from pathlib import Path
 from sqlalchemy.exc import IntegrityError
 from sqlhelp import select, insert
 from icron import croniter
+import isodate
 
 from rework.helper import (
-    delta_isoformat,
     filterio,
     host,
     InputEncoder,

          
@@ 268,7 268,7 @@ def freeze_operations(engine, domain=Non
         if domain is not None and domain != fdomain:
             continue
         if timeout is not None:
-            timeout = delta_isoformat(timeout)
+            timeout = isodate.duration_isoformat(timeout)
         funcmod = func.__module__
         module = sys.modules[funcmod]
         modpath = module.__file__

          
M rework/helper.py +1 -20
@@ 5,9 5,8 @@ from threading import Thread
 import socket
 import time
 import logging
-from datetime import datetime, timedelta
+from datetime import datetime
 from pathlib import Path
-import re
 import json
 import struct
 import tzlocal

          
@@ 215,24 214,6 @@ def kill_process_tree(pid, timeout=3):
     return kill(pid)
 
 
-# timedelta (de)serialisation
-
-def delta_isoformat(td):
-    return f'P{td.days}DT0H0M{td.seconds}S'
-
-
-_DELTA = re.compile('P(.*)DT(.*)H(.*)M(.*)S')
-def parse_delta(td):
-    match = _DELTA.match(td)
-    if not match:
-        raise Exception(f'unparseable time delta `{td}`')
-    days, hours, minutes, seconds = match.groups()
-    return timedelta(
-        days=int(days), hours=int(hours),
-        minutes=int(minutes), seconds=int(seconds)
-    )
-
-
 # configuration lookup
 
 def get_cfg_path():

          
M rework/monitor.py +2 -2
@@ 11,6 11,7 @@ import traceback as tb
 from pathlib import Path
 import sys
 
+import isodate
 import tzlocal
 import pytz
 import psutil

          
@@ 22,7 23,6 @@ from rework.helper import (
     kill_process_tree,
     memory_usage,
     iter_stamps_from_cronrules,
-    parse_delta,
     partition,
     schedule_plan,
     setuplogger,

          
@@ 390,7 390,7 @@ class Monitor:
         with self.engine.begin() as cn:
             for tid, start_time, timeout in cn.execute(sql).fetchall():
                 start_time = start_time.astimezone(pytz.utc)
-                delta = parse_delta(timeout)
+                delta = isodate.parse_duration(timeout)
                 now = utcnow()
                 if (now - start_time) > delta:
                     Task.byid(self.engine, tid).abort('timeout')

          
M setup.py +1 -0
@@ 25,6 25,7 @@ setup(name='rework',
           'psycopg2-binary',
           'click',
           'tzlocal',
+          'isodate',
           'inireader',
           'python-icron',
           'pystuck',

          
M tests/test_monitor.py +4 -5
@@ 5,6 5,7 @@ import time
 
 import pytest
 from sqlhelp import insert, update
+import isodate
 
 from rework import api
 from rework.monitor import Monitor

          
@@ 12,11 13,9 @@ from rework.task import Task, TimeOut
 from rework.worker import Worker
 from rework.helper import (
     cpu_usage,
-    delta_isoformat,
     guard,
     kill_process_tree,
     memory_usage,
-    parse_delta,
     wait_true
 )
 from rework.testutils import scrub, workers

          
@@ 626,9 625,9 @@ def test_timeout(engine, cleanup):
     d1 = datetime(2018, 1, 1)
     d2 = datetime(2018, 3, 3, 12, 45, 30)
     delta = d2 - d1
-    iso = delta_isoformat(delta)
-    assert iso == 'P61DT0H0M45930S'
-    delta_out = parse_delta(iso)
+    iso = isodate.duration_isoformat(delta)
+    assert iso == 'P61DT12H45M30S'
+    delta_out = isodate.parse_duration(iso)
     assert delta == delta_out
 
     with workers(engine, numworkers=3) as mon: