# HG changeset patch # User Björn Ricks # Date 1393854163 -3600 # Node ID 5df363bba5cbe0e53907c6a8a933e719bb750dc8 # Parent 2b2e371b9bed01b7946b2c4529573b9f468107d0 Change zeiterfassung.py script to use getan.template diff -r 2b2e371b9bed -r 5df363bba5cb getan/contrib/zeiterfassung.py --- a/getan/contrib/zeiterfassung.py Mon Mar 03 14:32:12 2014 +0100 +++ b/getan/contrib/zeiterfassung.py Mon Mar 03 14:42:43 2014 +0100 @@ -11,23 +11,18 @@ # This is Free Software licensed under the terms of GPLv3 or later. # For details see LICENSE coming with the source of 'getan'. # -import os -import os.path import sys import getopt -import re import codecs import locale -from pysqlite2 import dbapi2 as db +from datetime import datetime, timedelta -from datetime import date, datetime, timedelta +from getan.template import render DEFAULT_DATABASE = "time.db" -TYPE_OF_ENTRY = "?" - -WORKPACKAGE = re.compile("^\[(\w*)(\s|\])") +ZEITERFASSUNG_TEMPLATE = "zeiterfassung" USAGE = '''usage: %s with @@ -42,139 +37,24 @@ [--emtpy|-m] : show empty projects [--lastweek|-c] : entries of last working week''' -LIST_PROJECTS = ''' -SELECT key, description, active FROM projects -''' - -PROJECT_ID_BY_KEY = ''' -SELECT id, description FROM projects where key = :key -''' - -ALL_PROJECT_IDS = ''' -SELECT id, key, description FROM projects -''' - -WEEK_ENTRIES = ''' -SELECT - date(start_time) AS t, - sum(strftime('%s', stop_time) - strftime('%s', start_time)), - 'no description' AS description -FROM entries -WHERE - project_id = :project_id AND - (strftime('%Y', start_time) ) = :year AND - (description IS NULL or length(description) = 0) -- trim() function is missing - AND (strftime('%W', start_time) = :week OR strftime('%W', stop_time) = :week) -GROUP BY round(julianday(start_time)) -UNION -SELECT date(start_time) AS s, strftime('%s', stop_time) - strftime('%s', start_time), description -FROM entries -WHERE - project_id = :project_id AND - (strftime('%Y', start_time) ) = :year AND - description IS NOT NULL AND length(description) > 0 - AND (strftime('%W', start_time) = :week OR strftime('%W', stop_time) = :week) -ORDER BY t -''' - -ENTRIES = ''' -SELECT - date(start_time), - sum(strftime('%s', stop_time) - strftime('%s', start_time)), - 'no description' AS description -FROM entries -WHERE - project_id = :project_id AND - (description IS NULL or length(description) = 0) -- trim() function is missing -GROUP BY round(julianday(start_time)) -UNION -SELECT date(start_time), strftime('%s', stop_time) - strftime('%s', start_time), description -FROM entries -WHERE - project_id = :project_id AND - description IS NOT NULL AND length(description) > 0 -''' -ENTRIES_YEAR = ''' -SELECT - date(start_time), - sum(strftime('%s', stop_time) - strftime('%s', start_time)), - 'no description' AS description -FROM entries -WHERE - project_id = :project_id AND - (description IS NULL or length(description) = 0) -- trim() function is missing -GROUP BY round(julianday(start_time)) -UNION -SELECT date(start_time), strftime('%s', stop_time) - strftime('%s', start_time), description -FROM entries -WHERE - project_id = :project_id AND - (strftime('%Y', start_time) ) = :year AND - description IS NOT NULL AND length(description) > 0 -''' - -def unix_week(week, year=None): - """Convert iso week to unix week - - For unix week see man date "%W" - Args: - week: Week number as int to convert - year: Year as int. If year is none the current year is used. - """ - if not year: - year = datetime.now().year - firstday = date(year, 1, 4) - isoweek = firstday.isocalendar()[1] - unixweek = int(firstday.strftime("%W")) - diff = isoweek - unixweek - return week - diff - - -def human_time(s): - h = s / 3600 - m = (s % 3600) / 60 - if (s % 60) >= 30: - m += 1 - if m == 60: - m = 0 - h += 1 - return "%2d:%02d" % (h, m) - -class TermError(Exception): - - def __init__(self, msg): - Exception.__init__(self) - self.msg = msg - - def __str__(self): - return repr(self.msg) - -def tolerantClose(c): - if c: - try: c.close() - except: pass - -def usage(exit_code = 0): +def usage(exit_code=0): print USAGE % sys.argv[0] sys.exit(exit_code) + def main(): - database = DEFAULT_DATABASE - user = None + database = DEFAULT_DATABASE + user = None list_projects = False - project = None - encoding = None - week = None - year = None - empty_proj = False - - if os.path.isfile(DEFAULT_DATABASE): - database = os.path.abspath(DEFAULT_DATABASE) - else: - database = os.path.expanduser(os.path.join("~", ".getan", - DEFAULT_DATABASE)) + project = None + encoding = None + week = None + year = None + empty_proj = False + database = None + template = ZEITERFASSUNG_TEMPLATE opts, args = getopt.getopt( sys.argv[1:], @@ -200,99 +80,19 @@ elif opt in ("--week", "-w"): week = int(val) elif opt in ("--lastweek", "-c") and not week: - week = (datetime.now()-timedelta(7)).isocalendar()[1] + week = (datetime.now() - timedelta(7)).isocalendar()[1] elif opt in ("--empty", "-m"): empty_proj = True - if not week is None: - wyear = None - if not year is None: - wyear = int(year) - week = "%02d" % unix_week(week, wyear) - - if not user: - user = os.getenv("USER") - - proj_year = year - if not proj_year: - proj_year = date.today().strftime("%Y") - if not encoding: encoding = locale.getdefaultlocale()[1] + Writer = codecs.getwriter(encoding) sys.stdout = Writer(sys.stdout) - if not os.path.isfile(database): - print >> sys.stderr, "'%s' does not exist or is not a file." % database - sys.exit(1) - - con, cur = None, None - try: - try: - con = db.connect(database) - if encoding: - con.text_factory = lambda s: s.decode(encoding) - cur = con.cursor() - - if list_projects: - cur.execute(LIST_PROJECTS) - while True: - row = cur.fetchone() - if not row: break - print "%s %s %s" % (row[0], row[2] and "*" or "-", row[1]) - else: - if project: - cur.execute(PROJECT_ID_BY_KEY, { 'key': project }) - row = cur.fetchone() - if row is None: - raise TermError("There is no project with key '%s'" % project) - project_ids = [[row[0], project, row[1]]] - else: - cur.execute(ALL_PROJECT_IDS); - project_ids = cur.fetchall() + print render(user=user, database=database, week=week, year=year, + template=template, project=project) - total = 0 - for project_id, project, proj_desc in project_ids: - if not week is None: - cur.execute(WEEK_ENTRIES, {'project_id': project_id, 'week': week, 'year' : proj_year}) - elif not year: - cur.execute(ENTRIES, {'project_id': project_id}) - else: - cur.execute(ENTRIES_YEAR, {'project_id': project_id, 'year':proj_year}) - total_proj = 0 - row = cur.fetchone() - if row or empty_proj: - print "# project: %s (%s)" % (project, proj_desc) - while row: - d = date(*map(int, row[0].split('-'))) - t = max(60, row[1]) - c = row[2] - total_proj += t - workpackage = "----" - if c: - m = WORKPACKAGE.match(c) - if m: - workpackage = m.group(1) - c = c[m.end():].strip() - c = c.replace('\x1b', '') - print "%s %sh %s %-3s [%s] %s" % ( - d.strftime("%d.%m.%Y"), - human_time(t), - TYPE_OF_ENTRY, - user, - workpackage, - c) - row = cur.fetchone() - total += total_proj - if empty_proj or total_proj > 0: - print "# total: %sh\n\n" % human_time(total_proj) - print "# total all projects: %sh\n\n" % human_time(total) - finally: - tolerantClose(cur) - tolerantClose(con) - - except TermError, e: - print >> sys.stderr, "error: %s" % e.msg if __name__ == '__main__': main()