Skip to content

Commit b15e27c

Browse files
committed
Merge pull request #587 from FedericoCeratto/drop-timeago
2 parents 3a4795d + 267923f commit b15e27c

4 files changed

Lines changed: 51 additions & 9 deletions

File tree

meshtastic/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def onConnection(interface, topic=pub.AUTO_TOPIC): # called when we (re)connect
7676

7777
import google.protobuf.json_format
7878
import serial # type: ignore[import-untyped]
79-
import timeago # type: ignore[import-untyped]
79+
from dotmap import DotMap # type: ignore[import-untyped]
8080
from google.protobuf.json_format import MessageToJson
8181
from pubsub import pub # type: ignore[import-untyped]
8282
from tabulate import tabulate

meshtastic/mesh_interface.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
from typing import Any, Callable, Dict, List, Optional, Union
1515

1616
import google.protobuf.json_format
17-
import timeago # type: ignore[import-untyped]
1817
from pubsub import pub # type: ignore[import-untyped]
1918
from tabulate import tabulate
2019

@@ -42,6 +41,29 @@
4241
)
4342

4443

44+
def _timeago(delta_secs: int) -> str:
45+
"""Convert a number of seconds in the past into a short, friendly string
46+
e.g. "now", "30 sec ago", "1 hour ago"
47+
Zero or negative intervals simply return "now"
48+
"""
49+
intervals = (
50+
("year", 60 * 60 * 24 * 365),
51+
("month", 60 * 60 * 24 * 30),
52+
("day", 60 * 60 * 24),
53+
("hour", 60 * 60),
54+
("min", 60),
55+
("sec", 1),
56+
)
57+
for name, interval_duration in intervals:
58+
if delta_secs < interval_duration:
59+
continue
60+
x = delta_secs // interval_duration
61+
plur = "s" if x > 1 else ""
62+
return f"{x} {name}{plur} ago"
63+
64+
return "now"
65+
66+
4567
class MeshInterface: # pylint: disable=R0902
4668
"""Interface class for meshtastic devices
4769
@@ -158,11 +180,13 @@ def getLH(ts) -> Optional[str]:
158180

159181
def getTimeAgo(ts) -> Optional[str]:
160182
"""Format how long ago have we heard from this node (aka timeago)."""
161-
return (
162-
timeago.format(datetime.fromtimestamp(ts), datetime.now())
163-
if ts
164-
else None
165-
)
183+
if ts is None:
184+
return None
185+
delta = datetime.now() - datetime.fromtimestamp(ts)
186+
delta_secs = int(delta.total_seconds())
187+
if delta_secs < 0:
188+
return None # not handling a timestamp from the future
189+
return _timeago(delta_secs)
166190

167191
rows: List[Dict[str, Any]] = []
168192
if self.nodesByNum:

meshtastic/tests/test_mesh_interface.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
from unittest.mock import MagicMock, patch
66

77
import pytest
8+
from hypothesis import given, strategies as st
89

910
from .. import mesh_pb2, config_pb2, BROADCAST_ADDR, LOCAL_ADDR
10-
from ..mesh_interface import MeshInterface
11+
from ..mesh_interface import MeshInterface, _timeago
1112
from ..node import Node
1213

1314
# TODO
@@ -684,3 +685,21 @@ def test_waitConnected_isConnected_timeout(capsys):
684685
out, err = capsys.readouterr()
685686
assert re.search(r"warn about something", err, re.MULTILINE)
686687
assert out == ""
688+
689+
690+
@pytest.mark.unit
691+
def test_timeago():
692+
"""Test that the _timeago function returns sane values"""
693+
assert _timeago(0) == "now"
694+
assert _timeago(1) == "1 sec ago"
695+
assert _timeago(15) == "15 secs ago"
696+
assert _timeago(333) == "5 mins ago"
697+
assert _timeago(99999) == "1 day ago"
698+
assert _timeago(9999999) == "3 months ago"
699+
assert _timeago(-999) == "now"
700+
701+
@given(seconds=st.integers())
702+
def test_timeago_fuzz(seconds):
703+
"""Fuzz _timeago to ensure it works with any integer"""
704+
val = _timeago(seconds)
705+
assert re.match(r"(now|\d+ (secs?|mins?|hours?|days?|months?|years?))", val)

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
"dotmap>=1.3.14",
4141
"pyqrcode>=1.2.1",
4242
"tabulate>=0.8.9",
43-
"timeago>=1.0.15",
4443
"pyyaml",
4544
"bleak>=0.21.1",
4645
"packaging",

0 commit comments

Comments
 (0)