Skip to content
Merged
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
2 changes: 1 addition & 1 deletion makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ start:
trk --trk-dir $(DIRTRK) start
find $(DIRTRK)
@grep -Hw --color filename $(DIRTRK)/config
@ls -lrt ~/timetrackers/timetracker_trk_$(USER).csv
@ls -lrt ../timetrackers/timetracker_trk_$(USER).csv
find $(DIRTRK)

cancel:
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ classifiers=[


[project.scripts]
trk = "timetracker.main:main"
trk = "timetracker.cli.main:main"
timestr = "timetracker.epoch.cli.timestr:main"
timecalc = "timetracker.epoch.cli.calc:main"

Expand Down Expand Up @@ -93,6 +93,7 @@ omit = [
[tool.setuptools]
packages = [
'timetracker',
'timetracker.cli',
'timetracker.cmd',
'timetracker.cfg',
'timetracker.epoch',
Expand Down
11 changes: 6 additions & 5 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from timeit import default_timer
from pytest import raises
from timetracker.consts import DIRTRK
from timetracker.cli import Cli
from timetracker.cli.cli import Cli

# pylint: disable=fixme

Expand Down Expand Up @@ -91,12 +91,13 @@ def _trk():
assert args.command is None

def _parse_args(arglist):
print(f'RESEARCHER ARGS: {arglist}')
cli = Cli(arglist)
username = environ.get('USER', 'researcher')
print(f'{username} ARGS: {arglist}')
cli = Cli(username, arglist)
print(f'TEST ARGS: {cli.args}\n')
return cli.args

if __name__ == '__main__':
test_cfg()
#test_basic()
#test_dir()
test_basic()
test_dir()
48 changes: 25 additions & 23 deletions tests/test_try_billable.py
Original file line number Diff line number Diff line change
@@ -1,74 +1,76 @@
#!/usr/bin/env python3
"""Test adding 'Billable' tag, if specified in args"""

from timetracker.cli import Cli
from os import environ
from timetracker.cli.cli import Cli
from timetracker.cmd.common import add_tag_billable


def test_try_billable():
def test_try_billable(username='researcher'):
"""Test adding 'Billable' to tags"""
_test_billable0tags0()
_test_billable1tags0()
_test_billable0tags1()
_test_billable1tags1()
_test_billable0tags2()
_test_billable1tags2a()
_test_billable1tags2b()
username = environ.get('USER', username)
_test_billable0tags0(username)
_test_billable1tags0(username)
_test_billable0tags1(username)
_test_billable1tags1(username)
_test_billable0tags2(username)
_test_billable1tags2a(username)
_test_billable1tags2b(username)


def _test_billable0tags0():
def _test_billable0tags0(username):
args = ['stop', '-m', 'Not marked billable; no other tags']
cli = Cli(args)
cli = Cli(username, args)
_try_billable(cli.args, cli.args.billable)
assert cli.args.tags is None
assert not cli.args.billable
_prt(args, cli)

def _test_billable1tags0():
def _test_billable1tags0(username):
args = ['stop', '-b', '-m', 'Marked billable; no other tags']
cli = Cli(args)
cli = Cli(username, args)
_try_billable(cli.args, cli.args.billable)
assert cli.args.tags == ['Billable']
assert cli.args.billable
_prt(args, cli)

def _test_billable0tags1():
def _test_billable0tags1(username):
args = ['stop', '-t', 'tag1', '-m', 'Not marked billable; no other tags']
cli = Cli(args)
cli = Cli(username, args)
_try_billable(cli.args, cli.args.billable)
assert cli.args.tags == ['tag1']
assert not cli.args.billable
_prt(args, cli)

def _test_billable1tags1():
def _test_billable1tags1(username):
args = ['stop', '-t', 'tag1', '-b', '-m', 'Marked billable; no other tags']
cli = Cli(args)
cli = Cli(username, args)
_try_billable(cli.args, cli.args.billable)
assert cli.args.tags == ['tag1', 'Billable']
assert cli.args.billable
_prt(args, cli)

def _test_billable0tags2():
def _test_billable0tags2(username):
args = ['stop', '-t', 'tag1', 'tag2', '-m', 'Not marked billable; no other tags']
cli = Cli(args)
cli = Cli(username, args)
_try_billable(cli.args, cli.args.billable)
assert cli.args.tags == ['tag1', 'tag2'], cli.args.tags
assert not cli.args.billable
_prt(args, cli)

def _test_billable1tags2a():
def _test_billable1tags2a(username):
"""Tags cannot be specified as: -t tag1 -t tag2"""
args = ['stop', '-t', 'tag1', '-t', 'tag2', '-b', '-m', 'Marked billable; no other tags']
cli = Cli(args)
cli = Cli(username, args)
_try_billable(cli.args, cli.args.billable)
assert cli.args.tags == ['tag2', 'Billable'], cli.args.tags
assert cli.args.billable
_prt(args, cli)

def _test_billable1tags2b():
def _test_billable1tags2b(username):
"""Tags must be specified as: -t tag1 tag2"""
args = ['stop', '-t', 'tag1', 'tag2', '-b', '-m', 'Marked billable; no other tags']
cli = Cli(args)
cli = Cli(username, args)
_try_billable(cli.args, cli.args.billable)
assert cli.args.tags == ['tag1', 'tag2', 'Billable'], cli.args.tags
assert cli.args.billable
Expand Down
2 changes: 1 addition & 1 deletion tests/test_usecases.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#from datetime import timedelta
#from timeit import default_timer
#from timetracker.consts import DIRTRK
#from timetracker.cli import Cli
#from timetracker.cli.cli import Cli

# pylint: disable=fixme

Expand Down
15 changes: 13 additions & 2 deletions timetracker/cfg/doc_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
__copyright__ = 'Copyright (C) 2025-present, DV Klopfenstein, PhD. All rights reserved.'
__author__ = "DV Klopfenstein, PhD"

import os
import os.path as op
from os.path import dirname
from collections import namedtuple
Expand Down Expand Up @@ -59,7 +60,7 @@ def get_abspath_dircsv(self):
def get_filename_csv(self, username=None, dirhome=None):
"""Get the csv filename by reading the cfg csv pattern and filling in"""
assert username is None or '/' not in username
username = utils.get_username(username)
username = self.get_username(username)
return self._get_csvfilename_proj_user(username, dirhome)

def get_filenames_csv(self, dirhome):
Expand Down Expand Up @@ -90,7 +91,7 @@ def timer_started(self, username):
def get_startobj(self, username):
"""Get a Starttime object"""
if self.project:
return Starttime(self.dircfg, self.project, utils.get_username(username))
return Starttime(self.dircfg, self.project, self.get_username(username))
return None

##-------------------------------------------------------------
Expand Down Expand Up @@ -120,5 +121,15 @@ def _get_csvfilename_proj(self, dirhome):
return fpat.replace('PROJECT', self.project)
return None

@staticmethod
def get_username(name=None):
"""Get the default username"""
# timetracker/cli/main.py environ
if name is None:
return os.environ.get('USER', 'researcher')
if name in os.environ:
return os.environ[name]
return name


# Copyright (C) 2025-present, DV Klopfenstein, PhD. All rights reserved.
21 changes: 0 additions & 21 deletions timetracker/cfg/finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,26 +131,5 @@ def _init_dict_trkgit(path, trksubdir):
return {'trk': NORMPATH(trkdir)}
return {'git': NORMPATH(gitdir)} if exists_git else {}

####def _get_abspathtrk(path, trksubdir):
#### """Get .timetracker/ proj dir by searching up parent path"""
#### trkabsdir, found = _finddirtrk(path, trksubdir)
#### return trkabsdir if found else None

####def _finddirtrk(path, trksubdir):
#### """Walk up dirs until find .timetracker/ proj dir or mount dir"""
#### path = op.abspath(path)
#### join = op.join
#### trkdir = join(path, trksubdir)
#### exists = op.exists
#### if exists(trkdir):
#### return op.normpath(trkdir), True
#### ismount = op.ismount
#### while not ismount(path):
#### trkdir = join(path, trksubdir)
#### if exists(trkdir):
#### return op.normpath(trkdir), True
#### path = DIRNAME(path)
#### return op.normpath(path), False


# Copyright (C) 2025-present, DV Klopfenstein, PhD. All rights reserved.
15 changes: 8 additions & 7 deletions timetracker/cfg/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,14 @@ def get_relpath(absfilename, dirproj, dirhome=None):
return rpth if len(rpth) < len(hpth) else hpth
return rpth

def get_username(name=None):
"""Get the default username"""
if name is None:
return environ.get('USER', 'researcher')
if name in environ:
return environ[name]
return name
####def get_username(name=None):
#### """Get the default username"""
#### # timetracker/cli/main.py environ
#### if name is None:
#### return environ.get('USER', 'researcher')
#### if name in environ:
#### return environ[name]
#### return name

def run_cmd(cmd):
"""Run a command with output to stdout"""
Expand Down
1 change: 1 addition & 0 deletions timetracker/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""CLI tools"""
5 changes: 2 additions & 3 deletions timetracker/cli.py → timetracker/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#print(f'{timedelta(seconds=default_timer()-tic)} TOP OF CLI: IMPORT argparse') # PRT
from timetracker.cmd.fncs import FNCS
#print(f'{timedelta(seconds=default_timer()-tic)} TOP OF CLI: IMPORT FNCS') # PRT
from timetracker.cfg.utils import get_username
from timetracker.cfg.finder import CfgFinder
#print(f'{timedelta(seconds=default_timer()-tic)} TOP OF CLI: AFTER CfgFinder') # PRT
#from timetracker.cmd.none import cli_run_none
Expand All @@ -37,11 +36,11 @@ class Cli:
'trksubdir': set(['--trk-dir']),
}

def __init__(self, args=None):
def __init__(self, username, args=None):
sysargs = self._adjust_args(args)
self.finder = CfgFinder(getcwd(), self._init_trksubdir())
self.fcfg = self.finder.get_cfgfilename()
self.user = get_username() # default username
self.user = username # default username
self.parser = self._init_parser_top('timetracker')
# print('PARSE ARGS') # PRT
self.args = self._init_args(sysargs)
Expand Down
11 changes: 8 additions & 3 deletions timetracker/main.py → timetracker/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,34 @@
__copyright__ = 'Copyright (C) 2025-present, DV Klopfenstein, PhD. All rights reserved.'
__author__ = "DV Klopfenstein, PhD"

import os
import sys
#from timeit import default_timer # PRT
#tic = default_timer() # PRT
#from datetime import timedelta # PRT
#print(f'{timedelta(seconds=default_timer()-tic)} AFTER IMPORT datetime.timedelta') # PRT
#print(f'{timedelta(seconds=default_timer()-tic)} BEFORE IMPORT Cli') # PRT
import timetracker.cli as modcli
import timetracker.cli.cli as modcli
#print(f'{timedelta(seconds=default_timer()-tic)} AFTER IMPORT Cli') # PRT


def main():
def main(username='researcher'):
"""Connect all parts of the timetracker"""
#from logging import basicConfig, DEBUG
#basicConfig(level=DEBUG)
#print('ENTERING Cli')
args_sys = sys.argv[1:]
username = os.environ.get('USER', username)
# print(f'{timedelta(seconds=default_timer()-tic)} AFTER sys.argv[1:]') # PRT
if not args_sys:
pass
# pylint: disable=import-outside-toplevel
# from timetracker.cmd.none import run_none
# run_none(self.fcfg, username)
# print('NO ARGS') # PRT
# ##print(f'{timedelta(seconds=default_timer()-tic)} AFTER sys.argv[1:]') # PRT
# timetracker/cmd/common.py str_uninitialized
obj = modcli.Cli()
obj = modcli.Cli(username)
#print('ENTERING Cli.run')
obj.run()
#print('EXITING Cli.run')
Expand Down