Splitted up utils
This commit is contained in:
parent
99afe042cd
commit
74a4129afd
87
nxy/utils.py
87
nxy/utils.py
@ -1,87 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from pprint import pprint
|
||||
|
||||
# @formatter:off
|
||||
COLORS = dict(
|
||||
white=0, # white
|
||||
black=1, # black
|
||||
blue=2, # blue (navy)
|
||||
green=3, # green
|
||||
red=4, # red
|
||||
maroon=5, # brown (maroon)
|
||||
purple=6, # purple
|
||||
orange=7, # orange (olive)
|
||||
yellow=8, # yellow
|
||||
ltgreen=9, # light green (lime)
|
||||
teal=10, # teal (a green/blue cyan)
|
||||
ltcyan=11, # light cyan (cyan / aqua)
|
||||
ltblue=12, # light blue (royal)
|
||||
pink=13, # pink (light purple / fuchsia)
|
||||
grey=14, # grey
|
||||
ltgrey=15, # light grey (silver)
|
||||
)
|
||||
|
||||
FORMATTING = dict(
|
||||
bold='\x02', # bold
|
||||
color='\x03', # colored text
|
||||
italic='\x1D', # italic text
|
||||
underline='\x1F', # underlined text
|
||||
swap='\x16', # swap bg and fg colors ("reverse video")
|
||||
reset='\x0F', # reset all formatting
|
||||
**COLORS
|
||||
)
|
||||
# @formatter:on
|
||||
|
||||
# Debug helper
|
||||
pp = pprint
|
||||
|
||||
|
||||
def fmt(__text: str, **kwargs) -> str:
|
||||
"""Formats a str with `kwargs` and `FORMATTING`."""
|
||||
return __text.format(**kwargs, **FORMATTING)
|
||||
|
||||
|
||||
def date_from_iso(date: str) -> datetime:
|
||||
return datetime.strptime(date, '%Y-%m-%dT%H:%M:%S.%fZ')
|
||||
|
||||
|
||||
def time_delta(text: str) -> timedelta:
|
||||
match = re.match(r'(\d+)(s|m|h|mon|w|y)', text)
|
||||
if match:
|
||||
num, unit = match.groups()
|
||||
num = int(num)
|
||||
if unit == 's':
|
||||
unit = 'seconds'
|
||||
elif unit == 'm':
|
||||
unit = 'minutes'
|
||||
elif unit == 'h':
|
||||
unit = 'hours'
|
||||
elif unit == 'd':
|
||||
unit = 'days'
|
||||
elif unit == 'w':
|
||||
unit = 'weeks'
|
||||
elif unit == 'mon':
|
||||
unit = 'weeks'
|
||||
num *= 4
|
||||
elif unit == 'y':
|
||||
unit = 'weeks'
|
||||
num *= 52
|
||||
return timedelta(**{unit: num})
|
||||
|
||||
|
||||
def parse_int(val: str) -> tuple:
|
||||
try:
|
||||
val = int(val)
|
||||
if val is not 0:
|
||||
if val < 1:
|
||||
order, op = 'desc', '<='
|
||||
val *= -1
|
||||
else:
|
||||
order, op = 'asc', '>='
|
||||
val -= 1
|
||||
return val, order, op
|
||||
except ValueError:
|
||||
pass
|
20
nxy/utils/__init__.py
Normal file
20
nxy/utils/__init__.py
Normal file
@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from pprint import pprint as pp
|
||||
|
||||
from .date import date_from_iso, time_delta, time_since
|
||||
from .formatting import fmt, FORMATTING
|
||||
from .misc import parse_int
|
||||
|
||||
__all__ = (
|
||||
# pprint alias
|
||||
'pp',
|
||||
# date and time stuff
|
||||
'date_from_iso',
|
||||
'time_delta',
|
||||
'time_since',
|
||||
# formatting
|
||||
'fmt',
|
||||
'FORMATTING',
|
||||
# misc
|
||||
'parse_int'
|
||||
)
|
84
nxy/utils/date.py
Normal file
84
nxy/utils/date.py
Normal file
@ -0,0 +1,84 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
|
||||
def date_from_iso(date: str) -> datetime:
|
||||
return datetime.strptime(date, '%Y-%m-%dT%H:%M:%S.%fZ')
|
||||
|
||||
|
||||
def time_delta(text: str) -> timedelta:
|
||||
match = re.match(r'(\d+)(s|m|h|mon|w|y)', text)
|
||||
if match:
|
||||
num, unit = match.groups()
|
||||
num = int(num)
|
||||
if unit == 's':
|
||||
unit = 'seconds'
|
||||
elif unit == 'm':
|
||||
unit = 'minutes'
|
||||
elif unit == 'h':
|
||||
unit = 'hours'
|
||||
elif unit == 'd':
|
||||
unit = 'days'
|
||||
elif unit == 'w':
|
||||
unit = 'weeks'
|
||||
elif unit == 'mon':
|
||||
unit = 'weeks'
|
||||
num *= 4
|
||||
elif unit == 'y':
|
||||
unit = 'weeks'
|
||||
num *= 52
|
||||
return timedelta(**{unit: num})
|
||||
|
||||
|
||||
def time_since(date: datetime, now: datetime = None):
|
||||
"""
|
||||
Takes two datetime objects and returns the time between d and now
|
||||
as a nicely formatted string, e.g. "10 minutes". If d occurs after now,
|
||||
then "0 minutes" is returned.
|
||||
|
||||
Units used are years, months, weeks, days, hours, and minutes.
|
||||
Seconds and microseconds are ignored. Up to two adjacent units will be
|
||||
displayed. For example, "2 weeks, 3 days" and "1 year, 3 months" are
|
||||
possible outputs, but "2 weeks, 3 hours" and "1 year, 5 days" are not.
|
||||
|
||||
Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
|
||||
"""
|
||||
chunks = (
|
||||
(60 * 60 * 24 * 365, ('year', 'years')),
|
||||
(60 * 60 * 24 * 30, ('month', 'months')),
|
||||
(60 * 60 * 24 * 7, ('week', 'weeks')),
|
||||
(60 * 60 * 24, ('day', 'days')),
|
||||
(60 * 60, ('hour', 'hours')),
|
||||
(60, ('minute', 'minutes'))
|
||||
)
|
||||
|
||||
if not now:
|
||||
now = datetime.now()
|
||||
|
||||
# ignore microsecond part of 'd' since we removed it from 'now'
|
||||
delta = now - (date - timedelta(0, 0, date.microsecond))
|
||||
since = delta.days * 24 * 60 * 60 + delta.seconds
|
||||
if since <= 0:
|
||||
# d is in the future compared to now, stop processing.
|
||||
return u'0 ' + 'minutes'
|
||||
|
||||
name = None
|
||||
count = None
|
||||
seconds = None
|
||||
|
||||
for i, (seconds, name) in enumerate(chunks):
|
||||
count = since // seconds
|
||||
if count != 0:
|
||||
break
|
||||
|
||||
s = '%(number)d %(type)s' % {'number': count, 'type': name[count != 1]}
|
||||
|
||||
if i + 1 < len(chunks):
|
||||
# Now get the second item
|
||||
seconds2, name2 = chunks[i + 1]
|
||||
count2 = (since - (seconds * count)) // seconds2
|
||||
if count2 != 0:
|
||||
s += ', %d %s' % (count2, name2[count2 != 1])
|
||||
return s
|
38
nxy/utils/formatting.py
Normal file
38
nxy/utils/formatting.py
Normal file
@ -0,0 +1,38 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# @formatter:off
|
||||
COLORS = {
|
||||
'white': 0, # white
|
||||
'black': 1, # black
|
||||
'blue': 2, # blue (navy)
|
||||
'green': 3, # green
|
||||
'red': 4, # red
|
||||
'maroon': 5, # brown (maroon)
|
||||
'purple': 6, # purple
|
||||
'orange': 7, # orange (olive)
|
||||
'yellow': 8, # yellow
|
||||
'ltgreen': 9, # light green (lime)
|
||||
'teal': 10, # teal (a green/blue cyan)
|
||||
'ltcyan': 11, # light cyan (cyan / aqua)
|
||||
'ltblue': 12, # light blue (royal)
|
||||
'pink': 13, # pink (light purple / fuchsia)
|
||||
'grey': 14, # grey
|
||||
'ltgrey': 15, # light grey (silver)
|
||||
}
|
||||
|
||||
FORMATTING = {
|
||||
'bold': '\x02', # bold
|
||||
'color': '\x03', # colored text
|
||||
'italic': '\x1D', # italic text
|
||||
'underline': '\x1F', # underlined text
|
||||
'swap': '\x16', # swap bg and fg colors ("reverse video")
|
||||
'reset': '\x0F', # reset all formatting
|
||||
}
|
||||
|
||||
FORMATTING.update(COLORS)
|
||||
# @formatter:on
|
||||
|
||||
|
||||
def fmt(__text: str, **kwargs) -> str:
|
||||
"""Formats a str with `kwargs` and `FORMATTING`."""
|
||||
return __text.format(**kwargs, **FORMATTING)
|
17
nxy/utils/misc.py
Normal file
17
nxy/utils/misc.py
Normal file
@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
def parse_int(val: str, select: bool = True) -> tuple:
|
||||
try:
|
||||
val = int(val)
|
||||
if val is not 0:
|
||||
if val < 1:
|
||||
order, op = 'desc', '<='
|
||||
val *= -1
|
||||
else:
|
||||
order, op = 'asc', '>='
|
||||
if select:
|
||||
val -= 1
|
||||
return val, order, op
|
||||
except ValueError:
|
||||
pass
|
Loading…
Reference in New Issue
Block a user