Add my existing implementation
This commit is contained in:
78
ping.py
Normal file
78
ping.py
Normal file
@@ -0,0 +1,78 @@
|
||||
import re
|
||||
import datetime
|
||||
from dataclasses import dataclass
|
||||
from typing import List
|
||||
|
||||
|
||||
@dataclass
|
||||
class Ping:
|
||||
"""
|
||||
A ping is a single line in the log file consisting of a UNIX time stamp,
|
||||
followed by tags (where each individual string surrounded by spaces is a
|
||||
tag), followed by optional comments between square brackets or parentheses.
|
||||
The original Perl implementation puts a human readable representation of
|
||||
the UNIX time stamp into square brackets. Here are two example pings:
|
||||
|
||||
1601557948 morning_pages [2020.10.01 09:12:28 THU]
|
||||
1601560369 work_call another_tag [2020.10.01 09:52:49 THU]
|
||||
"""
|
||||
time: int # UNIX time stamp
|
||||
tags: List[str] # each separate word is a tag
|
||||
comments: List[str] # each string between [] or () is a comment
|
||||
line: str = "" # the whole line as found in the log file
|
||||
|
||||
r_time = re.compile("^\s*\d{9,11}")
|
||||
r_spaces = re.compile("\s+")
|
||||
r_comment_parens = re.compile("\(([^\)]*)\)")
|
||||
r_comment_square = re.compile("\[([^\]]*)\]")
|
||||
|
||||
def line_to_ping(line: str):
|
||||
"""
|
||||
Parses a string into a Ping object. Raises Exception on failure.
|
||||
|
||||
>>> line_to_ping(" 1601557948 t (c)")
|
||||
Ping(time=1601557948, tags=['t'], comments=['c'], line=' 1601557948 t (c)')
|
||||
"""
|
||||
time = int(Ping.r_time.match(line).group())
|
||||
tags = Ping.get_tags(line)
|
||||
comments = Ping.r_comment_parens.findall(line) + \
|
||||
Ping.r_comment_square.findall(line)
|
||||
return Ping(time, tags, comments, line)
|
||||
|
||||
def get_tags(line):
|
||||
"""Extracts the tags from a tag line."""
|
||||
line = Ping.r_time.sub("", line)
|
||||
line = Ping.r_comment_parens.sub("", line)
|
||||
line = Ping.r_comment_square.sub("", line)
|
||||
line = Ping.r_spaces.sub(" ", line)
|
||||
return line.split()
|
||||
|
||||
def ping_to_line(ping, annotate_time=False, line_length=79) -> str:
|
||||
tags = " ".join([t.strip() for t in ping.tags])
|
||||
comments = " ".join(["[" + c.strip() + "]" for c in ping.comments])
|
||||
line = "{} {} {}".format(ping.time, tags, comments)
|
||||
if annotate_time:
|
||||
line = Ping.add_time_annotation(ping.time, line, line_length)
|
||||
return line
|
||||
|
||||
def add_time_annotation(time: int, line: str, line_length: int) -> str:
|
||||
"""Appends human readable date/time in square brackets to line."""
|
||||
remaining_length = line_length - len(line)
|
||||
if remaining_length > 24:
|
||||
strf = " [%Y.%m.%d %H:%M:%S %a]"
|
||||
elif remaining_length > 18:
|
||||
strf = " [%m.%d %H:%M:%S %a]"
|
||||
elif remaining_length > 15:
|
||||
strf = " [%d %H:%M:%S %a]"
|
||||
elif remaining_length > 12:
|
||||
strf = " [%H:%M:%S %a]"
|
||||
elif remaining_length > 9:
|
||||
strf = " [%H:%M %a]"
|
||||
elif remaining_length > 5:
|
||||
strf = " [%H:%M]"
|
||||
else:
|
||||
strf = " [%M]"
|
||||
time_comment = datetime.datetime.fromtimestamp(time).strftime(strf)
|
||||
remaining_length -= len(time_comment)
|
||||
line += " " * remaining_length + time_comment
|
||||
return line
|
||||
Reference in New Issue
Block a user