Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion dit/dit.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ def load_plugin(plugin_name):
FILTER_OPTIONS = [
"--verbose",
"--id-only",
"--name-only",
"--sum",
"--from",
"--to",
Expand Down Expand Up @@ -1173,6 +1174,8 @@ def status(self, argv):
options['verbose'] = True
elif opt in ["--id-only", "-i"]:
options['id-only'] = True
elif opt in ["--name-only", "-i"]:
options['name-only'] = True
elif opt in ["--sum", "-s"]:
options["sum"] = True
elif opt in ["--from"]:
Expand Down Expand Up @@ -1214,6 +1217,7 @@ def list(self, argv):
@command("o", LIST_OPTIONS + ["--output", "--format"], SELECT_FORWARD, True)
def export(self, argv, listing=False):
all = False
daily = False
output_file = None
output_format = None

Expand All @@ -1230,6 +1234,8 @@ def export(self, argv, listing=False):
options['verbose'] = True
elif opt in ["--id-only", "-i"]:
options['id-only'] = True
elif opt in ["--name-only", "-i"]:
options['name-only'] = True
elif opt in ["--sum", "-s"]:
options["sum"] = True
elif opt in ["--from"]:
Expand All @@ -1240,6 +1246,8 @@ def export(self, argv, listing=False):
filters["where"] = [argv.pop(0), re.compile(argv.pop(0))]
elif opt in ["--all", "-a"]:
all = True
elif opt in ["--daily", "-d"]:
daily = True
elif opt in ["--concluded", "-c"]:
options['concluded'] = True
elif opt in ["--compact", "-z"]:
Expand Down Expand Up @@ -1271,7 +1279,10 @@ def export(self, argv, listing=False):

output_format = output_format or 'dit'

self.exporter = load_plugin("%s_exporter" % output_format)
if daily:
self.exporter = load_plugin("%s_exporter_daily" % output_format)
else:
self.exporter = load_plugin("%s_exporter" % output_format)
self.exporter.setup(exporter_stdout, options)
self.exporter.begin()

Expand Down
5 changes: 5 additions & 0 deletions dit/dit_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
_options = {
'verbose': False,
'id-only': False,
'name-only': False,
'concluded': False,
'statussing': False,
'compact-header': False,
Expand Down Expand Up @@ -125,6 +126,7 @@ def task(group, group_id, subgroup, subgroup_id, task, task_id, data):
# options
verbose = _options['verbose']
id_only = _options['id-only']
name_only = _options['name-only']
concluded = _options['concluded']
statussing = _options['statussing']
filters = _options['filters']
Expand All @@ -141,6 +143,9 @@ def task(group, group_id, subgroup, subgroup_id, task, task_id, data):
if id_only:
_write('%s/%s/%s' % (group_id, subgroup_id, task_id))
return
elif name_only:
_write(names_to_string(group, subgroup, task))
return

if _options.get('compact-header'):
_write(_ca('[%s/%s/%s]' % (group_id, subgroup_id, task_id)) + ' ' +
Expand Down
150 changes: 150 additions & 0 deletions dit/dit_exporter_daily.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# -*- coding: utf-8 -*-

import io
import sys
import subprocess
from datetime import timedelta

from .dit import names_to_string
from .utils import (
apply_filters,
convert_datetimes,
dt2str,
now,
)

_0_seconds = timedelta(0)

_file = None
_isatty = False
_pager = None
_days = {}
_options = {
'filters': {}
}
_now = None


# ===========================================
# Colors


def _ca(string):
if _isatty:
return '\033[2;34m' + string + '\033[0m'
return string


def _cc(string):
if _isatty:
return '\033[2;31m' + string + '\033[0m'
return string


def _cd(string):
if _isatty:
return '\033[2;32m' + string + '\033[0m'
return string


def _ce(string):
if _isatty:
return '\033[0;36m' + string + '\033[0m'
return string


# ===========================================
# Write helpers


def _write(string=''):
_file.write('%s\n' % string)


# ===========================================
# Logic helpers

def _lazy_now():
global _now
if _now is None:
_now = now()
return _now


def _calc_delta(log_entry):
if log_entry[1] is None:
return _lazy_now() - log_entry[0]
return log_entry[1] - log_entry[0]


# ===========================================
# API


def setup(file, options):
global _file
global _options
global _isatty
_file = file
_isatty = file.isatty()
_options.update(options)


def begin():
if _isatty:
global _pager
global _file
_pager = subprocess.Popen(['less', '-F', '-R', '-S', '-X', '-K'],
stdin=subprocess.PIPE, stdout=sys.stdout)
_file = io.TextIOWrapper(_pager.stdin, 'UTF-8')


def end():
for d, logs in sorted(_days.items(), reverse=True):
total = sum(map(_calc_delta, logs), _0_seconds)

_write('%s (%s)' % (_ca(d.strftime(r'%A %x')), _ce('%s' % total)))
for lin, lout, name, title in sorted(logs, reverse=True):
string = ' - %s' % dt2str(lin)
lout_s = dt2str(lout) if lout else 'ongoing'
string += ' ~ %s (%s)' % (lout_s, _ce('%s' % _calc_delta([lin, lout])))
string += ' : [%s] %s' % (_cc(name), _cd(title))
_write(string)

if _isatty:
_file.close()
_pager.wait()


def group(group, group_id):
pass


def subgroup(group, group_id, subgroup, subgroup_id):
pass


def task(group, group_id, subgroup, subgroup_id, task, task_id, data):
filters = _options['filters']

data = apply_filters(convert_datetimes(data), filters)
if not data:
return

logbook = data.get('logbook', [])

if not logbook:
return

for log in logbook:
d = log['in'].date()

if d not in _days:
_days[d] = []

_days[d].append((
log['in'],
log['out'],
names_to_string(group, subgroup, task),
data.get('title'),
))
2 changes: 1 addition & 1 deletion dit/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def today():
LOCALZONE = get_localzone()

def now(**kwargs):
return datetime.now(LOCALZONE)
return datetime.now(LOCALZONE).replace(microsecond=0)

def today():
return now().replace(hour=0,
Expand Down